From: Ashish Samant Date: Sat, 22 Jul 2017 02:20:06 +0000 (-0700) Subject: fuse: Call end_queued_requests() after releasing fc->lock in fuse_dev_release() X-Git-Tag: v4.1.12-124.31.3~1485 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=5b37c88ad4d4c6585633a90d0955128afb3849a5;p=users%2Fjedix%2Flinux-maple.git fuse: Call end_queued_requests() after releasing fc->lock in fuse_dev_release() Orabug: 27215268 During fs teardown,the following self deadlock can happen. [] _raw_spin_lock+0x2a/0x60 [] ? fuse_abort_conn+0x31/0x270 [fuse] [] ? cuse_read_iter+0x70/0x70 [cuse] [] cuse_process_init_reply+0x54/0x490 [cuse] [] ? cuse_read_iter+0x70/0x70 [cuse] [] request_end+0xbf/0x170 [fuse] [] end_queued_requests.isra.19+0x86/0x160 [fuse] [] fuse_dev_release+0x9f/0xd0 [fuse] [] cuse_channel_release+0x8a/0xa0 [cuse] [] __fput+0xe4/0x220 [] ____fput+0xe/0x10 [] task_work_run+0xb7/0xf0 [] do_notify_resume+0x8d/0xa0 [] 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 Reviewed-by: Somasundaram Krishnasamy --- diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 9ae98d471975..1dbb7129345f 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -2366,9 +2366,9 @@ int fuse_dev_release(struct inode *inode, struct file *file) wake_up_all(&fn->blocked_waitq); spin_unlock(&fn->lock); } - end_queued_requests(fc); end_polls(fc); spin_unlock(&fc->lock); + end_queued_requests(fc); fuse_conn_put(fc); }