[libvirt] [PATCH] blockcommit: document semantics of committing active layer
Peter Krempa
pkrempa at redhat.com
Mon May 19 07:58:18 UTC 2014
On 05/16/14 22:17, Eric Blake wrote:
> Now that qemu 2.0 allows commit of the active layer, people are
> attempting to use virsh blockcommit and getting into a stuck
> state, because libvirt is unprepared to handle the two-phase
> commit required by qemu.
>
> Stepping back a bit, there are two valid semantics for a
> commit operation:
>
> 1. Maintain a 'golden' base, and a transient overlay. Make
> changes in the overlay, and if everything appears to work,
> commit those changes into the base, but still keep the overlay
> for the next round of changes; repeat the cycle as desired.
>
> 2. Create an external snapshot, then back up the stable state
> in the backing file. Once the backup is complete, commit the
> overlay back into the base, and delete the temporary snapshot.
>
> Since qemu doesn't know up front which of the two styles is
> preferred, a block commit of the active layer merely gets
> the job into a synchronized state, and sends an event; then
> the user must either cancel (case 1) or complete (case 2),
> where qemu then sends a second event that actually ends the
> job. However, libvirt was blindly assuming the semantics that
> apply to a commit of an intermediate image, where there is
> only one sane conclusion (the job automatically ends with
> fewer elements in the chain); and getting stuck because it
> wasn't prepared for qemu to enter a second phase of the job.
>
> This patch adds a flag to the libvirt API that a user MUST
> supply in order to acknowledge that they will be using two-phase
> semantics. It might be possible to have a mode where if the
> flag is omitted, we automatically do the case 2 semantics on
> the user's behalf; but before that happens, I must do additional
> patches to track the fact that we are doing an active commit
> in the domain XML. So the safest thing for now is to reject the
> new flag in qemu, as well as prevent commits of the active layer
> without the flag. Later patches will add support of the flag,
> and once 2-phase semantics are working, we can then decide
> whether to relax things to allow an omitted flag to cause an
> automatic pivot.
>
> * include/libvirt/libvirt.h.in (VIR_DOMAIN_BLOCK_COMMIT_ACTIVE)
> (VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT): New enums.
> * src/libvirt.c (virDomainBlockCommit): Document two-phase job
> when committing active layer, through new flag.
> (virDomainBlockJobAbort): Document that pivot also occurs after
> active commit.
> * src/qemu/qemu_driver.c (qemuDomainBlockCommit): Explicitly
> reject active copy; later patches will add it in.
>
> Signed-off-by: Eric Blake <eblake at redhat.com>
> ---
>
> This patch should probably be backported, even if later patches
> in the series are not, so that users avoid getting hung.
>
> include/libvirt/libvirt.h.in | 12 ++++++----
> src/libvirt.c | 55 +++++++++++++++++++++++++++++---------------
> src/qemu/qemu_driver.c | 9 ++++++++
> 3 files changed, 54 insertions(+), 22 deletions(-)
>
> diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
> index 260c971..127de11 100644
> --- a/include/libvirt/libvirt.h.in
> +++ b/include/libvirt/libvirt.h.in
> @@ -2513,6 +2513,7 @@ typedef enum {
> VIR_DOMAIN_BLOCK_JOB_TYPE_PULL = 1,
> VIR_DOMAIN_BLOCK_JOB_TYPE_COPY = 2,
> VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT = 3,
> + VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT = 4,
>
> #ifdef VIR_ENUM_SENTINELS
> VIR_DOMAIN_BLOCK_JOB_TYPE_LAST
> @@ -2523,7 +2524,8 @@ typedef enum {
> * virDomainBlockJobAbortFlags:
> *
> * VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC: Request only, do not wait for completion
> - * VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT: Pivot to mirror when ending a copy job
> + * VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT: Pivot to new file when ending a copy or
> + * active commit job
> */
> typedef enum {
> VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC = 1 << 0,
> @@ -2588,6 +2590,8 @@ typedef enum {
> VIR_DOMAIN_BLOCK_COMMIT_DELETE = 1 << 1, /* Delete any files that are now
> invalid after their contents
> have been committed */
> + VIR_DOMAIN_BLOCK_COMMIT_ACTIVE = 1 << 2, /* Allow a two-phase commit when
> + top is the active layer */
> } virDomainBlockCommitFlags;
>
> int virDomainBlockCommit(virDomainPtr dom, const char *disk, const char *base,
> @@ -4823,8 +4827,8 @@ typedef void (*virConnectDomainEventGraphicsCallback)(virConnectPtr conn,
> /**
> * virConnectDomainEventBlockJobStatus:
> *
> - * The final status of a virDomainBlockPull() or virDomainBlockRebase()
> - * operation
> + * Tracks status of a virDomainBlockPull(), virDomainBlockRebase(),
> + * or virDomainBlockCommit() operation
> */
> typedef enum {
> VIR_DOMAIN_BLOCK_JOB_COMPLETED = 0,
> @@ -4843,7 +4847,7 @@ typedef enum {
> * @dom: domain on which the event occurred
> * @disk: fully-qualified filename of the affected disk
> * @type: type of block job (virDomainBlockJobType)
> - * @status: final status of the operation (virConnectDomainEventBlockJobStatus)
> + * @status: status of the operation (virConnectDomainEventBlockJobStatus)
> * @opaque: application specified data
> *
> * The callback signature to use when registering for an event of type
> diff --git a/src/libvirt.c b/src/libvirt.c
> index 19fa18b..20abfce 100644
> --- a/src/libvirt.c
> +++ b/src/libvirt.c
> @@ -19467,13 +19467,16 @@ virDomainOpenChannel(virDomainPtr dom,
> *
> * If the current block job for @disk is VIR_DOMAIN_BLOCK_JOB_TYPE_COPY, then
> * the default is to abort the mirroring and revert to the source disk;
> - * adding @flags of VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT causes this call to
> - * fail with VIR_ERR_BLOCK_COPY_ACTIVE if the copy is not fully populated,
> - * otherwise it will swap the disk over to the copy to end the mirroring. An
> - * event will be issued when the job is ended, and it is possible to use
> - * VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC to control whether this command waits
> - * for the completion of the job. Restarting this job requires starting
> - * over from the beginning of the first phase.
> + * likewise, if the current job is VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT,
> + * the default is to abort without changing the active layer of @disk.
> + * Adding @flags of VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT causes this call to
> + * fail with VIR_ERR_BLOCK_COPY_ACTIVE if the copy or commit is not yet
> + * ready; otherwise it will swap the disk over to the new active image
> + * to end the mirroring or active commit. An event will be issued when the
> + * job is ended, and it is possible to use VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC
> + * to control whether this command waits for the completion of the job.
> + * Restarting a copy or active commit job requires starting over from the
> + * beginning of the first phase.
> *
> * Returns -1 in case of failure, 0 when successful.
> */
> @@ -19843,17 +19846,32 @@ virDomainBlockRebase(virDomainPtr dom, const char *disk,
> * the job is aborted, it is up to the hypervisor whether starting a new
> * job will resume from the same point, or start over.
> *
> + * As a special case, if @top is the active image (or NULL), and @flags
> + * includes VIR_DOMAIN_BLOCK_COMMIT_ACTIVE, the block job will have a type
> + * of VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT, and operates in two phases.
> + * In the first phase, the contents are being committed into @base, and the
> + * job can only be canceled. The job transitions to the second phase when
> + * the job info states cur == end, and remains alive to keep all further
> + * changes to @top synchronized into @base; an event with status
> + * VIR_DOMAIN_BLOCK_JOB_READY is also issued to mark the job transition.
> + * Once in the second phase, the user must choose whether to cancel the job
> + * (keeping @top as the active image, but now containing only the changes
> + * since the time the job ended) or to pivot the job (adjusting to @base as
> + * the active image, and invalidating @top).
> + *
> * Be aware that this command may invalidate files even if it is aborted;
> * the user is cautioned against relying on the contents of invalidated
> - * intermediate files such as @top without manually rebasing those files
> - * to use a backing file of a read-only copy of @base prior to the point
> - * where the commit operation was started (although such a rebase cannot
> - * be safely done until the commit has successfully completed). However,
> - * the domain itself will not have any issues; the active layer remains
> - * valid throughout the entire commit operation. As a convenience,
> - * if @flags contains VIR_DOMAIN_BLOCK_COMMIT_DELETE, this command will
> - * unlink all files that were invalidated, after the commit successfully
> - * completes.
> + * intermediate files such as @top (when @top is not the active image)
> + * without manually rebasing those files to use a backing file of a
> + * read-only copy of @base prior to the point where the commit operation
> + * was started (and such a rebase cannot be safely done until the commit
> + * has successfully completed). However, the domain itself will not have
> + * any issues; the active layer remains valid throughout the entire commit
> + * operation.
> + *
> + * Some hypervisors may support a shortcut where if @flags contains
> + * VIR_DOMAIN_BLOCK_COMMIT_DELETE, then this command will unlink all files
> + * that were invalidated, after the commit successfully completes.
> *
> * By default, if @base is NULL, the commit target will be the bottom of
> * the backing chain; if @flags contains VIR_DOMAIN_BLOCK_COMMIT_SHALLOW,
> @@ -19861,8 +19879,9 @@ virDomainBlockRebase(virDomainPtr dom, const char *disk,
> * is NULL, the active image at the top of the chain will be used. Some
> * hypervisors place restrictions on how much can be committed, and might
> * fail if @base is not the immediate backing file of @top, or if @top is
> - * the active layer in use by a running domain, or if @top is not the
> - * top-most file; restrictions may differ for online vs. offline domains.
> + * the active layer in use by a running domain but @flags did not include
> + * VIR_DOMAIN_BLOCK_COMMIT_ACTIVE, or if @top is not the top-most file;
> + * restrictions may differ for online vs. offline domains.
> *
> * The @disk parameter is either an unambiguous source name of the
> * block device (the <source file='...'/> sub-element, such as
Doc changes seem okay to me.
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index 55b4755..75c59e0 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -15377,6 +15377,7 @@ qemuDomainBlockCommit(virDomainPtr dom,
> const char *top_parent = NULL;
> bool clean_access = false;
>
> + /* XXX Add support for COMMIT_ACTIVE, COMMIT_DELETE */
> virCheckFlags(VIR_DOMAIN_BLOCK_COMMIT_SHALLOW, -1);
>
> if (!(vm = qemuDomObjFromDomain(dom)))
> @@ -15423,6 +15424,14 @@ qemuDomainBlockCommit(virDomainPtr dom,
> &top_parent)))
> goto endjob;
>
> + /* XXX Should we auto-pivot when COMMIT_ACTIVE is not specified? */
I think we should. But I agree in postponing it to later patch.
> + if (topSource == &disk->src && !(flags & VIR_DOMAIN_BLOCK_COPY_ACTIVE)) {
As mentioned in the previous mail, this breaks build.
s/BLOCK_COPY/BLOCK_COMMIT/
Also shouldn't this hunk actually go in the patch that adds the active
block commit feature? It seems a bit out of place here.
> + virReportError(VIR_ERR_INVALID_ARG,
> + _("commit of '%s' active layer requires active flag"),
> + disk->dst);
> + goto endjob;
> + }
> +
> if (!topSource->backingStore) {
> virReportError(VIR_ERR_INVALID_ARG,
> _("top '%s' in chain for '%s' has no backing file"),
>
I think that this patch should also export this new flag in virsh as we
usually do with API flag additions.
Additionally a change in virsh is missing again breaks the build process:
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 84a6706..94688ef 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -1968,7 +1968,8 @@ VIR_ENUM_IMPL(vshDomainBlockJob,
N_("Unknown job"),
N_("Block Pull"),
N_("Block Copy"),
- N_("Block Commit"))
+ N_("Block Commit"),
+ N_("Block commit from active layer"))
static const char *
vshDomainBlockJobToString(int type)
Peter
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 901 bytes
Desc: OpenPGP digital signature
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20140519/194b2e55/attachment-0001.sig>
More information about the libvir-list
mailing list