diff mbox

[v5,42/45] postcopy: Wire up loadvm_postcopy_handle_{run, end} commands

Message ID 1424883128-9841-43-git-send-email-dgilbert@redhat.com
State New
Headers show

Commit Message

Dr. David Alan Gilbert Feb. 25, 2015, 4:52 p.m. UTC
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>

Wire up more of the handlers for the commands on the destination side,
in particular loadvm_postcopy_handle_run now has enough to start the
guest running.

handle_end has to wait for the main thread to finish.

Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
---
 include/migration/migration.h |  6 +++++
 migration/migration.c         |  2 ++
 savevm.c                      | 56 ++++++++++++++++++++++++++++++++++++++-----
 trace-events                  |  4 +++-
 4 files changed, 61 insertions(+), 7 deletions(-)
diff mbox

Patch

diff --git a/include/migration/migration.h b/include/migration/migration.h
index c2af2ef..02376df 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -86,6 +86,12 @@  struct MigrationIncomingState {
 
     PostcopyState postcopy_state;
 
+    /*
+     * Free at the start of the main state load, set as the main thread finishes
+     * loading state.
+     */
+    QemuEvent      main_thread_load_event;
+
     bool           have_fault_thread;
     QemuThread     fault_thread;
     QemuSemaphore  fault_thread_sem;
diff --git a/migration/migration.c b/migration/migration.c
index c108851..97b86cc 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -84,6 +84,7 @@  MigrationIncomingState *migration_incoming_state_new(QEMUFile* f)
     mis_current->file = f;
     QLIST_INIT(&mis_current->loadvm_handlers);
     qemu_mutex_init(&mis_current->rp_mutex);
+    qemu_event_init(&mis_current->main_thread_load_event, false);
 
     return mis_current;
 }
@@ -91,6 +92,7 @@  MigrationIncomingState *migration_incoming_state_new(QEMUFile* f)
 void migration_incoming_state_destroy(void)
 {
     postcopy_pmi_destroy(mis_current);
+    qemu_event_destroy(&mis_current->main_thread_load_event);
     loadvm_free_handlers(mis_current);
     g_free(mis_current);
     mis_current = NULL;
diff --git a/savevm.c b/savevm.c
index eb22410..45d46db 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1396,12 +1396,34 @@  static int loadvm_postcopy_handle_listen(MigrationIncomingState *mis)
 static int loadvm_postcopy_handle_run(MigrationIncomingState *mis)
 {
     PostcopyState ps = postcopy_state_set(mis, POSTCOPY_INCOMING_RUNNING);
+    Error *local_err = NULL;
+
     trace_loadvm_postcopy_handle_run();
     if (ps != POSTCOPY_INCOMING_LISTENING) {
         error_report("CMD_POSTCOPY_RUN in wrong postcopy state (%d)", ps);
         return -1;
     }
 
+    /* TODO we should move all of this lot into postcopy_ram.c or a shared code
+     * in migration.c
+     */
+    cpu_synchronize_all_post_init();
+
+    qemu_announce_self();
+
+    /* Make sure all file formats flush their mutable metadata */
+    bdrv_invalidate_cache_all(&local_err);
+    if (local_err) {
+        qerror_report_err(local_err);
+        error_free(local_err);
+        return -1;
+    }
+
+    trace_loadvm_postcopy_handle_run_cpu_sync();
+    cpu_synchronize_all_post_init();
+
+    trace_loadvm_postcopy_handle_run_vmstart();
+
     if (autostart) {
         /* Hold onto your hats, starting the CPU */
         vm_start();
@@ -1410,19 +1432,40 @@  static int loadvm_postcopy_handle_run(MigrationIncomingState *mis)
         runstate_set(RUN_STATE_PAUSED);
     }
 
-    return 0;
+    return LOADVM_QUIT_LOOP;
 }
 
-/* The end - with a byte from the source which can tell us to fail. */
-static int loadvm_postcopy_handle_end(MigrationIncomingState *mis)
+/* The end - with a byte from the source which can tell us to fail.
+ * The source sends this either if there is a failure, or if it believes it's
+ * sent everything
+ */
+static int loadvm_postcopy_handle_end(MigrationIncomingState *mis,
+                                          uint8_t status)
 {
     PostcopyState ps = postcopy_state_get(mis);
-    trace_loadvm_postcopy_handle_end();
+    trace_loadvm_postcopy_handle_end(status);
     if (ps == POSTCOPY_INCOMING_NONE) {
         error_report("CMD_POSTCOPY_END in wrong postcopy state (%d)", ps);
         return -1;
     }
-    return -1; /* TODO - expecting 1 byte good/fail */
+
+    if (!status) {
+        /*
+         * This looks good, but it's possible that the device loading in the
+         * main thread hasn't finished yet, and so we might not be in 'RUN'
+         * state yet; wait for the end of the main thread.
+         */
+        qemu_event_wait(&mis->main_thread_load_event);
+    }
+
+    if (status) {
+        error_report("CMD_POSTCOPY_END: error on source host (%d)",
+                     status);
+        qemu_file_set_error(mis->file, -EPIPE);
+    }
+
+    /* This will cause the listen thread to exit and call cleanup */
+    return LOADVM_QUIT_LOOP;
 }
 
 static int loadvm_process_command_simple_lencheck(const char *name,
@@ -1566,7 +1609,7 @@  static int loadvm_process_command(QEMUFile *f)
                                                    len, 1)) {
             return -1;
         }
-        return loadvm_postcopy_handle_end(mis);
+        return loadvm_postcopy_handle_end(mis, qemu_get_byte(f));
 
     case MIG_CMD_POSTCOPY_RAM_DISCARD:
         return loadvm_postcopy_ram_handle_discard(mis, len);
@@ -1730,6 +1773,7 @@  int qemu_loadvm_state(QEMUFile *f)
     }
 
     ret = qemu_loadvm_state_main(f, mis);
+    qemu_event_set(&mis->main_thread_load_event);
 
     trace_qemu_loadvm_state_post_main(ret);
     if (mis->have_listen_thread) {
diff --git a/trace-events b/trace-events
index 82b3631..869988b 100644
--- a/trace-events
+++ b/trace-events
@@ -1176,9 +1176,11 @@  loadvm_handle_cmd_packaged(unsigned int length) "%u"
 loadvm_handle_cmd_packaged_main(int ret) "%d"
 loadvm_handle_cmd_packaged_received(int ret) "%d"
 loadvm_postcopy_handle_advise(void) ""
-loadvm_postcopy_handle_end(void) ""
+loadvm_postcopy_handle_end(uint8_t status) "%d"
 loadvm_postcopy_handle_listen(void) ""
 loadvm_postcopy_handle_run(void) ""
+loadvm_postcopy_handle_run_cpu_sync(void) ""
+loadvm_postcopy_handle_run_vmstart(void) ""
 loadvm_postcopy_ram_handle_discard(void) ""
 loadvm_postcopy_ram_handle_discard_end(void) ""
 loadvm_process_command(uint16_t com, uint16_t len) "com=0x%x len=%d"