mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-30 07:34:12 +08:00
rbd: add force close option
This adds a force close option, so we can force the unmapping of a rbd device that is open. If a path/device is blacklisted, apps like multipathd can map a new device and then unmap the old one. The unmapping cleanup would then be handled by the generic hotunplug code paths in multipahd like is done for iSCSI, FC/FCOE, SAS, etc. Signed-off-by: Mike Christie <mchristi@redhat.com> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
This commit is contained in:
parent
0d6d1e9c2e
commit
0276dca6c1
@ -6,7 +6,7 @@ Description:
|
||||
|
||||
Being used for adding and removing rbd block devices.
|
||||
|
||||
Usage: <mon ip addr> <options> <pool name> <rbd image name> [snap name]
|
||||
Usage: <mon ip addr> <options> <pool name> <rbd image name> [<snap name>]
|
||||
|
||||
$ echo "192.168.0.1 name=admin rbd foo" > /sys/bus/rbd/add
|
||||
|
||||
@ -14,9 +14,13 @@ The snapshot name can be "-" or omitted to map the image read/write. A <dev-id>
|
||||
will be assigned for any registered block device. If snapshot is used, it will
|
||||
be mapped read-only.
|
||||
|
||||
Removal of a device:
|
||||
Usage: <dev-id> [force]
|
||||
|
||||
$ echo <dev-id> > /sys/bus/rbd/remove
|
||||
$ echo 2 > /sys/bus/rbd/remove
|
||||
|
||||
Optional "force" argument which when passed will wait for running requests and
|
||||
then unmap the image. Requests sent to the driver after initiating the removal
|
||||
will be failed. (August 2016, since 4.9.)
|
||||
|
||||
What: /sys/bus/rbd/add_single_major
|
||||
Date: December 2013
|
||||
|
@ -6347,18 +6347,26 @@ static ssize_t do_rbd_remove(struct bus_type *bus,
|
||||
struct rbd_device *rbd_dev = NULL;
|
||||
struct list_head *tmp;
|
||||
int dev_id;
|
||||
unsigned long ul;
|
||||
char opt_buf[6];
|
||||
bool already = false;
|
||||
bool force = false;
|
||||
int ret;
|
||||
|
||||
ret = kstrtoul(buf, 10, &ul);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* convert to int; abort if we lost anything in the conversion */
|
||||
dev_id = (int)ul;
|
||||
if (dev_id != ul)
|
||||
dev_id = -1;
|
||||
opt_buf[0] = '\0';
|
||||
sscanf(buf, "%d %5s", &dev_id, opt_buf);
|
||||
if (dev_id < 0) {
|
||||
pr_err("dev_id out of range\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (opt_buf[0] != '\0') {
|
||||
if (!strcmp(opt_buf, "force")) {
|
||||
force = true;
|
||||
} else {
|
||||
pr_err("bad remove option at '%s'\n", opt_buf);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
ret = -ENOENT;
|
||||
spin_lock(&rbd_dev_list_lock);
|
||||
@ -6371,7 +6379,7 @@ static ssize_t do_rbd_remove(struct bus_type *bus,
|
||||
}
|
||||
if (!ret) {
|
||||
spin_lock_irq(&rbd_dev->lock);
|
||||
if (rbd_dev->open_count)
|
||||
if (rbd_dev->open_count && !force)
|
||||
ret = -EBUSY;
|
||||
else
|
||||
already = test_and_set_bit(RBD_DEV_FLAG_REMOVING,
|
||||
@ -6382,6 +6390,15 @@ static ssize_t do_rbd_remove(struct bus_type *bus,
|
||||
if (ret < 0 || already)
|
||||
return ret;
|
||||
|
||||
if (force) {
|
||||
/*
|
||||
* Prevent new IO from being queued and wait for existing
|
||||
* IO to complete/fail.
|
||||
*/
|
||||
blk_mq_freeze_queue(rbd_dev->disk->queue);
|
||||
blk_set_queue_dying(rbd_dev->disk->queue);
|
||||
}
|
||||
|
||||
down_write(&rbd_dev->lock_rwsem);
|
||||
if (__rbd_is_lock_owner(rbd_dev))
|
||||
rbd_unlock(rbd_dev);
|
||||
|
Loading…
Reference in New Issue
Block a user