* [Qemu-devel] [PATCH v6 1/4] block: rename BlockdevSnapshot to BlockdevSnapshotSync
2015-09-22 13:28 [Qemu-devel] [PATCH v6 0/4] Add 'blockdev-snapshot' command Alberto Garcia
@ 2015-09-22 13:28 ` Alberto Garcia
2015-10-06 15:31 ` Kevin Wolf
2015-09-22 13:28 ` [Qemu-devel] [PATCH v6 2/4] block: support passing 'backing': '' to 'blockdev-add' Alberto Garcia
` (2 subsequent siblings)
3 siblings, 1 reply; 13+ messages in thread
From: Alberto Garcia @ 2015-09-22 13:28 UTC (permalink / raw)
To: qemu-devel
Cc: Kevin Wolf, Alberto Garcia, qemu-block, Max Reitz,
Stefan Hajnoczi
We will introduce the 'blockdev-snapshot' command that will require
its own struct for the parameters, so we need to rename this one in
order to avoid name clashes.
Signed-off-by: Alberto Garcia <berto@igalia.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
---
blockdev.c | 2 +-
qapi-schema.json | 2 +-
qapi/block-core.json | 8 ++++----
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/blockdev.c b/blockdev.c
index 4731843..1a5b889 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1166,7 +1166,7 @@ void qmp_blockdev_snapshot_sync(bool has_device, const char *device,
bool has_format, const char *format,
bool has_mode, NewImageMode mode, Error **errp)
{
- BlockdevSnapshot snapshot = {
+ BlockdevSnapshotSync snapshot = {
.has_device = has_device,
.device = (char *) device,
.has_node_name = has_node_name,
diff --git a/qapi-schema.json b/qapi-schema.json
index 0d5190b..45a85db 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1499,7 +1499,7 @@
##
{ 'union': 'TransactionAction',
'data': {
- 'blockdev-snapshot-sync': 'BlockdevSnapshot',
+ 'blockdev-snapshot-sync': 'BlockdevSnapshotSync',
'drive-backup': 'DriveBackup',
'blockdev-backup': 'BlockdevBackup',
'abort': 'Abort',
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 5f12af7..6b5ac02 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -682,7 +682,7 @@
'data': [ 'existing', 'absolute-paths' ] }
##
-# @BlockdevSnapshot
+# @BlockdevSnapshotSync
#
# Either @device or @node-name must be set but not both.
#
@@ -699,7 +699,7 @@
# @mode: #optional whether and how QEMU should create a new image, default is
# 'absolute-paths'.
##
-{ 'struct': 'BlockdevSnapshot',
+{ 'struct': 'BlockdevSnapshotSync',
'data': { '*device': 'str', '*node-name': 'str',
'snapshot-file': 'str', '*snapshot-node-name': 'str',
'*format': 'str', '*mode': 'NewImageMode' } }
@@ -790,7 +790,7 @@
#
# Generates a synchronous snapshot of a block device.
#
-# For the arguments, see the documentation of BlockdevSnapshot.
+# For the arguments, see the documentation of BlockdevSnapshotSync.
#
# Returns: nothing on success
# If @device is not a valid block device, DeviceNotFound
@@ -798,7 +798,7 @@
# Since 0.14.0
##
{ 'command': 'blockdev-snapshot-sync',
- 'data': 'BlockdevSnapshot' }
+ 'data': 'BlockdevSnapshotSync' }
##
# @change-backing-file
--
2.5.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v6 2/4] block: support passing 'backing': '' to 'blockdev-add'
2015-09-22 13:28 [Qemu-devel] [PATCH v6 0/4] Add 'blockdev-snapshot' command Alberto Garcia
2015-09-22 13:28 ` [Qemu-devel] [PATCH v6 1/4] block: rename BlockdevSnapshot to BlockdevSnapshotSync Alberto Garcia
@ 2015-09-22 13:28 ` Alberto Garcia
2015-10-06 15:31 ` Kevin Wolf
2015-09-22 13:28 ` [Qemu-devel] [PATCH v6 3/4] block: add a 'blockdev-snapshot' QMP command Alberto Garcia
2015-09-22 13:28 ` [Qemu-devel] [PATCH v6 4/4] block: add tests for the 'blockdev-snapshot' command Alberto Garcia
3 siblings, 1 reply; 13+ messages in thread
From: Alberto Garcia @ 2015-09-22 13:28 UTC (permalink / raw)
To: qemu-devel
Cc: Kevin Wolf, Alberto Garcia, qemu-block, Max Reitz,
Stefan Hajnoczi
Passing an empty string allows opening an image but not its backing
file. This was already described in the API documentation, only the
implementation was missing.
This is useful for creating snapshots using images opened with
blockdev-add, since they are not supposed to have a backing image
before the operation.
Signed-off-by: Alberto Garcia <berto@igalia.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
block.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/block.c b/block.c
index 7776871..3a4cc9c 100644
--- a/block.c
+++ b/block.c
@@ -1406,6 +1406,7 @@ static int bdrv_open_inherit(BlockDriverState **pbs, const char *filename,
BlockDriverState *file = NULL, *bs;
BlockDriver *drv = NULL;
const char *drvname;
+ const char *backing;
Error *local_err = NULL;
int snapshot_flags = 0;
@@ -1473,6 +1474,12 @@ static int bdrv_open_inherit(BlockDriverState **pbs, const char *filename,
assert(drvname || !(flags & BDRV_O_PROTOCOL));
+ backing = qdict_get_try_str(options, "backing");
+ if (backing && *backing == '\0') {
+ flags |= BDRV_O_NO_BACKING;
+ qdict_del(options, "backing");
+ }
+
bs->open_flags = flags;
bs->options = options;
options = qdict_clone_shallow(options);
--
2.5.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v6 2/4] block: support passing 'backing': '' to 'blockdev-add'
2015-09-22 13:28 ` [Qemu-devel] [PATCH v6 2/4] block: support passing 'backing': '' to 'blockdev-add' Alberto Garcia
@ 2015-10-06 15:31 ` Kevin Wolf
0 siblings, 0 replies; 13+ messages in thread
From: Kevin Wolf @ 2015-10-06 15:31 UTC (permalink / raw)
To: Alberto Garcia; +Cc: Stefan Hajnoczi, qemu-devel, qemu-block, Max Reitz
Am 22.09.2015 um 15:28 hat Alberto Garcia geschrieben:
> Passing an empty string allows opening an image but not its backing
> file. This was already described in the API documentation, only the
> implementation was missing.
>
> This is useful for creating snapshots using images opened with
> blockdev-add, since they are not supposed to have a backing image
> before the operation.
>
> Signed-off-by: Alberto Garcia <berto@igalia.com>
> Reviewed-by: Max Reitz <mreitz@redhat.com>
> Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
^ permalink raw reply [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v6 3/4] block: add a 'blockdev-snapshot' QMP command
2015-09-22 13:28 [Qemu-devel] [PATCH v6 0/4] Add 'blockdev-snapshot' command Alberto Garcia
2015-09-22 13:28 ` [Qemu-devel] [PATCH v6 1/4] block: rename BlockdevSnapshot to BlockdevSnapshotSync Alberto Garcia
2015-09-22 13:28 ` [Qemu-devel] [PATCH v6 2/4] block: support passing 'backing': '' to 'blockdev-add' Alberto Garcia
@ 2015-09-22 13:28 ` Alberto Garcia
2015-09-22 16:38 ` Max Reitz
2015-10-06 15:30 ` Kevin Wolf
2015-09-22 13:28 ` [Qemu-devel] [PATCH v6 4/4] block: add tests for the 'blockdev-snapshot' command Alberto Garcia
3 siblings, 2 replies; 13+ messages in thread
From: Alberto Garcia @ 2015-09-22 13:28 UTC (permalink / raw)
To: qemu-devel
Cc: Kevin Wolf, Alberto Garcia, qemu-block, Max Reitz,
Stefan Hajnoczi
One of the limitations of the 'blockdev-snapshot-sync' command is that
it does not allow passing BlockdevOptions to the newly created
snapshots, so they are always opened using the default values.
Extending the command to allow passing options is not a practical
solution because there is overlap between those options and some of
the existing parameters of the command.
This patch introduces a new 'blockdev-snapshot' command with a simpler
interface: it just takes two references to existing block devices that
will be used as the source and target for the snapshot.
Since the main difference between the two commands is that one of them
creates and opens the target image, while the other uses an already
opened one, the bulk of the implementation is shared.
Signed-off-by: Alberto Garcia <berto@igalia.com>
Cc: Eric Blake <eblake@redhat.com>
Cc: Max Reitz <mreitz@redhat.com>
---
blockdev.c | 163 ++++++++++++++++++++++++++++++++-------------------
qapi-schema.json | 2 +
qapi/block-core.json | 28 +++++++++
qmp-commands.hx | 38 ++++++++++++
4 files changed, 171 insertions(+), 60 deletions(-)
diff --git a/blockdev.c b/blockdev.c
index 1a5b889..daf72f3 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1183,6 +1183,18 @@ void qmp_blockdev_snapshot_sync(bool has_device, const char *device,
&snapshot, errp);
}
+void qmp_blockdev_snapshot(const char *node, const char *overlay,
+ Error **errp)
+{
+ BlockdevSnapshot snapshot_data = {
+ .node = (char *) node,
+ .overlay = (char *) overlay
+ };
+
+ blockdev_do_action(TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT,
+ &snapshot_data, errp);
+}
+
void qmp_blockdev_snapshot_internal_sync(const char *device,
const char *name,
Error **errp)
@@ -1521,57 +1533,48 @@ typedef struct ExternalSnapshotState {
static void external_snapshot_prepare(BlkTransactionState *common,
Error **errp)
{
- int flags, ret;
- QDict *options;
+ int flags = 0, ret;
+ QDict *options = NULL;
Error *local_err = NULL;
- bool has_device = false;
+ /* Device and node name of the image to generate the snapshot from */
const char *device;
- bool has_node_name = false;
const char *node_name;
- bool has_snapshot_node_name = false;
- const char *snapshot_node_name;
+ /* Reference to the new image (for 'blockdev-snapshot') */
+ const char *snapshot_ref;
+ /* File name of the new image (for 'blockdev-snapshot-sync') */
const char *new_image_file;
- const char *format = "qcow2";
- enum NewImageMode mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
ExternalSnapshotState *state =
DO_UPCAST(ExternalSnapshotState, common, common);
TransactionAction *action = common->action;
- /* get parameters */
- g_assert(action->kind == TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC);
-
- has_device = action->blockdev_snapshot_sync->has_device;
- device = action->blockdev_snapshot_sync->device;
- has_node_name = action->blockdev_snapshot_sync->has_node_name;
- node_name = action->blockdev_snapshot_sync->node_name;
- has_snapshot_node_name =
- action->blockdev_snapshot_sync->has_snapshot_node_name;
- snapshot_node_name = action->blockdev_snapshot_sync->snapshot_node_name;
-
- new_image_file = action->blockdev_snapshot_sync->snapshot_file;
- if (action->blockdev_snapshot_sync->has_format) {
- format = action->blockdev_snapshot_sync->format;
- }
- if (action->blockdev_snapshot_sync->has_mode) {
- mode = action->blockdev_snapshot_sync->mode;
+ /* 'blockdev-snapshot' and 'blockdev-snapshot-sync' have similar
+ * purpose but a different set of parameters */
+ switch (action->kind) {
+ case TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT:
+ {
+ BlockdevSnapshot *s = action->blockdev_snapshot;
+ device = s->node;
+ node_name = s->node;
+ new_image_file = NULL;
+ snapshot_ref = s->overlay;
+ }
+ break;
+ case TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC:
+ {
+ BlockdevSnapshotSync *s = action->blockdev_snapshot_sync;
+ device = s->has_device ? s->device : NULL;
+ node_name = s->has_node_name ? s->node_name : NULL;
+ new_image_file = s->snapshot_file;
+ snapshot_ref = NULL;
+ }
+ break;
+ default:
+ g_assert_not_reached();
}
/* start processing */
- state->old_bs = bdrv_lookup_bs(has_device ? device : NULL,
- has_node_name ? node_name : NULL,
- &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
-
- if (has_node_name && !has_snapshot_node_name) {
- error_setg(errp, "New snapshot node name missing");
- return;
- }
-
- if (has_snapshot_node_name && bdrv_find_node(snapshot_node_name)) {
- error_setg(errp, "New snapshot node name already existing");
+ state->old_bs = bdrv_lookup_bs(device, node_name, errp);
+ if (!state->old_bs) {
return;
}
@@ -1601,35 +1604,69 @@ static void external_snapshot_prepare(BlkTransactionState *common,
return;
}
- flags = state->old_bs->open_flags;
+ if (action->kind == TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC) {
+ BlockdevSnapshotSync *s = action->blockdev_snapshot_sync;
+ const char *format = s->has_format ? s->format : "qcow2";
+ enum NewImageMode mode;
+ const char *snapshot_node_name =
+ s->has_snapshot_node_name ? s->snapshot_node_name : NULL;
- /* create new image w/backing file */
- if (mode != NEW_IMAGE_MODE_EXISTING) {
- bdrv_img_create(new_image_file, format,
- state->old_bs->filename,
- state->old_bs->drv->format_name,
- NULL, -1, flags, &local_err, false);
- if (local_err) {
- error_propagate(errp, local_err);
+ if (node_name && !snapshot_node_name) {
+ error_setg(errp, "New snapshot node name missing");
return;
}
- }
- options = qdict_new();
- if (has_snapshot_node_name) {
- qdict_put(options, "node-name",
- qstring_from_str(snapshot_node_name));
+ if (snapshot_node_name && bdrv_find_node(snapshot_node_name)) {
+ error_setg(errp, "New snapshot node name already exists");
+ return;
+ }
+
+ flags = state->old_bs->open_flags;
+
+ /* create new image w/backing file */
+ mode = s->has_mode ? s->mode : NEW_IMAGE_MODE_ABSOLUTE_PATHS;
+ if (mode != NEW_IMAGE_MODE_EXISTING) {
+ bdrv_img_create(new_image_file, format,
+ state->old_bs->filename,
+ state->old_bs->drv->format_name,
+ NULL, -1, flags, &local_err, false);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+ }
+
+ options = qdict_new();
+ if (s->has_snapshot_node_name) {
+ qdict_put(options, "node-name",
+ qstring_from_str(snapshot_node_name));
+ }
+ qdict_put(options, "driver", qstring_from_str(format));
+
+ flags |= BDRV_O_NO_BACKING;
}
- qdict_put(options, "driver", qstring_from_str(format));
- /* TODO Inherit bs->options or only take explicit options with an
- * extended QMP command? */
assert(state->new_bs == NULL);
- ret = bdrv_open(&state->new_bs, new_image_file, NULL, options,
- flags | BDRV_O_NO_BACKING, &local_err);
+ ret = bdrv_open(&state->new_bs, new_image_file, snapshot_ref, options,
+ flags, errp);
/* We will manually add the backing_hd field to the bs later */
if (ret != 0) {
- error_propagate(errp, local_err);
+ return;
+ }
+
+ if (state->new_bs->blk != NULL) {
+ error_setg(errp, "The snapshot is already in use by %s",
+ blk_name(state->new_bs->blk));
+ return;
+ }
+
+ if (bdrv_op_is_blocked(state->new_bs, BLOCK_OP_TYPE_EXTERNAL_SNAPSHOT,
+ errp)) {
+ return;
+ }
+
+ if (state->new_bs->backing_hd != NULL) {
+ error_setg(errp, "The snapshot already has a backing image");
}
}
@@ -1818,6 +1855,12 @@ static void abort_commit(BlkTransactionState *common)
}
static const BdrvActionOps actions[] = {
+ [TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT] = {
+ .instance_size = sizeof(ExternalSnapshotState),
+ .prepare = external_snapshot_prepare,
+ .commit = external_snapshot_commit,
+ .abort = external_snapshot_abort,
+ },
[TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC] = {
.instance_size = sizeof(ExternalSnapshotState),
.prepare = external_snapshot_prepare,
diff --git a/qapi-schema.json b/qapi-schema.json
index 45a85db..296da01 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1496,9 +1496,11 @@
# abort since 1.6
# blockdev-snapshot-internal-sync since 1.7
# blockdev-backup since 2.3
+# blockdev-snapshot since 2.5
##
{ 'union': 'TransactionAction',
'data': {
+ 'blockdev-snapshot': 'BlockdevSnapshot',
'blockdev-snapshot-sync': 'BlockdevSnapshotSync',
'drive-backup': 'DriveBackup',
'blockdev-backup': 'BlockdevBackup',
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 6b5ac02..2563ac9 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -705,6 +705,21 @@
'*format': 'str', '*mode': 'NewImageMode' } }
##
+# @BlockdevSnapshot
+#
+# @node: device or node name that will have a snapshot created.
+#
+# @overlay: reference to the existing block device that will become
+# the overlay of @node, as part of creating the snapshot.
+# It must not have a current backing file (this can be
+# achieved by passing "backing": "" to blockdev-add).
+#
+# Since 2.5
+##
+{ 'struct': 'BlockdevSnapshot',
+ 'data': { 'node': 'str', 'overlay': 'str' } }
+
+##
# @DriveBackup
#
# @device: the name of the device which should be copied.
@@ -800,6 +815,19 @@
{ 'command': 'blockdev-snapshot-sync',
'data': 'BlockdevSnapshotSync' }
+
+##
+# @blockdev-snapshot
+#
+# Generates a snapshot of a block device.
+#
+# For the arguments, see the documentation of BlockdevSnapshot.
+#
+# Since 2.5
+##
+{ 'command': 'blockdev-snapshot',
+ 'data': 'BlockdevSnapshot' }
+
##
# @change-backing-file
#
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 495670b..e5bd0e0 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -1454,6 +1454,44 @@ Example:
EQMP
{
+ .name = "blockdev-snapshot",
+ .args_type = "node:s,overlay:s",
+ .mhandler.cmd_new = qmp_marshal_input_blockdev_snapshot,
+ },
+
+SQMP
+blockdev-snapshot
+-----------------
+Since 2.5
+
+Create a snapshot, by installing 'node' as the backing image of
+'overlay'. Additionally, if 'node' is associated with a block
+device, the block device changes to using 'overlay' as its new active
+image.
+
+Arguments:
+
+- "node": device that will have a snapshot created (json-string)
+- "overlay": device that will have 'node' as its backing image (json-string)
+
+Example:
+
+-> { "execute": "blockdev-add",
+ "arguments": { "options": { "driver": "qcow2",
+ "node-name": "node1534",
+ "file": { "driver": "file",
+ "filename": "hd1.qcow2" },
+ "backing": "" } } }
+
+<- { "return": {} }
+
+-> { "execute": "blockdev-snapshot", "arguments": { "node": "ide-hd0",
+ "overlay": "node1534" } }
+<- { "return": {} }
+
+EQMP
+
+ {
.name = "blockdev-snapshot-internal-sync",
.args_type = "device:B,name:s",
.mhandler.cmd_new = qmp_marshal_input_blockdev_snapshot_internal_sync,
--
2.5.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v6 3/4] block: add a 'blockdev-snapshot' QMP command
2015-09-22 13:28 ` [Qemu-devel] [PATCH v6 3/4] block: add a 'blockdev-snapshot' QMP command Alberto Garcia
@ 2015-09-22 16:38 ` Max Reitz
2015-09-23 8:59 ` Alberto Garcia
2015-10-06 15:30 ` Kevin Wolf
1 sibling, 1 reply; 13+ messages in thread
From: Max Reitz @ 2015-09-22 16:38 UTC (permalink / raw)
To: Alberto Garcia, qemu-devel; +Cc: Kevin Wolf, Stefan Hajnoczi, qemu-block
[-- Attachment #1: Type: text/plain, Size: 3191 bytes --]
On 22.09.2015 15:28, Alberto Garcia wrote:
> One of the limitations of the 'blockdev-snapshot-sync' command is that
> it does not allow passing BlockdevOptions to the newly created
> snapshots, so they are always opened using the default values.
>
> Extending the command to allow passing options is not a practical
> solution because there is overlap between those options and some of
> the existing parameters of the command.
>
> This patch introduces a new 'blockdev-snapshot' command with a simpler
> interface: it just takes two references to existing block devices that
> will be used as the source and target for the snapshot.
>
> Since the main difference between the two commands is that one of them
> creates and opens the target image, while the other uses an already
> opened one, the bulk of the implementation is shared.
>
> Signed-off-by: Alberto Garcia <berto@igalia.com>
> Cc: Eric Blake <eblake@redhat.com>
> Cc: Max Reitz <mreitz@redhat.com>
> ---
> blockdev.c | 163 ++++++++++++++++++++++++++++++++-------------------
> qapi-schema.json | 2 +
> qapi/block-core.json | 28 +++++++++
> qmp-commands.hx | 38 ++++++++++++
> 4 files changed, 171 insertions(+), 60 deletions(-)
>
[snip]
> diff --git a/qmp-commands.hx b/qmp-commands.hx
> index 495670b..e5bd0e0 100644
> --- a/qmp-commands.hx
> +++ b/qmp-commands.hx
> @@ -1454,6 +1454,44 @@ Example:
> EQMP
>
> {
> + .name = "blockdev-snapshot",
> + .args_type = "node:s,overlay:s",
> + .mhandler.cmd_new = qmp_marshal_input_blockdev_snapshot,
As of 7fad30f06eb6aa57aaa8f3d264288f24ae7646f0, this needs to be
qmp_marshal_blockdev_snapshot.
> + },
> +
> +SQMP
> +blockdev-snapshot
> +-----------------
> +Since 2.5
> +
> +Create a snapshot, by installing 'node' as the backing image of
> +'overlay'. Additionally, if 'node' is associated with a block
> +device, the block device changes to using 'overlay' as its new active
> +image.
> +
> +Arguments:
> +
> +- "node": device that will have a snapshot created (json-string)
> +- "overlay": device that will have 'node' as its backing image (json-string)
> +
> +Example:
> +
> +-> { "execute": "blockdev-add",
> + "arguments": { "options": { "driver": "qcow2",
> + "node-name": "node1534",
> + "file": { "driver": "file",
> + "filename": "hd1.qcow2" },
> + "backing": "" } } }
> +
> +<- { "return": {} }
> +
> +-> { "execute": "blockdev-snapshot", "arguments": { "node": "ide-hd0",
> + "overlay": "node1534" } }
> +<- { "return": {} }
> +
> +EQMP
> +
> + {
> .name = "blockdev-snapshot-internal-sync",
> .args_type = "device:B,name:s",
> .mhandler.cmd_new = qmp_marshal_input_blockdev_snapshot_internal_sync,
Consequently, this context needs to be fixed up, too.
With that changed:
Reviewed-by: Max Reitz <mreitz@redhat.com>
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v6 3/4] block: add a 'blockdev-snapshot' QMP command
2015-09-22 16:38 ` Max Reitz
@ 2015-09-23 8:59 ` Alberto Garcia
0 siblings, 0 replies; 13+ messages in thread
From: Alberto Garcia @ 2015-09-23 8:59 UTC (permalink / raw)
To: Max Reitz, qemu-devel; +Cc: Kevin Wolf, Stefan Hajnoczi, qemu-block
On Tue 22 Sep 2015 06:38:27 PM CEST, Max Reitz wrote:
>> + .name = "blockdev-snapshot",
>> + .args_type = "node:s,overlay:s",
>> + .mhandler.cmd_new = qmp_marshal_input_blockdev_snapshot,
>
> As of 7fad30f06eb6aa57aaa8f3d264288f24ae7646f0, this needs to be
> qmp_marshal_blockdev_snapshot.
Sure, that needs to be part of the next rebase, otherwise it won't
build.
Berto
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v6 3/4] block: add a 'blockdev-snapshot' QMP command
2015-09-22 13:28 ` [Qemu-devel] [PATCH v6 3/4] block: add a 'blockdev-snapshot' QMP command Alberto Garcia
2015-09-22 16:38 ` Max Reitz
@ 2015-10-06 15:30 ` Kevin Wolf
2015-10-06 15:49 ` Alberto Garcia
1 sibling, 1 reply; 13+ messages in thread
From: Kevin Wolf @ 2015-10-06 15:30 UTC (permalink / raw)
To: Alberto Garcia; +Cc: Stefan Hajnoczi, qemu-devel, qemu-block, Max Reitz
Am 22.09.2015 um 15:28 hat Alberto Garcia geschrieben:
> One of the limitations of the 'blockdev-snapshot-sync' command is that
> it does not allow passing BlockdevOptions to the newly created
> snapshots, so they are always opened using the default values.
>
> Extending the command to allow passing options is not a practical
> solution because there is overlap between those options and some of
> the existing parameters of the command.
>
> This patch introduces a new 'blockdev-snapshot' command with a simpler
> interface: it just takes two references to existing block devices that
> will be used as the source and target for the snapshot.
>
> Since the main difference between the two commands is that one of them
> creates and opens the target image, while the other uses an already
> opened one, the bulk of the implementation is shared.
>
> Signed-off-by: Alberto Garcia <berto@igalia.com>
> Cc: Eric Blake <eblake@redhat.com>
> Cc: Max Reitz <mreitz@redhat.com>
> ---
> blockdev.c | 163 ++++++++++++++++++++++++++++++++-------------------
> qapi-schema.json | 2 +
> qapi/block-core.json | 28 +++++++++
> qmp-commands.hx | 38 ++++++++++++
> 4 files changed, 171 insertions(+), 60 deletions(-)
>
> diff --git a/blockdev.c b/blockdev.c
> index 1a5b889..daf72f3 100644
> --- a/blockdev.c
> +++ b/blockdev.c
> @@ -1183,6 +1183,18 @@ void qmp_blockdev_snapshot_sync(bool has_device, const char *device,
> &snapshot, errp);
> }
>
> +void qmp_blockdev_snapshot(const char *node, const char *overlay,
> + Error **errp)
> +{
> + BlockdevSnapshot snapshot_data = {
> + .node = (char *) node,
> + .overlay = (char *) overlay
> + };
> +
> + blockdev_do_action(TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT,
> + &snapshot_data, errp);
> +}
> +
> void qmp_blockdev_snapshot_internal_sync(const char *device,
> const char *name,
> Error **errp)
> @@ -1521,57 +1533,48 @@ typedef struct ExternalSnapshotState {
> static void external_snapshot_prepare(BlkTransactionState *common,
> Error **errp)
> {
> - int flags, ret;
> - QDict *options;
> + int flags = 0, ret;
> + QDict *options = NULL;
> Error *local_err = NULL;
> - bool has_device = false;
> + /* Device and node name of the image to generate the snapshot from */
> const char *device;
> - bool has_node_name = false;
> const char *node_name;
> - bool has_snapshot_node_name = false;
> - const char *snapshot_node_name;
> + /* Reference to the new image (for 'blockdev-snapshot') */
> + const char *snapshot_ref;
> + /* File name of the new image (for 'blockdev-snapshot-sync') */
> const char *new_image_file;
> - const char *format = "qcow2";
> - enum NewImageMode mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
> ExternalSnapshotState *state =
> DO_UPCAST(ExternalSnapshotState, common, common);
> TransactionAction *action = common->action;
>
> - /* get parameters */
> - g_assert(action->kind == TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC);
> -
> - has_device = action->blockdev_snapshot_sync->has_device;
> - device = action->blockdev_snapshot_sync->device;
> - has_node_name = action->blockdev_snapshot_sync->has_node_name;
> - node_name = action->blockdev_snapshot_sync->node_name;
> - has_snapshot_node_name =
> - action->blockdev_snapshot_sync->has_snapshot_node_name;
> - snapshot_node_name = action->blockdev_snapshot_sync->snapshot_node_name;
> -
> - new_image_file = action->blockdev_snapshot_sync->snapshot_file;
> - if (action->blockdev_snapshot_sync->has_format) {
> - format = action->blockdev_snapshot_sync->format;
> - }
> - if (action->blockdev_snapshot_sync->has_mode) {
> - mode = action->blockdev_snapshot_sync->mode;
> + /* 'blockdev-snapshot' and 'blockdev-snapshot-sync' have similar
> + * purpose but a different set of parameters */
> + switch (action->kind) {
> + case TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT:
> + {
> + BlockdevSnapshot *s = action->blockdev_snapshot;
> + device = s->node;
> + node_name = s->node;
> + new_image_file = NULL;
> + snapshot_ref = s->overlay;
> + }
> + break;
> + case TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC:
> + {
> + BlockdevSnapshotSync *s = action->blockdev_snapshot_sync;
> + device = s->has_device ? s->device : NULL;
> + node_name = s->has_node_name ? s->node_name : NULL;
> + new_image_file = s->snapshot_file;
> + snapshot_ref = NULL;
> + }
> + break;
> + default:
> + g_assert_not_reached();
> }
>
> /* start processing */
> - state->old_bs = bdrv_lookup_bs(has_device ? device : NULL,
> - has_node_name ? node_name : NULL,
> - &local_err);
> - if (local_err) {
> - error_propagate(errp, local_err);
> - return;
> - }
> -
> - if (has_node_name && !has_snapshot_node_name) {
> - error_setg(errp, "New snapshot node name missing");
> - return;
> - }
> -
> - if (has_snapshot_node_name && bdrv_find_node(snapshot_node_name)) {
> - error_setg(errp, "New snapshot node name already existing");
> + state->old_bs = bdrv_lookup_bs(device, node_name, errp);
> + if (!state->old_bs) {
> return;
> }
>
> @@ -1601,35 +1604,69 @@ static void external_snapshot_prepare(BlkTransactionState *common,
> return;
> }
>
> - flags = state->old_bs->open_flags;
> + if (action->kind == TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC) {
> + BlockdevSnapshotSync *s = action->blockdev_snapshot_sync;
> + const char *format = s->has_format ? s->format : "qcow2";
> + enum NewImageMode mode;
> + const char *snapshot_node_name =
> + s->has_snapshot_node_name ? s->snapshot_node_name : NULL;
>
> - /* create new image w/backing file */
> - if (mode != NEW_IMAGE_MODE_EXISTING) {
> - bdrv_img_create(new_image_file, format,
> - state->old_bs->filename,
> - state->old_bs->drv->format_name,
> - NULL, -1, flags, &local_err, false);
> - if (local_err) {
> - error_propagate(errp, local_err);
> + if (node_name && !snapshot_node_name) {
> + error_setg(errp, "New snapshot node name missing");
> return;
> }
> - }
>
> - options = qdict_new();
> - if (has_snapshot_node_name) {
> - qdict_put(options, "node-name",
> - qstring_from_str(snapshot_node_name));
> + if (snapshot_node_name && bdrv_find_node(snapshot_node_name)) {
> + error_setg(errp, "New snapshot node name already exists");
> + return;
> + }
Preexisting, but shouldn't we use bdrv_lookup_bs() here (because devices
and node names share a namespace)?
Otherwise, we could decide to drop the check altogether (because
bdrv_open() already checks this), but then we would already have created
the new image.
> +
> + flags = state->old_bs->open_flags;
> +
> + /* create new image w/backing file */
> + mode = s->has_mode ? s->mode : NEW_IMAGE_MODE_ABSOLUTE_PATHS;
> + if (mode != NEW_IMAGE_MODE_EXISTING) {
> + bdrv_img_create(new_image_file, format,
> + state->old_bs->filename,
> + state->old_bs->drv->format_name,
> + NULL, -1, flags, &local_err, false);
> + if (local_err) {
> + error_propagate(errp, local_err);
> + return;
> + }
> + }
> +
> + options = qdict_new();
> + if (s->has_snapshot_node_name) {
> + qdict_put(options, "node-name",
> + qstring_from_str(snapshot_node_name));
> + }
> + qdict_put(options, "driver", qstring_from_str(format));
> +
> + flags |= BDRV_O_NO_BACKING;
> }
> - qdict_put(options, "driver", qstring_from_str(format));
>
> - /* TODO Inherit bs->options or only take explicit options with an
> - * extended QMP command? */
> assert(state->new_bs == NULL);
> - ret = bdrv_open(&state->new_bs, new_image_file, NULL, options,
> - flags | BDRV_O_NO_BACKING, &local_err);
> + ret = bdrv_open(&state->new_bs, new_image_file, snapshot_ref, options,
> + flags, errp);
> /* We will manually add the backing_hd field to the bs later */
> if (ret != 0) {
> - error_propagate(errp, local_err);
> + return;
> + }
> +
> + if (state->new_bs->blk != NULL) {
> + error_setg(errp, "The snapshot is already in use by %s",
> + blk_name(state->new_bs->blk));
> + return;
> + }
Is it even possible yet to create a root BDS without a BB?
> + if (bdrv_op_is_blocked(state->new_bs, BLOCK_OP_TYPE_EXTERNAL_SNAPSHOT,
> + errp)) {
> + return;
> + }
> +
> + if (state->new_bs->backing_hd != NULL) {
> + error_setg(errp, "The snapshot already has a backing image");
> }
The error cases after bdrv_open() should probably bdrv_unref() the node.
Kevin
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v6 3/4] block: add a 'blockdev-snapshot' QMP command
2015-10-06 15:30 ` Kevin Wolf
@ 2015-10-06 15:49 ` Alberto Garcia
2015-10-07 7:34 ` Kevin Wolf
0 siblings, 1 reply; 13+ messages in thread
From: Alberto Garcia @ 2015-10-06 15:49 UTC (permalink / raw)
To: Kevin Wolf; +Cc: Stefan Hajnoczi, qemu-devel, qemu-block, Max Reitz
On Tue 06 Oct 2015 05:30:07 PM CEST, Kevin Wolf wrote:
>> - options = qdict_new();
>> - if (has_snapshot_node_name) {
>> - qdict_put(options, "node-name",
>> - qstring_from_str(snapshot_node_name));
>> + if (snapshot_node_name && bdrv_find_node(snapshot_node_name)) {
>> + error_setg(errp, "New snapshot node name already exists");
>> + return;
>> + }
>
> Preexisting, but shouldn't we use bdrv_lookup_bs() here (because devices
> and node names share a namespace)?
I think you're right, good catch!
>> + if (state->new_bs->blk != NULL) {
>> + error_setg(errp, "The snapshot is already in use by %s",
>> + blk_name(state->new_bs->blk));
>> + return;
>> + }
>
> Is it even possible yet to create a root BDS without a BB?
It is possible with Max's series, on which mine depends.
http://patchwork.ozlabs.org/patch/519375/
>> + if (bdrv_op_is_blocked(state->new_bs, BLOCK_OP_TYPE_EXTERNAL_SNAPSHOT,
>> + errp)) {
>> + return;
>> + }
>> +
>> + if (state->new_bs->backing_hd != NULL) {
>> + error_setg(errp, "The snapshot already has a backing image");
>> }
>
> The error cases after bdrv_open() should probably bdrv_unref() the
> node.
I don't think it's necessary, external_snapshot_abort() already takes
care of that.
Thanks for reviewing!
Berto
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v6 3/4] block: add a 'blockdev-snapshot' QMP command
2015-10-06 15:49 ` Alberto Garcia
@ 2015-10-07 7:34 ` Kevin Wolf
0 siblings, 0 replies; 13+ messages in thread
From: Kevin Wolf @ 2015-10-07 7:34 UTC (permalink / raw)
To: Alberto Garcia; +Cc: Stefan Hajnoczi, qemu-devel, qemu-block, Max Reitz
Am 06.10.2015 um 17:49 hat Alberto Garcia geschrieben:
> On Tue 06 Oct 2015 05:30:07 PM CEST, Kevin Wolf wrote:
> >> - options = qdict_new();
> >> - if (has_snapshot_node_name) {
> >> - qdict_put(options, "node-name",
> >> - qstring_from_str(snapshot_node_name));
> >> + if (snapshot_node_name && bdrv_find_node(snapshot_node_name)) {
> >> + error_setg(errp, "New snapshot node name already exists");
> >> + return;
> >> + }
> >
> > Preexisting, but shouldn't we use bdrv_lookup_bs() here (because devices
> > and node names share a namespace)?
>
> I think you're right, good catch!
>
> >> + if (state->new_bs->blk != NULL) {
> >> + error_setg(errp, "The snapshot is already in use by %s",
> >> + blk_name(state->new_bs->blk));
> >> + return;
> >> + }
> >
> > Is it even possible yet to create a root BDS without a BB?
>
> It is possible with Max's series, on which mine depends.
>
> http://patchwork.ozlabs.org/patch/519375/
Okay. I missed this dependency, it doesn't seem to be very explicit in
the cover letter.
> >> + if (bdrv_op_is_blocked(state->new_bs, BLOCK_OP_TYPE_EXTERNAL_SNAPSHOT,
> >> + errp)) {
> >> + return;
> >> + }
> >> +
> >> + if (state->new_bs->backing_hd != NULL) {
> >> + error_setg(errp, "The snapshot already has a backing image");
> >> }
> >
> > The error cases after bdrv_open() should probably bdrv_unref() the
> > node.
>
> I don't think it's necessary, external_snapshot_abort() already takes
> care of that.
Sorry for the noise, you're right. I was confused by bdrv_reopen()
transactions working differently: There, abort isn't called for the
queue entry that has failed prepare, but here it is.
Kevin
^ permalink raw reply [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v6 4/4] block: add tests for the 'blockdev-snapshot' command
2015-09-22 13:28 [Qemu-devel] [PATCH v6 0/4] Add 'blockdev-snapshot' command Alberto Garcia
` (2 preceding siblings ...)
2015-09-22 13:28 ` [Qemu-devel] [PATCH v6 3/4] block: add a 'blockdev-snapshot' QMP command Alberto Garcia
@ 2015-09-22 13:28 ` Alberto Garcia
2015-09-22 16:54 ` Max Reitz
3 siblings, 1 reply; 13+ messages in thread
From: Alberto Garcia @ 2015-09-22 13:28 UTC (permalink / raw)
To: qemu-devel
Cc: Kevin Wolf, Alberto Garcia, qemu-block, Max Reitz,
Stefan Hajnoczi
Signed-off-by: Alberto Garcia <berto@igalia.com>
Cc: Max Reitz <mreitz@redhat.com>
---
tests/qemu-iotests/085 | 102 ++++++++++++++++++++++++++++++++++++++++++---
tests/qemu-iotests/085.out | 34 ++++++++++++++-
2 files changed, 128 insertions(+), 8 deletions(-)
diff --git a/tests/qemu-iotests/085 b/tests/qemu-iotests/085
index 56cd6f8..9484117 100755
--- a/tests/qemu-iotests/085
+++ b/tests/qemu-iotests/085
@@ -7,6 +7,7 @@
# snapshots are performed.
#
# Copyright (C) 2014 Red Hat, Inc.
+# Copyright (C) 2015 Igalia, S.L.
#
# 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
@@ -34,17 +35,17 @@ status=1 # failure is the default!
snapshot_virt0="snapshot-v0.qcow2"
snapshot_virt1="snapshot-v1.qcow2"
-MAX_SNAPSHOTS=10
+SNAPSHOTS=10
_cleanup()
{
_cleanup_qemu
- for i in $(seq 1 ${MAX_SNAPSHOTS})
+ for i in $(seq 1 ${SNAPSHOTS})
do
rm -f "${TEST_DIR}/${i}-${snapshot_virt0}"
rm -f "${TEST_DIR}/${i}-${snapshot_virt1}"
done
- _cleanup_test_img
+ rm -f "${TEST_IMG}.1" "${TEST_IMG}.2"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -85,18 +86,50 @@ function create_group_snapshot()
_send_qemu_cmd $h "${cmd}" "return"
}
+# ${1}: unique identifier for the snapshot filename
+# ${2}: true: open backing images; false: don't open them (default)
+function add_snapshot_image()
+{
+ if [ "${2}" = "true" ]; then
+ extra_params=""
+ else
+ extra_params="'backing': '', "
+ fi
+ base_image="${TEST_DIR}/$((${1}-1))-${snapshot_virt0}"
+ snapshot_file="${TEST_DIR}/${1}-${snapshot_virt0}"
+ _make_test_img -b "${base_image}" "$size"
+ mv "${TEST_IMG}" "${snapshot_file}"
+ cmd="{ 'execute': 'blockdev-add', 'arguments':
+ { 'options':
+ { 'driver': 'qcow2', 'node-name': 'snap_"${1}"', "${extra_params}"
+ 'file':
+ { 'driver': 'file', 'filename': '"${snapshot_file}"' } } } }"
+ _send_qemu_cmd $h "${cmd}" "return"
+}
+
+# ${1}: unique identifier for the snapshot filename
+# ${2}: expected response, defaults to 'return'
+function blockdev_snapshot()
+{
+ cmd="{ 'execute': 'blockdev-snapshot',
+ 'arguments': { 'node': 'virtio0',
+ 'overlay':'snap_"${1}"' } }"
+ _send_qemu_cmd $h "${cmd}" "${2:-return}"
+}
+
size=128M
_make_test_img $size
-mv "${TEST_IMG}" "${TEST_IMG}.orig"
+mv "${TEST_IMG}" "${TEST_IMG}.1"
_make_test_img $size
+mv "${TEST_IMG}" "${TEST_IMG}.2"
echo
echo === Running QEMU ===
echo
qemu_comm_method="qmp"
-_launch_qemu -drive file="${TEST_IMG}.orig",if=virtio -drive file="${TEST_IMG}",if=virtio
+_launch_qemu -drive file="${TEST_IMG}.1",if=virtio -drive file="${TEST_IMG}.2",if=virtio
h=$QEMU_HANDLE
echo
@@ -105,6 +138,8 @@ echo
_send_qemu_cmd $h "{ 'execute': 'qmp_capabilities' }" "return"
+# Tests for the blockdev-snapshot-sync command
+
echo
echo === Create a single snapshot on virtio0 ===
echo
@@ -132,11 +167,66 @@ echo
echo === Create several transactional group snapshots ===
echo
-for i in $(seq 2 ${MAX_SNAPSHOTS})
+for i in $(seq 2 ${SNAPSHOTS})
do
create_group_snapshot ${i}
done
+# Tests for the blockdev-snapshot command
+
+echo
+echo === Create a couple of snapshots using blockdev-snapshot ===
+echo
+
+SNAPSHOTS=$((${SNAPSHOTS}+1))
+add_snapshot_image ${SNAPSHOTS}
+blockdev_snapshot ${SNAPSHOTS}
+
+SNAPSHOTS=$((${SNAPSHOTS}+1))
+add_snapshot_image ${SNAPSHOTS}
+blockdev_snapshot ${SNAPSHOTS}
+
+echo
+echo === Invalid command - snapshot node used as active layer ===
+echo
+
+blockdev_snapshot ${SNAPSHOTS} error
+
+_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot',
+ 'arguments': { 'node':'virtio0',
+ 'overlay':'virtio0' }
+ }" "error"
+
+_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot',
+ 'arguments': { 'node':'virtio0',
+ 'overlay':'virtio1' }
+ }" "error"
+
+echo
+echo === Invalid command - snapshot node used as backing hd ===
+echo
+
+blockdev_snapshot $((${SNAPSHOTS}-1)) error
+
+echo
+echo === Invalid command - snapshot node has a backing image ===
+echo
+
+SNAPSHOTS=$((${SNAPSHOTS}+1))
+add_snapshot_image ${SNAPSHOTS} true
+blockdev_snapshot ${SNAPSHOTS} error
+
+echo
+echo === Invalid command - The node does not exist ===
+echo
+
+blockdev_snapshot $((${SNAPSHOTS}+1)) error
+
+_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot',
+ 'arguments': { 'node':'nodevice',
+ 'overlay':'snap_"${SNAPSHOTS}"' }
+ }" "error"
+
# success, all done
echo "*** done"
rm -f $seq.full
diff --git a/tests/qemu-iotests/085.out b/tests/qemu-iotests/085.out
index a6cf19e..52292ea 100644
--- a/tests/qemu-iotests/085.out
+++ b/tests/qemu-iotests/085.out
@@ -11,7 +11,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
=== Create a single snapshot on virtio0 ===
-Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2.orig backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2.1 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
{"return": {}}
=== Invalid command - missing device and nodename ===
@@ -26,7 +26,7 @@ Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file
=== Create several transactional group snapshots ===
Formatting 'TEST_DIR/2-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/1-snapshot-v0.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
-Formatting 'TEST_DIR/2-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/2-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2.2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
{"return": {}}
Formatting 'TEST_DIR/3-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/2-snapshot-v0.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/3-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/2-snapshot-v1.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
@@ -52,4 +52,34 @@ Formatting 'TEST_DIR/9-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file
Formatting 'TEST_DIR/10-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/9-snapshot-v0.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
Formatting 'TEST_DIR/10-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/9-snapshot-v1.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
{"return": {}}
+
+=== Create a couple of snapshots using blockdev-snapshot ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/10-snapshot-v0.IMGFMT
+{"return": {}}
+{"return": {}}
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/11-snapshot-v0.IMGFMT
+{"return": {}}
+{"return": {}}
+
+=== Invalid command - snapshot node used as active layer ===
+
+{"error": {"class": "GenericError", "desc": "The snapshot is already in use by virtio0"}}
+{"error": {"class": "GenericError", "desc": "The snapshot is already in use by virtio0"}}
+{"error": {"class": "GenericError", "desc": "The snapshot is already in use by virtio1"}}
+
+=== Invalid command - snapshot node used as backing hd ===
+
+{"error": {"class": "GenericError", "desc": "Node 'snap_11' is busy: node is used as backing hd of 'virtio0'"}}
+
+=== Invalid command - snapshot node has a backing image ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/12-snapshot-v0.IMGFMT
+{"return": {}}
+{"error": {"class": "GenericError", "desc": "The snapshot already has a backing image"}}
+
+=== Invalid command - The node does not exist ===
+
+{"error": {"class": "GenericError", "desc": "Cannot find device=snap_14 nor node_name=snap_14"}}
+{"error": {"class": "GenericError", "desc": "Cannot find device=nodevice nor node_name=nodevice"}}
*** done
--
2.5.1
^ permalink raw reply related [flat|nested] 13+ messages in thread