Skip to contentSkip to conversation

loop: Do not call loop_unplug for not configured loop device.

PATCH Applied Milan Broz 2 participants 2 messages Dec 12, 2008 Block layer

lore
Share & tools
lore

Milan Broz

author
#0 lore raw

PATCH 1/1 loop: Do not call loop_unplug for not configured loop device.

Do not call loop_unplug for not configured loop device.

In loop_unplug() function is expected that mapping is set and lo->lo_backing_file is not NULL.

Unfortunately loop_set_fd() set the request queue unplug function, but loop_clr_fd() doesn't clear that.

Loop device allows open of non-configured loop in some situations. If the unplug on request queue is called, loop module oopses because of missing lo_backing_file.

Simple reproducer:
losetup /dev/loop0 /xxx
losetup -d /dev/loop0
dmsetup create x --table "0 1 linear /dev/loop0 0"

EIP is at loop_unplug+0x1d/0x3b
...

  Call Trace:
   blk_unplug+0x57/0x5e
   dm_table_unplug_all+0x34/0x77 [dm_mod]
   destroy_inode+0x27/0x38
   generic_delete_inode+0xd5/0xd9
   iput+0x4b/0x4e
   dm_resume+0xca/0xfe [dm_mod]
   dev_suspend+0x143/0x165 [dm_mod]
   dm_ctl_ioctl+0x18e/0x1cf [dm_mod]
   dev_suspend+0x0/0x165 [dm_mod]
   dm_ctl_ioctl+0x0/0x1cf [dm_mod]
   vfs_ioctl+0x22/0x69
   do_vfs_ioctl+0x39d/0x3c7
   trace_hardirqs_on+0xb/0xd
   remove_vma+0x50/0x56
   do_munmap+0x21c/0x237
   sys_ioctl+0x2c/0x45
   sysenter_do_call+0x12/0x31

Several reports here
http://www.kerneloops.org/search.php?search=loop_unplug

Fix it by simply clear unplug function together with removing of backing file.

---
 drivers/block/loop.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
drivers/block/loop.c +1 -0
index 90d19df..1e4b41e 100644
@@ -919,6 +919,7 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
 
 	kthread_stop(lo->lo_thread);
 
+	lo->lo_queue->unplug_fn = NULL;
 	lo->lo_backing_file = NULL;
 
 	loop_release_xfer(lo);
Applied
#1 lore raw
Quoted 56 lines · Milan Broz

Do not call loop_unplug for not configured loop device.

In loop_unplug() function is expected that mapping is set and lo->lo_backing_file is not NULL.

Unfortunately loop_set_fd() set the request queue unplug function, but loop_clr_fd() doesn't clear that.

Loop device allows open of non-configured loop in some situations. If the unplug on request queue is called, loop module oopses because of missing lo_backing_file.

Simple reproducer:
losetup /dev/loop0 /xxx
losetup -d /dev/loop0
dmsetup create x --table "0 1 linear /dev/loop0 0"

EIP is at loop_unplug+0x1d/0x3b
...

  Call Trace:
   blk_unplug+0x57/0x5e
   dm_table_unplug_all+0x34/0x77 [dm_mod]
   destroy_inode+0x27/0x38
   generic_delete_inode+0xd5/0xd9
   iput+0x4b/0x4e
   dm_resume+0xca/0xfe [dm_mod]
   dev_suspend+0x143/0x165 [dm_mod]
   dm_ctl_ioctl+0x18e/0x1cf [dm_mod]
   dev_suspend+0x0/0x165 [dm_mod]
   dm_ctl_ioctl+0x0/0x1cf [dm_mod]
   vfs_ioctl+0x22/0x69
   do_vfs_ioctl+0x39d/0x3c7
   trace_hardirqs_on+0xb/0xd
   remove_vma+0x50/0x56
   do_munmap+0x21c/0x237
   sys_ioctl+0x2c/0x45
   sysenter_do_call+0x12/0x31

Several reports here
http://www.kerneloops.org/search.php?search=loop_unplug

Fix it by simply clear unplug function together with removing of backing file.

---
 drivers/block/loop.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
drivers/block/loop.c +0 -0
index 90d19df..1e4b41e 100644

drivers/block/loop.c static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev) · line 925

Quoted 7 lines
drivers/block/loop.c +1 -0
@@ -919,6 +919,7 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
 
 	kthread_stop(lo->lo_thread);
 
+	lo->lo_queue->unplug_fn = NULL;
 	lo->lo_backing_file = NULL;
 
 	loop_release_xfer(lo);

Thanks, applied.

Signature · 1 line
Jens Axboe