[PATCHv3 05/26] snapshot: don't leak resources on qemu snapshot failure

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



https://bugzilla.redhat.com/show_bug.cgi?id=727709
mentions that if qemu fails to create the snapshot (such as what
happens on Fedora 15 qemu, which has qmp but where savevm is only
in hmp, and where libvirt is old enough to not try the hmp fallback),
then 'virsh snapshot-list dom' will show a garbage snapshot entry,
and the libvirt internal directory for storing snapshot metadata
will have a bogus file.

This fixes the fallout bug of polluting the snapshot-list with
garbage on failure (the root cause of the F15 bug of not having
fallback to hmp has already been fixed in newer libvirt releases).

* src/qemu/qemu_driver.c (qemuDomainSnapshotCreateXML): Allocate
memory before making snapshot, and cleanup on failure.  Don't
dereference NULL if transient domain exited during snapshot creation.
---

v3: rearrange checks to avoid dereferencing NULL vm; transfer def
when snap is created so that def gets cleaned regardless of vm state

 src/qemu/qemu_driver.c |   43 ++++++++++++++++++++++++-------------------
 1 files changed, 24 insertions(+), 19 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 989d21b..4ce2409 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -8455,8 +8455,12 @@ cleanup:
                         _("resuming after snapshot failed"));
     }

-    if (qemuDomainObjEndJob(driver, vm) == 0)
+    if (qemuDomainObjEndJob(driver, vm) == 0) {
+        /* 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;
+    }

     return ret;
 }
@@ -8470,7 +8474,7 @@ static virDomainSnapshotPtr qemuDomainSnapshotCreateXML(virDomainPtr domain,
     virDomainSnapshotObjPtr snap = NULL;
     virDomainSnapshotPtr snapshot = NULL;
     char uuidstr[VIR_UUID_STRING_BUFLEN];
-    virDomainSnapshotDefPtr def;
+    virDomainSnapshotDefPtr def = NULL;

     virCheckFlags(0, NULL);

@@ -8498,8 +8502,17 @@ static virDomainSnapshotPtr qemuDomainSnapshotCreateXML(virDomainPtr domain,

     if (!(snap = virDomainSnapshotAssignDef(&vm->snapshots, def)))
         goto cleanup;
+    def = NULL;

     snap->def->state = virDomainObjGetState(vm, NULL);
+    if (vm->current_snapshot) {
+        snap->def->parent = strdup(vm->current_snapshot->def->name);
+        if (snap->def->parent == NULL) {
+            virReportOOMError();
+            goto cleanup;
+        }
+        vm->current_snapshot = NULL;
+    }

     /* actually do the snapshot */
     if (!virDomainObjIsActive(vm)) {
@@ -8511,32 +8524,24 @@ static virDomainSnapshotPtr qemuDomainSnapshotCreateXML(virDomainPtr domain,
             goto cleanup;
     }

-    /* FIXME: if we fail after this point, there's not a whole lot we can
+    /* 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
      */
-
-    if (vm->current_snapshot) {
-        def->parent = strdup(vm->current_snapshot->def->name);
-        if (def->parent == NULL) {
-            virReportOOMError();
-            goto cleanup;
-        }
-    }
-
-    /* Now we set the new current_snapshot for the domain */
-    vm->current_snapshot = snap;
-
-    if (qemuDomainSnapshotWriteMetadata(vm, vm->current_snapshot,
-                                        driver->snapshotDir) < 0)
-        /* qemuDomainSnapshotWriteMetadata set the error */
+    if (qemuDomainSnapshotWriteMetadata(vm, snap, driver->snapshotDir) < 0)
         goto cleanup;

     snapshot = virGetDomainSnapshot(domain, snap->def->name);

 cleanup:
-    if (vm)
+    if (vm) {
+        if (snapshot)
+            vm->current_snapshot = snap;
+        else if (snap)
+            virDomainSnapshotObjListRemove(&vm->snapshots, snap);
         virDomainObjUnlock(vm);
+    }
+    virDomainSnapshotDefFree(def);
     qemuDriverUnlock(driver);
     return snapshot;
 }
-- 
1.7.4.4

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list


[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]