diff mbox series

[v2,05/29] migration: Introduce global_state_store_once

Message ID 20231023203608.26370-6-farosas@suse.de
State New
Headers show
Series migration: File based migration with multifd and fixed-ram | expand

Commit Message

Fabiano Rosas Oct. 23, 2023, 8:35 p.m. UTC
There are some situations during migration when we want to change the
runstate of the VM, but don't actually want the new runstate to be put
on the wire to be restored on the destination VM. In those cases, the
pattern is to use global_state_store() to save the state for migration
before changing it.

One scenario where this happens is when switching the source VM into
the FINISH_MIGRATE state. This state only makes sense on the source
VM. Another situation is when pausing the source VM prior to migration
completion.

We are about to introduce a third scenario when the whole migration
should be performed with a paused VM. In this case we will want to
save the VM runstate at the very start of the migration and that state
will be the one restored on the destination regardless of all the
runstate changes that happen in between.

To achieve that we need to make sure that the other two calls to
global_state_store() do not overwrite the state that is to be
migrated.

Introduce a version of global_state_store() that only saves the state
if no other state has already been saved.

Signed-off-by: Fabiano Rosas <farosas@suse.de>
---
 include/migration/global_state.h |  1 +
 migration/global_state.c         | 13 +++++++++++++
 migration/migration.c            |  6 +++---
 3 files changed, 17 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/include/migration/global_state.h b/include/migration/global_state.h
index e268dc1f18..9d3624100e 100644
--- a/include/migration/global_state.h
+++ b/include/migration/global_state.h
@@ -17,6 +17,7 @@ 
 
 void register_global_state(void);
 RunState global_state_store(void);
+RunState global_state_store_once(void);
 void global_state_store_running(void);
 bool global_state_received(void);
 RunState global_state_get_runstate(void);
diff --git a/migration/global_state.c b/migration/global_state.c
index d094af6198..beb00039d9 100644
--- a/migration/global_state.c
+++ b/migration/global_state.c
@@ -45,6 +45,19 @@  RunState global_state_store(void)
     return r;
 }
 
+RunState global_state_store_once(void)
+{
+    int r;
+    char *runstate = (char *)global_state.runstate;
+
+    r = qapi_enum_parse(&RunState_lookup, runstate, -1, NULL);
+    if (r < 0) {
+        return global_state_store();
+    }
+
+    return r;
+}
+
 void global_state_store_running(void)
 {
     global_state_do_store(RUN_STATE_RUNNING);
diff --git a/migration/migration.c b/migration/migration.c
index 0c23117369..a6efbd837a 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -2144,7 +2144,7 @@  static int postcopy_start(MigrationState *ms, Error **errp)
     trace_postcopy_start_set_run();
 
     qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL);
-    global_state_store();
+    global_state_store_once();
     ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
     if (ret < 0) {
         goto fail;
@@ -2344,7 +2344,7 @@  static int migration_completion_precopy(MigrationState *s,
     s->downtime_start = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
     qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL);
 
-    s->vm_old_state = global_state_store();
+    s->vm_old_state = global_state_store_once();
 
     ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
     trace_migration_completion_vm_stop(ret);
@@ -3200,7 +3200,7 @@  static void *bg_migration_thread(void *opaque)
      * transition in vm_stop_force_state() we need to wakeup it up.
      */
     qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL);
-    s->vm_old_state = global_state_store();
+    s->vm_old_state = global_state_store_once();
 
     /* Forcibly stop VM before saving state of vCPUs and devices */
     if (vm_stop_force_state(RUN_STATE_PAUSED)) {