Skip to content

Commit 669dfeb

Browse files
committed
NFS: fix nfs_release_folio() to not deadlock via kcompactd writeback
JIRA: https://issues.redhat.com/browse/RHEL-108616 commit ce6d9c1 Author: Mike Snitzer <[email protected]> Date: Mon Feb 24 21:20:02 2025 -0500 NFS: fix nfs_release_folio() to not deadlock via kcompactd writeback Add PF_KCOMPACTD flag and current_is_kcompactd() helper to check for it so nfs_release_folio() can skip calling nfs_wb_folio() from kcompactd. Otherwise NFS can deadlock waiting for kcompactd enduced writeback which recurses back to NFS (which triggers writeback to NFSD via NFS loopback mount on the same host, NFSD blocks waiting for XFS's call to __filemap_get_folio): 6070.550357] INFO: task kcompactd0:58 blocked for more than 4435 seconds. {--- [58] "kcompactd0" [<0>] folio_wait_bit+0xe8/0x200 [<0>] folio_wait_writeback+0x2b/0x80 [<0>] nfs_wb_folio+0x80/0x1b0 [nfs] [<0>] nfs_release_folio+0x68/0x130 [nfs] [<0>] split_huge_page_to_list_to_order+0x362/0x840 [<0>] migrate_pages_batch+0x43d/0xb90 [<0>] migrate_pages_sync+0x9a/0x240 [<0>] migrate_pages+0x93c/0x9f0 [<0>] compact_zone+0x8e2/0x1030 [<0>] compact_node+0xdb/0x120 [<0>] kcompactd+0x121/0x2e0 [<0>] kthread+0xcf/0x100 [<0>] ret_from_fork+0x31/0x40 [<0>] ret_from_fork_asm+0x1a/0x30 ---} [[email protected]: fix build] Link: https://lkml.kernel.org/r/[email protected] Fixes: 96780ca ("NFS: fix up nfs_release_folio() to try to release the page") Signed-off-by: Mike Snitzer <[email protected]> Cc: Anna Schumaker <[email protected]> Cc: Trond Myklebust <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Benjamin Coddington <[email protected]>
1 parent cc6e81b commit 669dfeb

File tree

4 files changed

+11
-2
lines changed

4 files changed

+11
-2
lines changed

fs/nfs/file.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <linux/pagemap.h>
3030
#include <linux/gfp.h>
3131
#include <linux/swap.h>
32+
#include <linux/compaction.h>
3233

3334
#include <linux/uaccess.h>
3435
#include <linux/filelock.h>
@@ -429,7 +430,7 @@ static bool nfs_release_folio(struct folio *folio, gfp_t gfp)
429430
/* If the private flag is set, then the folio is not freeable */
430431
if (folio_test_private(folio)) {
431432
if ((current_gfp_context(gfp) & GFP_KERNEL) != GFP_KERNEL ||
432-
current_is_kswapd())
433+
current_is_kswapd() || current_is_kcompactd())
433434
return false;
434435
if (nfs_wb_folio(folio->mapping->host, folio) < 0)
435436
return false;

include/linux/compaction.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ static inline unsigned long compact_gap(unsigned int order)
8080
return 2UL << order;
8181
}
8282

83+
static inline int current_is_kcompactd(void)
84+
{
85+
return current->flags & PF_KCOMPACTD;
86+
}
87+
8388
#ifdef CONFIG_COMPACTION
8489

8590
extern unsigned int extfrag_for_order(struct zone *zone, unsigned int order);

include/linux/sched.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1787,7 +1787,7 @@ extern struct pid *cad_pid;
17871787
#define PF_USED_MATH 0x00002000 /* If unset the fpu must be initialized before use */
17881788
#define PF__HOLE__00004000 0x00004000
17891789
#define PF_NOFREEZE 0x00008000 /* This thread should not be frozen */
1790-
#define PF__HOLE__00010000 0x00010000
1790+
#define PF_KCOMPACTD 0x00010000 /* I am kcompactd */
17911791
#define PF_KSWAPD 0x00020000 /* I am kswapd */
17921792
#define PF_MEMALLOC_NOFS 0x00040000 /* All allocation requests will inherit GFP_NOFS */
17931793
#define PF_MEMALLOC_NOIO 0x00080000 /* All allocation requests will inherit GFP_NOIO */

mm/compaction.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3083,6 +3083,7 @@ static int kcompactd(void *p)
30833083
if (!cpumask_empty(cpumask))
30843084
set_cpus_allowed_ptr(tsk, cpumask);
30853085

3086+
current->flags |= PF_KCOMPACTD;
30863087
set_freezable();
30873088

30883089
pgdat->kcompactd_max_order = 0;
@@ -3139,6 +3140,8 @@ static int kcompactd(void *p)
31393140
pgdat->proactive_compact_trigger = false;
31403141
}
31413142

3143+
current->flags &= ~PF_KCOMPACTD;
3144+
31423145
return 0;
31433146
}
31443147

0 commit comments

Comments
 (0)