Re: [syzbot] INFO: task hung in fuse_launder_page

From: Miklos Szeredi
Date: Tue Aug 17 2021 - 10:41:29 EST


On Fri, 13 Aug 2021 at 15:16, syzbot
<syzbot+bea44a5189836d956894@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote:
>
> Hello,
>
> syzbot found the following issue on:
>
> HEAD commit: 36a21d51725a Linux 5.14-rc5
> git tree: upstream
> console output: https://syzkaller.appspot.com/x/log.txt?x=104b8eaa300000
> kernel config: https://syzkaller.appspot.com/x/.config?x=e3a20bae04b96ccd
> dashboard link: https://syzkaller.appspot.com/bug?extid=bea44a5189836d956894
> compiler: gcc (Debian 10.2.1-6) 10.2.1 20210110, GNU ld (GNU Binutils for Debian) 2.35.1
> syz repro: https://syzkaller.appspot.com/x/repro.syz?x=143c0ee9300000
> C reproducer: https://syzkaller.appspot.com/x/repro.c?x=158fc9aa300000
>
> IMPORTANT: if you fix the issue, please add the following tag to the commit:
> Reported-by: syzbot+bea44a5189836d956894@xxxxxxxxxxxxxxxxxxxxxxxxx
>
> INFO: task syz-executor276:8433 blocked for more than 143 seconds.
> Not tainted 5.14.0-rc5-syzkaller #0
> "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
> task:syz-executor276 state:D stack:27736 pid: 8433 ppid: 8430 flags:0x00004004
> Call Trace:
> context_switch kernel/sched/core.c:4681 [inline]
> __schedule+0x93a/0x26f0 kernel/sched/core.c:5938
> schedule+0xd3/0x270 kernel/sched/core.c:6017
> fuse_wait_on_page_writeback fs/fuse/file.c:452 [inline]
> fuse_wait_on_page_writeback+0x120/0x170 fs/fuse/file.c:448
> fuse_launder_page fs/fuse/file.c:2316 [inline]
> fuse_launder_page+0xe9/0x130 fs/fuse/file.c:2306
> do_launder_page mm/truncate.c:595 [inline]
> invalidate_inode_pages2_range+0x994/0xf80 mm/truncate.c:661
> fuse_finish_open+0x2d9/0x560 fs/fuse/file.c:202
> fuse_open_common+0x2f9/0x4c0 fs/fuse/file.c:254
> do_dentry_open+0x4c8/0x11d0 fs/open.c:826
> do_open fs/namei.c:3374 [inline]
> path_openat+0x1c23/0x27f0 fs/namei.c:3507
> do_filp_open+0x1aa/0x400 fs/namei.c:3534
> do_sys_openat2+0x16d/0x420 fs/open.c:1204
> do_sys_open fs/open.c:1220 [inline]
> __do_sys_creat fs/open.c:1294 [inline]
> __se_sys_creat fs/open.c:1288 [inline]
> __x64_sys_creat+0xc9/0x120 fs/open.c:1288
> do_syscall_x64 arch/x86/entry/common.c:50 [inline]
> do_syscall_64+0x35/0xb0 arch/x86/entry/common.c:80
> entry_SYSCALL_64_after_hwframe+0x44/0xae
> RIP: 0033:0x446409
> RSP: 002b:00007f0e6a9f92f8 EFLAGS: 00000246 ORIG_RAX: 0000000000000055
> RAX: ffffffffffffffda RBX: 00000000004d34f0 RCX: 0000000000446409
> RDX: 0000000000446409 RSI: 0000000000000000 RDI: 0000000020000280
> RBP: 00000000004a3164 R08: 0000000000000000 R09: 0000000000000000
> R10: 0000000000000000 R11: 0000000000000246 R12: 0030656c69662f2e
> R13: 000000000049f158 R14: 00000000004a1160 R15: 00000000004d34f8

Attached patch should fix this.

#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
master
---
fs/fuse/file.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)

--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -198,12 +198,11 @@ void fuse_finish_open(struct inode *inod
struct fuse_file *ff = file->private_data;
struct fuse_conn *fc = get_fuse_conn(inode);

- if (!(ff->open_flags & FOPEN_KEEP_CACHE))
- invalidate_inode_pages2(inode->i_mapping);
if (ff->open_flags & FOPEN_STREAM)
stream_open(inode, file);
else if (ff->open_flags & FOPEN_NONSEEKABLE)
nonseekable_open(inode, file);
+
if (fc->atomic_o_trunc && (file->f_flags & O_TRUNC)) {
struct fuse_inode *fi = get_fuse_inode(inode);

@@ -211,10 +210,14 @@ void fuse_finish_open(struct inode *inod
fi->attr_version = atomic64_inc_return(&fc->attr_version);
i_size_write(inode, 0);
spin_unlock(&fi->lock);
+ truncate_pagecache(inode, 0);
fuse_invalidate_attr(inode);
if (fc->writeback_cache)
file_update_time(file);
+ } else if (!(ff->open_flags & FOPEN_KEEP_CACHE)) {
+ invalidate_inode_pages2(inode->i_mapping);
}
+
if ((file->f_mode & FMODE_WRITE) && fc->writeback_cache)
fuse_link_write_file(file);
}