loop: suppress uevents while reconfiguring the device
authorChristoph Hellwig <hch@lst.de>
Wed, 30 Mar 2022 05:29:14 +0000 (07:29 +0200)
committerJens Axboe <axboe@kernel.dk>
Mon, 18 Apr 2022 12:54:09 +0000 (06:54 -0600)
Currently, udev change event is generated for a loop device before the
device is ready for IO. Due to serialization on lo->lo_mutex in
lo_open() this does not matter because anybody is able to open the
device and do IO only after the configuration is finished. However this
synchronization in lo_open() is going away so make sure userspace
reacting to the change event will see the new device state by generating
the event only when the device is setup.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jan Kara <jack@suse.cz>
Link: https://lore.kernel.org/r/20220330052917.2566582-13-hch@lst.de
Signed-off-by: Jens Axboe <axboe@kernel.dk>
drivers/block/loop.c

index e0c8768..ef76923 100644 (file)
@@ -569,6 +569,10 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
 
        if (!file)
                return -EBADF;
+
+       /* suppress uevents while reconfiguring the device */
+       dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 1);
+
        is_loop = is_loop_device(file);
        error = loop_global_lock_killable(lo, is_loop);
        if (error)
@@ -623,13 +627,18 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
        fput(old_file);
        if (partscan)
                loop_reread_partitions(lo);
-       return 0;
+
+       error = 0;
+done:
+       /* enable and uncork uevent now that we are done */
+       dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 0);
+       return error;
 
 out_err:
        loop_global_unlock(lo, is_loop);
 out_putf:
        fput(file);
-       return error;
+       goto done;
 }
 
 /* loop sysfs attributes */
@@ -994,6 +1003,9 @@ static int loop_configure(struct loop_device *lo, fmode_t mode,
        /* This is safe, since we have a reference from open(). */
        __module_get(THIS_MODULE);
 
+       /* suppress uevents while reconfiguring the device */
+       dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 1);
+
        /*
         * If we don't hold exclusive handle for the device, upgrade to it
         * here to avoid changing device under exclusive owner.
@@ -1096,7 +1108,12 @@ static int loop_configure(struct loop_device *lo, fmode_t mode,
                loop_reread_partitions(lo);
        if (!(mode & FMODE_EXCL))
                bd_abort_claiming(bdev, loop_configure);
-       return 0;
+
+       error = 0;
+done:
+       /* enable and uncork uevent now that we are done */
+       dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 0);
+       return error;
 
 out_unlock:
        loop_global_unlock(lo, is_loop);
@@ -1107,7 +1124,7 @@ out_putf:
        fput(file);
        /* This is safe: open() is still holding a reference. */
        module_put(THIS_MODULE);
-       return error;
+       goto done;
 }
 
 static void __loop_clr_fd(struct loop_device *lo, bool release)