45
45
46
46
static DEFINE_IDR (nbd_index_idr );
47
47
static DEFINE_MUTEX (nbd_index_mutex );
48
+ static int nbd_total_devices = 0 ;
48
49
49
50
struct nbd_sock {
50
51
struct socket * sock ;
@@ -130,6 +131,7 @@ static int nbd_dev_dbg_init(struct nbd_device *nbd);
130
131
static void nbd_dev_dbg_close (struct nbd_device * nbd );
131
132
static void nbd_config_put (struct nbd_device * nbd );
132
133
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 );
133
135
static void nbd_dead_link_work (struct work_struct * work );
134
136
135
137
static inline struct device * nbd_to_dev (struct nbd_device * nbd )
@@ -1457,6 +1459,7 @@ static int nbd_dev_add(int index)
1457
1459
sprintf (disk -> disk_name , "nbd%d" , index );
1458
1460
nbd_reset (nbd );
1459
1461
add_disk (disk );
1462
+ nbd_total_devices ++ ;
1460
1463
return index ;
1461
1464
1462
1465
out_free_tags :
@@ -1493,12 +1496,22 @@ static struct nla_policy nbd_attr_policy[NBD_ATTR_MAX + 1] = {
1493
1496
[NBD_ATTR_CLIENT_FLAGS ] = { .type = NLA_U64 },
1494
1497
[NBD_ATTR_SOCKETS ] = { .type = NLA_NESTED },
1495
1498
[NBD_ATTR_DEAD_CONN_TIMEOUT ] = { .type = NLA_U64 },
1499
+ [NBD_ATTR_DEVICE_LIST ] = { .type = NLA_NESTED },
1496
1500
};
1497
1501
1498
1502
static struct nla_policy nbd_sock_policy [NBD_SOCK_MAX + 1 ] = {
1499
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
+ */
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
+
1502
1515
static int nbd_genl_connect (struct sk_buff * skb , struct genl_info * info )
1503
1516
{
1504
1517
struct nbd_device * nbd = NULL ;
@@ -1764,6 +1777,11 @@ static const struct genl_ops nbd_connect_genl_ops[] = {
1764
1777
.policy = nbd_attr_policy ,
1765
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
1769
1787
static const struct genl_multicast_group nbd_mcast_grps [] = {
@@ -1782,6 +1800,96 @@ static struct genl_family nbd_genl_family __ro_after_init = {
1782
1800
.n_mcgrps = ARRAY_SIZE (nbd_mcast_grps ),
1783
1801
};
1784
1802
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
+
1785
1893
static void nbd_connect_reply (struct genl_info * info , int index )
1786
1894
{
1787
1895
struct sk_buff * skb ;
0 commit comments