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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list