diff mbox series

fuse: avoid deadlock by clearing __GFP_FS

Message ID 1601014471-3126-1-git-send-email-jing.xia.mail@gmail.com
State New
Headers show
Series fuse: avoid deadlock by clearing __GFP_FS | expand

Commit Message

Jing Xia Sept. 25, 2020, 6:14 a.m. UTC
From: Jing Xia <jing.xia@unisoc.com>

Writeback thread and fuse block each other.
Writeback thread waits fuse's reply with inode's I_SYNC being
held.Fuse enters the slowpath of memory allocation when handle
the request and has to wait the inode's I_SYNC is cleared.

writeback's backtrace
---------------------
PID: 6197   TASK: ed130780  CPU: 3   COMMAND: "kworker/u8:7"
 #0 [<c0a0bae0>] (__schedule) from [<c0a0bdb0>]
 #1 [<c0a0bdb0>] (schedule) from [<c03d1330>]
 #2 [<c03d1330>] (__fuse_request_send) from [<c03d16a0>]
 #3 [<c03d16a0>] (fuse_simple_request) from [<c03d58fc>]
 #4 [<c03d58fc>] (fuse_flush_times) from [<c03d95dc>]
 #5 [<c03d95dc>] (fuse_write_inode) from [<c02df87c>]
 #6 [<c02df87c>] (__writeback_single_inode) from [<c02dee4c>]
 #7 [<c02dee4c>] (writeback_sb_inodes) from [<c02df0e8>]
 #8 [<c02df0e8>] (__writeback_inodes_wb) from [<c02de72c>]
 #9 [<c02de72c>] (wb_writeback) from [<c02dbafc>]
 #10 [<c02dbafc>] (wb_workfn) from [<c014d3d0>]
 #11 [<c014d3d0>] (process_one_work) from [<c014d9b8>]
 #12 [<c014d9b8>] (worker_thread) from [<c0151e40>]
 #13 [<c0151e40>] (kthread) from [<c0107648>]

fuse's backtrace
---------------------
PID: 4412   TASK: c4b47800  CPU: 3   COMMAND: "Thread-9"
 #0 [<c0a0bae0>] (__schedule) from [<c0a0bdb0>]
 #1 [<c0a0bdb0>] (schedule) from [<c0a0c74c>]
 #2 [<c0a0c74c>] (bit_wait) from [<c0a0c310>]
 #3 [<c0a0c310>] (__wait_on_bit) from [<c02db7d0>]
 #4 [<c02db7d0>] (__inode_wait_for_writeback) from [<c02db700>]
 #5 [<c02db700>] (inode_wait_for_writeback) from [<c02cb33c>]
 #6 [<c02cb33c>] (evict) from [<c02c40fc>]
 #7 [<c02c40fc>] (__dentry_kill) from [<c02c4430>]
 #8 [<c02c4430>] (shrink_dentry_list) from [<c02c41dc>]
 #9 [<c02c41dc>] (prune_dcache_sb) from [<c02af8a0>]
 #10 [<c02af8a0>] (super_cache_scan) from [<c0258f2c>]
 #11 [<c0258f2c>] (shrink_slab) from [<c025dc6c>]
 #12 [<c025dc6c>] (shrink_node) from [<c025b240>]
 #13 [<c025b240>] (do_try_to_free_pages) from [<c025adc0>]
 #14 [<c025adc0>] (try_to_free_pages) from [<c0249cb0>]
 #15 [<c0249cb0>] (__alloc_pages_nodemask) from [<c03d3638>]
 #16 [<c03d3638>] (fuse_copy_fill) from [<c03d33c0>]
 #17 [<c03d33c0>] (fuse_copy_one) from [<c03d2fe4>]
 #18 [<c03d2fe4>] (fuse_dev_do_read) from [<c03d2814>]
 #19 [<c03d2814>] (fuse_dev_splice_read) from [<c02e2548>]
 #20 [<c02e2548>] (sys_splice) from [<c0107740>]

This patch clears __GFP_FS flag when fuse alloctes pages to avoid
deadlock,as super_cache_scan will directly return SHRINK_STOP when
__GFP_FS is not set.

Signed-off-by: Jing Xia <jing.xia@unisoc.com>
---
 fs/fuse/dev.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 02b3c36..165c416 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -708,7 +708,7 @@  static int fuse_copy_fill(struct fuse_copy_state *cs)
 			if (cs->nr_segs >= cs->pipe->max_usage)
 				return -EIO;
 
-			page = alloc_page(GFP_HIGHUSER);
+			page = alloc_page(GFP_HIGHUSER & ~__GFP_FS);
 			if (!page)
 				return -ENOMEM;