From 60244f0332cce1e7c86d5d38c34220e77edde2de Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 27 May 2022 07:58:06 +0200 Subject: [PATCH] block, loop: support partitions without scanning Origin: https://git.kernel.org/linus/b9684a71fca793213378dd410cd11675d973eaa1 Bug-Debian: https://bugs.debian.org/1012298 Historically we did distinguish between a flag that surpressed partition scanning, and a combinations of the minors variable and another flag if any partitions were supported. This was generally confusing and doesn't make much sense, but some corner case uses of the loop driver actually do want to support manually added partitions on a device that does not actively scan for partitions. To make things worsee the loop driver also wants to dynamically toggle the scanning for partitions on a live gendisk, which makes the disk->flags updates non-atomic. Introduce a new GD_SUPPRESS_PART_SCAN bit in disk->state that disables just scanning for partitions, and toggle that instead of GENHD_FL_NO_PART in the loop driver. Fixes: 1ebe2e5f9d68 ("block: remove GENHD_FL_EXT_DEVT") Reported-by: Ming Lei Signed-off-by: Christoph Hellwig Reviewed-by: Ming Lei Link: https://lore.kernel.org/r/20220527055806.1972352-1-hch@lst.de Signed-off-by: Jens Axboe [Backport to 5.18.y: Refresh context in drivers/block/loop.c not containing a0e286b6a5b6 ("loop: remove lo_refcount and avoid lo_mutex in ->open / ->release")] Gbp-Pq: Topic bugfix/all Gbp-Pq: Name block-loop-support-partitions-without-scanning.patch --- block/genhd.c | 2 ++ drivers/block/loop.c | 8 ++++---- include/linux/blkdev.h | 1 + 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index b8b6759d670..3008ec21365 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -385,6 +385,8 @@ int disk_scan_partitions(struct gendisk *disk, fmode_t mode) if (disk->flags & (GENHD_FL_NO_PART | GENHD_FL_HIDDEN)) return -EINVAL; + if (test_bit(GD_SUPPRESS_PART_SCAN, &disk->state)) + return -EINVAL; if (disk->open_partitions) return -EBUSY; diff --git a/drivers/block/loop.c b/drivers/block/loop.c index a58595f5ee2..ba3627f982f 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1066,7 +1066,7 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, lo->lo_flags |= LO_FLAGS_PARTSCAN; partscan = lo->lo_flags & LO_FLAGS_PARTSCAN; if (partscan) - lo->lo_disk->flags &= ~GENHD_FL_NO_PART; + clear_bit(GD_SUPPRESS_PART_SCAN, &lo->lo_disk->state); loop_global_unlock(lo, is_loop); if (partscan) @@ -1185,7 +1185,7 @@ static void __loop_clr_fd(struct loop_device *lo, bool release) */ lo->lo_flags = 0; if (!part_shift) - lo->lo_disk->flags |= GENHD_FL_NO_PART; + set_bit(GD_SUPPRESS_PART_SCAN, &lo->lo_disk->state); mutex_lock(&lo->lo_mutex); lo->lo_state = Lo_unbound; mutex_unlock(&lo->lo_mutex); @@ -1295,7 +1295,7 @@ out_unfreeze: if (!err && (lo->lo_flags & LO_FLAGS_PARTSCAN) && !(prev_lo_flags & LO_FLAGS_PARTSCAN)) { - lo->lo_disk->flags &= ~GENHD_FL_NO_PART; + clear_bit(GD_SUPPRESS_PART_SCAN, &lo->lo_disk->state); partscan = true; } out_unlock: @@ -2045,7 +2045,7 @@ static int loop_add(int i) * userspace tools. Parameters like this in general should be avoided. */ if (!part_shift) - disk->flags |= GENHD_FL_NO_PART; + set_bit(GD_SUPPRESS_PART_SCAN, &disk->state); atomic_set(&lo->lo_refcnt, 0); mutex_init(&lo->lo_mutex); lo->lo_number = i; diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 60d01613899..108e3d114bf 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -147,6 +147,7 @@ struct gendisk { #define GD_DEAD 2 #define GD_NATIVE_CAPACITY 3 #define GD_ADDED 4 +#define GD_SUPPRESS_PART_SCAN 5 struct mutex open_mutex; /* open/close mutex */ unsigned open_partitions; /* number of open partitions */ -- 2.30.2