@@ -650,17 +650,26 @@ static inline void loop_update_dio(struct loop_device *lo)
}
static void loop_reread_partitions(struct loop_device *lo,
- struct block_device *bdev, bool locked)
+ struct block_device *bdev, bool locked,
+ bool force_scan)
{
int rc;
+ bool no_scan;
- if (locked) {
- rc = bdev_disk_changed(bdev, false);
- } else {
+ if (!locked)
mutex_lock(&bdev->bd_mutex);
- rc = bdev_disk_changed(bdev, false);
+
+ no_scan = lo->lo_disk->flags & GENHD_FL_NO_PART_SCAN;
+ if (force_scan && no_scan)
+ lo->lo_disk->flags &= ~GENHD_FL_NO_PART_SCAN;
+
+ rc = bdev_disk_changed(bdev, false);
+
+ if (force_scan && no_scan)
+ lo->lo_disk->flags |= GENHD_FL_NO_PART_SCAN;
+
+ if (!locked)
mutex_unlock(&bdev->bd_mutex);
- }
if (rc)
pr_warn("%s: partition scan of loop%d (%s) failed (rc=%d)\n",
__func__, lo->lo_number, lo->lo_file_name, rc);
@@ -758,7 +767,7 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
*/
fput(old_file);
if (partscan)
- loop_reread_partitions(lo, bdev, false);
+ loop_reread_partitions(lo, bdev, false, true);
return 0;
out_err:
@@ -1183,7 +1192,7 @@ static int loop_configure(struct loop_device *lo, fmode_t mode,
bdgrab(bdev);
mutex_unlock(&loop_ctl_mutex);
if (partscan)
- loop_reread_partitions(lo, bdev, false);
+ loop_reread_partitions(lo, bdev, false, false);
if (claimed_bdev)
bd_abort_claiming(bdev, claimed_bdev, loop_configure);
return 0;
@@ -1274,7 +1283,7 @@ static int __loop_clr_fd(struct loop_device *lo, bool release)
* must be at least one and it can only become zero when the
* current holder is released.
*/
- loop_reread_partitions(lo, bdev, release);
+ loop_reread_partitions(lo, bdev, release, true);
}
/*
@@ -1415,7 +1424,7 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
out_unlock:
mutex_unlock(&loop_ctl_mutex);
if (partscan)
- loop_reread_partitions(lo, bdev, false);
+ loop_reread_partitions(lo, bdev, false, false);
return err;
}
After clearing fd or changing fd, we have to delete old partitions, otherwise they may become ghost partitions. Fix this issue by clearing GENHD_FL_NO_PART_SCAN during calling bdev_disk_changed() which won't drop old partitions if GENHD_FL_NO_PART_SCAN isn't set. Signed-off-by: Ming Lei <ming.lei@redhat.com> --- drivers/block/loop.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-)