aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/nbd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block/nbd.c')
-rw-r--r--drivers/block/nbd.c42
1 files changed, 34 insertions, 8 deletions
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 3b7083b8ecbb..74a05561b620 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -76,6 +76,7 @@ struct link_dead_args {
76#define NBD_HAS_CONFIG_REF 4 76#define NBD_HAS_CONFIG_REF 4
77#define NBD_BOUND 5 77#define NBD_BOUND 5
78#define NBD_DESTROY_ON_DISCONNECT 6 78#define NBD_DESTROY_ON_DISCONNECT 6
79#define NBD_DISCONNECT_ON_CLOSE 7
79 80
80struct nbd_config { 81struct nbd_config {
81 u32 flags; 82 u32 flags;
@@ -138,6 +139,7 @@ static void nbd_config_put(struct nbd_device *nbd);
138static void nbd_connect_reply(struct genl_info *info, int index); 139static void nbd_connect_reply(struct genl_info *info, int index);
139static int nbd_genl_status(struct sk_buff *skb, struct genl_info *info); 140static int nbd_genl_status(struct sk_buff *skb, struct genl_info *info);
140static void nbd_dead_link_work(struct work_struct *work); 141static void nbd_dead_link_work(struct work_struct *work);
142static void nbd_disconnect_and_put(struct nbd_device *nbd);
141 143
142static inline struct device *nbd_to_dev(struct nbd_device *nbd) 144static inline struct device *nbd_to_dev(struct nbd_device *nbd)
143{ 145{
@@ -1305,6 +1307,12 @@ out:
1305static void nbd_release(struct gendisk *disk, fmode_t mode) 1307static void nbd_release(struct gendisk *disk, fmode_t mode)
1306{ 1308{
1307 struct nbd_device *nbd = disk->private_data; 1309 struct nbd_device *nbd = disk->private_data;
1310 struct block_device *bdev = bdget_disk(disk, 0);
1311
1312 if (test_bit(NBD_DISCONNECT_ON_CLOSE, &nbd->config->runtime_flags) &&
1313 bdev->bd_openers == 0)
1314 nbd_disconnect_and_put(nbd);
1315
1308 nbd_config_put(nbd); 1316 nbd_config_put(nbd);
1309 nbd_put(nbd); 1317 nbd_put(nbd);
1310} 1318}
@@ -1705,6 +1713,10 @@ again:
1705 &config->runtime_flags); 1713 &config->runtime_flags);
1706 put_dev = true; 1714 put_dev = true;
1707 } 1715 }
1716 if (flags & NBD_CFLAG_DISCONNECT_ON_CLOSE) {
1717 set_bit(NBD_DISCONNECT_ON_CLOSE,
1718 &config->runtime_flags);
1719 }
1708 } 1720 }
1709 1721
1710 if (info->attrs[NBD_ATTR_SOCKETS]) { 1722 if (info->attrs[NBD_ATTR_SOCKETS]) {
@@ -1749,6 +1761,17 @@ out:
1749 return ret; 1761 return ret;
1750} 1762}
1751 1763
1764static void nbd_disconnect_and_put(struct nbd_device *nbd)
1765{
1766 mutex_lock(&nbd->config_lock);
1767 nbd_disconnect(nbd);
1768 nbd_clear_sock(nbd);
1769 mutex_unlock(&nbd->config_lock);
1770 if (test_and_clear_bit(NBD_HAS_CONFIG_REF,
1771 &nbd->config->runtime_flags))
1772 nbd_config_put(nbd);
1773}
1774
1752static int nbd_genl_disconnect(struct sk_buff *skb, struct genl_info *info) 1775static int nbd_genl_disconnect(struct sk_buff *skb, struct genl_info *info)
1753{ 1776{
1754 struct nbd_device *nbd; 1777 struct nbd_device *nbd;
@@ -1781,13 +1804,7 @@ static int nbd_genl_disconnect(struct sk_buff *skb, struct genl_info *info)
1781 nbd_put(nbd); 1804 nbd_put(nbd);
1782 return 0; 1805 return 0;
1783 } 1806 }
1784 mutex_lock(&nbd->config_lock); 1807 nbd_disconnect_and_put(nbd);
1785 nbd_disconnect(nbd);
1786 nbd_clear_sock(nbd);
1787 mutex_unlock(&nbd->config_lock);
1788 if (test_and_clear_bit(NBD_HAS_CONFIG_REF,
1789 &nbd->config->runtime_flags))
1790 nbd_config_put(nbd);
1791 nbd_config_put(nbd); 1808 nbd_config_put(nbd);
1792 nbd_put(nbd); 1809 nbd_put(nbd);
1793 return 0; 1810 return 0;
@@ -1798,7 +1815,7 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)
1798 struct nbd_device *nbd = NULL; 1815 struct nbd_device *nbd = NULL;
1799 struct nbd_config *config; 1816 struct nbd_config *config;
1800 int index; 1817 int index;
1801 int ret = -EINVAL; 1818 int ret = 0;
1802 bool put_dev = false; 1819 bool put_dev = false;
1803 1820
1804 if (!netlink_capable(skb, CAP_SYS_ADMIN)) 1821 if (!netlink_capable(skb, CAP_SYS_ADMIN))
@@ -1838,6 +1855,7 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)
1838 !nbd->task_recv) { 1855 !nbd->task_recv) {
1839 dev_err(nbd_to_dev(nbd), 1856 dev_err(nbd_to_dev(nbd),
1840 "not configured, cannot reconfigure\n"); 1857 "not configured, cannot reconfigure\n");
1858 ret = -EINVAL;
1841 goto out; 1859 goto out;
1842 } 1860 }
1843 1861
@@ -1862,6 +1880,14 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)
1862 &config->runtime_flags)) 1880 &config->runtime_flags))
1863 refcount_inc(&nbd->refs); 1881 refcount_inc(&nbd->refs);
1864 } 1882 }
1883
1884 if (flags & NBD_CFLAG_DISCONNECT_ON_CLOSE) {
1885 set_bit(NBD_DISCONNECT_ON_CLOSE,
1886 &config->runtime_flags);
1887 } else {
1888 clear_bit(NBD_DISCONNECT_ON_CLOSE,
1889 &config->runtime_flags);
1890 }
1865 } 1891 }
1866 1892
1867 if (info->attrs[NBD_ATTR_SOCKETS]) { 1893 if (info->attrs[NBD_ATTR_SOCKETS]) {