[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