diff options
Diffstat (limited to 'migration')
-rw-r--r-- | migration/Makefile.objs | 2 | ||||
-rw-r--r-- | migration/block.c | 3 | ||||
-rw-r--r-- | migration/channel.c | 7 | ||||
-rw-r--r-- | migration/channel.h | 3 | ||||
-rw-r--r-- | migration/colo-comm.c | 2 | ||||
-rw-r--r-- | migration/colo.c | 2 | ||||
-rw-r--r-- | migration/exec.c | 4 | ||||
-rw-r--r-- | migration/fd.c | 4 | ||||
-rw-r--r-- | migration/global_state.c | 140 | ||||
-rw-r--r-- | migration/migration.c | 226 | ||||
-rw-r--r-- | migration/migration.h | 164 | ||||
-rw-r--r-- | migration/postcopy-ram.c | 2 | ||||
-rw-r--r-- | migration/qemu-file.c | 2 | ||||
-rw-r--r-- | migration/qemu-file.h | 17 | ||||
-rw-r--r-- | migration/ram.c | 3 | ||||
-rw-r--r-- | migration/rdma.c | 2 | ||||
-rw-r--r-- | migration/savevm.c | 5 | ||||
-rw-r--r-- | migration/savevm.h | 15 | ||||
-rw-r--r-- | migration/socket.c | 5 | ||||
-rw-r--r-- | migration/tls.c | 4 | ||||
-rw-r--r-- | migration/trace-events | 4 | ||||
-rw-r--r-- | migration/vmstate-types.c | 2 | ||||
-rw-r--r-- | migration/vmstate.c | 3 |
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" |