diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2015-12-18 16:34:44 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2015-12-18 16:34:44 +0000 |
commit | de532ff1df75cc80f0fb30885524e54b014d4983 (patch) | |
tree | 54c95dbb3a1da01df51886054694d5fec1f98f6b | |
parent | b06f904f2e37eb2a9ab0a8344faec7e5d609508a (diff) | |
parent | 9d4a6cf0ea471fb5aeaba9360fec863ef8a0ab44 (diff) | |
download | qemu-de532ff1df75cc80f0fb30885524e54b014d4983.zip qemu-de532ff1df75cc80f0fb30885524e54b014d4983.tar.gz qemu-de532ff1df75cc80f0fb30885524e54b014d4983.tar.bz2 |
Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging
Block layer patches
# gpg: Signature made Fri 18 Dec 2015 13:41:03 GMT using RSA key ID C88F2FD6
# gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>"
* remotes/kevin/tags/for-upstream: (48 commits)
block/qapi: allow best-effort query
qemu-img: abort when full_backing_filename not present
block/qapi: explicitly warn if !has_full_backing_filename
block/qapi: always report full_backing_filename
block/qapi: do not redundantly print "actual path"
qemu-iotests: s390x: fix test 068
qemu-iotests: s390x: fix test 051
qemu-iotests: refine common.config
block: fix bdrv_ioctl called from coroutine
block: use drained section around bdrv_snapshot_delete
iotests: Update comments for bdrv_swap() in 094
block: Remove prototype of bdrv_swap from header
raw-posix: Make aio=native option binding
qcow2: insert assert into qcow2_get_specific_info()
iotests: Extend test 112 for qemu-img amend
qcow2: Point to amend function in check
qcow2: Invoke refcount order amendment function
qcow2: Add function for refcount order amendment
qcow2: Use intermediate helper CB for amend
qcow2: Split upgrade/downgrade paths for amend
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
38 files changed, 3326 insertions, 466 deletions
@@ -29,6 +29,7 @@ #include "qemu/error-report.h" #include "qemu/module.h" #include "qapi/qmp/qerror.h" +#include "qapi/qmp/qbool.h" #include "qapi/qmp/qjson.h" #include "sysemu/block-backend.h" #include "sysemu/sysemu.h" @@ -624,6 +625,20 @@ static int refresh_total_sectors(BlockDriverState *bs, int64_t hint) } /** + * Combines a QDict of new block driver @options with any missing options taken + * from @old_options, so that leaving out an option defaults to its old value. + */ +static void bdrv_join_options(BlockDriverState *bs, QDict *options, + QDict *old_options) +{ + if (bs->drv && bs->drv->bdrv_join_options) { + bs->drv->bdrv_join_options(options, old_options); + } else { + qdict_join(options, old_options, false); + } +} + +/** * Set open flags for a given discard mode * * Return 0 on success, -1 if the discard mode was invalid. @@ -681,60 +696,81 @@ static int bdrv_temp_snapshot_flags(int flags) } /* - * Returns the flags that bs->file should get if a protocol driver is expected, - * based on the given flags for the parent BDS + * Returns the options and flags that bs->file should get if a protocol driver + * is expected, based on the given options and flags for the parent BDS */ -static int bdrv_inherited_flags(int flags) +static void bdrv_inherited_options(int *child_flags, QDict *child_options, + int parent_flags, QDict *parent_options) { + int flags = parent_flags; + /* Enable protocol handling, disable format probing for bs->file */ flags |= BDRV_O_PROTOCOL; + /* If the cache mode isn't explicitly set, inherit direct and no-flush from + * the parent. */ + qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_DIRECT); + qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_NO_FLUSH); + /* Our block drivers take care to send flushes and respect unmap policy, - * so we can enable both unconditionally on lower layers. */ - flags |= BDRV_O_CACHE_WB | BDRV_O_UNMAP; + * so we can default to enable both on lower layers regardless of the + * corresponding parent options. */ + qdict_set_default_str(child_options, BDRV_OPT_CACHE_WB, "on"); + flags |= BDRV_O_UNMAP; /* Clear flags that only apply to the top layer */ flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING | BDRV_O_COPY_ON_READ); - return flags; + *child_flags = flags; } const BdrvChildRole child_file = { - .inherit_flags = bdrv_inherited_flags, + .inherit_options = bdrv_inherited_options, }; /* - * Returns the flags that bs->file should get if the use of formats (and not - * only protocols) is permitted for it, based on the given flags for the parent - * BDS + * Returns the options and flags that bs->file should get if the use of formats + * (and not only protocols) is permitted for it, based on the given options and + * flags for the parent BDS */ -static int bdrv_inherited_fmt_flags(int parent_flags) +static void bdrv_inherited_fmt_options(int *child_flags, QDict *child_options, + int parent_flags, QDict *parent_options) { - int flags = child_file.inherit_flags(parent_flags); - return flags & ~BDRV_O_PROTOCOL; + child_file.inherit_options(child_flags, child_options, + parent_flags, parent_options); + + *child_flags &= ~BDRV_O_PROTOCOL; } const BdrvChildRole child_format = { - .inherit_flags = bdrv_inherited_fmt_flags, + .inherit_options = bdrv_inherited_fmt_options, }; /* - * Returns the flags that bs->backing should get, based on the given flags - * for the parent BDS + * Returns the options and flags that bs->backing should get, based on the + * given options and flags for the parent BDS */ -static int bdrv_backing_flags(int flags) +static void bdrv_backing_options(int *child_flags, QDict *child_options, + int parent_flags, QDict *parent_options) { + int flags = parent_flags; + + /* The cache mode is inherited unmodified for backing files */ + qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_WB); + qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_DIRECT); + qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_NO_FLUSH); + /* backing files always opened read-only */ flags &= ~(BDRV_O_RDWR | BDRV_O_COPY_ON_READ); /* snapshot=on is handled on the top layer */ flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_TEMPORARY); - return flags; + *child_flags = flags; } static const BdrvChildRole child_backing = { - .inherit_flags = bdrv_backing_flags, + .inherit_options = bdrv_backing_options, }; static int bdrv_open_flags(BlockDriverState *bs, int flags) @@ -757,6 +793,42 @@ static int bdrv_open_flags(BlockDriverState *bs, int flags) return open_flags; } +static void update_flags_from_options(int *flags, QemuOpts *opts) +{ + *flags &= ~BDRV_O_CACHE_MASK; + + assert(qemu_opt_find(opts, BDRV_OPT_CACHE_WB)); + if (qemu_opt_get_bool(opts, BDRV_OPT_CACHE_WB, false)) { + *flags |= BDRV_O_CACHE_WB; + } + + assert(qemu_opt_find(opts, BDRV_OPT_CACHE_NO_FLUSH)); + if (qemu_opt_get_bool(opts, BDRV_OPT_CACHE_NO_FLUSH, false)) { + *flags |= BDRV_O_NO_FLUSH; + } + + assert(qemu_opt_find(opts, BDRV_OPT_CACHE_DIRECT)); + if (qemu_opt_get_bool(opts, BDRV_OPT_CACHE_DIRECT, false)) { + *flags |= BDRV_O_NOCACHE; + } +} + +static void update_options_from_flags(QDict *options, int flags) +{ + if (!qdict_haskey(options, BDRV_OPT_CACHE_WB)) { + qdict_put(options, BDRV_OPT_CACHE_WB, + qbool_from_bool(flags & BDRV_O_CACHE_WB)); + } + if (!qdict_haskey(options, BDRV_OPT_CACHE_DIRECT)) { + qdict_put(options, BDRV_OPT_CACHE_DIRECT, + qbool_from_bool(flags & BDRV_O_NOCACHE)); + } + if (!qdict_haskey(options, BDRV_OPT_CACHE_NO_FLUSH)) { + qdict_put(options, BDRV_OPT_CACHE_NO_FLUSH, + qbool_from_bool(flags & BDRV_O_NO_FLUSH)); + } +} + static void bdrv_assign_node_name(BlockDriverState *bs, const char *node_name, Error **errp) @@ -803,6 +875,26 @@ static QemuOptsList bdrv_runtime_opts = { .type = QEMU_OPT_STRING, .help = "Node name of the block device node", }, + { + .name = "driver", + .type = QEMU_OPT_STRING, + .help = "Block driver to use for the node", + }, + { + .name = BDRV_OPT_CACHE_WB, + .type = QEMU_OPT_BOOL, + .help = "Enable writeback mode", + }, + { + .name = BDRV_OPT_CACHE_DIRECT, + .type = QEMU_OPT_BOOL, + .help = "Bypass software writeback cache on the host", + }, + { + .name = BDRV_OPT_CACHE_NO_FLUSH, + .type = QEMU_OPT_BOOL, + .help = "Ignore flush requests", + }, { /* end of list */ } }, }; @@ -813,18 +905,31 @@ static QemuOptsList bdrv_runtime_opts = { * Removes all processed options from *options. */ static int bdrv_open_common(BlockDriverState *bs, BdrvChild *file, - QDict *options, int flags, BlockDriver *drv, Error **errp) + QDict *options, int flags, Error **errp) { int ret, open_flags; const char *filename; + const char *driver_name = NULL; const char *node_name = NULL; QemuOpts *opts; + BlockDriver *drv; Error *local_err = NULL; - assert(drv != NULL); assert(bs->file == NULL); assert(options != NULL && bs->options != options); + opts = qemu_opts_create(&bdrv_runtime_opts, NULL, 0, &error_abort); + qemu_opts_absorb_qdict(opts, options, &local_err); + if (local_err) { + error_propagate(errp, local_err); + ret = -EINVAL; + goto fail_opts; + } + + driver_name = qemu_opt_get(opts, "driver"); + drv = bdrv_find_format(driver_name); + assert(drv != NULL); + if (file != NULL) { filename = file->bs->filename; } else { @@ -834,19 +939,12 @@ static int bdrv_open_common(BlockDriverState *bs, BdrvChild *file, if (drv->bdrv_needs_filename && !filename) { error_setg(errp, "The '%s' block driver requires a file name", drv->format_name); - return -EINVAL; - } - - trace_bdrv_open_common(bs, filename ?: "", flags, drv->format_name); - - opts = qemu_opts_create(&bdrv_runtime_opts, NULL, 0, &error_abort); - qemu_opts_absorb_qdict(opts, options, &local_err); - if (local_err) { - error_propagate(errp, local_err); ret = -EINVAL; goto fail_opts; } + trace_bdrv_open_common(bs, filename ?: "", flags, drv->format_name); + node_name = qemu_opt_get(opts, "node-name"); bdrv_assign_node_name(bs, node_name, &local_err); if (local_err) { @@ -891,7 +989,9 @@ static int bdrv_open_common(BlockDriverState *bs, BdrvChild *file, bs->drv = drv; bs->opaque = g_malloc0(drv->instance_size); - bs->enable_write_cache = !!(flags & BDRV_O_CACHE_WB); + /* Apply cache mode options */ + update_flags_from_options(&bs->open_flags, opts); + bdrv_set_enable_write_cache(bs, bs->open_flags & BDRV_O_CACHE_WB); /* Open the image, either directly or using a protocol */ if (drv->bdrv_file_open) { @@ -984,37 +1084,45 @@ static QDict *parse_json_filename(const char *filename, Error **errp) return options; } +static void parse_json_protocol(QDict *options, const char **pfilename, + Error **errp) +{ + QDict *json_options; + Error *local_err = NULL; + + /* Parse json: pseudo-protocol */ + if (!*pfilename || !g_str_has_prefix(*pfilename, "json:")) { + return; + } + + json_options = parse_json_filename(*pfilename, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + /* Options given in the filename have lower priority than options + * specified directly */ + qdict_join(options, json_options, false); + QDECREF(json_options); + *pfilename = NULL; +} + /* * Fills in default options for opening images and converts the legacy * filename/flags pair to option QDict entries. * The BDRV_O_PROTOCOL flag in *flags will be set or cleared accordingly if a * block driver has been specified explicitly. */ -static int bdrv_fill_options(QDict **options, const char **pfilename, +static int bdrv_fill_options(QDict **options, const char *filename, int *flags, Error **errp) { - const char *filename = *pfilename; const char *drvname; bool protocol = *flags & BDRV_O_PROTOCOL; bool parse_filename = false; BlockDriver *drv = NULL; Error *local_err = NULL; - /* Parse json: pseudo-protocol */ - if (filename && g_str_has_prefix(filename, "json:")) { - QDict *json_options = parse_json_filename(filename, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return -EINVAL; - } - - /* Options given in the filename have lower priority than options - * specified directly */ - qdict_join(*options, json_options, false); - QDECREF(json_options); - *pfilename = filename = NULL; - } - drvname = qdict_get_try_str(*options, "driver"); if (drvname) { drv = bdrv_find_format(drvname); @@ -1033,6 +1141,9 @@ static int bdrv_fill_options(QDict **options, const char **pfilename, *flags &= ~BDRV_O_PROTOCOL; } + /* Translate cache options from flags into options */ + update_options_from_flags(*options, *flags); + /* Fetch the file name from the options QDict if necessary */ if (protocol && filename) { if (!qdict_haskey(*options, "filename")) { @@ -1087,11 +1198,13 @@ static int bdrv_fill_options(QDict **options, const char **pfilename, static BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs, BlockDriverState *child_bs, + const char *child_name, const BdrvChildRole *child_role) { BdrvChild *child = g_new(BdrvChild, 1); *child = (BdrvChild) { .bs = child_bs, + .name = g_strdup(child_name), .role = child_role, }; @@ -1105,6 +1218,7 @@ static void bdrv_detach_child(BdrvChild *child) { QLIST_REMOVE(child, next); QLIST_REMOVE(child, next_parent); + g_free(child->name); g_free(child); } @@ -1151,7 +1265,7 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd) bs->backing = NULL; goto out; } - bs->backing = bdrv_attach_child(bs, backing_hd, &child_backing); + bs->backing = bdrv_attach_child(bs, backing_hd, "backing", &child_backing); bs->open_flags &= ~BDRV_O_NO_BACKING; pstrcpy(bs->backing_file, sizeof(bs->backing_file), backing_hd->filename); pstrcpy(bs->backing_format, sizeof(bs->backing_format), @@ -1168,30 +1282,43 @@ out: /* * Opens the backing file for a BlockDriverState if not yet open * - * options is a QDict of options to pass to the block drivers, or NULL for an - * empty set of options. The reference to the QDict is transferred to this - * function (even on failure), so if the caller intends to reuse the dictionary, - * it needs to use QINCREF() before calling bdrv_file_open. + * bdref_key specifies the key for the image's BlockdevRef in the options QDict. + * That QDict has to be flattened; therefore, if the BlockdevRef is a QDict + * itself, all options starting with "${bdref_key}." are considered part of the + * BlockdevRef. + * + * TODO Can this be unified with bdrv_open_image()? */ -int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp) +int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options, + const char *bdref_key, Error **errp) { char *backing_filename = g_malloc0(PATH_MAX); + char *bdref_key_dot; + const char *reference = NULL; int ret = 0; BlockDriverState *backing_hd; + QDict *options; + QDict *tmp_parent_options = NULL; Error *local_err = NULL; if (bs->backing != NULL) { - QDECREF(options); goto free_exit; } /* NULL means an empty set of options */ - if (options == NULL) { - options = qdict_new(); + if (parent_options == NULL) { + tmp_parent_options = qdict_new(); + parent_options = tmp_parent_options; } bs->open_flags &= ~BDRV_O_NO_BACKING; - if (qdict_haskey(options, "file.filename")) { + + bdref_key_dot = g_strdup_printf("%s.", bdref_key); + qdict_extract_subqdict(parent_options, &options, bdref_key_dot); + g_free(bdref_key_dot); + + reference = qdict_get_try_str(parent_options, bdref_key); + if (reference || qdict_haskey(options, "file.filename")) { backing_filename[0] = '\0'; } else if (bs->backing_file[0] == '\0' && qdict_size(options) == 0) { QDECREF(options); @@ -1214,19 +1341,16 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp) goto free_exit; } - backing_hd = bdrv_new(); - if (bs->backing_format[0] != '\0' && !qdict_haskey(options, "driver")) { qdict_put(options, "driver", qstring_from_str(bs->backing_format)); } - assert(bs->backing == NULL); + backing_hd = NULL; ret = bdrv_open_inherit(&backing_hd, *backing_filename ? backing_filename : NULL, - NULL, options, 0, bs, &child_backing, &local_err); + reference, options, 0, bs, &child_backing, + &local_err); if (ret < 0) { - bdrv_unref(backing_hd); - backing_hd = NULL; bs->open_flags |= BDRV_O_NO_BACKING; error_setg(errp, "Could not open backing file: %s", error_get_pretty(local_err)); @@ -1239,8 +1363,11 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp) bdrv_set_backing_hd(bs, backing_hd); bdrv_unref(backing_hd); + qdict_del(parent_options, bdref_key); + free_exit: g_free(backing_filename); + QDECREF(tmp_parent_options); return ret; } @@ -1294,7 +1421,7 @@ BdrvChild *bdrv_open_child(const char *filename, goto done; } - c = bdrv_attach_child(parent, bs, child_role); + c = bdrv_attach_child(parent, bs, bdref_key, child_role); done: qdict_del(options, bdref_key); @@ -1437,21 +1564,34 @@ static int bdrv_open_inherit(BlockDriverState **pbs, const char *filename, options = qdict_new(); } + /* json: syntax counts as explicit options, as if in the QDict */ + parse_json_protocol(options, &filename, &local_err); + if (local_err) { + ret = -EINVAL; + goto fail; + } + + bs->explicit_options = qdict_clone_shallow(options); + if (child_role) { bs->inherits_from = parent; - flags = child_role->inherit_flags(parent->open_flags); + child_role->inherit_options(&flags, options, + parent->open_flags, parent->options); } - ret = bdrv_fill_options(&options, &filename, &flags, &local_err); + ret = bdrv_fill_options(&options, filename, &flags, &local_err); if (local_err) { goto fail; } + bs->open_flags = flags; + bs->options = options; + options = qdict_clone_shallow(options); + /* Find the right image format driver */ drvname = qdict_get_try_str(options, "driver"); if (drvname) { drv = bdrv_find_format(drvname); - qdict_del(options, "driver"); if (!drv) { error_setg(errp, "Unknown driver: '%s'", drvname); ret = -EINVAL; @@ -1467,10 +1607,6 @@ static int bdrv_open_inherit(BlockDriverState **pbs, const char *filename, qdict_del(options, "backing"); } - bs->open_flags = flags; - bs->options = options; - options = qdict_clone_shallow(options); - /* Open image file without format layer */ if ((flags & BDRV_O_PROTOCOL) == 0) { if (flags & BDRV_O_RDWR) { @@ -1478,7 +1614,7 @@ static int bdrv_open_inherit(BlockDriverState **pbs, const char *filename, } if (flags & BDRV_O_SNAPSHOT) { snapshot_flags = bdrv_temp_snapshot_flags(flags); - flags = bdrv_backing_flags(flags); + bdrv_backing_options(&flags, options, flags, options); } bs->open_flags = flags; @@ -1498,6 +1634,19 @@ static int bdrv_open_inherit(BlockDriverState **pbs, const char *filename, if (ret < 0) { goto fail; } + /* + * This option update would logically belong in bdrv_fill_options(), + * but we first need to open bs->file for the probing to work, while + * opening bs->file already requires the (mostly) final set of options + * so that cache mode etc. can be inherited. + * + * Adding the driver later is somewhat ugly, but it's not an option + * that would ever be inherited, so it's correct. We just need to make + * sure to update both bs->options (which has the full effective + * options for bs) and options (which has file.* already removed). + */ + qdict_put(bs->options, "driver", qstring_from_str(drv->format_name)); + qdict_put(options, "driver", qstring_from_str(drv->format_name)); } else if (!drv) { error_setg(errp, "Must specify either driver or file"); ret = -EINVAL; @@ -1511,7 +1660,7 @@ static int bdrv_open_inherit(BlockDriverState **pbs, const char *filename, assert(!(flags & BDRV_O_PROTOCOL) || !file); /* Open the image */ - ret = bdrv_open_common(bs, file, options, flags, drv, &local_err); + ret = bdrv_open_common(bs, file, options, flags, &local_err); if (ret < 0) { goto fail; } @@ -1523,10 +1672,7 @@ static int bdrv_open_inherit(BlockDriverState **pbs, const char *filename, /* If there is a backing file, use it */ if ((flags & BDRV_O_NO_BACKING) == 0) { - QDict *backing_options; - - qdict_extract_subqdict(options, &backing_options, "backing."); - ret = bdrv_open_backing_file(bs, backing_options, &local_err); + ret = bdrv_open_backing_file(bs, options, "backing", &local_err); if (ret < 0) { goto close_and_fail; } @@ -1581,6 +1727,7 @@ fail: if (file != NULL) { bdrv_unref_child(bs, file); } + QDECREF(bs->explicit_options); QDECREF(bs->options); QDECREF(options); bs->options = NULL; @@ -1643,15 +1790,19 @@ typedef struct BlockReopenQueueEntry { * bs_queue, or the existing bs_queue being used. * */ -BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue, - BlockDriverState *bs, - QDict *options, int flags) +static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue, + BlockDriverState *bs, + QDict *options, + int flags, + const BdrvChildRole *role, + QDict *parent_options, + int parent_flags) { assert(bs != NULL); BlockReopenQueueEntry *bs_entry; BdrvChild *child; - QDict *old_options; + QDict *old_options, *explicit_options; if (bs_queue == NULL) { bs_queue = g_new0(BlockReopenQueue, 1); @@ -1662,23 +1813,63 @@ BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue, options = qdict_new(); } + /* + * Precedence of options: + * 1. Explicitly passed in options (highest) + * 2. Set in flags (only for top level) + * 3. Retained from explicitly set options of bs + * 4. Inherited from parent node + * 5. Retained from effective options of bs + */ + + if (!parent_options) { + /* + * Any setting represented by flags is always updated. If the + * corresponding QDict option is set, it takes precedence. Otherwise + * the flag is translated into a QDict option. The old setting of bs is + * not considered. + */ + update_options_from_flags(options, flags); + } + + /* Old explicitly set values (don't overwrite by inherited value) */ + old_options = qdict_clone_shallow(bs->explicit_options); + bdrv_join_options(bs, options, old_options); + QDECREF(old_options); + + explicit_options = qdict_clone_shallow(options); + + /* Inherit from parent node */ + if (parent_options) { + assert(!flags); + role->inherit_options(&flags, options, parent_flags, parent_options); + } + + /* Old values are used for options that aren't set yet */ old_options = qdict_clone_shallow(bs->options); - qdict_join(options, old_options, false); + bdrv_join_options(bs, options, old_options); QDECREF(old_options); /* bdrv_open() masks this flag out */ flags &= ~BDRV_O_PROTOCOL; QLIST_FOREACH(child, &bs->children, next) { - int child_flags; + QDict *new_child_options; + char *child_key_dot; + /* reopen can only change the options of block devices that were + * implicitly created and inherited options. For other (referenced) + * block devices, a syntax like "backing.foo" results in an error. */ if (child->bs->inherits_from != bs) { continue; } - child_flags = child->role->inherit_flags(flags); - /* TODO Pass down child flags (backing.*, extents.*, ...) */ - bdrv_reopen_queue(bs_queue, child->bs, NULL, child_flags); + child_key_dot = g_strdup_printf("%s.", child->name); + qdict_extract_subqdict(options, &new_child_options, child_key_dot); + g_free(child_key_dot); + + bdrv_reopen_queue_child(bs_queue, child->bs, new_child_options, 0, + child->role, options, flags); } bs_entry = g_new0(BlockReopenQueueEntry, 1); @@ -1686,11 +1877,20 @@ BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue, bs_entry->state.bs = bs; bs_entry->state.options = options; + bs_entry->state.explicit_options = explicit_options; bs_entry->state.flags = flags; return bs_queue; } +BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue, + BlockDriverState *bs, + QDict *options, int flags) +{ + return bdrv_reopen_queue_child(bs_queue, bs, options, flags, + NULL, NULL, 0); +} + /* * Reopen multiple BlockDriverStates atomically & transactionally. * @@ -1737,6 +1937,8 @@ cleanup: QSIMPLEQ_FOREACH_SAFE(bs_entry, bs_queue, entry, next) { if (ret && bs_entry->prepared) { bdrv_reopen_abort(&bs_entry->state); + } else if (ret) { + QDECREF(bs_entry->state.explicit_options); } QDECREF(bs_entry->state.options); g_free(bs_entry); @@ -1784,11 +1986,47 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue, int ret = -1; Error *local_err = NULL; BlockDriver *drv; + QemuOpts *opts; + const char *value; assert(reopen_state != NULL); assert(reopen_state->bs->drv != NULL); drv = reopen_state->bs->drv; + /* Process generic block layer options */ + opts = qemu_opts_create(&bdrv_runtime_opts, NULL, 0, &error_abort); + qemu_opts_absorb_qdict(opts, reopen_state->options, &local_err); + if (local_err) { + error_propagate(errp, local_err); + ret = -EINVAL; + goto error; + } + + update_flags_from_options(&reopen_state->flags, opts); + + /* If a guest device is attached, it owns WCE */ + if (reopen_state->bs->blk && blk_get_attached_dev(reopen_state->bs->blk)) { + bool old_wce = bdrv_enable_write_cache(reopen_state->bs); + bool new_wce = (reopen_state->flags & BDRV_O_CACHE_WB); + if (old_wce != new_wce) { + error_setg(errp, "Cannot change cache.writeback: Device attached"); + ret = -EINVAL; + goto error; + } + } + + /* node-name and driver must be unchanged. Put them back into the QDict, so + * that they are checked at the end of this function. */ + value = qemu_opt_get(opts, "node-name"); + if (value) { + qdict_put(reopen_state->options, "node-name", qstring_from_str(value)); + } + + value = qemu_opt_get(opts, "driver"); + if (value) { + qdict_put(reopen_state->options, "driver", qstring_from_str(value)); + } + /* if we are to stay read-only, do not allow permission change * to r/w */ if (!(reopen_state->bs->open_flags & BDRV_O_ALLOW_RDWR) && @@ -1849,6 +2087,7 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue, ret = 0; error: + qemu_opts_del(opts); return ret; } @@ -1871,6 +2110,9 @@ void bdrv_reopen_commit(BDRVReopenState *reopen_state) } /* set BDS specific flags now */ + QDECREF(reopen_state->bs->explicit_options); + + reopen_state->bs->explicit_options = reopen_state->explicit_options; reopen_state->bs->open_flags = reopen_state->flags; reopen_state->bs->enable_write_cache = !!(reopen_state->flags & BDRV_O_CACHE_WB); @@ -1894,6 +2136,8 @@ void bdrv_reopen_abort(BDRVReopenState *reopen_state) if (drv->bdrv_reopen_abort) { drv->bdrv_reopen_abort(reopen_state); } + + QDECREF(reopen_state->explicit_options); } @@ -1952,6 +2196,7 @@ void bdrv_close(BlockDriverState *bs) bs->sg = 0; bs->zero_beyond_eof = false; QDECREF(bs->options); + QDECREF(bs->explicit_options); bs->options = NULL; QDECREF(bs->full_open_options); bs->full_open_options = NULL; @@ -3823,12 +4068,12 @@ void bdrv_remove_aio_context_notifier(BlockDriverState *bs, } int bdrv_amend_options(BlockDriverState *bs, QemuOpts *opts, - BlockDriverAmendStatusCB *status_cb) + BlockDriverAmendStatusCB *status_cb, void *cb_opaque) { if (!bs->drv->bdrv_amend_options) { return -ENOTSUP; } - return bs->drv->bdrv_amend_options(bs, opts, status_cb); + return bs->drv->bdrv_amend_options(bs, opts, status_cb, cb_opaque); } /* This function will be called by the bdrv_recurse_is_first_non_filter method @@ -3926,20 +4171,39 @@ out: static bool append_open_options(QDict *d, BlockDriverState *bs) { const QDictEntry *entry; + QemuOptDesc *desc; + BdrvChild *child; bool found_any = false; + const char *p; for (entry = qdict_first(bs->options); entry; entry = qdict_next(bs->options, entry)) { - /* Only take options for this level and exclude all non-driver-specific - * options */ - if (!strchr(qdict_entry_key(entry), '.') && - strcmp(qdict_entry_key(entry), "node-name")) - { - qobject_incref(qdict_entry_value(entry)); - qdict_put_obj(d, qdict_entry_key(entry), qdict_entry_value(entry)); - found_any = true; + /* Exclude options for children */ + QLIST_FOREACH(child, &bs->children, next) { + if (strstart(qdict_entry_key(entry), child->name, &p) + && (!*p || *p == '.')) + { + break; + } } + if (child) { + continue; + } + + /* And exclude all non-driver-specific options */ + for (desc = bdrv_runtime_opts.desc; desc->name; desc++) { + if (!strcmp(qdict_entry_key(entry), desc->name)) { + break; + } + } + if (desc->name) { + continue; + } + + qobject_incref(qdict_entry_value(entry)); + qdict_put_obj(d, qdict_entry_key(entry), qdict_entry_value(entry)); + found_any = true; } return found_any; @@ -3981,7 +4245,10 @@ void bdrv_refresh_filename(BlockDriverState *bs) bs->full_open_options = NULL; } - drv->bdrv_refresh_filename(bs); + opts = qdict_new(); + append_open_options(opts, bs); + drv->bdrv_refresh_filename(bs, opts); + QDECREF(opts); } else if (bs->file) { /* Try to reconstruct valid information from the underlying file */ bool has_open_options; diff --git a/block/blkdebug.c b/block/blkdebug.c index 59c61eb..86b143d 100644 --- a/block/blkdebug.c +++ b/block/blkdebug.c @@ -674,17 +674,15 @@ static int blkdebug_truncate(BlockDriverState *bs, int64_t offset) return bdrv_truncate(bs->file->bs, offset); } -static void blkdebug_refresh_filename(BlockDriverState *bs) +static void blkdebug_refresh_filename(BlockDriverState *bs, QDict *options) { QDict *opts; const QDictEntry *e; bool force_json = false; - for (e = qdict_first(bs->options); e; e = qdict_next(bs->options, e)) { + for (e = qdict_first(options); e; e = qdict_next(options, e)) { if (strcmp(qdict_entry_key(e), "config") && - strcmp(qdict_entry_key(e), "x-image") && - strcmp(qdict_entry_key(e), "image") && - strncmp(qdict_entry_key(e), "image.", strlen("image."))) + strcmp(qdict_entry_key(e), "x-image")) { force_json = true; break; @@ -700,7 +698,7 @@ static void blkdebug_refresh_filename(BlockDriverState *bs) if (!force_json && bs->file->bs->exact_filename[0]) { snprintf(bs->exact_filename, sizeof(bs->exact_filename), "blkdebug:%s:%s", - qdict_get_try_str(bs->options, "config") ?: "", + qdict_get_try_str(options, "config") ?: "", bs->file->bs->exact_filename); } @@ -710,11 +708,8 @@ static void blkdebug_refresh_filename(BlockDriverState *bs) QINCREF(bs->file->bs->full_open_options); qdict_put_obj(opts, "image", QOBJECT(bs->file->bs->full_open_options)); - for (e = qdict_first(bs->options); e; e = qdict_next(bs->options, e)) { - if (strcmp(qdict_entry_key(e), "x-image") && - strcmp(qdict_entry_key(e), "image") && - strncmp(qdict_entry_key(e), "image.", strlen("image."))) - { + for (e = qdict_first(options); e; e = qdict_next(options, e)) { + if (strcmp(qdict_entry_key(e), "x-image")) { qobject_incref(qdict_entry_value(e)); qdict_put_obj(opts, qdict_entry_key(e), qdict_entry_value(e)); } @@ -723,6 +718,12 @@ static void blkdebug_refresh_filename(BlockDriverState *bs) bs->full_open_options = opts; } +static int blkdebug_reopen_prepare(BDRVReopenState *reopen_state, + BlockReopenQueue *queue, Error **errp) +{ + return 0; +} + static BlockDriver bdrv_blkdebug = { .format_name = "blkdebug", .protocol_name = "blkdebug", @@ -731,6 +732,7 @@ static BlockDriver bdrv_blkdebug = { .bdrv_parse_filename = blkdebug_parse_filename, .bdrv_file_open = blkdebug_open, .bdrv_close = blkdebug_close, + .bdrv_reopen_prepare = blkdebug_reopen_prepare, .bdrv_getlength = blkdebug_getlength, .bdrv_truncate = blkdebug_truncate, .bdrv_refresh_filename = blkdebug_refresh_filename, diff --git a/block/blkverify.c b/block/blkverify.c index c5f8e8d..1d75449 100644 --- a/block/blkverify.c +++ b/block/blkverify.c @@ -307,7 +307,7 @@ static void blkverify_attach_aio_context(BlockDriverState *bs, bdrv_attach_aio_context(s->test_file->bs, new_context); } -static void blkverify_refresh_filename(BlockDriverState *bs) +static void blkverify_refresh_filename(BlockDriverState *bs, QDict *options) { BDRVBlkverifyState *s = bs->opaque; @@ -2614,10 +2614,11 @@ int bdrv_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) bdrv_co_ioctl_entry(&data); } else { Coroutine *co = qemu_coroutine_create(bdrv_co_ioctl_entry); + qemu_coroutine_enter(co, &data); - } - while (data.ret == -EINPROGRESS) { - aio_poll(bdrv_get_aio_context(bs), true); + while (data.ret == -EINPROGRESS) { + aio_poll(bdrv_get_aio_context(bs), true); + } } return data.ret; } diff --git a/block/mirror.c b/block/mirror.c index 0e8f556..fc34a9c 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -18,6 +18,7 @@ #include "qapi/qmp/qerror.h" #include "qemu/ratelimit.h" #include "qemu/bitmap.h" +#include "qemu/error-report.h" #define SLICE_TIME 100000000ULL /* ns */ #define MAX_IN_FLIGHT 16 @@ -370,11 +371,22 @@ static void mirror_exit(BlockJob *job, void *opaque) if (s->to_replace) { to_replace = s->to_replace; } + + /* This was checked in mirror_start_job(), but meanwhile one of the + * nodes could have been newly attached to a BlockBackend. */ + if (to_replace->blk && s->target->blk) { + error_report("block job: Can't create node with two BlockBackends"); + data->ret = -EINVAL; + goto out; + } + if (bdrv_get_flags(s->target) != bdrv_get_flags(to_replace)) { bdrv_reopen(s->target, bdrv_get_flags(to_replace), NULL); } bdrv_replace_in_backing_chain(to_replace, s->target); } + +out: if (s->to_replace) { bdrv_op_unblock_all(s->to_replace, s->replace_blocker); error_free(s->replace_blocker); @@ -640,7 +652,7 @@ static void mirror_complete(BlockJob *job, Error **errp) Error *local_err = NULL; int ret; - ret = bdrv_open_backing_file(s->target, NULL, &local_err); + ret = bdrv_open_backing_file(s->target, NULL, "backing", &local_err); if (ret < 0) { error_propagate(errp, local_err); return; @@ -705,6 +717,7 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target, bool is_none_mode, BlockDriverState *base) { MirrorBlockJob *s; + BlockDriverState *replaced_bs; if (granularity == 0) { granularity = bdrv_get_default_bitmap_granularity(target); @@ -728,6 +741,21 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target, buf_size = DEFAULT_MIRROR_BUF_SIZE; } + /* We can't support this case as long as the block layer can't handle + * multiple BlockBackends per BlockDriverState. */ + if (replaces) { + replaced_bs = bdrv_lookup_bs(replaces, replaces, errp); + if (replaced_bs == NULL) { + return; + } + } else { + replaced_bs = bs; + } + if (replaced_bs->blk && target->blk) { + error_setg(errp, "Can't create node with two BlockBackends"); + return; + } + s = block_job_create(driver, bs, speed, cb, opaque, errp); if (!s) { return; diff --git a/block/nbd.c b/block/nbd.c index cd6a587..416f42b 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -342,13 +342,13 @@ static void nbd_attach_aio_context(BlockDriverState *bs, nbd_client_attach_aio_context(bs, new_context); } -static void nbd_refresh_filename(BlockDriverState *bs) +static void nbd_refresh_filename(BlockDriverState *bs, QDict *options) { QDict *opts = qdict_new(); - const char *path = qdict_get_try_str(bs->options, "path"); - const char *host = qdict_get_try_str(bs->options, "host"); - const char *port = qdict_get_try_str(bs->options, "port"); - const char *export = qdict_get_try_str(bs->options, "export"); + 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"); qdict_put_obj(opts, "driver", QOBJECT(qstring_from_str("nbd"))); diff --git a/block/qapi.c b/block/qapi.c index c0e877e..fecac25 100644 --- a/block/qapi.c +++ b/block/qapi.c @@ -245,15 +245,17 @@ void bdrv_query_image_info(BlockDriverState *bs, info->has_backing_filename = true; bdrv_get_full_backing_filename(bs, backing_filename2, PATH_MAX, &err); if (err) { - error_propagate(errp, err); - qapi_free_ImageInfo(info); + /* Can't reconstruct the full backing filename, so we must omit + * this field and apply a Best Effort to this query. */ g_free(backing_filename2); - return; + backing_filename2 = NULL; + error_free(err); } - if (strcmp(backing_filename, backing_filename2) != 0) { - info->full_backing_filename = - g_strdup(backing_filename2); + /* Always report the full_backing_filename if present, even if it's the + * same as backing_filename. That they are same is useful info. */ + if (backing_filename2) { + info->full_backing_filename = g_strdup(backing_filename2); info->has_full_backing_filename = true; } @@ -676,7 +678,10 @@ void bdrv_image_info_dump(fprintf_function func_fprintf, void *f, if (info->has_backing_filename) { func_fprintf(f, "backing file: %s", info->backing_filename); - if (info->has_full_backing_filename) { + if (!info->has_full_backing_filename) { + func_fprintf(f, " (cannot determine actual path)"); + } else if (strcmp(info->backing_filename, + info->full_backing_filename) != 0) { func_fprintf(f, " (actual path: %s)", info->full_backing_filename); } func_fprintf(f, "\n"); diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 24a60e2..34112c3 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -1641,7 +1641,8 @@ fail: static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table, int l1_size, int64_t *visited_l1_entries, int64_t l1_entries, - BlockDriverAmendStatusCB *status_cb) + BlockDriverAmendStatusCB *status_cb, + void *cb_opaque) { BDRVQcow2State *s = bs->opaque; bool is_active_l1 = (l1_table == s->l1_table); @@ -1667,7 +1668,7 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table, /* unallocated */ (*visited_l1_entries)++; if (status_cb) { - status_cb(bs, *visited_l1_entries, l1_entries); + status_cb(bs, *visited_l1_entries, l1_entries, cb_opaque); } continue; } @@ -1804,7 +1805,7 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table, (*visited_l1_entries)++; if (status_cb) { - status_cb(bs, *visited_l1_entries, l1_entries); + status_cb(bs, *visited_l1_entries, l1_entries, cb_opaque); } } @@ -1828,7 +1829,8 @@ fail: * qcow2 version which doesn't yet support metadata zero clusters. */ int qcow2_expand_zero_clusters(BlockDriverState *bs, - BlockDriverAmendStatusCB *status_cb) + BlockDriverAmendStatusCB *status_cb, + void *cb_opaque) { BDRVQcow2State *s = bs->opaque; uint64_t *l1_table = NULL; @@ -1845,7 +1847,7 @@ int qcow2_expand_zero_clusters(BlockDriverState *bs, ret = expand_zero_clusters_in_l1(bs, s->l1_table, s->l1_size, &visited_l1_entries, l1_entries, - status_cb); + status_cb, cb_opaque); if (ret < 0) { goto fail; } @@ -1881,7 +1883,7 @@ int qcow2_expand_zero_clusters(BlockDriverState *bs, ret = expand_zero_clusters_in_l1(bs, l1_table, s->snapshots[i].l1_size, &visited_l1_entries, l1_entries, - status_cb); + status_cb, cb_opaque); if (ret < 0) { goto fail; } diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 820f412..af493f8 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -1345,6 +1345,9 @@ static int inc_refcounts(BlockDriverState *bs, if (refcount == s->refcount_max) { fprintf(stderr, "ERROR: overflow cluster offset=0x%" PRIx64 "\n", cluster_offset); + fprintf(stderr, "Use qemu-img amend to increase the refcount entry " + "width or qemu-img convert to create a clean copy if the " + "image cannot be opened for writing\n"); res->corruptions++; continue; } @@ -2467,3 +2470,450 @@ int qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset, return 0; } + +/* A pointer to a function of this type is given to walk_over_reftable(). That + * function will create refblocks and pass them to a RefblockFinishOp once they + * are completed (@refblock). @refblock_empty is set if the refblock is + * completely empty. + * + * Along with the refblock, a corresponding reftable entry is passed, in the + * reftable @reftable (which may be reallocated) at @reftable_index. + * + * @allocated should be set to true if a new cluster has been allocated. + */ +typedef int (RefblockFinishOp)(BlockDriverState *bs, uint64_t **reftable, + uint64_t reftable_index, uint64_t *reftable_size, + void *refblock, bool refblock_empty, + bool *allocated, Error **errp); + +/** + * This "operation" for walk_over_reftable() allocates the refblock on disk (if + * it is not empty) and inserts its offset into the new reftable. The size of + * this new reftable is increased as required. + */ +static int alloc_refblock(BlockDriverState *bs, uint64_t **reftable, + uint64_t reftable_index, uint64_t *reftable_size, + void *refblock, bool refblock_empty, bool *allocated, + Error **errp) +{ + BDRVQcow2State *s = bs->opaque; + int64_t offset; + + if (!refblock_empty && reftable_index >= *reftable_size) { + uint64_t *new_reftable; + uint64_t new_reftable_size; + + new_reftable_size = ROUND_UP(reftable_index + 1, + s->cluster_size / sizeof(uint64_t)); + if (new_reftable_size > QCOW_MAX_REFTABLE_SIZE / sizeof(uint64_t)) { + error_setg(errp, + "This operation would make the refcount table grow " + "beyond the maximum size supported by QEMU, aborting"); + return -ENOTSUP; + } + + new_reftable = g_try_realloc(*reftable, new_reftable_size * + sizeof(uint64_t)); + if (!new_reftable) { + error_setg(errp, "Failed to increase reftable buffer size"); + return -ENOMEM; + } + + memset(new_reftable + *reftable_size, 0, + (new_reftable_size - *reftable_size) * sizeof(uint64_t)); + + *reftable = new_reftable; + *reftable_size = new_reftable_size; + } + + if (!refblock_empty && !(*reftable)[reftable_index]) { + offset = qcow2_alloc_clusters(bs, s->cluster_size); + if (offset < 0) { + error_setg_errno(errp, -offset, "Failed to allocate refblock"); + return offset; + } + (*reftable)[reftable_index] = offset; + *allocated = true; + } + + return 0; +} + +/** + * This "operation" for walk_over_reftable() writes the refblock to disk at the + * offset specified by the new reftable's entry. It does not modify the new + * reftable or change any refcounts. + */ +static int flush_refblock(BlockDriverState *bs, uint64_t **reftable, + uint64_t reftable_index, uint64_t *reftable_size, + void *refblock, bool refblock_empty, bool *allocated, + Error **errp) +{ + BDRVQcow2State *s = bs->opaque; + int64_t offset; + int ret; + + if (reftable_index < *reftable_size && (*reftable)[reftable_index]) { + offset = (*reftable)[reftable_index]; + + ret = qcow2_pre_write_overlap_check(bs, 0, offset, s->cluster_size); + if (ret < 0) { + error_setg_errno(errp, -ret, "Overlap check failed"); + return ret; + } + + ret = bdrv_pwrite(bs->file->bs, offset, refblock, s->cluster_size); + if (ret < 0) { + error_setg_errno(errp, -ret, "Failed to write refblock"); + return ret; + } + } else { + assert(refblock_empty); + } + + return 0; +} + +/** + * This function walks over the existing reftable and every referenced refblock; + * if @new_set_refcount is non-NULL, it is called for every refcount entry to + * create an equal new entry in the passed @new_refblock. Once that + * @new_refblock is completely filled, @operation will be called. + * + * @status_cb and @cb_opaque are used for the amend operation's status callback. + * @index is the index of the walk_over_reftable() calls and @total is the total + * number of walk_over_reftable() calls per amend operation. Both are used for + * calculating the parameters for the status callback. + * + * @allocated is set to true if a new cluster has been allocated. + */ +static int walk_over_reftable(BlockDriverState *bs, uint64_t **new_reftable, + uint64_t *new_reftable_index, + uint64_t *new_reftable_size, + void *new_refblock, int new_refblock_size, + int new_refcount_bits, + RefblockFinishOp *operation, bool *allocated, + Qcow2SetRefcountFunc *new_set_refcount, + BlockDriverAmendStatusCB *status_cb, + void *cb_opaque, int index, int total, + Error **errp) +{ + BDRVQcow2State *s = bs->opaque; + uint64_t reftable_index; + bool new_refblock_empty = true; + int refblock_index; + int new_refblock_index = 0; + int ret; + + for (reftable_index = 0; reftable_index < s->refcount_table_size; + reftable_index++) + { + uint64_t refblock_offset = s->refcount_table[reftable_index] + & REFT_OFFSET_MASK; + + status_cb(bs, (uint64_t)index * s->refcount_table_size + reftable_index, + (uint64_t)total * s->refcount_table_size, cb_opaque); + + if (refblock_offset) { + void *refblock; + + if (offset_into_cluster(s, refblock_offset)) { + qcow2_signal_corruption(bs, true, -1, -1, "Refblock offset %#" + PRIx64 " unaligned (reftable index: %#" + PRIx64 ")", refblock_offset, + reftable_index); + error_setg(errp, + "Image is corrupt (unaligned refblock offset)"); + return -EIO; + } + + ret = qcow2_cache_get(bs, s->refcount_block_cache, refblock_offset, + &refblock); + if (ret < 0) { + error_setg_errno(errp, -ret, "Failed to retrieve refblock"); + return ret; + } + + for (refblock_index = 0; refblock_index < s->refcount_block_size; + refblock_index++) + { + uint64_t refcount; + + if (new_refblock_index >= new_refblock_size) { + /* new_refblock is now complete */ + ret = operation(bs, new_reftable, *new_reftable_index, + new_reftable_size, new_refblock, + new_refblock_empty, allocated, errp); + if (ret < 0) { + qcow2_cache_put(bs, s->refcount_block_cache, &refblock); + return ret; + } + + (*new_reftable_index)++; + new_refblock_index = 0; + new_refblock_empty = true; + } + + refcount = s->get_refcount(refblock, refblock_index); + if (new_refcount_bits < 64 && refcount >> new_refcount_bits) { + uint64_t offset; + + qcow2_cache_put(bs, s->refcount_block_cache, &refblock); + + offset = ((reftable_index << s->refcount_block_bits) + + refblock_index) << s->cluster_bits; + + error_setg(errp, "Cannot decrease refcount entry width to " + "%i bits: Cluster at offset %#" PRIx64 " has a " + "refcount of %" PRIu64, new_refcount_bits, + offset, refcount); + return -EINVAL; + } + + if (new_set_refcount) { + new_set_refcount(new_refblock, new_refblock_index++, + refcount); + } else { + new_refblock_index++; + } + new_refblock_empty = new_refblock_empty && refcount == 0; + } + + qcow2_cache_put(bs, s->refcount_block_cache, &refblock); + } else { + /* No refblock means every refcount is 0 */ + for (refblock_index = 0; refblock_index < s->refcount_block_size; + refblock_index++) + { + if (new_refblock_index >= new_refblock_size) { + /* new_refblock is now complete */ + ret = operation(bs, new_reftable, *new_reftable_index, + new_reftable_size, new_refblock, + new_refblock_empty, allocated, errp); + if (ret < 0) { + return ret; + } + + (*new_reftable_index)++; + new_refblock_index = 0; + new_refblock_empty = true; + } + + if (new_set_refcount) { + new_set_refcount(new_refblock, new_refblock_index++, 0); + } else { + new_refblock_index++; + } + } + } + } + + if (new_refblock_index > 0) { + /* Complete the potentially existing partially filled final refblock */ + if (new_set_refcount) { + for (; new_refblock_index < new_refblock_size; + new_refblock_index++) + { + new_set_refcount(new_refblock, new_refblock_index, 0); + } + } + + ret = operation(bs, new_reftable, *new_reftable_index, + new_reftable_size, new_refblock, new_refblock_empty, + allocated, errp); + if (ret < 0) { + return ret; + } + + (*new_reftable_index)++; + } + + status_cb(bs, (uint64_t)(index + 1) * s->refcount_table_size, + (uint64_t)total * s->refcount_table_size, cb_opaque); + + return 0; +} + +int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order, + BlockDriverAmendStatusCB *status_cb, + void *cb_opaque, Error **errp) +{ + BDRVQcow2State *s = bs->opaque; + Qcow2GetRefcountFunc *new_get_refcount; + Qcow2SetRefcountFunc *new_set_refcount; + void *new_refblock = qemu_blockalign(bs->file->bs, s->cluster_size); + uint64_t *new_reftable = NULL, new_reftable_size = 0; + uint64_t *old_reftable, old_reftable_size, old_reftable_offset; + uint64_t new_reftable_index = 0; + uint64_t i; + int64_t new_reftable_offset = 0, allocated_reftable_size = 0; + int new_refblock_size, new_refcount_bits = 1 << refcount_order; + int old_refcount_order; + int walk_index = 0; + int ret; + bool new_allocation; + + assert(s->qcow_version >= 3); + assert(refcount_order >= 0 && refcount_order <= 6); + + /* see qcow2_open() */ + new_refblock_size = 1 << (s->cluster_bits - (refcount_order - 3)); + + new_get_refcount = get_refcount_funcs[refcount_order]; + new_set_refcount = set_refcount_funcs[refcount_order]; + + + do { + int total_walks; + + new_allocation = false; + + /* At least we have to do this walk and the one which writes the + * refblocks; also, at least we have to do this loop here at least + * twice (normally), first to do the allocations, and second to + * determine that everything is correctly allocated, this then makes + * three walks in total */ + total_walks = MAX(walk_index + 2, 3); + + /* First, allocate the structures so they are present in the refcount + * structures */ + ret = walk_over_reftable(bs, &new_reftable, &new_reftable_index, + &new_reftable_size, NULL, new_refblock_size, + new_refcount_bits, &alloc_refblock, + &new_allocation, NULL, status_cb, cb_opaque, + walk_index++, total_walks, errp); + if (ret < 0) { + goto done; + } + + new_reftable_index = 0; + + if (new_allocation) { + if (new_reftable_offset) { + qcow2_free_clusters(bs, new_reftable_offset, + allocated_reftable_size * sizeof(uint64_t), + QCOW2_DISCARD_NEVER); + } + + new_reftable_offset = qcow2_alloc_clusters(bs, new_reftable_size * + sizeof(uint64_t)); + if (new_reftable_offset < 0) { + error_setg_errno(errp, -new_reftable_offset, + "Failed to allocate the new reftable"); + ret = new_reftable_offset; + goto done; + } + allocated_reftable_size = new_reftable_size; + } + } while (new_allocation); + + /* Second, write the new refblocks */ + ret = walk_over_reftable(bs, &new_reftable, &new_reftable_index, + &new_reftable_size, new_refblock, + new_refblock_size, new_refcount_bits, + &flush_refblock, &new_allocation, new_set_refcount, + status_cb, cb_opaque, walk_index, walk_index + 1, + errp); + if (ret < 0) { + goto done; + } + assert(!new_allocation); + + + /* Write the new reftable */ + ret = qcow2_pre_write_overlap_check(bs, 0, new_reftable_offset, + new_reftable_size * sizeof(uint64_t)); + if (ret < 0) { + error_setg_errno(errp, -ret, "Overlap check failed"); + goto done; + } + + for (i = 0; i < new_reftable_size; i++) { + cpu_to_be64s(&new_reftable[i]); + } + + ret = bdrv_pwrite(bs->file->bs, new_reftable_offset, new_reftable, + new_reftable_size * sizeof(uint64_t)); + + for (i = 0; i < new_reftable_size; i++) { + be64_to_cpus(&new_reftable[i]); + } + + if (ret < 0) { + error_setg_errno(errp, -ret, "Failed to write the new reftable"); + goto done; + } + + + /* Empty the refcount cache */ + ret = qcow2_cache_flush(bs, s->refcount_block_cache); + if (ret < 0) { + error_setg_errno(errp, -ret, "Failed to flush the refblock cache"); + goto done; + } + + /* Update the image header to point to the new reftable; this only updates + * the fields which are relevant to qcow2_update_header(); other fields + * such as s->refcount_table or s->refcount_bits stay stale for now + * (because we have to restore everything if qcow2_update_header() fails) */ + old_refcount_order = s->refcount_order; + old_reftable_size = s->refcount_table_size; + old_reftable_offset = s->refcount_table_offset; + + s->refcount_order = refcount_order; + s->refcount_table_size = new_reftable_size; + s->refcount_table_offset = new_reftable_offset; + + ret = qcow2_update_header(bs); + if (ret < 0) { + s->refcount_order = old_refcount_order; + s->refcount_table_size = old_reftable_size; + s->refcount_table_offset = old_reftable_offset; + error_setg_errno(errp, -ret, "Failed to update the qcow2 header"); + goto done; + } + + /* Now update the rest of the in-memory information */ + old_reftable = s->refcount_table; + s->refcount_table = new_reftable; + + s->refcount_bits = 1 << refcount_order; + s->refcount_max = UINT64_C(1) << (s->refcount_bits - 1); + s->refcount_max += s->refcount_max - 1; + + s->refcount_block_bits = s->cluster_bits - (refcount_order - 3); + s->refcount_block_size = 1 << s->refcount_block_bits; + + s->get_refcount = new_get_refcount; + s->set_refcount = new_set_refcount; + + /* For cleaning up all old refblocks and the old reftable below the "done" + * label */ + new_reftable = old_reftable; + new_reftable_size = old_reftable_size; + new_reftable_offset = old_reftable_offset; + +done: + if (new_reftable) { + /* On success, new_reftable actually points to the old reftable (and + * new_reftable_size is the old reftable's size); but that is just + * fine */ + for (i = 0; i < new_reftable_size; i++) { + uint64_t offset = new_reftable[i] & REFT_OFFSET_MASK; + if (offset) { + qcow2_free_clusters(bs, offset, s->cluster_size, + QCOW2_DISCARD_OTHER); + } + } + g_free(new_reftable); + + if (new_reftable_offset > 0) { + qcow2_free_clusters(bs, new_reftable_offset, + new_reftable_size * sizeof(uint64_t), + QCOW2_DISCARD_OTHER); + } + } + + qemu_vfree(new_refblock); + return ret; +} diff --git a/block/qcow2.c b/block/qcow2.c index 5b59fa3..1789af4 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1282,6 +1282,52 @@ static void qcow2_reopen_abort(BDRVReopenState *state) g_free(state->opaque); } +static void qcow2_join_options(QDict *options, QDict *old_options) +{ + bool has_new_overlap_template = + qdict_haskey(options, QCOW2_OPT_OVERLAP) || + qdict_haskey(options, QCOW2_OPT_OVERLAP_TEMPLATE); + bool has_new_total_cache_size = + qdict_haskey(options, QCOW2_OPT_CACHE_SIZE); + bool has_all_cache_options; + + /* New overlap template overrides all old overlap options */ + if (has_new_overlap_template) { + qdict_del(old_options, QCOW2_OPT_OVERLAP); + qdict_del(old_options, QCOW2_OPT_OVERLAP_TEMPLATE); + qdict_del(old_options, QCOW2_OPT_OVERLAP_MAIN_HEADER); + qdict_del(old_options, QCOW2_OPT_OVERLAP_ACTIVE_L1); + qdict_del(old_options, QCOW2_OPT_OVERLAP_ACTIVE_L2); + qdict_del(old_options, QCOW2_OPT_OVERLAP_REFCOUNT_TABLE); + qdict_del(old_options, QCOW2_OPT_OVERLAP_REFCOUNT_BLOCK); + qdict_del(old_options, QCOW2_OPT_OVERLAP_SNAPSHOT_TABLE); + qdict_del(old_options, QCOW2_OPT_OVERLAP_INACTIVE_L1); + qdict_del(old_options, QCOW2_OPT_OVERLAP_INACTIVE_L2); + } + + /* New total cache size overrides all old options */ + if (qdict_haskey(options, QCOW2_OPT_CACHE_SIZE)) { + qdict_del(old_options, QCOW2_OPT_L2_CACHE_SIZE); + qdict_del(old_options, QCOW2_OPT_REFCOUNT_CACHE_SIZE); + } + + qdict_join(options, old_options, false); + + /* + * If after merging all cache size options are set, an old total size is + * overwritten. Do keep all options, however, if all three are new. The + * resulting error message is what we want to happen. + */ + has_all_cache_options = + qdict_haskey(options, QCOW2_OPT_CACHE_SIZE) || + qdict_haskey(options, QCOW2_OPT_L2_CACHE_SIZE) || + qdict_haskey(options, QCOW2_OPT_REFCOUNT_CACHE_SIZE); + + if (has_all_cache_options && !has_new_total_cache_size) { + qdict_del(options, QCOW2_OPT_CACHE_SIZE); + } +} + static int64_t coroutine_fn qcow2_co_get_block_status(BlockDriverState *bs, int64_t sector_num, int nb_sectors, int *pnum) { @@ -2757,6 +2803,10 @@ static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs) .has_corrupt = true, .refcount_bits = s->refcount_bits, }; + } else { + /* if this assertion fails, this probably means a new version was + * added without having it covered here */ + assert(false); } return spec_info; @@ -2824,7 +2874,7 @@ static int qcow2_load_vmstate(BlockDriverState *bs, uint8_t *buf, * have to be removed. */ static int qcow2_downgrade(BlockDriverState *bs, int target_version, - BlockDriverAmendStatusCB *status_cb) + BlockDriverAmendStatusCB *status_cb, void *cb_opaque) { BDRVQcow2State *s = bs->opaque; int current_version = s->qcow_version; @@ -2839,13 +2889,7 @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version, } if (s->refcount_order != 4) { - /* we would have to convert the image to a refcount_order == 4 image - * here; however, since qemu (at the time of writing this) does not - * support anything different than 4 anyway, there is no point in doing - * so right now; however, we should error out (if qemu supports this in - * the future and this code has not been adapted) */ - error_report("qcow2_downgrade: Image refcount orders other than 4 are " - "currently not supported."); + error_report("compat=0.10 requires refcount_bits=16"); return -ENOTSUP; } @@ -2873,7 +2917,7 @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version, /* clearing autoclear features is trivial */ s->autoclear_features = 0; - ret = qcow2_expand_zero_clusters(bs, status_cb); + ret = qcow2_expand_zero_clusters(bs, status_cb, cb_opaque); if (ret < 0) { return ret; } @@ -2887,8 +2931,79 @@ static int qcow2_downgrade(BlockDriverState *bs, int target_version, return 0; } +typedef enum Qcow2AmendOperation { + /* This is the value Qcow2AmendHelperCBInfo::last_operation will be + * statically initialized to so that the helper CB can discern the first + * invocation from an operation change */ + QCOW2_NO_OPERATION = 0, + + QCOW2_CHANGING_REFCOUNT_ORDER, + QCOW2_DOWNGRADING, +} Qcow2AmendOperation; + +typedef struct Qcow2AmendHelperCBInfo { + /* The code coordinating the amend operations should only modify + * these four fields; the rest will be managed by the CB */ + BlockDriverAmendStatusCB *original_status_cb; + void *original_cb_opaque; + + Qcow2AmendOperation current_operation; + + /* Total number of operations to perform (only set once) */ + int total_operations; + + /* The following fields are managed by the CB */ + + /* Number of operations completed */ + int operations_completed; + + /* Cumulative offset of all completed operations */ + int64_t offset_completed; + + Qcow2AmendOperation last_operation; + int64_t last_work_size; +} Qcow2AmendHelperCBInfo; + +static void qcow2_amend_helper_cb(BlockDriverState *bs, + int64_t operation_offset, + int64_t operation_work_size, void *opaque) +{ + Qcow2AmendHelperCBInfo *info = opaque; + int64_t current_work_size; + int64_t projected_work_size; + + if (info->current_operation != info->last_operation) { + if (info->last_operation != QCOW2_NO_OPERATION) { + info->offset_completed += info->last_work_size; + info->operations_completed++; + } + + info->last_operation = info->current_operation; + } + + assert(info->total_operations > 0); + assert(info->operations_completed < info->total_operations); + + info->last_work_size = operation_work_size; + + current_work_size = info->offset_completed + operation_work_size; + + /* current_work_size is the total work size for (operations_completed + 1) + * operations (which includes this one), so multiply it by the number of + * operations not covered and divide it by the number of operations + * covered to get a projection for the operations not covered */ + projected_work_size = current_work_size * (info->total_operations - + info->operations_completed - 1) + / (info->operations_completed + 1); + + info->original_status_cb(bs, info->offset_completed + operation_offset, + current_work_size + projected_work_size, + info->original_cb_opaque); +} + static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts, - BlockDriverAmendStatusCB *status_cb) + BlockDriverAmendStatusCB *status_cb, + void *cb_opaque) { BDRVQcow2State *s = bs->opaque; int old_version = s->qcow_version, new_version = old_version; @@ -2898,8 +3013,10 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts, const char *compat = NULL; uint64_t cluster_size = s->cluster_size; bool encrypt; + int refcount_bits = s->refcount_bits; int ret; QemuOptDesc *desc = opts->list->desc; + Qcow2AmendHelperCBInfo helper_cb_info; while (desc && desc->name) { if (!qemu_opt_find(opts, desc->name)) { @@ -2917,11 +3034,11 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts, } else if (!strcmp(compat, "1.1")) { new_version = 3; } else { - fprintf(stderr, "Unknown compatibility level %s.\n", compat); + error_report("Unknown compatibility level %s", compat); return -EINVAL; } } else if (!strcmp(desc->name, BLOCK_OPT_PREALLOC)) { - fprintf(stderr, "Cannot change preallocation mode.\n"); + error_report("Cannot change preallocation mode"); return -ENOTSUP; } else if (!strcmp(desc->name, BLOCK_OPT_SIZE)) { new_size = qemu_opt_get_size(opts, BLOCK_OPT_SIZE, 0); @@ -2934,47 +3051,74 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts, !!s->cipher); if (encrypt != !!s->cipher) { - fprintf(stderr, "Changing the encryption flag is not " - "supported.\n"); + error_report("Changing the encryption flag is not supported"); return -ENOTSUP; } } else if (!strcmp(desc->name, BLOCK_OPT_CLUSTER_SIZE)) { cluster_size = qemu_opt_get_size(opts, BLOCK_OPT_CLUSTER_SIZE, cluster_size); if (cluster_size != s->cluster_size) { - fprintf(stderr, "Changing the cluster size is not " - "supported.\n"); + error_report("Changing the cluster size is not supported"); return -ENOTSUP; } } else if (!strcmp(desc->name, BLOCK_OPT_LAZY_REFCOUNTS)) { lazy_refcounts = qemu_opt_get_bool(opts, BLOCK_OPT_LAZY_REFCOUNTS, lazy_refcounts); } else if (!strcmp(desc->name, BLOCK_OPT_REFCOUNT_BITS)) { - error_report("Cannot change refcount entry width"); - return -ENOTSUP; + refcount_bits = qemu_opt_get_number(opts, BLOCK_OPT_REFCOUNT_BITS, + refcount_bits); + + if (refcount_bits <= 0 || refcount_bits > 64 || + !is_power_of_2(refcount_bits)) + { + error_report("Refcount width must be a power of two and may " + "not exceed 64 bits"); + return -EINVAL; + } } else { - /* if this assertion fails, this probably means a new option was + /* if this point is reached, this probably means a new option was * added without having it covered here */ - assert(false); + abort(); } desc++; } - if (new_version != old_version) { - if (new_version > old_version) { - /* Upgrade */ - s->qcow_version = new_version; - ret = qcow2_update_header(bs); - if (ret < 0) { - s->qcow_version = old_version; - return ret; - } - } else { - ret = qcow2_downgrade(bs, new_version, status_cb); - if (ret < 0) { - return ret; - } + helper_cb_info = (Qcow2AmendHelperCBInfo){ + .original_status_cb = status_cb, + .original_cb_opaque = cb_opaque, + .total_operations = (new_version < old_version) + + (s->refcount_bits != refcount_bits) + }; + + /* Upgrade first (some features may require compat=1.1) */ + if (new_version > old_version) { + s->qcow_version = new_version; + ret = qcow2_update_header(bs); + if (ret < 0) { + s->qcow_version = old_version; + return ret; + } + } + + if (s->refcount_bits != refcount_bits) { + int refcount_order = ctz32(refcount_bits); + Error *local_error = NULL; + + if (new_version < 3 && refcount_bits != 16) { + error_report("Different refcount widths than 16 bits require " + "compatibility level 1.1 or above (use compat=1.1 or " + "greater)"); + return -EINVAL; + } + + helper_cb_info.current_operation = QCOW2_CHANGING_REFCOUNT_ORDER; + ret = qcow2_change_refcount_order(bs, refcount_order, + &qcow2_amend_helper_cb, + &helper_cb_info, &local_error); + if (ret < 0) { + error_report_err(local_error); + return ret; } } @@ -2989,9 +3133,9 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts, if (s->use_lazy_refcounts != lazy_refcounts) { if (lazy_refcounts) { - if (s->qcow_version < 3) { - fprintf(stderr, "Lazy refcounts only supported with compatibility " - "level 1.1 and above (use compat=1.1 or greater)\n"); + if (new_version < 3) { + error_report("Lazy refcounts only supported with compatibility " + "level 1.1 and above (use compat=1.1 or greater)"); return -EINVAL; } s->compatible_features |= QCOW2_COMPAT_LAZY_REFCOUNTS; @@ -3025,6 +3169,16 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts, } } + /* Downgrade last (so unsupported features can be removed before) */ + if (new_version < old_version) { + helper_cb_info.current_operation = QCOW2_DOWNGRADING; + ret = qcow2_downgrade(bs, new_version, &qcow2_amend_helper_cb, + &helper_cb_info); + if (ret < 0) { + return ret; + } + } + return 0; } @@ -3145,6 +3299,7 @@ BlockDriver bdrv_qcow2 = { .bdrv_reopen_prepare = qcow2_reopen_prepare, .bdrv_reopen_commit = qcow2_reopen_commit, .bdrv_reopen_abort = qcow2_reopen_abort, + .bdrv_join_options = qcow2_join_options, .bdrv_create = qcow2_create, .bdrv_has_zero_init = bdrv_has_zero_init_1, .bdrv_co_get_block_status = qcow2_co_get_block_status, diff --git a/block/qcow2.h b/block/qcow2.h index b8c500b..a063a3c 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -529,6 +529,10 @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset, int qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset, int64_t size); +int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order, + BlockDriverAmendStatusCB *status_cb, + void *cb_opaque, Error **errp); + /* qcow2-cluster.c functions */ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, bool exact_size); @@ -553,7 +557,8 @@ int qcow2_discard_clusters(BlockDriverState *bs, uint64_t offset, int qcow2_zero_clusters(BlockDriverState *bs, uint64_t offset, int nb_sectors); int qcow2_expand_zero_clusters(BlockDriverState *bs, - BlockDriverAmendStatusCB *status_cb); + BlockDriverAmendStatusCB *status_cb, + void *cb_opaque); /* qcow2-snapshot.c functions */ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info); diff --git a/block/quorum.c b/block/quorum.c index d162459..6793f12 100644 --- a/block/quorum.c +++ b/block/quorum.c @@ -997,7 +997,7 @@ static void quorum_attach_aio_context(BlockDriverState *bs, } } -static void quorum_refresh_filename(BlockDriverState *bs) +static void quorum_refresh_filename(BlockDriverState *bs, QDict *options) { BDRVQuorumState *s = bs->opaque; QDict *opts; diff --git a/block/raw-posix.c b/block/raw-posix.c index ffeebe1..076d070 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -500,21 +500,17 @@ static int raw_open_common(BlockDriverState *bs, QDict *options, goto fail; } if (!s->use_aio && (bdrv_flags & BDRV_O_NATIVE_AIO)) { - error_printf("WARNING: aio=native was specified for '%s', but " - "it requires cache.direct=on, which was not " - "specified. Falling back to aio=threads.\n" - " This will become an error condition in " - "future QEMU versions.\n", - bs->filename); + error_setg(errp, "aio=native was specified, but it requires " + "cache.direct=on, which was not specified."); + ret = -EINVAL; + goto fail; } #else if (bdrv_flags & BDRV_O_NATIVE_AIO) { - error_printf("WARNING: aio=native was specified for '%s', but " - "is not supported in this build. Falling back to " - "aio=threads.\n" - " This will become an error condition in " - "future QEMU versions.\n", - bs->filename); + error_setg(errp, "aio=native was specified, but is not supported " + "in this build."); + ret = -EINVAL; + goto fail; } #endif /* !defined(CONFIG_LINUX_AIO) */ diff --git a/block/snapshot.c b/block/snapshot.c index 6e9fa8d..2d86b88 100644 --- a/block/snapshot.c +++ b/block/snapshot.c @@ -229,6 +229,8 @@ int bdrv_snapshot_delete(BlockDriverState *bs, Error **errp) { BlockDriver *drv = bs->drv; + int ret; + if (!drv) { error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, bdrv_get_device_name(bs)); return -ENOMEDIUM; @@ -239,18 +241,21 @@ int bdrv_snapshot_delete(BlockDriverState *bs, } /* drain all pending i/o before deleting snapshot */ - bdrv_drain(bs); + bdrv_drained_begin(bs); if (drv->bdrv_snapshot_delete) { - return drv->bdrv_snapshot_delete(bs, snapshot_id, name, errp); + ret = drv->bdrv_snapshot_delete(bs, snapshot_id, name, errp); + } else if (bs->file) { + ret = bdrv_snapshot_delete(bs->file->bs, snapshot_id, name, errp); + } else { + error_setg(errp, "Block format '%s' used by device '%s' " + "does not support internal snapshot deletion", + drv->format_name, bdrv_get_device_name(bs)); + ret = -ENOTSUP; } - if (bs->file) { - return bdrv_snapshot_delete(bs->file->bs, snapshot_id, name, errp); - } - error_setg(errp, "Block format '%s' used by device '%s' " - "does not support internal snapshot deletion", - drv->format_name, bdrv_get_device_name(bs)); - return -ENOTSUP; + + bdrv_drained_end(bs); + return ret; } int bdrv_snapshot_delete_by_id_or_name(BlockDriverState *bs, @@ -387,16 +387,6 @@ static void extract_common_blockdev_options(QemuOpts *opts, int *bdrv_flags, } } - if (qemu_opt_get_bool(opts, BDRV_OPT_CACHE_WB, true)) { - *bdrv_flags |= BDRV_O_CACHE_WB; - } - if (qemu_opt_get_bool(opts, BDRV_OPT_CACHE_DIRECT, false)) { - *bdrv_flags |= BDRV_O_NOCACHE; - } - if (qemu_opt_get_bool(opts, BDRV_OPT_CACHE_NO_FLUSH, false)) { - *bdrv_flags |= BDRV_O_NO_FLUSH; - } - if ((aio = qemu_opt_get(opts, "aio")) != NULL) { if (!strcmp(aio, "native")) { *bdrv_flags |= BDRV_O_NATIVE_AIO; @@ -490,7 +480,6 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, QDict *interval_dict = NULL; QList *interval_list = NULL; const char *id; - bool has_driver_specific_opts; BlockdevDetectZeroesOptions detect_zeroes = BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF; const char *throttling_group = NULL; @@ -514,8 +503,6 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, qdict_del(bs_opts, "id"); } - has_driver_specific_opts = !!qdict_size(bs_opts); - /* extract parameters */ snapshot = qemu_opt_get_bool(opts, "snapshot", 0); @@ -572,13 +559,11 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, } if (snapshot) { - /* always use cache=unsafe with snapshot */ - bdrv_flags &= ~BDRV_O_CACHE_MASK; - bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH); + bdrv_flags |= BDRV_O_SNAPSHOT; } /* init */ - if ((!file || !*file) && !has_driver_specific_opts) { + if ((!file || !*file) && !qdict_size(bs_opts)) { BlockBackendRootState *blk_rs; blk = blk_new(qemu_opts_id(opts), errp); @@ -606,6 +591,20 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, file = NULL; } + /* bdrv_open() defaults to the values in bdrv_flags (for compatibility + * with other callers) rather than what we want as the real defaults. + * Apply the defaults here instead. */ + qdict_set_default_str(bs_opts, BDRV_OPT_CACHE_WB, "on"); + qdict_set_default_str(bs_opts, BDRV_OPT_CACHE_DIRECT, "off"); + qdict_set_default_str(bs_opts, BDRV_OPT_CACHE_NO_FLUSH, "off"); + + if (snapshot) { + /* always use cache=unsafe with snapshot */ + qdict_put(bs_opts, BDRV_OPT_CACHE_WB, qstring_from_str("on")); + qdict_put(bs_opts, BDRV_OPT_CACHE_DIRECT, qstring_from_str("off")); + qdict_put(bs_opts, BDRV_OPT_CACHE_NO_FLUSH, qstring_from_str("on")); + } + blk = blk_new_open(qemu_opts_id(opts), file, NULL, bs_opts, bdrv_flags, errp); if (!blk) { @@ -3873,18 +3872,6 @@ QemuOptsList qemu_common_drive_opts = { .type = QEMU_OPT_STRING, .help = "discard operation (ignore/off, unmap/on)", },{ - .name = BDRV_OPT_CACHE_WB, - .type = QEMU_OPT_BOOL, - .help = "enables writeback mode for any caches", - },{ - .name = BDRV_OPT_CACHE_DIRECT, - .type = QEMU_OPT_BOOL, - .help = "enables use of O_DIRECT (bypass the host page cache)", - },{ - .name = BDRV_OPT_CACHE_NO_FLUSH, - .type = QEMU_OPT_BOOL, - .help = "ignore any flush requests for the device", - },{ .name = "aio", .type = QEMU_OPT_STRING, .help = "host AIO implementation (threads, native)", @@ -3992,18 +3979,6 @@ static QemuOptsList qemu_root_bds_opts = { .type = QEMU_OPT_STRING, .help = "discard operation (ignore/off, unmap/on)", },{ - .name = "cache.writeback", - .type = QEMU_OPT_BOOL, - .help = "enables writeback mode for any caches", - },{ - .name = "cache.direct", - .type = QEMU_OPT_BOOL, - .help = "enables use of O_DIRECT (bypass the host page cache)", - },{ - .name = "cache.no-flush", - .type = QEMU_OPT_BOOL, - .help = "ignore any flush requests for the device", - },{ .name = "aio", .type = QEMU_OPT_STRING, .help = "host AIO implementation (threads, native)", diff --git a/include/block/block.h b/include/block/block.h index d048bbf..db8e096 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -150,6 +150,7 @@ typedef struct BDRVReopenState { BlockDriverState *bs; int flags; QDict *options; + QDict *explicit_options; void *opaque; } BDRVReopenState; @@ -197,7 +198,6 @@ int bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp); BlockDriverState *bdrv_new_root(void); BlockDriverState *bdrv_new(void); void bdrv_make_anon(BlockDriverState *bs); -void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old); void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top); void bdrv_replace_in_backing_chain(BlockDriverState *old, BlockDriverState *new); @@ -210,7 +210,8 @@ BdrvChild *bdrv_open_child(const char *filename, const BdrvChildRole *child_role, bool allow_none, Error **errp); void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd); -int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp); +int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options, + const char *bdref_key, Error **errp); int bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp); int bdrv_open(BlockDriverState **pbs, const char *filename, const char *reference, QDict *options, int flags, Error **errp); @@ -304,9 +305,9 @@ int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res, BdrvCheckMode fix); * block driver; total_work_size may change during the course of the amendment * operation */ typedef void BlockDriverAmendStatusCB(BlockDriverState *bs, int64_t offset, - int64_t total_work_size); + int64_t total_work_size, void *opaque); int bdrv_amend_options(BlockDriverState *bs_new, QemuOpts *opts, - BlockDriverAmendStatusCB *status_cb); + BlockDriverAmendStatusCB *status_cb, void *cb_opaque); /* external snapshots */ bool bdrv_recurse_is_first_non_filter(BlockDriverState *bs, diff --git a/include/block/block_int.h b/include/block/block_int.h index 66e208d..9a1c466 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -121,6 +121,7 @@ struct BlockDriver { BlockReopenQueue *queue, Error **errp); void (*bdrv_reopen_commit)(BDRVReopenState *reopen_state); void (*bdrv_reopen_abort)(BDRVReopenState *reopen_state); + void (*bdrv_join_options)(QDict *options, QDict *old_options); int (*bdrv_open)(BlockDriverState *bs, QDict *options, int flags, Error **errp); @@ -135,7 +136,7 @@ struct BlockDriver { int (*bdrv_set_key)(BlockDriverState *bs, const char *key); int (*bdrv_make_empty)(BlockDriverState *bs); - void (*bdrv_refresh_filename)(BlockDriverState *bs); + void (*bdrv_refresh_filename)(BlockDriverState *bs, QDict *options); /* aio */ BlockAIOCB *(*bdrv_aio_readv)(BlockDriverState *bs, @@ -242,7 +243,8 @@ struct BlockDriver { BdrvCheckMode fix); int (*bdrv_amend_options)(BlockDriverState *bs, QemuOpts *opts, - BlockDriverAmendStatusCB *status_cb); + BlockDriverAmendStatusCB *status_cb, + void *cb_opaque); void (*bdrv_debug_event)(BlockDriverState *bs, BlkdebugEvent event); @@ -342,7 +344,8 @@ typedef struct BdrvAioNotifier { } BdrvAioNotifier; struct BdrvChildRole { - int (*inherit_flags)(int parent_flags); + void (*inherit_options)(int *child_flags, QDict *child_options, + int parent_flags, QDict *parent_options); }; extern const BdrvChildRole child_file; @@ -350,6 +353,7 @@ extern const BdrvChildRole child_format; struct BdrvChild { BlockDriverState *bs; + char *name; const BdrvChildRole *role; QLIST_ENTRY(BdrvChild) next; QLIST_ENTRY(BdrvChild) next_parent; @@ -456,6 +460,7 @@ struct BlockDriverState { QLIST_HEAD(, BdrvChild) parents; QDict *options; + QDict *explicit_options; BlockdevDetectZeroesOptions detect_zeroes; /* The error object in use for blocking operations on backing_hd */ @@ -2040,7 +2040,10 @@ static ImageInfoList *collect_image_info_list(const char *filename, if (info->has_full_backing_filename) { filename = info->full_backing_filename; } else if (info->has_backing_filename) { - filename = info->backing_filename; + error_report("Could not determine absolute backing filename," + " but backing filename '%s' present", + info->backing_filename); + goto err; } if (info->has_backing_filename_format) { fmt = info->backing_filename_format; @@ -2896,7 +2899,8 @@ out: } static void amend_status_cb(BlockDriverState *bs, - int64_t offset, int64_t total_work_size) + int64_t offset, int64_t total_work_size, + void *opaque) { qemu_progress_print(100.f * offset / total_work_size, 0); } @@ -3020,7 +3024,7 @@ static int img_amend(int argc, char **argv) /* In case the driver does not call amend_status_cb() */ qemu_progress_print(0.f, 0); - ret = bdrv_amend_options(bs, opts, &amend_status_cb); + ret = bdrv_amend_options(bs, opts, &amend_status_cb, NULL); qemu_progress_print(100.f, 0); if (ret < 0) { error_report("Error while amending options: %s", strerror(-ret)); diff --git a/tests/hd-geo-test.c b/tests/hd-geo-test.c index 00afc20..13b763d 100644 --- a/tests/hd-geo-test.c +++ b/tests/hd-geo-test.c @@ -206,13 +206,13 @@ static int setup_ide(int argc, char *argv[], int argv_sz, { char *s1, *s2, *s3; - s1 = g_strdup_printf("-drive id=drive%d,if=%s,format=raw", + s1 = g_strdup_printf("-drive id=drive%d,if=%s", ide_idx, dev ? "none" : "ide"); s2 = dev ? g_strdup("") : g_strdup_printf(",index=%d", ide_idx); if (img_secs[img_idx] >= 0) { setup_mbr(img_idx, mbr); - s3 = g_strdup_printf(",file=%s", img_file_name[img_idx]); + s3 = g_strdup_printf(",format=raw,file=%s", img_file_name[img_idx]); } else { s3 = g_strdup(",media=cdrom"); } diff --git a/tests/qemu-iotests/043.out b/tests/qemu-iotests/043.out index 33f8cc3..b37d2a3 100644 --- a/tests/qemu-iotests/043.out +++ b/tests/qemu-iotests/043.out @@ -44,6 +44,7 @@ cluster_size: 65536 "filename": "TEST_DIR/t.IMGFMT", "cluster-size": 65536, "format": "IMGFMT", + "full-backing-filename": "TEST_DIR/t.IMGFMT.2.base", "backing-filename": "TEST_DIR/t.IMGFMT.2.base", "dirty-flag": false }, @@ -52,6 +53,7 @@ cluster_size: 65536 "filename": "TEST_DIR/t.IMGFMT.2.base", "cluster-size": 65536, "format": "IMGFMT", + "full-backing-filename": "TEST_DIR/t.IMGFMT.1.base", "backing-filename": "TEST_DIR/t.IMGFMT.1.base", "dirty-flag": false }, diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051 index 17dbf04..75713c2 100755 --- a/tests/qemu-iotests/051 +++ b/tests/qemu-iotests/051 @@ -61,7 +61,7 @@ function do_run_qemu() function run_qemu() { - do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu + do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_generated_node_ids } size=128M @@ -148,33 +148,49 @@ run_qemu -drive if=ide run_qemu -drive if=virtio run_qemu -drive if=scsi -run_qemu -drive if=none,id=disk -device ide-cd,drive=disk -run_qemu -drive if=none,id=disk -device lsi53c895a -device scsi-cd,drive=disk - -run_qemu -drive if=none,id=disk -device ide-drive,drive=disk -run_qemu -drive if=none,id=disk -device ide-hd,drive=disk -run_qemu -drive if=none,id=disk -device lsi53c895a -device scsi-disk,drive=disk -run_qemu -drive if=none,id=disk -device lsi53c895a -device scsi-hd,drive=disk +case "$QEMU_DEFAULT_MACHINE" in + pc) + run_qemu -drive if=none,id=disk -device ide-cd,drive=disk + run_qemu -drive if=none,id=disk -device lsi53c895a -device scsi-cd,drive=disk + run_qemu -drive if=none,id=disk -device ide-drive,drive=disk + run_qemu -drive if=none,id=disk -device ide-hd,drive=disk + run_qemu -drive if=none,id=disk -device lsi53c895a -device scsi-disk,drive=disk + run_qemu -drive if=none,id=disk -device lsi53c895a -device scsi-hd,drive=disk + ;; + *) + ;; +esac echo echo === Read-only === echo -run_qemu -drive file="$TEST_IMG",if=floppy,readonly=on -run_qemu -drive file="$TEST_IMG",if=ide,media=cdrom,readonly=on -run_qemu -drive file="$TEST_IMG",if=scsi,media=cdrom,readonly=on +case "$QEMU_DEFAULT_MACHINE" in + pc) + run_qemu -drive file="$TEST_IMG",if=floppy,readonly=on + run_qemu -drive file="$TEST_IMG",if=ide,media=cdrom,readonly=on + run_qemu -drive file="$TEST_IMG",if=scsi,media=cdrom,readonly=on + run_qemu -drive file="$TEST_IMG",if=ide,readonly=on + ;; + *) + ;; +esac -run_qemu -drive file="$TEST_IMG",if=ide,readonly=on run_qemu -drive file="$TEST_IMG",if=virtio,readonly=on run_qemu -drive file="$TEST_IMG",if=scsi,readonly=on -run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device ide-cd,drive=disk -run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device lsi53c895a -device scsi-cd,drive=disk - -run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device ide-drive,drive=disk -run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device ide-hd,drive=disk -run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device lsi53c895a -device scsi-disk,drive=disk -run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device lsi53c895a -device scsi-hd,drive=disk +case "$QEMU_DEFAULT_MACHINE" in + pc) + run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device ide-cd,drive=disk + run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device lsi53c895a -device scsi-cd,drive=disk + run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device ide-drive,drive=disk + run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device ide-hd,drive=disk + run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device lsi53c895a -device scsi-disk,drive=disk + run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device lsi53c895a -device scsi-hd,drive=disk + ;; + *) + ;; +esac echo echo === Cache modes === @@ -183,12 +199,20 @@ echo # Cannot use the test image because cache=none might not work on the host FS # Use cdrom so that we won't get errors about missing media -run_qemu -drive media=cdrom,cache=none -run_qemu -drive media=cdrom,cache=directsync -run_qemu -drive media=cdrom,cache=writeback -run_qemu -drive media=cdrom,cache=writethrough -run_qemu -drive media=cdrom,cache=unsafe -run_qemu -drive media=cdrom,cache=invalid_value +run_qemu -drive driver=null-co,cache=none +run_qemu -drive driver=null-co,cache=directsync +run_qemu -drive driver=null-co,cache=writeback +run_qemu -drive driver=null-co,cache=writethrough +run_qemu -drive driver=null-co,cache=unsafe +run_qemu -drive driver=null-co,cache=invalid_value + +# Can't test direct=on here because O_DIRECT might not be supported on this FS +# Test 142 checks the direct=on cases + +for cache in writeback writethrough unsafe invalid_value; do + echo -e "info block\ninfo block file\ninfo block backing\ninfo block backing-file" | \ + run_qemu -drive file="$TEST_IMG",cache=$cache,backing.file.filename="$TEST_IMG.base",backing.cache.no-flush=on,backing.cache.writeback=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file -nodefaults +done echo echo === Specifying the protocol layer === @@ -253,26 +277,31 @@ echo $QEMU_IO -c "write -P 0x11 0 4k" "$TEST_IMG" | _filter_qemu_io -echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file="$TEST_IMG" -snapshot | _filter_qemu_io -echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file="$TEST_IMG",snapshot=on | _filter_qemu_io -echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file.filename="$TEST_IMG",driver=qcow2,snapshot=on | _filter_qemu_io -echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file.filename="$TEST_IMG",driver=qcow2 -snapshot | _filter_qemu_io -echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file="file:$TEST_IMG" -snapshot | _filter_qemu_io -echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file="file:$TEST_IMG",snapshot=on | _filter_qemu_io +device_id="drive0" + +echo "qemu-io $device_id \"write -P 0x22 0 4k\"" | run_qemu -drive file="$TEST_IMG",if=none,id=$device_id -snapshot | _filter_qemu_io +echo "qemu-io $device_id \"write -P 0x22 0 4k\"" | run_qemu -drive file="$TEST_IMG",snapshot=on,if=none,id=$device_id | _filter_qemu_io +echo "qemu-io $device_id \"write -P 0x22 0 4k\"" | run_qemu -drive file.filename="$TEST_IMG",driver=qcow2,snapshot=on,if=none,id=$device_id\ + | _filter_qemu_io +echo "qemu-io $device_id \"write -P 0x22 0 4k\"" | run_qemu -drive file.filename="$TEST_IMG",driver=qcow2,if=none,id=$device_id -snapshot\ + | _filter_qemu_io +echo "qemu-io $device_id \"write -P 0x22 0 4k\"" | run_qemu -drive file="file:$TEST_IMG",if=none,id=$device_id -snapshot | _filter_qemu_io +echo "qemu-io $device_id \"write -P 0x22 0 4k\"" | run_qemu -drive file="file:$TEST_IMG",snapshot=on,if=none,id=$device_id | _filter_qemu_io # Opening a read-only file r/w with snapshot=on chmod u-w "$TEST_IMG" -echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file="$TEST_IMG" -snapshot | _filter_qemu_io -echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file="$TEST_IMG",snapshot=on | _filter_qemu_io +echo "qemu-io $device_id \"write -P 0x22 0 4k\"" | run_qemu -drive file="$TEST_IMG",if=none,id=$device_id -snapshot | _filter_qemu_io +echo "qemu-io $device_id \"write -P 0x22 0 4k\"" | run_qemu -drive file="$TEST_IMG",snapshot=on,if=none,id=$device_id | _filter_qemu_io chmod u+w "$TEST_IMG" $QEMU_IO -c "read -P 0x11 0 4k" "$TEST_IMG" | _filter_qemu_io -echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file="$TEST_IMG",snapshot=off | _filter_qemu_io +echo "qemu-io $device_id \"write -P 0x22 0 4k\"" | run_qemu -drive file="$TEST_IMG",snapshot=off,if=none,id=$device_id | _filter_qemu_io $QEMU_IO -c "read -P 0x22 0 4k" "$TEST_IMG" | _filter_qemu_io -echo -e 'qemu-io ide0-hd0 "write -P 0x33 0 4k"\ncommit ide0-hd0' | run_qemu -drive file="$TEST_IMG",snapshot=on | _filter_qemu_io +echo -e "qemu-io $device_id \"write -P 0x33 0 4k\"\ncommit $device_id" | run_qemu -drive file="$TEST_IMG",snapshot=on,if=none,id=$device_id\ + | _filter_qemu_io $QEMU_IO -c "read -P 0x33 0 4k" "$TEST_IMG" | _filter_qemu_io diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out index 7765aa0..143e3ea 100644 --- a/tests/qemu-iotests/051.out +++ b/tests/qemu-iotests/051.out @@ -5,16 +5,16 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/ === Unknown option === Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt= -QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=: Block format 'qcow2' used by device 'ide0-hd0' doesn't support the option 'unknown_opt' +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=: Block format 'qcow2' used by device 'virtio0' doesn't support the option 'unknown_opt' Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=on -QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=on: Block format 'qcow2' used by device 'ide0-hd0' doesn't support the option 'unknown_opt' +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=on: Block format 'qcow2' used by device 'virtio0' doesn't support the option 'unknown_opt' Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=1234 -QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=1234: Block format 'qcow2' used by device 'ide0-hd0' doesn't support the option 'unknown_opt' +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=1234: Block format 'qcow2' used by device 'virtio0' doesn't support the option 'unknown_opt' Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=foo -QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=foo: Block format 'qcow2' used by device 'ide0-hd0' doesn't support the option 'unknown_opt' +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=foo: Block format 'qcow2' used by device 'virtio0' doesn't support the option 'unknown_opt' === Unknown protocol option === @@ -59,7 +59,7 @@ QEMU X.Y.Z monitor - type 'help' for more information Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,backing.file.filename=TEST_DIR/t.qcow2.orig -nodefaults QEMU X.Y.Z monitor - type 'help' for more information (qemu) i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K -ide0-hd0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) +virtio0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) Cache mode: writeback Backing file: TEST_DIR/t.qcow2.orig (chain depth: 1) (qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K @@ -109,20 +109,23 @@ QEMU X.Y.Z monitor - type 'help' for more information Testing: -drive if=floppy QEMU X.Y.Z monitor - type 'help' for more information -(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K +(qemu) Warning: Orphaned drive without device: id=floppy0,file=,if=floppy,bus=0,unit=0 +q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K Testing: -drive if=ide,media=cdrom QEMU X.Y.Z monitor - type 'help' for more information -(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K +(qemu) Warning: Orphaned drive without device: id=ide0-cd0,file=,if=ide,bus=0,unit=0 +q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K Testing: -drive if=scsi,media=cdrom QEMU X.Y.Z monitor - type 'help' for more information -(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K +(qemu) Warning: Orphaned drive without device: id=scsi0-cd0,file=,if=scsi,bus=0,unit=0 +q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K Testing: -drive if=ide QEMU X.Y.Z monitor - type 'help' for more information -(qemu) QEMU_PROG: Device needs media, but drive is empty -QEMU_PROG: Initialization of device ide-hd failed: Device initialization failed. +(qemu) Warning: Orphaned drive without device: id=ide0-hd0,file=,if=ide,bus=0,unit=0 +q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K Testing: -drive if=virtio QEMU X.Y.Z monitor - type 'help' for more information @@ -130,113 +133,106 @@ QEMU X.Y.Z monitor - type 'help' for more information Testing: -drive if=scsi QEMU X.Y.Z monitor - type 'help' for more information -(qemu) QEMU_PROG: Initialization of device lsi53c895a failed: Device needs media, but drive is empty +(qemu) Warning: Orphaned drive without device: id=scsi0-hd0,file=,if=scsi,bus=0,unit=0 +q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K -Testing: -drive if=none,id=disk -device ide-cd,drive=disk -QEMU X.Y.Z monitor - type 'help' for more information -(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K -Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-cd,drive=disk -QEMU X.Y.Z monitor - type 'help' for more information -(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K - -Testing: -drive if=none,id=disk -device ide-drive,drive=disk -QEMU X.Y.Z monitor - type 'help' for more information -(qemu) QEMU_PROG: -device ide-drive,drive=disk: Device needs media, but drive is empty -QEMU_PROG: -device ide-drive,drive=disk: Device initialization failed. - -Testing: -drive if=none,id=disk -device ide-hd,drive=disk -QEMU X.Y.Z monitor - type 'help' for more information -(qemu) QEMU_PROG: -device ide-hd,drive=disk: Device needs media, but drive is empty -QEMU_PROG: -device ide-hd,drive=disk: Device initialization failed. +=== Read-only === -Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-disk,drive=disk +Testing: -drive file=TEST_DIR/t.qcow2,if=virtio,readonly=on QEMU X.Y.Z monitor - type 'help' for more information -(qemu) QEMU_PROG: -device scsi-disk,drive=disk: Device needs media, but drive is empty +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K -Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-hd,drive=disk +Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,readonly=on QEMU X.Y.Z monitor - type 'help' for more information -(qemu) QEMU_PROG: -device scsi-hd,drive=disk: Device needs media, but drive is empty +(qemu) Warning: Orphaned drive without device: id=scsi0-hd0,file=TEST_DIR/t.qcow2,if=scsi,bus=0,unit=0 +q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K -=== Read-only === +=== Cache modes === -Testing: -drive file=TEST_DIR/t.qcow2,if=floppy,readonly=on +Testing: -drive driver=null-co,cache=none QEMU X.Y.Z monitor - type 'help' for more information (qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K -Testing: -drive file=TEST_DIR/t.qcow2,if=ide,media=cdrom,readonly=on +Testing: -drive driver=null-co,cache=directsync QEMU X.Y.Z monitor - type 'help' for more information (qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K -Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,media=cdrom,readonly=on +Testing: -drive driver=null-co,cache=writeback QEMU X.Y.Z monitor - type 'help' for more information (qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K -Testing: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on -QEMU X.Y.Z monitor - type 'help' for more information -(qemu) QEMU_PROG: Can't use a read-only drive -QEMU_PROG: Initialization of device ide-hd failed: Device initialization failed. - -Testing: -drive file=TEST_DIR/t.qcow2,if=virtio,readonly=on +Testing: -drive driver=null-co,cache=writethrough QEMU X.Y.Z monitor - type 'help' for more information (qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K -Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,readonly=on +Testing: -drive driver=null-co,cache=unsafe QEMU X.Y.Z monitor - type 'help' for more information (qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K -Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-cd,drive=disk -QEMU X.Y.Z monitor - type 'help' for more information -(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K +Testing: -drive driver=null-co,cache=invalid_value +QEMU_PROG: -drive driver=null-co,cache=invalid_value: invalid cache option -Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-cd,drive=disk +Testing: -drive file=TEST_DIR/t.qcow2,cache=writeback,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.cache.writeback=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file -nodefaults QEMU X.Y.Z monitor - type 'help' for more information -(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K - -Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-drive,drive=disk -QEMU X.Y.Z monitor - type 'help' for more information -(qemu) QEMU_PROG: -device ide-drive,drive=disk: Can't use a read-only drive -QEMU_PROG: -device ide-drive,drive=disk: Device initialization failed. +(qemu) i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K +ide0-hd0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Cache mode: writeback + Backing file: TEST_DIR/t.qcow2.base (chain depth: 1) +(qemu) i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K[D[D[D[D[D[D[D[D[D[Dinfo block [K[D[D[D[D[D[D[D[D[D[D[Dinfo block f[K[D[D[D[D[D[D[D[D[D[D[D[Dinfo block fi[K[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block fil[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block file[K -Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-hd,drive=disk -QEMU X.Y.Z monitor - type 'help' for more information -(qemu) QEMU_PROG: -device ide-hd,drive=disk: Can't use a read-only drive -QEMU_PROG: -device ide-hd,drive=disk: Device initialization failed. +file: TEST_DIR/t.qcow2 (file) + Cache mode: writeback +(qemu) i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K[D[D[D[D[D[D[D[D[D[Dinfo block [K[D[D[D[D[D[D[D[D[D[D[Dinfo block b[K[D[D[D[D[D[D[D[D[D[D[D[Dinfo block ba[K[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block bac[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block back[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backi[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backin[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing[K +backing: TEST_DIR/t.qcow2.base (qcow2, read-only) + Cache mode: writeback, ignore flushes +(qemu) i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K[D[D[D[D[D[D[D[D[D[Dinfo block [K[D[D[D[D[D[D[D[D[D[D[Dinfo block b[K[D[D[D[D[D[D[D[D[D[D[D[Dinfo block ba[K[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block bac[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block back[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backi[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backin[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing-[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing-f[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing-fi[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing-fil[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing-file[K -Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-disk,drive=disk -QEMU X.Y.Z monitor - type 'help' for more information +backing-file: TEST_DIR/t.qcow2.base (file, read-only) + Cache mode: writeback, ignore flushes (qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K -Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-hd,drive=disk +Testing: -drive file=TEST_DIR/t.qcow2,cache=writethrough,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.cache.writeback=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file -nodefaults QEMU X.Y.Z monitor - type 'help' for more information -(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K - - -=== Cache modes === +(qemu) i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K +ide0-hd0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Cache mode: writethrough + Backing file: TEST_DIR/t.qcow2.base (chain depth: 1) +(qemu) i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K[D[D[D[D[D[D[D[D[D[Dinfo block [K[D[D[D[D[D[D[D[D[D[D[Dinfo block f[K[D[D[D[D[D[D[D[D[D[D[D[Dinfo block fi[K[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block fil[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block file[K -Testing: -drive media=cdrom,cache=none -QEMU X.Y.Z monitor - type 'help' for more information -(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K +file: TEST_DIR/t.qcow2 (file) + Cache mode: writeback +(qemu) i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K[D[D[D[D[D[D[D[D[D[Dinfo block [K[D[D[D[D[D[D[D[D[D[D[Dinfo block b[K[D[D[D[D[D[D[D[D[D[D[D[Dinfo block ba[K[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block bac[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block back[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backi[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backin[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing[K +backing: TEST_DIR/t.qcow2.base (qcow2, read-only) + Cache mode: writeback, ignore flushes +(qemu) i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K[D[D[D[D[D[D[D[D[D[Dinfo block [K[D[D[D[D[D[D[D[D[D[D[Dinfo block b[K[D[D[D[D[D[D[D[D[D[D[D[Dinfo block ba[K[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block bac[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block back[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backi[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backin[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing-[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing-f[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing-fi[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing-fil[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing-file[K -Testing: -drive media=cdrom,cache=directsync -QEMU X.Y.Z monitor - type 'help' for more information +backing-file: TEST_DIR/t.qcow2.base (file, read-only) + Cache mode: writeback, ignore flushes (qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K -Testing: -drive media=cdrom,cache=writeback +Testing: -drive file=TEST_DIR/t.qcow2,cache=unsafe,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.cache.writeback=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file -nodefaults QEMU X.Y.Z monitor - type 'help' for more information -(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K +(qemu) i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K +ide0-hd0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Cache mode: writeback, ignore flushes + Backing file: TEST_DIR/t.qcow2.base (chain depth: 1) +(qemu) i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K[D[D[D[D[D[D[D[D[D[Dinfo block [K[D[D[D[D[D[D[D[D[D[D[Dinfo block f[K[D[D[D[D[D[D[D[D[D[D[D[Dinfo block fi[K[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block fil[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block file[K -Testing: -drive media=cdrom,cache=writethrough -QEMU X.Y.Z monitor - type 'help' for more information -(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K +file: TEST_DIR/t.qcow2 (file) + Cache mode: writeback, ignore flushes +(qemu) i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K[D[D[D[D[D[D[D[D[D[Dinfo block [K[D[D[D[D[D[D[D[D[D[D[Dinfo block b[K[D[D[D[D[D[D[D[D[D[D[D[Dinfo block ba[K[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block bac[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block back[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backi[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backin[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing[K +backing: TEST_DIR/t.qcow2.base (qcow2, read-only) + Cache mode: writeback, ignore flushes +(qemu) i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K[D[D[D[D[D[D[D[D[D[Dinfo block [K[D[D[D[D[D[D[D[D[D[D[Dinfo block b[K[D[D[D[D[D[D[D[D[D[D[D[Dinfo block ba[K[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block bac[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block back[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backi[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backin[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing-[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing-f[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing-fi[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing-fil[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing-file[K -Testing: -drive media=cdrom,cache=unsafe -QEMU X.Y.Z monitor - type 'help' for more information +backing-file: TEST_DIR/t.qcow2.base (file, read-only) + Cache mode: writeback, ignore flushes (qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K -Testing: -drive media=cdrom,cache=invalid_value -QEMU_PROG: -drive media=cdrom,cache=invalid_value: invalid cache option +Testing: -drive file=TEST_DIR/t.qcow2,cache=invalid_value,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.cache.writeback=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file -nodefaults +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,cache=invalid_value,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.cache.writeback=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file: invalid cache option === Specifying the protocol layer === @@ -342,79 +338,79 @@ QEMU_PROG: -drive file.filename=file:TEST_DIR/t.qcow2: Could not open 'file:TEST wrote 4096/4096 bytes at offset 0 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Testing: -drive file=TEST_DIR/t.qcow2 -snapshot +Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=drive0 -snapshot QEMU X.Y.Z monitor - type 'help' for more information -(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io i[K[D[D[D[D[D[D[D[D[Dqemu-io id[K[D[D[D[D[D[D[D[D[D[Dqemu-io ide[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-h[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4k"[K +(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io d[K[D[D[D[D[D[D[D[D[Dqemu-io dr[K[D[D[D[D[D[D[D[D[D[Dqemu-io dri[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io driv[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k"[K wrote 4096/4096 bytes at offset 0 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) (qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K -Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on +Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on,if=none,id=drive0 QEMU X.Y.Z monitor - type 'help' for more information -(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io i[K[D[D[D[D[D[D[D[D[Dqemu-io id[K[D[D[D[D[D[D[D[D[D[Dqemu-io ide[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-h[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4k"[K +(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io d[K[D[D[D[D[D[D[D[D[Dqemu-io dr[K[D[D[D[D[D[D[D[D[D[Dqemu-io dri[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io driv[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k"[K wrote 4096/4096 bytes at offset 0 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) (qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K -Testing: -drive file.filename=TEST_DIR/t.qcow2,driver=qcow2,snapshot=on +Testing: -drive file.filename=TEST_DIR/t.qcow2,driver=qcow2,snapshot=on,if=none,id=drive0 QEMU X.Y.Z monitor - type 'help' for more information -(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io i[K[D[D[D[D[D[D[D[D[Dqemu-io id[K[D[D[D[D[D[D[D[D[D[Dqemu-io ide[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-h[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4k"[K +(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io d[K[D[D[D[D[D[D[D[D[Dqemu-io dr[K[D[D[D[D[D[D[D[D[D[Dqemu-io dri[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io driv[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k"[K wrote 4096/4096 bytes at offset 0 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) (qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K -Testing: -drive file.filename=TEST_DIR/t.qcow2,driver=qcow2 -snapshot +Testing: -drive file.filename=TEST_DIR/t.qcow2,driver=qcow2,if=none,id=drive0 -snapshot QEMU X.Y.Z monitor - type 'help' for more information -(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io i[K[D[D[D[D[D[D[D[D[Dqemu-io id[K[D[D[D[D[D[D[D[D[D[Dqemu-io ide[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-h[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4k"[K +(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io d[K[D[D[D[D[D[D[D[D[Dqemu-io dr[K[D[D[D[D[D[D[D[D[D[Dqemu-io dri[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io driv[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k"[K wrote 4096/4096 bytes at offset 0 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) (qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K -Testing: -drive file=file:TEST_DIR/t.qcow2 -snapshot +Testing: -drive file=file:TEST_DIR/t.qcow2,if=none,id=drive0 -snapshot QEMU X.Y.Z monitor - type 'help' for more information -(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io i[K[D[D[D[D[D[D[D[D[Dqemu-io id[K[D[D[D[D[D[D[D[D[D[Dqemu-io ide[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-h[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4k"[K +(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io d[K[D[D[D[D[D[D[D[D[Dqemu-io dr[K[D[D[D[D[D[D[D[D[D[Dqemu-io dri[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io driv[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k"[K wrote 4096/4096 bytes at offset 0 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) (qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K -Testing: -drive file=file:TEST_DIR/t.qcow2,snapshot=on +Testing: -drive file=file:TEST_DIR/t.qcow2,snapshot=on,if=none,id=drive0 QEMU X.Y.Z monitor - type 'help' for more information -(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io i[K[D[D[D[D[D[D[D[D[Dqemu-io id[K[D[D[D[D[D[D[D[D[D[Dqemu-io ide[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-h[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4k"[K +(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io d[K[D[D[D[D[D[D[D[D[Dqemu-io dr[K[D[D[D[D[D[D[D[D[D[Dqemu-io dri[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io driv[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k"[K wrote 4096/4096 bytes at offset 0 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) (qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K -Testing: -drive file=TEST_DIR/t.qcow2 -snapshot +Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=drive0 -snapshot QEMU X.Y.Z monitor - type 'help' for more information -(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io i[K[D[D[D[D[D[D[D[D[Dqemu-io id[K[D[D[D[D[D[D[D[D[D[Dqemu-io ide[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-h[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4k"[K +(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io d[K[D[D[D[D[D[D[D[D[Dqemu-io dr[K[D[D[D[D[D[D[D[D[D[Dqemu-io dri[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io driv[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k"[K wrote 4096/4096 bytes at offset 0 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) (qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K -Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on +Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on,if=none,id=drive0 QEMU X.Y.Z monitor - type 'help' for more information -(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io i[K[D[D[D[D[D[D[D[D[Dqemu-io id[K[D[D[D[D[D[D[D[D[D[Dqemu-io ide[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-h[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4k"[K +(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io d[K[D[D[D[D[D[D[D[D[Dqemu-io dr[K[D[D[D[D[D[D[D[D[D[Dqemu-io dri[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io driv[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k"[K wrote 4096/4096 bytes at offset 0 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) (qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K read 4096/4096 bytes at offset 0 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Testing: -drive file=TEST_DIR/t.qcow2,snapshot=off +Testing: -drive file=TEST_DIR/t.qcow2,snapshot=off,if=none,id=drive0 QEMU X.Y.Z monitor - type 'help' for more information -(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io i[K[D[D[D[D[D[D[D[D[Dqemu-io id[K[D[D[D[D[D[D[D[D[D[Dqemu-io ide[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-h[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x22 0 4k"[K +(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io d[K[D[D[D[D[D[D[D[D[Dqemu-io dr[K[D[D[D[D[D[D[D[D[D[Dqemu-io dri[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io driv[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k"[K wrote 4096/4096 bytes at offset 0 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) (qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K read 4096/4096 bytes at offset 0 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on +Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on,if=none,id=drive0 QEMU X.Y.Z monitor - type 'help' for more information -(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io i[K[D[D[D[D[D[D[D[D[Dqemu-io id[K[D[D[D[D[D[D[D[D[D[Dqemu-io ide[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-h[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x3[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x33[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x33 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x33 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x33 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x33 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x33 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io ide0-hd0 "write -P 0x33 0 4k"[K +(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io d[K[D[D[D[D[D[D[D[D[Dqemu-io dr[K[D[D[D[D[D[D[D[D[D[Dqemu-io dri[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io driv[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x3[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x33[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x33 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x33 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x33 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x33 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x33 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x33 0 4k"[K wrote 4096/4096 bytes at offset 0 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -(qemu) c[K[Dco[K[D[Dcom[K[D[D[Dcomm[K[D[D[D[Dcommi[K[D[D[D[D[Dcommit[K[D[D[D[D[D[Dcommit [K[D[D[D[D[D[D[Dcommit i[K[D[D[D[D[D[D[D[Dcommit id[K[D[D[D[D[D[D[D[D[Dcommit ide[K[D[D[D[D[D[D[D[D[D[Dcommit ide0[K[D[D[D[D[D[D[D[D[D[D[Dcommit ide0-[K[D[D[D[D[D[D[D[D[D[D[D[Dcommit ide0-h[K[D[D[D[D[D[D[D[D[D[D[D[D[Dcommit ide0-hd[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dcommit ide0-hd0[K +(qemu) c[K[Dco[K[D[Dcom[K[D[D[Dcomm[K[D[D[D[Dcommi[K[D[D[D[D[Dcommit[K[D[D[D[D[D[Dcommit [K[D[D[D[D[D[D[Dcommit d[K[D[D[D[D[D[D[D[Dcommit dr[K[D[D[D[D[D[D[D[D[Dcommit dri[K[D[D[D[D[D[D[D[D[D[Dcommit driv[K[D[D[D[D[D[D[D[D[D[D[Dcommit drive[K[D[D[D[D[D[D[D[D[D[D[D[Dcommit drive0[K (qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K read 4096/4096 bytes at offset 0 diff --git a/tests/qemu-iotests/051.pc.out b/tests/qemu-iotests/051.pc.out new file mode 100644 index 0000000..05c925a --- /dev/null +++ b/tests/qemu-iotests/051.pc.out @@ -0,0 +1,482 @@ +QA output created by 051 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base + +=== Unknown option === + +Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt= +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=: Block format 'qcow2' used by device 'ide0-hd0' doesn't support the option 'unknown_opt' + +Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=on +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=on: Block format 'qcow2' used by device 'ide0-hd0' doesn't support the option 'unknown_opt' + +Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=1234 +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=1234: Block format 'qcow2' used by device 'ide0-hd0' doesn't support the option 'unknown_opt' + +Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=foo +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=foo: Block format 'qcow2' used by device 'ide0-hd0' doesn't support the option 'unknown_opt' + + +=== Unknown protocol option === + +Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,file.unknown_opt= +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,file.unknown_opt=: Block protocol 'file' doesn't support the option 'unknown_opt' + +Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,file.unknown_opt=on +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,file.unknown_opt=on: Block protocol 'file' doesn't support the option 'unknown_opt' + +Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,file.unknown_opt=1234 +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,file.unknown_opt=1234: Block protocol 'file' doesn't support the option 'unknown_opt' + +Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,file.unknown_opt=foo +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,file.unknown_opt=foo: Block protocol 'file' doesn't support the option 'unknown_opt' + + +=== Invalid format === + +Testing: -drive file=TEST_DIR/t.qcow2,format=foo +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=foo: Unknown driver 'foo' + +Testing: -drive file=TEST_DIR/t.qcow2,driver=foo +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,driver=foo: Unknown driver 'foo' + +Testing: -drive file=TEST_DIR/t.qcow2,driver=raw,format=qcow2 +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,driver=raw,format=qcow2: Cannot specify both 'driver' and 'format' + +Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,format=qcow2 +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,driver=qcow2,format=qcow2: Cannot specify both 'driver' and 'format' + + +=== Device without drive === + +Testing: -device virtio-scsi-pci -device scsi-hd +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) QEMU_PROG: -device scsi-hd: drive property not set + + +=== Overriding backing file === + +Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,backing.file.filename=TEST_DIR/t.qcow2.orig -nodefaults +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K +ide0-hd0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Cache mode: writeback + Backing file: TEST_DIR/t.qcow2.orig (chain depth: 1) +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file=TEST_DIR/t.qcow2,driver=raw,backing.file.filename=TEST_DIR/t.qcow2.orig +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,driver=raw,backing.file.filename=TEST_DIR/t.qcow2.orig: Driver doesn't support backing files + +Testing: -drive file=TEST_DIR/t.qcow2,file.backing.driver=file,file.backing.filename=TEST_DIR/t.qcow2.orig +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,file.backing.driver=file,file.backing.filename=TEST_DIR/t.qcow2.orig: Driver doesn't support backing files + +Testing: -drive file=TEST_DIR/t.qcow2,file.backing.driver=qcow2,file.backing.file.filename=TEST_DIR/t.qcow2.orig +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,file.backing.driver=qcow2,file.backing.file.filename=TEST_DIR/t.qcow2.orig: Driver doesn't support backing files + + +=== Enable and disable lazy refcounting on the command line, plus some invalid values === + +Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=off +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts= +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=: Parameter 'lazy-refcounts' expects 'on' or 'off' + +Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=42 +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=42: Parameter 'lazy-refcounts' expects 'on' or 'off' + +Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=foo +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=foo: Parameter 'lazy-refcounts' expects 'on' or 'off' + + +=== With version 2 images enabling lazy refcounts must fail === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on: Lazy refcounts require a qcow2 image with at least qemu 1.1 compatibility level + +Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=off +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + + +=== No medium === + +Testing: -drive if=floppy +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive if=ide,media=cdrom +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive if=scsi,media=cdrom +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive if=ide +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) QEMU_PROG: Device needs media, but drive is empty +QEMU_PROG: Initialization of device ide-hd failed: Device initialization failed. + +Testing: -drive if=virtio +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) QEMU_PROG: -drive if=virtio: Device needs media, but drive is empty + +Testing: -drive if=scsi +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) QEMU_PROG: Initialization of device lsi53c895a failed: Device needs media, but drive is empty + +Testing: -drive if=none,id=disk -device ide-cd,drive=disk +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-cd,drive=disk +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive if=none,id=disk -device ide-drive,drive=disk +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) QEMU_PROG: -device ide-drive,drive=disk: Device needs media, but drive is empty +QEMU_PROG: -device ide-drive,drive=disk: Device initialization failed. + +Testing: -drive if=none,id=disk -device ide-hd,drive=disk +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) QEMU_PROG: -device ide-hd,drive=disk: Device needs media, but drive is empty +QEMU_PROG: -device ide-hd,drive=disk: Device initialization failed. + +Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-disk,drive=disk +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) QEMU_PROG: -device scsi-disk,drive=disk: Device needs media, but drive is empty + +Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-hd,drive=disk +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) QEMU_PROG: -device scsi-hd,drive=disk: Device needs media, but drive is empty + + +=== Read-only === + +Testing: -drive file=TEST_DIR/t.qcow2,if=floppy,readonly=on +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file=TEST_DIR/t.qcow2,if=ide,media=cdrom,readonly=on +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,media=cdrom,readonly=on +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) QEMU_PROG: Can't use a read-only drive +QEMU_PROG: Initialization of device ide-hd failed: Device initialization failed. + +Testing: -drive file=TEST_DIR/t.qcow2,if=virtio,readonly=on +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,readonly=on +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-cd,drive=disk +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-cd,drive=disk +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-drive,drive=disk +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) QEMU_PROG: -device ide-drive,drive=disk: Can't use a read-only drive +QEMU_PROG: -device ide-drive,drive=disk: Device initialization failed. + +Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-hd,drive=disk +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) QEMU_PROG: -device ide-hd,drive=disk: Can't use a read-only drive +QEMU_PROG: -device ide-hd,drive=disk: Device initialization failed. + +Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-disk,drive=disk +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-hd,drive=disk +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + + +=== Cache modes === + +Testing: -drive driver=null-co,cache=none +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive driver=null-co,cache=directsync +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive driver=null-co,cache=writeback +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive driver=null-co,cache=writethrough +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive driver=null-co,cache=unsafe +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive driver=null-co,cache=invalid_value +QEMU_PROG: -drive driver=null-co,cache=invalid_value: invalid cache option + +Testing: -drive file=TEST_DIR/t.qcow2,cache=writeback,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.cache.writeback=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file -nodefaults +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K +ide0-hd0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Cache mode: writeback + Backing file: TEST_DIR/t.qcow2.base (chain depth: 1) +(qemu) i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K[D[D[D[D[D[D[D[D[D[Dinfo block [K[D[D[D[D[D[D[D[D[D[D[Dinfo block f[K[D[D[D[D[D[D[D[D[D[D[D[Dinfo block fi[K[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block fil[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block file[K + +file: TEST_DIR/t.qcow2 (file) + Cache mode: writeback +(qemu) i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K[D[D[D[D[D[D[D[D[D[Dinfo block [K[D[D[D[D[D[D[D[D[D[D[Dinfo block b[K[D[D[D[D[D[D[D[D[D[D[D[Dinfo block ba[K[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block bac[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block back[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backi[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backin[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing[K +backing: TEST_DIR/t.qcow2.base (qcow2, read-only) + Cache mode: writeback, ignore flushes +(qemu) i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K[D[D[D[D[D[D[D[D[D[Dinfo block [K[D[D[D[D[D[D[D[D[D[D[Dinfo block b[K[D[D[D[D[D[D[D[D[D[D[D[Dinfo block ba[K[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block bac[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block back[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backi[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backin[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing-[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing-f[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing-fi[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing-fil[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing-file[K + +backing-file: TEST_DIR/t.qcow2.base (file, read-only) + Cache mode: writeback, ignore flushes +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file=TEST_DIR/t.qcow2,cache=writethrough,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.cache.writeback=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file -nodefaults +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K +ide0-hd0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Cache mode: writethrough + Backing file: TEST_DIR/t.qcow2.base (chain depth: 1) +(qemu) i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K[D[D[D[D[D[D[D[D[D[Dinfo block [K[D[D[D[D[D[D[D[D[D[D[Dinfo block f[K[D[D[D[D[D[D[D[D[D[D[D[Dinfo block fi[K[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block fil[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block file[K + +file: TEST_DIR/t.qcow2 (file) + Cache mode: writeback +(qemu) i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K[D[D[D[D[D[D[D[D[D[Dinfo block [K[D[D[D[D[D[D[D[D[D[D[Dinfo block b[K[D[D[D[D[D[D[D[D[D[D[D[Dinfo block ba[K[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block bac[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block back[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backi[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backin[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing[K +backing: TEST_DIR/t.qcow2.base (qcow2, read-only) + Cache mode: writeback, ignore flushes +(qemu) i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K[D[D[D[D[D[D[D[D[D[Dinfo block [K[D[D[D[D[D[D[D[D[D[D[Dinfo block b[K[D[D[D[D[D[D[D[D[D[D[D[Dinfo block ba[K[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block bac[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block back[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backi[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backin[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing-[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing-f[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing-fi[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing-fil[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing-file[K + +backing-file: TEST_DIR/t.qcow2.base (file, read-only) + Cache mode: writeback, ignore flushes +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file=TEST_DIR/t.qcow2,cache=unsafe,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.cache.writeback=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file -nodefaults +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K +ide0-hd0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) + Cache mode: writeback, ignore flushes + Backing file: TEST_DIR/t.qcow2.base (chain depth: 1) +(qemu) i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K[D[D[D[D[D[D[D[D[D[Dinfo block [K[D[D[D[D[D[D[D[D[D[D[Dinfo block f[K[D[D[D[D[D[D[D[D[D[D[D[Dinfo block fi[K[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block fil[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block file[K + +file: TEST_DIR/t.qcow2 (file) + Cache mode: writeback, ignore flushes +(qemu) i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K[D[D[D[D[D[D[D[D[D[Dinfo block [K[D[D[D[D[D[D[D[D[D[D[Dinfo block b[K[D[D[D[D[D[D[D[D[D[D[D[Dinfo block ba[K[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block bac[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block back[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backi[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backin[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing[K +backing: TEST_DIR/t.qcow2.base (qcow2, read-only) + Cache mode: writeback, ignore flushes +(qemu) i[K[Din[K[D[Dinf[K[D[D[Dinfo[K[D[D[D[Dinfo [K[D[D[D[D[Dinfo b[K[D[D[D[D[D[Dinfo bl[K[D[D[D[D[D[D[Dinfo blo[K[D[D[D[D[D[D[D[Dinfo bloc[K[D[D[D[D[D[D[D[D[Dinfo block[K[D[D[D[D[D[D[D[D[D[Dinfo block [K[D[D[D[D[D[D[D[D[D[D[Dinfo block b[K[D[D[D[D[D[D[D[D[D[D[D[Dinfo block ba[K[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block bac[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block back[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backi[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backin[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing-[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing-f[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing-fi[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing-fil[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dinfo block backing-file[K + +backing-file: TEST_DIR/t.qcow2.base (file, read-only) + Cache mode: writeback, ignore flushes +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file=TEST_DIR/t.qcow2,cache=invalid_value,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.cache.writeback=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file -nodefaults +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,cache=invalid_value,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.cache.writeback=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file: invalid cache option + + +=== Specifying the protocol layer === + +Testing: -drive file=TEST_DIR/t.qcow2,file.driver=file +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + + +=== Leaving out required options === + +Testing: -drive driver=file +QEMU_PROG: -drive driver=file: The 'file' block driver requires a file name + +Testing: -drive driver=nbd +QEMU_PROG: -drive driver=nbd: one of path and host must be specified. + +Testing: -drive driver=raw +QEMU_PROG: -drive driver=raw: Can't use 'raw' as a block driver for the protocol level + +Testing: -drive file.driver=file +QEMU_PROG: -drive file.driver=file: The 'file' block driver requires a file name + +Testing: -drive file.driver=nbd +QEMU_PROG: -drive file.driver=nbd: one of path and host must be specified. + +Testing: -drive file.driver=raw +QEMU_PROG: -drive file.driver=raw: Can't use 'raw' as a block driver for the protocol level + +Testing: -drive foo=bar +QEMU_PROG: -drive foo=bar: Must specify either driver or file + + +=== Specifying both an option and its legacy alias === + +Testing: -drive file=TEST_DIR/t.qcow2,iops=1234,throttling.iops-total=5678 +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,iops=1234,throttling.iops-total=5678: 'throttling.iops-total' and its alias 'iops' can't be used at the same time + +Testing: -drive file=TEST_DIR/t.qcow2,iops_rd=1234,throttling.iops-read=5678 +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,iops_rd=1234,throttling.iops-read=5678: 'throttling.iops-read' and its alias 'iops_rd' can't be used at the same time + +Testing: -drive file=TEST_DIR/t.qcow2,iops_wr=1234,throttling.iops-write=5678 +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,iops_wr=1234,throttling.iops-write=5678: 'throttling.iops-write' and its alias 'iops_wr' can't be used at the same time + +Testing: -drive file=TEST_DIR/t.qcow2,bps=1234,throttling.bps-total=5678 +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,bps=1234,throttling.bps-total=5678: 'throttling.bps-total' and its alias 'bps' can't be used at the same time + +Testing: -drive file=TEST_DIR/t.qcow2,bps_rd=1234,throttling.bps-read=5678 +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,bps_rd=1234,throttling.bps-read=5678: 'throttling.bps-read' and its alias 'bps_rd' can't be used at the same time + +Testing: -drive file=TEST_DIR/t.qcow2,bps_wr=1234,throttling.bps-write=5678 +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,bps_wr=1234,throttling.bps-write=5678: 'throttling.bps-write' and its alias 'bps_wr' can't be used at the same time + +Testing: -drive file=TEST_DIR/t.qcow2,iops_max=1234,throttling.iops-total-max=5678 +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,iops_max=1234,throttling.iops-total-max=5678: 'throttling.iops-total-max' and its alias 'iops_max' can't be used at the same time + +Testing: -drive file=TEST_DIR/t.qcow2,iops_rd_max=1234,throttling.iops-read-max=5678 +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,iops_rd_max=1234,throttling.iops-read-max=5678: 'throttling.iops-read-max' and its alias 'iops_rd_max' can't be used at the same time + +Testing: -drive file=TEST_DIR/t.qcow2,iops_wr_max=1234,throttling.iops-write-max=5678 +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,iops_wr_max=1234,throttling.iops-write-max=5678: 'throttling.iops-write-max' and its alias 'iops_wr_max' can't be used at the same time + +Testing: -drive file=TEST_DIR/t.qcow2,bps_max=1234,throttling.bps-total-max=5678 +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,bps_max=1234,throttling.bps-total-max=5678: 'throttling.bps-total-max' and its alias 'bps_max' can't be used at the same time + +Testing: -drive file=TEST_DIR/t.qcow2,bps_rd_max=1234,throttling.bps-read-max=5678 +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,bps_rd_max=1234,throttling.bps-read-max=5678: 'throttling.bps-read-max' and its alias 'bps_rd_max' can't be used at the same time + +Testing: -drive file=TEST_DIR/t.qcow2,bps_wr_max=1234,throttling.bps-write-max=5678 +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,bps_wr_max=1234,throttling.bps-write-max=5678: 'throttling.bps-write-max' and its alias 'bps_wr_max' can't be used at the same time + +Testing: -drive file=TEST_DIR/t.qcow2,iops_size=1234,throttling.iops-size=5678 +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,iops_size=1234,throttling.iops-size=5678: 'throttling.iops-size' and its alias 'iops_size' can't be used at the same time + +Testing: -drive file=TEST_DIR/t.qcow2,readonly=on,read-only=off +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,readonly=on,read-only=off: 'read-only' and its alias 'readonly' can't be used at the same time + + +=== Parsing protocol from file name === + +Testing: -hda foo:bar +QEMU_PROG: -hda foo:bar: Unknown protocol 'foo' + +Testing: -drive file=foo:bar +QEMU_PROG: -drive file=foo:bar: Unknown protocol 'foo' + +Testing: -drive file.filename=foo:bar +QEMU_PROG: -drive file.filename=foo:bar: Could not open 'foo:bar': No such file or directory + +Testing: -hda file:TEST_DIR/t.qcow2 +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file=file:TEST_DIR/t.qcow2 +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file.filename=file:TEST_DIR/t.qcow2 +QEMU_PROG: -drive file.filename=file:TEST_DIR/t.qcow2: Could not open 'file:TEST_DIR/t.qcow2': No such file or directory + + +=== Snapshot mode === + +wrote 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=drive0 -snapshot +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io d[K[D[D[D[D[D[D[D[D[Dqemu-io dr[K[D[D[D[D[D[D[D[D[D[Dqemu-io dri[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io driv[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k"[K +wrote 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on,if=none,id=drive0 +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io d[K[D[D[D[D[D[D[D[D[Dqemu-io dr[K[D[D[D[D[D[D[D[D[D[Dqemu-io dri[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io driv[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k"[K +wrote 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file.filename=TEST_DIR/t.qcow2,driver=qcow2,snapshot=on,if=none,id=drive0 +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io d[K[D[D[D[D[D[D[D[D[Dqemu-io dr[K[D[D[D[D[D[D[D[D[D[Dqemu-io dri[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io driv[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k"[K +wrote 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file.filename=TEST_DIR/t.qcow2,driver=qcow2,if=none,id=drive0 -snapshot +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io d[K[D[D[D[D[D[D[D[D[Dqemu-io dr[K[D[D[D[D[D[D[D[D[D[Dqemu-io dri[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io driv[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k"[K +wrote 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file=file:TEST_DIR/t.qcow2,if=none,id=drive0 -snapshot +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io d[K[D[D[D[D[D[D[D[D[Dqemu-io dr[K[D[D[D[D[D[D[D[D[D[Dqemu-io dri[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io driv[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k"[K +wrote 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file=file:TEST_DIR/t.qcow2,snapshot=on,if=none,id=drive0 +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io d[K[D[D[D[D[D[D[D[D[Dqemu-io dr[K[D[D[D[D[D[D[D[D[D[Dqemu-io dri[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io driv[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k"[K +wrote 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=drive0 -snapshot +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io d[K[D[D[D[D[D[D[D[D[Dqemu-io dr[K[D[D[D[D[D[D[D[D[D[Dqemu-io dri[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io driv[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k"[K +wrote 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on,if=none,id=drive0 +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io d[K[D[D[D[D[D[D[D[D[Dqemu-io dr[K[D[D[D[D[D[D[D[D[D[Dqemu-io dri[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io driv[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k"[K +wrote 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +read 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Testing: -drive file=TEST_DIR/t.qcow2,snapshot=off,if=none,id=drive0 +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io d[K[D[D[D[D[D[D[D[D[Dqemu-io dr[K[D[D[D[D[D[D[D[D[D[Dqemu-io dri[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io driv[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x2[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x22 0 4k"[K +wrote 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +read 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on,if=none,id=drive0 +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqe[K[D[Dqem[K[D[D[Dqemu[K[D[D[D[Dqemu-[K[D[D[D[D[Dqemu-i[K[D[D[D[D[D[Dqemu-io[K[D[D[D[D[D[D[Dqemu-io [K[D[D[D[D[D[D[D[Dqemu-io d[K[D[D[D[D[D[D[D[D[Dqemu-io dr[K[D[D[D[D[D[D[D[D[D[Dqemu-io dri[K[D[D[D[D[D[D[D[D[D[D[Dqemu-io driv[K[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive[K[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "w[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wr[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "wri[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "writ[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x3[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x33[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x33 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x33 0[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x33 0 [K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x33 0 4[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x33 0 4k[K[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[D[Dqemu-io drive0 "write -P 0x33 0 4k"[K +wrote 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +(qemu) c[K[Dco[K[D[Dcom[K[D[D[Dcomm[K[D[D[D[Dcommi[K[D[D[D[D[Dcommit[K[D[D[D[D[D[Dcommit [K[D[D[D[D[D[D[Dcommit d[K[D[D[D[D[D[D[D[Dcommit dr[K[D[D[D[D[D[D[D[D[Dcommit dri[K[D[D[D[D[D[D[D[D[D[Dcommit driv[K[D[D[D[D[D[D[D[D[D[D[Dcommit drive[K[D[D[D[D[D[D[D[D[D[D[D[Dcommit drive0[K +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +read 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +*** done diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out index f2598a8..57aae28 100644 --- a/tests/qemu-iotests/061.out +++ b/tests/qemu-iotests/061.out @@ -291,18 +291,18 @@ No errors were found on the image. === Testing invalid configurations === Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 -Lazy refcounts only supported with compatibility level 1.1 and above (use compat=1.1 or greater) +qemu-img: Lazy refcounts only supported with compatibility level 1.1 and above (use compat=1.1 or greater) qemu-img: Error while amending options: Invalid argument -Lazy refcounts only supported with compatibility level 1.1 and above (use compat=1.1 or greater) +qemu-img: Lazy refcounts only supported with compatibility level 1.1 and above (use compat=1.1 or greater) qemu-img: Error while amending options: Invalid argument -Unknown compatibility level 0.42. +qemu-img: Unknown compatibility level 0.42 qemu-img: Error while amending options: Invalid argument qemu-img: Invalid parameter 'foo' -Changing the cluster size is not supported. +qemu-img: Changing the cluster size is not supported qemu-img: Error while amending options: Operation not supported -Changing the encryption flag is not supported. +qemu-img: Changing the encryption flag is not supported qemu-img: Error while amending options: Operation not supported -Cannot change preallocation mode. +qemu-img: Cannot change preallocation mode qemu-img: Error while amending options: Operation not supported === Testing correct handling of unset value === @@ -310,7 +310,7 @@ qemu-img: Error while amending options: Operation not supported Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 Should work: Should not work: -Changing the cluster size is not supported. +qemu-img: Changing the cluster size is not supported qemu-img: Error while amending options: Operation not supported === Testing zero expansion on inactive clusters === diff --git a/tests/qemu-iotests/068 b/tests/qemu-iotests/068 index b72e555..58d1d80 100755 --- a/tests/qemu-iotests/068 +++ b/tests/qemu-iotests/068 @@ -50,13 +50,23 @@ echo echo "=== Saving and reloading a VM state to/from a qcow2 image ===" echo _make_test_img $IMG_SIZE + +case "$QEMU_DEFAULT_MACHINE" in + s390-ccw-virtio) + platform_parm="-no-shutdown -machine accel=kvm" + ;; + *) + platform_parm="" + ;; +esac + # Give qemu some time to boot before saving the VM state bash -c 'sleep 1; echo -e "savevm 0\nquit"' |\ - $QEMU -nographic -monitor stdio -serial none -hda "$TEST_IMG" |\ + $QEMU $platform_parm -nographic -monitor stdio -serial none -hda "$TEST_IMG" |\ _filter_qemu # Now try to continue from that VM state (this should just work) echo quit |\ - $QEMU -nographic -monitor stdio -serial none -hda "$TEST_IMG" -loadvm 0 |\ + $QEMU $platform_parm -nographic -monitor stdio -serial none -hda "$TEST_IMG" -loadvm 0 |\ _filter_qemu # success, all done diff --git a/tests/qemu-iotests/094 b/tests/qemu-iotests/094 index 27a2be2..57a68f8 100755 --- a/tests/qemu-iotests/094 +++ b/tests/qemu-iotests/094 @@ -1,6 +1,6 @@ #!/bin/bash # -# Test case for drive-mirror to NBD (especially bdrv_swap() on NBD BDS) +# Test case for drive-mirror to NBD # # Copyright (C) 2015 Red Hat, Inc. # @@ -50,8 +50,10 @@ _send_qemu_cmd $QEMU_HANDLE \ "{'execute': 'qmp_capabilities'}" \ 'return' -# 'format': 'nbd' is not actually "correct", but this is probably the only way -# to test bdrv_swap() on an NBD BDS +# 'format': 'nbd' is not actually "correct", but this was the only way to +# test the bug fixed in commit f53a829. Though the bug's related code +# bdrv_swap() was replaced later, let's make sure we don't fall in the same +# pit again. _send_qemu_cmd $QEMU_HANDLE \ "{'execute': 'drive-mirror', 'arguments': {'device': 'src', diff --git a/tests/qemu-iotests/110.out b/tests/qemu-iotests/110.out index 0270980..b3584ff 100644 --- a/tests/qemu-iotests/110.out +++ b/tests/qemu-iotests/110.out @@ -11,7 +11,10 @@ backing file: t.IMGFMT.base (actual path: TEST_DIR/t.IMGFMT.base) === Non-reconstructable filename === -qemu-img: Cannot use relative backing file names for 'json:{"driver": "IMGFMT", "file": {"set-state.0.event": "read_aio", "image": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "driver": "blkdebug", "set-state.0.new_state": 42}}' +image: json:{"driver": "IMGFMT", "file": {"set-state.0.event": "read_aio", "image": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "driver": "blkdebug", "set-state.0.new_state": 42}} +file format: IMGFMT +virtual size: 64M (67108864 bytes) +backing file: t.IMGFMT.base (cannot determine actual path) === Backing name is always relative to the backed image === diff --git a/tests/qemu-iotests/112 b/tests/qemu-iotests/112 index 3f054a3..34ba06a 100755 --- a/tests/qemu-iotests/112 +++ b/tests/qemu-iotests/112 @@ -180,6 +180,115 @@ $QEMU_IMG snapshot -c foo "$TEST_IMG" # leaked (refcount=UINT64_MAX reference=1) _check_test_img +echo +echo '=== Amend from refcount_bits=16 to refcount_bits=1 ===' +echo + +_make_test_img 64M +print_refcount_bits + +$QEMU_IO -c 'write 16M 32M' "$TEST_IMG" | _filter_qemu_io +$QEMU_IMG amend -o refcount_bits=1 "$TEST_IMG" +_check_test_img +print_refcount_bits + +echo +echo '=== Amend from refcount_bits=1 to refcount_bits=64 ===' +echo + +$QEMU_IMG amend -o refcount_bits=64 "$TEST_IMG" +_check_test_img +print_refcount_bits + +echo +echo '=== Amend to compat=0.10 ===' +echo + +# Should not work because refcount_bits needs to be 16 for compat=0.10 +$QEMU_IMG amend -o compat=0.10 "$TEST_IMG" +print_refcount_bits +# Should work +$QEMU_IMG amend -o compat=0.10,refcount_bits=16 "$TEST_IMG" +_check_test_img +print_refcount_bits + +# Get back to compat=1.1 and refcount_bits=16 +$QEMU_IMG amend -o compat=1.1 "$TEST_IMG" +print_refcount_bits +# Should not work +$QEMU_IMG amend -o refcount_bits=32,compat=0.10 "$TEST_IMG" +print_refcount_bits + +echo +echo '=== Amend with snapshot ===' +echo + +$QEMU_IMG snapshot -c foo "$TEST_IMG" +# Just to have different refcounts across the image +$QEMU_IO -c 'write 0 16M' "$TEST_IMG" | _filter_qemu_io + +# Should not work (may work in the future by first decreasing all refcounts so +# they fit into the target range by copying them) +$QEMU_IMG amend -o refcount_bits=1 "$TEST_IMG" +_check_test_img +print_refcount_bits + +# Should work +$QEMU_IMG amend -o refcount_bits=2 "$TEST_IMG" +_check_test_img +print_refcount_bits + +echo +echo '=== Testing too many references for check ===' +echo + +IMGOPTS="$IMGOPTS,refcount_bits=1" _make_test_img 64M +print_refcount_bits + +# This cluster should be created at 0x50000 +$QEMU_IO -c 'write 0 64k' "$TEST_IMG" | _filter_qemu_io +# Now make the second L2 entry (the L2 table should be at 0x40000) point to that +# cluster, so we have two references +poke_file "$TEST_IMG" $((0x40008)) "\x80\x00\x00\x00\x00\x05\x00\x00" + +# This should say "please use amend" +_check_test_img -r all + +# So we do that +$QEMU_IMG amend -o refcount_bits=2 "$TEST_IMG" +print_refcount_bits + +# And try again +_check_test_img -r all + +echo +echo '=== Multiple walks necessary during amend ===' +echo + +IMGOPTS="$IMGOPTS,refcount_bits=1,cluster_size=512" _make_test_img 64k + +# Cluster 0 is the image header, clusters 1 to 4 are used by the L1 table, a +# single L2 table, the reftable and a single refblock. This creates 58 data +# clusters (actually, the L2 table is created here, too), so in total there are +# then 63 used clusters in the image. With a refcount width of 64, one refblock +# describes 64 clusters (512 bytes / 64 bits/entry = 64 entries), so this will +# make the first refblock in the amended image have exactly one free entry. +$QEMU_IO -c "write 0 $((58 * 512))" "$TEST_IMG" | _filter_qemu_io + +# Now change the refcount width; since the first new refblock will have exactly +# one free entry, that entry will be used to store its own reference. No other +# refblocks are needed, so then the new reftable will be allocated; since the +# first new refblock is completely filled up, this will require a new refblock +# which is why the refcount width changing function will need to run through +# everything one more time until the allocations are stable. +# Having more walks than usual should be visible as regressing progress (from +# 66.67 % (2/3 walks) to 50.00 % (2/4 walks)). +$QEMU_IMG amend -o refcount_bits=64 -p "$TEST_IMG" | tr '\r' '\n' \ + | grep -A 1 '66.67' +print_refcount_bits + +_check_test_img + # success, all done echo '*** done' diff --git a/tests/qemu-iotests/112.out b/tests/qemu-iotests/112.out index 8dd3df0..81b04d1 100644 --- a/tests/qemu-iotests/112.out +++ b/tests/qemu-iotests/112.out @@ -81,4 +81,75 @@ Leaked cluster 6 refcount=1 reference=0 2 leaked clusters were found on the image. This means waste of disk space, but no harm to data. + +=== Amend from refcount_bits=16 to refcount_bits=1 === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +refcount bits: 16 +wrote 33554432/33554432 bytes at offset 16777216 +32 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +No errors were found on the image. +refcount bits: 1 + +=== Amend from refcount_bits=1 to refcount_bits=64 === + +No errors were found on the image. +refcount bits: 64 + +=== Amend to compat=0.10 === + +qemu-img: compat=0.10 requires refcount_bits=16 +qemu-img: Error while amending options: Operation not supported +refcount bits: 64 +No errors were found on the image. +refcount bits: 16 +refcount bits: 16 +qemu-img: Different refcount widths than 16 bits require compatibility level 1.1 or above (use compat=1.1 or greater) +qemu-img: Error while amending options: Invalid argument +refcount bits: 16 + +=== Amend with snapshot === + +wrote 16777216/16777216 bytes at offset 0 +16 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +qemu-img: Cannot decrease refcount entry width to 1 bits: Cluster at offset 0x50000 has a refcount of 2 +qemu-img: Error while amending options: Invalid argument +No errors were found on the image. +refcount bits: 16 +No errors were found on the image. +refcount bits: 2 + +=== Testing too many references for check === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +refcount bits: 1 +wrote 65536/65536 bytes at offset 0 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +ERROR: overflow cluster offset=0x50000 +Use qemu-img amend to increase the refcount entry width or qemu-img convert to create a clean copy if the image cannot be opened for writing + +1 errors were found on the image. +Data may be corrupted, or further writes to the image may corrupt it. +refcount bits: 2 +ERROR cluster 5 refcount=1 reference=2 +Repairing cluster 5 refcount=1 reference=2 +Repairing OFLAG_COPIED data cluster: l2_entry=8000000000050000 refcount=2 +Repairing OFLAG_COPIED data cluster: l2_entry=8000000000050000 refcount=2 +The following inconsistencies were found and repaired: + + 0 leaked clusters + 3 corruptions + +Double checking the fixed image now... +No errors were found on the image. + +=== Multiple walks necessary during amend === + +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65536 +wrote 29696/29696 bytes at offset 0 +29 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + (66.67/100%) + (50.00/100%) +refcount bits: 64 +No errors were found on the image. *** done diff --git a/tests/qemu-iotests/124 b/tests/qemu-iotests/124 index c928f01..7d33422 100644 --- a/tests/qemu-iotests/124 +++ b/tests/qemu-iotests/124 @@ -91,24 +91,31 @@ class Bitmap: try_remove(image) -class TestIncrementalBackup(iotests.QMPTestCase): - def setUp(self): +class TestIncrementalBackupBase(iotests.QMPTestCase): + def __init__(self, *args): + super(TestIncrementalBackupBase, self).__init__(*args) self.bitmaps = list() self.files = list() self.drives = list() self.vm = iotests.VM() self.err_img = os.path.join(iotests.test_dir, 'err.%s' % iotests.imgfmt) + + def setUp(self): # Create a base image with a distinctive patterning drive0 = self.add_node('drive0') self.img_create(drive0['file'], drive0['fmt']) self.vm.add_drive(drive0['file']) - io_write_patterns(drive0['file'], (('0x41', 0, 512), - ('0xd5', '1M', '32k'), - ('0xdc', '32M', '124k'))) + self.write_default_pattern(drive0['file']) self.vm.launch() + def write_default_pattern(self, target): + io_write_patterns(target, (('0x41', 0, 512), + ('0xd5', '1M', '32k'), + ('0xdc', '32M', '124k'))) + + def add_node(self, node_id, fmt=iotests.imgfmt, path=None, backup=None): if path is None: path = os.path.join(iotests.test_dir, '%s.%s' % (node_id, fmt)) @@ -259,6 +266,16 @@ class TestIncrementalBackup(iotests.QMPTestCase): self.check_backups() + def tearDown(self): + self.vm.shutdown() + for bitmap in self.bitmaps: + bitmap.cleanup() + for filename in self.files: + try_remove(filename) + + + +class TestIncrementalBackup(TestIncrementalBackupBase): def test_incremental_simple(self): ''' Test: Create and verify three incremental backups. @@ -327,63 +344,6 @@ class TestIncrementalBackup(iotests.QMPTestCase): self.check_backups() - def test_incremental_failure(self): - '''Test: Verify backups made after a failure are correct. - - Simulate a failure during an incremental backup block job, - emulate additional writes, then create another incremental backup - afterwards and verify that the backup created is correct. - ''' - - # Create a blkdebug interface to this img as 'drive1', - # but don't actually create a new image. - drive1 = self.add_node('drive1', self.drives[0]['fmt'], - path=self.drives[0]['file'], - backup=self.drives[0]['backup']) - result = self.vm.qmp('blockdev-add', options={ - 'id': drive1['id'], - 'driver': drive1['fmt'], - 'file': { - 'driver': 'blkdebug', - 'image': { - 'driver': 'file', - 'filename': drive1['file'] - }, - 'set-state': [{ - 'event': 'flush_to_disk', - 'state': 1, - 'new_state': 2 - }], - 'inject-error': [{ - 'event': 'read_aio', - 'errno': 5, - 'state': 2, - 'immediately': False, - 'once': True - }], - } - }) - self.assert_qmp(result, 'return', {}) - - self.create_anchor_backup(self.drives[0]) - self.add_bitmap('bitmap0', drive1) - # Note: at this point, during a normal execution, - # Assume that the VM resumes and begins issuing IO requests here. - - self.hmp_io_writes(drive1['id'], (('0xab', 0, 512), - ('0xfe', '16M', '256k'), - ('0x64', '32736k', '64k'))) - - result = self.create_incremental(validate=False) - self.assertFalse(result) - self.hmp_io_writes(drive1['id'], (('0x9a', 0, 512), - ('0x55', '8M', '352k'), - ('0x78', '15872k', '1M'))) - self.create_incremental() - self.vm.shutdown() - self.check_backups() - - def test_transaction_failure(self): '''Test: Verify backups made from a transaction that partially fails. @@ -531,12 +491,66 @@ class TestIncrementalBackup(iotests.QMPTestCase): granularity=64000) - def tearDown(self): +class TestIncrementalBackupBlkdebug(TestIncrementalBackupBase): + '''Incremental backup tests that utilize a BlkDebug filter on drive0.''' + + def setUp(self): + drive0 = self.add_node('drive0') + self.img_create(drive0['file'], drive0['fmt']) + self.write_default_pattern(drive0['file']) + self.vm.launch() + + def test_incremental_failure(self): + '''Test: Verify backups made after a failure are correct. + + Simulate a failure during an incremental backup block job, + emulate additional writes, then create another incremental backup + afterwards and verify that the backup created is correct. + ''' + + drive0 = self.drives[0] + result = self.vm.qmp('blockdev-add', options={ + 'id': drive0['id'], + 'driver': drive0['fmt'], + 'file': { + 'driver': 'blkdebug', + 'image': { + 'driver': 'file', + 'filename': drive0['file'] + }, + 'set-state': [{ + 'event': 'flush_to_disk', + 'state': 1, + 'new_state': 2 + }], + 'inject-error': [{ + 'event': 'read_aio', + 'errno': 5, + 'state': 2, + 'immediately': False, + 'once': True + }], + } + }) + self.assert_qmp(result, 'return', {}) + + self.create_anchor_backup(drive0) + self.add_bitmap('bitmap0', drive0) + # Note: at this point, during a normal execution, + # Assume that the VM resumes and begins issuing IO requests here. + + self.hmp_io_writes(drive0['id'], (('0xab', 0, 512), + ('0xfe', '16M', '256k'), + ('0x64', '32736k', '64k'))) + + result = self.create_incremental(validate=False) + self.assertFalse(result) + self.hmp_io_writes(drive0['id'], (('0x9a', 0, 512), + ('0x55', '8M', '352k'), + ('0x78', '15872k', '1M'))) + self.create_incremental() self.vm.shutdown() - for bitmap in self.bitmaps: - bitmap.cleanup() - for filename in self.files: - try_remove(filename) + self.check_backups() if __name__ == '__main__': diff --git a/tests/qemu-iotests/133 b/tests/qemu-iotests/133 new file mode 100755 index 0000000..8587102 --- /dev/null +++ b/tests/qemu-iotests/133 @@ -0,0 +1,90 @@ +#!/bin/bash +# +# Test for reopen +# +# Copyright (C) 2015 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=kwolf@redhat.com + +seq=`basename $0` +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +_supported_fmt qcow2 +_supported_proto file +_supported_os Linux + +TEST_IMG="$TEST_IMG.base" _make_test_img 64M +_make_test_img -b "$TEST_IMG.base" + +echo +echo "=== Check that node-name can't be changed ===" +echo + +$QEMU_IO -c 'reopen -o node-name=foo' $TEST_IMG +$QEMU_IO -c 'reopen -o file.node-name=foo' $TEST_IMG +$QEMU_IO -c 'reopen -o backing.node-name=foo' $TEST_IMG + +echo +echo "=== Check that unchanged node-name is okay ===" +echo + +# Explicitly repeated +$QEMU_IO -c "open -o node-name=foo $TEST_IMG" -c 'reopen -o node-name=foo' +$QEMU_IO -c "open -o file.node-name=foo $TEST_IMG" -c 'reopen -o file.node-name=foo' +$QEMU_IO -c "open -o backing.node-name=foo $TEST_IMG" -c 'reopen -o backing.node-name=foo' + +# Implicitly retained +$QEMU_IO -c "open -o node-name=foo $TEST_IMG" -c 'reopen' +$QEMU_IO -c "open -o file.node-name=foo $TEST_IMG" -c 'reopen' +$QEMU_IO -c "open -o backing.node-name=foo $TEST_IMG" -c 'reopen' + +echo +echo "=== Check that driver can't be changed ===" +echo + +$QEMU_IO -c 'reopen -o driver=raw' $TEST_IMG +$QEMU_IO -c 'reopen -o file.driver=qcow2' $TEST_IMG +$QEMU_IO -c 'reopen -o backing.driver=file' $TEST_IMG + +echo +echo "=== Check that unchanged driver is okay ===" +echo + +# Explicitly repeated (implicit case is covered in node-name test) +$QEMU_IO -c 'reopen -o driver=qcow2' $TEST_IMG +$QEMU_IO -c 'reopen -o file.driver=file' $TEST_IMG +$QEMU_IO -c 'reopen -o backing.driver=qcow2' $TEST_IMG + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/133.out b/tests/qemu-iotests/133.out new file mode 100644 index 0000000..cc86b94 --- /dev/null +++ b/tests/qemu-iotests/133.out @@ -0,0 +1,22 @@ +QA output created by 133 +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base + +=== Check that node-name can't be changed === + +Cannot change the option 'node-name' +Cannot change the option 'node-name' +Cannot change the option 'node-name' + +=== Check that unchanged node-name is okay === + + +=== Check that driver can't be changed === + +Cannot change the option 'driver' +Cannot change the option 'driver' +Cannot change the option 'driver' + +=== Check that unchanged driver is okay === + +*** done diff --git a/tests/qemu-iotests/142 b/tests/qemu-iotests/142 new file mode 100755 index 0000000..8aa50f8 --- /dev/null +++ b/tests/qemu-iotests/142 @@ -0,0 +1,354 @@ +#!/bin/bash +# +# Test for configuring cache modes of arbitrary nodes (requires O_DIRECT) +# +# Copyright (C) 2015 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=kwolf@redhat.com + +seq=`basename $0` +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img + rm -f $TEST_IMG.snap +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +_supported_fmt qcow2 +_supported_proto file +_supported_os Linux + +# We test all cache modes anyway, but O_DIRECT needs to be supported +_default_cache_mode none +_supported_cache_modes none directsync + +function do_run_qemu() +{ + echo Testing: "$@" + ( + if ! test -t 0; then + while read cmd; do + echo $cmd + done + fi + echo quit + ) | $QEMU -nographic -monitor stdio -nodefaults "$@" + echo +} + +function run_qemu() +{ + do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu +} + +size=128M + +TEST_IMG="$TEST_IMG.base" _make_test_img $size +TEST_IMG="$TEST_IMG.snap" _make_test_img $size +_make_test_img -b "$TEST_IMG.base" $size + +echo +echo === Simple test for all cache modes === +echo + +run_qemu -drive file="$TEST_IMG",cache=none +run_qemu -drive file="$TEST_IMG",cache=directsync +run_qemu -drive file="$TEST_IMG",cache=writeback +run_qemu -drive file="$TEST_IMG",cache=writethrough +run_qemu -drive file="$TEST_IMG",cache=unsafe +run_qemu -drive file="$TEST_IMG",cache=invalid_value + +echo +echo === Check inheritance of cache modes === +echo + +files="if=none,file=$TEST_IMG,backing.file.filename=$TEST_IMG.base" +ids="node-name=image,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file" + +function check_cache_all() +{ + # cache.direct is supposed to be inherited by both bs->file and + # bs->backing + + echo -e "cache.direct=on on none0" + echo "$hmp_cmds" | run_qemu -drive "$files","$ids",cache.direct=on | grep "Cache" + echo -e "\ncache.direct=on on file" + echo "$hmp_cmds" | run_qemu -drive "$files","$ids",file.cache.direct=on | grep "Cache" + echo -e "\ncache.direct=on on backing" + echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.cache.direct=on | grep "Cache" + echo -e "\ncache.direct=on on backing-file" + echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.file.cache.direct=on | grep "Cache" + + # cache.writeback is supposed to be inherited by bs->backing; bs->file + # always gets cache.writeback=on + + echo -e "\n\ncache.writeback=off on none0" + echo "$hmp_cmds" | run_qemu -drive "$files","$ids",cache.writeback=off | grep "Cache" + echo -e "\ncache.writeback=off on file" + echo "$hmp_cmds" | run_qemu -drive "$files","$ids",file.cache.writeback=off | grep "Cache" + echo -e "\ncache.writeback=off on backing" + echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.cache.writeback=off | grep "Cache" + echo -e "\ncache.writeback=off on backing-file" + echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.file.cache.writeback=off | grep "Cache" + + # cache.no-flush is supposed to be inherited by both bs->file and bs->backing + + echo -e "\n\ncache.no-flush=on on none0" + echo "$hmp_cmds" | run_qemu -drive "$files","$ids",cache.no-flush=on | grep "Cache" + echo -e "\ncache.no-flush=on on file" + echo "$hmp_cmds" | run_qemu -drive "$files","$ids",file.cache.no-flush=on | grep "Cache" + echo -e "\ncache.no-flush=on on backing" + echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.cache.no-flush=on | grep "Cache" + echo -e "\ncache.no-flush=on on backing-file" + echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.file.cache.no-flush=on | grep "Cache" +} + +echo +echo "--- Configure cache modes on the command line ---" +echo + +# First check the inherited cache mode after opening the image. + +hmp_cmds="info block image +info block file +info block backing +info block backing-file" + +check_cache_all + +echo +echo "--- Cache modes after reopen (live snapshot) ---" +echo + +# Then trigger a reopen and check that the cache modes are still the same. + +hmp_cmds="snapshot_blkdev -n none0 $TEST_IMG.snap $IMGFMT +info block +info block image +info block file +info block backing +info block backing-file" + +check_cache_all + +echo +echo "--- Change cache modes with reopen (qemu-io command, flags) ---" +echo + +# This one actually changes the cache mode with the reopen. For this test, the +# new cache mode is specified in the flags, not as an option. + +hmp_cmds='qemu-io none0 "reopen -c none" +info block image +info block file +info block backing +info block backing-file' + +check_cache_all + +echo +echo "--- Change cache modes with reopen (qemu-io command, options) ---" +echo + +# This one actually changes the cache mode with the reopen. For this test, the +# new cache mode is specified as an option, not in the flags. + +hmp_cmds='qemu-io none0 "reopen -o cache.direct=on" +info block image +info block file +info block backing +info block backing-file' + +check_cache_all + +echo +echo "--- Change cache modes after snapshot ---" +echo + +# This checks that the original image doesn't inherit from the snapshot + +hmp_cmds="snapshot_blkdev -n none0 $TEST_IMG.snap $IMGFMT +qemu-io none0 \"reopen -c none\" +info block none0 +info block image +info block file +info block backing +info block backing-file" + +check_cache_all + +echo +echo "--- Change cache mode in parent, child has explicit option in JSON ---" +echo + +# This checks that children with options explicitly set by the json: +# pseudo-protocol don't inherit these options from their parents. +# +# Yes, blkdebug::json:... is criminal, but I can't see another way to have a +# BDS initialised with the json: pseudo-protocol, but still have it inherit +# options from its parent node. + +hmp_cmds="qemu-io none0 \"reopen -o cache.writeback=off,cache.direct=on,cache.no-flush=on\" +info block image +info block blkdebug +info block file" + +echo "$hmp_cmds" | run_qemu -drive if=none,file="blkdebug::json:{\"filename\":\"$TEST_IMG\",,\"cache\":{\"writeback\":false,,\"direct\":false}}",node-name=image,file.node-name=blkdebug,file.image.node-name=file | grep "Cache" + +echo +echo "=== Check that referenced BDSes don't inherit ===" +echo + +drv_bkfile="if=none,driver=file,filename=$TEST_IMG.base,node-name=backing-file" +drv_bk="if=none,file=json:{'driver':'$IMGFMT',,'file':'backing-file',,'node-name':'backing'}" +drv_file="if=none,driver=file,filename=$TEST_IMG,node-name=file" +drv_img="if=none,id=blk,file=json:{'driver':'$IMGFMT',,'file':'file',,'backing':'backing',,'node-name':'image'}" + +function check_cache_all_separate() +{ + # Check cache.direct + + echo -e "cache.direct=on on blk" + echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img",cache.direct=on | grep "Cache" + echo -e "\ncache.direct=on on file" + echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file",cache.direct=on -drive "$drv_img" | grep "Cache" + echo -e "\ncache.direct=on on backing" + echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk",cache.direct=on -drive "$drv_file" -drive "$drv_img" | grep "Cache" + echo -e "\ncache.direct=on on backing-file" + echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile",cache.direct=on -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img" | grep "Cache" + + # Check cache.writeback + + echo -e "\n\ncache.writeback=off on blk" + echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img",cache.writeback=off | grep "Cache" + echo -e "\ncache.writeback=off on file" + echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file",cache.writeback=off -drive "$drv_img" | grep "Cache" + echo -e "\ncache.writeback=off on backing" + echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk",cache.writeback=off -drive "$drv_file" -drive "$drv_img" | grep "Cache" + echo -e "\ncache.writeback=off on backing-file" + echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile",cache.writeback=off -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img" | grep "Cache" + + # Check cache.no-flush + + echo -e "\n\ncache.no-flush=on on blk" + echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img",cache.no-flush=on | grep "Cache" + echo -e "\ncache.no-flush=on on file" + echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file",cache.no-flush=on -drive "$drv_img" | grep "Cache" + echo -e "\ncache.no-flush=on on backing" + echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk",cache.no-flush=on -drive "$drv_file" -drive "$drv_img" | grep "Cache" + echo -e "\ncache.no-flush=on on backing-file" + echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile",cache.no-flush=on -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img" | grep "Cache" +} + +echo +echo "--- Configure cache modes on the command line ---" +echo + +# First check the inherited cache mode after opening the image. + +hmp_cmds="info block image +info block file +info block backing +info block backing-file" + +check_cache_all_separate + +echo +echo "--- Cache modes after reopen (live snapshot) ---" +echo + +# Then trigger a reopen and check that the cache modes are still the same. + +hmp_cmds="snapshot_blkdev -n blk $TEST_IMG.snap $IMGFMT +info block blk +info block image +info block file +info block backing +info block backing-file" + +check_cache_all_separate + +echo +echo "--- Change cache modes with reopen (qemu-io command, flags) ---" +echo + +# This one actually changes the cache mode with the reopen. For this test, the +# new cache mode is specified as flags, not as option. + +hmp_cmds='qemu-io blk "reopen -c none" +info block image +info block file +info block backing +info block backing-file' + +check_cache_all_separate + + +echo +echo "=== Reopening children instead of the root ===" +echo + +files="if=none,file=$TEST_IMG,backing.file.filename=$TEST_IMG.base" +ids="node-name=image,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file" + +echo +echo "--- Basic reopen ---" +echo + +hmp_cmds='qemu-io none0 "reopen -o backing.cache.direct=on" +info block image +info block file +info block backing +info block backing-file' + +check_cache_all + +echo +echo "--- Change cache mode after reopening child ---" +echo + +# This checks that children with options explicitly set with reopen don't +# inherit these options from their parents any more + +# TODO Implement node-name support for 'qemu-io' HMP command for -c +# Can use only -o to access child node options for now + +hmp_cmds="qemu-io none0 \"reopen -o file.cache.writeback=off,file.cache.direct=off,file.cache.no-flush=off\" +qemu-io none0 \"reopen -o backing.file.cache.writeback=on,backing.file.cache.direct=off,backing.file.cache.no-flush=on\" +qemu-io none0 \"reopen -c none\" +info block image +info block file +info block backing +info block backing-file" + +echo "$hmp_cmds" | run_qemu -drive "$files","$ids" | grep "Cache" + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/142.out b/tests/qemu-iotests/142.out new file mode 100644 index 0000000..b555d5a --- /dev/null +++ b/tests/qemu-iotests/142.out @@ -0,0 +1,773 @@ +QA output created by 142 +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT.snap', fmt=IMGFMT size=134217728 +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base + +=== Simple test for all cache modes === + +Testing: -drive file=TEST_DIR/t.qcow2,cache=none +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file=TEST_DIR/t.qcow2,cache=directsync +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file=TEST_DIR/t.qcow2,cache=writeback +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file=TEST_DIR/t.qcow2,cache=writethrough +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file=TEST_DIR/t.qcow2,cache=unsafe +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K + +Testing: -drive file=TEST_DIR/t.qcow2,cache=invalid_value +QEMU_PROG: -drive file=TEST_DIR/t.qcow2,cache=invalid_value: invalid cache option + + +=== Check inheritance of cache modes === + + +--- Configure cache modes on the command line --- + +cache.direct=on on none0 + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + +cache.direct=on on file + Cache mode: writeback + Cache mode: writeback, direct + Cache mode: writeback + Cache mode: writeback + +cache.direct=on on backing + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback, direct + Cache mode: writeback, direct + +cache.direct=on on backing-file + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback, direct + + +cache.writeback=off on none0 + Cache mode: writethrough + Cache mode: writeback + Cache mode: writethrough + Cache mode: writeback + +cache.writeback=off on file + Cache mode: writeback + Cache mode: writethrough + Cache mode: writeback + Cache mode: writeback + +cache.writeback=off on backing + Cache mode: writeback + Cache mode: writeback + Cache mode: writethrough + Cache mode: writeback + +cache.writeback=off on backing-file + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + Cache mode: writethrough + + +cache.no-flush=on on none0 + Cache mode: writeback, ignore flushes + Cache mode: writeback, ignore flushes + Cache mode: writeback, ignore flushes + Cache mode: writeback, ignore flushes + +cache.no-flush=on on file + Cache mode: writeback + Cache mode: writeback, ignore flushes + Cache mode: writeback + Cache mode: writeback + +cache.no-flush=on on backing + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback, ignore flushes + Cache mode: writeback, ignore flushes + +cache.no-flush=on on backing-file + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback, ignore flushes + +--- Cache modes after reopen (live snapshot) --- + +cache.direct=on on none0 + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + +cache.direct=on on file + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback, direct + Cache mode: writeback + Cache mode: writeback + +cache.direct=on on backing + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback, direct + Cache mode: writeback, direct + +cache.direct=on on backing-file + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback, direct + + +cache.writeback=off on none0 + Cache mode: writethrough + Cache mode: writethrough + Cache mode: writeback + Cache mode: writethrough + Cache mode: writeback + +cache.writeback=off on file + Cache mode: writeback + Cache mode: writeback + Cache mode: writethrough + Cache mode: writeback + Cache mode: writeback + +cache.writeback=off on backing + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + Cache mode: writethrough + Cache mode: writeback + +cache.writeback=off on backing-file + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + Cache mode: writethrough + + +cache.no-flush=on on none0 + Cache mode: writeback, ignore flushes + Cache mode: writeback, ignore flushes + Cache mode: writeback, ignore flushes + Cache mode: writeback, ignore flushes + Cache mode: writeback, ignore flushes + +cache.no-flush=on on file + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback, ignore flushes + Cache mode: writeback + Cache mode: writeback + +cache.no-flush=on on backing + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback, ignore flushes + Cache mode: writeback, ignore flushes + +cache.no-flush=on on backing-file + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback, ignore flushes + +--- Change cache modes with reopen (qemu-io command, flags) --- + +cache.direct=on on none0 + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + +cache.direct=on on file + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + +cache.direct=on on backing + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + +cache.direct=on on backing-file + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + + +cache.writeback=off on none0 + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + +cache.writeback=off on file + Cache mode: writeback, direct + Cache mode: writethrough, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + +cache.writeback=off on backing + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writethrough, direct + Cache mode: writeback, direct + +cache.writeback=off on backing-file + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writethrough, direct + + +cache.no-flush=on on none0 + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + +cache.no-flush=on on file + Cache mode: writeback, direct + Cache mode: writeback, direct, ignore flushes + Cache mode: writeback, direct + Cache mode: writeback, direct + +cache.no-flush=on on backing + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct, ignore flushes + Cache mode: writeback, direct, ignore flushes + +cache.no-flush=on on backing-file + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct, ignore flushes + +--- Change cache modes with reopen (qemu-io command, options) --- + +cache.direct=on on none0 + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + +cache.direct=on on file + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + +cache.direct=on on backing + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + +cache.direct=on on backing-file + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + + +cache.writeback=off on none0 + Cache mode: writethrough, direct + Cache mode: writeback, direct + Cache mode: writethrough, direct + Cache mode: writeback, direct + +cache.writeback=off on file + Cache mode: writeback, direct + Cache mode: writethrough, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + +cache.writeback=off on backing + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writethrough, direct + Cache mode: writeback, direct + +cache.writeback=off on backing-file + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writethrough, direct + + +cache.no-flush=on on none0 + Cache mode: writeback, direct, ignore flushes + Cache mode: writeback, direct, ignore flushes + Cache mode: writeback, direct, ignore flushes + Cache mode: writeback, direct, ignore flushes + +cache.no-flush=on on file + Cache mode: writeback, direct + Cache mode: writeback, direct, ignore flushes + Cache mode: writeback, direct + Cache mode: writeback, direct + +cache.no-flush=on on backing + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct, ignore flushes + Cache mode: writeback, direct, ignore flushes + +cache.no-flush=on on backing-file + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct, ignore flushes + +--- Change cache modes after snapshot --- + +cache.direct=on on none0 + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + +cache.direct=on on file + Cache mode: writeback, direct + Cache mode: writeback + Cache mode: writeback, direct + Cache mode: writeback + Cache mode: writeback + +cache.direct=on on backing + Cache mode: writeback, direct + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback, direct + Cache mode: writeback, direct + +cache.direct=on on backing-file + Cache mode: writeback, direct + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback, direct + + +cache.writeback=off on none0 + Cache mode: writeback, direct + Cache mode: writethrough + Cache mode: writeback + Cache mode: writethrough + Cache mode: writeback + +cache.writeback=off on file + Cache mode: writeback, direct + Cache mode: writeback + Cache mode: writethrough + Cache mode: writeback + Cache mode: writeback + +cache.writeback=off on backing + Cache mode: writeback, direct + Cache mode: writeback + Cache mode: writeback + Cache mode: writethrough + Cache mode: writeback + +cache.writeback=off on backing-file + Cache mode: writeback, direct + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + Cache mode: writethrough + + +cache.no-flush=on on none0 + Cache mode: writeback, direct + Cache mode: writeback, ignore flushes + Cache mode: writeback, ignore flushes + Cache mode: writeback, ignore flushes + Cache mode: writeback, ignore flushes + +cache.no-flush=on on file + Cache mode: writeback, direct + Cache mode: writeback + Cache mode: writeback, ignore flushes + Cache mode: writeback + Cache mode: writeback + +cache.no-flush=on on backing + Cache mode: writeback, direct + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback, ignore flushes + Cache mode: writeback, ignore flushes + +cache.no-flush=on on backing-file + Cache mode: writeback, direct + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback, ignore flushes + +--- Change cache mode in parent, child has explicit option in JSON --- + + Cache mode: writethrough, direct, ignore flushes + Cache mode: writeback, direct, ignore flushes + Cache mode: writethrough, ignore flushes + +=== Check that referenced BDSes don't inherit === + + +--- Configure cache modes on the command line --- + +cache.direct=on on blk + Cache mode: writeback, direct + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + +cache.direct=on on file + Cache mode: writeback + Cache mode: writeback, direct + Cache mode: writeback + Cache mode: writeback + +cache.direct=on on backing + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback, direct + Cache mode: writeback + +cache.direct=on on backing-file + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback, direct + + +cache.writeback=off on blk + Cache mode: writethrough + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + +cache.writeback=off on file + Cache mode: writeback + Cache mode: writethrough + Cache mode: writeback + Cache mode: writeback + +cache.writeback=off on backing + Cache mode: writeback + Cache mode: writeback + Cache mode: writethrough + Cache mode: writeback + +cache.writeback=off on backing-file + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + Cache mode: writethrough + + +cache.no-flush=on on blk + Cache mode: writeback, ignore flushes + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + +cache.no-flush=on on file + Cache mode: writeback + Cache mode: writeback, ignore flushes + Cache mode: writeback + Cache mode: writeback + +cache.no-flush=on on backing + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback, ignore flushes + Cache mode: writeback + +cache.no-flush=on on backing-file + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback, ignore flushes + +--- Cache modes after reopen (live snapshot) --- + +cache.direct=on on blk + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + +cache.direct=on on file + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback, direct + Cache mode: writeback + Cache mode: writeback + +cache.direct=on on backing + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback, direct + Cache mode: writeback + +cache.direct=on on backing-file + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback, direct + + +cache.writeback=off on blk + Cache mode: writethrough + Cache mode: writethrough + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + +cache.writeback=off on file + Cache mode: writeback + Cache mode: writeback + Cache mode: writethrough + Cache mode: writeback + Cache mode: writeback + +cache.writeback=off on backing + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + Cache mode: writethrough + Cache mode: writeback + +cache.writeback=off on backing-file + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + Cache mode: writethrough + + +cache.no-flush=on on blk + Cache mode: writeback, ignore flushes + Cache mode: writeback, ignore flushes + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + +cache.no-flush=on on file + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback, ignore flushes + Cache mode: writeback + Cache mode: writeback + +cache.no-flush=on on backing + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback, ignore flushes + Cache mode: writeback + +cache.no-flush=on on backing-file + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback, ignore flushes + +--- Change cache modes with reopen (qemu-io command, flags) --- + +cache.direct=on on blk + Cache mode: writeback, direct + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + +cache.direct=on on file + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback + Cache mode: writeback + +cache.direct=on on backing + Cache mode: writeback, direct + Cache mode: writeback + Cache mode: writeback, direct + Cache mode: writeback + +cache.direct=on on backing-file + Cache mode: writeback, direct + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback, direct + + +cache.writeback=off on blk + Cache mode: writeback, direct + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + +cache.writeback=off on file + Cache mode: writeback, direct + Cache mode: writethrough + Cache mode: writeback + Cache mode: writeback + +cache.writeback=off on backing + Cache mode: writeback, direct + Cache mode: writeback + Cache mode: writethrough + Cache mode: writeback + +cache.writeback=off on backing-file + Cache mode: writeback, direct + Cache mode: writeback + Cache mode: writeback + Cache mode: writethrough + + +cache.no-flush=on on blk + Cache mode: writeback, direct + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback + +cache.no-flush=on on file + Cache mode: writeback, direct + Cache mode: writeback, ignore flushes + Cache mode: writeback + Cache mode: writeback + +cache.no-flush=on on backing + Cache mode: writeback, direct + Cache mode: writeback + Cache mode: writeback, ignore flushes + Cache mode: writeback + +cache.no-flush=on on backing-file + Cache mode: writeback, direct + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback, ignore flushes + +=== Reopening children instead of the root === + + +--- Basic reopen --- + +cache.direct=on on none0 + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + +cache.direct=on on file + Cache mode: writeback + Cache mode: writeback, direct + Cache mode: writeback, direct + Cache mode: writeback, direct + +cache.direct=on on backing + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback, direct + Cache mode: writeback, direct + +cache.direct=on on backing-file + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback, direct + Cache mode: writeback, direct + + +cache.writeback=off on none0 + Cache mode: writethrough + Cache mode: writeback + Cache mode: writethrough, direct + Cache mode: writeback, direct + +cache.writeback=off on file + Cache mode: writeback + Cache mode: writethrough + Cache mode: writeback, direct + Cache mode: writeback, direct + +cache.writeback=off on backing + Cache mode: writeback + Cache mode: writeback + Cache mode: writethrough, direct + Cache mode: writeback, direct + +cache.writeback=off on backing-file + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback, direct + Cache mode: writethrough, direct + + +cache.no-flush=on on none0 + Cache mode: writeback, ignore flushes + Cache mode: writeback, ignore flushes + Cache mode: writeback, direct, ignore flushes + Cache mode: writeback, direct, ignore flushes + +cache.no-flush=on on file + Cache mode: writeback + Cache mode: writeback, ignore flushes + Cache mode: writeback, direct + Cache mode: writeback, direct + +cache.no-flush=on on backing + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback, direct, ignore flushes + Cache mode: writeback, direct, ignore flushes + +cache.no-flush=on on backing-file + Cache mode: writeback + Cache mode: writeback + Cache mode: writeback, direct + Cache mode: writeback, direct, ignore flushes + +--- Change cache mode after reopening child --- + + Cache mode: writeback, direct + Cache mode: writethrough + Cache mode: writeback, direct + Cache mode: writeback, ignore flushes +*** done diff --git a/tests/qemu-iotests/common.config b/tests/qemu-iotests/common.config index 3ed51b8..60bfabf 100644 --- a/tests/qemu-iotests/common.config +++ b/tests/qemu-iotests/common.config @@ -154,11 +154,10 @@ export QEMU_IMG=_qemu_img_wrapper export QEMU_IO=_qemu_io_wrapper export QEMU_NBD=_qemu_nbd_wrapper -default_machine=$($QEMU -machine \? | awk '/(default)/{print $1}') -default_alias_machine=$($QEMU -machine \? |\ - awk -v var_default_machine="$default_machine"\)\ - '{if ($(NF-2)=="(alias"&&$(NF-1)=="of"&&$(NF)==var_default_machine){print $1}}') -if [ ! -z "$default_alias_machine" ]; then +default_machine=$($QEMU -machine help | sed -n '/(default)/ s/ .*//p') +default_alias_machine=$($QEMU -machine help | \ + sed -n "/(alias of $default_machine)/ { s/ .*//p; q; }") +if [[ "$default_alias_machine" ]]; then default_machine="$default_alias_machine" fi diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index 5a08808..d6e9219 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -134,9 +134,11 @@ 130 rw auto quick 131 rw auto quick 132 rw auto quick +133 auto quick 134 rw auto quick 135 rw auto 136 rw auto 137 rw auto 138 rw auto quick 139 rw auto quick +142 auto diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py index e02245e..0a238ec 100644 --- a/tests/qemu-iotests/iotests.py +++ b/tests/qemu-iotests/iotests.py @@ -148,12 +148,12 @@ class VM(object): def add_drive(self, path, opts='', interface='virtio'): '''Add a virtio-blk drive to the VM''' options = ['if=%s' % interface, - 'format=%s' % imgfmt, - 'cache=%s' % cachemode, 'id=drive%d' % self._num_drives] if path is not None: options.append('file=%s' % path) + options.append('format=%s' % imgfmt) + options.append('cache=%s' % cachemode) if opts: options.append(opts) diff --git a/util/qemu-progress.c b/util/qemu-progress.c index 4ee5cd0..532333e 100644 --- a/util/qemu-progress.c +++ b/util/qemu-progress.c @@ -152,7 +152,8 @@ void qemu_progress_print(float delta, int max) state.current = current; if (current > (state.last_print + state.min_skip) || - (current == 100) || (current == 0)) { + current < (state.last_print - state.min_skip) || + current == 100 || current == 0) { state.last_print = state.current; state.print(); } |