Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Josef Bacik and committed by
Jens Axboe
a2c97909 c6a4759e

+35 -1
+30
drivers/block/nbd.c
··· 74 74 #define NBD_HAS_PID_FILE 3 75 75 #define NBD_HAS_CONFIG_REF 4 76 76 #define NBD_BOUND 5 77 + #define NBD_DESTROY_ON_DISCONNECT 6 77 78 78 79 struct nbd_config { 79 80 u32 flags; ··· 175 174 del_gendisk(disk); 176 175 blk_cleanup_queue(disk->queue); 177 176 blk_mq_free_tag_set(&nbd->tag_set); 177 + disk->private_data = NULL; 178 178 put_disk(disk); 179 179 } 180 180 kfree(nbd); ··· 1030 1028 kfree(config->socks); 1031 1029 } 1032 1030 nbd_reset(nbd); 1031 + 1033 1032 mutex_unlock(&nbd->config_lock); 1034 1033 nbd_put(nbd); 1035 1034 module_put(THIS_MODULE); ··· 1542 1539 struct nbd_config *config; 1543 1540 int index = -1; 1544 1541 int ret; 1542 + bool put_dev = false; 1545 1543 1546 1544 if (!netlink_capable(skb, CAP_SYS_ADMIN)) 1547 1545 return -EPERM; ··· 1637 1633 if (info->attrs[NBD_ATTR_SERVER_FLAGS]) 1638 1634 config->flags = 1639 1635 nla_get_u64(info->attrs[NBD_ATTR_SERVER_FLAGS]); 1636 + if (info->attrs[NBD_ATTR_CLIENT_FLAGS]) { 1637 + u64 flags = nla_get_u64(info->attrs[NBD_ATTR_CLIENT_FLAGS]); 1638 + if (flags & NBD_CFLAG_DESTROY_ON_DISCONNECT) { 1639 + set_bit(NBD_DESTROY_ON_DISCONNECT, 1640 + &config->runtime_flags); 1641 + put_dev = true; 1642 + } 1643 + } 1644 + 1640 1645 if (info->attrs[NBD_ATTR_SOCKETS]) { 1641 1646 struct nlattr *attr; 1642 1647 int rem, fd; ··· 1683 1670 nbd_connect_reply(info, nbd->index); 1684 1671 } 1685 1672 nbd_config_put(nbd); 1673 + if (put_dev) 1674 + nbd_put(nbd); 1686 1675 return ret; 1687 1676 } 1688 1677 ··· 1737 1722 struct nbd_config *config; 1738 1723 int index; 1739 1724 int ret = -EINVAL; 1725 + bool put_dev = false; 1740 1726 1741 1727 if (!netlink_capable(skb, CAP_SYS_ADMIN)) 1742 1728 return -EPERM; ··· 1789 1773 nla_get_u64(info->attrs[NBD_ATTR_DEAD_CONN_TIMEOUT]); 1790 1774 config->dead_conn_timeout *= HZ; 1791 1775 } 1776 + if (info->attrs[NBD_ATTR_CLIENT_FLAGS]) { 1777 + u64 flags = nla_get_u64(info->attrs[NBD_ATTR_CLIENT_FLAGS]); 1778 + if (flags & NBD_CFLAG_DESTROY_ON_DISCONNECT) { 1779 + if (!test_and_set_bit(NBD_DESTROY_ON_DISCONNECT, 1780 + &config->runtime_flags)) 1781 + put_dev = true; 1782 + } else { 1783 + if (test_and_clear_bit(NBD_DESTROY_ON_DISCONNECT, 1784 + &config->runtime_flags)) 1785 + refcount_inc(&nbd->refs); 1786 + } 1787 + } 1792 1788 1793 1789 if (info->attrs[NBD_ATTR_SOCKETS]) { 1794 1790 struct nlattr *attr; ··· 1838 1810 mutex_unlock(&nbd->config_lock); 1839 1811 nbd_config_put(nbd); 1840 1812 nbd_put(nbd); 1813 + if (put_dev) 1814 + nbd_put(nbd); 1841 1815 return ret; 1842 1816 } 1843 1817
+5 -1
include/uapi/linux/nbd.h
··· 37 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 41 #define NBD_FLAG_HAS_FLAGS (1 << 0) /* nbd-server supports flags */ 42 42 #define NBD_FLAG_READ_ONLY (1 << 1) /* device is read-only */ 43 43 #define NBD_FLAG_SEND_FLUSH (1 << 2) /* can flush writeback cache */ 44 44 /* there is a gap here to match userspace */ 45 45 #define NBD_FLAG_SEND_TRIM (1 << 5) /* send trim/discard */ 46 46 #define NBD_FLAG_CAN_MULTI_CONN (1 << 8) /* Server supports multiple connections per export. */ 47 + 48 + /* These are client behavior specific flags. */ 49 + #define NBD_CFLAG_DESTROY_ON_DISCONNECT (1 << 0) /* delete the nbd device on 50 + disconnect. */ 47 51 48 52 /* userspace doesn't need the nbd_device structure */ 49 53