提交 0276dca6 编写于 作者: M Mike Christie 提交者: Ilya Dryomov

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: NMike Christie <mchristi@redhat.com>
Signed-off-by: NIlya Dryomov <idryomov@gmail.com>
上级 0d6d1e9c
......@@ -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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册