Skip to content

Commit 47d902b

Browse files
josefbacikaxboe
authored andcommitted
nbd: add a status netlink command
Allow users to query the status of existing nbd devices. Right now this only returns whether or not the device is connected, but could be extended in the future to include more information. Signed-off-by: Josef Bacik <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent 560bc4b commit 47d902b

File tree

2 files changed

+133
-0
lines changed

2 files changed

+133
-0
lines changed

drivers/block/nbd.c

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545

4646
static DEFINE_IDR(nbd_index_idr);
4747
static DEFINE_MUTEX(nbd_index_mutex);
48+
static int nbd_total_devices = 0;
4849

4950
struct nbd_sock {
5051
struct socket *sock;
@@ -130,6 +131,7 @@ static int nbd_dev_dbg_init(struct nbd_device *nbd);
130131
static void nbd_dev_dbg_close(struct nbd_device *nbd);
131132
static void nbd_config_put(struct nbd_device *nbd);
132133
static void nbd_connect_reply(struct genl_info *info, int index);
134+
static int nbd_genl_status(struct sk_buff *skb, struct genl_info *info);
133135
static void nbd_dead_link_work(struct work_struct *work);
134136

135137
static inline struct device *nbd_to_dev(struct nbd_device *nbd)
@@ -1457,6 +1459,7 @@ static int nbd_dev_add(int index)
14571459
sprintf(disk->disk_name, "nbd%d", index);
14581460
nbd_reset(nbd);
14591461
add_disk(disk);
1462+
nbd_total_devices++;
14601463
return index;
14611464

14621465
out_free_tags:
@@ -1493,12 +1496,22 @@ static struct nla_policy nbd_attr_policy[NBD_ATTR_MAX + 1] = {
14931496
[NBD_ATTR_CLIENT_FLAGS] = { .type = NLA_U64 },
14941497
[NBD_ATTR_SOCKETS] = { .type = NLA_NESTED},
14951498
[NBD_ATTR_DEAD_CONN_TIMEOUT] = { .type = NLA_U64 },
1499+
[NBD_ATTR_DEVICE_LIST] = { .type = NLA_NESTED},
14961500
};
14971501

14981502
static struct nla_policy nbd_sock_policy[NBD_SOCK_MAX + 1] = {
14991503
[NBD_SOCK_FD] = { .type = NLA_U32 },
15001504
};
15011505

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+
*/
1509+
static struct nla_policy __attribute__((unused))
1510+
nbd_device_policy[NBD_DEVICE_ATTR_MAX + 1] = {
1511+
[NBD_DEVICE_INDEX] = { .type = NLA_U32 },
1512+
[NBD_DEVICE_CONNECTED] = { .type = NLA_U8 },
1513+
};
1514+
15021515
static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info)
15031516
{
15041517
struct nbd_device *nbd = NULL;
@@ -1764,6 +1777,11 @@ static const struct genl_ops nbd_connect_genl_ops[] = {
17641777
.policy = nbd_attr_policy,
17651778
.doit = nbd_genl_reconfigure,
17661779
},
1780+
{
1781+
.cmd = NBD_CMD_STATUS,
1782+
.policy = nbd_attr_policy,
1783+
.doit = nbd_genl_status,
1784+
},
17671785
};
17681786

17691787
static const struct genl_multicast_group nbd_mcast_grps[] = {
@@ -1782,6 +1800,96 @@ static struct genl_family nbd_genl_family __ro_after_init = {
17821800
.n_mcgrps = ARRAY_SIZE(nbd_mcast_grps),
17831801
};
17841802

1803+
static 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+
1832+
static 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+
1838+
static 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;
1888+
out:
1889+
mutex_unlock(&nbd_index_mutex);
1890+
return ret;
1891+
}
1892+
17851893
static void nbd_connect_reply(struct genl_info *info, int index)
17861894
{
17871895
struct sk_buff *skb;

include/uapi/linux/nbd-netlink.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,34 @@ enum {
3333
NBD_ATTR_CLIENT_FLAGS,
3434
NBD_ATTR_SOCKETS,
3535
NBD_ATTR_DEAD_CONN_TIMEOUT,
36+
NBD_ATTR_DEVICE_LIST,
3637
__NBD_ATTR_MAX,
3738
};
3839
#define NBD_ATTR_MAX (__NBD_ATTR_MAX - 1)
3940

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+
*/
49+
enum {
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+
56+
enum {
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+
4064
/*
4165
* This is the format for multiple sockets with NBD_ATTR_SOCKETS
4266
*
@@ -66,6 +90,7 @@ enum {
6690
NBD_CMD_DISCONNECT,
6791
NBD_CMD_RECONFIGURE,
6892
NBD_CMD_LINK_DEAD,
93+
NBD_CMD_STATUS,
6994
__NBD_CMD_MAX,
7095
};
7196
#define NBD_CMD_MAX (__NBD_CMD_MAX - 1)

0 commit comments

Comments
 (0)