Block layer patches

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iQIcBAABAgAGBQJWdAzvAAoJEH8JsnLIjy/WBk4P/RyU+ZJGEGNpcEK0OSwZ4Oi5
 L+JDbJnsYz9zsX2yFhxv1qaGt6Lft5GDWU/nwva+urPm+hPCg7P5gF5i69iQC7wQ
 PoRZY7UVGtE5EhmZW6KVp1B6tK1Xmfyuwvc+3jgxJdwUzDCZ6w818f2e1M3HfLsj
 FSMYa3Pxj1wSxIodxko+7S0n+PugpcOjvMoM3/5Lo067tgvCbU31WW8kmVBlq0mZ
 GEEVELsZ/sSXt7Rjq+Y4qC+zwWG5ZiX3opNOqydh7eltiINiIvWhvEs1WYbIyMPb
 hpX3UX8XqHQRl8NmWpvEzTkWY6z7C+g5G7znKtqvA/S6f8KxIVcdx7wsYZHWOZja
 xkB2nJXVLxn8ni5EMfG6OpfDNY1ZTaoSysLJ9mnRnEn6cNh7qzJa+dryt1vwDJw3
 INOtjdcBPPvkLjJ3SwXGFpwcIYcpkNXdSolNsCiihOtT/2gDhP2OAoowit8+miBI
 /pN0GkTSH+syNe7SPmApFqPVWoWNVFPkKm1nxzo1H1/dbA0P5O/ly3wlGZtRA4cj
 atenXuSpT6R/hPZs55HEVdwHNoleluRSHJ6BcLZzkS+fpz8zdgsXDsv0BK8s7jXC
 EUHKiBQacny7HzrZFjtqz0rO8iBIhw62R+gYBoALYuTszbFIAY29qLQFbC6iKec5
 MA4rwYOcpNVSII22zXcs
 =RcEq
 -----END PGP SIGNATURE-----

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>
This commit is contained in:
Peter Maydell 2015-12-18 16:34:44 +00:00
commit de532ff1df
38 changed files with 3339 additions and 479 deletions

467
block.c
View File

@ -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"
@ -623,6 +624,20 @@ static int refresh_total_sectors(BlockDriverState *bs, int64_t hint)
return 0;
}
/**
* 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
*
@ -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();
}
if (child_role) {
bs->inherits_from = parent;
flags = child_role->inherit_flags(parent->open_flags);
/* 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;
}
ret = bdrv_fill_options(&options, &filename, &flags, &local_err);
bs->explicit_options = qdict_clone_shallow(options);
if (child_role) {
bs->inherits_from = parent;
child_role->inherit_options(&flags, options,
parent->open_flags, parent->options);
}
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;

View File

@ -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,

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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")));

View File

@ -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");

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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,

View File

@ -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);

View File

@ -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;

View File

@ -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) */

View File

@ -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,

View File

@ -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) {
@ -3872,18 +3871,6 @@ QemuOptsList qemu_common_drive_opts = {
.name = "discard",
.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,
@ -3991,18 +3978,6 @@ static QemuOptsList qemu_root_bds_opts = {
.name = "discard",
.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,

View File

@ -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,

View File

@ -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 */

View File

@ -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));

View File

@ -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");
}

View File

@ -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
},

View File

@ -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

View File

@ -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) iininfinfoinfo info binfo blinfo bloinfo blocinfo block
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) qququiquit
@ -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) qququiquit
(qemu) Warning: Orphaned drive without device: id=floppy0,file=,if=floppy,bus=0,unit=0
qququiquit
Testing: -drive if=ide,media=cdrom
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
(qemu) Warning: Orphaned drive without device: id=ide0-cd0,file=,if=ide,bus=0,unit=0
qququiquit
Testing: -drive if=scsi,media=cdrom
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
(qemu) Warning: Orphaned drive without device: id=scsi0-cd0,file=,if=scsi,bus=0,unit=0
qququiquit
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
qququiquit
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
Testing: -drive if=none,id=disk -device ide-cd,drive=disk
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-cd,drive=disk
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
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
(qemu) Warning: Orphaned drive without device: id=scsi0-hd0,file=,if=scsi,bus=0,unit=0
qququiquit
=== Read-only ===
Testing: -drive file=TEST_DIR/t.qcow2,if=floppy,readonly=on
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
Testing: -drive file=TEST_DIR/t.qcow2,if=ide,media=cdrom,readonly=on
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,media=cdrom,readonly=on
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
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) qququiquit
Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,readonly=on
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
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) qququiquit
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) qququiquit
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) qququiquit
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) qququiquit
(qemu) Warning: Orphaned drive without device: id=scsi0-hd0,file=TEST_DIR/t.qcow2,if=scsi,bus=0,unit=0
qququiquit
=== Cache modes ===
Testing: -drive media=cdrom,cache=none
Testing: -drive driver=null-co,cache=none
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
Testing: -drive media=cdrom,cache=directsync
Testing: -drive driver=null-co,cache=directsync
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
Testing: -drive media=cdrom,cache=writeback
Testing: -drive driver=null-co,cache=writeback
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
Testing: -drive media=cdrom,cache=writethrough
Testing: -drive driver=null-co,cache=writethrough
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
Testing: -drive media=cdrom,cache=unsafe
Testing: -drive driver=null-co,cache=unsafe
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
Testing: -drive media=cdrom,cache=invalid_value
QEMU_PROG: -drive media=cdrom,cache=invalid_value: invalid cache option
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) iininfinfoinfo info binfo blinfo bloinfo blocinfo block
ide0-hd0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
Cache mode: writeback
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block finfo block fiinfo block filinfo block file
file: TEST_DIR/t.qcow2 (file)
Cache mode: writeback
(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block binfo block bainfo block bacinfo block backinfo block backiinfo block backininfo block backing
backing: TEST_DIR/t.qcow2.base (qcow2, read-only)
Cache mode: writeback, ignore flushes
(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block binfo block bainfo block bacinfo block backinfo block backiinfo block backininfo block backinginfo block backing-info block backing-finfo block backing-fiinfo block backing-filinfo block backing-file
backing-file: TEST_DIR/t.qcow2.base (file, read-only)
Cache mode: writeback, ignore flushes
(qemu) qququiquit
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) iininfinfoinfo info binfo blinfo bloinfo blocinfo block
ide0-hd0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
Cache mode: writethrough
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block finfo block fiinfo block filinfo block file
file: TEST_DIR/t.qcow2 (file)
Cache mode: writeback
(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block binfo block bainfo block bacinfo block backinfo block backiinfo block backininfo block backing
backing: TEST_DIR/t.qcow2.base (qcow2, read-only)
Cache mode: writeback, ignore flushes
(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block binfo block bainfo block bacinfo block backinfo block backiinfo block backininfo block backinginfo block backing-info block backing-finfo block backing-fiinfo block backing-filinfo block backing-file
backing-file: TEST_DIR/t.qcow2.base (file, read-only)
Cache mode: writeback, ignore flushes
(qemu) qququiquit
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) iininfinfoinfo info binfo blinfo bloinfo blocinfo block
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) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block finfo block fiinfo block filinfo block file
file: TEST_DIR/t.qcow2 (file)
Cache mode: writeback, ignore flushes
(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block binfo block bainfo block bacinfo block backinfo block backiinfo block backininfo block backing
backing: TEST_DIR/t.qcow2.base (qcow2, read-only)
Cache mode: writeback, ignore flushes
(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block binfo block bainfo block bacinfo block backinfo block backiinfo block backininfo block backinginfo block backing-info block backing-finfo block backing-fiinfo block backing-filinfo block backing-file
backing-file: TEST_DIR/t.qcow2.base (file, read-only)
Cache mode: writeback, ignore flushes
(qemu) qququiquit
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) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io iqemu-io idqemu-io ideqemu-io ide0qemu-io ide0-qemu-io ide0-hqemu-io ide0-hdqemu-io ide0-hd0qemu-io ide0-hd0 qemu-io ide0-hd0 "qemu-io ide0-hd0 "wqemu-io ide0-hd0 "wrqemu-io ide0-hd0 "wriqemu-io ide0-hd0 "writqemu-io ide0-hd0 "writeqemu-io ide0-hd0 "write qemu-io ide0-hd0 "write -qemu-io ide0-hd0 "write -Pqemu-io ide0-hd0 "write -P qemu-io ide0-hd0 "write -P 0qemu-io ide0-hd0 "write -P 0xqemu-io ide0-hd0 "write -P 0x2qemu-io ide0-hd0 "write -P 0x22qemu-io ide0-hd0 "write -P 0x22 qemu-io ide0-hd0 "write -P 0x22 0qemu-io ide0-hd0 "write -P 0x22 0 qemu-io ide0-hd0 "write -P 0x22 0 4qemu-io ide0-hd0 "write -P 0x22 0 4kqemu-io ide0-hd0 "write -P 0x22 0 4k"
(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
(qemu) qququiquit
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) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io iqemu-io idqemu-io ideqemu-io ide0qemu-io ide0-qemu-io ide0-hqemu-io ide0-hdqemu-io ide0-hd0qemu-io ide0-hd0 qemu-io ide0-hd0 "qemu-io ide0-hd0 "wqemu-io ide0-hd0 "wrqemu-io ide0-hd0 "wriqemu-io ide0-hd0 "writqemu-io ide0-hd0 "writeqemu-io ide0-hd0 "write qemu-io ide0-hd0 "write -qemu-io ide0-hd0 "write -Pqemu-io ide0-hd0 "write -P qemu-io ide0-hd0 "write -P 0qemu-io ide0-hd0 "write -P 0xqemu-io ide0-hd0 "write -P 0x2qemu-io ide0-hd0 "write -P 0x22qemu-io ide0-hd0 "write -P 0x22 qemu-io ide0-hd0 "write -P 0x22 0qemu-io ide0-hd0 "write -P 0x22 0 qemu-io ide0-hd0 "write -P 0x22 0 4qemu-io ide0-hd0 "write -P 0x22 0 4kqemu-io ide0-hd0 "write -P 0x22 0 4k"
(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
(qemu) qququiquit
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) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io iqemu-io idqemu-io ideqemu-io ide0qemu-io ide0-qemu-io ide0-hqemu-io ide0-hdqemu-io ide0-hd0qemu-io ide0-hd0 qemu-io ide0-hd0 "qemu-io ide0-hd0 "wqemu-io ide0-hd0 "wrqemu-io ide0-hd0 "wriqemu-io ide0-hd0 "writqemu-io ide0-hd0 "writeqemu-io ide0-hd0 "write qemu-io ide0-hd0 "write -qemu-io ide0-hd0 "write -Pqemu-io ide0-hd0 "write -P qemu-io ide0-hd0 "write -P 0qemu-io ide0-hd0 "write -P 0xqemu-io ide0-hd0 "write -P 0x2qemu-io ide0-hd0 "write -P 0x22qemu-io ide0-hd0 "write -P 0x22 qemu-io ide0-hd0 "write -P 0x22 0qemu-io ide0-hd0 "write -P 0x22 0 qemu-io ide0-hd0 "write -P 0x22 0 4qemu-io ide0-hd0 "write -P 0x22 0 4kqemu-io ide0-hd0 "write -P 0x22 0 4k"
(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
(qemu) qququiquit
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) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io iqemu-io idqemu-io ideqemu-io ide0qemu-io ide0-qemu-io ide0-hqemu-io ide0-hdqemu-io ide0-hd0qemu-io ide0-hd0 qemu-io ide0-hd0 "qemu-io ide0-hd0 "wqemu-io ide0-hd0 "wrqemu-io ide0-hd0 "wriqemu-io ide0-hd0 "writqemu-io ide0-hd0 "writeqemu-io ide0-hd0 "write qemu-io ide0-hd0 "write -qemu-io ide0-hd0 "write -Pqemu-io ide0-hd0 "write -P qemu-io ide0-hd0 "write -P 0qemu-io ide0-hd0 "write -P 0xqemu-io ide0-hd0 "write -P 0x2qemu-io ide0-hd0 "write -P 0x22qemu-io ide0-hd0 "write -P 0x22 qemu-io ide0-hd0 "write -P 0x22 0qemu-io ide0-hd0 "write -P 0x22 0 qemu-io ide0-hd0 "write -P 0x22 0 4qemu-io ide0-hd0 "write -P 0x22 0 4kqemu-io ide0-hd0 "write -P 0x22 0 4k"
(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
(qemu) qququiquit
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) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io iqemu-io idqemu-io ideqemu-io ide0qemu-io ide0-qemu-io ide0-hqemu-io ide0-hdqemu-io ide0-hd0qemu-io ide0-hd0 qemu-io ide0-hd0 "qemu-io ide0-hd0 "wqemu-io ide0-hd0 "wrqemu-io ide0-hd0 "wriqemu-io ide0-hd0 "writqemu-io ide0-hd0 "writeqemu-io ide0-hd0 "write qemu-io ide0-hd0 "write -qemu-io ide0-hd0 "write -Pqemu-io ide0-hd0 "write -P qemu-io ide0-hd0 "write -P 0qemu-io ide0-hd0 "write -P 0xqemu-io ide0-hd0 "write -P 0x2qemu-io ide0-hd0 "write -P 0x22qemu-io ide0-hd0 "write -P 0x22 qemu-io ide0-hd0 "write -P 0x22 0qemu-io ide0-hd0 "write -P 0x22 0 qemu-io ide0-hd0 "write -P 0x22 0 4qemu-io ide0-hd0 "write -P 0x22 0 4kqemu-io ide0-hd0 "write -P 0x22 0 4k"
(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
(qemu) qququiquit
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) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io iqemu-io idqemu-io ideqemu-io ide0qemu-io ide0-qemu-io ide0-hqemu-io ide0-hdqemu-io ide0-hd0qemu-io ide0-hd0 qemu-io ide0-hd0 "qemu-io ide0-hd0 "wqemu-io ide0-hd0 "wrqemu-io ide0-hd0 "wriqemu-io ide0-hd0 "writqemu-io ide0-hd0 "writeqemu-io ide0-hd0 "write qemu-io ide0-hd0 "write -qemu-io ide0-hd0 "write -Pqemu-io ide0-hd0 "write -P qemu-io ide0-hd0 "write -P 0qemu-io ide0-hd0 "write -P 0xqemu-io ide0-hd0 "write -P 0x2qemu-io ide0-hd0 "write -P 0x22qemu-io ide0-hd0 "write -P 0x22 qemu-io ide0-hd0 "write -P 0x22 0qemu-io ide0-hd0 "write -P 0x22 0 qemu-io ide0-hd0 "write -P 0x22 0 4qemu-io ide0-hd0 "write -P 0x22 0 4kqemu-io ide0-hd0 "write -P 0x22 0 4k"
(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
(qemu) qququiquit
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) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io iqemu-io idqemu-io ideqemu-io ide0qemu-io ide0-qemu-io ide0-hqemu-io ide0-hdqemu-io ide0-hd0qemu-io ide0-hd0 qemu-io ide0-hd0 "qemu-io ide0-hd0 "wqemu-io ide0-hd0 "wrqemu-io ide0-hd0 "wriqemu-io ide0-hd0 "writqemu-io ide0-hd0 "writeqemu-io ide0-hd0 "write qemu-io ide0-hd0 "write -qemu-io ide0-hd0 "write -Pqemu-io ide0-hd0 "write -P qemu-io ide0-hd0 "write -P 0qemu-io ide0-hd0 "write -P 0xqemu-io ide0-hd0 "write -P 0x2qemu-io ide0-hd0 "write -P 0x22qemu-io ide0-hd0 "write -P 0x22 qemu-io ide0-hd0 "write -P 0x22 0qemu-io ide0-hd0 "write -P 0x22 0 qemu-io ide0-hd0 "write -P 0x22 0 4qemu-io ide0-hd0 "write -P 0x22 0 4kqemu-io ide0-hd0 "write -P 0x22 0 4k"
(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
(qemu) qququiquit
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) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io iqemu-io idqemu-io ideqemu-io ide0qemu-io ide0-qemu-io ide0-hqemu-io ide0-hdqemu-io ide0-hd0qemu-io ide0-hd0 qemu-io ide0-hd0 "qemu-io ide0-hd0 "wqemu-io ide0-hd0 "wrqemu-io ide0-hd0 "wriqemu-io ide0-hd0 "writqemu-io ide0-hd0 "writeqemu-io ide0-hd0 "write qemu-io ide0-hd0 "write -qemu-io ide0-hd0 "write -Pqemu-io ide0-hd0 "write -P qemu-io ide0-hd0 "write -P 0qemu-io ide0-hd0 "write -P 0xqemu-io ide0-hd0 "write -P 0x2qemu-io ide0-hd0 "write -P 0x22qemu-io ide0-hd0 "write -P 0x22 qemu-io ide0-hd0 "write -P 0x22 0qemu-io ide0-hd0 "write -P 0x22 0 qemu-io ide0-hd0 "write -P 0x22 0 4qemu-io ide0-hd0 "write -P 0x22 0 4kqemu-io ide0-hd0 "write -P 0x22 0 4k"
(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
(qemu) qququiquit
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) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io iqemu-io idqemu-io ideqemu-io ide0qemu-io ide0-qemu-io ide0-hqemu-io ide0-hdqemu-io ide0-hd0qemu-io ide0-hd0 qemu-io ide0-hd0 "qemu-io ide0-hd0 "wqemu-io ide0-hd0 "wrqemu-io ide0-hd0 "wriqemu-io ide0-hd0 "writqemu-io ide0-hd0 "writeqemu-io ide0-hd0 "write qemu-io ide0-hd0 "write -qemu-io ide0-hd0 "write -Pqemu-io ide0-hd0 "write -P qemu-io ide0-hd0 "write -P 0qemu-io ide0-hd0 "write -P 0xqemu-io ide0-hd0 "write -P 0x2qemu-io ide0-hd0 "write -P 0x22qemu-io ide0-hd0 "write -P 0x22 qemu-io ide0-hd0 "write -P 0x22 0qemu-io ide0-hd0 "write -P 0x22 0 qemu-io ide0-hd0 "write -P 0x22 0 4qemu-io ide0-hd0 "write -P 0x22 0 4kqemu-io ide0-hd0 "write -P 0x22 0 4k"
(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
(qemu) qququiquit
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) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io iqemu-io idqemu-io ideqemu-io ide0qemu-io ide0-qemu-io ide0-hqemu-io ide0-hdqemu-io ide0-hd0qemu-io ide0-hd0 qemu-io ide0-hd0 "qemu-io ide0-hd0 "wqemu-io ide0-hd0 "wrqemu-io ide0-hd0 "wriqemu-io ide0-hd0 "writqemu-io ide0-hd0 "writeqemu-io ide0-hd0 "write qemu-io ide0-hd0 "write -qemu-io ide0-hd0 "write -Pqemu-io ide0-hd0 "write -P qemu-io ide0-hd0 "write -P 0qemu-io ide0-hd0 "write -P 0xqemu-io ide0-hd0 "write -P 0x3qemu-io ide0-hd0 "write -P 0x33qemu-io ide0-hd0 "write -P 0x33 qemu-io ide0-hd0 "write -P 0x33 0qemu-io ide0-hd0 "write -P 0x33 0 qemu-io ide0-hd0 "write -P 0x33 0 4qemu-io ide0-hd0 "write -P 0x33 0 4kqemu-io ide0-hd0 "write -P 0x33 0 4k"
(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x3qemu-io drive0 "write -P 0x33qemu-io drive0 "write -P 0x33 qemu-io drive0 "write -P 0x33 0qemu-io drive0 "write -P 0x33 0 qemu-io drive0 "write -P 0x33 0 4qemu-io drive0 "write -P 0x33 0 4kqemu-io drive0 "write -P 0x33 0 4k"
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
(qemu) ccocomcommcommicommitcommit commit icommit idcommit idecommit ide0commit ide0-commit ide0-hcommit ide0-hdcommit ide0-hd0
(qemu) ccocomcommcommicommitcommit commit dcommit drcommit dricommit drivcommit drivecommit drive0
(qemu) qququiquit
read 4096/4096 bytes at offset 0

View File

@ -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) iininfinfoinfo info binfo blinfo bloinfo blocinfo block
ide0-hd0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
Cache mode: writeback
Backing file: TEST_DIR/t.qcow2.orig (chain depth: 1)
(qemu) qququiquit
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) qququiquit
Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=off
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
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) qququiquit
=== No medium ===
Testing: -drive if=floppy
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
Testing: -drive if=ide,media=cdrom
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
Testing: -drive if=scsi,media=cdrom
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
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) qququiquit
Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-cd,drive=disk
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
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) qququiquit
Testing: -drive file=TEST_DIR/t.qcow2,if=ide,media=cdrom,readonly=on
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,media=cdrom,readonly=on
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
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) qququiquit
Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,readonly=on
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
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) qququiquit
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) qququiquit
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) qququiquit
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) qququiquit
=== Cache modes ===
Testing: -drive driver=null-co,cache=none
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
Testing: -drive driver=null-co,cache=directsync
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
Testing: -drive driver=null-co,cache=writeback
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
Testing: -drive driver=null-co,cache=writethrough
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
Testing: -drive driver=null-co,cache=unsafe
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
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) iininfinfoinfo info binfo blinfo bloinfo blocinfo block
ide0-hd0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
Cache mode: writeback
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block finfo block fiinfo block filinfo block file
file: TEST_DIR/t.qcow2 (file)
Cache mode: writeback
(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block binfo block bainfo block bacinfo block backinfo block backiinfo block backininfo block backing
backing: TEST_DIR/t.qcow2.base (qcow2, read-only)
Cache mode: writeback, ignore flushes
(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block binfo block bainfo block bacinfo block backinfo block backiinfo block backininfo block backinginfo block backing-info block backing-finfo block backing-fiinfo block backing-filinfo block backing-file
backing-file: TEST_DIR/t.qcow2.base (file, read-only)
Cache mode: writeback, ignore flushes
(qemu) qququiquit
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) iininfinfoinfo info binfo blinfo bloinfo blocinfo block
ide0-hd0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
Cache mode: writethrough
Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block finfo block fiinfo block filinfo block file
file: TEST_DIR/t.qcow2 (file)
Cache mode: writeback
(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block binfo block bainfo block bacinfo block backinfo block backiinfo block backininfo block backing
backing: TEST_DIR/t.qcow2.base (qcow2, read-only)
Cache mode: writeback, ignore flushes
(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block binfo block bainfo block bacinfo block backinfo block backiinfo block backininfo block backinginfo block backing-info block backing-finfo block backing-fiinfo block backing-filinfo block backing-file
backing-file: TEST_DIR/t.qcow2.base (file, read-only)
Cache mode: writeback, ignore flushes
(qemu) qququiquit
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) iininfinfoinfo info binfo blinfo bloinfo blocinfo block
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) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block finfo block fiinfo block filinfo block file
file: TEST_DIR/t.qcow2 (file)
Cache mode: writeback, ignore flushes
(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block binfo block bainfo block bacinfo block backinfo block backiinfo block backininfo block backing
backing: TEST_DIR/t.qcow2.base (qcow2, read-only)
Cache mode: writeback, ignore flushes
(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block binfo block bainfo block bacinfo block backinfo block backiinfo block backininfo block backinginfo block backing-info block backing-finfo block backing-fiinfo block backing-filinfo block backing-file
backing-file: TEST_DIR/t.qcow2.base (file, read-only)
Cache mode: writeback, ignore flushes
(qemu) qququiquit
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) qququiquit
=== 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) qququiquit
Testing: -drive file=file:TEST_DIR/t.qcow2
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
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) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
(qemu) qququiquit
Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on,if=none,id=drive0
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
(qemu) qququiquit
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) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
(qemu) qququiquit
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) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
(qemu) qququiquit
Testing: -drive file=file:TEST_DIR/t.qcow2,if=none,id=drive0 -snapshot
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
(qemu) qququiquit
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) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
(qemu) qququiquit
Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=drive0 -snapshot
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
(qemu) qququiquit
Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on,if=none,id=drive0
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
(qemu) qququiquit
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) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
(qemu) qququiquit
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) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x3qemu-io drive0 "write -P 0x33qemu-io drive0 "write -P 0x33 qemu-io drive0 "write -P 0x33 0qemu-io drive0 "write -P 0x33 0 qemu-io drive0 "write -P 0x33 0 4qemu-io drive0 "write -P 0x33 0 4kqemu-io drive0 "write -P 0x33 0 4k"
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
(qemu) ccocomcommcommicommitcommit commit dcommit drcommit dricommit drivcommit drivecommit drive0
(qemu) qququiquit
read 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
*** done

View File

@ -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 ===

View File

@ -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

View File

@ -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',

View File

@ -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 ===

View File

@ -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'

View File

@ -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

View File

@ -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__':

90
tests/qemu-iotests/133 Executable file
View File

@ -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

View File

@ -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

354
tests/qemu-iotests/142 Executable file
View File

@ -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

773
tests/qemu-iotests/142.out Normal file
View File

@ -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) qququiquit
Testing: -drive file=TEST_DIR/t.qcow2,cache=directsync
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
Testing: -drive file=TEST_DIR/t.qcow2,cache=writeback
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
Testing: -drive file=TEST_DIR/t.qcow2,cache=writethrough
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
Testing: -drive file=TEST_DIR/t.qcow2,cache=unsafe
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
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

View File

@ -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

View File

@ -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

View File

@ -148,12 +148,12 @@ def add_drive_raw(self, opts):
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)

View File

@ -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();
}