public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* loop: fix deadlock when sysfs and LOOP_CLR_FD race against each other
@ 2011-07-30 19:19 Kay Sievers
  2011-07-31 20:20 ` Jens Axboe
  0 siblings, 1 reply; 4+ messages in thread
From: Kay Sievers @ 2011-07-30 19:19 UTC (permalink / raw)
  To: Jens Axboe; +Cc: Milan Broz, Tejun Heo, linux-kernel

From: Kay Sievers <kay.sievers@vrfy.org>
Subject: loop: fix deadlock when sysfs and LOOP_CLR_FD race against each other

LOOP_CLR_FD takes lo->lo_ctl_mutex and tries to remove the loop sysfs
files. Sysfs calls show() and waits for lo->lo_ctl_mutex. LOOP_CLR_FD
waits for show() to finish to remove the sysfs file.

  cat /sys/class/block/loop0/loop/backing_file
    mutex_lock_nested+0x176/0x350
    ? loop_attr_do_show_backing_file+0x2f/0xd0 [loop]
    ? loop_attr_do_show_backing_file+0x2f/0xd0 [loop]
    loop_attr_do_show_backing_file+0x2f/0xd0 [loop]
    dev_attr_show+0x1b/0x60
    ? sysfs_read_file+0x86/0x1a0
    ? __get_free_pages+0x12/0x50
    sysfs_read_file+0xaf/0x1a0

  ioctl(LOOP_CLR_FD):
    wait_for_common+0x12c/0x180
    ? try_to_wake_up+0x2a0/0x2a0
    wait_for_completion+0x18/0x20
    sysfs_deactivate+0x178/0x180
    ? sysfs_addrm_finish+0x43/0x70
    ? sysfs_addrm_start+0x1d/0x20
    sysfs_addrm_finish+0x43/0x70
    sysfs_hash_and_remove+0x85/0xa0
    sysfs_remove_group+0x59/0x100
    loop_clr_fd+0x1dc/0x3f0 [loop]
    lo_ioctl+0x223/0x7a0 [loop]

Instead of taking the lo_ctl_mutex from sysfs code, take the inner
lo->lo_lock, to protect the access to the backing_file data.

Thanks to Tejun for help debugging and finding a solution.

Cc: Milan Broz <mbroz@redhat.com>
Cc: Tejun Heo <tj@kernel.org>
Signed-off-by: Kay Sievers <kay.sievers@vrfy.org>
---
 drivers/block/loop.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -743,10 +743,10 @@ static ssize_t loop_attr_backing_file_sh
 	ssize_t ret;
 	char *p = NULL;
 
-	mutex_lock(&lo->lo_ctl_mutex);
+	spin_lock_irq(&lo->lo_lock);
 	if (lo->lo_backing_file)
 		p = d_path(&lo->lo_backing_file->f_path, buf, PAGE_SIZE - 1);
-	mutex_unlock(&lo->lo_ctl_mutex);
+	spin_unlock_irq(&lo->lo_lock);
 
 	if (IS_ERR_OR_NULL(p))
 		ret = PTR_ERR(p);
@@ -1000,7 +1000,9 @@ static int loop_clr_fd(struct loop_devic
 
 	kthread_stop(lo->lo_thread);
 
+	spin_lock_irq(&lo->lo_lock);
 	lo->lo_backing_file = NULL;
+	spin_unlock_irq(&lo->lo_lock);
 
 	loop_release_xfer(lo);
 	lo->transfer = NULL;



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: loop: fix deadlock when sysfs and LOOP_CLR_FD race against each other
  2011-07-30 19:19 loop: fix deadlock when sysfs and LOOP_CLR_FD race against each other Kay Sievers
@ 2011-07-31 20:20 ` Jens Axboe
  2011-07-31 20:42   ` Kay Sievers
  0 siblings, 1 reply; 4+ messages in thread
From: Jens Axboe @ 2011-07-31 20:20 UTC (permalink / raw)
  To: Kay Sievers; +Cc: Milan Broz, Tejun Heo, linux-kernel@vger.kernel.org

On 2011-07-30 21:19, Kay Sievers wrote:
> From: Kay Sievers <kay.sievers@vrfy.org>
> Subject: loop: fix deadlock when sysfs and LOOP_CLR_FD race against each other
> 
> LOOP_CLR_FD takes lo->lo_ctl_mutex and tries to remove the loop sysfs
> files. Sysfs calls show() and waits for lo->lo_ctl_mutex. LOOP_CLR_FD
> waits for show() to finish to remove the sysfs file.
> 
>   cat /sys/class/block/loop0/loop/backing_file
>     mutex_lock_nested+0x176/0x350
>     ? loop_attr_do_show_backing_file+0x2f/0xd0 [loop]
>     ? loop_attr_do_show_backing_file+0x2f/0xd0 [loop]
>     loop_attr_do_show_backing_file+0x2f/0xd0 [loop]
>     dev_attr_show+0x1b/0x60
>     ? sysfs_read_file+0x86/0x1a0
>     ? __get_free_pages+0x12/0x50
>     sysfs_read_file+0xaf/0x1a0
> 
>   ioctl(LOOP_CLR_FD):
>     wait_for_common+0x12c/0x180
>     ? try_to_wake_up+0x2a0/0x2a0
>     wait_for_completion+0x18/0x20
>     sysfs_deactivate+0x178/0x180
>     ? sysfs_addrm_finish+0x43/0x70
>     ? sysfs_addrm_start+0x1d/0x20
>     sysfs_addrm_finish+0x43/0x70
>     sysfs_hash_and_remove+0x85/0xa0
>     sysfs_remove_group+0x59/0x100
>     loop_clr_fd+0x1dc/0x3f0 [loop]
>     lo_ioctl+0x223/0x7a0 [loop]
> 
> Instead of taking the lo_ctl_mutex from sysfs code, take the inner
> lo->lo_lock, to protect the access to the backing_file data.
> 
> Thanks to Tejun for help debugging and finding a solution.

Looks good, looks like something that should have a stable tag as well?

-- 
Jens Axboe


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: loop: fix deadlock when sysfs and LOOP_CLR_FD race against each other
  2011-07-31 20:20 ` Jens Axboe
@ 2011-07-31 20:42   ` Kay Sievers
  2011-07-31 20:57     ` Jens Axboe
  0 siblings, 1 reply; 4+ messages in thread
From: Kay Sievers @ 2011-07-31 20:42 UTC (permalink / raw)
  To: Jens Axboe; +Cc: Milan Broz, Tejun Heo, linux-kernel@vger.kernel.org

On Sun, Jul 31, 2011 at 22:20, Jens Axboe <jaxboe@fusionio.com> wrote:
> On 2011-07-30 21:19, Kay Sievers wrote:
>> Instead of taking the lo_ctl_mutex from sysfs code, take the inner
>> lo->lo_lock, to protect the access to the backing_file data.
>>
>> Thanks to Tejun for help debugging and finding a solution.
>
> Looks good, looks like something that should have a stable tag as well?

Right, I think it makes sense to have that in -stable.

It's pretty hard to trigger, I had multiple threads running, crawling
/sys and adding/binding/unbinding/removing 1000s of loop devices, and
it takes several minutes sometimes until its hit. So I only tested it
on top of the 3 loop-control patches, but the issue should exist in
the current code as well.

Thanks,
Kay

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: loop: fix deadlock when sysfs and LOOP_CLR_FD race against each other
  2011-07-31 20:42   ` Kay Sievers
@ 2011-07-31 20:57     ` Jens Axboe
  0 siblings, 0 replies; 4+ messages in thread
From: Jens Axboe @ 2011-07-31 20:57 UTC (permalink / raw)
  To: Kay Sievers; +Cc: Milan Broz, Tejun Heo, linux-kernel@vger.kernel.org

On 2011-07-31 22:42, Kay Sievers wrote:
> On Sun, Jul 31, 2011 at 22:20, Jens Axboe <jaxboe@fusionio.com> wrote:
>> On 2011-07-30 21:19, Kay Sievers wrote:
>>> Instead of taking the lo_ctl_mutex from sysfs code, take the inner
>>> lo->lo_lock, to protect the access to the backing_file data.
>>>
>>> Thanks to Tejun for help debugging and finding a solution.
>>
>> Looks good, looks like something that should have a stable tag as well?
> 
> Right, I think it makes sense to have that in -stable.
> 
> It's pretty hard to trigger, I had multiple threads running, crawling
> /sys and adding/binding/unbinding/removing 1000s of loop devices, and
> it takes several minutes sometimes until its hit. So I only tested it
> on top of the 3 loop-control patches, but the issue should exist in
> the current code as well.

I applied those for 3.1 as well, but I'm thinking they probably should
have been queued up for 3.2 instead.

-- 
Jens Axboe


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2011-07-31 20:57 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-07-30 19:19 loop: fix deadlock when sysfs and LOOP_CLR_FD race against each other Kay Sievers
2011-07-31 20:20 ` Jens Axboe
2011-07-31 20:42   ` Kay Sievers
2011-07-31 20:57     ` Jens Axboe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox