diff options
Diffstat (limited to 'block')
-rw-r--r-- | block/curl.c | 10 | ||||
-rw-r--r-- | block/file-posix.c | 6 | ||||
-rw-r--r-- | block/gluster.c | 28 | ||||
-rw-r--r-- | block/nbd.c | 62 | ||||
-rw-r--r-- | block/nfs.c | 7 | ||||
-rw-r--r-- | block/parallels.c | 19 | ||||
-rw-r--r-- | block/qcow2-cluster.c | 10 | ||||
-rw-r--r-- | block/rbd.c | 93 | ||||
-rw-r--r-- | block/sheepdog.c | 90 | ||||
-rw-r--r-- | block/ssh.c | 8 |
10 files changed, 211 insertions, 122 deletions
diff --git a/block/curl.c b/block/curl.c index 34dbd335f4..2708d57c2f 100644 --- a/block/curl.c +++ b/block/curl.c @@ -659,6 +659,7 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags, const char *cookie; double d; const char *secretid; + const char *protocol_delimiter; static int inited = 0; @@ -700,6 +701,15 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags, goto out_noclean; } + if (!strstart(file, bs->drv->protocol_name, &protocol_delimiter) || + !strstart(protocol_delimiter, "://", NULL)) + { + error_setg(errp, "%s curl driver cannot handle the URL '%s' (does not " + "start with '%s://')", bs->drv->protocol_name, file, + bs->drv->protocol_name); + goto out_noclean; + } + s->username = g_strdup(qemu_opt_get(opts, CURL_BLOCK_OPT_USERNAME)); secretid = qemu_opt_get(opts, CURL_BLOCK_OPT_PASSWORD_SECRET); diff --git a/block/file-posix.c b/block/file-posix.c index 0841a08785..0c4896876e 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -2193,6 +2193,12 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags, int ret; #if defined(__APPLE__) && defined(__MACH__) + /* + * Caution: while qdict_get_str() is fine, getting non-string types + * would require more care. When @options come from -blockdev or + * blockdev_add, its members are typed according to the QAPI + * schema, but when they come from -drive, they're all QString. + */ const char *filename = qdict_get_str(options, "filename"); char bsd_path[MAXPATHLEN] = ""; bool error_occurred = false; diff --git a/block/gluster.c b/block/gluster.c index a577daef10..cf29b5f9a4 100644 --- a/block/gluster.c +++ b/block/gluster.c @@ -412,10 +412,12 @@ static struct glfs *qemu_gluster_glfs_init(BlockdevOptionsGluster *gconf, glfs_set_preopened(gconf->volume, glfs); for (server = gconf->server; server; server = server->next) { - if (server->value->type == SOCKET_ADDRESS_FLAT_TYPE_UNIX) { + switch (server->value->type) { + case SOCKET_ADDRESS_FLAT_TYPE_UNIX: ret = glfs_set_volfile_server(glfs, "unix", server->value->u.q_unix.path, 0); - } else { + break; + case SOCKET_ADDRESS_FLAT_TYPE_INET: if (parse_uint_full(server->value->u.inet.port, &port, 10) < 0 || port > 65535) { error_setg(errp, "'%s' is not a valid port number", @@ -426,6 +428,11 @@ static struct glfs *qemu_gluster_glfs_init(BlockdevOptionsGluster *gconf, ret = glfs_set_volfile_server(glfs, "tcp", server->value->u.inet.host, (int)port); + break; + case SOCKET_ADDRESS_FLAT_TYPE_VSOCK: + case SOCKET_ADDRESS_FLAT_TYPE_FD: + default: + abort(); } if (ret < 0) { @@ -487,7 +494,7 @@ static int qemu_gluster_parse_json(BlockdevOptionsGluster *gconf, char *str = NULL; const char *ptr; size_t num_servers; - int i; + int i, type; /* create opts info from runtime_json_opts list */ opts = qemu_opts_create(&runtime_json_opts, NULL, 0, &error_abort); @@ -539,16 +546,17 @@ static int qemu_gluster_parse_json(BlockdevOptionsGluster *gconf, if (!strcmp(ptr, "tcp")) { ptr = "inet"; /* accept legacy "tcp" */ } - gsconf->type = qapi_enum_parse(SocketAddressFlatType_lookup, ptr, - SOCKET_ADDRESS_FLAT_TYPE__MAX, -1, - &local_err); - if (local_err) { - error_append_hint(&local_err, - "Parameter '%s' may be 'inet' or 'unix'\n", - GLUSTER_OPT_TYPE); + type = qapi_enum_parse(SocketAddressFlatType_lookup, ptr, + SOCKET_ADDRESS_FLAT_TYPE__MAX, -1, NULL); + if (type != SOCKET_ADDRESS_FLAT_TYPE_INET + && type != SOCKET_ADDRESS_FLAT_TYPE_UNIX) { + error_setg(&local_err, + "Parameter '%s' may be 'inet' or 'unix'", + GLUSTER_OPT_TYPE); error_append_hint(&local_err, GERR_INDEX_HINT, i); goto out; } + gsconf->type = type; qemu_opts_del(opts); if (gsconf->type == SOCKET_ADDRESS_FLAT_TYPE_INET) { diff --git a/block/nbd.c b/block/nbd.c index 3150712f0c..814ab26dce 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -47,7 +47,7 @@ typedef struct BDRVNBDState { NBDClientSession client; /* For nbd_refresh_filename() */ - SocketAddress *saddr; + SocketAddressFlat *saddr; char *export, *tlscredsid; } BDRVNBDState; @@ -95,7 +95,7 @@ static int nbd_parse_uri(const char *filename, QDict *options) goto out; } qdict_put(options, "server.type", qstring_from_str("unix")); - qdict_put(options, "server.data.path", + qdict_put(options, "server.path", qstring_from_str(qp->p[0].value)); } else { QString *host; @@ -116,10 +116,10 @@ static int nbd_parse_uri(const char *filename, QDict *options) } qdict_put(options, "server.type", qstring_from_str("inet")); - qdict_put(options, "server.data.host", host); + qdict_put(options, "server.host", host); port_str = g_strdup_printf("%d", uri->port ?: NBD_DEFAULT_PORT); - qdict_put(options, "server.data.port", qstring_from_str(port_str)); + qdict_put(options, "server.port", qstring_from_str(port_str)); g_free(port_str); } @@ -197,7 +197,7 @@ static void nbd_parse_filename(const char *filename, QDict *options, /* are we a UNIX or TCP socket? */ if (strstart(host_spec, "unix:", &unixpath)) { qdict_put(options, "server.type", qstring_from_str("unix")); - qdict_put(options, "server.data.path", qstring_from_str(unixpath)); + qdict_put(options, "server.path", qstring_from_str(unixpath)); } else { InetSocketAddress *addr = NULL; @@ -207,8 +207,8 @@ static void nbd_parse_filename(const char *filename, QDict *options, } qdict_put(options, "server.type", qstring_from_str("inet")); - qdict_put(options, "server.data.host", qstring_from_str(addr->host)); - qdict_put(options, "server.data.port", qstring_from_str(addr->port)); + qdict_put(options, "server.host", qstring_from_str(addr->host)); + qdict_put(options, "server.port", qstring_from_str(addr->port)); qapi_free_InetSocketAddress(addr); } @@ -248,20 +248,21 @@ static bool nbd_process_legacy_socket_options(QDict *output_options, } qdict_put(output_options, "server.type", qstring_from_str("unix")); - qdict_put(output_options, "server.data.path", qstring_from_str(path)); + qdict_put(output_options, "server.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", + qdict_put(output_options, "server.host", qstring_from_str(host)); + qdict_put(output_options, "server.port", qstring_from_str(port ?: stringify(NBD_DEFAULT_PORT))); } return true; } -static SocketAddress *nbd_config(BDRVNBDState *s, QDict *options, Error **errp) +static SocketAddressFlat *nbd_config(BDRVNBDState *s, QDict *options, + Error **errp) { - SocketAddress *saddr = NULL; + SocketAddressFlat *saddr = NULL; QDict *addr = NULL; QObject *crumpled_addr = NULL; Visitor *iv = NULL; @@ -278,8 +279,16 @@ static SocketAddress *nbd_config(BDRVNBDState *s, QDict *options, Error **errp) goto done; } + /* + * FIXME .numeric, .to, .ipv4 or .ipv6 don't work with -drive + * server.type=inet. .to doesn't matter, it's ignored anyway. + * That's because when @options come from -blockdev or + * blockdev_add, members are typed according to the QAPI schema, + * but when they come from -drive, they're all QString. The + * visitor expects the former. + */ iv = qobject_input_visitor_new(crumpled_addr); - visit_type_SocketAddress(iv, NULL, &saddr, &local_err); + visit_type_SocketAddressFlat(iv, NULL, &saddr, &local_err); if (local_err) { error_propagate(errp, local_err); goto done; @@ -298,9 +307,10 @@ NBDClientSession *nbd_get_client_session(BlockDriverState *bs) return &s->client; } -static QIOChannelSocket *nbd_establish_connection(SocketAddress *saddr, +static QIOChannelSocket *nbd_establish_connection(SocketAddressFlat *saddr_flat, Error **errp) { + SocketAddress *saddr = socket_address_crumple(saddr_flat); QIOChannelSocket *sioc; Error *local_err = NULL; @@ -310,6 +320,7 @@ static QIOChannelSocket *nbd_establish_connection(SocketAddress *saddr, qio_channel_socket_connect_sync(sioc, saddr, &local_err); + qapi_free_SocketAddress(saddr); if (local_err) { object_unref(OBJECT(sioc)); error_propagate(errp, local_err); @@ -402,7 +413,7 @@ static int nbd_open(BlockDriverState *bs, QDict *options, int flags, goto error; } - /* Translate @host, @port, and @path to a SocketAddress */ + /* Translate @host, @port, and @path to a SocketAddressFlat */ if (!nbd_process_legacy_socket_options(options, opts, errp)) { goto error; } @@ -422,11 +433,12 @@ static int nbd_open(BlockDriverState *bs, QDict *options, int flags, goto error; } - if (s->saddr->type != SOCKET_ADDRESS_KIND_INET) { + /* TODO SOCKET_ADDRESS_KIND_FD where fd has AF_INET or AF_INET6 */ + if (s->saddr->type != SOCKET_ADDRESS_FLAT_TYPE_INET) { error_setg(errp, "TLS only supported over IP sockets"); goto error; } - hostname = s->saddr->u.inet.data->host; + hostname = s->saddr->u.inet.host; } /* establish TCP connection, return error if it fails @@ -449,7 +461,7 @@ static int nbd_open(BlockDriverState *bs, QDict *options, int flags, object_unref(OBJECT(tlscreds)); } if (ret < 0) { - qapi_free_SocketAddress(s->saddr); + qapi_free_SocketAddressFlat(s->saddr); g_free(s->export); g_free(s->tlscredsid); } @@ -475,7 +487,7 @@ static void nbd_close(BlockDriverState *bs) nbd_client_close(bs); - qapi_free_SocketAddress(s->saddr); + qapi_free_SocketAddressFlat(s->saddr); g_free(s->export); g_free(s->tlscredsid); } @@ -506,15 +518,15 @@ static void nbd_refresh_filename(BlockDriverState *bs, QDict *options) Visitor *ov; const char *host = NULL, *port = NULL, *path = NULL; - if (s->saddr->type == SOCKET_ADDRESS_KIND_INET) { - const InetSocketAddress *inet = s->saddr->u.inet.data; + if (s->saddr->type == SOCKET_ADDRESS_FLAT_TYPE_INET) { + const InetSocketAddress *inet = &s->saddr->u.inet; if (!inet->has_ipv4 && !inet->has_ipv6 && !inet->has_to) { host = inet->host; port = inet->port; } - } else if (s->saddr->type == SOCKET_ADDRESS_KIND_UNIX) { - path = s->saddr->u.q_unix.data->path; - } + } else if (s->saddr->type == SOCKET_ADDRESS_FLAT_TYPE_UNIX) { + path = s->saddr->u.q_unix.path; + } /* else can't represent as pseudo-filename */ qdict_put(opts, "driver", qstring_from_str("nbd")); @@ -533,7 +545,7 @@ static void nbd_refresh_filename(BlockDriverState *bs, QDict *options) } ov = qobject_output_visitor_new(&saddr_qdict); - visit_type_SocketAddress(ov, NULL, &s->saddr, &error_abort); + visit_type_SocketAddressFlat(ov, NULL, &s->saddr, &error_abort); visit_complete(ov, &saddr_qdict); visit_free(ov); qdict_put_obj(opts, "server", saddr_qdict); diff --git a/block/nfs.c b/block/nfs.c index 3f43f6e26a..0816678307 100644 --- a/block/nfs.c +++ b/block/nfs.c @@ -474,6 +474,13 @@ static NFSServer *nfs_config(QDict *options, Error **errp) goto out; } + /* + * Caution: this works only because all scalar members of + * NFSServer are QString in @crumpled_addr. The visitor expects + * @crumpled_addr to be typed according to the QAPI schema. It + * is when @options come from -blockdev or blockdev_add. But when + * they come from -drive, they're all QString. + */ iv = qobject_input_visitor_new(crumpled_addr); visit_type_NFSServer(iv, NULL, &server, &local_error); if (local_error) { diff --git a/block/parallels.c b/block/parallels.c index 4173b3fb9d..90acf79687 100644 --- a/block/parallels.c +++ b/block/parallels.c @@ -192,8 +192,7 @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum) { BDRVParallelsState *s = bs->opaque; - uint32_t idx, to_allocate, i; - int64_t pos, space; + int64_t pos, space, idx, to_allocate, i; pos = block_status(s, sector_num, nb_sectors, pnum); if (pos > 0) { @@ -201,11 +200,19 @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num, } idx = sector_num / s->tracks; - if (idx >= s->bat_size) { - return -EINVAL; - } - to_allocate = DIV_ROUND_UP(sector_num + *pnum, s->tracks) - idx; + + /* This function is called only by parallels_co_writev(), which will never + * pass a sector_num at or beyond the end of the image (because the block + * layer never passes such a sector_num to that function). Therefore, idx + * is always below s->bat_size. + * block_status() will limit *pnum so that sector_num + *pnum will not + * exceed the image end. Therefore, idx + to_allocate cannot exceed + * s->bat_size. + * Note that s->bat_size is an unsigned int, therefore idx + to_allocate + * will always fit into a uint32_t. */ + assert(idx < s->bat_size && idx + to_allocate <= s->bat_size); + space = to_allocate * s->tracks; if (s->data_end + space > bdrv_getlength(bs->file->bs) >> BDRV_SECTOR_BITS) { int ret; diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 78c11d4948..100398c565 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -1519,12 +1519,10 @@ int qcow2_discard_clusters(BlockDriverState *bs, uint64_t offset, end_offset = offset + (nb_sectors << BDRV_SECTOR_BITS); - /* Round start up and end down */ - offset = align_offset(offset, s->cluster_size); - end_offset = start_of_cluster(s, end_offset); - - if (offset > end_offset) { - return 0; + /* The caller must cluster-align start; round end down except at EOF */ + assert(QEMU_IS_ALIGNED(offset, s->cluster_size)); + if (end_offset != bs->total_sectors * BDRV_SECTOR_SIZE) { + end_offset = start_of_cluster(s, end_offset); } nb_clusters = size_to_clusters(s, end_offset - offset); diff --git a/block/rbd.c b/block/rbd.c index 498322b30b..1ceeeb5a60 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -20,6 +20,7 @@ #include "crypto/secret.h" #include "qemu/cutils.h" #include "qapi/qmp/qstring.h" +#include "qapi/qmp/qjson.h" /* * When specifying the image filename use: @@ -135,18 +136,16 @@ static void qemu_rbd_parse_filename(const char *filename, QDict *options, Error **errp) { const char *start; - char *p, *buf, *keypairs; + char *p, *buf; + QList *keypairs = NULL; char *found_str; - size_t max_keypair_size; if (!strstart(filename, "rbd:", &start)) { error_setg(errp, "File name must start with 'rbd:'"); return; } - max_keypair_size = strlen(start) + 1; buf = g_strdup(start); - keypairs = g_malloc0(max_keypair_size); p = buf; found_str = qemu_rbd_next_tok(p, '/', &p); @@ -194,33 +193,30 @@ static void qemu_rbd_parse_filename(const char *filename, QDict *options, } else if (!strcmp(name, "id")) { qdict_put(options, "user" , qstring_from_str(value)); } else { - /* FIXME: This is pretty ugly, and not the right way to do this. - * These should be contained in a structure, and then - * passed explicitly as individual key/value pairs to - * rados. Consider this legacy code that needs to be - * updated. */ - char *tmp = g_malloc0(max_keypair_size); - /* only use a delimiter if it is not the first keypair found */ - /* These are sets of unknown key/value pairs we'll pass along - * to ceph */ - if (keypairs[0]) { - snprintf(tmp, max_keypair_size, ":%s=%s", name, value); - pstrcat(keypairs, max_keypair_size, tmp); - } else { - snprintf(keypairs, max_keypair_size, "%s=%s", name, value); + /* + * We pass these internally to qemu_rbd_set_keypairs(), so + * we can get away with the simpler list of [ "key1", + * "value1", "key2", "value2" ] rather than a raw dict + * { "key1": "value1", "key2": "value2" } where we can't + * guarantee order, or even a more correct but complex + * [ { "key1": "value1" }, { "key2": "value2" } ] + */ + if (!keypairs) { + keypairs = qlist_new(); } - g_free(tmp); + qlist_append(keypairs, qstring_from_str(name)); + qlist_append(keypairs, qstring_from_str(value)); } } - if (keypairs[0]) { - qdict_put(options, "=keyvalue-pairs", qstring_from_str(keypairs)); + if (keypairs) { + qdict_put(options, "=keyvalue-pairs", + qobject_to_json(QOBJECT(keypairs))); } - done: g_free(buf); - g_free(keypairs); + QDECREF(keypairs); return; } @@ -244,36 +240,41 @@ static int qemu_rbd_set_auth(rados_t cluster, const char *secretid, return 0; } -static int qemu_rbd_set_keypairs(rados_t cluster, const char *keypairs, +static int qemu_rbd_set_keypairs(rados_t cluster, const char *keypairs_json, Error **errp) { - char *p, *buf; - char *name; - char *value; + QList *keypairs; + QString *name; + QString *value; + const char *key; + size_t remaining; int ret = 0; - buf = g_strdup(keypairs); - p = buf; - - while (p) { - name = qemu_rbd_next_tok(p, '=', &p); - if (!p) { - error_setg(errp, "conf option %s has no value", name); - ret = -EINVAL; - break; - } - - value = qemu_rbd_next_tok(p, ':', &p); - - ret = rados_conf_set(cluster, name, value); + if (!keypairs_json) { + return ret; + } + keypairs = qobject_to_qlist(qobject_from_json(keypairs_json, + &error_abort)); + remaining = qlist_size(keypairs) / 2; + assert(remaining); + + while (remaining--) { + name = qobject_to_qstring(qlist_pop(keypairs)); + value = qobject_to_qstring(qlist_pop(keypairs)); + assert(name && value); + key = qstring_get_str(name); + + ret = rados_conf_set(cluster, key, qstring_get_str(value)); + QDECREF(name); + QDECREF(value); if (ret < 0) { - error_setg_errno(errp, -ret, "invalid conf option %s", name); + error_setg_errno(errp, -ret, "invalid conf option %s", key); ret = -EINVAL; break; } } - g_free(buf); + QDECREF(keypairs); return ret; } @@ -384,6 +385,12 @@ static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **errp) goto exit; } + /* + * Caution: while qdict_get_try_str() is fine, getting non-string + * types would require more care. When @options come from -blockdev + * or blockdev_add, its members are typed according to the QAPI + * schema, but when they come from -drive, they're all QString. + */ pool = qdict_get_try_str(options, "pool"); conf = qdict_get_try_str(options, "conf"); clientname = qdict_get_try_str(options, "user"); diff --git a/block/sheepdog.c b/block/sheepdog.c index 89e98edab6..1b71fc81ec 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -13,9 +13,11 @@ */ #include "qemu/osdep.h" +#include "qapi-visit.h" #include "qapi/error.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qint.h" +#include "qapi/qobject-input-visitor.h" #include "qemu/uri.h" #include "qemu/error-report.h" #include "qemu/sockets.h" @@ -547,6 +549,47 @@ static SocketAddress *sd_socket_address(const char *path, return addr; } +static SocketAddress *sd_server_config(QDict *options, Error **errp) +{ + QDict *server = NULL; + QObject *crumpled_server = NULL; + Visitor *iv = NULL; + SocketAddressFlat *saddr_flat = NULL; + SocketAddress *saddr = NULL; + Error *local_err = NULL; + + qdict_extract_subqdict(options, &server, "server."); + + crumpled_server = qdict_crumple(server, errp); + if (!crumpled_server) { + goto done; + } + + /* + * FIXME .numeric, .to, .ipv4 or .ipv6 don't work with -drive + * server.type=inet. .to doesn't matter, it's ignored anyway. + * That's because when @options come from -blockdev or + * blockdev_add, members are typed according to the QAPI schema, + * but when they come from -drive, they're all QString. The + * visitor expects the former. + */ + iv = qobject_input_visitor_new(crumpled_server); + visit_type_SocketAddressFlat(iv, NULL, &saddr_flat, &local_err); + if (local_err) { + error_propagate(errp, local_err); + goto done; + } + + saddr = socket_address_crumple(saddr_flat); + +done: + qapi_free_SocketAddressFlat(saddr_flat); + visit_free(iv); + qobject_decref(crumpled_server); + QDECREF(server); + return saddr; +} + /* Return -EIO in case of error, file descriptor on success */ static int connect_to_sdog(BDRVSheepdogState *s, Error **errp) { @@ -1174,15 +1217,15 @@ static void sd_parse_filename(const char *filename, QDict *options, return; } - if (cfg.host) { - qdict_set_default_str(options, "host", cfg.host); - } - if (cfg.port) { - snprintf(buf, sizeof(buf), "%d", cfg.port); - qdict_set_default_str(options, "port", buf); - } if (cfg.path) { - qdict_set_default_str(options, "path", cfg.path); + qdict_set_default_str(options, "server.path", cfg.path); + qdict_set_default_str(options, "server.type", "unix"); + } else { + qdict_set_default_str(options, "server.type", "inet"); + qdict_set_default_str(options, "server.host", + cfg.host ?: SD_DEFAULT_ADDR); + snprintf(buf, sizeof(buf), "%d", cfg.port ?: SD_DEFAULT_PORT); + qdict_set_default_str(options, "server.port", buf); } qdict_set_default_str(options, "vdi", cfg.vdi); qdict_set_default_str(options, "tag", cfg.tag); @@ -1510,18 +1553,6 @@ static QemuOptsList runtime_opts = { .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head), .desc = { { - .name = "host", - .type = QEMU_OPT_STRING, - }, - { - .name = "port", - .type = QEMU_OPT_STRING, - }, - { - .name = "path", - .type = QEMU_OPT_STRING, - }, - { .name = "vdi", .type = QEMU_OPT_STRING, }, @@ -1543,7 +1574,7 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags, int ret, fd; uint32_t vid = 0; BDRVSheepdogState *s = bs->opaque; - const char *host, *port, *path, *vdi, *snap_id_str, *tag; + const char *vdi, *snap_id_str, *tag; uint64_t snap_id; char *buf = NULL; QemuOpts *opts; @@ -1560,20 +1591,17 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags, goto err_no_fd; } - host = qemu_opt_get(opts, "host"); - port = qemu_opt_get(opts, "port"); - path = qemu_opt_get(opts, "path"); + s->addr = sd_server_config(options, errp); + if (!s->addr) { + ret = -EINVAL; + goto err_no_fd; + } + vdi = qemu_opt_get(opts, "vdi"); snap_id_str = qemu_opt_get(opts, "snap-id"); snap_id = qemu_opt_get_number(opts, "snap-id", CURRENT_VDI_ID); tag = qemu_opt_get(opts, "tag"); - if ((host || port) && path) { - error_setg(errp, "can't use 'path' together with 'host' or 'port'"); - ret = -EINVAL; - goto err_no_fd; - } - if (!vdi) { error_setg(errp, "parameter 'vdi' is missing"); ret = -EINVAL; @@ -1604,8 +1632,6 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags, goto err_no_fd; } - s->addr = sd_socket_address(path, host, port); - QLIST_INIT(&s->inflight_aio_head); QLIST_INIT(&s->failed_aio_head); QLIST_INIT(&s->inflight_aiocb_head); diff --git a/block/ssh.c b/block/ssh.c index 278e66faa6..471ba8a260 100644 --- a/block/ssh.c +++ b/block/ssh.c @@ -601,6 +601,14 @@ static InetSocketAddress *ssh_config(QDict *options, Error **errp) goto out; } + /* + * FIXME .numeric, .to, .ipv4 or .ipv6 don't work with -drive. + * .to doesn't matter, it's ignored anyway. + * That's because when @options come from -blockdev or + * blockdev_add, members are typed according to the QAPI schema, + * but when they come from -drive, they're all QString. The + * visitor expects the former. + */ iv = qobject_input_visitor_new(crumpled_addr); visit_type_InetSocketAddress(iv, NULL, &inet, &local_error); if (local_error) { |