From 82c500fac5003c0f7448cebe7805fb083322724e Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Tue, 28 Mar 2017 11:28:18 -0400 Subject: [PATCH] nbd: add nbd-get-status 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 [Forward-ported after seven (!) years by Wouter Verhelst] Signed-off-by: Wouter Verhelst --- Makefile.am | 6 ++++ configure.ac | 2 ++ nbd-get-status.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ nbd-netlink.h | 28 +++++++++++++++++ 4 files changed, 130 insertions(+) create mode 100644 nbd-get-status.c diff --git a/Makefile.am b/Makefile.am index 608931a..b32ec81 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 diff --git a/configure.ac b/configure.ac index c73fef4..5adc670 100644 --- a/configure.ac +++ b/configure.ac @@ -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]), diff --git a/nbd-get-status.c b/nbd-get-status.c new file mode 100644 index 0000000..2b98881 --- /dev/null +++ b/nbd-get-status.c @@ -0,0 +1,94 @@ +#include "config.h" +#include "lfs.h" + +#include +#include +#include +#include +#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"); +} diff --git a/nbd-netlink.h b/nbd-netlink.h index fd0f4e4..a9e6802 100644 --- a/nbd-netlink.h +++ b/nbd-netlink.h @@ -31,11 +31,36 @@ 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 * * [NBD_ATTR_SOCKETS] @@ -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) -- 2.11.4.GIT