aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/migration/snapshot.h7
-rw-r--r--migration/migration-hmp-cmds.c8
-rw-r--r--migration/savevm.c23
-rw-r--r--system/runstate.c5
-rw-r--r--system/vl.c2
5 files changed, 32 insertions, 13 deletions
diff --git a/include/migration/snapshot.h b/include/migration/snapshot.h
index e72083b..9e4dcaa 100644
--- a/include/migration/snapshot.h
+++ b/include/migration/snapshot.h
@@ -16,6 +16,7 @@
#define QEMU_MIGRATION_SNAPSHOT_H
#include "qapi/qapi-builtin-types.h"
+#include "qapi/qapi-types-run-state.h"
/**
* save_snapshot: Save an internal snapshot.
@@ -61,4 +62,10 @@ bool delete_snapshot(const char *name,
bool has_devices, strList *devices,
Error **errp);
+/**
+ * load_snapshot_resume: Restore runstate after loading snapshot.
+ * @state: state to restore
+ */
+void load_snapshot_resume(RunState state);
+
#endif
diff --git a/migration/migration-hmp-cmds.c b/migration/migration-hmp-cmds.c
index 99710c8..740a219 100644
--- a/migration/migration-hmp-cmds.c
+++ b/migration/migration-hmp-cmds.c
@@ -399,15 +399,17 @@ void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict)
void hmp_loadvm(Monitor *mon, const QDict *qdict)
{
- int saved_vm_running = runstate_is_running();
+ RunState saved_state = runstate_get();
+
const char *name = qdict_get_str(qdict, "name");
Error *err = NULL;
vm_stop(RUN_STATE_RESTORE_VM);
- if (load_snapshot(name, NULL, false, NULL, &err) && saved_vm_running) {
- vm_start();
+ if (load_snapshot(name, NULL, false, NULL, &err)) {
+ load_snapshot_resume(saved_state);
}
+
hmp_handle_error(mon, err);
}
diff --git a/migration/savevm.c b/migration/savevm.c
index 1b9ab7b..74f915f 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -3046,7 +3046,7 @@ bool save_snapshot(const char *name, bool overwrite, const char *vmstate,
QEMUSnapshotInfo sn1, *sn = &sn1;
int ret = -1, ret2;
QEMUFile *f;
- int saved_vm_running;
+ RunState saved_state = runstate_get();
uint64_t vm_state_size;
g_autoptr(GDateTime) now = g_date_time_new_now_local();
@@ -3092,8 +3092,6 @@ bool save_snapshot(const char *name, bool overwrite, const char *vmstate,
return false;
}
- saved_vm_running = runstate_is_running();
-
global_state_store();
vm_stop(RUN_STATE_SAVE_VM);
@@ -3147,9 +3145,7 @@ bool save_snapshot(const char *name, bool overwrite, const char *vmstate,
the_end:
bdrv_drain_all_end();
- if (saved_vm_running) {
- vm_start();
- }
+ vm_resume(saved_state);
return ret == 0;
}
@@ -3317,6 +3313,14 @@ err_drain:
return false;
}
+void load_snapshot_resume(RunState state)
+{
+ vm_resume(state);
+ if (state == RUN_STATE_RUNNING && runstate_get() == RUN_STATE_SUSPENDED) {
+ qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, &error_abort);
+ }
+}
+
bool delete_snapshot(const char *name, bool has_devices,
strList *devices, Error **errp)
{
@@ -3381,16 +3385,15 @@ static void snapshot_load_job_bh(void *opaque)
{
Job *job = opaque;
SnapshotJob *s = container_of(job, SnapshotJob, common);
- int orig_vm_running;
+ RunState orig_state = runstate_get();
job_progress_set_remaining(&s->common, 1);
- orig_vm_running = runstate_is_running();
vm_stop(RUN_STATE_RESTORE_VM);
s->ret = load_snapshot(s->tag, s->vmstate, true, s->devices, s->errp);
- if (s->ret && orig_vm_running) {
- vm_start();
+ if (s->ret) {
+ load_snapshot_resume(orig_state);
}
job_progress_update(&s->common, 1);
diff --git a/system/runstate.c b/system/runstate.c
index e2fa204..ca9eb54 100644
--- a/system/runstate.c
+++ b/system/runstate.c
@@ -77,6 +77,7 @@ typedef struct {
static const RunStateTransition runstate_transitions_def[] = {
{ RUN_STATE_PRELAUNCH, RUN_STATE_INMIGRATE },
+ { RUN_STATE_PRELAUNCH, RUN_STATE_SUSPENDED },
{ RUN_STATE_DEBUG, RUN_STATE_RUNNING },
{ RUN_STATE_DEBUG, RUN_STATE_FINISH_MIGRATE },
@@ -132,6 +133,7 @@ static const RunStateTransition runstate_transitions_def[] = {
{ RUN_STATE_RESTORE_VM, RUN_STATE_RUNNING },
{ RUN_STATE_RESTORE_VM, RUN_STATE_PRELAUNCH },
+ { RUN_STATE_RESTORE_VM, RUN_STATE_SUSPENDED },
{ RUN_STATE_COLO, RUN_STATE_RUNNING },
{ RUN_STATE_COLO, RUN_STATE_PRELAUNCH },
@@ -150,6 +152,7 @@ static const RunStateTransition runstate_transitions_def[] = {
{ RUN_STATE_RUNNING, RUN_STATE_COLO},
{ RUN_STATE_SAVE_VM, RUN_STATE_RUNNING },
+ { RUN_STATE_SAVE_VM, RUN_STATE_SUSPENDED },
{ RUN_STATE_SHUTDOWN, RUN_STATE_PAUSED },
{ RUN_STATE_SHUTDOWN, RUN_STATE_FINISH_MIGRATE },
@@ -163,6 +166,8 @@ static const RunStateTransition runstate_transitions_def[] = {
{ RUN_STATE_SUSPENDED, RUN_STATE_PRELAUNCH },
{ RUN_STATE_SUSPENDED, RUN_STATE_COLO},
{ RUN_STATE_SUSPENDED, RUN_STATE_PAUSED},
+ { RUN_STATE_SUSPENDED, RUN_STATE_SAVE_VM },
+ { RUN_STATE_SUSPENDED, RUN_STATE_RESTORE_VM },
{ RUN_STATE_WATCHDOG, RUN_STATE_RUNNING },
{ RUN_STATE_WATCHDOG, RUN_STATE_FINISH_MIGRATE },
diff --git a/system/vl.c b/system/vl.c
index 6b87bfa..1eec5f6 100644
--- a/system/vl.c
+++ b/system/vl.c
@@ -2710,7 +2710,9 @@ void qmp_x_exit_preconfig(Error **errp)
qemu_machine_creation_done();
if (loadvm) {
+ RunState state = autostart ? RUN_STATE_RUNNING : runstate_get();
load_snapshot(loadvm, NULL, false, NULL, &error_fatal);
+ load_snapshot_resume(state);
}
if (replay_mode != REPLAY_MODE_NONE) {
replay_vmstate_init();