summary refs log tree commit diff stats
path: root/migration
diff options
context:
space:
mode:
Diffstat (limited to 'migration')
-rw-r--r--migration/Makefile.objs2
-rw-r--r--migration/block.c3
-rw-r--r--migration/channel.c7
-rw-r--r--migration/channel.h3
-rw-r--r--migration/colo-comm.c2
-rw-r--r--migration/colo.c2
-rw-r--r--migration/exec.c4
-rw-r--r--migration/fd.c4
-rw-r--r--migration/global_state.c140
-rw-r--r--migration/migration.c226
-rw-r--r--migration/migration.h164
-rw-r--r--migration/postcopy-ram.c2
-rw-r--r--migration/qemu-file.c2
-rw-r--r--migration/qemu-file.h17
-rw-r--r--migration/ram.c3
-rw-r--r--migration/rdma.c2
-rw-r--r--migration/savevm.c5
-rw-r--r--migration/savevm.h15
-rw-r--r--migration/socket.c5
-rw-r--r--migration/tls.c4
-rw-r--r--migration/trace-events4
-rw-r--r--migration/vmstate-types.c2
-rw-r--r--migration/vmstate.c3
23 files changed, 420 insertions, 201 deletions
diff --git a/migration/Makefile.objs b/migration/Makefile.objs
index 90f8c1f177..1c7770da46 100644
--- a/migration/Makefile.objs
+++ b/migration/Makefile.objs
@@ -2,7 +2,7 @@ common-obj-y += migration.o socket.o fd.o exec.o
 common-obj-y += tls.o channel.o savevm.o
 common-obj-y += colo-comm.o colo.o colo-failover.o
 common-obj-y += vmstate.o vmstate-types.o page_cache.o
-common-obj-y += qemu-file.o
+common-obj-y += qemu-file.o global_state.o
 common-obj-y += qemu-file-channel.o
 common-obj-y += xbzrle.o postcopy-ram.o
 common-obj-y += qjson.o
diff --git a/migration/block.c b/migration/block.c
index 114cedbfd0..ae06975199 100644
--- a/migration/block.c
+++ b/migration/block.c
@@ -25,7 +25,8 @@
 #include "qemu/timer.h"
 #include "block.h"
 #include "migration/misc.h"
-#include "migration/migration.h"
+#include "migration.h"
+#include "migration/register.h"
 #include "sysemu/blockdev.h"
 #include "qemu-file.h"
 #include "migration/vmstate.h"
diff --git a/migration/channel.c b/migration/channel.c
index eae1d9e28a..3b7252f5a2 100644
--- a/migration/channel.c
+++ b/migration/channel.c
@@ -13,15 +13,16 @@
 #include "qemu/osdep.h"
 #include "channel.h"
 #include "tls.h"
-#include "migration/migration.h"
+#include "migration.h"
 #include "qemu-file-channel.h"
 #include "trace.h"
 #include "qapi/error.h"
 #include "io/channel-tls.h"
 
-void migration_channel_process_incoming(MigrationState *s,
-                                        QIOChannel *ioc)
+void migration_channel_process_incoming(QIOChannel *ioc)
 {
+    MigrationState *s = migrate_get_current();
+
     trace_migration_set_incoming_channel(
         ioc, object_get_typename(OBJECT(ioc)));
 
diff --git a/migration/channel.h b/migration/channel.h
index 2e0a7e33cc..e4b40579a1 100644
--- a/migration/channel.h
+++ b/migration/channel.h
@@ -18,8 +18,7 @@
 
 #include "io/channel.h"
 
-void migration_channel_process_incoming(MigrationState *s,
-                                        QIOChannel *ioc);
+void migration_channel_process_incoming(QIOChannel *ioc);
 
 void migration_channel_connect(MigrationState *s,
                                QIOChannel *ioc,
diff --git a/migration/colo-comm.c b/migration/colo-comm.c
index 8bfdf6825a..b61aa19a38 100644
--- a/migration/colo-comm.c
+++ b/migration/colo-comm.c
@@ -12,7 +12,7 @@
  */
 
 #include "qemu/osdep.h"
-#include "migration/migration.h"
+#include "migration.h"
 #include "migration/colo.h"
 #include "migration/vmstate.h"
 #include "trace.h"
diff --git a/migration/colo.c b/migration/colo.c
index 111b715546..45e9b46289 100644
--- a/migration/colo.c
+++ b/migration/colo.c
@@ -14,7 +14,7 @@
 #include "qemu/timer.h"
 #include "sysemu/sysemu.h"
 #include "qemu-file-channel.h"
-#include "migration/migration.h"
+#include "migration.h"
 #include "qemu-file.h"
 #include "savevm.h"
 #include "migration/colo.h"
diff --git a/migration/exec.c b/migration/exec.c
index 9077024286..b1de44543a 100644
--- a/migration/exec.c
+++ b/migration/exec.c
@@ -22,7 +22,7 @@
 #include "qemu-common.h"
 #include "channel.h"
 #include "exec.h"
-#include "migration/migration.h"
+#include "migration.h"
 #include "io/channel-command.h"
 #include "trace.h"
 
@@ -49,7 +49,7 @@ static gboolean exec_accept_incoming_migration(QIOChannel *ioc,
                                                GIOCondition condition,
                                                gpointer opaque)
 {
-    migration_channel_process_incoming(migrate_get_current(), ioc);
+    migration_channel_process_incoming(ioc);
     object_unref(OBJECT(ioc));
     return FALSE; /* unregister */
 }
diff --git a/migration/fd.c b/migration/fd.c
index 0077a505a3..b2384bf133 100644
--- a/migration/fd.c
+++ b/migration/fd.c
@@ -19,7 +19,7 @@
 #include "qemu-common.h"
 #include "channel.h"
 #include "fd.h"
-#include "migration/migration.h"
+#include "migration.h"
 #include "monitor/monitor.h"
 #include "io/channel-util.h"
 #include "trace.h"
@@ -49,7 +49,7 @@ static gboolean fd_accept_incoming_migration(QIOChannel *ioc,
                                              GIOCondition condition,
                                              gpointer opaque)
 {
-    migration_channel_process_incoming(migrate_get_current(), ioc);
+    migration_channel_process_incoming(ioc);
     object_unref(OBJECT(ioc));
     return FALSE; /* unregister */
 }
diff --git a/migration/global_state.c b/migration/global_state.c
new file mode 100644
index 0000000000..16ac63fb92
--- /dev/null
+++ b/migration/global_state.c
@@ -0,0 +1,140 @@
+/*
+ * Global State configuration
+ *
+ * Copyright (c) 2014-2017 Red Hat Inc
+ *
+ * Authors:
+ *  Juan Quintela <quintela@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/cutils.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+#include "qapi/util.h"
+#include "migration/global_state.h"
+#include "migration/vmstate.h"
+#include "sysemu/sysemu.h"
+#include "trace.h"
+
+typedef struct {
+    bool optional;
+    uint32_t size;
+    uint8_t runstate[100];
+    RunState state;
+    bool received;
+} GlobalState;
+
+static GlobalState global_state;
+
+int global_state_store(void)
+{
+    if (!runstate_store((char *)global_state.runstate,
+                        sizeof(global_state.runstate))) {
+        error_report("runstate name too big: %s", global_state.runstate);
+        trace_migrate_state_too_big();
+        return -EINVAL;
+    }
+    return 0;
+}
+
+void global_state_store_running(void)
+{
+    const char *state = RunState_lookup[RUN_STATE_RUNNING];
+    strncpy((char *)global_state.runstate,
+           state, sizeof(global_state.runstate));
+}
+
+bool global_state_received(void)
+{
+    return global_state.received;
+}
+
+RunState global_state_get_runstate(void)
+{
+    return global_state.state;
+}
+
+void global_state_set_optional(void)
+{
+    global_state.optional = true;
+}
+
+static bool global_state_needed(void *opaque)
+{
+    GlobalState *s = opaque;
+    char *runstate = (char *)s->runstate;
+
+    /* If it is not optional, it is mandatory */
+
+    if (s->optional == false) {
+        return true;
+    }
+
+    /* If state is running or paused, it is not needed */
+
+    if (strcmp(runstate, "running") == 0 ||
+        strcmp(runstate, "paused") == 0) {
+        return false;
+    }
+
+    /* for any other state it is needed */
+    return true;
+}
+
+static int global_state_post_load(void *opaque, int version_id)
+{
+    GlobalState *s = opaque;
+    Error *local_err = NULL;
+    int r;
+    char *runstate = (char *)s->runstate;
+
+    s->received = true;
+    trace_migrate_global_state_post_load(runstate);
+
+    r = qapi_enum_parse(RunState_lookup, runstate, RUN_STATE__MAX,
+                                -1, &local_err);
+
+    if (r == -1) {
+        if (local_err) {
+            error_report_err(local_err);
+        }
+        return -EINVAL;
+    }
+    s->state = r;
+
+    return 0;
+}
+
+static void global_state_pre_save(void *opaque)
+{
+    GlobalState *s = opaque;
+
+    trace_migrate_global_state_pre_save((char *)s->runstate);
+    s->size = strlen((char *)s->runstate) + 1;
+}
+
+static const VMStateDescription vmstate_globalstate = {
+    .name = "globalstate",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .post_load = global_state_post_load,
+    .pre_save = global_state_pre_save,
+    .needed = global_state_needed,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(size, GlobalState),
+        VMSTATE_BUFFER(runstate, GlobalState),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+void register_global_state(void)
+{
+    /* We would use it independently that we receive it */
+    strcpy((char *)&global_state.runstate, "");
+    global_state.received = false;
+    vmstate_register(NULL, 0, &vmstate_globalstate, &global_state);
+}
diff --git a/migration/migration.c b/migration/migration.c
index fc95acbde6..8ef6d6c412 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -23,7 +23,9 @@
 #include "socket.h"
 #include "rdma.h"
 #include "ram.h"
-#include "migration/migration.h"
+#include "migration/global_state.h"
+#include "migration/misc.h"
+#include "migration.h"
 #include "savevm.h"
 #include "qemu-file-channel.h"
 #include "qemu-file.h"
@@ -86,6 +88,18 @@ static NotifierList migration_state_notifiers =
 
 static bool deferred_incoming;
 
+/* Messages sent on the return path from destination to source */
+enum mig_rp_message_type {
+    MIG_RP_MSG_INVALID = 0,  /* Must be 0 */
+    MIG_RP_MSG_SHUT,         /* sibling will not send any more RP messages */
+    MIG_RP_MSG_PONG,         /* Response to a PING; data (seq: be32 ) */
+
+    MIG_RP_MSG_REQ_PAGES_ID, /* data (start: be64, len: be32, id: string) */
+    MIG_RP_MSG_REQ_PAGES,    /* data (start: be64, len: be32) */
+
+    MIG_RP_MSG_MAX
+};
+
 /* When we add fault tolerance, we could have several
    migrations at once.  For now we don't need to add
    dynamic creation of migration */
@@ -152,126 +166,6 @@ void migration_incoming_state_destroy(void)
     qemu_event_destroy(&mis->main_thread_load_event);
 }
 
-
-typedef struct {
-    bool optional;
-    uint32_t size;
-    uint8_t runstate[100];
-    RunState state;
-    bool received;
-} GlobalState;
-
-static GlobalState global_state;
-
-int global_state_store(void)
-{
-    if (!runstate_store((char *)global_state.runstate,
-                        sizeof(global_state.runstate))) {
-        error_report("runstate name too big: %s", global_state.runstate);
-        trace_migrate_state_too_big();
-        return -EINVAL;
-    }
-    return 0;
-}
-
-void global_state_store_running(void)
-{
-    const char *state = RunState_lookup[RUN_STATE_RUNNING];
-    strncpy((char *)global_state.runstate,
-           state, sizeof(global_state.runstate));
-}
-
-static bool global_state_received(void)
-{
-    return global_state.received;
-}
-
-static RunState global_state_get_runstate(void)
-{
-    return global_state.state;
-}
-
-void global_state_set_optional(void)
-{
-    global_state.optional = true;
-}
-
-static bool global_state_needed(void *opaque)
-{
-    GlobalState *s = opaque;
-    char *runstate = (char *)s->runstate;
-
-    /* If it is not optional, it is mandatory */
-
-    if (s->optional == false) {
-        return true;
-    }
-
-    /* If state is running or paused, it is not needed */
-
-    if (strcmp(runstate, "running") == 0 ||
-        strcmp(runstate, "paused") == 0) {
-        return false;
-    }
-
-    /* for any other state it is needed */
-    return true;
-}
-
-static int global_state_post_load(void *opaque, int version_id)
-{
-    GlobalState *s = opaque;
-    Error *local_err = NULL;
-    int r;
-    char *runstate = (char *)s->runstate;
-
-    s->received = true;
-    trace_migrate_global_state_post_load(runstate);
-
-    r = qapi_enum_parse(RunState_lookup, runstate, RUN_STATE__MAX,
-                                -1, &local_err);
-
-    if (r == -1) {
-        if (local_err) {
-            error_report_err(local_err);
-        }
-        return -EINVAL;
-    }
-    s->state = r;
-
-    return 0;
-}
-
-static void global_state_pre_save(void *opaque)
-{
-    GlobalState *s = opaque;
-
-    trace_migrate_global_state_pre_save((char *)s->runstate);
-    s->size = strlen((char *)s->runstate) + 1;
-}
-
-static const VMStateDescription vmstate_globalstate = {
-    .name = "globalstate",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .post_load = global_state_post_load,
-    .pre_save = global_state_pre_save,
-    .needed = global_state_needed,
-    .fields = (VMStateField[]) {
-        VMSTATE_UINT32(size, GlobalState),
-        VMSTATE_BUFFER(runstate, GlobalState),
-        VMSTATE_END_OF_LIST()
-    },
-};
-
-void register_global_state(void)
-{
-    /* We would use it independently that we receive it */
-    strcpy((char *)&global_state.runstate, "");
-    global_state.received = false;
-    vmstate_register(NULL, 0, &vmstate_globalstate, &global_state);
-}
-
 static void migrate_generate_event(int new_state)
 {
     if (migrate_use_events()) {
@@ -292,6 +186,23 @@ static void deferred_incoming_migration(Error **errp)
     deferred_incoming = true;
 }
 
+/*
+ * Send a message on the return channel back to the source
+ * of the migration.
+ */
+static void migrate_send_rp_message(MigrationIncomingState *mis,
+                                    enum mig_rp_message_type message_type,
+                                    uint16_t len, void *data)
+{
+    trace_migrate_send_rp_message((int)message_type, len);
+    qemu_mutex_lock(&mis->rp_mutex);
+    qemu_put_be16(mis->to_src_file, (unsigned int)message_type);
+    qemu_put_be16(mis->to_src_file, len);
+    qemu_put_buffer(mis->to_src_file, data, len);
+    qemu_fflush(mis->to_src_file);
+    qemu_mutex_unlock(&mis->rp_mutex);
+}
+
 /* Request a range of pages from the source VM at the given
  * start address.
  *   rbname: Name of the RAMBlock to request the page in, if NULL it's the same
@@ -462,23 +373,6 @@ void migration_fd_process_incoming(QEMUFile *f)
 }
 
 /*
- * Send a message on the return channel back to the source
- * of the migration.
- */
-void migrate_send_rp_message(MigrationIncomingState *mis,
-                             enum mig_rp_message_type message_type,
-                             uint16_t len, void *data)
-{
-    trace_migrate_send_rp_message((int)message_type, len);
-    qemu_mutex_lock(&mis->rp_mutex);
-    qemu_put_be16(mis->to_src_file, (unsigned int)message_type);
-    qemu_put_be16(mis->to_src_file, len);
-    qemu_put_buffer(mis->to_src_file, data, len);
-    qemu_fflush(mis->to_src_file);
-    qemu_mutex_unlock(&mis->rp_mutex);
-}
-
-/*
  * Send a 'SHUT' message on the return channel with the given value
  * to indicate that we've finished with the RP.  Non-0 value indicates
  * error.
@@ -627,6 +521,17 @@ static void populate_ram_info(MigrationInfo *info, MigrationState *s)
     }
 }
 
+static void populate_disk_info(MigrationInfo *info)
+{
+    if (blk_mig_active()) {
+        info->has_disk = true;
+        info->disk = g_malloc0(sizeof(*info->disk));
+        info->disk->transferred = blk_mig_bytes_transferred();
+        info->disk->remaining = blk_mig_bytes_remaining();
+        info->disk->total = blk_mig_bytes_total();
+    }
+}
+
 MigrationInfo *qmp_query_migrate(Error **errp)
 {
     MigrationInfo *info = g_malloc0(sizeof(*info));
@@ -642,28 +547,8 @@ MigrationInfo *qmp_query_migrate(Error **errp)
         break;
     case MIGRATION_STATUS_ACTIVE:
     case MIGRATION_STATUS_CANCELLING:
-        info->has_status = true;
-        info->has_total_time = true;
-        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;
-
-        populate_ram_info(info, s);
-
-        if (blk_mig_active()) {
-            info->has_disk = true;
-            info->disk = g_malloc0(sizeof(*info->disk));
-            info->disk->transferred = blk_mig_bytes_transferred();
-            info->disk->remaining = blk_mig_bytes_remaining();
-            info->disk->total = blk_mig_bytes_total();
-        }
-
-        break;
     case MIGRATION_STATUS_POSTCOPY_ACTIVE:
-        /* Mostly the same as active; TODO add some postcopy stats */
+         /* TODO add some postcopy stats */
         info->has_status = true;
         info->has_total_time = true;
         info->total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME)
@@ -674,15 +559,7 @@ MigrationInfo *qmp_query_migrate(Error **errp)
         info->setup_time = s->setup_time;
 
         populate_ram_info(info, s);
-
-        if (blk_mig_active()) {
-            info->has_disk = true;
-            info->disk = g_malloc0(sizeof(*info->disk));
-            info->disk->transferred = blk_mig_bytes_transferred();
-            info->disk->remaining = blk_mig_bytes_remaining();
-            info->disk->total = blk_mig_bytes_total();
-        }
-
+        populate_disk_info(info);
         break;
     case MIGRATION_STATUS_COLO:
         info->has_status = true;
@@ -1179,7 +1056,7 @@ bool migration_is_blocked(Error **errp)
     }
 
     if (migration_blockers) {
-        *errp = error_copy(migration_blockers->data);
+        error_propagate(errp, error_copy(migration_blockers->data));
         return true;
     }
 
@@ -1857,13 +1734,12 @@ static void migration_completion(MigrationState *s, int current_active_state,
      * cleaning everything else up (since if there are no failures
      * it will wait for the destination to send it's status in
      * a SHUT command).
-     * Postcopy opens rp if enabled (even if it's not avtivated)
      */
-    if (migrate_postcopy_ram()) {
+    if (s->rp_state.from_dst_file) {
         int rp_error;
-        trace_migration_completion_postcopy_end_before_rp();
+        trace_migration_return_path_end_before();
         rp_error = await_return_path_close_on_source(s);
-        trace_migration_completion_postcopy_end_after_rp(rp_error);
+        trace_migration_return_path_end_after(rp_error);
         if (rp_error) {
             goto fail_invalidate;
         }
@@ -1938,13 +1814,15 @@ static void *migration_thread(void *opaque)
 
     qemu_savevm_state_header(s->to_dst_file);
 
-    if (migrate_postcopy_ram()) {
+    if (s->to_dst_file) {
         /* Now tell the dest that it should open its end so it can reply */
         qemu_savevm_send_open_return_path(s->to_dst_file);
 
         /* And do a ping that will make stuff easier to debug */
         qemu_savevm_send_ping(s->to_dst_file, 1);
+    }
 
+    if (migrate_postcopy_ram()) {
         /*
          * Tell the destination that we *might* want to do postcopy later;
          * if the other end can't do postcopy it should fail now, nice and
diff --git a/migration/migration.h b/migration/migration.h
new file mode 100644
index 0000000000..601e4ab354
--- /dev/null
+++ b/migration/migration.h
@@ -0,0 +1,164 @@
+/*
+ * QEMU live migration
+ *
+ * Copyright IBM, Corp. 2008
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef QEMU_MIGRATION_H
+#define QEMU_MIGRATION_H
+
+#include "qapi/qmp/qdict.h"
+#include "qemu-common.h"
+#include "qemu/thread.h"
+#include "qemu/notify.h"
+#include "qapi-types.h"
+#include "exec/cpu-common.h"
+#include "qemu/coroutine_int.h"
+
+/* State for the incoming migration */
+struct MigrationIncomingState {
+    QEMUFile *from_src_file;
+
+    /*
+     * Free at the start of the main state load, set as the main thread finishes
+     * loading state.
+     */
+    QemuEvent main_thread_load_event;
+
+    size_t         largest_page_size;
+    bool           have_fault_thread;
+    QemuThread     fault_thread;
+    QemuSemaphore  fault_thread_sem;
+
+    bool           have_listen_thread;
+    QemuThread     listen_thread;
+    QemuSemaphore  listen_thread_sem;
+
+    /* For the kernel to send us notifications */
+    int       userfault_fd;
+    /* To tell the fault_thread to quit */
+    int       userfault_quit_fd;
+    QEMUFile *to_src_file;
+    QemuMutex rp_mutex;    /* We send replies from multiple threads */
+    void     *postcopy_tmp_page;
+    void     *postcopy_tmp_zero_page;
+
+    QEMUBH *bh;
+
+    int state;
+
+    bool have_colo_incoming_thread;
+    QemuThread colo_incoming_thread;
+    /* The coroutine we should enter (back) after failover */
+    Coroutine *migration_incoming_co;
+    QemuSemaphore colo_incoming_sem;
+};
+
+MigrationIncomingState *migration_incoming_get_current(void);
+void migration_incoming_state_destroy(void);
+
+struct MigrationState
+{
+    size_t bytes_xfer;
+    size_t xfer_limit;
+    QemuThread thread;
+    QEMUBH *cleanup_bh;
+    QEMUFile *to_dst_file;
+
+    /* params from 'migrate-set-parameters' */
+    MigrationParameters parameters;
+
+    int state;
+
+    /* State related to return path */
+    struct {
+        QEMUFile     *from_dst_file;
+        QemuThread    rp_thread;
+        bool          error;
+    } rp_state;
+
+    double mbps;
+    int64_t total_time;
+    int64_t downtime;
+    int64_t expected_downtime;
+    bool enabled_capabilities[MIGRATION_CAPABILITY__MAX];
+    int64_t xbzrle_cache_size;
+    int64_t setup_time;
+
+    /* Flag set once the migration has been asked to enter postcopy */
+    bool start_postcopy;
+    /* Flag set after postcopy has sent the device state */
+    bool postcopy_after_devices;
+
+    /* Flag set once the migration thread is running (and needs joining) */
+    bool migration_thread_running;
+
+    /* Flag set once the migration thread called bdrv_inactivate_all */
+    bool block_inactive;
+
+    /* The semaphore is used to notify COLO thread that failover is finished */
+    QemuSemaphore colo_exit_sem;
+
+    /* The semaphore is used to notify COLO thread to do checkpoint */
+    QemuSemaphore colo_checkpoint_sem;
+    int64_t colo_checkpoint_time;
+    QEMUTimer *colo_delay_timer;
+
+    /* The last error that occurred */
+    Error *error;
+    /* Do we have to clean up -b/-i from old migrate parameters */
+    /* This feature is deprecated and will be removed */
+    bool must_remove_block_options;
+};
+
+void migrate_set_state(int *state, int old_state, int new_state);
+
+void migration_fd_process_incoming(QEMUFile *f);
+
+uint64_t migrate_max_downtime(void);
+
+void migrate_fd_error(MigrationState *s, const Error *error);
+
+void migrate_fd_connect(MigrationState *s);
+
+MigrationState *migrate_init(void);
+bool migration_is_blocked(Error **errp);
+/* True if outgoing migration has entered postcopy phase */
+bool migration_in_postcopy(void);
+MigrationState *migrate_get_current(void);
+
+bool migrate_release_ram(void);
+bool migrate_postcopy_ram(void);
+bool migrate_zero_blocks(void);
+
+bool migrate_auto_converge(void);
+
+int migrate_use_xbzrle(void);
+int64_t migrate_xbzrle_cache_size(void);
+bool migrate_colo_enabled(void);
+
+bool migrate_use_block(void);
+bool migrate_use_block_incremental(void);
+
+bool migrate_use_compression(void);
+int migrate_compress_level(void);
+int migrate_compress_threads(void);
+int migrate_decompress_threads(void);
+bool migrate_use_events(void);
+
+/* Sending on the return path - generic and then for each message type */
+void migrate_send_rp_shut(MigrationIncomingState *mis,
+                          uint32_t value);
+void migrate_send_rp_pong(MigrationIncomingState *mis,
+                          uint32_t value);
+void migrate_send_rp_req_pages(MigrationIncomingState *mis, const char* rbname,
+                              ram_addr_t start, size_t len);
+
+#endif
diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c
index 9c4188724e..c8c4500cc4 100644
--- a/migration/postcopy-ram.c
+++ b/migration/postcopy-ram.c
@@ -20,7 +20,7 @@
 
 #include "qemu-common.h"
 #include "exec/target_page.h"
-#include "migration/migration.h"
+#include "migration.h"
 #include "qemu-file.h"
 #include "savevm.h"
 #include "postcopy-ram.h"
diff --git a/migration/qemu-file.c b/migration/qemu-file.c
index ab26f4eea9..e65c373341 100644
--- a/migration/qemu-file.c
+++ b/migration/qemu-file.c
@@ -28,7 +28,7 @@
 #include "qemu/iov.h"
 #include "qemu/sockets.h"
 #include "qemu/coroutine.h"
-#include "migration/migration.h"
+#include "migration.h"
 #include "qemu-file.h"
 #include "trace.h"
 
diff --git a/migration/qemu-file.h b/migration/qemu-file.h
index 49fd6978ac..aae4e5ed36 100644
--- a/migration/qemu-file.h
+++ b/migration/qemu-file.h
@@ -156,5 +156,22 @@ void qemu_file_set_blocking(QEMUFile *f, bool block);
 
 size_t qemu_get_counted_string(QEMUFile *f, char buf[256]);
 
+void ram_control_before_iterate(QEMUFile *f, uint64_t flags);
+void ram_control_after_iterate(QEMUFile *f, uint64_t flags);
+void ram_control_load_hook(QEMUFile *f, uint64_t flags, void *data);
+
+/* Whenever this is found in the data stream, the flags
+ * will be passed to ram_control_load_hook in the incoming-migration
+ * side. This lets before_ram_iterate/after_ram_iterate add
+ * transport-specific sections to the RAM migration data.
+ */
+#define RAM_SAVE_FLAG_HOOK     0x80
+
+#define RAM_SAVE_CONTROL_NOT_SUPP -1000
+#define RAM_SAVE_CONTROL_DELAYED  -2000
+
+size_t ram_control_save_page(QEMUFile *f, ram_addr_t block_offset,
+                             ram_addr_t offset, size_t size,
+                             uint64_t *bytes_sent);
 
 #endif
diff --git a/migration/ram.c b/migration/ram.c
index 9ffd0a5479..c1b4f4abf3 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -37,7 +37,8 @@
 #include "qemu/main-loop.h"
 #include "xbzrle.h"
 #include "ram.h"
-#include "migration/migration.h"
+#include "migration.h"
+#include "migration/register.h"
 #include "migration/misc.h"
 #include "qemu-file.h"
 #include "migration/vmstate.h"
diff --git a/migration/rdma.c b/migration/rdma.c
index e446c6fd6a..c6bc607a03 100644
--- a/migration/rdma.c
+++ b/migration/rdma.c
@@ -18,7 +18,7 @@
 #include "qemu-common.h"
 #include "qemu/cutils.h"
 #include "rdma.h"
-#include "migration/migration.h"
+#include "migration.h"
 #include "qemu-file.h"
 #include "ram.h"
 #include "qemu-file-channel.h"
diff --git a/migration/savevm.c b/migration/savevm.c
index 745caaebef..30cda2cb46 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -34,8 +34,11 @@
 #include "net/net.h"
 #include "sysemu/sysemu.h"
 #include "qemu/timer.h"
-#include "migration/migration.h"
+#include "migration.h"
 #include "migration/snapshot.h"
+#include "migration/misc.h"
+#include "migration/register.h"
+#include "migration/global_state.h"
 #include "ram.h"
 #include "qemu-file-channel.h"
 #include "qemu-file.h"
diff --git a/migration/savevm.h b/migration/savevm.h
index eb4487771a..45b59c19bc 100644
--- a/migration/savevm.h
+++ b/migration/savevm.h
@@ -14,6 +14,21 @@
 #ifndef MIGRATION_SAVEVM_H
 #define MIGRATION_SAVEVM_H
 
+#define QEMU_VM_FILE_MAGIC           0x5145564d
+#define QEMU_VM_FILE_VERSION_COMPAT  0x00000002
+#define QEMU_VM_FILE_VERSION         0x00000003
+
+#define QEMU_VM_EOF                  0x00
+#define QEMU_VM_SECTION_START        0x01
+#define QEMU_VM_SECTION_PART         0x02
+#define QEMU_VM_SECTION_END          0x03
+#define QEMU_VM_SECTION_FULL         0x04
+#define QEMU_VM_SUBSECTION           0x05
+#define QEMU_VM_VMDESCRIPTION        0x06
+#define QEMU_VM_CONFIGURATION        0x07
+#define QEMU_VM_COMMAND              0x08
+#define QEMU_VM_SECTION_FOOTER       0x7e
+
 bool qemu_savevm_state_blocked(Error **errp);
 void qemu_savevm_state_begin(QEMUFile *f);
 void qemu_savevm_state_header(QEMUFile *f);
diff --git a/migration/socket.c b/migration/socket.c
index 85bfdccae1..757d3821a1 100644
--- a/migration/socket.c
+++ b/migration/socket.c
@@ -21,7 +21,7 @@
 #include "qapi/error.h"
 #include "channel.h"
 #include "socket.h"
-#include "migration/migration.h"
+#include "migration.h"
 #include "qemu-file.h"
 #include "io/channel-socket.h"
 #include "trace.h"
@@ -148,8 +148,7 @@ static gboolean socket_accept_incoming_migration(QIOChannel *ioc,
     trace_migration_socket_incoming_accepted();
 
     qio_channel_set_name(QIO_CHANNEL(sioc), "migration-socket-incoming");
-    migration_channel_process_incoming(migrate_get_current(),
-                                       QIO_CHANNEL(sioc));
+    migration_channel_process_incoming(QIO_CHANNEL(sioc));
     object_unref(OBJECT(sioc));
 
 out:
diff --git a/migration/tls.c b/migration/tls.c
index bae9acad6c..596e8790bd 100644
--- a/migration/tls.c
+++ b/migration/tls.c
@@ -20,7 +20,7 @@
 
 #include "qemu/osdep.h"
 #include "channel.h"
-#include "migration/migration.h"
+#include "migration.h"
 #include "tls.h"
 #include "io/channel-tls.h"
 #include "crypto/tlscreds.h"
@@ -74,7 +74,7 @@ static void migration_tls_incoming_handshake(QIOTask *task,
         error_report_err(err);
     } else {
         trace_migration_tls_incoming_handshake_complete();
-        migration_channel_process_incoming(migrate_get_current(), ioc);
+        migration_channel_process_incoming(ioc);
     }
     object_unref(OBJECT(ioc));
 }
diff --git a/migration/trace-events b/migration/trace-events
index 5b8ccf301c..38345be9c3 100644
--- a/migration/trace-events
+++ b/migration/trace-events
@@ -88,8 +88,8 @@ migrate_send_rp_message(int msg_type, uint16_t len) "%d: len %d"
 migration_completion_file_err(void) ""
 migration_completion_postcopy_end(void) ""
 migration_completion_postcopy_end_after_complete(void) ""
-migration_completion_postcopy_end_before_rp(void) ""
-migration_completion_postcopy_end_after_rp(int rp_error) "%d"
+migration_return_path_end_before(void) ""
+migration_return_path_end_after(int rp_error) "%d"
 migration_thread_after_loop(void) ""
 migration_thread_file_err(void) ""
 migration_thread_setup_complete(void) ""
diff --git a/migration/vmstate-types.c b/migration/vmstate-types.c
index 7287c6baa6..02f05a3359 100644
--- a/migration/vmstate-types.c
+++ b/migration/vmstate-types.c
@@ -14,7 +14,7 @@
 #include "qemu-common.h"
 #include "exec/cpu-common.h"
 #include "qemu-file.h"
-#include "migration/migration.h"
+#include "migration.h"
 #include "migration/vmstate.h"
 #include "qemu/error-report.h"
 #include "qemu/queue.h"
diff --git a/migration/vmstate.c b/migration/vmstate.c
index 51a19b668a..3226e8eb45 100644
--- a/migration/vmstate.c
+++ b/migration/vmstate.c
@@ -12,8 +12,9 @@
 
 #include "qemu/osdep.h"
 #include "qemu-common.h"
-#include "migration/migration.h"
+#include "migration.h"
 #include "migration/vmstate.h"
+#include "migration/savevm.h"
 #include "qemu-file.h"
 #include "qemu/bitops.h"
 #include "qemu/error-report.h"