@@ -264,6 +264,7 @@ struct rbd_device {
enum rbd_dev_flags {
rbd_dev_flag_exists, /* mapped snapshot has not been deleted */
+ rbd_dev_flag_removing, /* this mapping is being removed */
};
static DEFINE_MUTEX(ctl_mutex); /* Serialize open/close/setup/teardown */
@@ -351,17 +352,22 @@ static int rbd_dev_v2_refresh(struct rbd_device
*rbd_dev, u64 *hver);
static int rbd_open(struct block_device *bdev, fmode_t mode)
{
struct rbd_device *rbd_dev = bdev->bd_disk->private_data;
+ int ret = 0;
if ((mode & FMODE_WRITE) && rbd_dev->mapping.read_only)
return -EROFS;
mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
- (void) get_device(&rbd_dev->dev);
- set_device_ro(bdev, rbd_dev->mapping.read_only);
- rbd_dev->open_count++;
+ if (!test_bit(rbd_dev_flag_removing, &rbd_dev->flags)) {
+ (void) get_device(&rbd_dev->dev);
+ set_device_ro(bdev, rbd_dev->mapping.read_only);
+ rbd_dev->open_count++;
+ } else {
+ ret = -ENOENT;
+ }
mutex_unlock(&ctl_mutex);
- return 0;
+ return ret;
}
An open request for a mapped rbd image can arrive while removal of that mapping is underway. The control mutex and an open count is protect a mapped device that's in use from being removed. But it is possible for the removal of the mapping to reach the point of no return *after* a racing open has concluded it is OK to proceed. The result of this is not good. Define and use a flag to indicate a mapping is getting removed to avoid this problem. This addresses http://tracker.newdream.net/issues/3427 Signed-off-by: Alex Elder <elder@inktank.com> --- drivers/block/rbd.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) static int rbd_release(struct gendisk *disk, fmode_t mode) @@ -3796,6 +3802,7 @@ static ssize_t rbd_remove(struct bus_type *bus, ret = -EBUSY; goto done; } + set_bit(rbd_dev_flag_removing, &rbd_dev->flags); rbd_remove_all_snaps(rbd_dev); rbd_bus_del_dev(rbd_dev);