Skip to content

Commit 5ae31c5

Browse files
Mike Snitzergregkh
authored andcommitted
NFS: fix nfs_release_folio() to not deadlock via kcompactd writeback
commit ce6d9c1 upstream. 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 ---} [akpm@linux-foundation.org: fix build] Link: https://lkml.kernel.org/r/20250225022002.26141-1-snitzer@kernel.org Fixes: 96780ca ("NFS: fix up nfs_release_folio() to try to release the page") Signed-off-by: Mike Snitzer <snitzer@kernel.org> Cc: Anna Schumaker <anna.schumaker@oracle.com> Cc: Trond Myklebust <trond.myklebust@hammerspace.com> Cc: <stable@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 845590b commit 5ae31c5

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>
@@ -451,7 +452,7 @@ static bool nfs_release_folio(struct folio *folio, gfp_t gfp)
451452
/* If the private flag is set, then the folio is not freeable */
452453
if (folio_test_private(folio)) {
453454
if ((current_gfp_context(gfp) & GFP_KERNEL) != GFP_KERNEL ||
454-
current_is_kswapd())
455+
current_is_kswapd() || current_is_kcompactd())
455456
return false;
456457
if (nfs_wb_folio(folio->mapping->host, folio) < 0)
457458
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
@@ -1682,7 +1682,7 @@ extern struct pid *cad_pid;
16821682
#define PF_USED_MATH 0x00002000 /* If unset the fpu must be initialized before use */
16831683
#define PF_USER_WORKER 0x00004000 /* Kernel thread cloned from userspace thread */
16841684
#define PF_NOFREEZE 0x00008000 /* This thread should not be frozen */
1685-
#define PF__HOLE__00010000 0x00010000
1685+
#define PF_KCOMPACTD 0x00010000 /* I am kcompactd */
16861686
#define PF_KSWAPD 0x00020000 /* I am kswapd */
16871687
#define PF_MEMALLOC_NOFS 0x00040000 /* All allocations inherit GFP_NOFS. See memalloc_nfs_save() */
16881688
#define PF_MEMALLOC_NOIO 0x00080000 /* All allocations inherit GFP_NOIO. See memalloc_noio_save() */

mm/compaction.c

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

3167+
current->flags |= PF_KCOMPACTD;
31673168
set_freezable();
31683169

31693170
pgdat->kcompactd_max_order = 0;
@@ -3220,6 +3221,8 @@ static int kcompactd(void *p)
32203221
pgdat->proactive_compact_trigger = false;
32213222
}
32223223

3224+
current->flags &= ~PF_KCOMPACTD;
3225+
32233226
return 0;
32243227
}
32253228

0 commit comments

Comments
 (0)