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@xxxxxxxxxx> --- 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