Skip to content

Commit

Permalink
nbd: add nbd-get-status
Browse files Browse the repository at this point in the history
Add support for the netlink get status command to get the connection
status of one or all of the nbd devices in a system.

Signed-off-by: Josef Bacik <[email protected]>
[Forward-ported after seven (!) years by Wouter Verhelst]
Signed-off-by: Wouter Verhelst <[email protected]>
  • Loading branch information
Josef Bacik authored and yoe committed Sep 28, 2024
1 parent 6ff6c94 commit 82c500f
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 0 deletions.
6 changes: 6 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,9 @@ nbdtab_parser.tab.h: $(srcdir)/nbdtab_parser.y
bison -d $^ > $@

AM_DISTCHECK_CONFIGURE_FLAGS=--enable-syslog

if NETLINK
bin_PROGRAMS += nbd-get-status
nbd_get_status_SOURCES = nbd-get-status.c cliserv.c
nbd_get_status_CFLAGS = @CFLAGS@
endif
2 changes: 2 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,8 @@ else
AC_DEFINE(HAVE_NETLINK, 0, [Define to 1 if we have netlink support])
fi

AM_CONDITIONAL(NETLINK, [test "$HAVE_NETLINK" = "1"])

AC_MSG_CHECKING([whether man pages are requested])
AC_ARG_ENABLE([manpages],
AS_HELP_STRING([--disable-manpages], [Do not install man pages]),
Expand Down
94 changes: 94 additions & 0 deletions nbd-get-status.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#include "config.h"
#include "lfs.h"

#include <stdio.h>
#include <netlink/netlink.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/ctrl.h>
#include "cliserv.h"
#include "nbd-netlink.h"

static struct nla_policy nbd_device_policy[NBD_DEVICE_ATTR_MAX + 1] = {
[NBD_DEVICE_INDEX] = { .type = NLA_U32 },
[NBD_DEVICE_CONNECTED] = { .type = NLA_U8 },
};

static struct nl_sock *get_nbd_socket(int *driver_id)
{
struct nl_sock *socket;
int id;

socket = nl_socket_alloc();
if (!socket)
err("Couldn't allocate netlink socket\n");

if (genl_connect(socket))
err("Couldn't connect to the generic netlink socket\n");
id = genl_ctrl_resolve(socket, "nbd");
if (id < 0)
err("Couldn't resolve the nbd netlink family, make sure the nbd module is loaded and your nbd driver supports the netlink interface.\n");
if (driver_id)
*driver_id = id;
return socket;
}

static int callback(struct nl_msg *msg, void *arg)
{
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
struct nlattr *msg_attr[NBD_ATTR_MAX + 1];
struct nlattr *attr;
int ret, rem;

ret = nla_parse(msg_attr, NBD_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
genlmsg_attrlen(gnlh, 0), NULL);
if (ret)
err("Invalid response from get status?\n");

nla_for_each_nested(attr, msg_attr[NBD_ATTR_DEVICE_LIST], rem) {
struct nlattr *device[NBD_DEVICE_ATTR_MAX + 1];
u32 index;
uint8_t connected;

if (nla_type(attr) != NBD_DEVICE_ITEM)
err("Invalid attr type in the device list\n");
ret = nla_parse_nested(device, NBD_DEVICE_ATTR_MAX, attr,
nbd_device_policy);
if (ret)
err("Invalid attr device attr\n");
index = nla_get_u32(device[NBD_DEVICE_INDEX]);
connected = nla_get_u8(device[NBD_DEVICE_CONNECTED]);
printf("/dev/nbd%d: %s\n", (int)index,
connected ? "connected" : "disconnected");
}
return NL_OK;
}

int main(int argc, char **argv)
{
struct nl_sock *socket;
struct nlattr *sock_attr;
struct nl_msg *msg;
int driver_id;
int index = -1;

if (argc > 1) {
if (sscanf(argv[1], "/dev/nbd%d", &index) != 1)
err("Invalid nbd device target\n");
}

socket = get_nbd_socket(&driver_id);
nl_socket_modify_cb(socket, NL_CB_VALID, NL_CB_CUSTOM, callback, NULL);

msg = nlmsg_alloc();
if (!msg)
err("Couldn't allocate netlink message\n");
genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, driver_id, 0, 0,
NBD_CMD_STATUS, 0);
if (index >= 0)
NLA_PUT_U32(msg, NBD_ATTR_INDEX, index);
if (nl_send_sync(socket, msg) < 0)
err("Failed to get status\n");
return 0;
nla_put_failure:
err("Failed to create netlink message\n");
}
28 changes: 28 additions & 0 deletions nbd-netlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,35 @@ enum {
NBD_ATTR_SERVER_FLAGS,
NBD_ATTR_CLIENT_FLAGS,
NBD_ATTR_SOCKETS,
NBD_ATTR_DEAD_CONN_TIMEOUT,
NBD_ATTR_DEVICE_LIST,
__NBD_ATTR_MAX,
};
#define NBD_ATTR_MAX (__NBD_ATTR_MAX - 1)

/*
* This is the format for multiple devices with NBD_ATTR_DEVICE_LIST
*
* [NBD_ATTR_DEVICE_LIST]
* [NBD_DEVICE_ITEM]
* [NBD_DEVICE_INDEX]
* [NBD_DEVICE_CONNECTED]
*/
enum {
NBD_DEVICE_ITEM_UNSPEC,
NBD_DEVICE_ITEM,
__NBD_DEVICE_ITEM_MAX,
};
#define NBD_DEVICE_ITEM_MAX (__NBD_DEVICE_ITEM_MAX - 1)

enum {
NBD_DEVICE_UNSPEC,
NBD_DEVICE_INDEX,
NBD_DEVICE_CONNECTED,
__NBD_DEVICE_MAX,
};
#define NBD_DEVICE_ATTR_MAX (__NBD_DEVICE_MAX - 1)

/*
* This is the format for multiple sockets with NBD_ATTR_SOCKETS
*
Expand Down Expand Up @@ -62,6 +87,9 @@ enum {
NBD_CMD_UNSPEC,
NBD_CMD_CONNECT,
NBD_CMD_DISCONNECT,
NBD_CMD_RECONFIGURE,
NBD_CMD_LINK_DEAD,
NBD_CMD_STATUS,
__NBD_CMD_MAX,
};
#define NBD_CMD_MAX (__NBD_CMD_MAX - 1)
Expand Down

0 comments on commit 82c500f

Please sign in to comment.