diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2017-04-03 16:43:39 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2017-04-03 16:43:39 +0100 |
commit | b1a419ec79c2451fd7b6acfb415a02881ad77844 (patch) | |
tree | e103c4b121c6b1d25c3b60cacb55ac3c2783697d | |
parent | 102a3d847891f48c0b13cace19d189217b05a725 (diff) | |
parent | 86d1bd70987cd11d85d01f52aa5824c63d910471 (diff) |
Merge remote-tracking branch 'remotes/maxreitz/tags/pull-block-2017-04-03' into staging
Block patches for 2.9-rc3
# gpg: Signature made Mon 03 Apr 2017 16:29:49 BST
# gpg: using RSA key 0xF407DB0061D5CF40
# gpg: Good signature from "Max Reitz <mreitz@redhat.com>"
# Primary key fingerprint: 91BE B60A 30DB 3E88 57D1 1829 F407 DB00 61D5 CF40
* remotes/maxreitz/tags/pull-block-2017-04-03:
block/parallels: Avoid overflows
iotests: Improve image-clear tests on non-aligned image
qcow2: Discard unaligned tail when wiping image
iotests: fix 097 when run with qcow
qemu-io-cmds: Assert that global and nofile commands don't use ct->perms
sheepdog: Fix blockdev-add
nbd: Tidy up blockdev-add interface
sockets: New helper socket_address_crumple()
qapi-schema: SocketAddressFlat variants 'vsock' and 'fd'
gluster: Prepare for SocketAddressFlat extension
block: Document -drive problematic code and bugs
io vnc sockets: Clean up SocketAddressKind switches
char: Fix socket with "type": "vsock" address
nbd sockets vnc: Mark problematic address family tests TODO
block: add missed aio_context_acquire into release_drive
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | block.c | 48 | ||||
-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 | 6 | ||||
-rw-r--r-- | block/sheepdog.c | 90 | ||||
-rw-r--r-- | block/ssh.c | 8 | ||||
-rw-r--r-- | blockdev-nbd.c | 1 | ||||
-rw-r--r-- | chardev/char-socket.c | 9 | ||||
-rw-r--r-- | hw/core/qdev-properties-system.c | 4 | ||||
-rw-r--r-- | include/qemu/sockets.h | 11 | ||||
-rw-r--r-- | io/dns-resolver.c | 7 | ||||
-rw-r--r-- | qapi-schema.json | 19 | ||||
-rw-r--r-- | qapi/block-core.json | 6 | ||||
-rw-r--r-- | qemu-io-cmds.c | 7 | ||||
-rwxr-xr-x | tests/qemu-iotests/097 | 27 | ||||
-rw-r--r-- | tests/qemu-iotests/097.out | 180 | ||||
-rwxr-xr-x | tests/qemu-iotests/147 | 25 | ||||
-rwxr-xr-x | tests/qemu-iotests/176 | 131 | ||||
-rw-r--r-- | tests/qemu-iotests/176.out | 150 | ||||
-rw-r--r-- | tests/qemu-iotests/group | 1 | ||||
-rw-r--r-- | ui/vnc.c | 19 | ||||
-rw-r--r-- | util/qemu-sockets.c | 40 |
26 files changed, 655 insertions, 266 deletions
@@ -1157,6 +1157,13 @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file, if (file != NULL) { filename = blk_bs(file)->filename; } else { + /* + * 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. + */ filename = qdict_get_try_str(options, "filename"); } @@ -1324,6 +1331,13 @@ static int bdrv_fill_options(QDict **options, const char *filename, BlockDriver *drv = NULL; Error *local_err = NULL; + /* + * 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. + */ drvname = qdict_get_try_str(*options, "driver"); if (drvname) { drv = bdrv_find_format(drvname); @@ -1358,6 +1372,7 @@ static int bdrv_fill_options(QDict **options, const char *filename, } /* Find the right block driver */ + /* See cautionary note on accessing @options above */ filename = qdict_get_try_str(*options, "filename"); if (!drvname && protocol) { @@ -1987,6 +2002,13 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options, qdict_extract_subqdict(parent_options, &options, bdref_key_dot); g_free(bdref_key_dot); + /* + * Caution: while qdict_get_try_str() is fine, getting non-string + * types would require more care. When @parent_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. + */ reference = qdict_get_try_str(parent_options, bdref_key); if (reference || qdict_haskey(options, "file.filename")) { backing_filename[0] = '\0'; @@ -2059,6 +2081,13 @@ bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key, qdict_extract_subqdict(options, &image_options, bdref_key_dot); g_free(bdref_key_dot); + /* + * 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. + */ reference = qdict_get_try_str(options, bdref_key); if (!filename && !reference && !qdict_size(image_options)) { if (!allow_none) { @@ -2274,9 +2303,13 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, goto fail; } - /* Set the BDRV_O_RDWR and BDRV_O_ALLOW_RDWR flags. - * FIXME: we're parsing the QDict to avoid having to create a - * QemuOpts just for this, but neither option is optimal. */ + /* + * Set the BDRV_O_RDWR and BDRV_O_ALLOW_RDWR flags. + * Caution: getting a boolean member of @options requires care. + * 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. + */ if (g_strcmp0(qdict_get_try_str(options, BDRV_OPT_READ_ONLY), "on") && !qdict_get_try_bool(options, BDRV_OPT_READ_ONLY, false)) { flags |= (BDRV_O_RDWR | BDRV_O_ALLOW_RDWR); @@ -2298,6 +2331,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, options = qdict_clone_shallow(options); /* Find the right image format driver */ + /* See cautionary note on accessing @options above */ drvname = qdict_get_try_str(options, "driver"); if (drvname) { drv = bdrv_find_format(drvname); @@ -2309,6 +2343,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, assert(drvname || !(flags & BDRV_O_PROTOCOL)); + /* See cautionary note on accessing @options above */ backing = qdict_get_try_str(options, "backing"); if (backing && *backing == '\0') { flags |= BDRV_O_NO_BACKING; @@ -2787,6 +2822,13 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue, do { QString *new_obj = qobject_to_qstring(entry->value); const char *new = qstring_get_str(new_obj); + /* + * Caution: while qdict_get_try_str() is fine, getting + * non-string types would require more care. When + * bs->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 *old = qdict_get_try_str(reopen_state->bs->options, entry->key); 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 1b832c2132..8bb29a90bb 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) { error_propagate(errp, local_err); return NULL; @@ -401,7 +412,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; } @@ -421,11 +432,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 @@ -448,7 +460,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); } @@ -474,7 +486,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); } @@ -505,15 +517,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")); @@ -532,7 +544,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 fbdb131a68..1ceeeb5a60 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -385,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) { diff --git a/blockdev-nbd.c b/blockdev-nbd.c index 7ea836b46e..8a11807df3 100644 --- a/blockdev-nbd.c +++ b/blockdev-nbd.c @@ -124,6 +124,7 @@ void qmp_nbd_server_start(SocketAddress *addr, goto error; } + /* TODO SOCKET_ADDRESS_KIND_FD where fd has AF_INET or AF_INET6 */ if (addr->type != SOCKET_ADDRESS_KIND_INET) { error_setg(errp, "TLS is only supported with IPv4/IPv6"); goto error; diff --git a/chardev/char-socket.c b/chardev/char-socket.c index d7e92e1bd3..36ab0d633a 100644 --- a/chardev/char-socket.c +++ b/chardev/char-socket.c @@ -47,7 +47,6 @@ typedef struct { int max_size; int do_telnetopt; int do_nodelay; - int is_unix; int *read_msgfds; size_t read_msgfds_num; int *write_msgfds; @@ -358,6 +357,10 @@ static char *SocketAddress_to_str(const char *prefix, SocketAddress *addr, return g_strdup_printf("%sfd:%s%s", prefix, addr->u.fd.data->str, is_listen ? ",server" : ""); break; + case SOCKET_ADDRESS_KIND_VSOCK: + return g_strdup_printf("%svsock:%s:%s", prefix, + addr->u.vsock.data->cid, + addr->u.vsock.data->port); default: abort(); } @@ -825,7 +828,6 @@ static void qmp_chardev_open_socket(Chardev *chr, int64_t reconnect = sock->has_reconnect ? sock->reconnect : 0; QIOChannelSocket *sioc = NULL; - s->is_unix = addr->type == SOCKET_ADDRESS_KIND_UNIX; s->is_listen = is_listen; s->is_telnet = is_telnet; s->do_nodelay = do_nodelay; @@ -865,7 +867,8 @@ static void qmp_chardev_open_socket(Chardev *chr, s->addr = QAPI_CLONE(SocketAddress, sock->addr); qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_RECONNECTABLE); - if (s->is_unix) { + /* TODO SOCKET_ADDRESS_FD where fd has AF_UNIX */ + if (addr->type == SOCKET_ADDRESS_KIND_UNIX) { qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_FD_PASS); } diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index c34be1c1ba..e885e650fb 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -124,8 +124,12 @@ static void release_drive(Object *obj, const char *name, void *opaque) BlockBackend **ptr = qdev_get_prop_ptr(dev, prop); if (*ptr) { + AioContext *ctx = blk_get_aio_context(*ptr); + + aio_context_acquire(ctx); blockdev_auto_del(*ptr); blk_detach_dev(*ptr, dev); + aio_context_release(ctx); } } diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h index 5f1bab9b3e..7842f6d150 100644 --- a/include/qemu/sockets.h +++ b/include/qemu/sockets.h @@ -119,4 +119,15 @@ SocketAddress *socket_remote_address(int fd, Error **errp); */ char *socket_address_to_string(struct SocketAddress *addr, Error **errp); +/** + * socket_address_crumple: + * @addr_flat: the socket address to crumple + * + * Convert SocketAddressFlat to SocketAddress. Caller is responsible + * for freeing with qapi_free_SocketAddress(). + * + * Returns: the argument converted to SocketAddress. + */ +SocketAddress *socket_address_crumple(SocketAddressFlat *addr_flat); + #endif /* QEMU_SOCKETS_H */ diff --git a/io/dns-resolver.c b/io/dns-resolver.c index 0ac6b23c02..a407075934 100644 --- a/io/dns-resolver.c +++ b/io/dns-resolver.c @@ -164,9 +164,12 @@ int qio_dns_resolver_lookup_sync(QIODNSResolver *resolver, addrs, errp); - default: - error_setg(errp, "Unknown socket address kind"); + case SOCKET_ADDRESS_KIND_FD: + error_setg(errp, "Unsupported socket address type 'fd'"); return -1; + + default: + abort(); } } diff --git a/qapi-schema.json b/qapi-schema.json index b921994ae3..250e4dc49b 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -4144,7 +4144,7 @@ # Since: 2.9 ## { 'enum': 'SocketAddressFlatType', - 'data': [ 'unix', 'inet' ] } + 'data': [ 'inet', 'unix', 'vsock', 'fd' ] } ## # @SocketAddressFlat: @@ -4153,22 +4153,19 @@ # # @type: Transport type # -# This is similar to SocketAddress, only distinction: -# -# 1. SocketAddressFlat is a flat union, SocketAddress is a simple union. -# A flat union is nicer than simple because it avoids nesting -# (i.e. more {}) on the wire. -# -# 2. SocketAddressFlat supports only types 'unix' and 'inet', because -# that's what its current users need. +# This is just like SocketAddress, except it's a flat union rather +# than a simple union. Nicer because it avoids nesting on the wire, +# i.e. this form has fewer {}. # # Since: 2.9 ## { 'union': 'SocketAddressFlat', 'base': { 'type': 'SocketAddressFlatType' }, 'discriminator': 'type', - 'data': { 'unix': 'UnixSocketAddress', - 'inet': 'InetSocketAddress' } } + 'data': { 'inet': 'InetSocketAddress', + 'unix': 'UnixSocketAddress', + 'vsock': 'VsockSocketAddress', + 'fd': 'String' } } ## # @getfd: diff --git a/qapi/block-core.json b/qapi/block-core.json index 8de39d143a..033457ce86 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -2623,7 +2623,7 @@ # Driver specific block device options for sheepdog # # @vdi: Virtual disk image name -# @addr: The Sheepdog server to connect to +# @server: The Sheepdog server to connect to # @snap-id: Snapshot ID # @tag: Snapshot tag name # @@ -2632,7 +2632,7 @@ # Since: 2.9 ## { 'struct': 'BlockdevOptionsSheepdog', - 'data': { 'addr': 'SocketAddressFlat', + 'data': { 'server': 'SocketAddressFlat', 'vdi': 'str', '*snap-id': 'uint32', '*tag': 'str' } } @@ -2847,7 +2847,7 @@ # Since: 2.9 ## { 'struct': 'BlockdevOptionsNbd', - 'data': { 'server': 'SocketAddress', + 'data': { 'server': 'SocketAddressFlat', '*export': 'str', '*tls-creds': 'str' } } diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c index 2c48f9ce1a..883f53b64d 100644 --- a/qemu-io-cmds.c +++ b/qemu-io-cmds.c @@ -35,6 +35,13 @@ static int compare_cmdname(const void *a, const void *b) void qemuio_add_command(const cmdinfo_t *ci) { + /* ci->perm assumes a file is open, but the GLOBAL and NOFILE_OK + * flags allow it not to be, so that combination is invalid. + * Catch it now rather than letting it manifest as a crash if a + * particular set of command line options are used. + */ + assert(ci->perm == 0 || + (ci->flags & (CMD_FLAG_GLOBAL | CMD_NOFILE_OK)) == 0); cmdtab = g_renew(cmdinfo_t, cmdtab, ++ncmds); cmdtab[ncmds - 1] = *ci; qsort(cmdtab, ncmds, sizeof(*cmdtab), compare_cmdname); diff --git a/tests/qemu-iotests/097 b/tests/qemu-iotests/097 index 4c33e8038a..e22670c8d0 100755 --- a/tests/qemu-iotests/097 +++ b/tests/qemu-iotests/097 @@ -56,30 +56,25 @@ _supported_os Linux # 3: Two-layer backing chain, commit to lower backing file # (in this case, the top image will implicitly stay unchanged) # -# Each pass is run twice, since qcow2 has different code paths for cleaning -# an image depending on whether it has a snapshot. -# # 020 already tests committing, so this only tests whether image chains are # working properly and that all images above the base are emptied; therefore, # no complicated patterns are necessary. Check near the 2G mark, as qcow2 # has been buggy at that boundary in the past. for i in 0 1 2 3; do -for j in 0 1; do echo -echo "=== Test pass $i.$j ===" +echo "=== Test pass $i ===" echo -TEST_IMG="$TEST_IMG.base" _make_test_img 2100M -TEST_IMG="$TEST_IMG.itmd" _make_test_img -b "$TEST_IMG.base" 2100M -_make_test_img -b "$TEST_IMG.itmd" 2100M -if [ $j -eq 0 ]; then - $QEMU_IMG snapshot -c snap "$TEST_IMG" -fi +len=$((2100 * 1024 * 1024 + 512)) # larger than 2G, and not cluster aligned +TEST_IMG="$TEST_IMG.base" _make_test_img $len +TEST_IMG="$TEST_IMG.itmd" _make_test_img -b "$TEST_IMG.base" $len +_make_test_img -b "$TEST_IMG.itmd" $len -$QEMU_IO -c 'write -P 1 0x7ffd0000 192k' "$TEST_IMG.base" | _filter_qemu_io -$QEMU_IO -c 'write -P 2 0x7ffe0000 128k' "$TEST_IMG.itmd" | _filter_qemu_io -$QEMU_IO -c 'write -P 3 0x7fff0000 64k' "$TEST_IMG" | _filter_qemu_io +$QEMU_IO -c "write -P 1 0x7ffd0000 192k" "$TEST_IMG.base" | _filter_qemu_io +$QEMU_IO -c "write -P 2 0x7ffe0000 128k" "$TEST_IMG.itmd" | _filter_qemu_io +$QEMU_IO -c "write -P 3 0x7fff0000 64k" "$TEST_IMG" | _filter_qemu_io +$QEMU_IO -c "write -P 4 $(($len - 512)) 512" "$TEST_IMG" | _filter_qemu_io if [ $i -lt 3 ]; then if [ $i == 0 ]; then @@ -97,11 +92,13 @@ if [ $i -lt 3 ]; then # Bottom should be unchanged $QEMU_IO -c 'read -P 1 0x7ffd0000 192k' "$TEST_IMG.base" | _filter_qemu_io + $QEMU_IO -c "read -P 0 $((len - 512)) 512" "$TEST_IMG.base" | _filter_qemu_io # Intermediate should contain changes from top $QEMU_IO -c 'read -P 1 0x7ffd0000 64k' "$TEST_IMG.itmd" | _filter_qemu_io $QEMU_IO -c 'read -P 2 0x7ffe0000 64k' "$TEST_IMG.itmd" | _filter_qemu_io $QEMU_IO -c 'read -P 3 0x7fff0000 64k' "$TEST_IMG.itmd" | _filter_qemu_io + $QEMU_IO -c "read -P 4 $((len - 512)) 512" "$TEST_IMG.itmd" | _filter_qemu_io # And in pass 0, the top image should be empty, whereas in both other passes # it should be unchanged (which is both checked by qemu-img map) @@ -112,6 +109,7 @@ else $QEMU_IO -c 'read -P 1 0x7ffd0000 64k' "$TEST_IMG.base" | _filter_qemu_io $QEMU_IO -c 'read -P 2 0x7ffe0000 64k' "$TEST_IMG.base" | _filter_qemu_io $QEMU_IO -c 'read -P 3 0x7fff0000 64k' "$TEST_IMG.base" | _filter_qemu_io + $QEMU_IO -c "read -P 4 $((len - 512)) 512" "$TEST_IMG.base" | _filter_qemu_io # Both top and intermediate should be unchanged fi @@ -121,7 +119,6 @@ $QEMU_IMG map "$TEST_IMG.itmd" | _filter_qemu_img_map $QEMU_IMG map "$TEST_IMG" | _filter_qemu_img_map done -done # success, all done diff --git a/tests/qemu-iotests/097.out b/tests/qemu-iotests/097.out index 8106cc9275..f6705a1cc7 100644 --- a/tests/qemu-iotests/097.out +++ b/tests/qemu-iotests/097.out @@ -1,222 +1,131 @@ QA output created by 097 -=== Test pass 0.0 === +=== Test pass 0 === -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202009600 -Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202009600 backing_file=TEST_DIR/t.IMGFMT.base -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202009600 backing_file=TEST_DIR/t.IMGFMT.itmd +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202010112 +Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd wrote 196608/196608 bytes at offset 2147287040 192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 131072/131072 bytes at offset 2147352576 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 65536/65536 bytes at offset 2147418112 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 2202009600 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) Image committed. read 196608/196608 bytes at offset 2147287040 192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 2202009600 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) read 65536/65536 bytes at offset 2147287040 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) read 65536/65536 bytes at offset 2147352576 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) read 65536/65536 bytes at offset 2147418112 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 2202009600 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) Offset Length File 0x7ffd0000 0x30000 TEST_DIR/t.IMGFMT.base Offset Length File 0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base 0x7ffe0000 0x20000 TEST_DIR/t.IMGFMT.itmd +0x83400000 0x200 TEST_DIR/t.IMGFMT.itmd Offset Length File 0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base 0x7ffe0000 0x20000 TEST_DIR/t.IMGFMT.itmd +0x83400000 0x200 TEST_DIR/t.IMGFMT.itmd -=== Test pass 0.1 === +=== Test pass 1 === -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202009600 -Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202009600 backing_file=TEST_DIR/t.IMGFMT.base -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202009600 backing_file=TEST_DIR/t.IMGFMT.itmd -wrote 196608/196608 bytes at offset 2147287040 -192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -wrote 131072/131072 bytes at offset 2147352576 -128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -wrote 65536/65536 bytes at offset 2147418112 -64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Image committed. -read 196608/196608 bytes at offset 2147287040 -192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -read 65536/65536 bytes at offset 2147287040 -64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -read 65536/65536 bytes at offset 2147352576 -64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -read 65536/65536 bytes at offset 2147418112 -64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Offset Length File -0x7ffd0000 0x30000 TEST_DIR/t.IMGFMT.base -Offset Length File -0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base -0x7ffe0000 0x20000 TEST_DIR/t.IMGFMT.itmd -Offset Length File -0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base -0x7ffe0000 0x20000 TEST_DIR/t.IMGFMT.itmd - -=== Test pass 1.0 === - -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202009600 -Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202009600 backing_file=TEST_DIR/t.IMGFMT.base -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202009600 backing_file=TEST_DIR/t.IMGFMT.itmd -wrote 196608/196608 bytes at offset 2147287040 -192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -wrote 131072/131072 bytes at offset 2147352576 -128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -wrote 65536/65536 bytes at offset 2147418112 -64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Image committed. -read 196608/196608 bytes at offset 2147287040 -192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -read 65536/65536 bytes at offset 2147287040 -64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -read 65536/65536 bytes at offset 2147352576 -64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -read 65536/65536 bytes at offset 2147418112 -64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Offset Length File -0x7ffd0000 0x30000 TEST_DIR/t.IMGFMT.base -Offset Length File -0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base -0x7ffe0000 0x20000 TEST_DIR/t.IMGFMT.itmd -Offset Length File -0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base -0x7ffe0000 0x10000 TEST_DIR/t.IMGFMT.itmd -0x7fff0000 0x10000 TEST_DIR/t.IMGFMT - -=== Test pass 1.1 === - -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202009600 -Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202009600 backing_file=TEST_DIR/t.IMGFMT.base -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202009600 backing_file=TEST_DIR/t.IMGFMT.itmd +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202010112 +Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd wrote 196608/196608 bytes at offset 2147287040 192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 131072/131072 bytes at offset 2147352576 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 65536/65536 bytes at offset 2147418112 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 2202009600 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) Image committed. read 196608/196608 bytes at offset 2147287040 192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 2202009600 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) read 65536/65536 bytes at offset 2147287040 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) read 65536/65536 bytes at offset 2147352576 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) read 65536/65536 bytes at offset 2147418112 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 2202009600 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) Offset Length File 0x7ffd0000 0x30000 TEST_DIR/t.IMGFMT.base Offset Length File 0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base 0x7ffe0000 0x20000 TEST_DIR/t.IMGFMT.itmd +0x83400000 0x200 TEST_DIR/t.IMGFMT.itmd Offset Length File 0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base 0x7ffe0000 0x10000 TEST_DIR/t.IMGFMT.itmd 0x7fff0000 0x10000 TEST_DIR/t.IMGFMT +0x83400000 0x200 TEST_DIR/t.IMGFMT -=== Test pass 2.0 === +=== Test pass 2 === -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202009600 -Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202009600 backing_file=TEST_DIR/t.IMGFMT.base -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202009600 backing_file=TEST_DIR/t.IMGFMT.itmd +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202010112 +Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd wrote 196608/196608 bytes at offset 2147287040 192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 131072/131072 bytes at offset 2147352576 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 65536/65536 bytes at offset 2147418112 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 2202009600 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) Image committed. read 196608/196608 bytes at offset 2147287040 192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 2202009600 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) read 65536/65536 bytes at offset 2147287040 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) read 65536/65536 bytes at offset 2147352576 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) read 65536/65536 bytes at offset 2147418112 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 2202009600 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) Offset Length File 0x7ffd0000 0x30000 TEST_DIR/t.IMGFMT.base Offset Length File 0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base 0x7ffe0000 0x20000 TEST_DIR/t.IMGFMT.itmd +0x83400000 0x200 TEST_DIR/t.IMGFMT.itmd Offset Length File 0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base 0x7ffe0000 0x10000 TEST_DIR/t.IMGFMT.itmd 0x7fff0000 0x10000 TEST_DIR/t.IMGFMT +0x83400000 0x200 TEST_DIR/t.IMGFMT -=== Test pass 2.1 === - -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202009600 -Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202009600 backing_file=TEST_DIR/t.IMGFMT.base -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202009600 backing_file=TEST_DIR/t.IMGFMT.itmd -wrote 196608/196608 bytes at offset 2147287040 -192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -wrote 131072/131072 bytes at offset 2147352576 -128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -wrote 65536/65536 bytes at offset 2147418112 -64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Image committed. -read 196608/196608 bytes at offset 2147287040 -192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -read 65536/65536 bytes at offset 2147287040 -64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -read 65536/65536 bytes at offset 2147352576 -64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -read 65536/65536 bytes at offset 2147418112 -64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Offset Length File -0x7ffd0000 0x30000 TEST_DIR/t.IMGFMT.base -Offset Length File -0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base -0x7ffe0000 0x20000 TEST_DIR/t.IMGFMT.itmd -Offset Length File -0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base -0x7ffe0000 0x10000 TEST_DIR/t.IMGFMT.itmd -0x7fff0000 0x10000 TEST_DIR/t.IMGFMT - -=== Test pass 3.0 === - -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202009600 -Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202009600 backing_file=TEST_DIR/t.IMGFMT.base -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202009600 backing_file=TEST_DIR/t.IMGFMT.itmd -wrote 196608/196608 bytes at offset 2147287040 -192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -wrote 131072/131072 bytes at offset 2147352576 -128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -wrote 65536/65536 bytes at offset 2147418112 -64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Image committed. -read 65536/65536 bytes at offset 2147287040 -64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -read 65536/65536 bytes at offset 2147352576 -64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -read 65536/65536 bytes at offset 2147418112 -64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Offset Length File -0x7ffd0000 0x30000 TEST_DIR/t.IMGFMT.base -Offset Length File -0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base -0x7ffe0000 0x20000 TEST_DIR/t.IMGFMT.itmd -Offset Length File -0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base -0x7ffe0000 0x10000 TEST_DIR/t.IMGFMT.itmd -0x7fff0000 0x10000 TEST_DIR/t.IMGFMT - -=== Test pass 3.1 === +=== Test pass 3 === -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202009600 -Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202009600 backing_file=TEST_DIR/t.IMGFMT.base -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202009600 backing_file=TEST_DIR/t.IMGFMT.itmd +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202010112 +Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd wrote 196608/196608 bytes at offset 2147287040 192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 131072/131072 bytes at offset 2147352576 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 65536/65536 bytes at offset 2147418112 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 2202009600 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) Image committed. read 65536/65536 bytes at offset 2147287040 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) @@ -224,13 +133,18 @@ read 65536/65536 bytes at offset 2147352576 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) read 65536/65536 bytes at offset 2147418112 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 2202009600 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) Offset Length File 0x7ffd0000 0x30000 TEST_DIR/t.IMGFMT.base +0x83400000 0x200 TEST_DIR/t.IMGFMT.base Offset Length File 0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base 0x7ffe0000 0x20000 TEST_DIR/t.IMGFMT.itmd +0x83400000 0x200 TEST_DIR/t.IMGFMT.base Offset Length File 0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base 0x7ffe0000 0x10000 TEST_DIR/t.IMGFMT.itmd 0x7fff0000 0x10000 TEST_DIR/t.IMGFMT +0x83400000 0x200 TEST_DIR/t.IMGFMT *** done diff --git a/tests/qemu-iotests/147 b/tests/qemu-iotests/147 index cca75c562c..32afea63d4 100755 --- a/tests/qemu-iotests/147 +++ b/tests/qemu-iotests/147 @@ -30,6 +30,13 @@ NBD_PORT = 10811 test_img = os.path.join(iotests.test_dir, 'test.img') unix_socket = os.path.join(iotests.test_dir, 'nbd.socket') + +def flatten_sock_addr(crumpled_address): + result = { 'type': crumpled_address['type'] } + result.update(crumpled_address['data']) + return result + + class NBDBlockdevAddBase(iotests.QMPTestCase): def blockdev_add_options(self, address, export=None): options = { 'node-name': 'nbd-blockdev', @@ -85,13 +92,15 @@ class QemuNBD(NBDBlockdevAddBase): 'host': 'localhost', 'port': str(NBD_PORT) } } - self.client_test('nbd://localhost:%i' % NBD_PORT, address) + self.client_test('nbd://localhost:%i' % NBD_PORT, + flatten_sock_addr(address)) def test_unix(self): self._server_up('-k', unix_socket) address = { 'type': 'unix', 'data': { 'path': unix_socket } } - self.client_test('nbd+unix://?socket=' + unix_socket, address) + self.client_test('nbd+unix://?socket=' + unix_socket, + flatten_sock_addr(address)) class BuiltinNBD(NBDBlockdevAddBase): @@ -134,7 +143,7 @@ class BuiltinNBD(NBDBlockdevAddBase): } } self._server_up(address) self.client_test('nbd://localhost:%i/nbd-export' % NBD_PORT, - address, 'nbd-export') + flatten_sock_addr(address), 'nbd-export') self._server_down() def test_inet6(self): @@ -149,10 +158,10 @@ class BuiltinNBD(NBDBlockdevAddBase): 'file': { 'driver': 'nbd', 'export': 'nbd-export', - 'server': address + 'server': flatten_sock_addr(address) } } self._server_up(address) - self.client_test(filename, address, 'nbd-export') + self.client_test(filename, flatten_sock_addr(address), 'nbd-export') self._server_down() def test_unix(self): @@ -160,7 +169,7 @@ class BuiltinNBD(NBDBlockdevAddBase): 'data': { 'path': unix_socket } } self._server_up(address) self.client_test('nbd+unix:///nbd-export?socket=' + unix_socket, - address, 'nbd-export') + flatten_sock_addr(address), 'nbd-export') self._server_down() def test_fd(self): @@ -182,9 +191,9 @@ class BuiltinNBD(NBDBlockdevAddBase): 'file': { 'driver': 'nbd', 'export': 'nbd-export', - 'server': address + 'server': flatten_sock_addr(address) } } - self.client_test(filename, address, 'nbd-export') + self.client_test(filename, flatten_sock_addr(address), 'nbd-export') self._server_down() diff --git a/tests/qemu-iotests/176 b/tests/qemu-iotests/176 new file mode 100755 index 0000000000..950b28720e --- /dev/null +++ b/tests/qemu-iotests/176 @@ -0,0 +1,131 @@ +#!/bin/bash +# +# Commit changes into backing chains and empty the top image if the +# backing image is not explicitly specified. +# +# Variant of 097, which includes snapshots to test different codepath +# in qcow2 +# +# Copyright (C) 2014 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# creator +owner=mreitz@redhat.com + +seq="$(basename $0)" +echo "QA output created by $seq" + +here="$PWD" +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img + _rm_test_img "$TEST_IMG.itmd" +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter +. ./common.pattern + +# Any format supporting backing files and bdrv_make_empty +_supported_fmt qcow2 +_supported_proto file +_supported_os Linux + + +# Four passes: +# 0: Two-layer backing chain, commit to upper backing file (implicitly) +# (in this case, the top image will be emptied) +# 1: Two-layer backing chain, commit to upper backing file (explicitly) +# (in this case, the top image will implicitly stay unchanged) +# 2: Two-layer backing chain, commit to upper backing file (implicitly with -d) +# (in this case, the top image will explicitly stay unchanged) +# 3: Two-layer backing chain, commit to lower backing file +# (in this case, the top image will implicitly stay unchanged) +# +# 020 already tests committing, so this only tests whether image chains are +# working properly and that all images above the base are emptied; therefore, +# no complicated patterns are necessary. Check near the 2G mark, as qcow2 +# has been buggy at that boundary in the past. +for i in 0 1 2 3; do + +echo +echo "=== Test pass $i ===" +echo + +len=$((2100 * 1024 * 1024 + 512)) # larger than 2G, and not cluster aligned +TEST_IMG="$TEST_IMG.base" _make_test_img $len +TEST_IMG="$TEST_IMG.itmd" _make_test_img -b "$TEST_IMG.base" $len +_make_test_img -b "$TEST_IMG.itmd" $len +$QEMU_IMG snapshot -c snap "$TEST_IMG" + +$QEMU_IO -c "write -P 1 0x7ffd0000 192k" "$TEST_IMG.base" | _filter_qemu_io +$QEMU_IO -c "write -P 2 0x7ffe0000 128k" "$TEST_IMG.itmd" | _filter_qemu_io +$QEMU_IO -c "write -P 3 0x7fff0000 64k" "$TEST_IMG" | _filter_qemu_io +$QEMU_IO -c "write -P 4 $(($len - 512)) 512" "$TEST_IMG" | _filter_qemu_io + +if [ $i -lt 3 ]; then + if [ $i == 0 ]; then + # -b "$TEST_IMG.itmd" should be the default (that is, committing to the + # first backing file in the chain) + $QEMU_IMG commit "$TEST_IMG" + elif [ $i == 1 ]; then + # explicitly specify the commit target (this should imply -d) + $QEMU_IMG commit -b "$TEST_IMG.itmd" "$TEST_IMG" + else + # do not explicitly specify the commit target, but use -d to leave the + # top image unchanged + $QEMU_IMG commit -d "$TEST_IMG" + fi + + # Bottom should be unchanged + $QEMU_IO -c 'read -P 1 0x7ffd0000 192k' "$TEST_IMG.base" | _filter_qemu_io + $QEMU_IO -c "read -P 0 $((len - 512)) 512" "$TEST_IMG.base" | _filter_qemu_io + + # Intermediate should contain changes from top + $QEMU_IO -c 'read -P 1 0x7ffd0000 64k' "$TEST_IMG.itmd" | _filter_qemu_io + $QEMU_IO -c 'read -P 2 0x7ffe0000 64k' "$TEST_IMG.itmd" | _filter_qemu_io + $QEMU_IO -c 'read -P 3 0x7fff0000 64k' "$TEST_IMG.itmd" | _filter_qemu_io + $QEMU_IO -c "read -P 4 $((len - 512)) 512" "$TEST_IMG.itmd" | _filter_qemu_io + + # And in pass 0, the top image should be empty, whereas in both other passes + # it should be unchanged (which is both checked by qemu-img map) +else + $QEMU_IMG commit -b "$TEST_IMG.base" "$TEST_IMG" + + # Bottom should contain all changes + $QEMU_IO -c 'read -P 1 0x7ffd0000 64k' "$TEST_IMG.base" | _filter_qemu_io + $QEMU_IO -c 'read -P 2 0x7ffe0000 64k' "$TEST_IMG.base" | _filter_qemu_io + $QEMU_IO -c 'read -P 3 0x7fff0000 64k' "$TEST_IMG.base" | _filter_qemu_io + $QEMU_IO -c "read -P 4 $((len - 512)) 512" "$TEST_IMG.base" | _filter_qemu_io + + # Both top and intermediate should be unchanged +fi + +$QEMU_IMG map "$TEST_IMG.base" | _filter_qemu_img_map +$QEMU_IMG map "$TEST_IMG.itmd" | _filter_qemu_img_map +$QEMU_IMG map "$TEST_IMG" | _filter_qemu_img_map + +done + + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/176.out b/tests/qemu-iotests/176.out new file mode 100644 index 0000000000..6271fa7d6f --- /dev/null +++ b/tests/qemu-iotests/176.out @@ -0,0 +1,150 @@ +QA output created by 176 + +=== Test pass 0 === + +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202010112 +Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd +wrote 196608/196608 bytes at offset 2147287040 +192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 131072/131072 bytes at offset 2147352576 +128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 65536/65536 bytes at offset 2147418112 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 2202009600 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Image committed. +read 196608/196608 bytes at offset 2147287040 +192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 2202009600 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 65536/65536 bytes at offset 2147287040 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 65536/65536 bytes at offset 2147352576 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 65536/65536 bytes at offset 2147418112 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 2202009600 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Offset Length File +0x7ffd0000 0x30000 TEST_DIR/t.IMGFMT.base +Offset Length File +0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base +0x7ffe0000 0x20000 TEST_DIR/t.IMGFMT.itmd +0x83400000 0x200 TEST_DIR/t.IMGFMT.itmd +Offset Length File +0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base +0x7ffe0000 0x20000 TEST_DIR/t.IMGFMT.itmd +0x83400000 0x200 TEST_DIR/t.IMGFMT.itmd + +=== Test pass 1 === + +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202010112 +Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd +wrote 196608/196608 bytes at offset 2147287040 +192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 131072/131072 bytes at offset 2147352576 +128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 65536/65536 bytes at offset 2147418112 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 2202009600 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Image committed. +read 196608/196608 bytes at offset 2147287040 +192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 2202009600 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 65536/65536 bytes at offset 2147287040 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 65536/65536 bytes at offset 2147352576 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 65536/65536 bytes at offset 2147418112 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 2202009600 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Offset Length File +0x7ffd0000 0x30000 TEST_DIR/t.IMGFMT.base +Offset Length File +0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base +0x7ffe0000 0x20000 TEST_DIR/t.IMGFMT.itmd +0x83400000 0x200 TEST_DIR/t.IMGFMT.itmd +Offset Length File +0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base +0x7ffe0000 0x10000 TEST_DIR/t.IMGFMT.itmd +0x7fff0000 0x10000 TEST_DIR/t.IMGFMT +0x83400000 0x200 TEST_DIR/t.IMGFMT + +=== Test pass 2 === + +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202010112 +Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd +wrote 196608/196608 bytes at offset 2147287040 +192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 131072/131072 bytes at offset 2147352576 +128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 65536/65536 bytes at offset 2147418112 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 2202009600 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Image committed. +read 196608/196608 bytes at offset 2147287040 +192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 2202009600 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 65536/65536 bytes at offset 2147287040 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 65536/65536 bytes at offset 2147352576 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 65536/65536 bytes at offset 2147418112 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 2202009600 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Offset Length File +0x7ffd0000 0x30000 TEST_DIR/t.IMGFMT.base +Offset Length File +0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base +0x7ffe0000 0x20000 TEST_DIR/t.IMGFMT.itmd +0x83400000 0x200 TEST_DIR/t.IMGFMT.itmd +Offset Length File +0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base +0x7ffe0000 0x10000 TEST_DIR/t.IMGFMT.itmd +0x7fff0000 0x10000 TEST_DIR/t.IMGFMT +0x83400000 0x200 TEST_DIR/t.IMGFMT + +=== Test pass 3 === + +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=2202010112 +Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.base +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2202010112 backing_file=TEST_DIR/t.IMGFMT.itmd +wrote 196608/196608 bytes at offset 2147287040 +192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 131072/131072 bytes at offset 2147352576 +128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 65536/65536 bytes at offset 2147418112 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 512/512 bytes at offset 2202009600 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Image committed. +read 65536/65536 bytes at offset 2147287040 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 65536/65536 bytes at offset 2147352576 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 65536/65536 bytes at offset 2147418112 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 2202009600 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Offset Length File +0x7ffd0000 0x30000 TEST_DIR/t.IMGFMT.base +0x83400000 0x200 TEST_DIR/t.IMGFMT.base +Offset Length File +0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base +0x7ffe0000 0x20000 TEST_DIR/t.IMGFMT.itmd +0x83400000 0x200 TEST_DIR/t.IMGFMT.base +Offset Length File +0x7ffd0000 0x10000 TEST_DIR/t.IMGFMT.base +0x7ffe0000 0x10000 TEST_DIR/t.IMGFMT.itmd +0x7fff0000 0x10000 TEST_DIR/t.IMGFMT +0x83400000 0x200 TEST_DIR/t.IMGFMT +*** done diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index 1f4bf03185..43142ddfcf 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -168,3 +168,4 @@ 173 rw auto 174 auto 175 auto quick +176 rw auto backing @@ -129,10 +129,13 @@ static void vnc_init_basic_info(SocketAddress *addr, info->family = NETWORK_ADDRESS_FAMILY_UNIX; break; - default: - error_setg(errp, "Unsupported socket kind %d", - addr->type); + case SOCKET_ADDRESS_KIND_VSOCK: + case SOCKET_ADDRESS_KIND_FD: + error_setg(errp, "Unsupported socket address type %s", + SocketAddressKind_lookup[addr->type]); break; + default: + abort(); } return; @@ -411,10 +414,13 @@ VncInfo *qmp_query_vnc(Error **errp) info->family = NETWORK_ADDRESS_FAMILY_UNIX; break; - default: - error_setg(errp, "Unsupported socket kind %d", - addr->type); + case SOCKET_ADDRESS_KIND_VSOCK: + case SOCKET_ADDRESS_KIND_FD: + error_setg(errp, "Unsupported socket address type %s", + SocketAddressKind_lookup[addr->type]); goto out_error; + default: + abort(); } info->has_host = true; @@ -3642,6 +3648,7 @@ static int vnc_display_connect(VncDisplay *vd, error_setg(errp, "Expected a single address in reverse mode"); return -1; } + /* TODO SOCKET_ADDRESS_KIND_FD when fd has AF_UNIX */ vd->is_unix = saddr[0]->type == SOCKET_ADDRESS_KIND_UNIX; sioc = qio_channel_socket_new(); qio_channel_set_name(QIO_CHANNEL(sioc), "vnc-reverse"); diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c index 40164bf681..21442c30dc 100644 --- a/util/qemu-sockets.c +++ b/util/qemu-sockets.c @@ -25,6 +25,7 @@ #include "qapi/error.h" #include "qemu/sockets.h" #include "qemu/main-loop.h" +#include "qapi/clone-visitor.h" #include "qapi/qobject-input-visitor.h" #include "qapi/qobject-output-visitor.h" #include "qapi-visit.h" @@ -1154,6 +1155,10 @@ int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp) { int fd; + /* + * TODO SOCKET_ADDRESS_KIND_FD when fd is AF_INET or AF_INET6 + * (although other address families can do SOCK_DGRAM, too) + */ switch (remote->type) { case SOCKET_ADDRESS_KIND_INET: fd = inet_dgram_saddr(remote->u.inet.data, @@ -1333,9 +1338,38 @@ char *socket_address_to_string(struct SocketAddress *addr, Error **errp) break; default: - error_setg(errp, "socket family %d unsupported", - addr->type); - return NULL; + abort(); } return buf; } + +SocketAddress *socket_address_crumple(SocketAddressFlat *addr_flat) +{ + SocketAddress *addr = g_new(SocketAddress, 1); + + switch (addr_flat->type) { + case SOCKET_ADDRESS_FLAT_TYPE_INET: + addr->type = SOCKET_ADDRESS_KIND_INET; + addr->u.inet.data = QAPI_CLONE(InetSocketAddress, + &addr_flat->u.inet); + break; + case SOCKET_ADDRESS_FLAT_TYPE_UNIX: + addr->type = SOCKET_ADDRESS_KIND_UNIX; + addr->u.q_unix.data = QAPI_CLONE(UnixSocketAddress, + &addr_flat->u.q_unix); + break; + case SOCKET_ADDRESS_FLAT_TYPE_VSOCK: + addr->type = SOCKET_ADDRESS_KIND_VSOCK; + addr->u.vsock.data = QAPI_CLONE(VsockSocketAddress, + &addr_flat->u.vsock); + break; + case SOCKET_ADDRESS_FLAT_TYPE_FD: + addr->type = SOCKET_ADDRESS_KIND_FD; + addr->u.fd.data = QAPI_CLONE(String, &addr_flat->u.fd); + break; + default: + abort(); + } + + return addr; +} |