qemu-nbd: Allow users to adjust handshake limit

Although defaulting the handshake limit to 10 seconds was a nice QoI
change to weed out intentionally slow clients, it can interfere with
integration testing done with manual NBD_OPT commands over 'nbdsh
--opt-mode'.  Expose a command line option to allow the user to alter
the timeout away from the default.  This option is unlikely to be used
in enough scenarios to warrant a short option letter.

The option --handshake-limit intentionally differs from the name of
the constant added in commit fb1c2aaa98 (limit instead of max_secs)
and the QMP name to be added in the next commit; this is because
typing a longer command-line name is undesirable and there is
sufficient --help text to document the units.

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-ID: <20250203222722.650694-5-eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
This commit is contained in:
Eric Blake 2025-02-03 16:26:06 -06:00
parent ffaf7f0376
commit 617017f8dc
2 changed files with 31 additions and 15 deletions

View file

@ -156,6 +156,11 @@ driver options if :option:`--image-opts` is specified.
Set the NBD volume export description, as a human-readable Set the NBD volume export description, as a human-readable
string. string.
.. option:: --handshake-limit=N
Set the timeout for a client to successfully complete its handshake
to N seconds (default 10), or 0 for no limit.
.. option:: -L, --list .. option:: -L, --list
Connect as a client and list all details about the exports exposed by Connect as a client and list all details about the exports exposed by

View file

@ -57,19 +57,20 @@
#define HAVE_NBD_DEVICE 0 #define HAVE_NBD_DEVICE 0
#endif #endif
#define SOCKET_PATH "/var/lock/qemu-nbd-%s" #define SOCKET_PATH "/var/lock/qemu-nbd-%s"
#define QEMU_NBD_OPT_CACHE 256 #define QEMU_NBD_OPT_CACHE 256
#define QEMU_NBD_OPT_AIO 257 #define QEMU_NBD_OPT_AIO 257
#define QEMU_NBD_OPT_DISCARD 258 #define QEMU_NBD_OPT_DISCARD 258
#define QEMU_NBD_OPT_DETECT_ZEROES 259 #define QEMU_NBD_OPT_DETECT_ZEROES 259
#define QEMU_NBD_OPT_OBJECT 260 #define QEMU_NBD_OPT_OBJECT 260
#define QEMU_NBD_OPT_TLSCREDS 261 #define QEMU_NBD_OPT_TLSCREDS 261
#define QEMU_NBD_OPT_IMAGE_OPTS 262 #define QEMU_NBD_OPT_IMAGE_OPTS 262
#define QEMU_NBD_OPT_FORK 263 #define QEMU_NBD_OPT_FORK 263
#define QEMU_NBD_OPT_TLSAUTHZ 264 #define QEMU_NBD_OPT_TLSAUTHZ 264
#define QEMU_NBD_OPT_PID_FILE 265 #define QEMU_NBD_OPT_PID_FILE 265
#define QEMU_NBD_OPT_SELINUX_LABEL 266 #define QEMU_NBD_OPT_SELINUX_LABEL 266
#define QEMU_NBD_OPT_TLSHOSTNAME 267 #define QEMU_NBD_OPT_TLSHOSTNAME 267
#define QEMU_NBD_OPT_HANDSHAKE_LIMIT 268
#define MBR_SIZE 512 #define MBR_SIZE 512
@ -80,6 +81,7 @@ static int nb_fds;
static QIONetListener *server; static QIONetListener *server;
static QCryptoTLSCreds *tlscreds; static QCryptoTLSCreds *tlscreds;
static const char *tlsauthz; static const char *tlsauthz;
static int handshake_limit = NBD_DEFAULT_HANDSHAKE_MAX_SECS;
static void usage(const char *name) static void usage(const char *name)
{ {
@ -101,6 +103,7 @@ static void usage(const char *name)
" -v, --verbose display extra debugging information\n" " -v, --verbose display extra debugging information\n"
" -x, --export-name=NAME expose export by name (default is empty string)\n" " -x, --export-name=NAME expose export by name (default is empty string)\n"
" -D, --description=TEXT export a human-readable description\n" " -D, --description=TEXT export a human-readable description\n"
" --handshake-limit=N limit client's handshake to N seconds (default 10)\n"
"\n" "\n"
"Exposing part of the image:\n" "Exposing part of the image:\n"
" -o, --offset=OFFSET offset into the image\n" " -o, --offset=OFFSET offset into the image\n"
@ -390,8 +393,7 @@ static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc,
nb_fds++; nb_fds++;
nbd_update_server_watch(); nbd_update_server_watch();
/* TODO - expose handshake timeout as command line option */ nbd_client_new(cioc, handshake_limit,
nbd_client_new(cioc, NBD_DEFAULT_HANDSHAKE_MAX_SECS,
tlscreds, tlsauthz, nbd_client_closed, NULL); tlscreds, tlsauthz, nbd_client_closed, NULL);
} }
@ -569,6 +571,8 @@ int main(int argc, char **argv)
{ "object", required_argument, NULL, QEMU_NBD_OPT_OBJECT }, { "object", required_argument, NULL, QEMU_NBD_OPT_OBJECT },
{ "export-name", required_argument, NULL, 'x' }, { "export-name", required_argument, NULL, 'x' },
{ "description", required_argument, NULL, 'D' }, { "description", required_argument, NULL, 'D' },
{ "handshake-limit", required_argument, NULL,
QEMU_NBD_OPT_HANDSHAKE_LIMIT },
{ "tls-creds", required_argument, NULL, QEMU_NBD_OPT_TLSCREDS }, { "tls-creds", required_argument, NULL, QEMU_NBD_OPT_TLSCREDS },
{ "tls-hostname", required_argument, NULL, QEMU_NBD_OPT_TLSHOSTNAME }, { "tls-hostname", required_argument, NULL, QEMU_NBD_OPT_TLSHOSTNAME },
{ "tls-authz", required_argument, NULL, QEMU_NBD_OPT_TLSAUTHZ }, { "tls-authz", required_argument, NULL, QEMU_NBD_OPT_TLSAUTHZ },
@ -815,6 +819,13 @@ int main(int argc, char **argv)
case QEMU_NBD_OPT_SELINUX_LABEL: case QEMU_NBD_OPT_SELINUX_LABEL:
selinux_label = optarg; selinux_label = optarg;
break; break;
case QEMU_NBD_OPT_HANDSHAKE_LIMIT:
if (qemu_strtoi(optarg, NULL, 0, &handshake_limit) < 0 ||
handshake_limit < 0) {
error_report("Invalid handshake limit '%s'", optarg);
exit(EXIT_FAILURE);
}
break;
} }
} }