* [Qemu-devel] [PATCH v3 00/13] qcow2: reopen: Change driver-specific runtime options
@ 2015-09-07 13:26 Kevin Wolf
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 01/13] block: Allow specifying driver-specific options to reopen Kevin Wolf
` (12 more replies)
0 siblings, 13 replies; 19+ messages in thread
From: Kevin Wolf @ 2015-09-07 13:26 UTC (permalink / raw)
To: qemu-block; +Cc: kwolf, qemu-devel, mreitz
This is part two of what I had sent earlier as "[PATCH 00/34] block:
Cache mode for children, reopen overhaul and more". Most of the patches
were actually already reviewed in v1.
v3:
- Removed tests that depend on memory size of test machine [Max]
- Rebased, resolved conflicts with Berto's cache cleaning timer series
v2:
Apart from a few addressed review comments, there are no functional
changes compared to v1. Some rebasing was necessary; also the
qemu-iotests cases are new.
Kevin Wolf (13):
block: Allow specifying driver-specific options to reopen
qemu-io: Remove duplicate 'open' error message
qemu-io: Add command 'reopen'
qcow2: Improve error message
qcow2: Factor out qcow2_update_options()
qcow2: Move qcow2_update_options() call up
qcow2: Move rest of option handling to qcow2_update_options()
qcow2: Leave s unchanged on qcow2_update_options() failure
qcow2: Fix memory leak in qcow2_update_options() error path
qcow2: Make qcow2_update_options() suitable for transactions
qcow2: Support updating driver-specific options in reopen
qemu-iotests: Reopen qcow2 with lazy-refcounts change
qemu-iotests: More qcow2 reopen tests
block.c | 42 ++++-
block/commit.c | 4 +-
block/qcow2.c | 390 ++++++++++++++++++++++++++++++---------------
include/block/block.h | 4 +-
qemu-io-cmds.c | 90 +++++++++++
qemu-io.c | 1 -
tests/qemu-iotests/039 | 27 ++++
tests/qemu-iotests/039.out | 18 +++
tests/qemu-iotests/137 | 145 +++++++++++++++++
tests/qemu-iotests/137.out | 42 +++++
tests/qemu-iotests/group | 1 +
11 files changed, 630 insertions(+), 134 deletions(-)
create mode 100755 tests/qemu-iotests/137
create mode 100644 tests/qemu-iotests/137.out
--
1.8.3.1
^ permalink raw reply [flat|nested] 19+ messages in thread
* [Qemu-devel] [PATCH v3 01/13] block: Allow specifying driver-specific options to reopen
2015-09-07 13:26 [Qemu-devel] [PATCH v3 00/13] qcow2: reopen: Change driver-specific runtime options Kevin Wolf
@ 2015-09-07 13:26 ` Kevin Wolf
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 02/13] qemu-io: Remove duplicate 'open' error message Kevin Wolf
` (11 subsequent siblings)
12 siblings, 0 replies; 19+ messages in thread
From: Kevin Wolf @ 2015-09-07 13:26 UTC (permalink / raw)
To: qemu-block; +Cc: kwolf, qemu-devel, mreitz
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
---
block.c | 42 +++++++++++++++++++++++++++++++++++++++---
block/commit.c | 4 ++--
include/block/block.h | 4 +++-
3 files changed, 44 insertions(+), 6 deletions(-)
diff --git a/block.c b/block.c
index 910e004..e859fd0 100644
--- a/block.c
+++ b/block.c
@@ -1636,6 +1636,9 @@ typedef struct BlockReopenQueueEntry {
*
* bs is the BlockDriverState to add to the reopen queue.
*
+ * options contains the changed options for the associated bs
+ * (the BlockReopenQueue takes ownership)
+ *
* flags contains the open flags for the associated bs
*
* returns a pointer to bs_queue, which is either the newly allocated
@@ -1643,18 +1646,28 @@ typedef struct BlockReopenQueueEntry {
*
*/
BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
- BlockDriverState *bs, int flags)
+ BlockDriverState *bs,
+ QDict *options, int flags)
{
assert(bs != NULL);
BlockReopenQueueEntry *bs_entry;
BdrvChild *child;
+ QDict *old_options;
if (bs_queue == NULL) {
bs_queue = g_new0(BlockReopenQueue, 1);
QSIMPLEQ_INIT(bs_queue);
}
+ if (!options) {
+ options = qdict_new();
+ }
+
+ old_options = qdict_clone_shallow(bs->options);
+ qdict_join(options, old_options, false);
+ QDECREF(old_options);
+
/* bdrv_open() masks this flag out */
flags &= ~BDRV_O_PROTOCOL;
@@ -1666,13 +1679,15 @@ BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
}
child_flags = child->role->inherit_flags(flags);
- bdrv_reopen_queue(bs_queue, child->bs, child_flags);
+ /* TODO Pass down child flags (backing.*, extents.*, ...) */
+ bdrv_reopen_queue(bs_queue, child->bs, NULL, child_flags);
}
bs_entry = g_new0(BlockReopenQueueEntry, 1);
QSIMPLEQ_INSERT_TAIL(bs_queue, bs_entry, entry);
bs_entry->state.bs = bs;
+ bs_entry->state.options = options;
bs_entry->state.flags = flags;
return bs_queue;
@@ -1725,6 +1740,7 @@ cleanup:
if (ret && bs_entry->prepared) {
bdrv_reopen_abort(&bs_entry->state);
}
+ QDECREF(bs_entry->state.options);
g_free(bs_entry);
}
g_free(bs_queue);
@@ -1737,7 +1753,7 @@ int bdrv_reopen(BlockDriverState *bs, int bdrv_flags, Error **errp)
{
int ret = -1;
Error *local_err = NULL;
- BlockReopenQueue *queue = bdrv_reopen_queue(NULL, bs, bdrv_flags);
+ BlockReopenQueue *queue = bdrv_reopen_queue(NULL, bs, NULL, bdrv_flags);
ret = bdrv_reopen_multiple(queue, &local_err);
if (local_err != NULL) {
@@ -1813,6 +1829,26 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
goto error;
}
+ /* Options that are not handled are only okay if they are unchanged
+ * compared to the old state. It is expected that some options are only
+ * used for the initial open, but not reopen (e.g. filename) */
+ if (qdict_size(reopen_state->options)) {
+ const QDictEntry *entry = qdict_first(reopen_state->options);
+
+ do {
+ QString *new_obj = qobject_to_qstring(entry->value);
+ const char *new = qstring_get_str(new_obj);
+ const char *old = qdict_get_try_str(reopen_state->bs->options,
+ entry->key);
+
+ if (!old || strcmp(new, old)) {
+ error_setg(errp, "Cannot change the option '%s'", entry->key);
+ ret = -EINVAL;
+ goto error;
+ }
+ } while ((entry = qdict_next(reopen_state->options, entry)));
+ }
+
ret = 0;
error:
diff --git a/block/commit.c b/block/commit.c
index 7312a5b..d12e26f 100644
--- a/block/commit.c
+++ b/block/commit.c
@@ -236,11 +236,11 @@ void commit_start(BlockDriverState *bs, BlockDriverState *base,
/* convert base & overlay_bs to r/w, if necessary */
if (!(orig_base_flags & BDRV_O_RDWR)) {
- reopen_queue = bdrv_reopen_queue(reopen_queue, base,
+ reopen_queue = bdrv_reopen_queue(reopen_queue, base, NULL,
orig_base_flags | BDRV_O_RDWR);
}
if (!(orig_overlay_flags & BDRV_O_RDWR)) {
- reopen_queue = bdrv_reopen_queue(reopen_queue, overlay_bs,
+ reopen_queue = bdrv_reopen_queue(reopen_queue, overlay_bs, NULL,
orig_overlay_flags | BDRV_O_RDWR);
}
if (reopen_queue) {
diff --git a/include/block/block.h b/include/block/block.h
index c7fdbaa..4ceceed 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -147,6 +147,7 @@ typedef QSIMPLEQ_HEAD(BlockReopenQueue, BlockReopenQueueEntry) BlockReopenQueue;
typedef struct BDRVReopenState {
BlockDriverState *bs;
int flags;
+ QDict *options;
void *opaque;
} BDRVReopenState;
@@ -218,7 +219,8 @@ 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);
BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
- BlockDriverState *bs, int flags);
+ BlockDriverState *bs,
+ QDict *options, int flags);
int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp);
int bdrv_reopen(BlockDriverState *bs, int bdrv_flags, Error **errp);
int bdrv_reopen_prepare(BDRVReopenState *reopen_state,
--
1.8.3.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Qemu-devel] [PATCH v3 02/13] qemu-io: Remove duplicate 'open' error message
2015-09-07 13:26 [Qemu-devel] [PATCH v3 00/13] qcow2: reopen: Change driver-specific runtime options Kevin Wolf
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 01/13] block: Allow specifying driver-specific options to reopen Kevin Wolf
@ 2015-09-07 13:26 ` Kevin Wolf
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 03/13] qemu-io: Add command 'reopen' Kevin Wolf
` (10 subsequent siblings)
12 siblings, 0 replies; 19+ messages in thread
From: Kevin Wolf @ 2015-09-07 13:26 UTC (permalink / raw)
To: qemu-block; +Cc: kwolf, qemu-devel, mreitz
qemu_opts_parse_noisily() already prints an error message with the exact
reason why the parsing failed. No need to add another less specific one.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
---
qemu-io.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/qemu-io.c b/qemu-io.c
index f1e3a67..269f17c 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -156,7 +156,6 @@ static int open_f(BlockBackend *blk, int argc, char **argv)
break;
case 'o':
if (!qemu_opts_parse_noisily(&empty_opts, optarg, false)) {
- printf("could not parse option list -- %s\n", optarg);
qemu_opts_reset(&empty_opts);
return 0;
}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Qemu-devel] [PATCH v3 03/13] qemu-io: Add command 'reopen'
2015-09-07 13:26 [Qemu-devel] [PATCH v3 00/13] qcow2: reopen: Change driver-specific runtime options Kevin Wolf
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 01/13] block: Allow specifying driver-specific options to reopen Kevin Wolf
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 02/13] qemu-io: Remove duplicate 'open' error message Kevin Wolf
@ 2015-09-07 13:26 ` Kevin Wolf
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 04/13] qcow2: Improve error message Kevin Wolf
` (9 subsequent siblings)
12 siblings, 0 replies; 19+ messages in thread
From: Kevin Wolf @ 2015-09-07 13:26 UTC (permalink / raw)
To: qemu-block; +Cc: kwolf, qemu-devel, mreitz
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
---
qemu-io-cmds.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 90 insertions(+)
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index 53477e1..d6572a8 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -1979,6 +1979,95 @@ static const cmdinfo_t map_cmd = {
.oneline = "prints the allocated areas of a file",
};
+static void reopen_help(void)
+{
+ printf(
+"\n"
+" Changes the open options of an already opened image\n"
+"\n"
+" Example:\n"
+" 'reopen -o lazy-refcounts=on' - activates lazy refcount writeback on a qcow2 image\n"
+"\n"
+" -r, -- Reopen the image read-only\n"
+" -c, -- Change the cache mode to the given value\n"
+" -o, -- Changes block driver options (cf. 'open' command)\n"
+"\n");
+}
+
+static int reopen_f(BlockBackend *blk, int argc, char **argv);
+
+static QemuOptsList reopen_opts = {
+ .name = "reopen",
+ .merge_lists = true,
+ .head = QTAILQ_HEAD_INITIALIZER(reopen_opts.head),
+ .desc = {
+ /* no elements => accept any params */
+ { /* end of list */ }
+ },
+};
+
+static const cmdinfo_t reopen_cmd = {
+ .name = "reopen",
+ .argmin = 0,
+ .argmax = -1,
+ .cfunc = reopen_f,
+ .args = "[-r] [-c cache] [-o options]",
+ .oneline = "reopens an image with new options",
+ .help = reopen_help,
+};
+
+static int reopen_f(BlockBackend *blk, int argc, char **argv)
+{
+ BlockDriverState *bs = blk_bs(blk);
+ QemuOpts *qopts;
+ QDict *opts;
+ int c;
+ int flags = bs->open_flags;
+
+ BlockReopenQueue *brq;
+ Error *local_err = NULL;
+
+ while ((c = getopt(argc, argv, "c:o:r")) != -1) {
+ switch (c) {
+ case 'c':
+ if (bdrv_parse_cache_flags(optarg, &flags) < 0) {
+ error_report("Invalid cache option: %s", optarg);
+ return 0;
+ }
+ break;
+ case 'o':
+ if (!qemu_opts_parse_noisily(&reopen_opts, optarg, 0)) {
+ qemu_opts_reset(&reopen_opts);
+ return 0;
+ }
+ break;
+ case 'r':
+ flags &= ~BDRV_O_RDWR;
+ break;
+ default:
+ qemu_opts_reset(&reopen_opts);
+ return qemuio_command_usage(&reopen_cmd);
+ }
+ }
+
+ if (optind != argc) {
+ qemu_opts_reset(&reopen_opts);
+ return qemuio_command_usage(&reopen_cmd);
+ }
+
+ qopts = qemu_opts_find(&reopen_opts, NULL);
+ opts = qopts ? qemu_opts_to_qdict(qopts, NULL) : NULL;
+ qemu_opts_reset(&reopen_opts);
+
+ brq = bdrv_reopen_queue(NULL, bs, opts, flags);
+ bdrv_reopen_multiple(brq, &local_err);
+ if (local_err) {
+ error_report_err(local_err);
+ }
+
+ return 0;
+}
+
static int break_f(BlockBackend *blk, int argc, char **argv)
{
int ret;
@@ -2266,6 +2355,7 @@ static void __attribute((constructor)) init_qemuio_commands(void)
qemuio_add_command(&discard_cmd);
qemuio_add_command(&alloc_cmd);
qemuio_add_command(&map_cmd);
+ qemuio_add_command(&reopen_cmd);
qemuio_add_command(&break_cmd);
qemuio_add_command(&remove_break_cmd);
qemuio_add_command(&resume_cmd);
--
1.8.3.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Qemu-devel] [PATCH v3 04/13] qcow2: Improve error message
2015-09-07 13:26 [Qemu-devel] [PATCH v3 00/13] qcow2: reopen: Change driver-specific runtime options Kevin Wolf
` (2 preceding siblings ...)
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 03/13] qemu-io: Add command 'reopen' Kevin Wolf
@ 2015-09-07 13:26 ` Kevin Wolf
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 05/13] qcow2: Factor out qcow2_update_options() Kevin Wolf
` (8 subsequent siblings)
12 siblings, 0 replies; 19+ messages in thread
From: Kevin Wolf @ 2015-09-07 13:26 UTC (permalink / raw)
To: qemu-block; +Cc: kwolf, qemu-devel, mreitz
Eric says that "any" sounds better than "either", and my non-native
feeling says the same, so let's change it.
Suggested-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
---
block/qcow2.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/block/qcow2.c b/block/qcow2.c
index a707d8d..b681977 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1030,7 +1030,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
overlap_check_template = QCOW2_OL_ALL;
} else {
error_setg(errp, "Unsupported value '%s' for qcow2 option "
- "'overlap-check'. Allowed are either of the following: "
+ "'overlap-check'. Allowed are any of the following: "
"none, constant, cached, all", opt_overlap_check);
ret = -EINVAL;
goto fail;
--
1.8.3.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Qemu-devel] [PATCH v3 05/13] qcow2: Factor out qcow2_update_options()
2015-09-07 13:26 [Qemu-devel] [PATCH v3 00/13] qcow2: reopen: Change driver-specific runtime options Kevin Wolf
` (3 preceding siblings ...)
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 04/13] qcow2: Improve error message Kevin Wolf
@ 2015-09-07 13:26 ` Kevin Wolf
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 06/13] qcow2: Move qcow2_update_options() call up Kevin Wolf
` (7 subsequent siblings)
12 siblings, 0 replies; 19+ messages in thread
From: Kevin Wolf @ 2015-09-07 13:26 UTC (permalink / raw)
To: qemu-block; +Cc: kwolf, qemu-devel, mreitz
Eventually we want to be able to change options at runtime. As a first
step towards that goal, separate some option handling code from the
general initialisation code in qcow2_open().
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
---
block/qcow2.c | 135 +++++++++++++++++++++++++++++++++-------------------------
1 file changed, 76 insertions(+), 59 deletions(-)
diff --git a/block/qcow2.c b/block/qcow2.c
index b681977..e98982d 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -589,6 +589,80 @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
}
}
+static int qcow2_update_options(BlockDriverState *bs, QemuOpts *opts,
+ int flags, Error **errp)
+{
+ BDRVQcowState *s = bs->opaque;
+ const char *opt_overlap_check, *opt_overlap_check_template;
+ int overlap_check_template = 0;
+ int i;
+ int ret;
+
+ s->use_lazy_refcounts = qemu_opt_get_bool(opts, QCOW2_OPT_LAZY_REFCOUNTS,
+ (s->compatible_features & QCOW2_COMPAT_LAZY_REFCOUNTS));
+
+ s->discard_passthrough[QCOW2_DISCARD_NEVER] = false;
+ s->discard_passthrough[QCOW2_DISCARD_ALWAYS] = true;
+ s->discard_passthrough[QCOW2_DISCARD_REQUEST] =
+ qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_REQUEST,
+ flags & BDRV_O_UNMAP);
+ s->discard_passthrough[QCOW2_DISCARD_SNAPSHOT] =
+ qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_SNAPSHOT, true);
+ s->discard_passthrough[QCOW2_DISCARD_OTHER] =
+ qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_OTHER, false);
+
+ opt_overlap_check = qemu_opt_get(opts, QCOW2_OPT_OVERLAP);
+ opt_overlap_check_template = qemu_opt_get(opts, QCOW2_OPT_OVERLAP_TEMPLATE);
+ if (opt_overlap_check_template && opt_overlap_check &&
+ strcmp(opt_overlap_check_template, opt_overlap_check))
+ {
+ error_setg(errp, "Conflicting values for qcow2 options '"
+ QCOW2_OPT_OVERLAP "' ('%s') and '" QCOW2_OPT_OVERLAP_TEMPLATE
+ "' ('%s')", opt_overlap_check, opt_overlap_check_template);
+ ret = -EINVAL;
+ goto fail;
+ }
+ if (!opt_overlap_check) {
+ opt_overlap_check = opt_overlap_check_template ?: "cached";
+ }
+
+ if (!strcmp(opt_overlap_check, "none")) {
+ overlap_check_template = 0;
+ } else if (!strcmp(opt_overlap_check, "constant")) {
+ overlap_check_template = QCOW2_OL_CONSTANT;
+ } else if (!strcmp(opt_overlap_check, "cached")) {
+ overlap_check_template = QCOW2_OL_CACHED;
+ } else if (!strcmp(opt_overlap_check, "all")) {
+ overlap_check_template = QCOW2_OL_ALL;
+ } else {
+ error_setg(errp, "Unsupported value '%s' for qcow2 option "
+ "'overlap-check'. Allowed are any of the following: "
+ "none, constant, cached, all", opt_overlap_check);
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ s->overlap_check = 0;
+ for (i = 0; i < QCOW2_OL_MAX_BITNR; i++) {
+ /* overlap-check defines a template bitmask, but every flag may be
+ * overwritten through the associated boolean option */
+ s->overlap_check |=
+ qemu_opt_get_bool(opts, overlap_bool_option_names[i],
+ overlap_check_template & (1 << i)) << i;
+ }
+
+ if (s->use_lazy_refcounts && s->qcow_version < 3) {
+ error_setg(errp, "Lazy refcounts require a qcow2 image with at least "
+ "qemu 1.1 compatibility level");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = 0;
+fail:
+ return ret;
+}
+
static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
Error **errp)
{
@@ -600,8 +674,6 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
Error *local_err = NULL;
uint64_t ext_end;
uint64_t l1_vm_state_index;
- const char *opt_overlap_check, *opt_overlap_check_template;
- int overlap_check_template = 0;
uint64_t l2_cache_size, refcount_cache_size;
uint64_t cache_clean_interval;
@@ -992,69 +1064,14 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
}
/* Enable lazy_refcounts according to image and command line options */
- s->use_lazy_refcounts = qemu_opt_get_bool(opts, QCOW2_OPT_LAZY_REFCOUNTS,
- (s->compatible_features & QCOW2_COMPAT_LAZY_REFCOUNTS));
-
- s->discard_passthrough[QCOW2_DISCARD_NEVER] = false;
- s->discard_passthrough[QCOW2_DISCARD_ALWAYS] = true;
- s->discard_passthrough[QCOW2_DISCARD_REQUEST] =
- qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_REQUEST,
- flags & BDRV_O_UNMAP);
- s->discard_passthrough[QCOW2_DISCARD_SNAPSHOT] =
- qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_SNAPSHOT, true);
- s->discard_passthrough[QCOW2_DISCARD_OTHER] =
- qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_OTHER, false);
-
- opt_overlap_check = qemu_opt_get(opts, QCOW2_OPT_OVERLAP);
- opt_overlap_check_template = qemu_opt_get(opts, QCOW2_OPT_OVERLAP_TEMPLATE);
- if (opt_overlap_check_template && opt_overlap_check &&
- strcmp(opt_overlap_check_template, opt_overlap_check))
- {
- error_setg(errp, "Conflicting values for qcow2 options '"
- QCOW2_OPT_OVERLAP "' ('%s') and '" QCOW2_OPT_OVERLAP_TEMPLATE
- "' ('%s')", opt_overlap_check, opt_overlap_check_template);
- ret = -EINVAL;
- goto fail;
- }
- if (!opt_overlap_check) {
- opt_overlap_check = opt_overlap_check_template ?: "cached";
- }
-
- if (!strcmp(opt_overlap_check, "none")) {
- overlap_check_template = 0;
- } else if (!strcmp(opt_overlap_check, "constant")) {
- overlap_check_template = QCOW2_OL_CONSTANT;
- } else if (!strcmp(opt_overlap_check, "cached")) {
- overlap_check_template = QCOW2_OL_CACHED;
- } else if (!strcmp(opt_overlap_check, "all")) {
- overlap_check_template = QCOW2_OL_ALL;
- } else {
- error_setg(errp, "Unsupported value '%s' for qcow2 option "
- "'overlap-check'. Allowed are any of the following: "
- "none, constant, cached, all", opt_overlap_check);
- ret = -EINVAL;
+ ret = qcow2_update_options(bs, opts, flags, errp);
+ if (ret < 0) {
goto fail;
}
- s->overlap_check = 0;
- for (i = 0; i < QCOW2_OL_MAX_BITNR; i++) {
- /* overlap-check defines a template bitmask, but every flag may be
- * overwritten through the associated boolean option */
- s->overlap_check |=
- qemu_opt_get_bool(opts, overlap_bool_option_names[i],
- overlap_check_template & (1 << i)) << i;
- }
-
qemu_opts_del(opts);
opts = NULL;
- if (s->use_lazy_refcounts && s->qcow_version < 3) {
- error_setg(errp, "Lazy refcounts require a qcow2 image with at least "
- "qemu 1.1 compatibility level");
- ret = -EINVAL;
- goto fail;
- }
-
#ifdef DEBUG_ALLOC
{
BdrvCheckResult result = {0};
--
1.8.3.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Qemu-devel] [PATCH v3 06/13] qcow2: Move qcow2_update_options() call up
2015-09-07 13:26 [Qemu-devel] [PATCH v3 00/13] qcow2: reopen: Change driver-specific runtime options Kevin Wolf
` (4 preceding siblings ...)
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 05/13] qcow2: Factor out qcow2_update_options() Kevin Wolf
@ 2015-09-07 13:26 ` Kevin Wolf
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 07/13] qcow2: Move rest of option handling to qcow2_update_options() Kevin Wolf
` (6 subsequent siblings)
12 siblings, 0 replies; 19+ messages in thread
From: Kevin Wolf @ 2015-09-07 13:26 UTC (permalink / raw)
To: qemu-block; +Cc: kwolf, qemu-devel, mreitz
qcow2_update_options() only updates some variables in BDRVQcowState and
doesn't really depend on other parts of it being initialised yet, so it
can be moved so that it immediately follows the other half of option
handling code in qcow2_open().
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
---
block/qcow2.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/block/qcow2.c b/block/qcow2.c
index e98982d..f7b5cbf 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -979,6 +979,15 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
s->cache_clean_interval = cache_clean_interval;
cache_clean_timer_init(bs, bdrv_get_aio_context(bs));
+ /* Enable lazy_refcounts according to image and command line options */
+ ret = qcow2_update_options(bs, opts, flags, errp);
+ if (ret < 0) {
+ goto fail;
+ }
+
+ qemu_opts_del(opts);
+ opts = NULL;
+
s->cluster_cache = g_malloc(s->cluster_size);
/* one more sector for decompressed data alignment */
s->cluster_data = qemu_try_blockalign(bs->file, QCOW_MAX_CRYPT_CLUSTERS
@@ -1063,15 +1072,6 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
}
}
- /* Enable lazy_refcounts according to image and command line options */
- ret = qcow2_update_options(bs, opts, flags, errp);
- if (ret < 0) {
- goto fail;
- }
-
- qemu_opts_del(opts);
- opts = NULL;
-
#ifdef DEBUG_ALLOC
{
BdrvCheckResult result = {0};
--
1.8.3.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Qemu-devel] [PATCH v3 07/13] qcow2: Move rest of option handling to qcow2_update_options()
2015-09-07 13:26 [Qemu-devel] [PATCH v3 00/13] qcow2: reopen: Change driver-specific runtime options Kevin Wolf
` (5 preceding siblings ...)
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 06/13] qcow2: Move qcow2_update_options() call up Kevin Wolf
@ 2015-09-07 13:26 ` Kevin Wolf
2015-09-07 19:35 ` Max Reitz
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 08/13] qcow2: Leave s unchanged on qcow2_update_options() failure Kevin Wolf
` (5 subsequent siblings)
12 siblings, 1 reply; 19+ messages in thread
From: Kevin Wolf @ 2015-09-07 13:26 UTC (permalink / raw)
To: qemu-block; +Cc: kwolf, qemu-devel, mreitz
With this commit, the handling of driver-specific options in
qcow2_open() is completely separated out into qcow2_update_options().
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block/qcow2.c | 134 +++++++++++++++++++++++++++++-----------------------------
1 file changed, 68 insertions(+), 66 deletions(-)
diff --git a/block/qcow2.c b/block/qcow2.c
index f7b5cbf..382d314 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -589,15 +589,77 @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
}
}
-static int qcow2_update_options(BlockDriverState *bs, QemuOpts *opts,
+static int qcow2_update_options(BlockDriverState *bs, QDict *options,
int flags, Error **errp)
{
BDRVQcowState *s = bs->opaque;
+ QemuOpts *opts = NULL;
const char *opt_overlap_check, *opt_overlap_check_template;
int overlap_check_template = 0;
+ uint64_t l2_cache_size, refcount_cache_size;
+ uint64_t cache_clean_interval;
int i;
+ Error *local_err = NULL;
int ret;
+ opts = qemu_opts_create(&qcow2_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;
+ }
+
+ /* get L2 table/refcount block cache size from command line options */
+ read_cache_sizes(bs, opts, &l2_cache_size, &refcount_cache_size,
+ &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ l2_cache_size /= s->cluster_size;
+ if (l2_cache_size < MIN_L2_CACHE_SIZE) {
+ l2_cache_size = MIN_L2_CACHE_SIZE;
+ }
+ if (l2_cache_size > INT_MAX) {
+ error_setg(errp, "L2 cache size too big");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ refcount_cache_size /= s->cluster_size;
+ if (refcount_cache_size < MIN_REFCOUNT_CACHE_SIZE) {
+ refcount_cache_size = MIN_REFCOUNT_CACHE_SIZE;
+ }
+ if (refcount_cache_size > INT_MAX) {
+ error_setg(errp, "Refcount cache size too big");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ /* alloc L2 table/refcount block cache */
+ s->l2_table_cache = qcow2_cache_create(bs, l2_cache_size);
+ s->refcount_block_cache = qcow2_cache_create(bs, refcount_cache_size);
+ if (s->l2_table_cache == NULL || s->refcount_block_cache == NULL) {
+ error_setg(errp, "Could not allocate metadata caches");
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ /* New interval for cache cleanup timer */
+ cache_clean_interval =
+ qemu_opt_get_number(opts, QCOW2_OPT_CACHE_CLEAN_INTERVAL, 0);
+ if (cache_clean_interval > UINT_MAX) {
+ error_setg(errp, "Cache clean interval too big");
+ ret = -EINVAL;
+ goto fail;
+ }
+ s->cache_clean_interval = cache_clean_interval;
+ cache_clean_timer_init(bs, bdrv_get_aio_context(bs));
+
+ /* Enable lazy_refcounts according to image and command line options */
s->use_lazy_refcounts = qemu_opt_get_bool(opts, QCOW2_OPT_LAZY_REFCOUNTS,
(s->compatible_features & QCOW2_COMPAT_LAZY_REFCOUNTS));
@@ -660,6 +722,9 @@ static int qcow2_update_options(BlockDriverState *bs, QemuOpts *opts,
ret = 0;
fail:
+ qemu_opts_del(opts);
+ opts = NULL;
+
return ret;
}
@@ -670,12 +735,9 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
unsigned int len, i;
int ret = 0;
QCowHeader header;
- QemuOpts *opts = NULL;
Error *local_err = NULL;
uint64_t ext_end;
uint64_t l1_vm_state_index;
- uint64_t l2_cache_size, refcount_cache_size;
- uint64_t cache_clean_interval;
ret = bdrv_pread(bs->file, 0, &header, sizeof(header));
if (ret < 0) {
@@ -923,71 +985,12 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
}
}
- /* get L2 table/refcount block cache size from command line options */
- opts = qemu_opts_create(&qcow2_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;
- }
-
- read_cache_sizes(bs, opts, &l2_cache_size, &refcount_cache_size,
- &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- ret = -EINVAL;
- goto fail;
- }
-
- l2_cache_size /= s->cluster_size;
- if (l2_cache_size < MIN_L2_CACHE_SIZE) {
- l2_cache_size = MIN_L2_CACHE_SIZE;
- }
- if (l2_cache_size > INT_MAX) {
- error_setg(errp, "L2 cache size too big");
- ret = -EINVAL;
- goto fail;
- }
-
- refcount_cache_size /= s->cluster_size;
- if (refcount_cache_size < MIN_REFCOUNT_CACHE_SIZE) {
- refcount_cache_size = MIN_REFCOUNT_CACHE_SIZE;
- }
- if (refcount_cache_size > INT_MAX) {
- error_setg(errp, "Refcount cache size too big");
- ret = -EINVAL;
- goto fail;
- }
-
- /* alloc L2 table/refcount block cache */
- s->l2_table_cache = qcow2_cache_create(bs, l2_cache_size);
- s->refcount_block_cache = qcow2_cache_create(bs, refcount_cache_size);
- if (s->l2_table_cache == NULL || s->refcount_block_cache == NULL) {
- error_setg(errp, "Could not allocate metadata caches");
- ret = -ENOMEM;
- goto fail;
- }
-
- cache_clean_interval =
- qemu_opt_get_number(opts, QCOW2_OPT_CACHE_CLEAN_INTERVAL, 0);
- if (cache_clean_interval > UINT_MAX) {
- error_setg(errp, "Cache clean interval too big");
- ret = -EINVAL;
- goto fail;
- }
- s->cache_clean_interval = cache_clean_interval;
- cache_clean_timer_init(bs, bdrv_get_aio_context(bs));
-
- /* Enable lazy_refcounts according to image and command line options */
- ret = qcow2_update_options(bs, opts, flags, errp);
+ /* Parse driver-specific options */
+ ret = qcow2_update_options(bs, options, flags, errp);
if (ret < 0) {
goto fail;
}
- qemu_opts_del(opts);
- opts = NULL;
-
s->cluster_cache = g_malloc(s->cluster_size);
/* one more sector for decompressed data alignment */
s->cluster_data = qemu_try_blockalign(bs->file, QCOW_MAX_CRYPT_CLUSTERS
@@ -1081,7 +1084,6 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
return ret;
fail:
- qemu_opts_del(opts);
g_free(s->unknown_header_fields);
cleanup_unknown_header_ext(bs);
qcow2_free_snapshots(bs);
--
1.8.3.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Qemu-devel] [PATCH v3 08/13] qcow2: Leave s unchanged on qcow2_update_options() failure
2015-09-07 13:26 [Qemu-devel] [PATCH v3 00/13] qcow2: reopen: Change driver-specific runtime options Kevin Wolf
` (6 preceding siblings ...)
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 07/13] qcow2: Move rest of option handling to qcow2_update_options() Kevin Wolf
@ 2015-09-07 13:26 ` Kevin Wolf
2015-09-07 19:38 ` Max Reitz
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 09/13] qcow2: Fix memory leak in qcow2_update_options() error path Kevin Wolf
` (4 subsequent siblings)
12 siblings, 1 reply; 19+ messages in thread
From: Kevin Wolf @ 2015-09-07 13:26 UTC (permalink / raw)
To: qemu-block; +Cc: kwolf, qemu-devel, mreitz
On return, either all new options should be applied to BDRVQcowState (on
success), or all of the old settings should be preserved (on failure).
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block/qcow2.c | 57 +++++++++++++++++++++++++++++++++++----------------------
1 file changed, 35 insertions(+), 22 deletions(-)
diff --git a/block/qcow2.c b/block/qcow2.c
index 382d314..923b9dd 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -597,7 +597,10 @@ static int qcow2_update_options(BlockDriverState *bs, QDict *options,
const char *opt_overlap_check, *opt_overlap_check_template;
int overlap_check_template = 0;
uint64_t l2_cache_size, refcount_cache_size;
+ Qcow2Cache *l2_table_cache;
+ Qcow2Cache *refcount_block_cache;
uint64_t cache_clean_interval;
+ bool use_lazy_refcounts;
int i;
Error *local_err = NULL;
int ret;
@@ -640,9 +643,9 @@ static int qcow2_update_options(BlockDriverState *bs, QDict *options,
}
/* alloc L2 table/refcount block cache */
- s->l2_table_cache = qcow2_cache_create(bs, l2_cache_size);
- s->refcount_block_cache = qcow2_cache_create(bs, refcount_cache_size);
- if (s->l2_table_cache == NULL || s->refcount_block_cache == NULL) {
+ l2_table_cache = qcow2_cache_create(bs, l2_cache_size);
+ refcount_block_cache = qcow2_cache_create(bs, refcount_cache_size);
+ if (l2_table_cache == NULL || refcount_block_cache == NULL) {
error_setg(errp, "Could not allocate metadata caches");
ret = -ENOMEM;
goto fail;
@@ -656,23 +659,18 @@ static int qcow2_update_options(BlockDriverState *bs, QDict *options,
ret = -EINVAL;
goto fail;
}
- s->cache_clean_interval = cache_clean_interval;
- cache_clean_timer_init(bs, bdrv_get_aio_context(bs));
/* Enable lazy_refcounts according to image and command line options */
- s->use_lazy_refcounts = qemu_opt_get_bool(opts, QCOW2_OPT_LAZY_REFCOUNTS,
+ use_lazy_refcounts = qemu_opt_get_bool(opts, QCOW2_OPT_LAZY_REFCOUNTS,
(s->compatible_features & QCOW2_COMPAT_LAZY_REFCOUNTS));
+ if (use_lazy_refcounts && s->qcow_version < 3) {
+ error_setg(errp, "Lazy refcounts require a qcow2 image with at least "
+ "qemu 1.1 compatibility level");
+ ret = -EINVAL;
+ goto fail;
+ }
- s->discard_passthrough[QCOW2_DISCARD_NEVER] = false;
- s->discard_passthrough[QCOW2_DISCARD_ALWAYS] = true;
- s->discard_passthrough[QCOW2_DISCARD_REQUEST] =
- qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_REQUEST,
- flags & BDRV_O_UNMAP);
- s->discard_passthrough[QCOW2_DISCARD_SNAPSHOT] =
- qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_SNAPSHOT, true);
- s->discard_passthrough[QCOW2_DISCARD_OTHER] =
- qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_OTHER, false);
-
+ /* Overlap check options */
opt_overlap_check = qemu_opt_get(opts, QCOW2_OPT_OVERLAP);
opt_overlap_check_template = qemu_opt_get(opts, QCOW2_OPT_OVERLAP_TEMPLATE);
if (opt_overlap_check_template && opt_overlap_check &&
@@ -704,6 +702,10 @@ static int qcow2_update_options(BlockDriverState *bs, QDict *options,
goto fail;
}
+ /*
+ * Start updating fields in BDRVQcowState.
+ * After this point no failure is allowed any more.
+ */
s->overlap_check = 0;
for (i = 0; i < QCOW2_OL_MAX_BITNR; i++) {
/* overlap-check defines a template bitmask, but every flag may be
@@ -713,12 +715,23 @@ static int qcow2_update_options(BlockDriverState *bs, QDict *options,
overlap_check_template & (1 << i)) << i;
}
- if (s->use_lazy_refcounts && s->qcow_version < 3) {
- error_setg(errp, "Lazy refcounts require a qcow2 image with at least "
- "qemu 1.1 compatibility level");
- ret = -EINVAL;
- goto fail;
- }
+ s->l2_table_cache = l2_table_cache;
+ s->refcount_block_cache = refcount_block_cache;
+
+ s->use_lazy_refcounts = use_lazy_refcounts;
+
+ s->discard_passthrough[QCOW2_DISCARD_NEVER] = false;
+ s->discard_passthrough[QCOW2_DISCARD_ALWAYS] = true;
+ s->discard_passthrough[QCOW2_DISCARD_REQUEST] =
+ qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_REQUEST,
+ flags & BDRV_O_UNMAP);
+ s->discard_passthrough[QCOW2_DISCARD_SNAPSHOT] =
+ qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_SNAPSHOT, true);
+ s->discard_passthrough[QCOW2_DISCARD_OTHER] =
+ qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_OTHER, false);
+
+ s->cache_clean_interval = cache_clean_interval;
+ cache_clean_timer_init(bs, bdrv_get_aio_context(bs));
ret = 0;
fail:
--
1.8.3.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Qemu-devel] [PATCH v3 09/13] qcow2: Fix memory leak in qcow2_update_options() error path
2015-09-07 13:26 [Qemu-devel] [PATCH v3 00/13] qcow2: reopen: Change driver-specific runtime options Kevin Wolf
` (7 preceding siblings ...)
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 08/13] qcow2: Leave s unchanged on qcow2_update_options() failure Kevin Wolf
@ 2015-09-07 13:26 ` Kevin Wolf
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 10/13] qcow2: Make qcow2_update_options() suitable for transactions Kevin Wolf
` (3 subsequent siblings)
12 siblings, 0 replies; 19+ messages in thread
From: Kevin Wolf @ 2015-09-07 13:26 UTC (permalink / raw)
To: qemu-block; +Cc: kwolf, qemu-devel, mreitz
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
---
block/qcow2.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/block/qcow2.c b/block/qcow2.c
index 923b9dd..226b1b1 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -597,8 +597,8 @@ static int qcow2_update_options(BlockDriverState *bs, QDict *options,
const char *opt_overlap_check, *opt_overlap_check_template;
int overlap_check_template = 0;
uint64_t l2_cache_size, refcount_cache_size;
- Qcow2Cache *l2_table_cache;
- Qcow2Cache *refcount_block_cache;
+ Qcow2Cache *l2_table_cache = NULL;
+ Qcow2Cache *refcount_block_cache = NULL;
uint64_t cache_clean_interval;
bool use_lazy_refcounts;
int i;
@@ -735,6 +735,14 @@ static int qcow2_update_options(BlockDriverState *bs, QDict *options,
ret = 0;
fail:
+ if (ret < 0) {
+ if (l2_table_cache) {
+ qcow2_cache_destroy(bs, l2_table_cache);
+ }
+ if (refcount_block_cache) {
+ qcow2_cache_destroy(bs, refcount_block_cache);
+ }
+ }
qemu_opts_del(opts);
opts = NULL;
--
1.8.3.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Qemu-devel] [PATCH v3 10/13] qcow2: Make qcow2_update_options() suitable for transactions
2015-09-07 13:26 [Qemu-devel] [PATCH v3 00/13] qcow2: reopen: Change driver-specific runtime options Kevin Wolf
` (8 preceding siblings ...)
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 09/13] qcow2: Fix memory leak in qcow2_update_options() error path Kevin Wolf
@ 2015-09-07 13:26 ` Kevin Wolf
2015-09-07 19:41 ` Max Reitz
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 11/13] qcow2: Support updating driver-specific options in reopen Kevin Wolf
` (2 subsequent siblings)
12 siblings, 1 reply; 19+ messages in thread
From: Kevin Wolf @ 2015-09-07 13:26 UTC (permalink / raw)
To: qemu-block; +Cc: kwolf, qemu-devel, mreitz
Before we can allow updating options at runtime with bdrv_reopen(), we
need to split the function into prepare/commit/abort parts.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block/qcow2.c | 113 +++++++++++++++++++++++++++++++++++++---------------------
1 file changed, 73 insertions(+), 40 deletions(-)
diff --git a/block/qcow2.c b/block/qcow2.c
index 226b1b1..eb379c1 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -589,18 +589,25 @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
}
}
-static int qcow2_update_options(BlockDriverState *bs, QDict *options,
- int flags, Error **errp)
+typedef struct Qcow2ReopenState {
+ Qcow2Cache *l2_table_cache;
+ Qcow2Cache *refcount_block_cache;
+ bool use_lazy_refcounts;
+ int overlap_check;
+ bool discard_passthrough[QCOW2_DISCARD_MAX];
+ uint64_t cache_clean_interval;
+} Qcow2ReopenState;
+
+static int qcow2_update_options_prepare(BlockDriverState *bs,
+ Qcow2ReopenState *r,
+ QDict *options, int flags,
+ Error **errp)
{
BDRVQcowState *s = bs->opaque;
QemuOpts *opts = NULL;
const char *opt_overlap_check, *opt_overlap_check_template;
int overlap_check_template = 0;
uint64_t l2_cache_size, refcount_cache_size;
- Qcow2Cache *l2_table_cache = NULL;
- Qcow2Cache *refcount_block_cache = NULL;
- uint64_t cache_clean_interval;
- bool use_lazy_refcounts;
int i;
Error *local_err = NULL;
int ret;
@@ -643,27 +650,27 @@ static int qcow2_update_options(BlockDriverState *bs, QDict *options,
}
/* alloc L2 table/refcount block cache */
- l2_table_cache = qcow2_cache_create(bs, l2_cache_size);
- refcount_block_cache = qcow2_cache_create(bs, refcount_cache_size);
- if (l2_table_cache == NULL || refcount_block_cache == NULL) {
+ r->l2_table_cache = qcow2_cache_create(bs, l2_cache_size);
+ r->refcount_block_cache = qcow2_cache_create(bs, refcount_cache_size);
+ if (r->l2_table_cache == NULL || r->refcount_block_cache == NULL) {
error_setg(errp, "Could not allocate metadata caches");
ret = -ENOMEM;
goto fail;
}
/* New interval for cache cleanup timer */
- cache_clean_interval =
+ r->cache_clean_interval =
qemu_opt_get_number(opts, QCOW2_OPT_CACHE_CLEAN_INTERVAL, 0);
- if (cache_clean_interval > UINT_MAX) {
+ if (r->cache_clean_interval > UINT_MAX) {
error_setg(errp, "Cache clean interval too big");
ret = -EINVAL;
goto fail;
}
/* Enable lazy_refcounts according to image and command line options */
- use_lazy_refcounts = qemu_opt_get_bool(opts, QCOW2_OPT_LAZY_REFCOUNTS,
+ r->use_lazy_refcounts = qemu_opt_get_bool(opts, QCOW2_OPT_LAZY_REFCOUNTS,
(s->compatible_features & QCOW2_COMPAT_LAZY_REFCOUNTS));
- if (use_lazy_refcounts && s->qcow_version < 3) {
+ if (r->use_lazy_refcounts && s->qcow_version < 3) {
error_setg(errp, "Lazy refcounts require a qcow2 image with at least "
"qemu 1.1 compatibility level");
ret = -EINVAL;
@@ -702,49 +709,75 @@ static int qcow2_update_options(BlockDriverState *bs, QDict *options,
goto fail;
}
- /*
- * Start updating fields in BDRVQcowState.
- * After this point no failure is allowed any more.
- */
- s->overlap_check = 0;
+ r->overlap_check = 0;
for (i = 0; i < QCOW2_OL_MAX_BITNR; i++) {
/* overlap-check defines a template bitmask, but every flag may be
* overwritten through the associated boolean option */
- s->overlap_check |=
+ r->overlap_check |=
qemu_opt_get_bool(opts, overlap_bool_option_names[i],
overlap_check_template & (1 << i)) << i;
}
- s->l2_table_cache = l2_table_cache;
- s->refcount_block_cache = refcount_block_cache;
-
- s->use_lazy_refcounts = use_lazy_refcounts;
-
- s->discard_passthrough[QCOW2_DISCARD_NEVER] = false;
- s->discard_passthrough[QCOW2_DISCARD_ALWAYS] = true;
- s->discard_passthrough[QCOW2_DISCARD_REQUEST] =
+ r->discard_passthrough[QCOW2_DISCARD_NEVER] = false;
+ r->discard_passthrough[QCOW2_DISCARD_ALWAYS] = true;
+ r->discard_passthrough[QCOW2_DISCARD_REQUEST] =
qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_REQUEST,
flags & BDRV_O_UNMAP);
- s->discard_passthrough[QCOW2_DISCARD_SNAPSHOT] =
+ r->discard_passthrough[QCOW2_DISCARD_SNAPSHOT] =
qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_SNAPSHOT, true);
- s->discard_passthrough[QCOW2_DISCARD_OTHER] =
+ r->discard_passthrough[QCOW2_DISCARD_OTHER] =
qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_OTHER, false);
- s->cache_clean_interval = cache_clean_interval;
- cache_clean_timer_init(bs, bdrv_get_aio_context(bs));
-
ret = 0;
fail:
- if (ret < 0) {
- if (l2_table_cache) {
- qcow2_cache_destroy(bs, l2_table_cache);
- }
- if (refcount_block_cache) {
- qcow2_cache_destroy(bs, refcount_block_cache);
- }
- }
qemu_opts_del(opts);
opts = NULL;
+ return ret;
+}
+
+static void qcow2_update_options_commit(BlockDriverState *bs,
+ Qcow2ReopenState *r)
+{
+ BDRVQcowState *s = bs->opaque;
+ int i;
+
+ s->l2_table_cache = r->l2_table_cache;
+ s->refcount_block_cache = r->refcount_block_cache;
+
+ s->overlap_check = r->overlap_check;
+ s->use_lazy_refcounts = r->use_lazy_refcounts;
+
+ for (i = 0; i < QCOW2_DISCARD_MAX; i++) {
+ s->discard_passthrough[i] = r->discard_passthrough[i];
+ }
+
+ s->cache_clean_interval = r->cache_clean_interval;
+ cache_clean_timer_init(bs, bdrv_get_aio_context(bs));
+}
+
+static void qcow2_update_options_abort(BlockDriverState *bs,
+ Qcow2ReopenState *r)
+{
+ if (r->l2_table_cache) {
+ qcow2_cache_destroy(bs, r->l2_table_cache);
+ }
+ if (r->refcount_block_cache) {
+ qcow2_cache_destroy(bs, r->refcount_block_cache);
+ }
+}
+
+static int qcow2_update_options(BlockDriverState *bs, QDict *options,
+ int flags, Error **errp)
+{
+ Qcow2ReopenState r = {};
+ int ret;
+
+ ret = qcow2_update_options_prepare(bs, &r, options, flags, errp);
+ if (ret >= 0) {
+ qcow2_update_options_commit(bs, &r);
+ } else {
+ qcow2_update_options_abort(bs, &r);
+ }
return ret;
}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Qemu-devel] [PATCH v3 11/13] qcow2: Support updating driver-specific options in reopen
2015-09-07 13:26 [Qemu-devel] [PATCH v3 00/13] qcow2: reopen: Change driver-specific runtime options Kevin Wolf
` (9 preceding siblings ...)
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 10/13] qcow2: Make qcow2_update_options() suitable for transactions Kevin Wolf
@ 2015-09-07 13:26 ` Kevin Wolf
2015-09-07 19:44 ` Max Reitz
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 12/13] qemu-iotests: Reopen qcow2 with lazy-refcounts change Kevin Wolf
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 13/13] qemu-iotests: More qcow2 reopen tests Kevin Wolf
12 siblings, 1 reply; 19+ messages in thread
From: Kevin Wolf @ 2015-09-07 13:26 UTC (permalink / raw)
To: qemu-block; +Cc: kwolf, qemu-devel, mreitz
For updating the cache sizes or disabling lazy refcounts there is a bit
more to do than just changing the variables, but otherwise we're all set
for changing options during bdrv_reopen().
Just implement the missing pieces and hook the functions up in
bdrv_reopen().
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block/qcow2.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 72 insertions(+), 9 deletions(-)
diff --git a/block/qcow2.c b/block/qcow2.c
index eb379c1..23493d4 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -649,7 +649,24 @@ static int qcow2_update_options_prepare(BlockDriverState *bs,
goto fail;
}
- /* alloc L2 table/refcount block cache */
+ /* alloc new L2 table/refcount block cache, flush old one */
+ if (s->l2_table_cache) {
+ ret = qcow2_cache_flush(bs, s->l2_table_cache);
+ if (ret) {
+ error_setg_errno(errp, -ret, "Failed to flush the L2 table cache");
+ goto fail;
+ }
+ }
+
+ if (s->refcount_block_cache) {
+ ret = qcow2_cache_flush(bs, s->refcount_block_cache);
+ if (ret) {
+ error_setg_errno(errp, -ret,
+ "Failed to flush the refcount block cache");
+ goto fail;
+ }
+ }
+
r->l2_table_cache = qcow2_cache_create(bs, l2_cache_size);
r->refcount_block_cache = qcow2_cache_create(bs, refcount_cache_size);
if (r->l2_table_cache == NULL || r->refcount_block_cache == NULL) {
@@ -660,14 +677,15 @@ static int qcow2_update_options_prepare(BlockDriverState *bs,
/* New interval for cache cleanup timer */
r->cache_clean_interval =
- qemu_opt_get_number(opts, QCOW2_OPT_CACHE_CLEAN_INTERVAL, 0);
+ qemu_opt_get_number(opts, QCOW2_OPT_CACHE_CLEAN_INTERVAL,
+ s->cache_clean_interval);
if (r->cache_clean_interval > UINT_MAX) {
error_setg(errp, "Cache clean interval too big");
ret = -EINVAL;
goto fail;
}
- /* Enable lazy_refcounts according to image and command line options */
+ /* lazy-refcounts; flush if going from enabled to disabled */
r->use_lazy_refcounts = qemu_opt_get_bool(opts, QCOW2_OPT_LAZY_REFCOUNTS,
(s->compatible_features & QCOW2_COMPAT_LAZY_REFCOUNTS));
if (r->use_lazy_refcounts && s->qcow_version < 3) {
@@ -677,6 +695,14 @@ static int qcow2_update_options_prepare(BlockDriverState *bs,
goto fail;
}
+ if (s->use_lazy_refcounts && !r->use_lazy_refcounts) {
+ ret = qcow2_mark_clean(bs);
+ if (ret < 0) {
+ error_setg_errno(errp, -ret, "Failed to disable lazy refcounts");
+ goto fail;
+ }
+ }
+
/* Overlap check options */
opt_overlap_check = qemu_opt_get(opts, QCOW2_OPT_OVERLAP);
opt_overlap_check_template = qemu_opt_get(opts, QCOW2_OPT_OVERLAP_TEMPLATE);
@@ -741,6 +767,12 @@ static void qcow2_update_options_commit(BlockDriverState *bs,
BDRVQcowState *s = bs->opaque;
int i;
+ if (s->l2_table_cache) {
+ qcow2_cache_destroy(bs, s->l2_table_cache);
+ }
+ if (s->refcount_block_cache) {
+ qcow2_cache_destroy(bs, s->refcount_block_cache);
+ }
s->l2_table_cache = r->l2_table_cache;
s->refcount_block_cache = r->refcount_block_cache;
@@ -751,8 +783,11 @@ static void qcow2_update_options_commit(BlockDriverState *bs,
s->discard_passthrough[i] = r->discard_passthrough[i];
}
- s->cache_clean_interval = r->cache_clean_interval;
- cache_clean_timer_init(bs, bdrv_get_aio_context(bs));
+ if (s->cache_clean_interval != r->cache_clean_interval) {
+ cache_clean_timer_del(bs);
+ s->cache_clean_interval = r->cache_clean_interval;
+ cache_clean_timer_init(bs, bdrv_get_aio_context(bs));
+ }
}
static void qcow2_update_options_abort(BlockDriverState *bs,
@@ -1199,26 +1234,52 @@ static int qcow2_set_key(BlockDriverState *bs, const char *key)
return 0;
}
-/* We have no actual commit/abort logic for qcow2, but we need to write out any
- * unwritten data if we reopen read-only. */
static int qcow2_reopen_prepare(BDRVReopenState *state,
BlockReopenQueue *queue, Error **errp)
{
+ Qcow2ReopenState *r;
int ret;
+ r = g_new0(Qcow2ReopenState, 1);
+ state->opaque = r;
+
+ ret = qcow2_update_options_prepare(state->bs, r, state->options,
+ state->flags, errp);
+ if (ret < 0) {
+ goto fail;
+ }
+
+ /* We need to write out any unwritten data if we reopen read-only. */
if ((state->flags & BDRV_O_RDWR) == 0) {
ret = bdrv_flush(state->bs);
if (ret < 0) {
- return ret;
+ goto fail;
}
ret = qcow2_mark_clean(state->bs);
if (ret < 0) {
- return ret;
+ goto fail;
}
}
return 0;
+
+fail:
+ qcow2_update_options_abort(state->bs, r);
+ g_free(r);
+ return ret;
+}
+
+static void qcow2_reopen_commit(BDRVReopenState *state)
+{
+ qcow2_update_options_commit(state->bs, state->opaque);
+ g_free(state->opaque);
+}
+
+static void qcow2_reopen_abort(BDRVReopenState *state)
+{
+ qcow2_update_options_abort(state->bs, state->opaque);
+ g_free(state->opaque);
}
static int64_t coroutine_fn qcow2_co_get_block_status(BlockDriverState *bs,
@@ -3082,6 +3143,8 @@ BlockDriver bdrv_qcow2 = {
.bdrv_open = qcow2_open,
.bdrv_close = qcow2_close,
.bdrv_reopen_prepare = qcow2_reopen_prepare,
+ .bdrv_reopen_commit = qcow2_reopen_commit,
+ .bdrv_reopen_abort = qcow2_reopen_abort,
.bdrv_create = qcow2_create,
.bdrv_has_zero_init = bdrv_has_zero_init_1,
.bdrv_co_get_block_status = qcow2_co_get_block_status,
--
1.8.3.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Qemu-devel] [PATCH v3 12/13] qemu-iotests: Reopen qcow2 with lazy-refcounts change
2015-09-07 13:26 [Qemu-devel] [PATCH v3 00/13] qcow2: reopen: Change driver-specific runtime options Kevin Wolf
` (10 preceding siblings ...)
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 11/13] qcow2: Support updating driver-specific options in reopen Kevin Wolf
@ 2015-09-07 13:26 ` Kevin Wolf
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 13/13] qemu-iotests: More qcow2 reopen tests Kevin Wolf
12 siblings, 0 replies; 19+ messages in thread
From: Kevin Wolf @ 2015-09-07 13:26 UTC (permalink / raw)
To: qemu-block; +Cc: kwolf, qemu-devel, mreitz
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
---
tests/qemu-iotests/039 | 27 +++++++++++++++++++++++++++
tests/qemu-iotests/039.out | 18 ++++++++++++++++++
2 files changed, 45 insertions(+)
diff --git a/tests/qemu-iotests/039 b/tests/qemu-iotests/039
index 617f397..9e9b379 100755
--- a/tests/qemu-iotests/039
+++ b/tests/qemu-iotests/039
@@ -147,6 +147,33 @@ $PYTHON qcow2.py "$TEST_IMG".base dump-header | grep incompatible_features
_check_test_img
TEST_IMG="$TEST_IMG".base _check_test_img
+echo
+echo "== Changing lazy_refcounts setting at runtime =="
+
+IMGOPTS="compat=1.1,lazy_refcounts=off"
+_make_test_img $size
+
+$QEMU_IO -c "reopen -o lazy-refcounts=on" \
+ -c "write -P 0x5a 0 512" \
+ -c "sigraise $(kill -l KILL)" "$TEST_IMG" 2>&1 \
+ | _filter_qemu_io
+
+# The dirty bit must be set
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+_check_test_img
+
+IMGOPTS="compat=1.1,lazy_refcounts=on"
+_make_test_img $size
+
+$QEMU_IO -c "reopen -o lazy-refcounts=off" \
+ -c "write -P 0x5a 0 512" \
+ -c "sigraise $(kill -l KILL)" "$TEST_IMG" 2>&1 \
+ | _filter_qemu_io
+
+# The dirty bit must not be set
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+_check_test_img
+
# success, all done
echo "*** done"
diff --git a/tests/qemu-iotests/039.out b/tests/qemu-iotests/039.out
index b055670..39859b2 100644
--- a/tests/qemu-iotests/039.out
+++ b/tests/qemu-iotests/039.out
@@ -74,4 +74,22 @@ incompatible_features 0x0
incompatible_features 0x0
No errors were found on the image.
No errors were found on the image.
+
+== Changing lazy_refcounts setting at runtime ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
+wrote 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+./common.config: Killed ( exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@" )
+incompatible_features 0x1
+ERROR cluster 5 refcount=0 reference=1
+ERROR OFLAG_COPIED data cluster: l2_entry=8000000000050000 refcount=0
+
+2 errors were found on the image.
+Data may be corrupted, or further writes to the image may corrupt it.
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
+wrote 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+./common.config: Killed ( exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@" )
+incompatible_features 0x0
+No errors were found on the image.
*** done
--
1.8.3.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [Qemu-devel] [PATCH v3 13/13] qemu-iotests: More qcow2 reopen tests
2015-09-07 13:26 [Qemu-devel] [PATCH v3 00/13] qcow2: reopen: Change driver-specific runtime options Kevin Wolf
` (11 preceding siblings ...)
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 12/13] qemu-iotests: Reopen qcow2 with lazy-refcounts change Kevin Wolf
@ 2015-09-07 13:26 ` Kevin Wolf
2015-09-07 19:45 ` Max Reitz
12 siblings, 1 reply; 19+ messages in thread
From: Kevin Wolf @ 2015-09-07 13:26 UTC (permalink / raw)
To: qemu-block; +Cc: kwolf, qemu-devel, mreitz
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
tests/qemu-iotests/137 | 145 +++++++++++++++++++++++++++++++++++++++++++++
tests/qemu-iotests/137.out | 42 +++++++++++++
tests/qemu-iotests/group | 1 +
3 files changed, 188 insertions(+)
create mode 100755 tests/qemu-iotests/137
create mode 100644 tests/qemu-iotests/137.out
diff --git a/tests/qemu-iotests/137 b/tests/qemu-iotests/137
new file mode 100755
index 0000000..9a6597c
--- /dev/null
+++ b/tests/qemu-iotests/137
@@ -0,0 +1,145 @@
+#!/bin/bash
+#
+# Test qcow2 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
+. ./common.qemu
+
+_supported_fmt qcow2
+_supported_proto generic
+_supported_os Linux
+
+
+_make_test_img 64M
+
+echo === Try setting valid values for all options ===
+echo
+
+# Try all options and then check that all of the basic I/O operations still
+# work on this image.
+$QEMU_IO \
+ -c "reopen -o lazy-refcounts=on,pass-discard-request=on" \
+ -c "reopen -o lazy-refcounts=off,pass-discard-request=off" \
+ -c "reopen -o pass-discard-snapshot=on,pass-discard-other=on" \
+ -c "reopen -o pass-discard-snapshot=off,pass-discard-other=off" \
+ -c "reopen -o overlap-check=all" \
+ -c "reopen -o overlap-check=none" \
+ -c "reopen -o overlap-check=cached" \
+ -c "reopen -o overlap-check=constant" \
+ -c "reopen -o overlap-check.template=all" \
+ -c "reopen -o overlap-check.template=none" \
+ -c "reopen -o overlap-check.template=cached" \
+ -c "reopen -o overlap-check.template=constant" \
+ -c "reopen -o overlap-check.main-header=on" \
+ -c "reopen -o overlap-check.main-header=off" \
+ -c "reopen -o overlap-check.active-l1=on" \
+ -c "reopen -o overlap-check.active-l1=off" \
+ -c "reopen -o overlap-check.active-l2=on" \
+ -c "reopen -o overlap-check.active-l2=off" \
+ -c "reopen -o overlap-check.refcount-table=on" \
+ -c "reopen -o overlap-check.refcount-table=off" \
+ -c "reopen -o overlap-check.refcount-block=on" \
+ -c "reopen -o overlap-check.refcount-block=off" \
+ -c "reopen -o overlap-check.snapshot-table=on" \
+ -c "reopen -o overlap-check.snapshot-table=off" \
+ -c "reopen -o overlap-check.inactive-l1=on" \
+ -c "reopen -o overlap-check.inactive-l1=off" \
+ -c "reopen -o overlap-check.inactive-l2=on" \
+ -c "reopen -o overlap-check.inactive-l2=off" \
+ -c "reopen -o cache-size=1M" \
+ -c "reopen -o l2-cache-size=512k" \
+ -c "reopen -o refcount-cache-size=128k" \
+ -c "reopen -o cache-clean-interval=5" \
+ -c "reopen -o cache-clean-interval=0" \
+ -c "reopen -o cache-clean-interval=10" \
+ \
+ -c "write -P 55 0 32M" \
+ -c "read -P 55 0 32M" \
+ -c "discard 0 32M" \
+ -c "write -z 0 32M" \
+ -c "read -P 0 0 32M" \
+ \
+ "$TEST_IMG" | _filter_qemu_io
+
+
+echo
+echo === Try setting some invalid values ===
+echo
+
+$QEMU_IO \
+ -c "reopen -o lazy-refcounts=42" \
+ -c "reopen -o cache-size=1M,l2-cache-size=64k,refcount-cache-size=64k" \
+ -c "reopen -o cache-size=1M,l2-cache-size=2M" \
+ -c "reopen -o cache-size=1M,refcount-cache-size=2M" \
+ -c "reopen -o l2-cache-size=256T" \
+ -c "reopen -o refcount-cache-size=256T" \
+ -c "reopen -o overlap-check=constant,overlap-check.template=all" \
+ -c "reopen -o overlap-check=blubb" \
+ -c "reopen -o overlap-check.template=blubb" \
+ -c "reopen -o cache-clean-interval=-1" \
+ "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo === Test transaction semantics ===
+echo
+
+# Whether lazy-refcounts was actually enabled can easily be tested: Check if
+# the dirty bit is set after a crash
+$QEMU_IO \
+ -c "reopen -o lazy-refcounts=on,overlap-check=blubb" \
+ -c "write -P 0x5a 0 512" \
+ -c "sigraise $(kill -l KILL)" \
+ "$TEST_IMG" 2>&1 | _filter_qemu_io
+
+# The dirty bit must not be set
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+
+# Similarly we can test whether corruption detection has been enabled:
+# Create L1/L2, overwrite first entry in refcount block, allocate something.
+# Disabling the checks should fail, so the corruption must be detected.
+_make_test_img 64M
+$QEMU_IO -c "write 0 64k" "$TEST_IMG" | _filter_qemu_io
+poke_file "$TEST_IMG" "$((0x20000))" "\x00\x00"
+$QEMU_IO \
+ -c "reopen -o overlap-check=none,lazy-refcounts=42" \
+ -c "write 64k 64k" \
+ "$TEST_IMG" 2>&1 | _filter_qemu_io
+
+# success, all done
+echo '*** done'
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/137.out b/tests/qemu-iotests/137.out
new file mode 100644
index 0000000..cf55a41
--- /dev/null
+++ b/tests/qemu-iotests/137.out
@@ -0,0 +1,42 @@
+QA output created by 137
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+=== Try setting valid values for all options ===
+
+wrote 33554432/33554432 bytes at offset 0
+32 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 33554432/33554432 bytes at offset 0
+32 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+discard 33554432/33554432 bytes at offset 0
+32 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 33554432/33554432 bytes at offset 0
+32 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 33554432/33554432 bytes at offset 0
+32 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+=== Try setting some invalid values ===
+
+Parameter 'lazy-refcounts' expects 'on' or 'off'
+cache-size, l2-cache-size and refcount-cache-size may not be set the same time
+l2-cache-size may not exceed cache-size
+refcount-cache-size may not exceed cache-size
+L2 cache size too big
+L2 cache size too big
+Conflicting values for qcow2 options 'overlap-check' ('constant') and 'overlap-check.template' ('all')
+Unsupported value 'blubb' for qcow2 option 'overlap-check'. Allowed are any of the following: none, constant, cached, all
+Unsupported value 'blubb' for qcow2 option 'overlap-check'. Allowed are any of the following: none, constant, cached, all
+Cache clean interval too big
+
+=== Test transaction semantics ===
+
+Unsupported value 'blubb' for qcow2 option 'overlap-check'. Allowed are any of the following: none, constant, cached, all
+wrote 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+./common.config: Killed ( exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@" )
+incompatible_features 0x0
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+wrote 65536/65536 bytes at offset 0
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+Parameter 'lazy-refcounts' expects 'on' or 'off'
+qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with qcow2_header); further corruption events will be suppressed
+write failed: Input/output error
+*** done
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index c430b6c..3a6a8f0 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -134,3 +134,4 @@
132 rw auto quick
134 rw auto quick
135 rw auto
+137 rw auto
--
1.8.3.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [Qemu-devel] [PATCH v3 07/13] qcow2: Move rest of option handling to qcow2_update_options()
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 07/13] qcow2: Move rest of option handling to qcow2_update_options() Kevin Wolf
@ 2015-09-07 19:35 ` Max Reitz
0 siblings, 0 replies; 19+ messages in thread
From: Max Reitz @ 2015-09-07 19:35 UTC (permalink / raw)
To: Kevin Wolf, qemu-block; +Cc: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 421 bytes --]
On 07.09.2015 15:26, Kevin Wolf wrote:
> With this commit, the handling of driver-specific options in
> qcow2_open() is completely separated out into qcow2_update_options().
>
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
> block/qcow2.c | 134 +++++++++++++++++++++++++++++-----------------------------
> 1 file changed, 68 insertions(+), 66 deletions(-)
Reviewed-by: Max Reitz <mreitz@redhat.com>
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [Qemu-devel] [PATCH v3 08/13] qcow2: Leave s unchanged on qcow2_update_options() failure
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 08/13] qcow2: Leave s unchanged on qcow2_update_options() failure Kevin Wolf
@ 2015-09-07 19:38 ` Max Reitz
0 siblings, 0 replies; 19+ messages in thread
From: Max Reitz @ 2015-09-07 19:38 UTC (permalink / raw)
To: Kevin Wolf, qemu-block; +Cc: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 432 bytes --]
On 07.09.2015 15:26, Kevin Wolf wrote:
> On return, either all new options should be applied to BDRVQcowState (on
> success), or all of the old settings should be preserved (on failure).
>
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
> block/qcow2.c | 57 +++++++++++++++++++++++++++++++++++----------------------
> 1 file changed, 35 insertions(+), 22 deletions(-)
Reviewed-by: Max Reitz <mreitz@redhat.com>
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [Qemu-devel] [PATCH v3 10/13] qcow2: Make qcow2_update_options() suitable for transactions
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 10/13] qcow2: Make qcow2_update_options() suitable for transactions Kevin Wolf
@ 2015-09-07 19:41 ` Max Reitz
0 siblings, 0 replies; 19+ messages in thread
From: Max Reitz @ 2015-09-07 19:41 UTC (permalink / raw)
To: Kevin Wolf, qemu-block; +Cc: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 421 bytes --]
On 07.09.2015 15:26, Kevin Wolf wrote:
> Before we can allow updating options at runtime with bdrv_reopen(), we
> need to split the function into prepare/commit/abort parts.
>
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
> block/qcow2.c | 113 +++++++++++++++++++++++++++++++++++++---------------------
> 1 file changed, 73 insertions(+), 40 deletions(-)
Reviewed-by: Max Reitz <mreitz@redhat.com>
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [Qemu-devel] [PATCH v3 11/13] qcow2: Support updating driver-specific options in reopen
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 11/13] qcow2: Support updating driver-specific options in reopen Kevin Wolf
@ 2015-09-07 19:44 ` Max Reitz
0 siblings, 0 replies; 19+ messages in thread
From: Max Reitz @ 2015-09-07 19:44 UTC (permalink / raw)
To: Kevin Wolf, qemu-block; +Cc: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 756 bytes --]
On 07.09.2015 15:26, Kevin Wolf wrote:
> For updating the cache sizes or disabling lazy refcounts
And updating the cache clean timer, too.
> there is a bit
> more to do than just changing the variables, but otherwise we're all set
> for changing options during bdrv_reopen().
>
> Just implement the missing pieces and hook the functions up in
> bdrv_reopen().
>
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
> block/qcow2.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------
> 1 file changed, 72 insertions(+), 9 deletions(-)
Whether you mention it or not (can be fixed up when applying the patch,
too):
Reviewed-by: Max Reitz <mreitz@redhat.com>
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [Qemu-devel] [PATCH v3 13/13] qemu-iotests: More qcow2 reopen tests
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 13/13] qemu-iotests: More qcow2 reopen tests Kevin Wolf
@ 2015-09-07 19:45 ` Max Reitz
0 siblings, 0 replies; 19+ messages in thread
From: Max Reitz @ 2015-09-07 19:45 UTC (permalink / raw)
To: Kevin Wolf, qemu-block; +Cc: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 451 bytes --]
On 07.09.2015 15:26, Kevin Wolf wrote:
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
> tests/qemu-iotests/137 | 145 +++++++++++++++++++++++++++++++++++++++++++++
> tests/qemu-iotests/137.out | 42 +++++++++++++
> tests/qemu-iotests/group | 1 +
> 3 files changed, 188 insertions(+)
> create mode 100755 tests/qemu-iotests/137
> create mode 100644 tests/qemu-iotests/137.out
Reviewed-by: Max Reitz <mreitz@redhat.com>
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2015-09-07 19:46 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-09-07 13:26 [Qemu-devel] [PATCH v3 00/13] qcow2: reopen: Change driver-specific runtime options Kevin Wolf
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 01/13] block: Allow specifying driver-specific options to reopen Kevin Wolf
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 02/13] qemu-io: Remove duplicate 'open' error message Kevin Wolf
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 03/13] qemu-io: Add command 'reopen' Kevin Wolf
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 04/13] qcow2: Improve error message Kevin Wolf
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 05/13] qcow2: Factor out qcow2_update_options() Kevin Wolf
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 06/13] qcow2: Move qcow2_update_options() call up Kevin Wolf
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 07/13] qcow2: Move rest of option handling to qcow2_update_options() Kevin Wolf
2015-09-07 19:35 ` Max Reitz
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 08/13] qcow2: Leave s unchanged on qcow2_update_options() failure Kevin Wolf
2015-09-07 19:38 ` Max Reitz
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 09/13] qcow2: Fix memory leak in qcow2_update_options() error path Kevin Wolf
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 10/13] qcow2: Make qcow2_update_options() suitable for transactions Kevin Wolf
2015-09-07 19:41 ` Max Reitz
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 11/13] qcow2: Support updating driver-specific options in reopen Kevin Wolf
2015-09-07 19:44 ` Max Reitz
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 12/13] qemu-iotests: Reopen qcow2 with lazy-refcounts change Kevin Wolf
2015-09-07 13:26 ` [Qemu-devel] [PATCH v3 13/13] qemu-iotests: More qcow2 reopen tests Kevin Wolf
2015-09-07 19:45 ` Max Reitz
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).