Skip to content

Commit 87c5318

Browse files
committed
nbd-client: Add support for setting /sys/block/nbdN/backend
In order for userspace apps to idempotently ensure that a netlink-managed NBD device corresponds to the device that the app is expecting, kernel 5.14 added a netlink backend string identifier. Expose the ability for setting this identifier when binding to a device; the user can then check with /sys/block/nbdN/backend to see if the contents match expectations. Signed-off-by: Eric Blake <[email protected]>
1 parent a78ea37 commit 87c5318

File tree

3 files changed

+49
-8
lines changed

3 files changed

+49
-8
lines changed

man/nbd-client.8.sgml.in

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,29 @@ manpage.1: manpage.sgml
260260
<emphasis>require</emphasis> the use of netlink, but it has
261261
not yet been decided when that will be the case.</para>
262262
</listitem>
263-
</varlistentry
263+
</varlistentry>
264+
<varlistentry>
265+
<term><option>-identifier <replaceable>ident</replaceable></option></term>
266+
<term><option>-i</option></term>
267+
<listitem>
268+
<para>Added in 3.27, this tells &dhpackage; to set the
269+
netlink identifier (requires kernel 5.14 or newer), which
270+
can later be viewed
271+
at <command>/sys/block/nbdN/backend</command>. This prevents
272+
any process from using netlink to silently reconfigure the
273+
device to a different backend, making it easier to write
274+
idempotent code that is safe in the presence of
275+
configuration races.
276+
</para>
277+
<para>This option is only available if &dhpackage; was
278+
compiled against libnl-genl. If that is not the case,
279+
nbd-client will only be able to use the ioctl interface (and
280+
the option will not be available).</para>
281+
<para>Note that a future version of &dhpackage; will
282+
<emphasis>require</emphasis> the use of netlink, but it has
283+
not yet been decided when that will be the case.</para>
284+
</listitem>
285+
</varlistentry>
264286
<varlistentry>
265287
<term><option>-persist</option></term>
266288
<term><option>-p</option></term>

nbd-client.c

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ static struct nl_sock *get_nbd_socket(int *driver_id) {
164164

165165
static void netlink_configure(int index, int *sockfds, int num_connects,
166166
u64 size64, int blocksize, uint16_t flags,
167-
int timeout) {
167+
int timeout, const char *identifier) {
168168
struct nl_sock *socket;
169169
struct nlattr *sock_attr;
170170
struct nl_msg *msg;
@@ -186,6 +186,8 @@ static void netlink_configure(int index, int *sockfds, int num_connects,
186186
NLA_PUT_U64(msg, NBD_ATTR_SERVER_FLAGS, flags);
187187
if (timeout)
188188
NLA_PUT_U64(msg, NBD_ATTR_TIMEOUT, timeout);
189+
if (identifier)
190+
NLA_PUT_STRING(msg, NBD_ATTR_BACKEND_IDENTIFIER, identifier);
189191

190192
sock_attr = nla_nest_start(msg, NBD_ATTR_SOCKETS);
191193
if (!sock_attr)
@@ -246,7 +248,7 @@ static void netlink_disconnect(char *nbddev) {
246248
#else
247249
static void netlink_configure(int index, int *sockfds, int num_connects,
248250
u64 size64, int blocksize, uint16_t flags,
249-
int timeout)
251+
int timeout, const char *identifier)
250252
{
251253
}
252254

@@ -875,7 +877,7 @@ void usage(char* errmsg, ...) {
875877
fprintf(stderr, "%s version %s\n", PROG_NAME, PACKAGE_VERSION);
876878
}
877879
#if HAVE_NETLINK
878-
fprintf(stderr, "Usage: nbd-client -name|-N name host [port] nbd_device\n\t[-block-size|-b block size] [-timeout|-t timeout] [-swap|-s]\n\t[-persist|-p] [-nofork|-n] [-systemd-mark|-m] [-nonetlink|-L]\n\t[-readonly|-R] [-size|-B bytes] [-preinit|-P]\n");
880+
fprintf(stderr, "Usage: nbd-client -name|-N name host [port] nbd_device\n\t[-block-size|-b block size] [-timeout|-t timeout] [-swap|-s]\n\t[-persist|-p] [-nofork|-n] [-systemd-mark|-m] [-i ident|-nonetlink|-L]\n\t[-readonly|-R] [-size|-B bytes] [-preinit|-P]\n");
879881
#else
880882
fprintf(stderr, "Usage: nbd-client -name|-N name host [port] nbd_device\n\t[-block-size|-b block size] [-timeout|-t timeout] [-swap|-s]\n\t[-persist|-p] [-nofork|-n] [-systemd-mark|-m]\n\t[-readonly|-R] [-size|-B bytes] [-preinit|-P]\n");
881883
#endif
@@ -914,7 +916,7 @@ void disconnect(char* device) {
914916

915917
static const char *short_opts = "-B:b:c:d:gH:hlnN:PpRSst:uVxy:"
916918
#if HAVE_NETLINK
917-
"L"
919+
"i:L"
918920
#endif
919921
#if HAVE_GNUTLS
920922
"A:C:F:K:"
@@ -935,6 +937,7 @@ int main(int argc, char *argv[]) {
935937
uint32_t opts=0;
936938
sigset_t block, old;
937939
struct sigaction sa;
940+
char *identifier = NULL;
938941
int netlink = HAVE_NETLINK;
939942
int need_disconnect = 0;
940943
int *sockfds;
@@ -949,6 +952,9 @@ int main(int argc, char *argv[]) {
949952
{ "no-optgo", no_argument, NULL, 'g' },
950953
{ "help", no_argument, NULL, 'h' },
951954
{ "tlshostname", required_argument, NULL, 'H' },
955+
#if HAVE_NETLINK
956+
{ "identifier", required_argument, NULL, 'i' },
957+
#endif
952958
{ "keyfile", required_argument, NULL, 'K' },
953959
{ "list", no_argument, NULL, 'l' },
954960
#if HAVE_NETLINK
@@ -1053,6 +1059,11 @@ int main(int argc, char *argv[]) {
10531059
case 'h':
10541060
usage(NULL);
10551061
exit(EXIT_SUCCESS);
1062+
#if HAVE_NETLINK
1063+
case 'i':
1064+
identifier = optarg;
1065+
break;
1066+
#endif
10561067
case 'l':
10571068
needed_flags |= NBD_FLAG_FIXED_NEWSTYLE;
10581069
opts |= NBDC_DO_LIST;
@@ -1180,6 +1191,10 @@ int main(int argc, char *argv[]) {
11801191

11811192
if (netlink)
11821193
nofork = 1;
1194+
else if (identifier) {
1195+
fprintf(stderr, "E: identifier is only useful with netlink\n");
1196+
exit(EXIT_FAILURE);
1197+
}
11831198

11841199
if((cur_client->force_size64 % cur_client->bs) != 0) {
11851200
fprintf(stderr, "E: size (%" PRIu64 " bytes) is not a multiple of blocksize (%d)!\n", cur_client->force_size64, cur_client->bs);
@@ -1246,7 +1261,8 @@ int main(int argc, char *argv[]) {
12461261
err("Invalid nbd device target\n");
12471262
}
12481263
netlink_configure(index, sockfds, cur_client->nconn,
1249-
cur_client->size64, cur_client->bs, flags, cur_client->timeout);
1264+
cur_client->size64, cur_client->bs, flags, cur_client->timeout,
1265+
identifier);
12501266
return 0;
12511267
}
12521268
/* Go daemon */

nbd-netlink.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
12
/*
23
* Copyright (C) 2017 Facebook. All rights reserved.
34
*
@@ -18,8 +19,9 @@
1819
#ifndef _UAPILINUX_NBD_NETLINK_H
1920
#define _UAPILINUX_NBD_NETLINK_H
2021

21-
#define NBD_GENL_FAMILY_NAME "nbd"
22-
#define NBD_GENL_VERSION 0x1
22+
#define NBD_GENL_FAMILY_NAME "nbd"
23+
#define NBD_GENL_VERSION 0x1
24+
#define NBD_GENL_MCAST_GROUP_NAME "nbd_mc_group"
2325

2426
/* Configuration policy attributes, used for CONNECT */
2527
enum {
@@ -33,6 +35,7 @@ enum {
3335
NBD_ATTR_SOCKETS,
3436
NBD_ATTR_DEAD_CONN_TIMEOUT,
3537
NBD_ATTR_DEVICE_LIST,
38+
NBD_ATTR_BACKEND_IDENTIFIER,
3639
__NBD_ATTR_MAX,
3740
};
3841
#define NBD_ATTR_MAX (__NBD_ATTR_MAX - 1)

0 commit comments

Comments
 (0)