rbd: do not allow remove of mounted-on image
There is no check in rbd_remove() to see if anybody holds open the image being removed. That's not cool. Add a simple open count that goes up and down with opens and closes (releases) of the device, and don't allow an rbd image to be removed if the count is non-zero. Protect the updates of the open count value with ctl_mutex to ensure the underlying rbd device doesn't get removed while concurrently being opened. Signed-off-by: Alex Elder <elder@inktank.com> Reviewed-by: Sage Weil <sage@inktank.com>
This commit is contained in:
parent
8884d53dd6
commit
42382b709b
|
@ -235,6 +235,7 @@ struct rbd_device {
|
|||
|
||||
/* sysfs related */
|
||||
struct device dev;
|
||||
unsigned long open_count;
|
||||
};
|
||||
|
||||
static DEFINE_MUTEX(ctl_mutex); /* Serialize open/close/setup/teardown */
|
||||
|
@ -309,8 +310,11 @@ static int rbd_open(struct block_device *bdev, fmode_t mode)
|
|||
if ((mode & FMODE_WRITE) && rbd_dev->mapping.read_only)
|
||||
return -EROFS;
|
||||
|
||||
mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
|
||||
rbd_get_dev(rbd_dev);
|
||||
set_device_ro(bdev, rbd_dev->mapping.read_only);
|
||||
rbd_dev->open_count++;
|
||||
mutex_unlock(&ctl_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -319,7 +323,11 @@ static int rbd_release(struct gendisk *disk, fmode_t mode)
|
|||
{
|
||||
struct rbd_device *rbd_dev = disk->private_data;
|
||||
|
||||
mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
|
||||
rbd_assert(rbd_dev->open_count > 0);
|
||||
rbd_dev->open_count--;
|
||||
rbd_put_dev(rbd_dev);
|
||||
mutex_unlock(&ctl_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -3745,6 +3753,11 @@ static ssize_t rbd_remove(struct bus_type *bus,
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (rbd_dev->open_count) {
|
||||
ret = -EBUSY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
rbd_remove_all_snaps(rbd_dev);
|
||||
rbd_bus_del_dev(rbd_dev);
|
||||
|
||||
|
|
Loading…
Reference in New Issue