X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/d94c426d46e01ad45fc5e3b8e5b485ca1b0158fe..31db5b3638553e616eba3391dbff88f77b8a5bc9:/migration.c diff --git a/migration.c b/migration.c index 1402fa7680..7235c23ffe 100644 --- a/migration.c +++ b/migration.c @@ -14,6 +14,7 @@ */ #include "qemu-common.h" +#include "qemu/main-loop.h" #include "migration/migration.h" #include "monitor/monitor.h" #include "migration/qemu-file.h" @@ -39,6 +40,7 @@ enum { MIG_STATE_ERROR = -1, MIG_STATE_NONE, MIG_STATE_SETUP, + MIG_STATE_CANCELLING, MIG_STATE_CANCELLED, MIG_STATE_ACTIVE, MIG_STATE_COMPLETED, @@ -149,6 +151,7 @@ MigrationCapabilityStatusList *qmp_query_migrate_capabilities(Error **errp) MigrationState *s = migrate_get_current(); int i; + caps = NULL; /* silence compiler warning */ for (i = 0; i < MIGRATION_CAPABILITY_MAX; i++) { if (head == NULL) { head = g_malloc0(sizeof(*caps)); @@ -194,10 +197,11 @@ MigrationInfo *qmp_query_migrate(Error **errp) info->has_total_time = false; break; case MIG_STATE_ACTIVE: + case MIG_STATE_CANCELLING: info->has_status = true; info->status = g_strdup("active"); info->has_total_time = true; - info->total_time = qemu_get_clock_ms(rt_clock) + info->total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) - s->total_time; info->has_expected_downtime = true; info->expected_downtime = s->expected_downtime; @@ -280,6 +284,13 @@ void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params, /* shared migration helpers */ +static void migrate_set_state(MigrationState *s, int old_state, int new_state) +{ + if (atomic_cmpxchg(&s->state, old_state, new_state) == new_state) { + trace_migrate_set_state(new_state); + } +} + static void migrate_fd_cleanup(void *opaque) { MigrationState *s = opaque; @@ -301,18 +312,14 @@ static void migrate_fd_cleanup(void *opaque) if (s->state != MIG_STATE_COMPLETED) { qemu_savevm_state_cancel(); + if (s->state == MIG_STATE_CANCELLING) { + migrate_set_state(s, MIG_STATE_CANCELLING, MIG_STATE_CANCELLED); + } } notifier_list_notify(&migration_state_notifiers, s); } -static void migrate_set_state(MigrationState *s, int old_state, int new_state) -{ - if (atomic_cmpxchg(&s->state, old_state, new_state) == new_state) { - trace_migrate_set_state(new_state); - } -} - void migrate_fd_error(MigrationState *s) { DPRINTF("setting error state\n"); @@ -324,9 +331,16 @@ void migrate_fd_error(MigrationState *s) static void migrate_fd_cancel(MigrationState *s) { + int old_state ; DPRINTF("cancelling migration\n"); - migrate_set_state(s, s->state, MIG_STATE_CANCELLED); + do { + old_state = s->state; + if (old_state != MIG_STATE_SETUP && old_state != MIG_STATE_ACTIVE) { + break; + } + migrate_set_state(s, old_state, MIG_STATE_CANCELLING); + } while (s->state != MIG_STATE_CANCELLING); } void add_migration_state_change_notifier(Notifier *notify) @@ -375,7 +389,7 @@ static MigrationState *migrate_init(const MigrationParams *params) s->state = MIG_STATE_SETUP; trace_migrate_set_state(MIG_STATE_SETUP); - s->total_time = qemu_get_clock_ms(rt_clock); + s->total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); return s; } @@ -403,7 +417,8 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, params.blk = has_blk && blk; params.shared = has_inc && inc; - if (s->state == MIG_STATE_ACTIVE || s->state == MIG_STATE_SETUP) { + if (s->state == MIG_STATE_ACTIVE || s->state == MIG_STATE_SETUP || + s->state == MIG_STATE_CANCELLING) { error_set(errp, QERR_MIGRATION_ACTIVE); return; } @@ -435,6 +450,7 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, #endif } else { error_set(errp, QERR_INVALID_PARAMETER_VALUE, "uri", "a valid migration protocol"); + s->state = MIG_STATE_ERROR; return; } @@ -544,8 +560,8 @@ int64_t migrate_xbzrle_cache_size(void) static void *migration_thread(void *opaque) { MigrationState *s = opaque; - int64_t initial_time = qemu_get_clock_ms(rt_clock); - int64_t setup_start = qemu_get_clock_ms(host_clock); + int64_t initial_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); + int64_t setup_start = qemu_clock_get_ms(QEMU_CLOCK_HOST); int64_t initial_bytes = 0; int64_t max_size = 0; int64_t start_time = initial_time; @@ -554,7 +570,7 @@ static void *migration_thread(void *opaque) DPRINTF("beginning savevm\n"); qemu_savevm_state_begin(s->file, &s->params); - s->setup_time = qemu_get_clock_ms(host_clock) - setup_start; + s->setup_time = qemu_clock_get_ms(QEMU_CLOCK_HOST) - setup_start; migrate_set_state(s, MIG_STATE_SETUP, MIG_STATE_ACTIVE); DPRINTF("setup complete\n"); @@ -566,7 +582,8 @@ static void *migration_thread(void *opaque) if (!qemu_file_rate_limit(s->file)) { DPRINTF("iterate\n"); pending_size = qemu_savevm_state_pending(s->file, max_size); - DPRINTF("pending size %lu max %lu\n", pending_size, max_size); + DPRINTF("pending size %" PRIu64 " max %" PRIu64 "\n", + pending_size, max_size); if (pending_size && pending_size >= max_size) { qemu_savevm_state_iterate(s->file); } else { @@ -574,13 +591,13 @@ static void *migration_thread(void *opaque) DPRINTF("done iterating\n"); qemu_mutex_lock_iothread(); - start_time = qemu_get_clock_ms(rt_clock); + start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); old_vm_running = runstate_is_running(); ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE); if (ret >= 0) { - qemu_file_set_rate_limit(s->file, INT_MAX); + qemu_file_set_rate_limit(s->file, INT64_MAX); qemu_savevm_state_complete(s->file); } qemu_mutex_unlock_iothread(); @@ -601,7 +618,7 @@ static void *migration_thread(void *opaque) migrate_set_state(s, MIG_STATE_ACTIVE, MIG_STATE_ERROR); break; } - current_time = qemu_get_clock_ms(rt_clock); + current_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); if (current_time >= initial_time + BUFFER_DELAY) { uint64_t transferred_bytes = qemu_ftell(s->file) - initial_bytes; uint64_t time_spent = current_time - initial_time; @@ -632,7 +649,7 @@ static void *migration_thread(void *opaque) qemu_mutex_lock_iothread(); if (s->state == MIG_STATE_COMPLETED) { - int64_t end_time = qemu_get_clock_ms(rt_clock); + int64_t end_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); s->total_time = end_time - s->total_time; s->downtime = end_time - start_time; runstate_set(RUN_STATE_POSTMIGRATE);