From: Eric Blake <eblake@redhat.com>
To: Alberto Garcia <berto@igalia.com>, qemu-devel@nongnu.org
Cc: Kevin Wolf <kwolf@redhat.com>,
Stefan Hajnoczi <stefanha@redhat.com>,
qemu-block@nongnu.org, Max Reitz <mreitz@redhat.com>
Subject: Re: [Qemu-devel] [PATCH v2 2/2] block: add a 'blockdev-snapshot' QMP command
Date: Fri, 4 Sep 2015 08:42:17 -0600 [thread overview]
Message-ID: <55E9ADC9.3000404@redhat.com> (raw)
In-Reply-To: <afc097ee73b5d9e844af1884e855694240024654.1441369227.git.berto@igalia.com>
[-- Attachment #1: Type: text/plain, Size: 7645 bytes --]
On 09/04/2015 06:37 AM, 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.
I like it. Obviously, we have to get the pre-requisites in first, to
allow opening a BDS without a BB, but it is nicer overall.
>
> Signed-off-by: Alberto Garcia <berto@igalia.com>
> ---
> blockdev.c | 154 ++++++++++++++++++++++++++++++++-------------------
> qapi-schema.json | 1 +
> qapi/block-core.json | 26 +++++++++
> qmp-commands.hx | 28 ++++++++++
> 4 files changed, 153 insertions(+), 56 deletions(-)
>
> diff --git a/blockdev.c b/blockdev.c
> index 6b787c1..db6e3bf 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 *device, const char *snapshot,
Is 'node' a better name than 'device' here?
> Error **errp)
> @@ -1521,60 +1533,52 @@ typedef struct ExternalSnapshotState {
> static void external_snapshot_prepare(BlkTransactionState *common,
> Error **errp)
> {
> + /* '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->device;
> + node_name = s->device;
Again, I think this should be setting s->node_name, not s->device.
> + new_image_file = NULL;
> + snapshot_ref = s->snapshot;
> + }
> + 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);
> + state->old_bs = bdrv_lookup_bs(device, node_name, &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");
> - return;
> - }
> -
> /* Acquire AioContext now so any threads operating on old_bs stop */
> state->aio_context = bdrv_get_aio_context(state->old_bs);
> aio_context_acquire(state->aio_context);
> @@ -1601,35 +1605,67 @@ static void external_snapshot_prepare(BlkTransactionState *common,
> return;
> }
>
> - flags = state->old_bs->open_flags;
> -
> - /* 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) {
> + if (snapshot_ref) {
> + if (!bdrv_lookup_bs(snapshot_ref, snapshot_ref, &local_err)) {
> error_propagate(errp, local_err);
> return;
> }
> }
Shouldn't you also check that snapshot_ref does not currently have a
backing BDS (as it is the act of creating the snapshot that sets the
current device as the backing of the snapshot_ref BDS before altering
the BB to point to snapshot_ref as its new BDS)?
> +++ b/qapi-schema.json
> @@ -1496,6 +1496,7 @@
> ##
> { 'union': 'TransactionAction',
> 'data': {
> + 'blockdev-snapshot': 'BlockdevSnapshot',
Missing 'since 2.5' documentation.
> 'blockdev-snapshot-sync': 'BlockdevSnapshotSync',
> 'drive-backup': 'DriveBackup',
> 'blockdev-backup': 'BlockdevBackup',
> diff --git a/qapi/block-core.json b/qapi/block-core.json
> index ec50f06..adfae23 100644
> --- a/qapi/block-core.json
> +++ b/qapi/block-core.json
> @@ -705,6 +705,19 @@
> '*format': 'str', '*mode': 'NewImageMode' } }
>
> ##
> +# @BlockdevSnapshot
> +#
> +# @device: device or node name to generate the snapshot from.
Would naming this 'node' make more sense?
> +#
> +# @snapshot: reference to the existing block device that will be used
> +# for the snapshot.
> +#
> +# Since 2.5
> +##
> +{ 'struct': 'BlockdevSnapshot',
> + 'data': { 'device': 'str', 'snapshot': 'str' } }
> +
> +##
> # @DriveBackup
> #
> # @device: the name of the device which should be copied.
> @@ -800,6 +813,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' }
> +
Overall, I like the syntax.
> +SQMP
> +blockdev-snapshot
> +-----------------
> +Since 2.5
> +
> +Create a snapshot of a block device. 'device' and 'snapshot' both
> +refer to existing block devices. The former is the one to generate the
> +snapshot from, and the latter is the target of the snapshot.
Is there any better terminology? Maybe:
The act of creating a snapshot installs 'device' as the backing image of
'snapshot'; additionally, if 'device' is associated with a block device,
the block device changes to using 'snapshot' as its new active image.
Hmm - I wonder if that means we should have an optional boolean
parameter that allows us to avoid the automatic pivot. After all, with
'blockdev-snapshot-sync', you can specify 'device' and omit 'node-name'
to update the device's active layer, or you can omit 'device' and
specify 'node-name' to create another qcow2 file but NOT install it as
the active layer, regardless of which 'node-name' that serves as the
starting point. So when 'node-name' is the BDS node that 'device' is
currently visiting, you have control over whether 'device' auto-updates
to the new BDS.
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]
next prev parent reply other threads:[~2015-09-04 14:42 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-09-04 12:37 [Qemu-devel] [PATCH v2 0/2] Add 'blockdev-snapshot' command Alberto Garcia
2015-09-04 12:37 ` [Qemu-devel] [PATCH v2 1/2] block: rename BlockdevSnapshot to BlockdevSnapshotSync Alberto Garcia
2015-09-04 14:25 ` Eric Blake
2015-09-04 12:37 ` [Qemu-devel] [PATCH v2 2/2] block: add a 'blockdev-snapshot' QMP command Alberto Garcia
2015-09-04 14:42 ` Eric Blake [this message]
2015-09-07 7:59 ` Alberto Garcia
2015-09-07 11:31 ` Alberto Garcia
2015-09-07 14:55 ` Kevin Wolf
2015-09-07 15:06 ` Alberto Garcia
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=55E9ADC9.3000404@redhat.com \
--to=eblake@redhat.com \
--cc=berto@igalia.com \
--cc=kwolf@redhat.com \
--cc=mreitz@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.