X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=migration.c;h=2b1ab20c54f9e93630dd85102a1c8466058fdc6a;hb=8b7acc79b9adb4dda6cc867b90e3a1e873f4f7e8;hp=fcdcf6196ad697a357c8125262eca1bc1cd7b345;hpb=d58f574bf39796ed2396dfd1e308352fbb03f944;p=qemu.git diff --git a/migration.c b/migration.c index fcdcf6196..2b1ab20c5 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" @@ -36,7 +37,8 @@ #endif enum { - MIG_STATE_ERROR, + MIG_STATE_ERROR = -1, + MIG_STATE_NONE, MIG_STATE_SETUP, MIG_STATE_CANCELLED, MIG_STATE_ACTIVE, @@ -63,7 +65,7 @@ static NotifierList migration_state_notifiers = MigrationState *migrate_get_current(void) { static MigrationState current_migration = { - .state = MIG_STATE_SETUP, + .state = MIG_STATE_NONE, .bandwidth_limit = MAX_THROTTLE, .xbzrle_cache_size = DEFAULT_MIGRATE_CACHE_SIZE, .mbps = -1, @@ -148,6 +150,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)); @@ -184,17 +187,24 @@ MigrationInfo *qmp_query_migrate(Error **errp) MigrationState *s = migrate_get_current(); switch (s->state) { - case MIG_STATE_SETUP: + case MIG_STATE_NONE: /* no migration has happened ever */ break; + case MIG_STATE_SETUP: + info->has_status = true; + info->status = g_strdup("setup"); + info->has_total_time = false; + break; case MIG_STATE_ACTIVE: 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; + info->has_setup_time = true; + info->setup_time = s->setup_time; info->has_ram = true; info->ram = g_malloc0(sizeof(*info->ram)); @@ -223,9 +233,12 @@ MigrationInfo *qmp_query_migrate(Error **errp) info->has_status = true; info->status = g_strdup("completed"); + info->has_total_time = true; info->total_time = s->total_time; info->has_downtime = true; info->downtime = s->downtime; + info->has_setup_time = true; + info->setup_time = s->setup_time; info->has_ram = true; info->ram = g_malloc0(sizeof(*info->ram)); @@ -257,7 +270,7 @@ void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params, MigrationState *s = migrate_get_current(); MigrationCapabilityStatusList *cap; - if (s->state == MIG_STATE_ACTIVE) { + if (s->state == MIG_STATE_ACTIVE || s->state == MIG_STATE_SETUP) { error_set(errp, QERR_MIGRATION_ACTIVE); return; } @@ -328,9 +341,9 @@ void remove_migration_state_change_notifier(Notifier *notify) notifier_remove(notify); } -bool migration_is_active(MigrationState *s) +bool migration_in_setup(MigrationState *s) { - return s->state == MIG_STATE_ACTIVE; + return s->state == MIG_STATE_SETUP; } bool migration_has_finished(MigrationState *s) @@ -364,7 +377,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; } @@ -389,10 +402,10 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, MigrationParams params; const char *p; - params.blk = blk; - params.shared = inc; + params.blk = has_blk && blk; + params.shared = has_inc && inc; - if (s->state == MIG_STATE_ACTIVE) { + if (s->state == MIG_STATE_ACTIVE || s->state == MIG_STATE_SETUP) { error_set(errp, QERR_MIGRATION_ACTIVE); return; } @@ -533,7 +546,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 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; @@ -542,6 +556,11 @@ static void *migration_thread(void *opaque) DPRINTF("beginning savevm\n"); qemu_savevm_state_begin(s->file, &s->params); + 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"); + while (s->state == MIG_STATE_ACTIVE) { int64_t current_time; uint64_t pending_size; @@ -549,7 +568,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 { @@ -557,7 +577,7 @@ 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(); @@ -584,7 +604,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; @@ -615,7 +635,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); @@ -632,8 +652,8 @@ static void *migration_thread(void *opaque) void migrate_fd_connect(MigrationState *s) { - s->state = MIG_STATE_ACTIVE; - trace_migrate_set_state(MIG_STATE_ACTIVE); + s->state = MIG_STATE_SETUP; + trace_migrate_set_state(MIG_STATE_SETUP); /* This is a best 1st approximation. ns to ms */ s->expected_downtime = max_downtime/1000000; @@ -642,7 +662,9 @@ void migrate_fd_connect(MigrationState *s) qemu_file_set_rate_limit(s->file, s->bandwidth_limit / XFER_LIMIT_RATIO); + /* Notify before starting migration thread */ + notifier_list_notify(&migration_state_notifiers, s); + qemu_thread_create(&s->thread, migration_thread, s, QEMU_THREAD_JOINABLE); - notifier_list_notify(&migration_state_notifiers, s); }