]> www.infradead.org Git - users/jedix/linux-maple.git/commit
fuse: Call end_queued_requests() after releasing fc->lock in fuse_dev_release()
authorAshish Samant <ashish.samant@oracle.com>
Sat, 22 Jul 2017 02:20:06 +0000 (19:20 -0700)
committerChuck Anderson <chuck.anderson@oracle.com>
Mon, 11 Dec 2017 04:24:43 +0000 (20:24 -0800)
commit5b37c88ad4d4c6585633a90d0955128afb3849a5
treeec83fd8c435ae76b70dd5b2e20af54cb89acf116
parenta64f058b03e72a0aee2f6351165c16413ec76908
fuse: Call end_queued_requests() after releasing fc->lock in fuse_dev_release()

Orabug: 27215268

During fs teardown,the following self deadlock can happen.

[<ffffffff8173891a>] _raw_spin_lock+0x2a/0x60
[<ffffffffa08a7ef1>] ? fuse_abort_conn+0x31/0x270 [fuse]
[<ffffffffa08763c0>] ? cuse_read_iter+0x70/0x70 [cuse]
[<ffffffffa0876414>] cuse_process_init_reply+0x54/0x490 [cuse]
[<ffffffffa08763c0>] ? cuse_read_iter+0x70/0x70 [cuse]
[<ffffffffa08a5bbf>] request_end+0xbf/0x170 [fuse]
[<ffffffffa08a7d16>] end_queued_requests.isra.19+0x86/0x160 [fuse]
[<ffffffffa08a7e8f>] fuse_dev_release+0x9f/0xd0 [fuse]
[<ffffffffa087611a>] cuse_channel_release+0x8a/0xa0 [cuse]
[<ffffffff81214cf4>] __fput+0xe4/0x220
[<ffffffff81214e7e>] ____fput+0xe/0x10
[<ffffffff810a5557>] task_work_run+0xb7/0xf0
[<ffffffff81017c6d>] do_notify_resume+0x8d/0xa0
[<ffffffff81738dbc>] int_signal+0x12/0x17

The deadlock happens when an attempt is made to take fc->lock in
fuse_abort_conn(). The same lock has already been taken in
fuse_dev_release() in the stack.

This flow is initiated from cuse_process_init_reply() in case of an error
and so, it is a very rare scenario, but it can lockup the fuse fs.

Fix this by releasing the spin lock before calling end_queued_requests()
instead of after, since it does not make a difference anyway.

Signed-off-by: Ashish Samant <ashish.samant@oracle.com>
Reviewed-by: Somasundaram Krishnasamy <somasundaram.krishnasamy@oracle.com>
fs/fuse/dev.c