summaryrefslogtreecommitdiffstats
path: root/migration/savevm.c
diff options
context:
space:
mode:
Diffstat (limited to 'migration/savevm.c')
-rw-r--r--migration/savevm.c46
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());