Message ID | 1688132988-314397-3-git-send-email-steven.sistare@oracle.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | fix migration of suspended runstate | expand |
Steve Sistare <steven.sistare@oracle.com> writes: > 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 causes 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(). That > alone fixes precopy migration, as process_incoming_migration_bh correctly > sets runstate from global_state_get_runstate(). > > 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 merely restore the runstate. > > In both cases, if the restored state is SUSPENDED, then a later wakeup > request will resume the guest, courtesy of the previous "start on wakeup" > patch. > > Signed-off-by: Steve Sistare <steven.sistare@oracle.com> Reviewed-by: Fabiano Rosas <farosas@suse.de>
diff --git a/migration/migration.c b/migration/migration.c index 17b4b47..5495571 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -2101,7 +2101,6 @@ static int postcopy_start(MigrationState *ms) 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) { @@ -2307,7 +2306,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 bc28408..dfdbf02 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -2069,12 +2069,15 @@ 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 { - /* 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);
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 causes 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(). That alone fixes precopy migration, as process_incoming_migration_bh correctly sets runstate from global_state_get_runstate(). 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 merely restore the runstate. In both cases, if the restored state is SUSPENDED, then a later wakeup request will resume the guest, courtesy of the previous "start on wakeup" patch. Signed-off-by: Steve Sistare <steven.sistare@oracle.com> --- migration/migration.c | 2 -- migration/savevm.c | 13 ++++++++----- 2 files changed, 8 insertions(+), 7 deletions(-)