New upstream version 1.1.12
- Enable Ruby plugin.
This commit is contained in:
parent
a85c67bc96
commit
3aedf9effc
@ -1,39 +0,0 @@
|
||||
From 5294b7d8cc011f8b5e068aad744f612df7414a82 Mon Sep 17 00:00:00 2001
|
||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||
Date: Sat, 31 Oct 2015 13:24:52 +0000
|
||||
Subject: [PATCH 01/11] Add mandir to --dump-config output.
|
||||
|
||||
This is useful for external plugins that want to install
|
||||
a man page.
|
||||
---
|
||||
src/Makefile.am | 1 +
|
||||
src/main.c | 1 +
|
||||
2 files changed, 2 insertions(+)
|
||||
|
||||
diff --git a/src/Makefile.am b/src/Makefile.am
|
||||
index c0fb95a..fb46903 100644
|
||||
--- a/src/Makefile.am
|
||||
+++ b/src/Makefile.am
|
||||
@@ -50,6 +50,7 @@ nbdkit_SOURCES = \
|
||||
nbdkit_CPPFLAGS = \
|
||||
-Dbindir=\"$(bindir)\" \
|
||||
-Dlibdir=\"$(libdir)\" \
|
||||
+ -Dmandir=\"$(mandir)\" \
|
||||
-Dplugindir=\"$(plugindir)\" \
|
||||
-Dsbindir=\"$(sbindir)\" \
|
||||
-Dsysconfdir=\"$(sysconfdir)\" \
|
||||
diff --git a/src/main.c b/src/main.c
|
||||
index cd676c0..1248a8e 100644
|
||||
--- a/src/main.c
|
||||
+++ b/src/main.c
|
||||
@@ -129,6 +129,7 @@ dump_config (void)
|
||||
{
|
||||
printf ("%s=%s\n", "bindir", bindir);
|
||||
printf ("%s=%s\n", "libdir", libdir);
|
||||
+ printf ("%s=%s\n", "mandir", mandir);
|
||||
printf ("%s=%s\n", "name", PACKAGE_NAME);
|
||||
printf ("%s=%s\n", "plugindir", plugindir);
|
||||
printf ("%s=%s\n", "sbindir", sbindir);
|
||||
--
|
||||
2.7.4
|
||||
|
@ -1,35 +0,0 @@
|
||||
From 4b562134c3dad1a84aa92c1658e72046569e1570 Mon Sep 17 00:00:00 2001
|
||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||
Date: Mon, 11 Jan 2016 15:34:57 +0000
|
||||
Subject: [PATCH 02/11] Update TODO.
|
||||
|
||||
---
|
||||
TODO | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/TODO b/TODO
|
||||
index bcf2276..a05aa5b 100644
|
||||
--- a/TODO
|
||||
+++ b/TODO
|
||||
@@ -1,6 +1,8 @@
|
||||
* There is a proposal to narrow the range of possible errnos that the
|
||||
server can return, and also to encode them in an OS-independent way.
|
||||
See: http://article.gmane.org/gmane.linux.drivers.nbd.general/3154
|
||||
+ Implemented in QEMU already:
|
||||
+ http://git.qemu.org/?p=qemu.git;a=commitdiff;h=ca4414804114fd0095b317785bc0b51862e62ebb
|
||||
|
||||
* Can we do language bindings using #!'s?
|
||||
You would enter:
|
||||
@@ -25,6 +27,9 @@
|
||||
default that accepts all exportnames, or to divide the export name
|
||||
"space" up using regexps or wildcards.
|
||||
|
||||
+ Annoyingly nbd-client dropped support for the oldstyle protocol (see
|
||||
+ https://bugzilla.redhat.com/1297100).
|
||||
+
|
||||
* Implement true parallel request handling. Currently
|
||||
NBDKIT_THREAD_MODEL_SERIALIZE_REQUESTS and
|
||||
NBDKIT_THREAD_MODEL_PARALLEL are the same, because we handle
|
||||
--
|
||||
2.7.4
|
||||
|
@ -1,760 +0,0 @@
|
||||
From f93807114634d58ca2ef0d64f7637ebd87e48a50 Mon Sep 17 00:00:00 2001
|
||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||
Date: Mon, 11 Jan 2016 17:08:51 +0000
|
||||
Subject: [PATCH 03/11] Add support for newstyle NBD protocol (RHBZ#1297100).
|
||||
|
||||
---
|
||||
.gitignore | 1 +
|
||||
TODO | 10 +--
|
||||
docs/nbdkit.pod | 67 +++++++++++++-
|
||||
src/connections.c | 235 ++++++++++++++++++++++++++++++++++++++++++++++++--
|
||||
src/internal.h | 1 +
|
||||
src/main.c | 26 ++++--
|
||||
src/protocol.h | 49 ++++++++++-
|
||||
tests/Makefile.am | 8 ++
|
||||
tests/test-newstyle.c | 102 ++++++++++++++++++++++
|
||||
tests/test.c | 6 +-
|
||||
tests/test.h | 2 +-
|
||||
11 files changed, 483 insertions(+), 24 deletions(-)
|
||||
create mode 100644 tests/test-newstyle.c
|
||||
|
||||
diff --git a/.gitignore b/.gitignore
|
||||
index b1a8850..9ea072f 100644
|
||||
--- a/.gitignore
|
||||
+++ b/.gitignore
|
||||
@@ -43,6 +43,7 @@ Makefile.in
|
||||
/tests/test-connect
|
||||
/tests/test-file
|
||||
/tests/test-gzip
|
||||
+/tests/test-newstyle
|
||||
/tests/test-ocaml
|
||||
/tests/test-ocaml-plugin.so
|
||||
/tests/test-perl
|
||||
diff --git a/TODO b/TODO
|
||||
index a05aa5b..d39e64c 100644
|
||||
--- a/TODO
|
||||
+++ b/TODO
|
||||
@@ -17,9 +17,9 @@
|
||||
|
||||
* Performance - measure and improve it.
|
||||
|
||||
-* Implement the new protocol and export names. With export names it
|
||||
- should be possible to have multiple plugins on the command line
|
||||
- (each responding to a different export of course):
|
||||
+* Implement export names. With export names it should be possible to
|
||||
+ have multiple plugins on the command line (each responding to a
|
||||
+ different export of course):
|
||||
|
||||
nbdkit --export /foo plugin.so --export /bar another-plugin.so
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
default that accepts all exportnames, or to divide the export name
|
||||
"space" up using regexps or wildcards.
|
||||
|
||||
- Annoyingly nbd-client dropped support for the oldstyle protocol (see
|
||||
- https://bugzilla.redhat.com/1297100).
|
||||
+ Export names are not actually paths (although that is how they are
|
||||
+ often used), but arbitrary UTF-8 text strings.
|
||||
|
||||
* Implement true parallel request handling. Currently
|
||||
NBDKIT_THREAD_MODEL_SERIALIZE_REQUESTS and
|
||||
diff --git a/docs/nbdkit.pod b/docs/nbdkit.pod
|
||||
index 9ce75d3..7204a38 100644
|
||||
--- a/docs/nbdkit.pod
|
||||
+++ b/docs/nbdkit.pod
|
||||
@@ -7,8 +7,8 @@ nbdkit - A toolkit for creating NBD servers
|
||||
=head1 SYNOPSIS
|
||||
|
||||
nbdkit [--dump-config] [-f] [-g GROUP] [-i IPADDR]
|
||||
- [-P PIDFILE] [-p PORT] [-r] [--run CMD] [-s]
|
||||
- [-U SOCKET] [-u USER] [-v] [-V]
|
||||
+ [--newstyle] [--oldstyle] [-P PIDFILE] [-p PORT] [-r]
|
||||
+ [--run CMD] [-s] [-U SOCKET] [-u USER] [-v] [-V]
|
||||
PLUGIN [key=value [key=value [...]]]
|
||||
|
||||
=head1 DESCRIPTION
|
||||
@@ -103,6 +103,25 @@ See also I<-u>.
|
||||
Listen on the specified interface. The default is to listen on all
|
||||
interfaces. See also I<-p>.
|
||||
|
||||
+=item B<-n>
|
||||
+
|
||||
+=item B<--new-style>
|
||||
+
|
||||
+=item B<--newstyle>
|
||||
+
|
||||
+Use the newstyle NBD protocol instead of the default (oldstyle)
|
||||
+protocol. See L</NEW STYLE VS OLD STYLE PROTOCOL> below.
|
||||
+
|
||||
+=item B<-o>
|
||||
+
|
||||
+=item B<--old-style>
|
||||
+
|
||||
+=item B<--oldstyle>
|
||||
+
|
||||
+Use the oldstyle NBD protocol. This is currently the default, so this
|
||||
+flag does nothing, but it is possible we might change the default
|
||||
+protocol in future. See L</NEW STYLE VS OLD STYLE PROTOCOL> below.
|
||||
+
|
||||
=item B<-P> PIDFILE
|
||||
|
||||
=item B<--pid-file> PIDFILE
|
||||
@@ -280,6 +299,50 @@ Unix socket, like this:
|
||||
|
||||
nbdkit -U - plugin [args] --run '...'
|
||||
|
||||
+=head1 NEW STYLE VS OLD STYLE PROTOCOL
|
||||
+
|
||||
+The NBD protocol comes in two incompatible forms that we call
|
||||
+"oldstyle" and "newstyle". Unfortunately which protocol you should
|
||||
+use depends on the client and cannot be known in advance, nor can it
|
||||
+be negotiated from the server side.
|
||||
+
|
||||
+nbdkit currently defaults to the oldstyle protocol for compatibility
|
||||
+with qemu and libguestfs. This is also the same behaviour as
|
||||
+qemu-nbd. Use the I<-n> or I<--newstyle> flag on the command line to
|
||||
+use the newstyle protocol. Use the I<-o> or I<--oldstyle> flag to
|
||||
+force the oldstyle protocol.
|
||||
+
|
||||
+Some common clients and the protocol they require:
|
||||
+
|
||||
+ Client Protocol
|
||||
+ ------------------------------------------------------------
|
||||
+ qemu without exportname oldstyle
|
||||
+ qemu with exportname newstyle
|
||||
+ nbd-client < 3.10 client can talk either protocol
|
||||
+ nbd-client >= 3.10 newstyle
|
||||
+
|
||||
+If you use qemu without the exportname field against a newstyle
|
||||
+server, it will give the error:
|
||||
+
|
||||
+ Server requires an export name
|
||||
+
|
||||
+If you use qemu with the exportname field against an oldstyle server,
|
||||
+it will give the error:
|
||||
+
|
||||
+ Server does not support export names
|
||||
+
|
||||
+If you use the oldstyle protocol with nbd-client E<ge> 3.10, it will
|
||||
+give the error:
|
||||
+
|
||||
+ Error: It looks like you're trying to connect to an oldstyle server.
|
||||
+
|
||||
+If you want to claim compatibility with what the NBD proto.txt
|
||||
+document says should be the case (which isn't based in reality), then
|
||||
+you should always use newstyle when using port 10809, and use oldstyle
|
||||
+on all other ports.
|
||||
+
|
||||
+nbdkit ignores export names at present (see also the C<TODO> file).
|
||||
+
|
||||
=head1 SIGNALS
|
||||
|
||||
C<nbdkit> responds to the following signals:
|
||||
diff --git a/src/connections.c b/src/connections.c
|
||||
index 15f416b..6bdf4ef 100644
|
||||
--- a/src/connections.c
|
||||
+++ b/src/connections.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/* nbdkit
|
||||
- * Copyright (C) 2013 Red Hat Inc.
|
||||
+ * Copyright (C) 2013-2016 Red Hat Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -52,6 +52,12 @@
|
||||
/* Maximum read or write request that we will handle. */
|
||||
#define MAX_REQUEST_SIZE (64 * 1024 * 1024)
|
||||
|
||||
+/* Maximum number of client options we allow before giving up. */
|
||||
+#define MAX_NR_OPTIONS 32
|
||||
+
|
||||
+/* Maximum length of any option data (bytes). */
|
||||
+#define MAX_OPTION_LENGTH 4096
|
||||
+
|
||||
static struct connection *new_connection (int sockin, int sockout);
|
||||
static void free_connection (struct connection *conn);
|
||||
static int negotiate_handshake (struct connection *conn);
|
||||
@@ -143,11 +149,8 @@ free_connection (struct connection *conn)
|
||||
free (conn);
|
||||
}
|
||||
|
||||
-/* XXX Note because we don't support multiple plugins or export names,
|
||||
- * we are using the old-style handshake. This will be fixed.
|
||||
- */
|
||||
static int
|
||||
-_negotiate_handshake (struct connection *conn)
|
||||
+_negotiate_handshake_oldstyle (struct connection *conn)
|
||||
{
|
||||
struct old_handshake handshake;
|
||||
int64_t r;
|
||||
@@ -201,7 +204,8 @@ _negotiate_handshake (struct connection *conn)
|
||||
conn->can_trim = 1;
|
||||
}
|
||||
|
||||
- debug ("flags: global 0x%x export 0x%x", gflags, eflags);
|
||||
+ debug ("oldstyle negotiation: flags: global 0x%x export 0x%x",
|
||||
+ gflags, eflags);
|
||||
|
||||
memset (&handshake, 0, sizeof handshake);
|
||||
memcpy (handshake.nbdmagic, "NBDMAGIC", 8);
|
||||
@@ -218,13 +222,230 @@ _negotiate_handshake (struct connection *conn)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/* Receive newstyle options.
|
||||
+ *
|
||||
+ * Currently we ignore NBD_OPT_EXPORT_NAME (see TODO), we close the
|
||||
+ * connection if sent NBD_OPT_ABORT, we send a canned list of
|
||||
+ * options for NBD_OPT_LIST, and we send NBD_REP_ERR_UNSUP for
|
||||
+ * everything else.
|
||||
+ */
|
||||
+static int
|
||||
+send_newstyle_option_reply (struct connection *conn,
|
||||
+ uint32_t option, uint32_t reply)
|
||||
+{
|
||||
+ struct fixed_new_option_reply fixed_new_option_reply;
|
||||
+
|
||||
+ fixed_new_option_reply.magic = htobe64 (NEW_OPTION_REPLY);
|
||||
+ fixed_new_option_reply.option = htobe32 (option);
|
||||
+ fixed_new_option_reply.reply = htobe32 (reply);
|
||||
+ fixed_new_option_reply.replylen = htobe32 (0);
|
||||
+
|
||||
+ if (xwrite (conn->sockout,
|
||||
+ &fixed_new_option_reply, sizeof fixed_new_option_reply) == -1) {
|
||||
+ nbdkit_error ("write: %m");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+_negotiate_handshake_newstyle_options (struct connection *conn)
|
||||
+{
|
||||
+ struct new_option new_option;
|
||||
+ size_t nr_options;
|
||||
+ uint64_t version;
|
||||
+ uint32_t option;
|
||||
+ uint32_t optlen;
|
||||
+ char data[MAX_OPTION_LENGTH+1];
|
||||
+
|
||||
+ for (nr_options = 0; nr_options < MAX_NR_OPTIONS; ++nr_options) {
|
||||
+ if (xread (conn->sockin, &new_option, sizeof new_option) == -1) {
|
||||
+ nbdkit_error ("read: %m");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ version = be64toh (new_option.version);
|
||||
+ if (version != NEW_VERSION) {
|
||||
+ nbdkit_error ("unknown option version %" PRIx64
|
||||
+ ", expecting %" PRIx64,
|
||||
+ version, NEW_VERSION);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ /* There is a maximum option length we will accept, regardless
|
||||
+ * of the option type.
|
||||
+ */
|
||||
+ optlen = be32toh (new_option.optlen);
|
||||
+ if (optlen > MAX_OPTION_LENGTH) {
|
||||
+ nbdkit_error ("client option data too long (%" PRIu32 ")", optlen);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ option = be32toh (new_option.option);
|
||||
+ switch (option) {
|
||||
+ case NBD_OPT_EXPORT_NAME:
|
||||
+ if (xread (conn->sockin, data, optlen) == -1) {
|
||||
+ nbdkit_error ("read: %m");
|
||||
+ return -1;
|
||||
+ }
|
||||
+ /* Apart from printing it, ignore the export name. */
|
||||
+ data[optlen] = '\0';
|
||||
+ debug ("newstyle negotiation: client requested export '%s' (ignored)",
|
||||
+ data);
|
||||
+ break;
|
||||
+
|
||||
+ case NBD_OPT_ABORT:
|
||||
+ if (send_newstyle_option_reply (conn, option, NBD_REP_ACK) == -1)
|
||||
+ return -1;
|
||||
+ nbdkit_error ("client sent NBD_OPT_ABORT to abort the connection");
|
||||
+ return -1;
|
||||
+
|
||||
+ case NBD_OPT_LIST:
|
||||
+ if (optlen != 0) {
|
||||
+ if (send_newstyle_option_reply (conn, option, NBD_REP_ERR_INVALID)
|
||||
+ == -1)
|
||||
+ return -1;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* Since we don't support export names, there is nothing to list. */
|
||||
+ if (send_newstyle_option_reply (conn, option, NBD_REP_ACK) == -1)
|
||||
+ return -1;
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ /* Unknown option. */
|
||||
+ if (send_newstyle_option_reply (conn, option, NBD_REP_ERR_UNSUP) == -1)
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ /* Note, since it's not very clear from the protocol doc, that the
|
||||
+ * client must send NBD_OPT_EXPORT_NAME last, and that ends option
|
||||
+ * negotiation.
|
||||
+ */
|
||||
+ if (option == NBD_OPT_EXPORT_NAME)
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (nr_options >= MAX_NR_OPTIONS) {
|
||||
+ nbdkit_error ("client exceeded maximum number of options (%d)",
|
||||
+ MAX_NR_OPTIONS);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+_negotiate_handshake_newstyle (struct connection *conn)
|
||||
+{
|
||||
+ struct new_handshake handshake;
|
||||
+ uint16_t gflags;
|
||||
+ uint32_t cflags;
|
||||
+ struct new_handshake_finish handshake_finish;
|
||||
+ int64_t r;
|
||||
+ uint64_t exportsize;
|
||||
+ uint16_t eflags;
|
||||
+ int fl;
|
||||
+
|
||||
+ gflags = NBD_FLAG_FIXED_NEWSTYLE;
|
||||
+
|
||||
+ debug ("newstyle negotiation: flags: global 0x%x", gflags);
|
||||
+
|
||||
+ memcpy (handshake.nbdmagic, "NBDMAGIC", 8);
|
||||
+ handshake.version = htobe64 (NEW_VERSION);
|
||||
+ handshake.gflags = htobe16 (gflags);
|
||||
+
|
||||
+ if (xwrite (conn->sockout, &handshake, sizeof handshake) == -1) {
|
||||
+ nbdkit_error ("write: %m");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ /* Client now sends us its 32 bit flags word ... */
|
||||
+ if (xread (conn->sockin, &cflags, sizeof cflags) == -1) {
|
||||
+ nbdkit_error ("read: %m");
|
||||
+ return -1;
|
||||
+ }
|
||||
+ cflags = be32toh (cflags);
|
||||
+ /* ... which other than printing out, we ignore. */
|
||||
+ debug ("newstyle negotiation: client flags: 0x%x", cflags);
|
||||
+
|
||||
+ /* Receive newstyle options. */
|
||||
+ if (_negotiate_handshake_newstyle_options (conn) == -1)
|
||||
+ return -1;
|
||||
+
|
||||
+ /* Finish the newstyle handshake. */
|
||||
+ r = plugin_get_size (conn);
|
||||
+ if (r == -1)
|
||||
+ return -1;
|
||||
+ if (r < 0) {
|
||||
+ nbdkit_error (".get_size function returned invalid value "
|
||||
+ "(%" PRIi64 ")", r);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ exportsize = (uint64_t) r;
|
||||
+ conn->exportsize = exportsize;
|
||||
+
|
||||
+ eflags = NBD_FLAG_HAS_FLAGS;
|
||||
+
|
||||
+ fl = plugin_can_write (conn);
|
||||
+ if (fl == -1)
|
||||
+ return -1;
|
||||
+ if (readonly || !fl) {
|
||||
+ eflags |= NBD_FLAG_READ_ONLY;
|
||||
+ conn->readonly = 1;
|
||||
+ }
|
||||
+
|
||||
+ fl = plugin_can_flush (conn);
|
||||
+ if (fl == -1)
|
||||
+ return -1;
|
||||
+ if (fl) {
|
||||
+ eflags |= NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA;
|
||||
+ conn->can_flush = 1;
|
||||
+ }
|
||||
+
|
||||
+ fl = plugin_is_rotational (conn);
|
||||
+ if (fl == -1)
|
||||
+ return -1;
|
||||
+ if (fl) {
|
||||
+ eflags |= NBD_FLAG_ROTATIONAL;
|
||||
+ conn->is_rotational = 1;
|
||||
+ }
|
||||
+
|
||||
+ fl = plugin_can_trim (conn);
|
||||
+ if (fl == -1)
|
||||
+ return -1;
|
||||
+ if (fl) {
|
||||
+ eflags |= NBD_FLAG_SEND_TRIM;
|
||||
+ conn->can_trim = 1;
|
||||
+ }
|
||||
+
|
||||
+ debug ("newstyle negotiation: flags: export 0x%x", eflags);
|
||||
+
|
||||
+ memset (&handshake_finish, 0, sizeof handshake_finish);
|
||||
+ handshake_finish.exportsize = htobe64 (exportsize);
|
||||
+ handshake_finish.eflags = htobe16 (eflags);
|
||||
+
|
||||
+ if (xwrite (conn->sockout,
|
||||
+ &handshake_finish, sizeof handshake_finish) == -1) {
|
||||
+ nbdkit_error ("write: %m");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int
|
||||
negotiate_handshake (struct connection *conn)
|
||||
{
|
||||
int r;
|
||||
|
||||
plugin_lock_request (conn);
|
||||
- r = _negotiate_handshake (conn);
|
||||
+ if (!newstyle)
|
||||
+ r = _negotiate_handshake_oldstyle (conn);
|
||||
+ else
|
||||
+ r = _negotiate_handshake_newstyle (conn);
|
||||
plugin_unlock_request (conn);
|
||||
|
||||
return r;
|
||||
diff --git a/src/internal.h b/src/internal.h
|
||||
index c834b14..0603779 100644
|
||||
--- a/src/internal.h
|
||||
+++ b/src/internal.h
|
||||
@@ -49,6 +49,7 @@
|
||||
|
||||
/* main.c */
|
||||
extern const char *ipaddr;
|
||||
+extern int newstyle;
|
||||
extern const char *port;
|
||||
extern int readonly;
|
||||
extern char *unixsocket;
|
||||
diff --git a/src/main.c b/src/main.c
|
||||
index 1248a8e..db4361e 100644
|
||||
--- a/src/main.c
|
||||
+++ b/src/main.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/* nbdkit
|
||||
- * Copyright (C) 2013-2014 Red Hat Inc.
|
||||
+ * Copyright (C) 2013-2016 Red Hat Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -67,11 +67,12 @@ static gid_t parsegroup (const char *);
|
||||
|
||||
int foreground; /* -f */
|
||||
const char *ipaddr; /* -i */
|
||||
-int listen_stdin; /* -s */
|
||||
+int newstyle; /* -n */
|
||||
char *pidfile; /* -P */
|
||||
const char *port; /* -p */
|
||||
int readonly; /* -r */
|
||||
char *run; /* --run */
|
||||
+int listen_stdin; /* -s */
|
||||
char *unixsocket; /* -U */
|
||||
const char *user, *group; /* -u & -g */
|
||||
int verbose; /* -v */
|
||||
@@ -83,7 +84,7 @@ static char *random_fifo = NULL;
|
||||
|
||||
enum { HELP_OPTION = CHAR_MAX + 1 };
|
||||
|
||||
-static const char *short_options = "fg:i:p:P:rsu:U:vV";
|
||||
+static const char *short_options = "fg:i:nop:P:rsu:U:vV";
|
||||
static const struct option long_options[] = {
|
||||
{ "help", 0, NULL, HELP_OPTION },
|
||||
{ "dump-config",0, NULL, 0 },
|
||||
@@ -92,6 +93,10 @@ static const struct option long_options[] = {
|
||||
{ "group", 1, NULL, 'g' },
|
||||
{ "ip-addr", 1, NULL, 'i' },
|
||||
{ "ipaddr", 1, NULL, 'i' },
|
||||
+ { "new-style", 1, NULL, 'n' },
|
||||
+ { "newstyle", 1, NULL, 'n' },
|
||||
+ { "old-style", 1, NULL, 'o' },
|
||||
+ { "oldstyle", 1, NULL, 'o' },
|
||||
{ "pid-file", 1, NULL, 'P' },
|
||||
{ "pidfile", 1, NULL, 'P' },
|
||||
{ "port", 1, NULL, 'p' },
|
||||
@@ -111,8 +116,8 @@ static void
|
||||
usage (void)
|
||||
{
|
||||
printf ("nbdkit [--dump-config] [-f] [-g GROUP] [-i IPADDR]\n"
|
||||
- " [-P PIDFILE] [-p PORT] [-r] [--run CMD] [-s]\n"
|
||||
- " [-U SOCKET] [-u USER] [-v] [-V]\n"
|
||||
+ " [--newstyle] [--oldstyle] [-P PIDFILE] [-p PORT] [-r]\n"
|
||||
+ " [--run CMD] [-s] [-U SOCKET] [-u USER] [-v] [-V]\n"
|
||||
" PLUGIN [key=value [key=value [...]]]\n"
|
||||
"\n"
|
||||
"Please read the nbdkit(1) manual page for full usage.\n");
|
||||
@@ -180,6 +185,17 @@ main (int argc, char *argv[])
|
||||
ipaddr = optarg;
|
||||
break;
|
||||
|
||||
+ case 'n':
|
||||
+ newstyle = 1;
|
||||
+ break;
|
||||
+
|
||||
+ case 'o':
|
||||
+ /* XXX When we add support for exportnames, we will need to
|
||||
+ * ensure that the user does not use -o + --export.
|
||||
+ */
|
||||
+ newstyle = 0;
|
||||
+ break;
|
||||
+
|
||||
case 'P':
|
||||
pidfile = nbdkit_absolute_path (optarg);
|
||||
if (pidfile == NULL)
|
||||
diff --git a/src/protocol.h b/src/protocol.h
|
||||
index 4449171..2f9a341 100644
|
||||
--- a/src/protocol.h
|
||||
+++ b/src/protocol.h
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
-/* Old-style handshake */
|
||||
+/* Old-style handshake. */
|
||||
struct old_handshake {
|
||||
char nbdmagic[8]; /* "NBDMAGIC" */
|
||||
uint64_t version; /* OLD_VERSION, in network byte order */
|
||||
@@ -48,6 +48,41 @@ struct old_handshake {
|
||||
|
||||
#define OLD_VERSION UINT64_C(0x420281861253)
|
||||
|
||||
+/* New-style handshake. */
|
||||
+struct new_handshake {
|
||||
+ char nbdmagic[8]; /* "NBDMAGIC" */
|
||||
+ uint64_t version; /* NEW_VERSION, in network byte order */
|
||||
+ uint16_t gflags; /* global flags, in network byte order */
|
||||
+} __attribute__((packed));
|
||||
+
|
||||
+#define NEW_VERSION UINT64_C(0x49484156454F5054)
|
||||
+
|
||||
+/* New-style handshake option (sent by the client to us). */
|
||||
+struct new_option {
|
||||
+ uint64_t version; /* NEW_VERSION, in network byte order */
|
||||
+ uint32_t option; /* NBD_OPT_* */
|
||||
+ uint32_t optlen; /* option data length */
|
||||
+ /* option data follows */
|
||||
+} __attribute__((packed));
|
||||
+
|
||||
+/* Fixed newstyle handshake reply message. */
|
||||
+struct fixed_new_option_reply {
|
||||
+ uint64_t magic; /* NEW_OPTION_REPLY, network byte order */
|
||||
+ uint32_t option; /* option we are replying to */
|
||||
+ uint32_t reply; /* NBD_REP_* */
|
||||
+ uint32_t replylen; /* we always send zero at the moment */
|
||||
+ /* reply data follows, but we currently never send any */
|
||||
+};
|
||||
+
|
||||
+#define NEW_OPTION_REPLY UINT64_C(0x3e889045565a9)
|
||||
+
|
||||
+/* New-style handshake server reply. */
|
||||
+struct new_handshake_finish {
|
||||
+ uint64_t exportsize; /* in network byte order */
|
||||
+ uint16_t eflags; /* per-export flags, in network byte order */
|
||||
+ char zeroes[124]; /* must be sent as zero bytes */
|
||||
+} __attribute__((packed));
|
||||
+
|
||||
/* Global flags. */
|
||||
#define NBD_FLAG_FIXED_NEWSTYLE 1
|
||||
|
||||
@@ -59,6 +94,18 @@ struct old_handshake {
|
||||
#define NBD_FLAG_ROTATIONAL 16
|
||||
#define NBD_FLAG_SEND_TRIM 32
|
||||
|
||||
+/* NBD options (new style handshake only). */
|
||||
+#define NBD_OPT_EXPORT_NAME 1
|
||||
+#define NBD_OPT_ABORT 2
|
||||
+#define NBD_OPT_LIST 3
|
||||
+
|
||||
+#define NBD_REP_ACK 1
|
||||
+#define NBD_REP_SERVER 2
|
||||
+#define NBD_REP_ERR_UNSUP 0x80000001
|
||||
+#define NBD_REP_ERR_POLICY 0x80000002
|
||||
+#define NBD_REP_ERR_INVALID 0x80000003
|
||||
+#define NBD_REP_ERR_PLATFORM 0x80000004
|
||||
+
|
||||
/* Request (client -> server). */
|
||||
struct request {
|
||||
uint32_t magic; /* NBD_REQUEST_MAGIC. */
|
||||
diff --git a/tests/Makefile.am b/tests/Makefile.am
|
||||
index 511c39c..8d27032 100644
|
||||
--- a/tests/Makefile.am
|
||||
+++ b/tests/Makefile.am
|
||||
@@ -103,6 +103,14 @@ file-data:
|
||||
for f in `seq 1 512`; do echo -ne '\x01\x02\x03\x04\x05\x06\x07\x08'; done > $@-t
|
||||
mv $@-t $@
|
||||
|
||||
+# newstyle protocol test.
|
||||
+check_PROGRAMS += test-newstyle
|
||||
+TESTS += test-newstyle
|
||||
+
|
||||
+test_newstyle_SOURCES = test-newstyle.c test.h
|
||||
+test_newstyle_CFLAGS = $(WARNINGS_CFLAGS) $(LIBGUESTFS_CFLAGS)
|
||||
+test_newstyle_LDADD = libtest.la $(LIBGUESTFS_LIBS)
|
||||
+
|
||||
# gzip plugin test.
|
||||
if HAVE_ZLIB
|
||||
if HAVE_GUESTFISH
|
||||
diff --git a/tests/test-newstyle.c b/tests/test-newstyle.c
|
||||
new file mode 100644
|
||||
index 0000000..b1d8ce7
|
||||
--- /dev/null
|
||||
+++ b/tests/test-newstyle.c
|
||||
@@ -0,0 +1,102 @@
|
||||
+/* nbdkit
|
||||
+ * Copyright (C) 2013-2016 Red Hat Inc.
|
||||
+ * All rights reserved.
|
||||
+ *
|
||||
+ * Redistribution and use in source and binary forms, with or without
|
||||
+ * modification, are permitted provided that the following conditions are
|
||||
+ * met:
|
||||
+ *
|
||||
+ * * Redistributions of source code must retain the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer.
|
||||
+ *
|
||||
+ * * Redistributions in binary form must reproduce the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer in the
|
||||
+ * documentation and/or other materials provided with the distribution.
|
||||
+ *
|
||||
+ * * Neither the name of Red Hat nor the names of its contributors may be
|
||||
+ * used to endorse or promote products derived from this software without
|
||||
+ * specific prior written permission.
|
||||
+ *
|
||||
+ * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
|
||||
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
|
||||
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
+ * SUCH DAMAGE.
|
||||
+ */
|
||||
+
|
||||
+#include <config.h>
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <stdint.h>
|
||||
+#include <inttypes.h>
|
||||
+#include <string.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+#include <guestfs.h>
|
||||
+
|
||||
+#include "test.h"
|
||||
+
|
||||
+int
|
||||
+main (int argc, char *argv[])
|
||||
+{
|
||||
+ guestfs_h *g;
|
||||
+ int r;
|
||||
+ char *data;
|
||||
+ size_t i, size;
|
||||
+
|
||||
+ if (test_start_nbdkit ("-n", NBDKIT_PLUGIN ("file"), "file=file-data",
|
||||
+ NULL) == -1)
|
||||
+ exit (EXIT_FAILURE);
|
||||
+
|
||||
+ g = guestfs_create ();
|
||||
+ if (g == NULL) {
|
||||
+ perror ("guestfs_create");
|
||||
+ exit (EXIT_FAILURE);
|
||||
+ }
|
||||
+
|
||||
+ /* Using any exportname causes qemu to use the newstyle protocol. */
|
||||
+ r = guestfs_add_drive_opts (g, "/" /* exportname */,
|
||||
+ GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
|
||||
+ GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "nbd",
|
||||
+ GUESTFS_ADD_DRIVE_OPTS_SERVER, server,
|
||||
+ -1);
|
||||
+ if (r == -1)
|
||||
+ exit (EXIT_FAILURE);
|
||||
+
|
||||
+ if (guestfs_launch (g) == -1)
|
||||
+ exit (EXIT_FAILURE);
|
||||
+
|
||||
+ /* Check the data in the file is \x01-\x08 repeated 512 times. */
|
||||
+ data = guestfs_pread_device (g, "/dev/sda", 8 * 512, 0, &size);
|
||||
+ if (!data)
|
||||
+ exit (EXIT_FAILURE);
|
||||
+ if (size != 8 * 512) {
|
||||
+ fprintf (stderr, "%s FAILED: unexpected size (actual: %zu, expected: 512)\n",
|
||||
+ program_name, size);
|
||||
+ exit (EXIT_FAILURE);
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < 512 * 8; i += 8) {
|
||||
+ if (data[i] != 1 || data[i+1] != 2 ||
|
||||
+ data[i+2] != 3 || data[i+3] != 4 ||
|
||||
+ data[i+4] != 5 || data[i+5] != 6 ||
|
||||
+ data[i+6] != 7 || data[i+7] != 8) {
|
||||
+ fprintf (stderr, "%s FAILED: unexpected data returned at offset %zu\n",
|
||||
+ program_name, i);
|
||||
+ exit (EXIT_FAILURE);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ free (data);
|
||||
+
|
||||
+ guestfs_close (g);
|
||||
+ exit (EXIT_SUCCESS);
|
||||
+}
|
||||
diff --git a/tests/test.c b/tests/test.c
|
||||
index 55d13fd..111e6fa 100644
|
||||
--- a/tests/test.c
|
||||
+++ b/tests/test.c
|
||||
@@ -68,7 +68,7 @@ cleanup (void)
|
||||
}
|
||||
|
||||
int
|
||||
-test_start_nbdkit (const char *plugin, ...)
|
||||
+test_start_nbdkit (const char *arg, ...)
|
||||
{
|
||||
size_t i, len;
|
||||
|
||||
@@ -95,10 +95,10 @@ test_start_nbdkit (const char *plugin, ...)
|
||||
argv[4] = pidpath;
|
||||
argv[5] = "-f";
|
||||
argv[6] = "-v";
|
||||
- argv[7] = plugin;
|
||||
+ argv[7] = arg;
|
||||
i = 8;
|
||||
|
||||
- va_start (args, plugin);
|
||||
+ va_start (args, arg);
|
||||
while ((p = va_arg (args, const char *)) != NULL) {
|
||||
if (i >= MAX_ARGS)
|
||||
abort ();
|
||||
diff --git a/tests/test.h b/tests/test.h
|
||||
index 7abf5af..c369150 100644
|
||||
--- a/tests/test.h
|
||||
+++ b/tests/test.h
|
||||
@@ -45,7 +45,7 @@
|
||||
extern pid_t pid; /* PID of nbdkit process. */
|
||||
extern const char *server[2]; /* server parameter for add_drive */
|
||||
|
||||
-extern int test_start_nbdkit (const char *plugin, ...);
|
||||
+extern int test_start_nbdkit (const char *arg, ...);
|
||||
|
||||
/* Declare program_name. */
|
||||
#if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME == 1
|
||||
--
|
||||
2.7.4
|
||||
|
@ -1,49 +0,0 @@
|
||||
From 0759d15aa3649d088eeae91fcd174d0b37e1ccde Mon Sep 17 00:00:00 2001
|
||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||
Date: Mon, 11 Jan 2016 19:02:53 +0000
|
||||
Subject: [PATCH 04/11] xz: Fix various printf warnings on 32 bit.
|
||||
|
||||
xzfile.c: In function 'xzfile_read_block':
|
||||
xzfile.c:456:19: warning: format '%zu' expects argument of type 'size_t', but argument 2 has type 'uint64_t {aka long long unsigned int}' [-Wformat=]
|
||||
nbdkit_error ("malloc (%zu bytes): %m\n"
|
||||
^
|
||||
xz.c: In function 'xz_close':
|
||||
xz.c:191:17: warning: format '%llu' expects argument of type 'long long unsigned int', but argument 2 has type 'size_t {aka unsigned int}' [-Wformat=]
|
||||
nbdkit_debug ("cache: hits = %" PRIu64 ", misses = %" PRIu64,
|
||||
^
|
||||
xz.c:191:17: warning: format '%llu' expects argument of type 'long long unsigned int', but argument 3 has type 'size_t {aka unsigned int}' [-Wformat=]
|
||||
---
|
||||
plugins/xz/xz.c | 3 +--
|
||||
plugins/xz/xzfile.c | 2 +-
|
||||
2 files changed, 2 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/plugins/xz/xz.c b/plugins/xz/xz.c
|
||||
index 9a1f5e5..437f798 100644
|
||||
--- a/plugins/xz/xz.c
|
||||
+++ b/plugins/xz/xz.c
|
||||
@@ -188,8 +188,7 @@ xz_close (void *handle)
|
||||
|
||||
blkcache_get_stats (h->c, &stats);
|
||||
|
||||
- nbdkit_debug ("cache: hits = %" PRIu64 ", misses = %" PRIu64,
|
||||
- stats.hits, stats.misses);
|
||||
+ nbdkit_debug ("cache: hits = %zu, misses = %zu", stats.hits, stats.misses);
|
||||
|
||||
xzfile_close (h->xz);
|
||||
free_blkcache (h->c);
|
||||
diff --git a/plugins/xz/xzfile.c b/plugins/xz/xzfile.c
|
||||
index fcc2937..3633099 100644
|
||||
--- a/plugins/xz/xzfile.c
|
||||
+++ b/plugins/xz/xzfile.c
|
||||
@@ -453,7 +453,7 @@ xzfile_read_block (xzfile *xz, uint64_t offset,
|
||||
|
||||
data = malloc (*size_rtn);
|
||||
if (data == NULL) {
|
||||
- nbdkit_error ("malloc (%zu bytes): %m\n"
|
||||
+ nbdkit_error ("malloc (%" PRIu64 " bytes): %m\n"
|
||||
"NOTE: If this error occurs, you need to recompress your xz files with a smaller block size. Use: 'xz --block-size=16777216 ...'.",
|
||||
*size_rtn);
|
||||
goto err1;
|
||||
--
|
||||
2.7.4
|
||||
|
@ -1,28 +0,0 @@
|
||||
From b6db2f65596470492f0ad76d1ed63ddb98b17167 Mon Sep 17 00:00:00 2001
|
||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||
Date: Mon, 11 Jan 2016 19:46:37 +0000
|
||||
Subject: [PATCH 05/11] ocaml: Avoid race when building NBDKit.cmi.
|
||||
|
||||
If both the NBDKit.cmi and NBDKit.cmx builds run in parallel, both
|
||||
will try to build NBDKit.cmi, resulting in a corrupt NBDKit.cmi file.
|
||||
Avoid this by adding an extra dependency.
|
||||
---
|
||||
plugins/ocaml/Makefile.am | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/plugins/ocaml/Makefile.am b/plugins/ocaml/Makefile.am
|
||||
index d4776b3..f63ba33 100644
|
||||
--- a/plugins/ocaml/Makefile.am
|
||||
+++ b/plugins/ocaml/Makefile.am
|
||||
@@ -43,7 +43,7 @@ ocamllib_DATA = NBDKit.mli NBDKit.cmi NBDKit.cmx NBDKit.o
|
||||
NBDKit.cmi: NBDKit.mli
|
||||
$(OCAMLC) -c $<
|
||||
|
||||
-NBDKit.cmx: NBDKit.ml
|
||||
+NBDKit.cmx: NBDKit.ml NBDKit.cmi
|
||||
$(OCAMLOPT) $(OCAMLOPTFLAGS) -c $<
|
||||
NBDKit.o: NBDKit.cmx
|
||||
|
||||
--
|
||||
2.7.4
|
||||
|
@ -1,154 +0,0 @@
|
||||
From 1c359d1140fee575cf478e2b4bf0c5ca0af9d05e Mon Sep 17 00:00:00 2001
|
||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||
Date: Mon, 11 Jan 2016 20:34:28 +0000
|
||||
Subject: [PATCH 06/11] Test the -o (oldstyle) command line option.
|
||||
|
||||
---
|
||||
.gitignore | 1 +
|
||||
tests/Makefile.am | 8 ++++
|
||||
tests/test-oldstyle.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 111 insertions(+)
|
||||
create mode 100644 tests/test-oldstyle.c
|
||||
|
||||
diff --git a/.gitignore b/.gitignore
|
||||
index 9ea072f..bc151ca 100644
|
||||
--- a/.gitignore
|
||||
+++ b/.gitignore
|
||||
@@ -46,6 +46,7 @@ Makefile.in
|
||||
/tests/test-newstyle
|
||||
/tests/test-ocaml
|
||||
/tests/test-ocaml-plugin.so
|
||||
+/tests/test-oldstyle
|
||||
/tests/test-perl
|
||||
/tests/test-python
|
||||
/tests/test-streaming
|
||||
diff --git a/tests/Makefile.am b/tests/Makefile.am
|
||||
index 8d27032..1e6114c 100644
|
||||
--- a/tests/Makefile.am
|
||||
+++ b/tests/Makefile.am
|
||||
@@ -111,6 +111,14 @@ test_newstyle_SOURCES = test-newstyle.c test.h
|
||||
test_newstyle_CFLAGS = $(WARNINGS_CFLAGS) $(LIBGUESTFS_CFLAGS)
|
||||
test_newstyle_LDADD = libtest.la $(LIBGUESTFS_LIBS)
|
||||
|
||||
+# oldstyle protocol test.
|
||||
+check_PROGRAMS += test-oldstyle
|
||||
+TESTS += test-oldstyle
|
||||
+
|
||||
+test_oldstyle_SOURCES = test-oldstyle.c test.h
|
||||
+test_oldstyle_CFLAGS = $(WARNINGS_CFLAGS) $(LIBGUESTFS_CFLAGS)
|
||||
+test_oldstyle_LDADD = libtest.la $(LIBGUESTFS_LIBS)
|
||||
+
|
||||
# gzip plugin test.
|
||||
if HAVE_ZLIB
|
||||
if HAVE_GUESTFISH
|
||||
diff --git a/tests/test-oldstyle.c b/tests/test-oldstyle.c
|
||||
new file mode 100644
|
||||
index 0000000..d809a0c
|
||||
--- /dev/null
|
||||
+++ b/tests/test-oldstyle.c
|
||||
@@ -0,0 +1,102 @@
|
||||
+/* nbdkit
|
||||
+ * Copyright (C) 2013-2016 Red Hat Inc.
|
||||
+ * All rights reserved.
|
||||
+ *
|
||||
+ * Redistribution and use in source and binary forms, with or without
|
||||
+ * modification, are permitted provided that the following conditions are
|
||||
+ * met:
|
||||
+ *
|
||||
+ * * Redistributions of source code must retain the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer.
|
||||
+ *
|
||||
+ * * Redistributions in binary form must reproduce the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer in the
|
||||
+ * documentation and/or other materials provided with the distribution.
|
||||
+ *
|
||||
+ * * Neither the name of Red Hat nor the names of its contributors may be
|
||||
+ * used to endorse or promote products derived from this software without
|
||||
+ * specific prior written permission.
|
||||
+ *
|
||||
+ * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
|
||||
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
|
||||
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
+ * SUCH DAMAGE.
|
||||
+ */
|
||||
+
|
||||
+#include <config.h>
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <stdint.h>
|
||||
+#include <inttypes.h>
|
||||
+#include <string.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+#include <guestfs.h>
|
||||
+
|
||||
+#include "test.h"
|
||||
+
|
||||
+int
|
||||
+main (int argc, char *argv[])
|
||||
+{
|
||||
+ guestfs_h *g;
|
||||
+ int r;
|
||||
+ char *data;
|
||||
+ size_t i, size;
|
||||
+
|
||||
+ if (test_start_nbdkit ("-o", NBDKIT_PLUGIN ("file"), "file=file-data",
|
||||
+ NULL) == -1)
|
||||
+ exit (EXIT_FAILURE);
|
||||
+
|
||||
+ g = guestfs_create ();
|
||||
+ if (g == NULL) {
|
||||
+ perror ("guestfs_create");
|
||||
+ exit (EXIT_FAILURE);
|
||||
+ }
|
||||
+
|
||||
+ /* Using exportname = "" causes qemu to use the oldstyle protocol. */
|
||||
+ r = guestfs_add_drive_opts (g, "",
|
||||
+ GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
|
||||
+ GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "nbd",
|
||||
+ GUESTFS_ADD_DRIVE_OPTS_SERVER, server,
|
||||
+ -1);
|
||||
+ if (r == -1)
|
||||
+ exit (EXIT_FAILURE);
|
||||
+
|
||||
+ if (guestfs_launch (g) == -1)
|
||||
+ exit (EXIT_FAILURE);
|
||||
+
|
||||
+ /* Check the data in the file is \x01-\x08 repeated 512 times. */
|
||||
+ data = guestfs_pread_device (g, "/dev/sda", 8 * 512, 0, &size);
|
||||
+ if (!data)
|
||||
+ exit (EXIT_FAILURE);
|
||||
+ if (size != 8 * 512) {
|
||||
+ fprintf (stderr, "%s FAILED: unexpected size (actual: %zu, expected: 512)\n",
|
||||
+ program_name, size);
|
||||
+ exit (EXIT_FAILURE);
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < 512 * 8; i += 8) {
|
||||
+ if (data[i] != 1 || data[i+1] != 2 ||
|
||||
+ data[i+2] != 3 || data[i+3] != 4 ||
|
||||
+ data[i+4] != 5 || data[i+5] != 6 ||
|
||||
+ data[i+6] != 7 || data[i+7] != 8) {
|
||||
+ fprintf (stderr, "%s FAILED: unexpected data returned at offset %zu\n",
|
||||
+ program_name, i);
|
||||
+ exit (EXIT_FAILURE);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ free (data);
|
||||
+
|
||||
+ guestfs_close (g);
|
||||
+ exit (EXIT_SUCCESS);
|
||||
+}
|
||||
--
|
||||
2.7.4
|
||||
|
@ -1,116 +0,0 @@
|
||||
From f141228d1b6baddadcd516137d76b3d852af8cde Mon Sep 17 00:00:00 2001
|
||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||
Date: Tue, 12 Jan 2016 12:16:48 +0000
|
||||
Subject: [PATCH 07/11] protocol: Send limited range of errno values to the
|
||||
client.
|
||||
|
||||
See the proposal here:
|
||||
http://article.gmane.org/gmane.linux.drivers.nbd.general/3154
|
||||
|
||||
This implementation is based on Paolo Bonzini's for qemu-nbd:
|
||||
http://git.qemu.org/?p=qemu.git;a=commitdiff;h=ca4414804114fd0095b317785bc0b51862e62ebb
|
||||
---
|
||||
TODO | 6 ------
|
||||
src/connections.c | 36 +++++++++++++++++++++++++++++++++++-
|
||||
src/protocol.h | 12 +++++++++++-
|
||||
3 files changed, 46 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/TODO b/TODO
|
||||
index d39e64c..177a07c 100644
|
||||
--- a/TODO
|
||||
+++ b/TODO
|
||||
@@ -1,9 +1,3 @@
|
||||
-* There is a proposal to narrow the range of possible errnos that the
|
||||
- server can return, and also to encode them in an OS-independent way.
|
||||
- See: http://article.gmane.org/gmane.linux.drivers.nbd.general/3154
|
||||
- Implemented in QEMU already:
|
||||
- http://git.qemu.org/?p=qemu.git;a=commitdiff;h=ca4414804114fd0095b317785bc0b51862e62ebb
|
||||
-
|
||||
* Can we do language bindings using #!'s?
|
||||
You would enter:
|
||||
nbdkit foo [args]
|
||||
diff --git a/src/connections.c b/src/connections.c
|
||||
index 6bdf4ef..f0a7662 100644
|
||||
--- a/src/connections.c
|
||||
+++ b/src/connections.c
|
||||
@@ -639,6 +639,31 @@ skip_over_write_buffer (int sock, size_t count)
|
||||
}
|
||||
}
|
||||
|
||||
+/* Convert a system errno to an NBD_E* error code. */
|
||||
+static int
|
||||
+nbd_errno (int error)
|
||||
+{
|
||||
+ switch (error) {
|
||||
+ case 0:
|
||||
+ return NBD_SUCCESS;
|
||||
+ case EPERM:
|
||||
+ return NBD_EPERM;
|
||||
+ case EIO:
|
||||
+ return NBD_EIO;
|
||||
+ case ENOMEM:
|
||||
+ return NBD_ENOMEM;
|
||||
+#ifdef EDQUOT
|
||||
+ case EDQUOT:
|
||||
+#endif
|
||||
+ case EFBIG:
|
||||
+ case ENOSPC:
|
||||
+ return NBD_ENOSPC;
|
||||
+ case EINVAL:
|
||||
+ default:
|
||||
+ return NBD_EINVAL;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static int
|
||||
recv_request_send_reply (struct connection *conn)
|
||||
{
|
||||
@@ -722,7 +747,16 @@ recv_request_send_reply (struct connection *conn)
|
||||
send_reply:
|
||||
reply.magic = htobe32 (NBD_REPLY_MAGIC);
|
||||
reply.handle = request.handle;
|
||||
- reply.error = htobe32 (error);
|
||||
+ reply.error = htobe32 (nbd_errno (error));
|
||||
+
|
||||
+ if (error != 0) {
|
||||
+ /* Since we're about to send only the limited NBD_E* errno to the
|
||||
+ * client, don't lose the information about what really happened
|
||||
+ * on the server side. Make sure there is a way for the operator
|
||||
+ * to retrieve the real error.
|
||||
+ */
|
||||
+ debug ("sending error reply: %s", strerror (error));
|
||||
+ }
|
||||
|
||||
r = xwrite (conn->sockout, &reply, sizeof reply);
|
||||
if (r == -1) {
|
||||
diff --git a/src/protocol.h b/src/protocol.h
|
||||
index 2f9a341..fcbc145 100644
|
||||
--- a/src/protocol.h
|
||||
+++ b/src/protocol.h
|
||||
@@ -118,7 +118,7 @@ struct request {
|
||||
/* Reply (server -> client). */
|
||||
struct reply {
|
||||
uint32_t magic; /* NBD_REPLY_MAGIC. */
|
||||
- uint32_t error; /* 0 = ok, error code */
|
||||
+ uint32_t error; /* NBD_SUCCESS or one of NBD_E*. */
|
||||
uint64_t handle; /* Opaque handle. */
|
||||
} __attribute__((packed));
|
||||
|
||||
@@ -133,4 +133,14 @@ struct reply {
|
||||
#define NBD_CMD_MASK_COMMAND 0xffff
|
||||
#define NBD_CMD_FLAG_FUA (1<<16)
|
||||
|
||||
+/* Error codes (previously errno).
|
||||
+ * See http://git.qemu.org/?p=qemu.git;a=commitdiff;h=ca4414804114fd0095b317785bc0b51862e62ebb
|
||||
+ */
|
||||
+#define NBD_SUCCESS 0
|
||||
+#define NBD_EPERM 1
|
||||
+#define NBD_EIO 5
|
||||
+#define NBD_ENOMEM 12
|
||||
+#define NBD_EINVAL 22
|
||||
+#define NBD_ENOSPC 28
|
||||
+
|
||||
#endif /* NBDKIT_PROTOCOL_H */
|
||||
--
|
||||
2.7.4
|
||||
|
@ -1,27 +0,0 @@
|
||||
From e5a945ea1e759e6441773c1e7663a1ac2492c8e4 Mon Sep 17 00:00:00 2001
|
||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||
Date: Tue, 17 May 2016 19:40:29 +0100
|
||||
Subject: [PATCH 08/11] protocol: Pack fixed_new_option_reply struct.
|
||||
|
||||
This struct was not packed, but we were sending a reply by sending the
|
||||
struct directly onto the wire. I think we got away with it, but not good.
|
||||
---
|
||||
src/protocol.h | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/protocol.h b/src/protocol.h
|
||||
index fcbc145..de511a6 100644
|
||||
--- a/src/protocol.h
|
||||
+++ b/src/protocol.h
|
||||
@@ -72,7 +72,7 @@ struct fixed_new_option_reply {
|
||||
uint32_t reply; /* NBD_REP_* */
|
||||
uint32_t replylen; /* we always send zero at the moment */
|
||||
/* reply data follows, but we currently never send any */
|
||||
-};
|
||||
+} __attribute__((packed));
|
||||
|
||||
#define NEW_OPTION_REPLY UINT64_C(0x3e889045565a9)
|
||||
|
||||
--
|
||||
2.7.4
|
||||
|
@ -1,48 +0,0 @@
|
||||
From f989fbad9b0527925c38f4350190cb1536a4d8c2 Mon Sep 17 00:00:00 2001
|
||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||
Date: Tue, 17 May 2016 19:42:35 +0100
|
||||
Subject: [PATCH 09/11] protocol: Rename NEW_OPTION_REPLY as NBD_REP_MAGIC.
|
||||
|
||||
To be consistent with qemu's implementation.
|
||||
---
|
||||
src/connections.c | 2 +-
|
||||
src/protocol.h | 4 ++--
|
||||
2 files changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/connections.c b/src/connections.c
|
||||
index f0a7662..34566b3 100644
|
||||
--- a/src/connections.c
|
||||
+++ b/src/connections.c
|
||||
@@ -235,7 +235,7 @@ send_newstyle_option_reply (struct connection *conn,
|
||||
{
|
||||
struct fixed_new_option_reply fixed_new_option_reply;
|
||||
|
||||
- fixed_new_option_reply.magic = htobe64 (NEW_OPTION_REPLY);
|
||||
+ fixed_new_option_reply.magic = htobe64 (NBD_REP_MAGIC);
|
||||
fixed_new_option_reply.option = htobe32 (option);
|
||||
fixed_new_option_reply.reply = htobe32 (reply);
|
||||
fixed_new_option_reply.replylen = htobe32 (0);
|
||||
diff --git a/src/protocol.h b/src/protocol.h
|
||||
index de511a6..71a8098 100644
|
||||
--- a/src/protocol.h
|
||||
+++ b/src/protocol.h
|
||||
@@ -67,14 +67,14 @@ struct new_option {
|
||||
|
||||
/* Fixed newstyle handshake reply message. */
|
||||
struct fixed_new_option_reply {
|
||||
- uint64_t magic; /* NEW_OPTION_REPLY, network byte order */
|
||||
+ uint64_t magic; /* NBD_REP_MAGIC, network byte order */
|
||||
uint32_t option; /* option we are replying to */
|
||||
uint32_t reply; /* NBD_REP_* */
|
||||
uint32_t replylen; /* we always send zero at the moment */
|
||||
/* reply data follows, but we currently never send any */
|
||||
} __attribute__((packed));
|
||||
|
||||
-#define NEW_OPTION_REPLY UINT64_C(0x3e889045565a9)
|
||||
+#define NBD_REP_MAGIC UINT64_C(0x3e889045565a9)
|
||||
|
||||
/* New-style handshake server reply. */
|
||||
struct new_handshake_finish {
|
||||
--
|
||||
2.7.4
|
||||
|
@ -1,360 +0,0 @@
|
||||
From 0095b003b56894baad8e6789d523cf3c51905c05 Mon Sep 17 00:00:00 2001
|
||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||
Date: Tue, 17 May 2016 19:43:16 +0100
|
||||
Subject: [PATCH 10/11] Implement newstyle export names.
|
||||
|
||||
This is now required by qemu >= 2.6. See this lengthy qemu-devel
|
||||
thread for details:
|
||||
https://lists.nongnu.org/archive/html/qemu-devel/2016-05/threads.html#02752
|
||||
---
|
||||
TODO | 13 -------------
|
||||
docs/nbdkit.pod | 52 ++++++++++++++++++++++++++++++++-------------------
|
||||
src/connections.c | 49 ++++++++++++++++++++++++++++++++++++++++--------
|
||||
src/internal.h | 1 +
|
||||
src/main.c | 32 +++++++++++++++++++++++--------
|
||||
src/protocol.h | 3 +--
|
||||
tests/test-newstyle.c | 7 +++++--
|
||||
7 files changed, 105 insertions(+), 52 deletions(-)
|
||||
|
||||
diff --git a/TODO b/TODO
|
||||
index 177a07c..30bf72e 100644
|
||||
--- a/TODO
|
||||
+++ b/TODO
|
||||
@@ -11,19 +11,6 @@
|
||||
|
||||
* Performance - measure and improve it.
|
||||
|
||||
-* Implement export names. With export names it should be possible to
|
||||
- have multiple plugins on the command line (each responding to a
|
||||
- different export of course):
|
||||
-
|
||||
- nbdkit --export /foo plugin.so --export /bar another-plugin.so
|
||||
-
|
||||
- Note it should also be possible to either elect one plugin as the
|
||||
- default that accepts all exportnames, or to divide the export name
|
||||
- "space" up using regexps or wildcards.
|
||||
-
|
||||
- Export names are not actually paths (although that is how they are
|
||||
- often used), but arbitrary UTF-8 text strings.
|
||||
-
|
||||
* Implement true parallel request handling. Currently
|
||||
NBDKIT_THREAD_MODEL_SERIALIZE_REQUESTS and
|
||||
NBDKIT_THREAD_MODEL_PARALLEL are the same, because we handle
|
||||
diff --git a/docs/nbdkit.pod b/docs/nbdkit.pod
|
||||
index 7204a38..728aad3 100644
|
||||
--- a/docs/nbdkit.pod
|
||||
+++ b/docs/nbdkit.pod
|
||||
@@ -6,7 +6,7 @@ nbdkit - A toolkit for creating NBD servers
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
- nbdkit [--dump-config] [-f] [-g GROUP] [-i IPADDR]
|
||||
+ nbdkit [--dump-config] [-e EXPORTNAME] [-f] [-g GROUP] [-i IPADDR]
|
||||
[--newstyle] [--oldstyle] [-P PIDFILE] [-p PORT] [-r]
|
||||
[--run CMD] [-s] [-U SOCKET] [-u USER] [-v] [-V]
|
||||
PLUGIN [key=value [key=value [...]]]
|
||||
@@ -74,6 +74,19 @@ Display brief command line usage information and exit.
|
||||
|
||||
Dump out the compile-time configuration values and exit.
|
||||
|
||||
+=item B<-e> EXPORTNAME
|
||||
+
|
||||
+=item B<--export> EXPORTNAME
|
||||
+
|
||||
+=item B<--export-name> EXPORTNAME
|
||||
+
|
||||
+=item B<--exportname> EXPORTNAME
|
||||
+
|
||||
+Set the exportname and use the newstyle protocol (implies I<-n>).
|
||||
+
|
||||
+If not set, exportname C<""> (empty string) is used. Exportnames are
|
||||
+not allowed with the oldstyle protocol.
|
||||
+
|
||||
=item B<-f>
|
||||
|
||||
=item B<--foreground>
|
||||
@@ -118,9 +131,10 @@ protocol. See L</NEW STYLE VS OLD STYLE PROTOCOL> below.
|
||||
|
||||
=item B<--oldstyle>
|
||||
|
||||
-Use the oldstyle NBD protocol. This is currently the default, so this
|
||||
-flag does nothing, but it is possible we might change the default
|
||||
-protocol in future. See L</NEW STYLE VS OLD STYLE PROTOCOL> below.
|
||||
+Use the oldstyle NBD protocol. This is currently the default (unless
|
||||
+you use I<-n> or I<-e>), so this flag does nothing, but it is possible
|
||||
+we might change the default protocol in future. See L</NEW STYLE VS
|
||||
+OLD STYLE PROTOCOL> below.
|
||||
|
||||
=item B<-P> PIDFILE
|
||||
|
||||
@@ -307,27 +321,29 @@ use depends on the client and cannot be known in advance, nor can it
|
||||
be negotiated from the server side.
|
||||
|
||||
nbdkit currently defaults to the oldstyle protocol for compatibility
|
||||
-with qemu and libguestfs. This is also the same behaviour as
|
||||
-qemu-nbd. Use the I<-n> or I<--newstyle> flag on the command line to
|
||||
-use the newstyle protocol. Use the I<-o> or I<--oldstyle> flag to
|
||||
-force the oldstyle protocol.
|
||||
+with qemu and libguestfs. This is also the same behaviour as qemu-nbd
|
||||
+E<le> 2.5. Use the I<-n> or I<--newstyle> flag on the command line to
|
||||
+use the newstyle protocol. Use the I<-e> or I<--exportname> flag to
|
||||
+set the exportname for the newstyle protocol. Use the I<-o> or
|
||||
+I<--oldstyle> flag to force the oldstyle protocol.
|
||||
|
||||
Some common clients and the protocol they require:
|
||||
|
||||
- Client Protocol
|
||||
+ Client Protocol
|
||||
------------------------------------------------------------
|
||||
- qemu without exportname oldstyle
|
||||
- qemu with exportname newstyle
|
||||
- nbd-client < 3.10 client can talk either protocol
|
||||
- nbd-client >= 3.10 newstyle
|
||||
+ qemu <= 2.5 without exportname oldstyle
|
||||
+ qemu <= 2.5 with exportname newstyle
|
||||
+ qemu >= 2.6 client can talk either protocol
|
||||
+ nbd-client < 3.10 client can talk either protocol
|
||||
+ nbd-client >= 3.10 newstyle
|
||||
|
||||
-If you use qemu without the exportname field against a newstyle
|
||||
-server, it will give the error:
|
||||
+If you use qemu E<le> 2.5 without the exportname field against a
|
||||
+newstyle server, it will give the error:
|
||||
|
||||
Server requires an export name
|
||||
|
||||
-If you use qemu with the exportname field against an oldstyle server,
|
||||
-it will give the error:
|
||||
+If you use qemu E<le> 2.5 with the exportname field against an
|
||||
+oldstyle server, it will give the error:
|
||||
|
||||
Server does not support export names
|
||||
|
||||
@@ -341,8 +357,6 @@ document says should be the case (which isn't based in reality), then
|
||||
you should always use newstyle when using port 10809, and use oldstyle
|
||||
on all other ports.
|
||||
|
||||
-nbdkit ignores export names at present (see also the C<TODO> file).
|
||||
-
|
||||
=head1 SIGNALS
|
||||
|
||||
C<nbdkit> responds to the following signals:
|
||||
diff --git a/src/connections.c b/src/connections.c
|
||||
index 34566b3..0c93f35 100644
|
||||
--- a/src/connections.c
|
||||
+++ b/src/connections.c
|
||||
@@ -222,13 +222,8 @@ _negotiate_handshake_oldstyle (struct connection *conn)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-/* Receive newstyle options.
|
||||
- *
|
||||
- * Currently we ignore NBD_OPT_EXPORT_NAME (see TODO), we close the
|
||||
- * connection if sent NBD_OPT_ABORT, we send a canned list of
|
||||
- * options for NBD_OPT_LIST, and we send NBD_REP_ERR_UNSUP for
|
||||
- * everything else.
|
||||
- */
|
||||
+/* Receive newstyle options. */
|
||||
+
|
||||
static int
|
||||
send_newstyle_option_reply (struct connection *conn,
|
||||
uint32_t option, uint32_t reply)
|
||||
@@ -250,6 +245,39 @@ send_newstyle_option_reply (struct connection *conn,
|
||||
}
|
||||
|
||||
static int
|
||||
+send_newstyle_option_reply_exportname (struct connection *conn,
|
||||
+ uint32_t option, uint32_t reply,
|
||||
+ const char *exportname)
|
||||
+{
|
||||
+ struct fixed_new_option_reply fixed_new_option_reply;
|
||||
+ size_t name_len = strlen (exportname);
|
||||
+ uint32_t len;
|
||||
+
|
||||
+ fixed_new_option_reply.magic = htobe64 (NBD_REP_MAGIC);
|
||||
+ fixed_new_option_reply.option = htobe32 (option);
|
||||
+ fixed_new_option_reply.reply = htobe32 (reply);
|
||||
+ fixed_new_option_reply.replylen = htobe32 (name_len + sizeof (len));
|
||||
+
|
||||
+ if (xwrite (conn->sockout,
|
||||
+ &fixed_new_option_reply, sizeof fixed_new_option_reply) == -1) {
|
||||
+ nbdkit_error ("write: %m");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ len = htobe32 (name_len);
|
||||
+ if (xwrite (conn->sockout, &len, sizeof len) == -1) {
|
||||
+ nbdkit_error ("write: %m");
|
||||
+ return -1;
|
||||
+ }
|
||||
+ if (xwrite (conn->sockout, exportname, name_len) == -1) {
|
||||
+ nbdkit_error ("write: %m");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
_negotiate_handshake_newstyle_options (struct connection *conn)
|
||||
{
|
||||
struct new_option new_option;
|
||||
@@ -309,7 +337,12 @@ _negotiate_handshake_newstyle_options (struct connection *conn)
|
||||
continue;
|
||||
}
|
||||
|
||||
- /* Since we don't support export names, there is nothing to list. */
|
||||
+ /* Send back the exportname. */
|
||||
+ debug ("newstyle negotiation: advertising export '%s'", exportname);
|
||||
+ if (send_newstyle_option_reply_exportname (conn, option, NBD_REP_SERVER,
|
||||
+ exportname) == -1)
|
||||
+ return -1;
|
||||
+
|
||||
if (send_newstyle_option_reply (conn, option, NBD_REP_ACK) == -1)
|
||||
return -1;
|
||||
break;
|
||||
diff --git a/src/internal.h b/src/internal.h
|
||||
index 0603779..f58086a 100644
|
||||
--- a/src/internal.h
|
||||
+++ b/src/internal.h
|
||||
@@ -48,6 +48,7 @@
|
||||
#endif
|
||||
|
||||
/* main.c */
|
||||
+extern const char *exportname;
|
||||
extern const char *ipaddr;
|
||||
extern int newstyle;
|
||||
extern const char *port;
|
||||
diff --git a/src/main.c b/src/main.c
|
||||
index db4361e..9529f19 100644
|
||||
--- a/src/main.c
|
||||
+++ b/src/main.c
|
||||
@@ -65,6 +65,7 @@ static void fork_into_background (void);
|
||||
static uid_t parseuser (const char *);
|
||||
static gid_t parsegroup (const char *);
|
||||
|
||||
+const char *exportname; /* -e */
|
||||
int foreground; /* -f */
|
||||
const char *ipaddr; /* -i */
|
||||
int newstyle; /* -n */
|
||||
@@ -84,10 +85,13 @@ static char *random_fifo = NULL;
|
||||
|
||||
enum { HELP_OPTION = CHAR_MAX + 1 };
|
||||
|
||||
-static const char *short_options = "fg:i:nop:P:rsu:U:vV";
|
||||
+static const char *short_options = "e:fg:i:nop:P:rsu:U:vV";
|
||||
static const struct option long_options[] = {
|
||||
{ "help", 0, NULL, HELP_OPTION },
|
||||
{ "dump-config",0, NULL, 0 },
|
||||
+ { "export", 1, NULL, 'e' },
|
||||
+ { "export-name",1, NULL, 'e' },
|
||||
+ { "exportname", 1, NULL, 'e' },
|
||||
{ "foreground", 0, NULL, 'f' },
|
||||
{ "no-fork", 0, NULL, 'f' },
|
||||
{ "group", 1, NULL, 'g' },
|
||||
@@ -115,7 +119,7 @@ static const struct option long_options[] = {
|
||||
static void
|
||||
usage (void)
|
||||
{
|
||||
- printf ("nbdkit [--dump-config] [-f] [-g GROUP] [-i IPADDR]\n"
|
||||
+ printf ("nbdkit [--dump-config] [-e EXPORTNAME] [-f] [-g GROUP] [-i IPADDR]\n"
|
||||
" [--newstyle] [--oldstyle] [-P PIDFILE] [-p PORT] [-r]\n"
|
||||
" [--run CMD] [-s] [-U SOCKET] [-u USER] [-v] [-V]\n"
|
||||
" PLUGIN [key=value [key=value [...]]]\n"
|
||||
@@ -173,6 +177,11 @@ main (int argc, char *argv[])
|
||||
}
|
||||
break;
|
||||
|
||||
+ case 'e':
|
||||
+ exportname = optarg;
|
||||
+ newstyle = 1;
|
||||
+ break;
|
||||
+
|
||||
case 'f':
|
||||
foreground = 1;
|
||||
break;
|
||||
@@ -190,9 +199,6 @@ main (int argc, char *argv[])
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
- /* XXX When we add support for exportnames, we will need to
|
||||
- * ensure that the user does not use -o + --export.
|
||||
- */
|
||||
newstyle = 0;
|
||||
break;
|
||||
|
||||
@@ -263,12 +269,22 @@ main (int argc, char *argv[])
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
+ /* Oldstyle protocol + exportname not allowed. */
|
||||
+ if (newstyle == 0 && exportname != NULL) {
|
||||
+ fprintf (stderr,
|
||||
+ "%s: cannot use oldstyle protocol (-o) and exportname (-e)\n",
|
||||
+ program_name);
|
||||
+ exit (EXIT_FAILURE);
|
||||
+ }
|
||||
+
|
||||
+ /* If exportname was not set on the command line, use "". */
|
||||
+ if (exportname == NULL)
|
||||
+ exportname = "";
|
||||
+
|
||||
/* Remaining command line arguments define the plugins and plugin
|
||||
* configuration. If --help or --version was specified, we still
|
||||
* partially parse these in order that we can display the per-plugin
|
||||
- * help/version information. In future (when the new protocol and
|
||||
- * export names are permitted) we will allow multiple plugins to be
|
||||
- * given, but at the moment only one plugin is allowed.
|
||||
+ * help/version information.
|
||||
*/
|
||||
while (optind < argc) {
|
||||
const char *filename = argv[optind];
|
||||
diff --git a/src/protocol.h b/src/protocol.h
|
||||
index 71a8098..c885d9e 100644
|
||||
--- a/src/protocol.h
|
||||
+++ b/src/protocol.h
|
||||
@@ -70,8 +70,7 @@ struct fixed_new_option_reply {
|
||||
uint64_t magic; /* NBD_REP_MAGIC, network byte order */
|
||||
uint32_t option; /* option we are replying to */
|
||||
uint32_t reply; /* NBD_REP_* */
|
||||
- uint32_t replylen; /* we always send zero at the moment */
|
||||
- /* reply data follows, but we currently never send any */
|
||||
+ uint32_t replylen;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define NBD_REP_MAGIC UINT64_C(0x3e889045565a9)
|
||||
diff --git a/tests/test-newstyle.c b/tests/test-newstyle.c
|
||||
index b1d8ce7..adcc568 100644
|
||||
--- a/tests/test-newstyle.c
|
||||
+++ b/tests/test-newstyle.c
|
||||
@@ -44,6 +44,8 @@
|
||||
|
||||
#include "test.h"
|
||||
|
||||
+#define EXPORTNAME "/"
|
||||
+
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
@@ -52,7 +54,8 @@ main (int argc, char *argv[])
|
||||
char *data;
|
||||
size_t i, size;
|
||||
|
||||
- if (test_start_nbdkit ("-n", NBDKIT_PLUGIN ("file"), "file=file-data",
|
||||
+ if (test_start_nbdkit ("-e", EXPORTNAME,
|
||||
+ "-n", NBDKIT_PLUGIN ("file"), "file=file-data",
|
||||
NULL) == -1)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
@@ -63,7 +66,7 @@ main (int argc, char *argv[])
|
||||
}
|
||||
|
||||
/* Using any exportname causes qemu to use the newstyle protocol. */
|
||||
- r = guestfs_add_drive_opts (g, "/" /* exportname */,
|
||||
+ r = guestfs_add_drive_opts (g, EXPORTNAME,
|
||||
GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw",
|
||||
GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "nbd",
|
||||
GUESTFS_ADD_DRIVE_OPTS_SERVER, server,
|
||||
--
|
||||
2.7.4
|
||||
|
@ -1,46 +0,0 @@
|
||||
From 7938bbc463a694aeda888d51f1de446f23402d8f Mon Sep 17 00:00:00 2001
|
||||
From: Eric Blake <eblake@redhat.com>
|
||||
Date: Fri, 20 May 2016 08:04:05 -0600
|
||||
Subject: [PATCH 11/11] protocol: Ignore rest of option when replying with
|
||||
error
|
||||
|
||||
We must consume the payload of any option received, whether or
|
||||
not we can answer the option successfully, in order to be in
|
||||
sync for reading the next option. This is particularly true
|
||||
once clients start using NBD_OPT_GO, as long as we don't happen
|
||||
to service that option.
|
||||
|
||||
Signed-off-by: Eric Blake <eblake@redhat.com>
|
||||
---
|
||||
src/connections.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/src/connections.c b/src/connections.c
|
||||
index 0c93f35..840e315 100644
|
||||
--- a/src/connections.c
|
||||
+++ b/src/connections.c
|
||||
@@ -334,6 +334,10 @@ _negotiate_handshake_newstyle_options (struct connection *conn)
|
||||
if (send_newstyle_option_reply (conn, option, NBD_REP_ERR_INVALID)
|
||||
== -1)
|
||||
return -1;
|
||||
+ if (xread (conn->sockin, data, optlen) == -1) {
|
||||
+ nbdkit_error ("read: %m");
|
||||
+ return -1;
|
||||
+ }
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -351,6 +355,10 @@ _negotiate_handshake_newstyle_options (struct connection *conn)
|
||||
/* Unknown option. */
|
||||
if (send_newstyle_option_reply (conn, option, NBD_REP_ERR_UNSUP) == -1)
|
||||
return -1;
|
||||
+ if (xread (conn->sockin, data, optlen) == -1) {
|
||||
+ nbdkit_error ("read: %m");
|
||||
+ return -1;
|
||||
+ }
|
||||
}
|
||||
|
||||
/* Note, since it's not very clear from the protocol doc, that the
|
||||
--
|
||||
2.7.4
|
||||
|
49
nbdkit.spec
49
nbdkit.spec
@ -5,8 +5,8 @@
|
||||
%endif
|
||||
|
||||
Name: nbdkit
|
||||
Version: 1.1.11
|
||||
Release: 10%{?dist}
|
||||
Version: 1.1.12
|
||||
Release: 1%{?dist}
|
||||
Summary: NBD server
|
||||
|
||||
License: BSD
|
||||
@ -14,22 +14,6 @@ URL: https://github.com/libguestfs/nbdkit
|
||||
|
||||
Source0: http://libguestfs.org/download/nbdkit/%{name}-%{version}.tar.gz
|
||||
|
||||
# All patches are upstream since 1.1.11.
|
||||
Patch0001: 0001-Add-mandir-to-dump-config-output.patch
|
||||
Patch0002: 0002-Update-TODO.patch
|
||||
Patch0003: 0003-Add-support-for-newstyle-NBD-protocol-RHBZ-1297100.patch
|
||||
Patch0004: 0004-xz-Fix-various-printf-warnings-on-32-bit.patch
|
||||
Patch0005: 0005-ocaml-Avoid-race-when-building-NBDKit.cmi.patch
|
||||
Patch0006: 0006-Test-the-o-oldstyle-command-line-option.patch
|
||||
Patch0007: 0007-protocol-Send-limited-range-of-errno-values-to-the-c.patch
|
||||
Patch0008: 0008-protocol-Pack-fixed_new_option_reply-struct.patch
|
||||
Patch0009: 0009-protocol-Rename-NEW_OPTION_REPLY-as-NBD_REP_MAGIC.patch
|
||||
Patch0010: 0010-Implement-newstyle-export-names.patch
|
||||
Patch0011: 0011-protocol-Ignore-rest-of-option-when-replying-with-er.patch
|
||||
|
||||
# Because patch3 & patch5 patches Makefile.am, we need:
|
||||
BuildRequires: automake, autoconf, libtool
|
||||
|
||||
BuildRequires: /usr/bin/pod2man
|
||||
%if 0%{?have_libguestfs}
|
||||
BuildRequires: libguestfs-devel
|
||||
@ -46,6 +30,7 @@ BuildRequires: python-devel
|
||||
# http://caml.inria.fr/mantis/view.php?id=6693
|
||||
BuildRequires: ocaml >= 4.02.2
|
||||
%endif
|
||||
BuildRequires: ruby-devel
|
||||
|
||||
# For complicated reasons, this is required so that
|
||||
# /bin/kernel-install puts the kernel directly into /boot, instead of
|
||||
@ -196,6 +181,17 @@ Requires: %{name}%{?_isa} = %{version}-%{release}
|
||||
This package lets you write Python plugins for %{name}.
|
||||
|
||||
|
||||
%package plugin-ruby
|
||||
Summary: Ruby plugin for %{name}
|
||||
License: BSD
|
||||
|
||||
Requires: %{name}%{?_isa} = %{version}-%{release}
|
||||
|
||||
|
||||
%description plugin-ruby
|
||||
This package lets you write Ruby plugins for %{name}.
|
||||
|
||||
|
||||
%package plugin-streaming
|
||||
Summary: Streaming file serving plugin for %{name}
|
||||
License: BSD
|
||||
@ -259,13 +255,12 @@ mkdir -p $HOME/.cache/libvirt
|
||||
export LIBGUESTFS_DEBUG=1
|
||||
export LIBGUESTFS_TRACE=1
|
||||
|
||||
# libguestfs 1.20 in Fedora 18 doesn't support NBD client protocol, so
|
||||
# the tests cannot be run.
|
||||
%if 0%{?fedora} >= 19
|
||||
# Unlikely that libguestfs will work on ARM and PPC, so don't try running the
|
||||
# tests there.
|
||||
# Broken on i686 because of https://bugzilla.redhat.com/show_bug.cgi?id=1302071
|
||||
%ifnarch %{arm} %{ix86} ppc %{power64}
|
||||
# Broken on F25 because of https://bugzilla.redhat.com/show_bug.cgi?id=1344016
|
||||
%if 0{?fedora} < 25
|
||||
make check || {
|
||||
cat tests/test-suite.log
|
||||
exit 1
|
||||
@ -350,6 +345,12 @@ make check || {
|
||||
%{_mandir}/man3/nbdkit-python-plugin.3*
|
||||
|
||||
|
||||
%files plugin-ruby
|
||||
%doc LICENSE README
|
||||
%{_libdir}/%{name}/plugins/nbdkit-ruby-plugin.so
|
||||
%{_mandir}/man3/nbdkit-ruby-plugin.3*
|
||||
|
||||
|
||||
%files plugin-streaming
|
||||
%doc LICENSE README
|
||||
%{_libdir}/%{name}/plugins/nbdkit-streaming-plugin.so
|
||||
@ -368,11 +369,17 @@ make check || {
|
||||
%doc plugins/example*/*.c
|
||||
%doc plugins/perl/example.pl
|
||||
%doc plugins/python/example.py
|
||||
%doc plugins/ruby/example.rb
|
||||
%{_includedir}/nbdkit-plugin.h
|
||||
%{_mandir}/man3/nbdkit-plugin.3*
|
||||
|
||||
|
||||
%changelog
|
||||
* Wed Jun 08 2016 Richard W.M. Jones <rjones@redhat.com> - 1.1.12-1
|
||||
- New upstream version 1.1.12
|
||||
- Enable Ruby plugin.
|
||||
- Disable tests on Rawhide because libvirt is broken again (RHBZ#1344016).
|
||||
|
||||
* Wed May 25 2016 Richard W.M. Jones <rjones@redhat.com> - 1.1.11-10
|
||||
- Add another upstream patch since 1.1.11.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user