[libvirt] [PATCH 2/3] snapshots: Introduce VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE flag

Jiri Denemark jdenemar at redhat.com
Tue Jan 24 18:49:39 UTC 2012


On Tue, Jan 24, 2012 at 18:37:44 +0100, Michal Privoznik wrote:
> With this flag, virDomainSnapshotCreate will use fs-freeze and
> fs-thaw guest agent commands to quiesce guest's disks.
> ---
>  include/libvirt/libvirt.h.in |    4 ++
>  src/libvirt.c                |    6 ++
>  src/qemu/qemu_driver.c       |  118 ++++++++++++++++++++++++++++++++++++-----
>  3 files changed, 113 insertions(+), 15 deletions(-)
> 
> diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
> index 5e6e488..182065d 100644
> --- a/include/libvirt/libvirt.h.in
> +++ b/include/libvirt/libvirt.h.in
> @@ -3125,6 +3125,10 @@ typedef enum {
>                                                            system checkpoint */
>      VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT   = (1 << 5), /* reuse any existing
>                                                            external files */
> +    VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE     = (1 << 6), /* use guest agent to
> +                                                          quiesce all mounted
> +                                                          file systems within
> +                                                          the domain */

Do we also want to add another flag that would make quiescing optional? That
is, use it if it's available but don't fail if it's not.

>  } virDomainSnapshotCreateFlags;
>  
>  /* Take a snapshot of the current VM state */
> diff --git a/src/libvirt.c b/src/libvirt.c
> index 96ad3d5..d9b8d88 100644
> --- a/src/libvirt.c
> +++ b/src/libvirt.c
> @@ -16602,6 +16602,12 @@ virDomainSnapshotGetConnect(virDomainSnapshotPtr snapshot)
>   * inconsistent (as if power had been pulled), and specifying this
>   * with the VIR_DOMAIN_SNAPSHOT_CREATE_HALT flag risks data loss.
>   *
> + * If @flags includes VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE, then the
> + * libvirt will attempt to use guest agent to freeze and thaw all
> + * file systems in use within domain OS. However, if the guest agent
> + * is not present, an error is trowed. Moreover, this flags requires

s/trowed/thrown/; s/flags/flag/

> + * VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY to be passed as well.
> + *
>   * By default, if the snapshot involves external files, and any of the
>   * destination files already exist as a regular file, the snapshot is
>   * rejected to avoid losing contents of those files.  However, if
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index c81289a..14ad30b 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -9461,6 +9461,56 @@ static int qemuDomainSnapshotIsAllowed(virDomainObjPtr vm)
>      return 1;
>  }
>  
> +static int
> +qemuDomainSnapshotFSFreeze(struct qemud_driver *driver,
> +                           virDomainObjPtr vm) {
> +    qemuDomainObjPrivatePtr priv = vm->privateData;
> +    int freezed;
> +
> +    if (priv->agentError) {
> +        qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                        _("QEMU guest agent is not "
> +                          "available due to an error"));
> +        return -1;
> +    }
> +    if (!priv->agent) {
> +        qemuReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
> +                        _("QEMU guest agent is not configured"));
> +        return -1;
> +    }
> +
> +    qemuDomainObjEnterAgent(driver, vm);
> +    freezed = qemuAgentFSFreeze(priv->agent);
> +    qemuDomainObjExitAgent(driver, vm);
> +
> +    return freezed;
> +}
> +
> +static int
> +qemuDomainSnapshotFSThaw(struct qemud_driver *driver,
> +                         virDomainObjPtr vm) {
> +    qemuDomainObjPrivatePtr priv = vm->privateData;
> +    int thawed;
> +
> +    if (priv->agentError) {
> +        qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                        _("QEMU guest agent is not "
> +                          "available due to an error"));
> +        return -1;
> +    }
> +    if (!priv->agent) {
> +        qemuReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
> +                        _("QEMU guest agent is not configured"));
> +        return -1;
> +    }
> +
> +    qemuDomainObjEnterAgent(driver, vm);
> +    thawed = qemuAgentFSThaw(priv->agent);
> +    qemuDomainObjExitAgent(driver, vm);
> +
> +    return thawed;
> +}
> +
>  /* The domain is expected to be locked and inactive. */
>  static int
>  qemuDomainSnapshotCreateInactive(struct qemud_driver *driver,
> @@ -9493,6 +9543,13 @@ qemuDomainSnapshotCreateActive(virConnectPtr conn,
>      }
>  
>      if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
> +        if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE) &&
> +            (qemuDomainSnapshotFSFreeze(driver, vm) < 0)) {
> +            qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                            _("Unable to freeze domain's file systems"));

This just masks useful error reported by qemuDomainSnapshotFSFreeze().

> +            goto endjob;
> +        }
> +
>          /* savevm monitor command pauses the domain emitting an event which
>           * confuses libvirt since it's not notified when qemu resumes the
>           * domain. Thus we stop and start CPUs ourselves.
> @@ -9532,13 +9589,21 @@ qemuDomainSnapshotCreateActive(virConnectPtr conn,
>      }
>  
>  cleanup:
> -    if (resume && virDomainObjIsActive(vm) &&
> -        qemuProcessStartCPUs(driver, vm, conn,
> -                             VIR_DOMAIN_RUNNING_UNPAUSED,
> -                             QEMU_ASYNC_JOB_NONE) < 0 &&
> -        virGetLastError() == NULL) {
> -        qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
> -                        _("resuming after snapshot failed"));
> +    if (resume && virDomainObjIsActive(vm)) {
> +        if (qemuProcessStartCPUs(driver, vm, conn,
> +                                 VIR_DOMAIN_RUNNING_UNPAUSED,
> +                                 QEMU_ASYNC_JOB_NONE) < 0 &&
> +            virGetLastError() == NULL) {
> +            qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
> +                            _("resuming after snapshot failed"));
> +            goto endjob;
> +        }
> +
> +        if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE) &&
> +            qemuDomainSnapshotFSThaw(driver, vm) < 0) {
> +            qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                            _("Unable to thaw domain's file systems"));

ditto

> +        }
>      }
>  
>  endjob:
> @@ -9773,6 +9838,13 @@ qemuDomainSnapshotCreateDiskActive(virConnectPtr conn,
>  
>  
>      if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
> +        if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE) &&
> +            (qemuDomainSnapshotFSFreeze(driver, vm) < 0)) {
> +            qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                            _("Unable to freeze domain's file systems"));

Again.

> +            goto endjob;
> +        }
> +
>          /* In qemu, snapshot_blkdev on a single disk will pause cpus,
>           * but this confuses libvirt since notifications are not given
>           * when qemu resumes.  And for multiple disks, libvirt must
> @@ -9840,13 +9912,21 @@ qemuDomainSnapshotCreateDiskActive(virConnectPtr conn,
>      }
>  
>  cleanup:
> -    if (resume && virDomainObjIsActive(vm) &&
> -        qemuProcessStartCPUs(driver, vm, conn,
> -                             VIR_DOMAIN_RUNNING_UNPAUSED,
> -                             QEMU_ASYNC_JOB_NONE) < 0 &&
> -        virGetLastError() == NULL) {
> -        qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
> -                        _("resuming after snapshot failed"));
> +    if (resume && virDomainObjIsActive(vm)) {
> +        if (qemuProcessStartCPUs(driver, vm, conn,
> +                                 VIR_DOMAIN_RUNNING_UNPAUSED,
> +                                 QEMU_ASYNC_JOB_NONE) < 0 &&
> +            virGetLastError() == NULL) {
> +            qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
> +                            _("resuming after snapshot failed"));
> +            goto endjob;
> +        }
> +
> +        if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE) &&
> +            qemuDomainSnapshotFSThaw(driver, vm) < 0) {
> +            qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                            _("Unable to thaw domain's file systems"));

And once more.

> +        }
>      }
>  
>      if (vm) {
> @@ -9888,7 +9968,15 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
>                    VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA |
>                    VIR_DOMAIN_SNAPSHOT_CREATE_HALT |
>                    VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY |
> -                  VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT, NULL);
> +                  VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT |
> +                  VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE, NULL);
> +
> +    if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE) &&
> +        !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY)) {
> +        qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
> +                        _("quiesce requires disk-only"));
> +        return NULL;
> +    }
>  
>      if (((flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE) &&
>           !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT)) ||

Jirka




More information about the libvir-list mailing list