loop: suppress uevents while reconfiguring the device
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>
This commit is contained in:
committed by
Jens Axboe
parent
d2c7f56f8b
commit
498ef5c777
+21
-4
@@ -569,6 +569,10 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
|
|||||||
|
|
||||||
if (!file)
|
if (!file)
|
||||||
return -EBADF;
|
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);
|
is_loop = is_loop_device(file);
|
||||||
error = loop_global_lock_killable(lo, is_loop);
|
error = loop_global_lock_killable(lo, is_loop);
|
||||||
if (error)
|
if (error)
|
||||||
@@ -623,13 +627,18 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
|
|||||||
fput(old_file);
|
fput(old_file);
|
||||||
if (partscan)
|
if (partscan)
|
||||||
loop_reread_partitions(lo);
|
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:
|
out_err:
|
||||||
loop_global_unlock(lo, is_loop);
|
loop_global_unlock(lo, is_loop);
|
||||||
out_putf:
|
out_putf:
|
||||||
fput(file);
|
fput(file);
|
||||||
return error;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* loop sysfs attributes */
|
/* 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(). */
|
/* This is safe, since we have a reference from open(). */
|
||||||
__module_get(THIS_MODULE);
|
__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
|
* If we don't hold exclusive handle for the device, upgrade to it
|
||||||
* here to avoid changing device under exclusive owner.
|
* 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);
|
loop_reread_partitions(lo);
|
||||||
if (!(mode & FMODE_EXCL))
|
if (!(mode & FMODE_EXCL))
|
||||||
bd_abort_claiming(bdev, loop_configure);
|
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:
|
out_unlock:
|
||||||
loop_global_unlock(lo, is_loop);
|
loop_global_unlock(lo, is_loop);
|
||||||
@@ -1107,7 +1124,7 @@ out_putf:
|
|||||||
fput(file);
|
fput(file);
|
||||||
/* This is safe: open() is still holding a reference. */
|
/* This is safe: open() is still holding a reference. */
|
||||||
module_put(THIS_MODULE);
|
module_put(THIS_MODULE);
|
||||||
return error;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __loop_clr_fd(struct loop_device *lo, bool release)
|
static void __loop_clr_fd(struct loop_device *lo, bool release)
|
||||||
|
|||||||
Reference in New Issue
Block a user