[PATCH] qemu: Reparent children when deleting a snapshot

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

 



Shorten qemuDomainSnapshotWriteSnapshotMetadata function name
and make it take a snapshot pointer instead of dealing with
the current snapshot. Update other functions accordingly.

Add a qemuDomainSnapshotReparentChildren hash iterator to
reparent the children of a snapshot that is being deleted. Use
qemuDomainSnapshotWriteMetadata to write updated metadata
to disk.

This fixes a problem where outdated parent information breaks
the snapshot tree and hinders the deletion of child snapshots.

Reported by Philipp Hahn.
---
 src/qemu/qemu_driver.c |   92 +++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 71 insertions(+), 21 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 924446f..9b538a3 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2607,10 +2607,10 @@ qemuPrepareMonitorChr(struct qemud_driver *driver,
     return 0;
 }
 
-static int qemuDomainSnapshotSetActive(virDomainObjPtr vm,
-                                       char *snapshotDir);
-static int qemuDomainSnapshotSetInactive(virDomainObjPtr vm,
-                                         char *snapshotDir);
+static int qemuDomainSnapshotSetCurrentActive(virDomainObjPtr vm,
+                                              char *snapshotDir);
+static int qemuDomainSnapshotSetCurrentInactive(virDomainObjPtr vm,
+                                                char *snapshotDir);
 
 
 #define START_POSTFIX ": starting up\n"
@@ -2807,7 +2807,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
                                      vm->current_snapshot, vmop)))
         goto cleanup;
 
-    if (qemuDomainSnapshotSetInactive(vm, driver->snapshotDir) < 0)
+    if (qemuDomainSnapshotSetCurrentInactive(vm, driver->snapshotDir) < 0)
         goto cleanup;
 
     /* now that we know it is about to start call the hook if present */
@@ -9472,8 +9472,9 @@ static char *qemuFindQemuImgBinary(void)
     return ret;
 }
 
-static int qemuDomainSnapshotWriteSnapshotMetadata(virDomainObjPtr vm,
-                                                   char *snapshotDir)
+static int qemuDomainSnapshotWriteMetadata(virDomainObjPtr vm,
+                                           virDomainSnapshotObjPtr snapshot,
+                                           char *snapshotDir)
 {
     int fd = -1;
     char *newxml = NULL;
@@ -9484,7 +9485,7 @@ static int qemuDomainSnapshotWriteSnapshotMetadata(virDomainObjPtr vm,
     char uuidstr[VIR_UUID_STRING_BUFLEN];
 
     virUUIDFormat(vm->def->uuid, uuidstr);
-    newxml = virDomainSnapshotDefFormat(uuidstr, vm->current_snapshot->def, 1);
+    newxml = virDomainSnapshotDefFormat(uuidstr, snapshot->def, 1);
     if (newxml == NULL) {
         virReportOOMError();
         return -1;
@@ -9501,8 +9502,7 @@ static int qemuDomainSnapshotWriteSnapshotMetadata(virDomainObjPtr vm,
         goto cleanup;
     }
 
-    if (virAsprintf(&snapFile, "%s/%s.xml", snapDir,
-                    vm->current_snapshot->def->name) < 0) {
+    if (virAsprintf(&snapFile, "%s/%s.xml", snapDir, snapshot->def->name) < 0) {
         virReportOOMError();
         goto cleanup;
     }
@@ -9528,25 +9528,27 @@ cleanup:
     return ret;
 }
 
-static int qemuDomainSnapshotSetActive(virDomainObjPtr vm,
-                                       char *snapshotDir)
+static int qemuDomainSnapshotSetCurrentActive(virDomainObjPtr vm,
+                                              char *snapshotDir)
 {
     if (vm->current_snapshot) {
         vm->current_snapshot->def->active = 1;
 
-        return qemuDomainSnapshotWriteSnapshotMetadata(vm, snapshotDir);
+        return qemuDomainSnapshotWriteMetadata(vm, vm->current_snapshot,
+                                               snapshotDir);
     }
 
     return 0;
 }
 
-static int qemuDomainSnapshotSetInactive(virDomainObjPtr vm,
-                                         char *snapshotDir)
+static int qemuDomainSnapshotSetCurrentInactive(virDomainObjPtr vm,
+                                                char *snapshotDir)
 {
     if (vm->current_snapshot) {
         vm->current_snapshot->def->active = 0;
 
-        return qemuDomainSnapshotWriteSnapshotMetadata(vm, snapshotDir);
+        return qemuDomainSnapshotWriteMetadata(vm, vm->current_snapshot,
+                                               snapshotDir);
     }
 
     return 0;
@@ -9686,8 +9688,9 @@ static virDomainSnapshotPtr qemuDomainSnapshotCreateXML(virDomainPtr domain,
     /* Now we set the new current_snapshot for the domain */
     vm->current_snapshot = snap;
 
-    if (qemuDomainSnapshotWriteSnapshotMetadata(vm, driver->snapshotDir) < 0)
-        /* qemuDomainSnapshotWriteSnapshotMetadata set the error */
+    if (qemuDomainSnapshotWriteMetadata(vm, vm->current_snapshot,
+                                        driver->snapshotDir) < 0)
+        /* qemuDomainSnapshotWriteMetadata set the error */
         goto cleanup;
 
     snapshot = virGetDomainSnapshot(domain, snap->def->name);
@@ -9941,13 +9944,13 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
                 goto endjob;
         }
         else {
-            if (qemuDomainSnapshotSetActive(vm, driver->snapshotDir) < 0)
+            if (qemuDomainSnapshotSetCurrentActive(vm, driver->snapshotDir) < 0)
                 goto endjob;
 
             rc = qemudStartVMDaemon(snapshot->domain->conn, driver, vm, NULL,
                                     false, -1, NULL, VIR_VM_OP_CREATE);
             qemuDomainStartAudit(vm, "from-snapshot", rc >= 0);
-            if (qemuDomainSnapshotSetInactive(vm, driver->snapshotDir) < 0)
+            if (qemuDomainSnapshotSetCurrentInactive(vm, driver->snapshotDir) < 0)
                 goto endjob;
             if (rc < 0)
                 goto endjob;
@@ -9991,7 +9994,7 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
             }
         }
 
-        if (qemuDomainSnapshotSetActive(vm, driver->snapshotDir) < 0)
+        if (qemuDomainSnapshotSetCurrentActive(vm, driver->snapshotDir) < 0)
             goto endjob;
     }
 
@@ -10128,6 +10131,43 @@ static void qemuDomainSnapshotDiscardChildren(void *payload,
     }
 }
 
+struct snap_reparent {
+    struct qemud_driver *driver;
+    virDomainSnapshotObjPtr snap;
+    virDomainObjPtr vm;
+    int err;
+};
+
+static void
+qemuDomainSnapshotReparentChildren(void *payload,
+                                   const char *name ATTRIBUTE_UNUSED,
+                                   void *data)
+{
+    virDomainSnapshotObjPtr snap = payload;
+    struct snap_reparent *rep = data;
+
+    if (rep->err < 0) {
+        return;
+    }
+
+    if (snap->def->parent && STREQ(snap->def->parent, rep->snap->def->name)) {
+        VIR_FREE(snap->def->parent);
+
+        if (rep->snap->def->parent != NULL) {
+            snap->def->parent = strdup(rep->snap->def->parent);
+
+            if (snap->def->parent == NULL) {
+                virReportOOMError();
+                rep->err = -1;
+                return;
+            }
+        }
+
+        rep->err = qemuDomainSnapshotWriteMetadata(rep->vm, snap,
+                                                   rep->driver->snapshotDir);
+    }
+}
+
 static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
                                     unsigned int flags)
 {
@@ -10137,6 +10177,7 @@ static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
     virDomainSnapshotObjPtr snap = NULL;
     char uuidstr[VIR_UUID_STRING_BUFLEN];
     struct snap_remove rem;
+    struct snap_reparent rep;
 
     virCheckFlags(VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN, -1);
 
@@ -10169,6 +10210,15 @@ static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
                        &rem);
         if (rem.err < 0)
             goto endjob;
+    } else {
+        rep.driver = driver;
+        rep.snap = snap;
+        rep.vm = vm;
+        rep.err = 0;
+        virHashForEach(vm->snapshots.objs, qemuDomainSnapshotReparentChildren,
+                       &rep);
+        if (rep.err < 0)
+            goto endjob;
     }
 
     ret = qemuDomainSnapshotDiscard(driver, vm, snap);
-- 
1.7.0.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]