[libvirt] [PATCHv2 15/26] snapshot: refactor some qemu code

Eric Blake eblake at redhat.com
Mon Aug 15 23:33:26 UTC 2011


Prepare for code sharing.  No semantic change.

* src/qemu/qemu_driver.c (qemuFindQemuImgBinary)
(qemuDomainSnapshotWriteMetadata)
(qemuDomainSnapshotDiscard): Float up.
(qemuDomainSnapshotDiscardDescendant): Likewise, and rename...
(qemuDomainSnapshotDiscardAll): ...for generic use.
(qemuDomainSnapshotDelete): Update caller.
---
 src/qemu/qemu_driver.c |  370 ++++++++++++++++++++++++------------------------
 1 files changed, 187 insertions(+), 183 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 754ab71..3977135 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -1580,6 +1580,192 @@ cleanup:
 }


+struct snap_remove {
+    struct qemud_driver *driver;
+    virDomainObjPtr vm;
+    bool metadata_only;
+    int err;
+};
+
+/* Locate an appropriate 'qemu-img' binary.  */
+static char *
+qemuFindQemuImgBinary(void)
+{
+    char *ret;
+
+    ret = virFindFileInPath("kvm-img");
+    if (ret == NULL)
+        ret = virFindFileInPath("qemu-img");
+    if (ret == NULL)
+        qemuReportError(VIR_ERR_INTERNAL_ERROR,
+                        "%s", _("unable to find kvm-img or qemu-img"));
+
+    return ret;
+}
+
+static int qemuDomainSnapshotWriteMetadata(virDomainObjPtr vm,
+                                           virDomainSnapshotObjPtr snapshot,
+                                           char *snapshotDir)
+{
+    int fd = -1;
+    char *newxml = NULL;
+    int ret = -1;
+    char *snapDir = NULL;
+    char *snapFile = NULL;
+    char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+    virUUIDFormat(vm->def->uuid, uuidstr);
+    newxml = virDomainSnapshotDefFormat(uuidstr, snapshot->def, 1);
+    if (newxml == NULL) {
+        virReportOOMError();
+        return -1;
+    }
+
+    if (virAsprintf(&snapDir, "%s/%s", snapshotDir, vm->def->name) < 0) {
+        virReportOOMError();
+        goto cleanup;
+    }
+    if (virFileMakePath(snapDir) < 0) {
+        virReportSystemError(errno, _("cannot create snapshot directory '%s'"),
+                             snapDir);
+        goto cleanup;
+    }
+
+    if (virAsprintf(&snapFile, "%s/%s.xml", snapDir, snapshot->def->name) < 0) {
+        virReportOOMError();
+        goto cleanup;
+    }
+    fd = open(snapFile, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR);
+    if (fd < 0) {
+        qemuReportError(VIR_ERR_OPERATION_FAILED,
+                        _("failed to create snapshot file '%s'"), snapFile);
+        goto cleanup;
+    }
+    if (safewrite(fd, newxml, strlen(newxml)) != strlen(newxml)) {
+        virReportSystemError(errno, _("Failed to write snapshot data to %s"),
+                             snapFile);
+        goto cleanup;
+    }
+
+    ret = 0;
+
+cleanup:
+    VIR_FREE(snapFile);
+    VIR_FREE(snapDir);
+    VIR_FREE(newxml);
+    VIR_FORCE_CLOSE(fd);
+    return ret;
+}
+
+/* Discard one snapshot (or its metadata), without reparenting any children.  */
+static int
+qemuDomainSnapshotDiscard(struct qemud_driver *driver,
+                          virDomainObjPtr vm,
+                          virDomainSnapshotObjPtr snap,
+                          bool metadata_only)
+{
+    const char *qemuimgarg[] = { NULL, "snapshot", "-d", NULL, NULL, NULL };
+    char *snapFile = NULL;
+    int ret = -1;
+    int i;
+    qemuDomainObjPrivatePtr priv;
+    virDomainSnapshotObjPtr parentsnap;
+
+    if (!metadata_only) {
+        if (!virDomainObjIsActive(vm)) {
+            qemuimgarg[0] = qemuFindQemuImgBinary();
+            if (qemuimgarg[0] == NULL)
+                /* qemuFindQemuImgBinary set the error */
+                goto cleanup;
+
+            qemuimgarg[3] = snap->def->name;
+
+            for (i = 0; i < vm->def->ndisks; i++) {
+                /* FIXME: we also need to handle LVM here */
+                if (vm->def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
+                    if (!vm->def->disks[i]->driverType ||
+                        STRNEQ(vm->def->disks[i]->driverType, "qcow2")) {
+                        /* we continue on even in the face of error, since other
+                         * disks in this VM may have this snapshot in place
+                         */
+                        continue;
+                    }
+
+                    qemuimgarg[4] = vm->def->disks[i]->src;
+
+                    if (virRun(qemuimgarg, NULL) < 0) {
+                        /* we continue on even in the face of error, since other
+                         * disks in this VM may have this snapshot in place
+                         */
+                        continue;
+                    }
+                }
+            }
+        } else {
+            priv = vm->privateData;
+            qemuDomainObjEnterMonitorWithDriver(driver, vm);
+            /* we continue on even in the face of error */
+            qemuMonitorDeleteSnapshot(priv->mon, snap->def->name);
+            qemuDomainObjExitMonitorWithDriver(driver, vm);
+        }
+    }
+
+    if (virAsprintf(&snapFile, "%s/%s/%s.xml", driver->snapshotDir,
+                    vm->def->name, snap->def->name) < 0) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    if (snap == vm->current_snapshot) {
+        if (snap->def->parent) {
+            parentsnap = virDomainSnapshotFindByName(&vm->snapshots,
+                                                     snap->def->parent);
+            if (!parentsnap) {
+                VIR_WARN("missing parent snapshot matching name '%s'",
+                         snap->def->parent);
+            } else {
+                parentsnap->def->current = true;
+                if (qemuDomainSnapshotWriteMetadata(vm, snap,
+                                                    driver->snapshotDir) < 0) {
+                    VIR_WARN("failed to set parent snapshot '%s' as current",
+                             snap->def->parent);
+                    parentsnap->def->current = false;
+                    parentsnap = NULL;
+                }
+            }
+        }
+        vm->current_snapshot = parentsnap;
+    }
+
+    if (unlink(snapFile) < 0)
+        VIR_WARN("Failed to unlink %s", snapFile);
+    virDomainSnapshotObjListRemove(&vm->snapshots, snap);
+
+    ret = 0;
+
+cleanup:
+    VIR_FREE(snapFile);
+    VIR_FREE(qemuimgarg[0]);
+
+    return ret;
+}
+
+/* Hash iterator callback to discard multiple snapshots.  */
+static void
+qemuDomainSnapshotDiscardAll(void *payload,
+                             const void *name ATTRIBUTE_UNUSED,
+                             void *data)
+{
+    virDomainSnapshotObjPtr snap = payload;
+    struct snap_remove *curr = data;
+    int err;
+
+    err = qemuDomainSnapshotDiscard(curr->driver, curr->vm, snap,
+                                    curr->metadata_only);
+    if (err && !curr->err)
+        curr->err = err;
+}
+
 static int
 qemuDomainDestroyFlags(virDomainPtr dom,
                        unsigned int flags)
@@ -8278,75 +8464,6 @@ cleanup:
     return ret;
 }

-static char *qemuFindQemuImgBinary(void)
-{
-    char *ret;
-
-    ret = virFindFileInPath("kvm-img");
-    if (ret == NULL)
-        ret = virFindFileInPath("qemu-img");
-    if (ret == NULL)
-        qemuReportError(VIR_ERR_INTERNAL_ERROR,
-                        "%s", _("unable to find kvm-img or qemu-img"));
-
-    return ret;
-}
-
-static int qemuDomainSnapshotWriteMetadata(virDomainObjPtr vm,
-                                           virDomainSnapshotObjPtr snapshot,
-                                           char *snapshotDir)
-{
-    int fd = -1;
-    char *newxml = NULL;
-    int ret = -1;
-    char *snapDir = NULL;
-    char *snapFile = NULL;
-    char uuidstr[VIR_UUID_STRING_BUFLEN];
-
-    virUUIDFormat(vm->def->uuid, uuidstr);
-    newxml = virDomainSnapshotDefFormat(uuidstr, snapshot->def, 1);
-    if (newxml == NULL) {
-        virReportOOMError();
-        return -1;
-    }
-
-    if (virAsprintf(&snapDir, "%s/%s", snapshotDir, vm->def->name) < 0) {
-        virReportOOMError();
-        goto cleanup;
-    }
-    if (virFileMakePath(snapDir) < 0) {
-        virReportSystemError(errno, _("cannot create snapshot directory '%s'"),
-                             snapDir);
-        goto cleanup;
-    }
-
-    if (virAsprintf(&snapFile, "%s/%s.xml", snapDir, snapshot->def->name) < 0) {
-        virReportOOMError();
-        goto cleanup;
-    }
-    fd = open(snapFile, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR);
-    if (fd < 0) {
-        qemuReportError(VIR_ERR_OPERATION_FAILED,
-                        _("failed to create snapshot file '%s'"), snapFile);
-        goto cleanup;
-    }
-    if (safewrite(fd, newxml, strlen(newxml)) != strlen(newxml)) {
-        virReportSystemError(errno, _("Failed to write snapshot data to %s"),
-                             snapFile);
-        goto cleanup;
-    }
-
-    ret = 0;
-
-cleanup:
-    VIR_FREE(snapFile);
-    VIR_FREE(snapDir);
-    VIR_FREE(newxml);
-    VIR_FORCE_CLOSE(fd);
-    return ret;
-}
-
-
 static int qemuDomainSnapshotIsAllowed(virDomainObjPtr vm)
 {
     int i;
@@ -8965,119 +9082,6 @@ cleanup:
     return ret;
 }

-static int qemuDomainSnapshotDiscard(struct qemud_driver *driver,
-                                     virDomainObjPtr vm,
-                                     virDomainSnapshotObjPtr snap,
-                                     bool metadata_only)
-{
-    const char *qemuimgarg[] = { NULL, "snapshot", "-d", NULL, NULL, NULL };
-    char *snapFile = NULL;
-    int ret = -1;
-    int i;
-    qemuDomainObjPrivatePtr priv;
-    virDomainSnapshotObjPtr parentsnap = NULL;
-
-    if (!metadata_only) {
-        if (!virDomainObjIsActive(vm)) {
-            qemuimgarg[0] = qemuFindQemuImgBinary();
-            if (qemuimgarg[0] == NULL)
-                /* qemuFindQemuImgBinary set the error */
-                goto cleanup;
-
-            qemuimgarg[3] = snap->def->name;
-
-            for (i = 0; i < vm->def->ndisks; i++) {
-                /* FIXME: we also need to handle LVM here */
-                if (vm->def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
-                    if (!vm->def->disks[i]->driverType ||
-                        STRNEQ(vm->def->disks[i]->driverType, "qcow2")) {
-                        /* we continue on even in the face of error, since other
-                         * disks in this VM may have this snapshot in place
-                         */
-                        continue;
-                    }
-
-                    qemuimgarg[4] = vm->def->disks[i]->src;
-
-                    if (virRun(qemuimgarg, NULL) < 0) {
-                        /* we continue on even in the face of error, since other
-                         * disks in this VM may have this snapshot in place
-                         */
-                        continue;
-                    }
-                }
-            }
-        } else {
-            priv = vm->privateData;
-            qemuDomainObjEnterMonitorWithDriver(driver, vm);
-            /* we continue on even in the face of error */
-            qemuMonitorDeleteSnapshot(priv->mon, snap->def->name);
-            qemuDomainObjExitMonitorWithDriver(driver, vm);
-        }
-    }
-
-    if (virAsprintf(&snapFile, "%s/%s/%s.xml", driver->snapshotDir,
-                    vm->def->name, snap->def->name) < 0) {
-        virReportOOMError();
-        goto cleanup;
-    }
-
-    if (snap == vm->current_snapshot) {
-        if (snap->def->parent) {
-            parentsnap = virDomainSnapshotFindByName(&vm->snapshots,
-                                                     snap->def->parent);
-            if (!parentsnap) {
-                VIR_WARN("missing parent snapshot matching name '%s'",
-                         snap->def->parent);
-            } else {
-                parentsnap->def->current = true;
-                if (qemuDomainSnapshotWriteMetadata(vm, snap,
-                                                    driver->snapshotDir) < 0) {
-                    VIR_WARN("failed to set parent snapshot '%s' as current",
-                             snap->def->parent);
-                    parentsnap->def->current = false;
-                    parentsnap = NULL;
-                }
-            }
-        }
-        vm->current_snapshot = parentsnap;
-    }
-
-    if (unlink(snapFile) < 0)
-        VIR_WARN("Failed to unlink %s", snapFile);
-    virDomainSnapshotObjListRemove(&vm->snapshots, snap);
-
-    ret = 0;
-
-cleanup:
-    VIR_FREE(snapFile);
-    VIR_FREE(qemuimgarg[0]);
-
-    return ret;
-}
-
-struct snap_remove {
-    struct qemud_driver *driver;
-    virDomainObjPtr vm;
-    bool metadata_only;
-    int err;
-};
-
-static void
-qemuDomainSnapshotDiscardDescendant(void *payload,
-                                    const void *name ATTRIBUTE_UNUSED,
-                                    void *data)
-{
-    virDomainSnapshotObjPtr snap = payload;
-    struct snap_remove *curr = data;
-    int err;
-
-    err = qemuDomainSnapshotDiscard(curr->driver, curr->vm, snap,
-                                    curr->metadata_only);
-    if (err && !curr->err)
-        curr->err = err;
-}
-
 struct snap_reparent {
     struct qemud_driver *driver;
     const char *parent;
@@ -9155,7 +9159,7 @@ static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
         rem.err = 0;
         virDomainSnapshotForEachDescendant(&vm->snapshots,
                                            snap,
-                                           qemuDomainSnapshotDiscardDescendant,
+                                           qemuDomainSnapshotDiscardAll,
                                            &rem);
         if (rem.err < 0)
             goto endjob;
-- 
1.7.4.4




More information about the libvir-list mailing list