[libvirt] [PATCH v2 4/4] qemu: Stop guest CPUs before creating a snapshot

Jiri Denemark jdenemar at redhat.com
Tue Mar 8 14:20:39 UTC 2011


This is currently needed because libvirt doesn't support qemu's RESUME
event. I have already implemented it but I need to test it thoroughly
since it has a great potential to break things when libvirt starts
seeing resume events that it wasn't seeing before.
---
 src/qemu/qemu_driver.c |   37 ++++++++++++++++++++++++++++++++-----
 1 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 2b286bb..d5776d6 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -6044,21 +6044,47 @@ cleanup:
 
 /* The domain is expected to be locked and active. */
 static int
-qemuDomainSnapshotCreateActive(struct qemud_driver *driver,
+qemuDomainSnapshotCreateActive(virConnectPtr conn,
+                               struct qemud_driver *driver,
                                virDomainObjPtr *vmptr,
                                virDomainSnapshotObjPtr snap)
 {
     virDomainObjPtr vm = *vmptr;
     qemuDomainObjPrivatePtr priv = vm->privateData;
-    int ret;
+    bool resume = false;
+    int ret = -1;
 
     if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
         return -1;
 
+    if (vm->state == VIR_DOMAIN_RUNNING) {
+        /* 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.
+         */
+        if (qemuProcessStopCPUs(driver, vm) < 0)
+            goto cleanup;
+
+        resume = true;
+        if (!virDomainObjIsActive(vm)) {
+            qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                            _("guest unexpectedly quit"));
+            goto cleanup;
+        }
+    }
+
     qemuDomainObjEnterMonitorWithDriver(driver, vm);
     ret = qemuMonitorCreateSnapshot(priv->mon, snap->def->name);
     qemuDomainObjExitMonitorWithDriver(driver, vm);
 
+cleanup:
+    if (resume && virDomainObjIsActive(vm) &&
+        qemuProcessStartCPUs(driver, vm, conn) < 0 &&
+        virGetLastError() == NULL) {
+        qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
+                        _("resuming after snapshot failed"));
+    }
+
     if (qemuDomainObjEndJob(vm) == 0)
         *vmptr = NULL;
 
@@ -6103,18 +6129,19 @@ static virDomainSnapshotPtr qemuDomainSnapshotCreateXML(virDomainPtr domain,
     if (!(snap = virDomainSnapshotAssignDef(&vm->snapshots, def)))
         goto cleanup;
 
+    snap->def->state = vm->state;
+
     /* actually do the snapshot */
     if (!virDomainObjIsActive(vm)) {
         if (qemuDomainSnapshotCreateInactive(vm, snap) < 0)
             goto cleanup;
     }
     else {
-        if (qemuDomainSnapshotCreateActive(driver, &vm, snap) < 0)
+        if (qemuDomainSnapshotCreateActive(domain->conn, driver,
+                                           &vm, snap) < 0)
             goto cleanup;
     }
 
-    snap->def->state = vm->state;
-
     /* FIXME: if we fail after this point, there's not a whole lot we can
      * do; we've successfully taken the snapshot, and we are now running
      * on it, so we have to go forward the best we can
-- 
1.7.4.1




More information about the libvir-list mailing list