• Ashish Samant's avatar
    fuse: Dont call set_page_dirty_lock() for ITER_BVEC pages for async_dio · 1b6a863f
    Ashish Samant authored
    [ Upstream commit 61c12b49 ]
    
    Commit 8fba54ae ("fuse: direct-io: don't dirty ITER_BVEC pages") fixes
    the ITER_BVEC page deadlock for direct io in fuse by checking in
    fuse_direct_io(), whether the page is a bvec page or not, before locking
    it.  However, this check is missed when the "async_dio" mount option is
    enabled.  In this case, set_page_dirty_lock() is called from the req->end
    callback in request_end(), when the fuse thread is returning from userspace
    to respond to the read request.  This will cause the same deadlock because
    the bvec condition is not checked in this path.
    
    Here is the stack of the deadlocked thread, while returning from userspace:
    
    [13706.656686] INFO: task glusterfs:3006 blocked for more than 120 seconds.
    [13706.657808] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables
    this message.
    [13706.658788] glusterfs       D ffffffff816c80f0     0  3006      1
    0x00000080
    [13706.658797]  ffff8800d6713a58 0000000000000086 ffff8800d9ad7000
    ffff8800d9ad5400
    [13706.658799]  ffff88011ffd5cc0 ffff8800d6710008 ffff88011fd176c0
    7fffffffffffffff
    [13706.658801]  0000000000000002 ffffffff816c80f0 ffff8800d6713a78
    ffffffff816c790e
    [13706.658803] Call Trace:
    [13706.658809]  [<ffffffff816c80f0>] ? bit_wait_io_timeout+0x80/0x80
    [13706.658811]  [<ffffffff816c790e>] schedule+0x3e/0x90
    [13706.658813]  [<ffffffff816ca7e5>] schedule_timeout+0x1b5/0x210
    [13706.658816]  [<ffffffff81073ffb>] ? gup_pud_range+0x1db/0x1f0
    [13706.658817]  [<ffffffff810668fe>] ? kvm_clock_read+0x1e/0x20
    [13706.658819]  [<ffffffff81066909>] ? kvm_clock_get_cycles+0x9/0x10
    [13706.658822]  [<ffffffff810f5792>] ? ktime_get+0x52/0xc0
    [13706.658824]  [<ffffffff816c6f04>] io_schedule_timeout+0xa4/0x110
    [13706.658826]  [<ffffffff816c8126>] bit_wait_io+0x36/0x50
    [13706.658828]  [<ffffffff816c7d06>] __wait_on_bit_lock+0x76/0xb0
    [13706.658831]  [<ffffffffa0545636>] ? lock_request+0x46/0x70 [fuse]
    [13706.658834]  [<ffffffff8118800a>] __lock_page+0xaa/0xb0
    [13706.658836]  [<ffffffff810c8500>] ? wake_atomic_t_function+0x40/0x40
    [13706.658838]  [<ffffffff81194d08>] set_page_dirty_lock+0x58/0x60
    [13706.658841]  [<ffffffffa054d968>] fuse_release_user_pages+0x58/0x70 [fuse]
    [13706.658844]  [<ffffffffa0551430>] ? fuse_aio_complete+0x190/0x190 [fuse]
    [13706.658847]  [<ffffffffa0551459>] fuse_aio_complete_req+0x29/0x90 [fuse]
    [13706.658849]  [<ffffffffa05471e9>] request_end+0xd9/0x190 [fuse]
    [13706.658852]  [<ffffffffa0549126>] fuse_dev_do_write+0x336/0x490 [fuse]
    [13706.658854]  [<ffffffffa054963e>] fuse_dev_write+0x6e/0xa0 [fuse]
    [13706.658857]  [<ffffffff812a9ef3>] ? security_file_permission+0x23/0x90
    [13706.658859]  [<ffffffff81205300>] do_iter_readv_writev+0x60/0x90
    [13706.658862]  [<ffffffffa05495d0>] ? fuse_dev_splice_write+0x350/0x350
    [fuse]
    [13706.658863]  [<ffffffff812062a1>] do_readv_writev+0x171/0x1f0
    [13706.658866]  [<ffffffff810b3d00>] ? try_to_wake_up+0x210/0x210
    [13706.658868]  [<ffffffff81206361>] vfs_writev+0x41/0x50
    [13706.658870]  [<ffffffff81206496>] SyS_writev+0x56/0xf0
    [13706.658872]  [<ffffffff810257a1>] ? syscall_trace_leave+0xf1/0x160
    [13706.658874]  [<ffffffff816cbb2e>] system_call_fastpath+0x12/0x71
    
    Fix this by making should_dirty a fuse_io_priv parameter that can be
    checked in fuse_aio_complete_req().
    Reported-by: default avatarTiger Yang <tiger.yang@oracle.com>
    Signed-off-by: default avatarAshish Samant <ashish.samant@oracle.com>
    Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
    Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
    1b6a863f
Name
Last commit
Last update
..
9p Loading commit data...
adfs Loading commit data...
affs Loading commit data...
afs Loading commit data...
autofs4 Loading commit data...
befs Loading commit data...
bfs Loading commit data...
btrfs Loading commit data...
cachefiles Loading commit data...
ceph Loading commit data...
cifs Loading commit data...
coda Loading commit data...
configfs Loading commit data...
cramfs Loading commit data...
debugfs Loading commit data...
devpts Loading commit data...
dlm Loading commit data...
ecryptfs Loading commit data...
efivarfs Loading commit data...
efs Loading commit data...
exofs Loading commit data...
exportfs Loading commit data...
ext2 Loading commit data...
ext4 Loading commit data...
f2fs Loading commit data...
fat Loading commit data...
freevxfs Loading commit data...
fscache Loading commit data...
fuse Loading commit data...
gfs2 Loading commit data...
hfs Loading commit data...
hfsplus Loading commit data...
hostfs Loading commit data...
hpfs Loading commit data...
hugetlbfs Loading commit data...
isofs Loading commit data...
jbd2 Loading commit data...
jffs2 Loading commit data...
jfs Loading commit data...
kernfs Loading commit data...
lockd Loading commit data...
logfs Loading commit data...
minix Loading commit data...
ncpfs Loading commit data...
nfs Loading commit data...
nfs_common Loading commit data...
nfsd Loading commit data...
nilfs2 Loading commit data...
nls Loading commit data...
notify Loading commit data...
ntfs Loading commit data...
ocfs2 Loading commit data...
omfs Loading commit data...
openpromfs Loading commit data...
overlayfs Loading commit data...
proc Loading commit data...
pstore Loading commit data...
qnx4 Loading commit data...
qnx6 Loading commit data...
quota Loading commit data...
ramfs Loading commit data...
reiserfs Loading commit data...
romfs Loading commit data...
squashfs Loading commit data...
sysfs Loading commit data...
sysv Loading commit data...
tracefs Loading commit data...
ubifs Loading commit data...
udf Loading commit data...
ufs Loading commit data...
xfs Loading commit data...
Kconfig Loading commit data...
Kconfig.binfmt Loading commit data...
Makefile Loading commit data...
aio.c Loading commit data...
anon_inodes.c Loading commit data...
attr.c Loading commit data...
bad_inode.c Loading commit data...
binfmt_aout.c Loading commit data...
binfmt_elf.c Loading commit data...
binfmt_elf_fdpic.c Loading commit data...
binfmt_em86.c Loading commit data...
binfmt_flat.c Loading commit data...
binfmt_misc.c Loading commit data...
binfmt_script.c Loading commit data...
block_dev.c Loading commit data...
buffer.c Loading commit data...
char_dev.c Loading commit data...
compat.c Loading commit data...
compat_binfmt_elf.c Loading commit data...
compat_ioctl.c Loading commit data...
coredump.c Loading commit data...
dax.c Loading commit data...
dcache.c Loading commit data...
dcookies.c Loading commit data...
direct-io.c Loading commit data...
drop_caches.c Loading commit data...
eventfd.c Loading commit data...
eventpoll.c Loading commit data...
exec.c Loading commit data...
fcntl.c Loading commit data...
fhandle.c Loading commit data...
file.c Loading commit data...
file_table.c Loading commit data...
filesystems.c Loading commit data...
fs-writeback.c Loading commit data...
fs_pin.c Loading commit data...
fs_struct.c Loading commit data...
inode.c Loading commit data...
internal.h Loading commit data...
ioctl.c Loading commit data...
libfs.c Loading commit data...
locks.c Loading commit data...
mbcache.c Loading commit data...
mount.h Loading commit data...
mpage.c Loading commit data...
namei.c Loading commit data...
namespace.c Loading commit data...
no-block.c Loading commit data...
nsfs.c Loading commit data...
open.c Loading commit data...
pipe.c Loading commit data...
pnode.c Loading commit data...
pnode.h Loading commit data...
posix_acl.c Loading commit data...
proc_namespace.c Loading commit data...
read_write.c Loading commit data...
readdir.c Loading commit data...
select.c Loading commit data...
seq_file.c Loading commit data...
signalfd.c Loading commit data...
splice.c Loading commit data...
stack.c Loading commit data...
stat.c Loading commit data...
statfs.c Loading commit data...
super.c Loading commit data...
sync.c Loading commit data...
timerfd.c Loading commit data...
userfaultfd.c Loading commit data...
utimes.c Loading commit data...
xattr.c Loading commit data...