aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2023-06-01 20:59:28 -0700
committerRichard Henderson <richard.henderson@linaro.org>2023-06-01 20:59:28 -0700
commita86d7b9ec0adb2f1efce8ab30d9ed2b72db0236e (patch)
tree7c91e7b712aab60cdf08bb7516b05036671ff192
parent9eb400cdd7b0940bd696aa01462dd53004ae04e9 (diff)
parent3a8b81f2e6393828589699bb0b8ef557b9ae5937 (diff)
Merge tag 'migration-20230601-pull-request' of https://gitlab.com/juan.quintela/qemu into staging
Migration Pull request (20230601) Hi In this series: - improve background migration (fiona) - improve vmstate failure states (vladimir) - dropped all the RDMA cleanups Please, apply. # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCAAdFiEEGJn/jt6/WMzuA0uC9IfvGFhy1yMFAmR5LAoACgkQ9IfvGFhy # 1yPOuxAA5QzUfswCIWehrkY8FApDjsecPDq5R6hS1p5pDZkHTF5y6j49J93I65o2 # E4qr4l0+DJvBvnxTW29JQ1i0RPqJHnJBFC9Ib4o0NaA/7iRP1sTwYxIN4wWZz6H/ # pqG3oQC0WPPqgj9tHSgDW4TNkFjETYaezTN8nddNmyiaO9UxNuR5ZKbeYMroVlfp # KbnAYfXV6CyXKUZFT32BYcajYBDZAqBCO6y3gEn77KPlT1/TqnucoYEVuNudq5SE # jeCamTzoAQ6SIRFM/eY+aASxdsSryqDS/WLqBFsleXs1kkJ6mkDnNels4HqS+xs9 # p2Vhv/59ktoC57XsRgTgzEklAaSHunZivcQkc5szyGVE5TZyKtWg8WhA6rvlqbjK # lb3kKpvtVi73+pAWU0hhKFdnCrB6ieCHI70CJ5mpiIu3MzLUyrNJOK4FoKNoJDOD # Dp45DK+W/EMg51pXyHJZZqHM1p0GGj0fmhv5T05nJ590fIWV4iqDdHFxsMZ9vEPN # iEvAB7/pXz+yECznDFrp2e047rshOGaKKNSW3zl3/7D32Ds2FKur76dL4BoymztW # HHLxmRWn8HmHMoKYLoawWVmCBsDqy8BFct+rHbA6h/0nSCPYIUCmMrSYVqajUbXD # Ulkh4KNQGoBCzp5Toa0dYEXVc891wVOw4k8PTARwf2OYskSkT88= # =Km5X # -----END PGP SIGNATURE----- # gpg: Signature made Thu 01 Jun 2023 04:38:50 PM PDT # gpg: using RSA key 1899FF8EDEBF58CCEE034B82F487EF185872D723 # gpg: Good signature from "Juan Quintela <quintela@redhat.com>" [unknown] # gpg: aka "Juan Quintela <quintela@trasno.org>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 1899 FF8E DEBF 58CC EE03 4B82 F487 EF18 5872 D723 * tag 'migration-20230601-pull-request' of https://gitlab.com/juan.quintela/qemu: migration: stop tracking ram writes when cancelling background migration migration: restore vmstate on migration failure migration: switch from .vm_was_running to .vm_old_state runstate: drop unused runstate_store() migration: never fail in global_state_store() runstate: add runstate_get() Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
-rw-r--r--include/migration/global_state.h2
-rw-r--r--include/sysemu/runstate.h2
-rw-r--r--migration/global_state.c23
-rw-r--r--migration/migration.c70
-rw-r--r--migration/migration.h9
-rw-r--r--migration/savevm.c6
-rw-r--r--softmmu/runstate.c25
7 files changed, 66 insertions, 71 deletions
diff --git a/include/migration/global_state.h b/include/migration/global_state.h
index 945eb35d5b..d7c2cd3216 100644
--- a/include/migration/global_state.h
+++ b/include/migration/global_state.h
@@ -16,7 +16,7 @@
#include "qapi/qapi-types-run-state.h"
void register_global_state(void);
-int global_state_store(void);
+void global_state_store(void);
void global_state_store_running(void);
bool global_state_received(void);
RunState global_state_get_runstate(void);
diff --git a/include/sysemu/runstate.h b/include/sysemu/runstate.h
index f3ed52548e..7beb29c2e2 100644
--- a/include/sysemu/runstate.h
+++ b/include/sysemu/runstate.h
@@ -6,9 +6,9 @@
bool runstate_check(RunState state);
void runstate_set(RunState new_state);
+RunState runstate_get(void);
bool runstate_is_running(void);
bool runstate_needs_reset(void);
-bool runstate_store(char *str, size_t size);
typedef void VMChangeStateHandler(void *opaque, bool running, RunState state);
diff --git a/migration/global_state.c b/migration/global_state.c
index a33947ca32..4e2a9d8ec0 100644
--- a/migration/global_state.c
+++ b/migration/global_state.c
@@ -29,23 +29,22 @@ typedef struct {
static GlobalState global_state;
-int global_state_store(void)
+static void global_state_do_store(RunState state)
{
- if (!runstate_store((char *)global_state.runstate,
- sizeof(global_state.runstate))) {
- error_report("runstate name too big: %s", global_state.runstate);
- trace_migrate_state_too_big();
- return -EINVAL;
- }
- return 0;
+ const char *state_str = RunState_str(state);
+ assert(strlen(state_str) < sizeof(global_state.runstate));
+ strpadcpy((char *)global_state.runstate, sizeof(global_state.runstate),
+ state_str, '\0');
+}
+
+void global_state_store(void)
+{
+ global_state_do_store(runstate_get());
}
void global_state_store_running(void)
{
- const char *state = RunState_str(RUN_STATE_RUNNING);
- assert(strlen(state) < sizeof(global_state.runstate));
- strpadcpy((char *)global_state.runstate, sizeof(global_state.runstate),
- state, '\0');
+ global_state_do_store(RUN_STATE_RUNNING);
}
bool global_state_received(void)
diff --git a/migration/migration.c b/migration/migration.c
index 5de7f734b9..dc05c6f6ea 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -1402,7 +1402,7 @@ void migrate_init(MigrationState *s)
s->start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
s->total_time = 0;
- s->vm_was_running = false;
+ s->vm_old_state = -1;
s->iteration_initial_bytes = 0;
s->threshold_size = 0;
}
@@ -2287,28 +2287,28 @@ static void migration_completion(MigrationState *s)
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_was_running = runstate_is_running();
- ret = global_state_store();
-
- if (!ret) {
- ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
- trace_migration_completion_vm_stop(ret);
- if (ret >= 0) {
- ret = migration_maybe_pause(s, &current_active_state,
- MIGRATION_STATUS_DEVICE);
- }
- if (ret >= 0) {
- /*
- * Inactivate disks except in COLO, and track that we
- * have done so in order to remember to reactivate
- * them if migration fails or is cancelled.
- */
- s->block_inactive = !migrate_colo();
- migration_rate_set(RATE_LIMIT_DISABLED);
- ret = qemu_savevm_state_complete_precopy(s->to_dst_file, false,
- s->block_inactive);
- }
+
+ s->vm_old_state = runstate_get();
+ global_state_store();
+
+ ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
+ trace_migration_completion_vm_stop(ret);
+ if (ret >= 0) {
+ ret = migration_maybe_pause(s, &current_active_state,
+ MIGRATION_STATUS_DEVICE);
+ }
+ if (ret >= 0) {
+ /*
+ * Inactivate disks except in COLO, and track that we
+ * have done so in order to remember to reactivate
+ * them if migration fails or is cancelled.
+ */
+ s->block_inactive = !migrate_colo();
+ migration_rate_set(RATE_LIMIT_DISABLED);
+ ret = qemu_savevm_state_complete_precopy(s->to_dst_file, false,
+ s->block_inactive);
}
+
qemu_mutex_unlock_iothread();
if (ret < 0) {
@@ -2400,13 +2400,6 @@ static void bg_migration_completion(MigrationState *s)
{
int current_active_state = s->state;
- /*
- * Stop tracking RAM writes - un-protect memory, un-register UFFD
- * memory ranges, flush kernel wait queues and wake up threads
- * waiting for write fault to be resolved.
- */
- ram_write_tracking_stop();
-
if (s->state == MIGRATION_STATUS_ACTIVE) {
/*
* By this moment we have RAM content saved into the migration stream.
@@ -2761,18 +2754,18 @@ static void migration_iteration_finish(MigrationState *s)
case MIGRATION_STATUS_COLO:
assert(migrate_colo());
migrate_start_colo_process(s);
- s->vm_was_running = true;
+ s->vm_old_state = RUN_STATE_RUNNING;
/* Fallthrough */
case MIGRATION_STATUS_FAILED:
case MIGRATION_STATUS_CANCELLED:
case MIGRATION_STATUS_CANCELLING:
- if (s->vm_was_running) {
+ if (s->vm_old_state == RUN_STATE_RUNNING) {
if (!runstate_check(RUN_STATE_SHUTDOWN)) {
vm_start();
}
} else {
if (runstate_check(RUN_STATE_FINISH_MIGRATE)) {
- runstate_set(RUN_STATE_POSTMIGRATE);
+ runstate_set(s->vm_old_state);
}
}
break;
@@ -2788,6 +2781,13 @@ static void migration_iteration_finish(MigrationState *s)
static void bg_migration_iteration_finish(MigrationState *s)
{
+ /*
+ * Stop tracking RAM writes - un-protect memory, un-register UFFD
+ * memory ranges, flush kernel wait queues and wake up threads
+ * waiting for write fault to be resolved.
+ */
+ ram_write_tracking_stop();
+
qemu_mutex_lock_iothread();
switch (s->state) {
case MIGRATION_STATUS_COMPLETED:
@@ -3086,11 +3086,9 @@ 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_was_running = runstate_is_running();
+ s->vm_old_state = runstate_get();
- if (global_state_store()) {
- goto fail;
- }
+ global_state_store();
/* Forcibly stop VM before saving state of vCPUs and devices */
if (vm_stop_force_state(RUN_STATE_PAUSED)) {
goto fail;
diff --git a/migration/migration.h b/migration/migration.h
index 48a46123a0..30c3e97635 100644
--- a/migration/migration.h
+++ b/migration/migration.h
@@ -25,6 +25,7 @@
#include "net/announce.h"
#include "qom/object.h"
#include "postcopy-ram.h"
+#include "sysemu/runstate.h"
struct PostcopyBlocktimeContext;
@@ -317,12 +318,14 @@ struct MigrationState {
int64_t expected_downtime;
bool capabilities[MIGRATION_CAPABILITY__MAX];
int64_t setup_time;
+
/*
- * Whether guest was running when we enter the completion stage.
+ * State before stopping the vm by vm_stop_force_state().
* If migration is interrupted by any reason, we need to continue
- * running the guest on source.
+ * running the guest on source if it was running or restore its stopped
+ * state.
*/
- bool vm_was_running;
+ RunState vm_old_state;
/* Flag set once the migration has been asked to enter postcopy */
bool start_postcopy;
diff --git a/migration/savevm.c b/migration/savevm.c
index 03795ce8dc..bc284087f9 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -2919,11 +2919,7 @@ bool save_snapshot(const char *name, bool overwrite, const char *vmstate,
saved_vm_running = runstate_is_running();
- ret = global_state_store();
- if (ret) {
- error_setg(errp, "Error saving global state");
- return false;
- }
+ global_state_store();
vm_stop(RUN_STATE_SAVE_VM);
bdrv_drain_all_begin();
diff --git a/softmmu/runstate.c b/softmmu/runstate.c
index 2f2396c819..1957caf73f 100644
--- a/softmmu/runstate.c
+++ b/softmmu/runstate.c
@@ -121,7 +121,13 @@ static const RunStateTransition runstate_transitions_def[] = {
{ RUN_STATE_FINISH_MIGRATE, RUN_STATE_PAUSED },
{ RUN_STATE_FINISH_MIGRATE, RUN_STATE_POSTMIGRATE },
{ RUN_STATE_FINISH_MIGRATE, RUN_STATE_PRELAUNCH },
- { RUN_STATE_FINISH_MIGRATE, RUN_STATE_COLO},
+ { RUN_STATE_FINISH_MIGRATE, RUN_STATE_COLO },
+ { RUN_STATE_FINISH_MIGRATE, RUN_STATE_INTERNAL_ERROR },
+ { RUN_STATE_FINISH_MIGRATE, RUN_STATE_IO_ERROR },
+ { RUN_STATE_FINISH_MIGRATE, RUN_STATE_SHUTDOWN },
+ { RUN_STATE_FINISH_MIGRATE, RUN_STATE_SUSPENDED },
+ { RUN_STATE_FINISH_MIGRATE, RUN_STATE_WATCHDOG },
+ { RUN_STATE_FINISH_MIGRATE, RUN_STATE_GUEST_PANICKED },
{ RUN_STATE_RESTORE_VM, RUN_STATE_RUNNING },
{ RUN_STATE_RESTORE_VM, RUN_STATE_PRELAUNCH },
@@ -175,18 +181,6 @@ bool runstate_check(RunState state)
return current_run_state == state;
}
-bool runstate_store(char *str, size_t size)
-{
- const char *state = RunState_str(current_run_state);
- size_t len = strlen(state) + 1;
-
- if (len > size) {
- return false;
- }
- memcpy(str, state, len);
- return true;
-}
-
static void runstate_init(void)
{
const RunStateTransition *p;
@@ -221,6 +215,11 @@ void runstate_set(RunState new_state)
current_run_state = new_state;
}
+RunState runstate_get(void)
+{
+ return current_run_state;
+}
+
bool runstate_is_running(void)
{
return runstate_check(RUN_STATE_RUNNING);