aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/block/nbd.c108
-rw-r--r--include/uapi/linux/nbd-netlink.h25
2 files changed, 133 insertions, 0 deletions
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index c5f866bcfea6..cb45d799bc5c 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -45,6 +45,7 @@
45 45
46static DEFINE_IDR(nbd_index_idr); 46static DEFINE_IDR(nbd_index_idr);
47static DEFINE_MUTEX(nbd_index_mutex); 47static DEFINE_MUTEX(nbd_index_mutex);
48static int nbd_total_devices = 0;
48 49
49struct nbd_sock { 50struct nbd_sock {
50 struct socket *sock; 51 struct socket *sock;
@@ -130,6 +131,7 @@ static int nbd_dev_dbg_init(struct nbd_device *nbd);
130static void nbd_dev_dbg_close(struct nbd_device *nbd); 131static void nbd_dev_dbg_close(struct nbd_device *nbd);
131static void nbd_config_put(struct nbd_device *nbd); 132static void nbd_config_put(struct nbd_device *nbd);
132static void nbd_connect_reply(struct genl_info *info, int index); 133static void nbd_connect_reply(struct genl_info *info, int index);
134static int nbd_genl_status(struct sk_buff *skb, struct genl_info *info);
133static void nbd_dead_link_work(struct work_struct *work); 135static void nbd_dead_link_work(struct work_struct *work);
134 136
135static inline struct device *nbd_to_dev(struct nbd_device *nbd) 137static inline struct device *nbd_to_dev(struct nbd_device *nbd)
@@ -1457,6 +1459,7 @@ static int nbd_dev_add(int index)
1457 sprintf(disk->disk_name, "nbd%d", index); 1459 sprintf(disk->disk_name, "nbd%d", index);
1458 nbd_reset(nbd); 1460 nbd_reset(nbd);
1459 add_disk(disk); 1461 add_disk(disk);
1462 nbd_total_devices++;
1460 return index; 1463 return index;
1461 1464
1462out_free_tags: 1465out_free_tags:
@@ -1493,12 +1496,22 @@ static struct nla_policy nbd_attr_policy[NBD_ATTR_MAX + 1] = {
1493 [NBD_ATTR_CLIENT_FLAGS] = { .type = NLA_U64 }, 1496 [NBD_ATTR_CLIENT_FLAGS] = { .type = NLA_U64 },
1494 [NBD_ATTR_SOCKETS] = { .type = NLA_NESTED}, 1497 [NBD_ATTR_SOCKETS] = { .type = NLA_NESTED},
1495 [NBD_ATTR_DEAD_CONN_TIMEOUT] = { .type = NLA_U64 }, 1498 [NBD_ATTR_DEAD_CONN_TIMEOUT] = { .type = NLA_U64 },
1499 [NBD_ATTR_DEVICE_LIST] = { .type = NLA_NESTED},
1496}; 1500};
1497 1501
1498static struct nla_policy nbd_sock_policy[NBD_SOCK_MAX + 1] = { 1502static struct nla_policy nbd_sock_policy[NBD_SOCK_MAX + 1] = {
1499 [NBD_SOCK_FD] = { .type = NLA_U32 }, 1503 [NBD_SOCK_FD] = { .type = NLA_U32 },
1500}; 1504};
1501 1505
1506/* We don't use this right now since we don't parse the incoming list, but we
1507 * still want it here so userspace knows what to expect.
1508 */
1509static struct nla_policy __attribute__((unused))
1510nbd_device_policy[NBD_DEVICE_ATTR_MAX + 1] = {
1511 [NBD_DEVICE_INDEX] = { .type = NLA_U32 },
1512 [NBD_DEVICE_CONNECTED] = { .type = NLA_U8 },
1513};
1514
1502static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info) 1515static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info)
1503{ 1516{
1504 struct nbd_device *nbd = NULL; 1517 struct nbd_device *nbd = NULL;
@@ -1764,6 +1777,11 @@ static const struct genl_ops nbd_connect_genl_ops[] = {
1764 .policy = nbd_attr_policy, 1777 .policy = nbd_attr_policy,
1765 .doit = nbd_genl_reconfigure, 1778 .doit = nbd_genl_reconfigure,
1766 }, 1779 },
1780 {
1781 .cmd = NBD_CMD_STATUS,
1782 .policy = nbd_attr_policy,
1783 .doit = nbd_genl_status,
1784 },
1767}; 1785};
1768 1786
1769static const struct genl_multicast_group nbd_mcast_grps[] = { 1787static const struct genl_multicast_group nbd_mcast_grps[] = {
@@ -1782,6 +1800,96 @@ static struct genl_family nbd_genl_family __ro_after_init = {
1782 .n_mcgrps = ARRAY_SIZE(nbd_mcast_grps), 1800 .n_mcgrps = ARRAY_SIZE(nbd_mcast_grps),
1783}; 1801};
1784 1802
1803static int populate_nbd_status(struct nbd_device *nbd, struct sk_buff *reply)
1804{
1805 struct nlattr *dev_opt;
1806 u8 connected = 0;
1807 int ret;
1808
1809 /* This is a little racey, but for status it's ok. The
1810 * reason we don't take a ref here is because we can't
1811 * take a ref in the index == -1 case as we would need
1812 * to put under the nbd_index_mutex, which could
1813 * deadlock if we are configured to remove ourselves
1814 * once we're disconnected.
1815 */
1816 if (refcount_read(&nbd->config_refs))
1817 connected = 1;
1818 dev_opt = nla_nest_start(reply, NBD_DEVICE_ITEM);
1819 if (!dev_opt)
1820 return -EMSGSIZE;
1821 ret = nla_put_u32(reply, NBD_DEVICE_INDEX, nbd->index);
1822 if (ret)
1823 return -EMSGSIZE;
1824 ret = nla_put_u8(reply, NBD_DEVICE_CONNECTED,
1825 connected);
1826 if (ret)
1827 return -EMSGSIZE;
1828 nla_nest_end(reply, dev_opt);
1829 return 0;
1830}
1831
1832static int status_cb(int id, void *ptr, void *data)
1833{
1834 struct nbd_device *nbd = ptr;
1835 return populate_nbd_status(nbd, (struct sk_buff *)data);
1836}
1837
1838static int nbd_genl_status(struct sk_buff *skb, struct genl_info *info)
1839{
1840 struct nlattr *dev_list;
1841 struct sk_buff *reply;
1842 void *reply_head;
1843 size_t msg_size;
1844 int index = -1;
1845 int ret = -ENOMEM;
1846
1847 if (info->attrs[NBD_ATTR_INDEX])
1848 index = nla_get_u32(info->attrs[NBD_ATTR_INDEX]);
1849
1850 mutex_lock(&nbd_index_mutex);
1851
1852 msg_size = nla_total_size(nla_attr_size(sizeof(u32)) +
1853 nla_attr_size(sizeof(u8)));
1854 msg_size *= (index == -1) ? nbd_total_devices : 1;
1855
1856 reply = genlmsg_new(msg_size, GFP_KERNEL);
1857 if (!reply)
1858 goto out;
1859 reply_head = genlmsg_put_reply(reply, info, &nbd_genl_family, 0,
1860 NBD_CMD_STATUS);
1861 if (!reply_head) {
1862 nlmsg_free(reply);
1863 goto out;
1864 }
1865
1866 dev_list = nla_nest_start(reply, NBD_ATTR_DEVICE_LIST);
1867 if (index == -1) {
1868 ret = idr_for_each(&nbd_index_idr, &status_cb, reply);
1869 if (ret) {
1870 nlmsg_free(reply);
1871 goto out;
1872 }
1873 } else {
1874 struct nbd_device *nbd;
1875 nbd = idr_find(&nbd_index_idr, index);
1876 if (nbd) {
1877 ret = populate_nbd_status(nbd, reply);
1878 if (ret) {
1879 nlmsg_free(reply);
1880 goto out;
1881 }
1882 }
1883 }
1884 nla_nest_end(reply, dev_list);
1885 genlmsg_end(reply, reply_head);
1886 genlmsg_reply(reply, info);
1887 ret = 0;
1888out:
1889 mutex_unlock(&nbd_index_mutex);
1890 return ret;
1891}
1892
1785static void nbd_connect_reply(struct genl_info *info, int index) 1893static void nbd_connect_reply(struct genl_info *info, int index)
1786{ 1894{
1787 struct sk_buff *skb; 1895 struct sk_buff *skb;
diff --git a/include/uapi/linux/nbd-netlink.h b/include/uapi/linux/nbd-netlink.h
index c2209c75626c..6f7ca3d63a65 100644
--- a/include/uapi/linux/nbd-netlink.h
+++ b/include/uapi/linux/nbd-netlink.h
@@ -33,11 +33,35 @@ enum {
33 NBD_ATTR_CLIENT_FLAGS, 33 NBD_ATTR_CLIENT_FLAGS,
34 NBD_ATTR_SOCKETS, 34 NBD_ATTR_SOCKETS,
35 NBD_ATTR_DEAD_CONN_TIMEOUT, 35 NBD_ATTR_DEAD_CONN_TIMEOUT,
36 NBD_ATTR_DEVICE_LIST,
36 __NBD_ATTR_MAX, 37 __NBD_ATTR_MAX,
37}; 38};
38#define NBD_ATTR_MAX (__NBD_ATTR_MAX - 1) 39#define NBD_ATTR_MAX (__NBD_ATTR_MAX - 1)
39 40
40/* 41/*
42 * This is the format for multiple devices with NBD_ATTR_DEVICE_LIST
43 *
44 * [NBD_ATTR_DEVICE_LIST]
45 * [NBD_DEVICE_ITEM]
46 * [NBD_DEVICE_INDEX]
47 * [NBD_DEVICE_CONNECTED]
48 */
49enum {
50 NBD_DEVICE_ITEM_UNSPEC,
51 NBD_DEVICE_ITEM,
52 __NBD_DEVICE_ITEM_MAX,
53};
54#define NBD_DEVICE_ITEM_MAX (__NBD_DEVICE_ITEM_MAX - 1)
55
56enum {
57 NBD_DEVICE_UNSPEC,
58 NBD_DEVICE_INDEX,
59 NBD_DEVICE_CONNECTED,
60 __NBD_DEVICE_MAX,
61};
62#define NBD_DEVICE_ATTR_MAX (__NBD_DEVICE_MAX - 1)
63
64/*
41 * This is the format for multiple sockets with NBD_ATTR_SOCKETS 65 * This is the format for multiple sockets with NBD_ATTR_SOCKETS
42 * 66 *
43 * [NBD_ATTR_SOCKETS] 67 * [NBD_ATTR_SOCKETS]
@@ -66,6 +90,7 @@ enum {
66 NBD_CMD_DISCONNECT, 90 NBD_CMD_DISCONNECT,
67 NBD_CMD_RECONFIGURE, 91 NBD_CMD_RECONFIGURE,
68 NBD_CMD_LINK_DEAD, 92 NBD_CMD_LINK_DEAD,
93 NBD_CMD_STATUS,
69 __NBD_CMD_MAX, 94 __NBD_CMD_MAX,
70}; 95};
71#define NBD_CMD_MAX (__NBD_CMD_MAX - 1) 96#define NBD_CMD_MAX (__NBD_CMD_MAX - 1)