[PATCH 10/11] qemu: use snapshot-load for modern QEMU to revert to snapshot

Nikolay Shirokovskiy nikolay.shirokovskiy at openvz.org
Thu Mar 31 11:19:20 UTC 2022


Note that if snapshot was done using old QEMU API then it is loaded
using old QEMU API as well as we don't know on which disk vmstate is.

Signed-off-by: Nikolay Shirokovskiy <nikolay.shirokovskiy at openvz.org>
---
 src/qemu/qemu_process.c  |  8 +++++-
 src/qemu/qemu_snapshot.c | 54 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 61 insertions(+), 1 deletion(-)

diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 6ed7eaaa83..eac6b00ff4 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -98,6 +98,7 @@
 #include "virutil.h"
 #include "storage_source.h"
 #include "backup_conf.h"
+#include "virdomainsnapshotobjlist.h"
 
 #include "logging/log_manager.h"
 #include "logging/log_protocol.h"
@@ -7389,6 +7390,7 @@ qemuProcessLaunch(virConnectPtr conn,
     size_t nnicindexes = 0;
     g_autofree int *nicindexes = NULL;
     unsigned long long maxMemLock = 0;
+    bool backcompatSnapshot;
 
     VIR_DEBUG("conn=%p driver=%p vm=%p name=%s if=%d asyncJob=%d "
               "incoming.launchURI=%s incoming.deferredURI=%s "
@@ -7444,11 +7446,15 @@ qemuProcessLaunch(virConnectPtr conn,
     if (qemuExtDevicesStart(driver, vm, incoming != NULL) < 0)
         goto cleanup;
 
+    if (snapshot)
+        backcompatSnapshot = !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_SNAPSHOT_SAVE) ||
+                             !virDomainSnapshotObjGetDef(snapshot)->memorydisk;
+
     VIR_DEBUG("Building emulator command line");
     if (!(cmd = qemuBuildCommandLine(driver,
                                      vm,
                                      incoming ? incoming->launchURI : NULL,
-                                     snapshot, vmop,
+                                     snapshot && backcompatSnapshot ? snapshot : NULL, vmop,
                                      false,
                                      qemuCheckFips(vm),
                                      &nnicindexes, &nicindexes, 0)))
diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c
index 9f81befe85..605288f6c5 100644
--- a/src/qemu/qemu_snapshot.c
+++ b/src/qemu/qemu_snapshot.c
@@ -2395,6 +2395,54 @@ qemuSnapshotRevertWriteMetadata(virDomainObj *vm,
 }
 
 
+static int
+qemuSnapshotLoadState(virQEMUDriver *driver,
+                      virDomainObj *vm,
+                      virDomainMomentObj *snap)
+{
+    qemuDomainObjPrivate *priv = vm->privateData;
+    virDomainSnapshotDef *snapdef = virDomainSnapshotObjGetDef(snap);
+    g_autoptr(GPtrArray) devices = g_ptr_array_new();
+    const char *memoryNode;
+    int ret = -1;
+    int rc;
+
+    if (!(devices = qemuSnapshotGetDisksNodes(snapdef, vm->def, &memoryNode)))
+        goto cleanup;
+
+    if (qemuDomainObjEnterMonitorAsync(driver, vm,
+                                       VIR_ASYNC_JOB_START) < 0)
+        goto cleanup;
+    rc = qemuMonitorSnapshotLoad(priv->mon,
+                                 "snapshot-load",
+                                 snap->def->name,
+                                 memoryNode,
+                                 (const char **)devices->pdata,
+                                 devices->len);
+    qemuDomainObjExitMonitor(vm);
+    if (rc < 0)
+        goto cleanup;
+
+    if (qemuSnapshotWaitJob(driver, vm, VIR_ASYNC_JOB_START,
+                            "snapshot-load") < 0)
+        goto cleanup;
+
+    ret = 0;
+
+ cleanup:
+    if (ret < 0 && virDomainObjIsActive(vm)) {
+        virErrorPtr err;
+
+        virErrorPreserveLast(&err);
+        qemuProcessStop(driver, vm,
+                        VIR_DOMAIN_SHUTOFF_FAILED,
+                        VIR_ASYNC_JOB_START, 0);
+        virErrorRestore(&err);
+    }
+    return ret;
+}
+
+
 static int
 qemuSnapshotRevertActive(virDomainObj *vm,
                          virDomainSnapshotPtr snapshot,
@@ -2407,6 +2455,7 @@ qemuSnapshotRevertActive(virDomainObj *vm,
                          unsigned int start_flags,
                          unsigned int flags)
 {
+    qemuDomainObjPrivate *priv = vm->privateData;
     virObjectEvent *event = NULL;
     virObjectEvent *event2 = NULL;
     int detail;
@@ -2458,6 +2507,11 @@ qemuSnapshotRevertActive(virDomainObj *vm,
     if (rc < 0)
         return -1;
 
+    if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_SNAPSHOT_SAVE) &&
+        snapdef->memorydisk &&
+        qemuSnapshotLoadState(driver, vm, snap) < 0)
+        return -1;
+
     /* Touch up domain state.  */
     if (!(flags & VIR_DOMAIN_SNAPSHOT_REVERT_RUNNING) &&
         (snapdef->state == VIR_DOMAIN_SNAPSHOT_PAUSED ||
-- 
2.35.1



More information about the libvir-list mailing list