diff options
Diffstat (limited to 'block/nbd.c')
-rw-r--r-- | block/nbd.c | 159 |
1 files changed, 105 insertions, 54 deletions
diff --git a/block/nbd.c b/block/nbd.c index 8d57220..6bc06d6 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -42,6 +42,9 @@ typedef struct BDRVNBDState { NbdClientSession client; + + /* For nbd_refresh_filename() */ + char *path, *host, *port, *export, *tlscredsid; } BDRVNBDState; static int nbd_parse_uri(const char *filename, QDict *options) @@ -188,13 +191,15 @@ out: g_free(file); } -static SocketAddress *nbd_config(BDRVNBDState *s, QDict *options, char **export, - Error **errp) +static SocketAddress *nbd_config(BDRVNBDState *s, QemuOpts *opts, Error **errp) { SocketAddress *saddr; - if (qdict_haskey(options, "path") == qdict_haskey(options, "host")) { - if (qdict_haskey(options, "path")) { + s->path = g_strdup(qemu_opt_get(opts, "path")); + s->host = g_strdup(qemu_opt_get(opts, "host")); + + 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."); @@ -204,32 +209,28 @@ static SocketAddress *nbd_config(BDRVNBDState *s, QDict *options, char **export, saddr = g_new0(SocketAddress, 1); - if (qdict_haskey(options, "path")) { + 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(qdict_get_str(options, "path")); - qdict_del(options, "path"); + q_unix->path = g_strdup(s->path); } else { InetSocketAddress *inet; + + s->port = g_strdup(qemu_opt_get(opts, "port")); + saddr->type = SOCKET_ADDRESS_KIND_INET; inet = saddr->u.inet.data = g_new0(InetSocketAddress, 1); - inet->host = g_strdup(qdict_get_str(options, "host")); - if (!qdict_get_try_str(options, "port")) { + inet->host = g_strdup(s->host); + inet->port = g_strdup(s->port); + if (!inet->port) { inet->port = g_strdup_printf("%d", NBD_DEFAULT_PORT); - } else { - inet->port = g_strdup(qdict_get_str(options, "port")); } - qdict_del(options, "host"); - qdict_del(options, "port"); } s->client.is_unix = saddr->type == SOCKET_ADDRESS_KIND_UNIX; - *export = g_strdup(qdict_get_try_str(options, "export")); - if (*export) { - qdict_del(options, "export"); - } + s->export = g_strdup(qemu_opt_get(opts, "export")); return saddr; } @@ -292,28 +293,66 @@ static QCryptoTLSCreds *nbd_get_tls_creds(const char *id, Error **errp) } +static QemuOptsList nbd_runtime_opts = { + .name = "nbd", + .head = QTAILQ_HEAD_INITIALIZER(nbd_runtime_opts.head), + .desc = { + { + .name = "host", + .type = QEMU_OPT_STRING, + .help = "TCP host to connect to", + }, + { + .name = "port", + .type = QEMU_OPT_STRING, + .help = "TCP port to connect to", + }, + { + .name = "path", + .type = QEMU_OPT_STRING, + .help = "Unix socket path to connect to", + }, + { + .name = "export", + .type = QEMU_OPT_STRING, + .help = "Name of the NBD export to open", + }, + { + .name = "tls-creds", + .type = QEMU_OPT_STRING, + .help = "ID of the TLS credentials to use", + }, + }, +}; + static int nbd_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { BDRVNBDState *s = bs->opaque; - char *export = NULL; + QemuOpts *opts = NULL; + Error *local_err = NULL; QIOChannelSocket *sioc = NULL; - SocketAddress *saddr; - const char *tlscredsid; + SocketAddress *saddr = NULL; QCryptoTLSCreds *tlscreds = NULL; const char *hostname = NULL; int ret = -EINVAL; + opts = qemu_opts_create(&nbd_runtime_opts, NULL, 0, &error_abort); + qemu_opts_absorb_qdict(opts, options, &local_err); + if (local_err) { + error_propagate(errp, local_err); + goto error; + } + /* Pop the config into our state object. Exit if invalid. */ - saddr = nbd_config(s, options, &export, errp); + saddr = nbd_config(s, opts, errp); if (!saddr) { goto error; } - tlscredsid = g_strdup(qdict_get_try_str(options, "tls-creds")); - if (tlscredsid) { - qdict_del(options, "tls-creds"); - tlscreds = nbd_get_tls_creds(tlscredsid, errp); + s->tlscredsid = g_strdup(qemu_opt_get(opts, "tls-creds")); + if (s->tlscredsid) { + tlscreds = nbd_get_tls_creds(s->tlscredsid, errp); if (!tlscreds) { goto error; } @@ -335,7 +374,7 @@ static int nbd_open(BlockDriverState *bs, QDict *options, int flags, } /* NBD handshake */ - ret = nbd_client_init(bs, sioc, export, + ret = nbd_client_init(bs, sioc, s->export, tlscreds, hostname, errp); error: if (sioc) { @@ -344,8 +383,15 @@ static int nbd_open(BlockDriverState *bs, QDict *options, int flags, if (tlscreds) { object_unref(OBJECT(tlscreds)); } + if (ret < 0) { + g_free(s->path); + g_free(s->host); + g_free(s->port); + g_free(s->export); + g_free(s->tlscredsid); + } qapi_free_SocketAddress(saddr); - g_free(export); + qemu_opts_del(opts); return ret; } @@ -362,7 +408,15 @@ static void nbd_refresh_limits(BlockDriverState *bs, Error **errp) static void nbd_close(BlockDriverState *bs) { + BDRVNBDState *s = bs->opaque; + nbd_client_close(bs); + + g_free(s->path); + g_free(s->host); + g_free(s->port); + g_free(s->export); + g_free(s->tlscredsid); } static int64_t nbd_getlength(BlockDriverState *bs) @@ -385,48 +439,45 @@ static void nbd_attach_aio_context(BlockDriverState *bs, static void nbd_refresh_filename(BlockDriverState *bs, QDict *options) { + BDRVNBDState *s = bs->opaque; QDict *opts = qdict_new(); - const char *path = qdict_get_try_str(options, "path"); - const char *host = qdict_get_try_str(options, "host"); - const char *port = qdict_get_try_str(options, "port"); - const char *export = qdict_get_try_str(options, "export"); - const char *tlscreds = qdict_get_try_str(options, "tls-creds"); qdict_put_obj(opts, "driver", QOBJECT(qstring_from_str("nbd"))); - if (path && export) { + if (s->path && s->export) { snprintf(bs->exact_filename, sizeof(bs->exact_filename), - "nbd+unix:///%s?socket=%s", export, path); - } else if (path && !export) { + "nbd+unix:///%s?socket=%s", s->export, s->path); + } else if (s->path && !s->export) { snprintf(bs->exact_filename, sizeof(bs->exact_filename), - "nbd+unix://?socket=%s", path); - } else if (!path && export && port) { + "nbd+unix://?socket=%s", s->path); + } else if (!s->path && s->export && s->port) { snprintf(bs->exact_filename, sizeof(bs->exact_filename), - "nbd://%s:%s/%s", host, port, export); - } else if (!path && export && !port) { + "nbd://%s:%s/%s", s->host, s->port, s->export); + } else if (!s->path && s->export && !s->port) { snprintf(bs->exact_filename, sizeof(bs->exact_filename), - "nbd://%s/%s", host, export); - } else if (!path && !export && port) { + "nbd://%s/%s", s->host, s->export); + } else if (!s->path && !s->export && s->port) { snprintf(bs->exact_filename, sizeof(bs->exact_filename), - "nbd://%s:%s", host, port); - } else if (!path && !export && !port) { + "nbd://%s:%s", s->host, s->port); + } else if (!s->path && !s->export && !s->port) { snprintf(bs->exact_filename, sizeof(bs->exact_filename), - "nbd://%s", host); + "nbd://%s", s->host); } - if (path) { - qdict_put_obj(opts, "path", QOBJECT(qstring_from_str(path))); - } else if (port) { - qdict_put_obj(opts, "host", QOBJECT(qstring_from_str(host))); - qdict_put_obj(opts, "port", QOBJECT(qstring_from_str(port))); + if (s->path) { + qdict_put_obj(opts, "path", QOBJECT(qstring_from_str(s->path))); + } else if (s->port) { + qdict_put_obj(opts, "host", QOBJECT(qstring_from_str(s->host))); + qdict_put_obj(opts, "port", QOBJECT(qstring_from_str(s->port))); } else { - qdict_put_obj(opts, "host", QOBJECT(qstring_from_str(host))); + qdict_put_obj(opts, "host", QOBJECT(qstring_from_str(s->host))); } - if (export) { - qdict_put_obj(opts, "export", QOBJECT(qstring_from_str(export))); + if (s->export) { + qdict_put_obj(opts, "export", QOBJECT(qstring_from_str(s->export))); } - if (tlscreds) { - qdict_put_obj(opts, "tls-creds", QOBJECT(qstring_from_str(tlscreds))); + if (s->tlscredsid) { + qdict_put_obj(opts, "tls-creds", + QOBJECT(qstring_from_str(s->tlscredsid))); } bs->full_open_options = opts; |