Skip to content

Commit c4f4c0f

Browse files
daandemeyeraxboe
authored andcommitted
loop: remove manually added partitions on detach
Commit 267ec4d ("loop: fix partition scan race between udev and loop_reread_partitions()") stopped disk_force_media_change() from setting GD_NEED_PART_SCAN because loop devices with LO_FLAGS_PARTSCAN rescan partitions explicitly. However, partitions can also be added manually with BLKPG while LO_FLAGS_PARTSCAN is clear. When such a loop device is detached, __loop_clr_fd() skips bdev_disk_changed(). Without GD_NEED_PART_SCAN, reopening the unbound device no longer performs the previous lazy cleanup, leaving dead partition devices behind. A subsequent LOOP_CONFIGURE can then fail its partition scan with -EBUSY, as seen in blktests loop/009 after loop/008. Call bdev_disk_changed() unconditionally during __loop_clr_fd(). The disk capacity is already zero and the release path holds open_mutex, so this drops all partitions without rescanning the detached backing file. The new blktests loop/013 case covers this sequence by adding a partition with BLKPG without LO_FLAGS_PARTSCAN, detaching the loop device, and checking that the partition is gone when the device is reopened. Fixes: 267ec4d ("loop: fix partition scan race between udev and loop_reread_partitions()") Reported-by: kernel test robot <oliver.sang@intel.com> Closes: https://lore.kernel.org/oe-lkp/202607150754.b660f5b9-lkp@intel.com Signed-off-by: Daan De Meyer <daan@amutable.com> Link: https://patch.msgid.link/20260715-b4-loop-partition-cleanup-v1-1-b9f59910cd1e@amutable.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 691b052 commit c4f4c0f

1 file changed

Lines changed: 14 additions & 18 deletions

File tree

drivers/block/loop.c

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,6 +1113,7 @@ static void __loop_clr_fd(struct loop_device *lo)
11131113
struct queue_limits lim;
11141114
struct file *filp;
11151115
gfp_t gfp = lo->old_gfp_mask;
1116+
int err;
11161117

11171118
spin_lock_irq(&lo->lo_lock);
11181119
filp = lo->lo_backing_file;
@@ -1146,26 +1147,21 @@ static void __loop_clr_fd(struct loop_device *lo)
11461147

11471148
disk_force_media_change(lo->lo_disk);
11481149

1149-
if (lo->lo_flags & LO_FLAGS_PARTSCAN) {
1150-
int err;
1151-
1152-
/*
1153-
* open_mutex has been held already in release path, so don't
1154-
* acquire it if this function is called in such case.
1155-
*
1156-
* If the reread partition isn't from release path, lo_refcnt
1157-
* must be at least one and it can only become zero when the
1158-
* current holder is released.
1159-
*/
1160-
err = bdev_disk_changed(lo->lo_disk, false);
1161-
if (err)
1162-
pr_warn("%s: partition scan of loop%d failed (rc=%d)\n",
1163-
__func__, lo->lo_number, err);
1164-
/* Device is gone, no point in returning error */
1165-
}
1150+
/*
1151+
* Remove all partitions, including partitions added manually with
1152+
* BLKPG, which may exist even if LO_FLAGS_PARTSCAN is not set.
1153+
*
1154+
* open_mutex has been held already in release path, so don't acquire
1155+
* it here.
1156+
*/
1157+
err = bdev_disk_changed(lo->lo_disk, false);
1158+
if (err)
1159+
pr_warn("%s: partition scan of loop%d failed (rc=%d)\n",
1160+
__func__, lo->lo_number, err);
1161+
/* Device is gone, no point in returning error */
11661162

11671163
/*
1168-
* lo->lo_state is set to Lo_unbound here after above partscan has
1164+
* lo->lo_state is set to Lo_unbound here after removing partitions has
11691165
* finished. There cannot be anybody else entering __loop_clr_fd() as
11701166
* Lo_rundown state protects us from all the other places trying to
11711167
* change the 'lo' device.

0 commit comments

Comments
 (0)