Skip to content

Commit 18048c1

Browse files
gulamsaxboe
authored andcommitted
loop: Fix a race between loop detach and loop open
1. Userspace sends the command "losetup -d" which uses the open() call to open the device 2. Kernel receives the ioctl command "LOOP_CLR_FD" which calls the function loop_clr_fd() 3. If LOOP_CLR_FD is the first command received at the time, then the AUTOCLEAR flag is not set and deletion of the loop device proceeds ahead and scans the partitions (drop/add partitions) if (disk_openers(lo->lo_disk) > 1) { lo->lo_flags |= LO_FLAGS_AUTOCLEAR; loop_global_unlock(lo, true); return 0; } 4. Before scanning partitions, it will check to see if any partition of the loop device is currently opened 5. If any partition is opened, then it will return EBUSY: if (disk->open_partitions) return -EBUSY; 6. So, after receiving the "LOOP_CLR_FD" command and just before the above check for open_partitions, if any other command (like blkid) opens any partition of the loop device, then the partition scan will not proceed and EBUSY is returned as shown in above code 7. But in "__loop_clr_fd()", this EBUSY error is not propagated 8. We have noticed that this is causing the partitions of the loop to remain stale even after the loop device is detached resulting in the IO errors on the partitions Fix: Defer the detach of loop device to release function, which is called when the last close happens, by setting the lo_flags to LO_FLAGS_AUTOCLEAR at the time of detach i.e in loop_clr_fd() function. Test case involves the following two scripts: script1.sh: while [ 1 ]; do losetup -P -f /home/opt/looptest/test10.img blkid /dev/loop0p1 done script2.sh: while [ 1 ]; do losetup -d /dev/loop0 done Without fix, the following IO errors have been observed: kernel: __loop_clr_fd: partition scan of loop0 failed (rc=-16) kernel: I/O error, dev loop0, sector 20971392 op 0x0:(READ) flags 0x80700 phys_seg 1 prio class 0 kernel: I/O error, dev loop0, sector 108868 op 0x0:(READ) flags 0x0 phys_seg 1 prio class 0 kernel: Buffer I/O error on dev loop0p1, logical block 27201, async page read Signed-off-by: Gulam Mohamed <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent 63db4a1 commit 18048c1

File tree

1 file changed

+36
-39
lines changed

1 file changed

+36
-39
lines changed

drivers/block/loop.c

Lines changed: 36 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,20 +1123,12 @@ static int loop_configure(struct loop_device *lo, blk_mode_t mode,
11231123
return error;
11241124
}
11251125

1126-
static void __loop_clr_fd(struct loop_device *lo, bool release)
1126+
static void __loop_clr_fd(struct loop_device *lo)
11271127
{
11281128
struct queue_limits lim;
11291129
struct file *filp;
11301130
gfp_t gfp = lo->old_gfp_mask;
11311131

1132-
/*
1133-
* Freeze the request queue when unbinding on a live file descriptor and
1134-
* thus an open device. When called from ->release we are guaranteed
1135-
* that there is no I/O in progress already.
1136-
*/
1137-
if (!release)
1138-
blk_mq_freeze_queue(lo->lo_queue);
1139-
11401132
spin_lock_irq(&lo->lo_lock);
11411133
filp = lo->lo_backing_file;
11421134
lo->lo_backing_file = NULL;
@@ -1161,8 +1153,6 @@ static void __loop_clr_fd(struct loop_device *lo, bool release)
11611153
mapping_set_gfp_mask(filp->f_mapping, gfp);
11621154
/* This is safe: open() is still holding a reference. */
11631155
module_put(THIS_MODULE);
1164-
if (!release)
1165-
blk_mq_unfreeze_queue(lo->lo_queue);
11661156

11671157
disk_force_media_change(lo->lo_disk);
11681158

@@ -1177,11 +1167,7 @@ static void __loop_clr_fd(struct loop_device *lo, bool release)
11771167
* must be at least one and it can only become zero when the
11781168
* current holder is released.
11791169
*/
1180-
if (!release)
1181-
mutex_lock(&lo->lo_disk->open_mutex);
11821170
err = bdev_disk_changed(lo->lo_disk, false);
1183-
if (!release)
1184-
mutex_unlock(&lo->lo_disk->open_mutex);
11851171
if (err)
11861172
pr_warn("%s: partition scan of loop%d failed (rc=%d)\n",
11871173
__func__, lo->lo_number, err);
@@ -1230,24 +1216,16 @@ static int loop_clr_fd(struct loop_device *lo)
12301216
return -ENXIO;
12311217
}
12321218
/*
1233-
* If we've explicitly asked to tear down the loop device,
1234-
* and it has an elevated reference count, set it for auto-teardown when
1235-
* the last reference goes away. This stops $!~#$@ udev from
1236-
* preventing teardown because it decided that it needs to run blkid on
1237-
* the loopback device whenever they appear. xfstests is notorious for
1238-
* failing tests because blkid via udev races with a losetup
1239-
* <dev>/do something like mkfs/losetup -d <dev> causing the losetup -d
1240-
* command to fail with EBUSY.
1219+
* Mark the device for removing the backing device on last close.
1220+
* If we are the only opener, also switch the state to roundown here to
1221+
* prevent new openers from coming in.
12411222
*/
1242-
if (disk_openers(lo->lo_disk) > 1) {
1243-
lo->lo_flags |= LO_FLAGS_AUTOCLEAR;
1244-
loop_global_unlock(lo, true);
1245-
return 0;
1246-
}
1247-
lo->lo_state = Lo_rundown;
1223+
1224+
lo->lo_flags |= LO_FLAGS_AUTOCLEAR;
1225+
if (disk_openers(lo->lo_disk) == 1)
1226+
lo->lo_state = Lo_rundown;
12481227
loop_global_unlock(lo, true);
12491228

1250-
__loop_clr_fd(lo, false);
12511229
return 0;
12521230
}
12531231

@@ -1714,25 +1692,43 @@ static int lo_compat_ioctl(struct block_device *bdev, blk_mode_t mode,
17141692
}
17151693
#endif
17161694

1695+
static int lo_open(struct gendisk *disk, blk_mode_t mode)
1696+
{
1697+
struct loop_device *lo = disk->private_data;
1698+
int err;
1699+
1700+
err = mutex_lock_killable(&lo->lo_mutex);
1701+
if (err)
1702+
return err;
1703+
1704+
if (lo->lo_state == Lo_deleting || lo->lo_state == Lo_rundown)
1705+
err = -ENXIO;
1706+
mutex_unlock(&lo->lo_mutex);
1707+
return err;
1708+
}
1709+
17171710
static void lo_release(struct gendisk *disk)
17181711
{
17191712
struct loop_device *lo = disk->private_data;
1713+
bool need_clear = false;
17201714

17211715
if (disk_openers(disk) > 0)
17221716
return;
1717+
/*
1718+
* Clear the backing device information if this is the last close of
1719+
* a device that's been marked for auto clear, or on which LOOP_CLR_FD
1720+
* has been called.
1721+
*/
17231722

17241723
mutex_lock(&lo->lo_mutex);
1725-
if (lo->lo_state == Lo_bound && (lo->lo_flags & LO_FLAGS_AUTOCLEAR)) {
1724+
if (lo->lo_state == Lo_bound && (lo->lo_flags & LO_FLAGS_AUTOCLEAR))
17261725
lo->lo_state = Lo_rundown;
1727-
mutex_unlock(&lo->lo_mutex);
1728-
/*
1729-
* In autoclear mode, stop the loop thread
1730-
* and remove configuration after last close.
1731-
*/
1732-
__loop_clr_fd(lo, true);
1733-
return;
1734-
}
1726+
1727+
need_clear = (lo->lo_state == Lo_rundown);
17351728
mutex_unlock(&lo->lo_mutex);
1729+
1730+
if (need_clear)
1731+
__loop_clr_fd(lo);
17361732
}
17371733

17381734
static void lo_free_disk(struct gendisk *disk)
@@ -1749,6 +1745,7 @@ static void lo_free_disk(struct gendisk *disk)
17491745

17501746
static const struct block_device_operations lo_fops = {
17511747
.owner = THIS_MODULE,
1748+
.open = lo_open,
17521749
.release = lo_release,
17531750
.ioctl = lo_ioctl,
17541751
#ifdef CONFIG_COMPAT

0 commit comments

Comments
 (0)