Add a new option "server" to the NBD block driver which accepts a
SocketAddress.
"path", "host" and "port" are still supported as legacy options and are
mapped to their corresponding SocketAddress representation.
Signed-off-by: Max Reitz
---
block/nbd.c | 175 +++---
tests/qemu-iotests/051.out| 4 +-
tests/qemu-iotests/051.pc.out | 4 +-
3 files changed, 117 insertions(+), 66 deletions(-)
diff --git a/block/nbd.c b/block/nbd.c
index cdab20f..a778692 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -32,6 +32,9 @@
#include "qemu/uri.h"
#include "block/block_int.h"
#include "qemu/module.h"
+#include "qapi-visit.h"
+#include "qapi/qobject-input-visitor.h"
+#include "qapi/qobject-output-visitor.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qjson.h"
#include "qapi/qmp/qint.h"
@@ -44,7 +47,8 @@ typedef struct BDRVNBDState {
NbdClientSession client;
/* For nbd_refresh_filename() */
-char *path, *host, *port, *export, *tlscredsid;
+SocketAddress *saddr;
+char *export, *tlscredsid;
} BDRVNBDState;
static int nbd_parse_uri(const char *filename, QDict *options)
@@ -131,7 +135,8 @@ static bool nbd_has_filename_options_conflict(QDict
*options, Error **errp)
if (!strcmp(e->key, "host") ||
!strcmp(e->key, "port") ||
!strcmp(e->key, "path") ||
-!strcmp(e->key, "export"))
+!strcmp(e->key, "export") ||
+strstart(e->key, "server.", NULL))
{
error_setg(errp, "Option '%s' cannot be used with a file name",
e->key);
@@ -205,50 +210,81 @@ out:
g_free(file);
}
-static SocketAddress *nbd_config(BDRVNBDState *s, QemuOpts *opts, Error **errp)
+static bool nbd_process_legacy_socket_options(QDict *output_options,
+ QemuOpts *legacy_opts,
+ Error **errp)
{
-SocketAddress *saddr;
+const char *path = qemu_opt_get(legacy_opts, "path");
+const char *host = qemu_opt_get(legacy_opts, "host");
+const char *port = qemu_opt_get(legacy_opts, "port");
+const QDictEntry *e;
-s->path = g_strdup(qemu_opt_get(opts, "path"));
-s->host = g_strdup(qemu_opt_get(opts, "host"));
-s->port = g_strdup(qemu_opt_get(opts, "port"));
+if (!path && !host && !port) {
+return true;
+}
-if (!s->path == !s->host) {
-if (s->path) {
-error_setg(errp, "path and host may not be used at the same time");
-} else {
-error_setg(errp, "one of path and host must be specified");
+for (e = qdict_first(output_options); e; e = qdict_next(output_options, e))
+{
+if (strstart(e->key, "server.", NULL)) {
+error_setg(errp, "Cannot use 'server' and path/host/port at the "
+ "same time");
+return false;
}
-return NULL;
}
-if (s->port && !s->host) {
-error_setg(errp, "port may not be used without host");
-return NULL;
+
+if (path && host) {
+error_setg(errp, "path and host may not be used at the same time");
+return false;
+} else if (path) {
+if (port) {
+error_setg(errp, "port may not be used without host");
+return false;
+}
+
+qdict_put(output_options, "server.type", qstring_from_str("unix"));
+qdict_put(output_options, "server.data.path", qstring_from_str(path));
+} else if (host) {
+qdict_put(output_options, "server.type", qstring_from_str("inet"));
+qdict_put(output_options, "server.data.host", qstring_from_str(host));
+qdict_put(output_options, "server.data.port",
+ qstring_from_str(port ?: stringify(NBD_DEFAULT_PORT)));
}
-saddr = g_new0(SocketAddress, 1);
+return true;
+}
-if (s->path) {
-UnixSocketAddress *q_unix;
-saddr->type = SOCKET_ADDRESS_KIND_UNIX;
-q_unix = saddr->u.q_unix.data = g_new0(UnixSocketAddress, 1);
-q_unix->path = g_strdup(s->path);
-} else {
-InetSocketAddress *inet;
-
-saddr->type = SOCKET_ADDRESS_KIND_INET;
-inet = saddr->u.inet.data = g_new0(InetSocketAddress, 1);
-inet->host = g_strdup(s->host);
-inet->port = g_strdup(s->port);
-if (!inet->port) {
-inet->port = g_strdup_printf("%d", NBD_DEFAULT_PORT);
-}
+static SocketAddress *nbd_config(BDRVNBDState *s, QDict *options, Error **errp)
+{
+SocketAddress *saddr = NULL;
+QDict *addr = NULL;
+QObject *crumpled_addr = NULL;
+Visitor *iv = NULL;
+Error *local_err = NULL;
+
+qdict_extract_subqdict(options, , "server.");
+if (!qdict_size(addr)) {
+error_setg(errp, "NBD server address missing");
+goto done;
}
-s->client.is_unix = saddr->type == SOCKET_ADDRESS_KIND_UNIX;
+crumpled_addr