diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2017-06-13 13:51:29 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2017-06-13 13:51:29 +0100 |
commit | 735286a4f88255e1463d42ce28d8d14181fd32d4 (patch) | |
tree | 5200eac6b4fb709bdee16bc1bb1f3dea228b766d | |
parent | e0b4891ae6647b0009b5c0f877255e6723bffed8 (diff) | |
parent | 6666c96aac9151568736226dec99aa8acb14d07c (diff) | |
download | qemu-735286a4f88255e1463d42ce28d8d14181fd32d4.zip qemu-735286a4f88255e1463d42ce28d8d14181fd32d4.tar.gz qemu-735286a4f88255e1463d42ce28d8d14181fd32d4.tar.bz2 |
Merge remote-tracking branch 'remotes/juanquintela/tags/migration/20170613' into staging
migration/next for 20170613
# gpg: Signature made Tue 13 Jun 2017 10:01:45 BST
# gpg: using RSA key 0xF487EF185872D723
# gpg: Good signature from "Juan Quintela <quintela@redhat.com>"
# gpg: aka "Juan Quintela <quintela@trasno.org>"
# Primary key fingerprint: 1899 FF8E DEBF 58CC EE03 4B82 F487 EF18 5872 D723
* remotes/juanquintela/tags/migration/20170613:
migration: Move migration.h to migration/
migration: Move remaining exported functions to migration/misc.h
migration: create global_state.c
migration: ram_control_* are implemented in qemu_file
migration: Commands are only used inside migration.c
migration: Move constants to savevm.h
migration: Move dump_vmsate_json_to_file() to misc.h
migration: Split registration functions from vmstate.h
migration: Move self_announce_delay() to misc.h
migration: Remove MigrationState from migration_channel_incomming()
ram: Now POSTCOPY_ACTIVE is the same that STATUS_ACTIVE
ram: Print block stats also in the complete case
migration: Don't try to set *errp directly
migration: isolate return path on src
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
39 files changed, 380 insertions, 323 deletions
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 2234bd0..46a2bc4 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -52,7 +52,8 @@ #include <xen/hvm/hvm_info_table.h> #include "hw/xen/xen_pt.h" #endif -#include "migration/migration.h" +#include "migration/global_state.h" +#include "migration/misc.h" #include "kvm_i386.h" #include "sysemu/numa.h" diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 9a3d769..91eddaf 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -25,6 +25,7 @@ #include "qapi/qmp/qjson.h" #include "qapi-event.h" #include "hw/virtio/virtio-access.h" +#include "migration/misc.h" #define VIRTIO_NET_VM_VERSION 11 diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c index 4df3110..a19a7a3 100644 --- a/hw/net/vmxnet3.c +++ b/hw/net/vmxnet3.c @@ -26,6 +26,7 @@ #include "qemu/bswap.h" #include "hw/pci/msix.h" #include "hw/pci/msi.h" +#include "migration/register.h" #include "vmxnet3.h" #include "vmxnet_debug.h" diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index b2951d7..e877d45 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -38,7 +38,9 @@ #include "sysemu/cpus.h" #include "sysemu/hw_accel.h" #include "kvm_ppc.h" -#include "migration/migration.h" +#include "migration/misc.h" +#include "migration/global_state.h" +#include "migration/register.h" #include "mmu-hash64.h" #include "mmu-book3s-v3.h" #include "qom/cpu.h" diff --git a/hw/s390x/s390-skeys.c b/hw/s390x/s390-skeys.c index 35e7f63..c0de3b0 100644 --- a/hw/s390x/s390-skeys.c +++ b/hw/s390x/s390-skeys.c @@ -15,6 +15,7 @@ #include "hw/s390x/storage-keys.h" #include "qemu/error-report.h" #include "sysemu/kvm.h" +#include "migration/register.h" #define S390_SKEYS_BUFFER_SIZE 131072 /* Room for 128k storage keys */ #define S390_SKEYS_SAVE_FLAG_EOS 0x01 diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index a806345..41ca666 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -28,6 +28,7 @@ #include "ipl.h" #include "hw/s390x/s390-virtio-ccw.h" #include "hw/s390x/css-bridge.h" +#include "migration/register.h" static const char *const reset_dev_types[] = { TYPE_VIRTUAL_CSS_BRIDGE, diff --git a/hw/xen/xen-common.c b/hw/xen/xen-common.c index 0bed577..d3fa705 100644 --- a/hw/xen/xen-common.c +++ b/hw/xen/xen-common.c @@ -13,7 +13,8 @@ #include "qmp-commands.h" #include "chardev/char.h" #include "sysemu/accel.h" -#include "migration/migration.h" +#include "migration/misc.h" +#include "migration/global_state.h" //#define DEBUG_XEN diff --git a/include/migration/global_state.h b/include/migration/global_state.h new file mode 100644 index 0000000..90faea7 --- /dev/null +++ b/include/migration/global_state.h @@ -0,0 +1,25 @@ +/* + * 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. + */ + +#ifndef QEMU_MIGRATION_GLOBAL_STATE_H +#define QEMU_MIGRATION_GLOBAL_STATE_H + +#include "sysemu/sysemu.h" + +void register_global_state(void); +void global_state_set_optional(void); +int global_state_store(void); +void global_state_store_running(void); +bool global_state_received(void); +RunState global_state_get_runstate(void); + +#endif diff --git a/include/migration/misc.h b/include/migration/misc.h index d7892b7..d5a433a 100644 --- a/include/migration/misc.h +++ b/include/migration/misc.h @@ -26,4 +26,30 @@ void blk_mig_init(void); static inline void blk_mig_init(void) {} #endif +#define SELF_ANNOUNCE_ROUNDS 5 + +static inline +int64_t self_announce_delay(int round) +{ + assert(round < SELF_ANNOUNCE_ROUNDS && round > 0); + /* delay 50ms, 150ms, 250ms, ... */ + return 50 + (SELF_ANNOUNCE_ROUNDS - round - 1) * 100; +} + +/* migration/savevm.c */ + +void dump_vmstate_json_to_file(FILE *out_fp); +void savevm_skip_section_footers(void); +void savevm_skip_configuration(void); + +/* migration/migration.c */ +void qemu_start_incoming_migration(const char *uri, Error **errp); +bool migration_is_idle(void); +void add_migration_state_change_notifier(Notifier *notify); +void remove_migration_state_change_notifier(Notifier *notify); +bool migration_in_setup(MigrationState *); +bool migration_has_finished(MigrationState *); +bool migration_has_failed(MigrationState *); +/* ...and after the device transmission */ +bool migration_in_postcopy_after_devices(MigrationState *); #endif diff --git a/include/migration/register.h b/include/migration/register.h new file mode 100644 index 0000000..717c617 --- /dev/null +++ b/include/migration/register.h @@ -0,0 +1,56 @@ +/* + * QEMU migration vmstate registration + * + * 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 MIGRATION_REGISTER_H +#define MIGRATION_REGISTER_H + +typedef void SaveStateHandler(QEMUFile *f, void *opaque); +typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id); + +typedef struct SaveVMHandlers { + /* This runs inside the iothread lock. */ + SaveStateHandler *save_state; + + void (*cleanup)(void *opaque); + int (*save_live_complete_postcopy)(QEMUFile *f, void *opaque); + int (*save_live_complete_precopy)(QEMUFile *f, void *opaque); + + /* This runs both outside and inside the iothread lock. */ + bool (*is_active)(void *opaque); + + /* This runs outside the iothread lock in the migration case, and + * within the lock in the savevm case. The callback had better only + * use data that is local to the migration thread or protected + * by other locks. + */ + int (*save_live_iterate)(QEMUFile *f, void *opaque); + + /* This runs outside the iothread lock! */ + int (*save_live_setup)(QEMUFile *f, void *opaque); + void (*save_live_pending)(QEMUFile *f, void *opaque, + uint64_t threshold_size, + uint64_t *non_postcopiable_pending, + uint64_t *postcopiable_pending); + LoadStateHandler *load_state; +} SaveVMHandlers; + +int register_savevm_live(DeviceState *dev, + const char *idstr, + int instance_id, + int version_id, + SaveVMHandlers *ops, + void *opaque); + +void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque); + +#endif diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h index 8a3e9e6..79a4b35 100644 --- a/include/migration/vmstate.h +++ b/include/migration/vmstate.h @@ -29,45 +29,7 @@ #include "migration/qjson.h" -typedef void SaveStateHandler(QEMUFile *f, void *opaque); typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id); - -typedef struct SaveVMHandlers { - /* This runs inside the iothread lock. */ - SaveStateHandler *save_state; - - void (*cleanup)(void *opaque); - int (*save_live_complete_postcopy)(QEMUFile *f, void *opaque); - int (*save_live_complete_precopy)(QEMUFile *f, void *opaque); - - /* This runs both outside and inside the iothread lock. */ - bool (*is_active)(void *opaque); - - /* This runs outside the iothread lock in the migration case, and - * within the lock in the savevm case. The callback had better only - * use data that is local to the migration thread or protected - * by other locks. - */ - int (*save_live_iterate)(QEMUFile *f, void *opaque); - - /* This runs outside the iothread lock! */ - int (*save_live_setup)(QEMUFile *f, void *opaque); - void (*save_live_pending)(QEMUFile *f, void *opaque, - uint64_t threshold_size, - uint64_t *non_postcopiable_pending, - uint64_t *postcopiable_pending); - LoadStateHandler *load_state; -} SaveVMHandlers; - -int register_savevm_live(DeviceState *dev, - const char *idstr, - int instance_id, - int version_id, - SaveVMHandlers *ops, - void *opaque); - -void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque); - typedef struct VMStateInfo VMStateInfo; typedef struct VMStateDescription VMStateDescription; typedef struct VMStateField VMStateField; @@ -1010,8 +972,6 @@ extern const VMStateInfo vmstate_info_qtailq; #define VMSTATE_END_OF_LIST() \ {} -#define SELF_ANNOUNCE_ROUNDS 5 - int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, void *opaque, int version_id); void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd, @@ -1043,16 +1003,6 @@ void vmstate_register_ram(struct MemoryRegion *memory, DeviceState *dev); void vmstate_unregister_ram(struct MemoryRegion *memory, DeviceState *dev); void vmstate_register_ram_global(struct MemoryRegion *memory); -static inline -int64_t self_announce_delay(int round) -{ - assert(round < SELF_ANNOUNCE_ROUNDS && round > 0); - /* delay 50ms, 150ms, 250ms, ... */ - return 50 + (SELF_ANNOUNCE_ROUNDS - round - 1) * 100; -} - -void dump_vmstate_json_to_file(FILE *out_fp); - bool vmstate_check_only_migratable(const VMStateDescription *vmsd); #endif diff --git a/migration/Makefile.objs b/migration/Makefile.objs index 90f8c1f..1c7770d 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 114cedb..ae06975 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 eae1d9e..3b7252f 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 2e0a7e3..e4b4057 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 8bfdf68..b61aa19 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 111b715..45e9b46 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 9077024..b1de445 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 0077a50..b2384bf 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 0000000..16ac63f --- /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 fc95acb..8ef6d6c 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/include/migration/migration.h b/migration/migration.h index 79b5484..601e4ab 100644 --- a/include/migration/migration.h +++ b/migration/migration.h @@ -22,33 +22,6 @@ #include "exec/cpu-common.h" #include "qemu/coroutine_int.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 - -/* 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 -}; - /* State for the incoming migration */ struct MigrationIncomingState { QEMUFile *from_src_file; @@ -149,26 +122,16 @@ void migrate_set_state(int *state, int old_state, int new_state); void migration_fd_process_incoming(QEMUFile *f); -void qemu_start_incoming_migration(const char *uri, Error **errp); - uint64_t migrate_max_downtime(void); void migrate_fd_error(MigrationState *s, const Error *error); void migrate_fd_connect(MigrationState *s); -void add_migration_state_change_notifier(Notifier *notify); -void remove_migration_state_change_notifier(Notifier *notify); MigrationState *migrate_init(void); bool migration_is_blocked(Error **errp); -bool migration_in_setup(MigrationState *); -bool migration_is_idle(void); -bool migration_has_finished(MigrationState *); -bool migration_has_failed(MigrationState *); /* True if outgoing migration has entered postcopy phase */ bool migration_in_postcopy(void); -/* ...and after the device transmission */ -bool migration_in_postcopy_after_devices(MigrationState *); MigrationState *migrate_get_current(void); bool migrate_release_ram(void); @@ -191,9 +154,6 @@ 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_message(MigrationIncomingState *mis, - enum mig_rp_message_type message_type, - uint16_t len, void *data); void migrate_send_rp_shut(MigrationIncomingState *mis, uint32_t value); void migrate_send_rp_pong(MigrationIncomingState *mis, @@ -201,29 +161,4 @@ void migrate_send_rp_pong(MigrationIncomingState *mis, void migrate_send_rp_req_pages(MigrationIncomingState *mis, const char* rbname, ram_addr_t start, size_t len); -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); - -void savevm_skip_section_footers(void); -void register_global_state(void); -void global_state_set_optional(void); -void savevm_skip_configuration(void); -int global_state_store(void); -void global_state_store_running(void); - #endif diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c index 9c41887..c8c4500 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 ab26f4e..e65c373 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 49fd697..aae4e5e 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 9ffd0a5..c1b4f4a 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 e446c6f..c6bc607 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 745caae..30cda2c 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 eb44877..45b59c1 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 85bfdcc..757d382 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 bae9aca..596e879 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 5b8ccf3..38345be 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 7287c6b..02f05a3 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 51a19b6..3226e8e 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" diff --git a/qdev-monitor.c b/qdev-monitor.c index 3ecbf0b..8fd6df9 100644 --- a/qdev-monitor.c +++ b/qdev-monitor.c @@ -29,7 +29,7 @@ #include "qemu/error-report.h" #include "qemu/help_option.h" #include "sysemu/block-backend.h" -#include "migration/migration.h" +#include "migration/misc.h" /* * Aliases were a bad idea from the start. Let's keep them diff --git a/slirp/slirp.c b/slirp/slirp.c index 2386493..1d67568 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -26,6 +26,7 @@ #include "qemu/timer.h" #include "qemu/error-report.h" #include "chardev/char-fe.h" +#include "migration/register.h" #include "slirp.h" #include "hw/hw.h" #include "qemu/cutils.h" diff --git a/tests/test-vmstate.c b/tests/test-vmstate.c index c52aff9..ee292c7 100644 --- a/tests/test-vmstate.c +++ b/tests/test-vmstate.c @@ -25,11 +25,12 @@ #include "qemu/osdep.h" #include "qemu-common.h" -#include "migration/migration.h" +#include "../migration/migration.h" #include "migration/vmstate.h" #include "migration/qemu-file-types.h" #include "../migration/qemu-file.h" #include "../migration/qemu-file-channel.h" +#include "../migration/savevm.h" #include "qemu/coroutine.h" #include "io/channel-file.h" diff --git a/ui/spice-core.c b/ui/spice-core.c index 804abc5..a087ad5 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -35,7 +35,7 @@ #include "qapi/qmp/qstring.h" #include "qapi/qmp/qjson.h" #include "qemu/notify.h" -#include "migration/migration.h" +#include "migration/misc.h" #include "hw/hw.h" #include "ui/spice-display.h" #include "qapi-event.h" @@ -88,11 +88,11 @@ int main(int argc, char **argv) #include "hw/block/block.h" #include "migration/misc.h" #include "migration/snapshot.h" +#include "migration/global_state.h" #include "sysemu/tpm.h" #include "sysemu/dma.h" #include "hw/audio/soundhw.h" #include "audio/audio.h" -#include "migration/migration.h" #include "sysemu/cpus.h" #include "migration/colo.h" #include "sysemu/kvm.h" |