diff options
Diffstat (limited to 'migration/savevm.c')
-rw-r--r-- | migration/savevm.c | 46 |
1 files changed, 33 insertions, 13 deletions
diff --git a/migration/savevm.c b/migration/savevm.c index 1599b02fbc..967ff80547 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -1863,7 +1863,7 @@ static void *postcopy_ram_listen_thread(void *opaque) migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE, MIGRATION_STATUS_POSTCOPY_ACTIVE); - qemu_sem_post(&mis->listen_thread_sem); + qemu_sem_post(&mis->thread_sync_sem); trace_postcopy_ram_listen_thread_start(); rcu_register_thread(); @@ -1948,9 +1948,10 @@ static void *postcopy_ram_listen_thread(void *opaque) static int loadvm_postcopy_handle_listen(MigrationIncomingState *mis) { PostcopyState ps = postcopy_state_set(POSTCOPY_INCOMING_LISTENING); - trace_loadvm_postcopy_handle_listen(); Error *local_err = NULL; + trace_loadvm_postcopy_handle_listen("enter"); + if (ps != POSTCOPY_INCOMING_ADVISE && ps != POSTCOPY_INCOMING_DISCARD) { error_report("CMD_POSTCOPY_LISTEN in wrong postcopy state (%d)", ps); return -1; @@ -1965,6 +1966,8 @@ static int loadvm_postcopy_handle_listen(MigrationIncomingState *mis) } } + trace_loadvm_postcopy_handle_listen("after discard"); + /* * Sensitise RAM - can now generate requests for blocks that don't exist * However, at this point the CPU shouldn't be running, and the IO @@ -1977,19 +1980,17 @@ static int loadvm_postcopy_handle_listen(MigrationIncomingState *mis) } } + trace_loadvm_postcopy_handle_listen("after uffd"); + if (postcopy_notify(POSTCOPY_NOTIFY_INBOUND_LISTEN, &local_err)) { error_report_err(local_err); return -1; } mis->have_listen_thread = true; - /* Start up the listening thread and wait for it to signal ready */ - qemu_sem_init(&mis->listen_thread_sem, 0); - qemu_thread_create(&mis->listen_thread, "postcopy/listen", - postcopy_ram_listen_thread, NULL, - QEMU_THREAD_DETACHED); - qemu_sem_wait(&mis->listen_thread_sem); - qemu_sem_destroy(&mis->listen_thread_sem); + postcopy_thread_create(mis, &mis->listen_thread, "postcopy/listen", + postcopy_ram_listen_thread, QEMU_THREAD_DETACHED); + trace_loadvm_postcopy_handle_listen("return"); return 0; } @@ -1999,13 +2000,19 @@ static void loadvm_postcopy_handle_run_bh(void *opaque) Error *local_err = NULL; MigrationIncomingState *mis = opaque; + trace_loadvm_postcopy_handle_run_bh("enter"); + /* TODO we should move all of this lot into postcopy_ram.c or a shared code * in migration.c */ cpu_synchronize_all_post_init(); + trace_loadvm_postcopy_handle_run_bh("after cpu sync"); + qemu_announce_self(&mis->announce_timer, migrate_announce_params()); + trace_loadvm_postcopy_handle_run_bh("after announce"); + /* Make sure all file formats flush their mutable metadata. * If we get an error here, just don't restart the VM yet. */ bdrv_invalidate_cache_all(&local_err); @@ -2015,9 +2022,7 @@ static void loadvm_postcopy_handle_run_bh(void *opaque) autostart = false; } - trace_loadvm_postcopy_handle_run_cpu_sync(); - - trace_loadvm_postcopy_handle_run_vmstart(); + trace_loadvm_postcopy_handle_run_bh("after invalidate cache"); dirty_bitmap_mig_before_vm_start(); @@ -2030,6 +2035,8 @@ static void loadvm_postcopy_handle_run_bh(void *opaque) } qemu_bh_delete(mis->bh); + + trace_loadvm_postcopy_handle_run_bh("return"); } /* After all discards we can start running and asking for pages */ @@ -2273,12 +2280,13 @@ static int loadvm_process_command(QEMUFile *f) return qemu_file_get_error(f); } - trace_loadvm_process_command(cmd, len); if (cmd >= MIG_CMD_MAX || cmd == MIG_CMD_INVALID) { error_report("MIG_CMD 0x%x unknown (len 0x%x)", cmd, len); return -EINVAL; } + trace_loadvm_process_command(mig_cmd_args[cmd].name, len); + if (mig_cmd_args[cmd].len != -1 && mig_cmd_args[cmd].len != len) { error_report("%s received with bad length - expecting %zu, got %d", mig_cmd_args[cmd].name, @@ -2565,6 +2573,18 @@ void qemu_loadvm_state_cleanup(void) /* Return true if we should continue the migration, or false. */ static bool postcopy_pause_incoming(MigrationIncomingState *mis) { + int i; + + /* + * If network is interrupted, any temp page we received will be useless + * because we didn't mark them as "received" in receivedmap. After a + * proper recovery later (which will sync src dirty bitmap with receivedmap + * on dest) these cached small pages will be resent again. + */ + for (i = 0; i < mis->postcopy_channels; i++) { + postcopy_temp_page_reset(&mis->postcopy_tmp_pages[i]); + } + trace_postcopy_pause_incoming(); assert(migrate_postcopy_ram()); |