[libvirt] [PATCHv2 10/20] snapshot: qemu: Add support for external checkpoints
Eric Blake
eblake at redhat.com
Fri Nov 2 23:17:49 UTC 2012
On 11/02/2012 04:28 PM, Eric Blake wrote:
> On 11/01/2012 10:22 AM, Peter Krempa wrote:
>> This patch adds support to take external system checkpoints.
>>
>> The functionality is layered on top of the previous disk-only snapshot
>> code. When the checkpoint is requested the domain memory is saved to the
>> memory image file using migration to file. (The user may specify to
>> do take the memory image while the guest is live with the
>
> s/do //
>
>> VIR_DOMAIN_SNAPSHOT_CREATE_LIVE flag.)
>>
>> The memory save image shares format with the image created by
>> virDomainSave() API.
>> ---
> Ouch. You left the quiesce logic in qemuDomainSnapshotCreateDiskActive,
> but changed the caller so that this point can be reached after the
> domain has been already paused. We already reject _QUIESCE without
> _DISK_ONLY, so we know there is no memory to worry about, but the
> quiesce must occur before pausing things.
>
> That means you need to move the quiesce and thaw logic out of
> CreateDiskActive and into CreateActiveExternal.
>
>
> I'm playing with squashing this in, but I also need to fix the quiesce
> outside pause issue before I can give ACK, if you can beat me to it.
Here's what I ended up with; I can ACK your patch plus this squashed in,
although it wouldn't hurt to do another round of reviews and/or testing.
diff --git i/src/qemu/qemu_driver.c w/src/qemu/qemu_driver.c
index d5cfdcc..2a9e09b 100644
--- i/src/qemu/qemu_driver.c
+++ w/src/qemu/qemu_driver.c
@@ -11020,7 +11020,6 @@ qemuDomainSnapshotCreateDiskActive(struct
qemud_driver *driver,
int ret = -1;
int i;
bool persist = false;
- int thaw = 0; /* 1 if freeze succeeded, -1 if freeze failed */
bool reuse = (flags & VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT) != 0;
virCgroupPtr cgroup = NULL;
@@ -11039,20 +11038,6 @@ qemuDomainSnapshotCreateDiskActive(struct
qemud_driver *driver,
}
/* 'cgroup' is still NULL if cgroups are disabled. */
- /* If quiesce was requested, then issue a freeze command, and a
- * counterpart thaw command, no matter what. The command will
- * fail if the guest is paused or the guest agent is not
- * running. */
- if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE) {
- if (qemuDomainSnapshotFSFreeze(driver, vm) < 0) {
- /* helper reported the error */
- thaw = -1;
- goto cleanup;
- } else {
- thaw = 1;
- }
- }
-
if (qemuCapsGet(priv->caps, QEMU_CAPS_TRANSACTION)) {
if (!(actions = virJSONValueNewArray())) {
virReportOOMError();
@@ -11131,13 +11116,6 @@ cleanup:
ret = -1;
}
- if (thaw != 0 &&
- qemuDomainSnapshotFSThaw(driver, vm, thaw > 0) < 0) {
- /* helper reported the error, if it was needed */
- if (thaw > 0)
- ret = -1;
- }
-
return ret;
}
@@ -11157,24 +11135,43 @@
qemuDomainSnapshotCreateActiveExternal(virConnectPtr conn,
bool memory = snap->def->memory ==
VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
bool atomic = !!(flags & VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC);
bool transaction = qemuCapsGet(priv->caps, QEMU_CAPS_TRANSACTION);
+ int thaw = 0; /* 1 if freeze succeeded, -1 if freeze failed */
if (qemuDomainObjBeginAsyncJobWithDriver(driver, vm,
QEMU_ASYNC_JOB_SNAPSHOT) < 0)
goto cleanup;
+ /* If quiesce was requested, then issue a freeze command, and a
+ * counterpart thaw command, no matter what. The command will
+ * fail if the guest is paused or the guest agent is not
+ * running. */
+ if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE) {
+ if (qemuDomainSnapshotFSFreeze(driver, vm) < 0) {
+ /* helper reported the error */
+ thaw = -1;
+ goto endjob;
+ } else {
+ thaw = 1;
+ }
+ }
+
/* we need to resume the guest only if it was previously running */
if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
resume = true;
- /* For multiple disks, libvirt must pause externally to get all
- * snapshots to be at the same point in time, unless qemu supports
- * transactions. For a single disk, snapshot is atomic without
- * requiring a pause. Thanks to qemuDomainSnapshotPrepare, if
- * we got to this point, the atomic flag now says whether we need
- * to pause, and a capability bit says whether to use transaction.
+ /* For external checkpoints (those with memory), the guest
+ * must pause (either by libvirt up front, or by qemu after
+ * _LIVE converges). For disk-only snapshots with multiple
+ * disks, libvirt must pause externally to get all snapshots
+ * to be at the same point in time, unless qemu supports
+ * transactions. For a single disk, snapshot is atomic
+ * without requiring a pause. Thanks to
+ * qemuDomainSnapshotPrepare, if we got to this point, the
+ * atomic flag now says whether we need to pause, and a
+ * capability bit says whether to use transaction.
*/
if ((memory && !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_LIVE)) ||
- (atomic && !transaction)) {
+ (!memory && atomic && !transaction)) {
if (qemuProcessStopCPUs(driver, vm, VIR_DOMAIN_PAUSED_SNAPSHOT,
QEMU_ASYNC_JOB_SNAPSHOT) < 0)
goto endjob;
@@ -11230,6 +11227,7 @@
qemuDomainSnapshotCreateActiveExternal(virConnectPtr conn,
* only, so this end job never drops the last reference. */
ignore_value(qemuDomainObjEndAsyncJob(driver, vm));
resume = false;
+ thaw = 0;
vm = NULL;
if (event)
qemuDomainEventQueue(driver, event);
@@ -11238,16 +11236,6 @@
qemuDomainSnapshotCreateActiveExternal(virConnectPtr conn,
ret = 0;
endjob:
- if (vm && !qemuDomainObjEndAsyncJob(driver, vm)) {
- /* Only possible if a transient vm quit while our locks were down,
- * in which case we don't want to save snapshot metadata.
- */
- *vmptr = NULL;
- ret = -1;
- }
-
-cleanup:
- VIR_FREE(xml);
if (resume && vm && virDomainObjIsActive(vm) &&
qemuProcessStartCPUs(driver, vm, conn,
VIR_DOMAIN_RUNNING_UNPAUSED,
@@ -11258,6 +11246,22 @@ cleanup:
return -1;
}
+ if (vm && thaw != 0 &&
+ qemuDomainSnapshotFSThaw(driver, vm, thaw > 0) < 0) {
+ /* helper reported the error, if it was needed */
+ if (thaw > 0)
+ ret = -1;
+ }
+ if (vm && !qemuDomainObjEndAsyncJob(driver, vm)) {
+ /* Only possible if a transient vm quit while our locks were down,
+ * in which case we don't want to save snapshot metadata.
+ */
+ *vmptr = NULL;
+ ret = -1;
+ }
+
+cleanup:
+ VIR_FREE(xml);
return ret;
}
@@ -11498,14 +11502,23 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
}
/* reject the VIR_DOMAIN_SNAPSHOT_CREATE_LIVE flag where not
supported */
- if ((flags & VIR_DOMAIN_SNAPSHOT_CREATE_LIVE) &&
+ if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_LIVE &&
(!virDomainObjIsActive(vm) ||
- snap->def->memory != VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL)) {
+ snap->def->memory != VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL ||
+ flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE)) {
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
_("live snapshot creation is supported only "
"with external checkpoints"));
goto cleanup;
}
+ if ((snap->def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL ||
+ snap->def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL) &&
+ flags & VIR_DOMAIN_SNAPSHOT_CREATE_DISK_ONLY) {
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+ _("disk-only snapshot creation is not compatible
with "
+ "memory snapshot"));
+ goto cleanup;
+ }
/* actually do the snapshot */
if (flags & VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE) {
--
Eric Blake eblake at redhat.com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 617 bytes
Desc: OpenPGP digital signature
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20121102/8f19f01f/attachment-0001.sig>
More information about the libvir-list
mailing list