From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Stefan Reiter Date: Wed, 8 Apr 2020 15:29:03 +0200 Subject: [PATCH] PVE: savevm-async: set up migration state code mostly adapted from upstream savevm.c Signed-off-by: Stefan Reiter --- savevm-async.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/savevm-async.c b/savevm-async.c index 790e27ae37..a38b15d652 100644 --- a/savevm-async.c +++ b/savevm-async.c @@ -225,6 +225,7 @@ static void *process_savevm_thread(void *opaque) { int ret; int64_t maxlen; + MigrationState *ms = migrate_get_current(); rcu_register_thread(); @@ -234,8 +235,7 @@ static void *process_savevm_thread(void *opaque) if (ret < 0) { save_snapshot_error("qemu_savevm_state_setup failed"); - rcu_unregister_thread(); - return NULL; + goto out; } while (snap_state.state == SAVE_STATE_ACTIVE) { @@ -287,6 +287,12 @@ static void *process_savevm_thread(void *opaque) qemu_bh_schedule(snap_state.cleanup_bh); qemu_mutex_unlock_iothread(); +out: + /* set migration state accordingly and clear soon-to-be stale file */ + migrate_set_state(&ms->state, MIGRATION_STATUS_SETUP, + ret ? MIGRATION_STATUS_FAILED : MIGRATION_STATUS_COMPLETED); + ms->to_dst_file = NULL; + rcu_unregister_thread(); return NULL; } @@ -294,6 +300,7 @@ static void *process_savevm_thread(void *opaque) void qmp_savevm_start(bool has_statefile, const char *statefile, Error **errp) { Error *local_err = NULL; + MigrationState *ms = migrate_get_current(); int bdrv_oflags = BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_NO_FLUSH; @@ -303,6 +310,17 @@ void qmp_savevm_start(bool has_statefile, const char *statefile, Error **errp) return; } + if (migration_is_running(ms->state)) { + error_set(errp, ERROR_CLASS_GENERIC_ERROR, QERR_MIGRATION_ACTIVE); + return; + } + + if (migrate_use_block()) { + error_set(errp, ERROR_CLASS_GENERIC_ERROR, + "Block migration and snapshots are incompatible"); + return; + } + /* initialize snapshot info */ snap_state.saved_vm_running = runstate_is_running(); snap_state.bs_pos = 0; @@ -341,6 +359,14 @@ void qmp_savevm_start(bool has_statefile, const char *statefile, Error **errp) goto restart; } + /* + * qemu_savevm_* paths use migration code and expect a migration state. + * State is cleared in process_savevm_thread, but has to be initialized + * here (blocking main thread, from QMP) to avoid race conditions. + */ + migrate_init(ms); + memset(&ram_counters, 0, sizeof(ram_counters)); + ms->to_dst_file = snap_state.file; error_setg(&snap_state.blocker, "block device is in use by savevm"); blk_op_block_all(snap_state.target, snap_state.blocker);