diff options
author | Josef Bacik <josef@toxicpanda.com> | 2017-04-06 17:02:07 -0400 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2017-04-17 11:58:42 -0400 |
commit | a2c97909f97ef32b76e856572fba4f77e1885fe6 (patch) | |
tree | 93693ce1eb0141806a19c307b92b6d5e11bbab0e | |
parent | c6a4759ea0c9a7e7661f34f6943dafb1c6ae1b1c (diff) |
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>
-rw-r--r-- | drivers/block/nbd.c | 30 | ||||
-rw-r--r-- | include/uapi/linux/nbd.h | 6 |
2 files changed, 35 insertions, 1 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 { | |||
74 | #define NBD_HAS_PID_FILE 3 | 74 | #define NBD_HAS_PID_FILE 3 |
75 | #define NBD_HAS_CONFIG_REF 4 | 75 | #define NBD_HAS_CONFIG_REF 4 |
76 | #define NBD_BOUND 5 | 76 | #define NBD_BOUND 5 |
77 | #define NBD_DESTROY_ON_DISCONNECT 6 | ||
77 | 78 | ||
78 | struct nbd_config { | 79 | struct nbd_config { |
79 | u32 flags; | 80 | u32 flags; |
@@ -174,6 +175,7 @@ static void nbd_dev_remove(struct nbd_device *nbd) | |||
174 | del_gendisk(disk); | 175 | del_gendisk(disk); |
175 | blk_cleanup_queue(disk->queue); | 176 | blk_cleanup_queue(disk->queue); |
176 | blk_mq_free_tag_set(&nbd->tag_set); | 177 | blk_mq_free_tag_set(&nbd->tag_set); |
178 | disk->private_data = NULL; | ||
177 | put_disk(disk); | 179 | put_disk(disk); |
178 | } | 180 | } |
179 | kfree(nbd); | 181 | kfree(nbd); |
@@ -1028,6 +1030,7 @@ static void nbd_config_put(struct nbd_device *nbd) | |||
1028 | kfree(config->socks); | 1030 | kfree(config->socks); |
1029 | } | 1031 | } |
1030 | nbd_reset(nbd); | 1032 | nbd_reset(nbd); |
1033 | |||
1031 | mutex_unlock(&nbd->config_lock); | 1034 | mutex_unlock(&nbd->config_lock); |
1032 | nbd_put(nbd); | 1035 | nbd_put(nbd); |
1033 | module_put(THIS_MODULE); | 1036 | module_put(THIS_MODULE); |
@@ -1539,6 +1542,7 @@ static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info) | |||
1539 | struct nbd_config *config; | 1542 | struct nbd_config *config; |
1540 | int index = -1; | 1543 | int index = -1; |
1541 | int ret; | 1544 | int ret; |
1545 | bool put_dev = false; | ||
1542 | 1546 | ||
1543 | if (!netlink_capable(skb, CAP_SYS_ADMIN)) | 1547 | if (!netlink_capable(skb, CAP_SYS_ADMIN)) |
1544 | return -EPERM; | 1548 | return -EPERM; |
@@ -1633,6 +1637,15 @@ again: | |||
1633 | if (info->attrs[NBD_ATTR_SERVER_FLAGS]) | 1637 | if (info->attrs[NBD_ATTR_SERVER_FLAGS]) |
1634 | config->flags = | 1638 | config->flags = |
1635 | nla_get_u64(info->attrs[NBD_ATTR_SERVER_FLAGS]); | 1639 | nla_get_u64(info->attrs[NBD_ATTR_SERVER_FLAGS]); |
1640 | if (info->attrs[NBD_ATTR_CLIENT_FLAGS]) { | ||
1641 | u64 flags = nla_get_u64(info->attrs[NBD_ATTR_CLIENT_FLAGS]); | ||
1642 | if (flags & NBD_CFLAG_DESTROY_ON_DISCONNECT) { | ||
1643 | set_bit(NBD_DESTROY_ON_DISCONNECT, | ||
1644 | &config->runtime_flags); | ||
1645 | put_dev = true; | ||
1646 | } | ||
1647 | } | ||
1648 | |||
1636 | if (info->attrs[NBD_ATTR_SOCKETS]) { | 1649 | if (info->attrs[NBD_ATTR_SOCKETS]) { |
1637 | struct nlattr *attr; | 1650 | struct nlattr *attr; |
1638 | int rem, fd; | 1651 | int rem, fd; |
@@ -1670,6 +1683,8 @@ out: | |||
1670 | nbd_connect_reply(info, nbd->index); | 1683 | nbd_connect_reply(info, nbd->index); |
1671 | } | 1684 | } |
1672 | nbd_config_put(nbd); | 1685 | nbd_config_put(nbd); |
1686 | if (put_dev) | ||
1687 | nbd_put(nbd); | ||
1673 | return ret; | 1688 | return ret; |
1674 | } | 1689 | } |
1675 | 1690 | ||
@@ -1722,6 +1737,7 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info) | |||
1722 | struct nbd_config *config; | 1737 | struct nbd_config *config; |
1723 | int index; | 1738 | int index; |
1724 | int ret = -EINVAL; | 1739 | int ret = -EINVAL; |
1740 | bool put_dev = false; | ||
1725 | 1741 | ||
1726 | if (!netlink_capable(skb, CAP_SYS_ADMIN)) | 1742 | if (!netlink_capable(skb, CAP_SYS_ADMIN)) |
1727 | return -EPERM; | 1743 | return -EPERM; |
@@ -1773,6 +1789,18 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info) | |||
1773 | nla_get_u64(info->attrs[NBD_ATTR_DEAD_CONN_TIMEOUT]); | 1789 | nla_get_u64(info->attrs[NBD_ATTR_DEAD_CONN_TIMEOUT]); |
1774 | config->dead_conn_timeout *= HZ; | 1790 | config->dead_conn_timeout *= HZ; |
1775 | } | 1791 | } |
1792 | if (info->attrs[NBD_ATTR_CLIENT_FLAGS]) { | ||
1793 | u64 flags = nla_get_u64(info->attrs[NBD_ATTR_CLIENT_FLAGS]); | ||
1794 | if (flags & NBD_CFLAG_DESTROY_ON_DISCONNECT) { | ||
1795 | if (!test_and_set_bit(NBD_DESTROY_ON_DISCONNECT, | ||
1796 | &config->runtime_flags)) | ||
1797 | put_dev = true; | ||
1798 | } else { | ||
1799 | if (test_and_clear_bit(NBD_DESTROY_ON_DISCONNECT, | ||
1800 | &config->runtime_flags)) | ||
1801 | refcount_inc(&nbd->refs); | ||
1802 | } | ||
1803 | } | ||
1776 | 1804 | ||
1777 | if (info->attrs[NBD_ATTR_SOCKETS]) { | 1805 | if (info->attrs[NBD_ATTR_SOCKETS]) { |
1778 | struct nlattr *attr; | 1806 | struct nlattr *attr; |
@@ -1810,6 +1838,8 @@ out: | |||
1810 | mutex_unlock(&nbd->config_lock); | 1838 | mutex_unlock(&nbd->config_lock); |
1811 | nbd_config_put(nbd); | 1839 | nbd_config_put(nbd); |
1812 | nbd_put(nbd); | 1840 | nbd_put(nbd); |
1841 | if (put_dev) | ||
1842 | nbd_put(nbd); | ||
1813 | return ret; | 1843 | return ret; |
1814 | } | 1844 | } |
1815 | 1845 | ||
diff --git a/include/uapi/linux/nbd.h b/include/uapi/linux/nbd.h index c91c642ea900..155e33f81913 100644 --- a/include/uapi/linux/nbd.h +++ b/include/uapi/linux/nbd.h | |||
@@ -37,7 +37,7 @@ enum { | |||
37 | NBD_CMD_TRIM = 4 | 37 | NBD_CMD_TRIM = 4 |
38 | }; | 38 | }; |
39 | 39 | ||
40 | /* values for flags field */ | 40 | /* values for flags field, these are server interaction specific. */ |
41 | #define NBD_FLAG_HAS_FLAGS (1 << 0) /* nbd-server supports flags */ | 41 | #define NBD_FLAG_HAS_FLAGS (1 << 0) /* nbd-server supports flags */ |
42 | #define NBD_FLAG_READ_ONLY (1 << 1) /* device is read-only */ | 42 | #define NBD_FLAG_READ_ONLY (1 << 1) /* device is read-only */ |
43 | #define NBD_FLAG_SEND_FLUSH (1 << 2) /* can flush writeback cache */ | 43 | #define NBD_FLAG_SEND_FLUSH (1 << 2) /* can flush writeback cache */ |
@@ -45,6 +45,10 @@ enum { | |||
45 | #define NBD_FLAG_SEND_TRIM (1 << 5) /* send trim/discard */ | 45 | #define NBD_FLAG_SEND_TRIM (1 << 5) /* send trim/discard */ |
46 | #define NBD_FLAG_CAN_MULTI_CONN (1 << 8) /* Server supports multiple connections per export. */ | 46 | #define NBD_FLAG_CAN_MULTI_CONN (1 << 8) /* Server supports multiple connections per export. */ |
47 | 47 | ||
48 | /* These are client behavior specific flags. */ | ||
49 | #define NBD_CFLAG_DESTROY_ON_DISCONNECT (1 << 0) /* delete the nbd device on | ||
50 | disconnect. */ | ||
51 | |||
48 | /* userspace doesn't need the nbd_device structure */ | 52 | /* userspace doesn't need the nbd_device structure */ |
49 | 53 | ||
50 | /* These are sent over the network in the request/reply magic fields */ | 54 | /* These are sent over the network in the request/reply magic fields */ |