block, loop: support partitions without scanning
authorChristoph Hellwig <hch@lst.de>
Fri, 27 May 2022 05:58:06 +0000 (07:58 +0200)
committerJens Axboe <axboe@kernel.dk>
Fri, 27 May 2022 12:39:00 +0000 (06:39 -0600)
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 <ming.lei@redhat.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Ming Lei <ming.lei@redhat.com>
Link: https://lore.kernel.org/r/20220527055806.1972352-1-hch@lst.de
Signed-off-by: Jens Axboe <axboe@kernel.dk>
block/genhd.c
drivers/block/loop.c
include/linux/blkdev.h

index 36532b93184191e08f5ab8048ecb6ce99cfc33ee..27205ae47d593b35076630d514be6baa299055af 100644 (file)
@@ -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;
 
index 01b4e257016a149d8715a87574533d233e970982..121f96dfc23ebe66a94a3e1fbe5051003540a64c 100644 (file)
@@ -1102,7 +1102,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)
@@ -1198,7 +1198,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);
@@ -1308,7 +1308,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:
@@ -2009,7 +2009,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);
        mutex_init(&lo->lo_mutex);
        lo->lo_number           = i;
        spin_lock_init(&lo->lo_lock);
index afad3d1d0dac0b47b19974d75a180d77dd5dc5a0..691b4c15b8ce1a1055426e4e326652ffa99173a2 100644 (file)
@@ -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 */