summaryrefslogtreecommitdiff
path: root/drivers/block/nbd.c
diff options
context:
space:
mode:
authorJosef Bacik <josef@toxicpanda.com>2017-04-07 00:02:07 +0300
committerJens Axboe <axboe@fb.com>2017-04-17 18:58:42 +0300
commita2c97909f97ef32b76e856572fba4f77e1885fe6 (patch)
tree93693ce1eb0141806a19c307b92b6d5e11bbab0e /drivers/block/nbd.c
parentc6a4759ea0c9a7e7661f34f6943dafb1c6ae1b1c (diff)
downloadlinux-a2c97909f97ef32b76e856572fba4f77e1885fe6.tar.xz
nbd: add a flag to destroy an nbd device on disconnect
For ease of management it would be nice for users to specify that the device node for a nbd device is destroyed once it is disconnected and there are no more users. Add a client flag and enable this operation to happen. Signed-off-by: Josef Bacik <jbacik@fb.com> Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'drivers/block/nbd.c')
-rw-r--r--drivers/block/nbd.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 4237e7286e99..b78f23ce2395 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -74,6 +74,7 @@ struct link_dead_args {
#define NBD_HAS_PID_FILE 3
#define NBD_HAS_CONFIG_REF 4
#define NBD_BOUND 5
+#define NBD_DESTROY_ON_DISCONNECT 6
struct nbd_config {
u32 flags;
@@ -174,6 +175,7 @@ static void nbd_dev_remove(struct nbd_device *nbd)
del_gendisk(disk);
blk_cleanup_queue(disk->queue);
blk_mq_free_tag_set(&nbd->tag_set);
+ disk->private_data = NULL;
put_disk(disk);
}
kfree(nbd);
@@ -1028,6 +1030,7 @@ static void nbd_config_put(struct nbd_device *nbd)
kfree(config->socks);
}
nbd_reset(nbd);
+
mutex_unlock(&nbd->config_lock);
nbd_put(nbd);
module_put(THIS_MODULE);
@@ -1539,6 +1542,7 @@ static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info)
struct nbd_config *config;
int index = -1;
int ret;
+ bool put_dev = false;
if (!netlink_capable(skb, CAP_SYS_ADMIN))
return -EPERM;
@@ -1633,6 +1637,15 @@ again:
if (info->attrs[NBD_ATTR_SERVER_FLAGS])
config->flags =
nla_get_u64(info->attrs[NBD_ATTR_SERVER_FLAGS]);
+ if (info->attrs[NBD_ATTR_CLIENT_FLAGS]) {
+ u64 flags = nla_get_u64(info->attrs[NBD_ATTR_CLIENT_FLAGS]);
+ if (flags & NBD_CFLAG_DESTROY_ON_DISCONNECT) {
+ set_bit(NBD_DESTROY_ON_DISCONNECT,
+ &config->runtime_flags);
+ put_dev = true;
+ }
+ }
+
if (info->attrs[NBD_ATTR_SOCKETS]) {
struct nlattr *attr;
int rem, fd;
@@ -1670,6 +1683,8 @@ out:
nbd_connect_reply(info, nbd->index);
}
nbd_config_put(nbd);
+ if (put_dev)
+ nbd_put(nbd);
return ret;
}
@@ -1722,6 +1737,7 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)
struct nbd_config *config;
int index;
int ret = -EINVAL;
+ bool put_dev = false;
if (!netlink_capable(skb, CAP_SYS_ADMIN))
return -EPERM;
@@ -1773,6 +1789,18 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)
nla_get_u64(info->attrs[NBD_ATTR_DEAD_CONN_TIMEOUT]);
config->dead_conn_timeout *= HZ;
}
+ if (info->attrs[NBD_ATTR_CLIENT_FLAGS]) {
+ u64 flags = nla_get_u64(info->attrs[NBD_ATTR_CLIENT_FLAGS]);
+ if (flags & NBD_CFLAG_DESTROY_ON_DISCONNECT) {
+ if (!test_and_set_bit(NBD_DESTROY_ON_DISCONNECT,
+ &config->runtime_flags))
+ put_dev = true;
+ } else {
+ if (test_and_clear_bit(NBD_DESTROY_ON_DISCONNECT,
+ &config->runtime_flags))
+ refcount_inc(&nbd->refs);
+ }
+ }
if (info->attrs[NBD_ATTR_SOCKETS]) {
struct nlattr *attr;
@@ -1810,6 +1838,8 @@ out:
mutex_unlock(&nbd->config_lock);
nbd_config_put(nbd);
nbd_put(nbd);
+ if (put_dev)
+ nbd_put(nbd);
return ret;
}