qemu-devel
[Top][All Lists]
Advanced

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

[PATCH V4 02/11] migration: preserve suspended runstate


From: Steve Sistare
Subject: [PATCH V4 02/11] migration: preserve suspended runstate
Date: Tue, 29 Aug 2023 11:17:57 -0700

A guest that is migrated in the suspended state automaticaly wakes and
continues execution.  This is wrong; the guest should end migration in
the same state it started.  The root cause is that the outgoing migration
code automatically wakes the guest, then saves the RUNNING runstate in
global_state_store(), hence the incoming migration code thinks the guest is
running and continues the guest if autostart is true.

On the outgoing side, do not call qemu_system_wakeup_request().

On the incoming side for precopy, prepare to start the vm, but do not
yet start it.  A future system_wakeup will cause the main loop to resume
the VCPUs.

On the incoming side for postcopy, do not wake the guest, and apply the
the same logic as found in precopy: if autostart and the runstate is
RUNNING, then vm_start, else prepare to start the vm.

Signed-off-by: Steve Sistare <steven.sistare@oracle.com>
Reviewed-by: Fabiano Rosas <farosas@suse.de>
---
 migration/migration.c |  4 ++--
 migration/savevm.c    | 15 ++++++++++-----
 2 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/migration/migration.c b/migration/migration.c
index 5528acb..5bcc761 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -496,6 +496,8 @@ static void process_incoming_migration_bh(void *opaque)
     } else if (migration_incoming_colo_enabled()) {
         migration_incoming_disable_colo();
         vm_start();
+    } else if (global_state_get_runstate() == RUN_STATE_SUSPENDED) {
+        vm_prepare_start(false, global_state_get_runstate());
     } else {
         runstate_set(global_state_get_runstate());
     }
@@ -2109,7 +2111,6 @@ static int postcopy_start(MigrationState *ms, Error 
**errp)
     qemu_mutex_lock_iothread();
     trace_postcopy_start_set_run();
 
-    qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL);
     global_state_store();
     ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
     if (ret < 0) {
@@ -2315,7 +2316,6 @@ static void migration_completion(MigrationState *s)
     if (s->state == MIGRATION_STATUS_ACTIVE) {
         qemu_mutex_lock_iothread();
         s->downtime_start = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
-        qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL);
 
         s->vm_old_state = runstate_get();
         global_state_store();
diff --git a/migration/savevm.c b/migration/savevm.c
index a2cb885..bae0a1a 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -2070,12 +2070,17 @@ static void loadvm_postcopy_handle_run_bh(void *opaque)
 
     dirty_bitmap_mig_before_vm_start();
 
-    if (autostart) {
-        /* Hold onto your hats, starting the CPU */
-        vm_start();
+    if (!global_state_received() ||
+        global_state_get_runstate() == RUN_STATE_RUNNING) {
+        if (autostart) {
+            vm_start();
+        } else {
+            runstate_set(RUN_STATE_PAUSED);
+        }
+    } else if (global_state_get_runstate() == RUN_STATE_SUSPENDED) {
+        vm_prepare_start(false, RUN_STATE_SUSPENDED);
     } else {
-        /* leave it paused and let management decide when to start the CPU */
-        runstate_set(RUN_STATE_PAUSED);
+        runstate_set(global_state_get_runstate());
     }
 
     qemu_bh_delete(mis->bh);
-- 
1.8.3.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]