migration/next for 20170613

-----BEGIN PGP SIGNATURE-----
 
 iQIcBAABCAAGBQJZP6n5AAoJEPSH7xhYctcj04oQAJczMfc2X8vTwII6lN9klf+T
 Cy32B4WB8FBO9M7oJYD/yytJ3ibcLuMwKwTy/GGfaTspuYDI/HrplUD3Pt+trDPc
 fUxmTNjK9vE9foPAwOTSwTGsdOp5ICoZuDjHTj8gtHmfFLclDxxJMojtthMJ1Csc
 qn9oJzjLn3izn8C6CY6oXGnqOt6gy2lz+RqNKlve/bwxaVdQIXTXCVsLWwQZuj48
 VI9qAFw9TsgSBi9dlTYpVfdMvItO73SVYd2c1ETzL0YSNK3S/Yhpww7fyK8TQNpO
 Y8xXMMBMybHZej1ixHXh01CRmEnBZXpjLCIXnWwxQGXxTH8p7F+W1+lhDTL4IIXR
 Py0EwiPUj4sPyTW2htSnDBRtE1uHcJlDtsFAAmsEqfeASet7ueE2bkfKwWUftqTs
 GZ7ikseIb9F0eQKjecYcEfaLtYNn+0UflgVkimW1gXIeuO58VYLpa8vdiUV3eKJn
 UCDDHGYKf7QJQLpSzYWXGRT4HJOQvaCbJ0a03hKceYyLB6rJv96khajirbczKZ92
 cja0EJfDy5S9fBulWRveHKLUAFMrR3zA4DhlK0pb591uIs4iMcKH3egHQZpv0uf0
 iifWNI+AFuorhQfdhV2G4Zg1g/fwI2RRJK7HdBOklulUrcr0caPvjjGdbA3Q0Hf6
 u61pWdr+Yb3XPaqlC2AH
 =EFHC
 -----END PGP SIGNATURE-----

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>
This commit is contained in:
Peter Maydell 2017-06-13 13:51:29 +01:00
commit 735286a4f8
39 changed files with 380 additions and 323 deletions

View File

@ -52,7 +52,8 @@
#include <xen/hvm/hvm_info_table.h> #include <xen/hvm/hvm_info_table.h>
#include "hw/xen/xen_pt.h" #include "hw/xen/xen_pt.h"
#endif #endif
#include "migration/migration.h" #include "migration/global_state.h"
#include "migration/misc.h"
#include "kvm_i386.h" #include "kvm_i386.h"
#include "sysemu/numa.h" #include "sysemu/numa.h"

View File

@ -25,6 +25,7 @@
#include "qapi/qmp/qjson.h" #include "qapi/qmp/qjson.h"
#include "qapi-event.h" #include "qapi-event.h"
#include "hw/virtio/virtio-access.h" #include "hw/virtio/virtio-access.h"
#include "migration/misc.h"
#define VIRTIO_NET_VM_VERSION 11 #define VIRTIO_NET_VM_VERSION 11

View File

@ -26,6 +26,7 @@
#include "qemu/bswap.h" #include "qemu/bswap.h"
#include "hw/pci/msix.h" #include "hw/pci/msix.h"
#include "hw/pci/msi.h" #include "hw/pci/msi.h"
#include "migration/register.h"
#include "vmxnet3.h" #include "vmxnet3.h"
#include "vmxnet_debug.h" #include "vmxnet_debug.h"

View File

@ -38,7 +38,9 @@
#include "sysemu/cpus.h" #include "sysemu/cpus.h"
#include "sysemu/hw_accel.h" #include "sysemu/hw_accel.h"
#include "kvm_ppc.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-hash64.h"
#include "mmu-book3s-v3.h" #include "mmu-book3s-v3.h"
#include "qom/cpu.h" #include "qom/cpu.h"

View File

@ -15,6 +15,7 @@
#include "hw/s390x/storage-keys.h" #include "hw/s390x/storage-keys.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "sysemu/kvm.h" #include "sysemu/kvm.h"
#include "migration/register.h"
#define S390_SKEYS_BUFFER_SIZE 131072 /* Room for 128k storage keys */ #define S390_SKEYS_BUFFER_SIZE 131072 /* Room for 128k storage keys */
#define S390_SKEYS_SAVE_FLAG_EOS 0x01 #define S390_SKEYS_SAVE_FLAG_EOS 0x01

View File

@ -28,6 +28,7 @@
#include "ipl.h" #include "ipl.h"
#include "hw/s390x/s390-virtio-ccw.h" #include "hw/s390x/s390-virtio-ccw.h"
#include "hw/s390x/css-bridge.h" #include "hw/s390x/css-bridge.h"
#include "migration/register.h"
static const char *const reset_dev_types[] = { static const char *const reset_dev_types[] = {
TYPE_VIRTUAL_CSS_BRIDGE, TYPE_VIRTUAL_CSS_BRIDGE,

View File

@ -13,7 +13,8 @@
#include "qmp-commands.h" #include "qmp-commands.h"
#include "chardev/char.h" #include "chardev/char.h"
#include "sysemu/accel.h" #include "sysemu/accel.h"
#include "migration/migration.h" #include "migration/misc.h"
#include "migration/global_state.h"
//#define DEBUG_XEN //#define DEBUG_XEN

View File

@ -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

View File

@ -26,4 +26,30 @@ void blk_mig_init(void);
static inline void blk_mig_init(void) {} static inline void blk_mig_init(void) {}
#endif #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 #endif

View File

@ -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

View File

@ -29,45 +29,7 @@
#include "migration/qjson.h" #include "migration/qjson.h"
typedef void SaveStateHandler(QEMUFile *f, void *opaque);
typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id); 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 VMStateInfo VMStateInfo;
typedef struct VMStateDescription VMStateDescription; typedef struct VMStateDescription VMStateDescription;
typedef struct VMStateField VMStateField; typedef struct VMStateField VMStateField;
@ -1010,8 +972,6 @@ extern const VMStateInfo vmstate_info_qtailq;
#define VMSTATE_END_OF_LIST() \ #define VMSTATE_END_OF_LIST() \
{} {}
#define SELF_ANNOUNCE_ROUNDS 5
int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
void *opaque, int version_id); void *opaque, int version_id);
void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd, 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_unregister_ram(struct MemoryRegion *memory, DeviceState *dev);
void vmstate_register_ram_global(struct MemoryRegion *memory); 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); bool vmstate_check_only_migratable(const VMStateDescription *vmsd);
#endif #endif

View File

@ -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 += tls.o channel.o savevm.o
common-obj-y += colo-comm.o colo.o colo-failover.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 += 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 += qemu-file-channel.o
common-obj-y += xbzrle.o postcopy-ram.o common-obj-y += xbzrle.o postcopy-ram.o
common-obj-y += qjson.o common-obj-y += qjson.o

View File

@ -25,7 +25,8 @@
#include "qemu/timer.h" #include "qemu/timer.h"
#include "block.h" #include "block.h"
#include "migration/misc.h" #include "migration/misc.h"
#include "migration/migration.h" #include "migration.h"
#include "migration/register.h"
#include "sysemu/blockdev.h" #include "sysemu/blockdev.h"
#include "qemu-file.h" #include "qemu-file.h"
#include "migration/vmstate.h" #include "migration/vmstate.h"

View File

@ -13,15 +13,16 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "channel.h" #include "channel.h"
#include "tls.h" #include "tls.h"
#include "migration/migration.h" #include "migration.h"
#include "qemu-file-channel.h" #include "qemu-file-channel.h"
#include "trace.h" #include "trace.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "io/channel-tls.h" #include "io/channel-tls.h"
void migration_channel_process_incoming(MigrationState *s, void migration_channel_process_incoming(QIOChannel *ioc)
QIOChannel *ioc)
{ {
MigrationState *s = migrate_get_current();
trace_migration_set_incoming_channel( trace_migration_set_incoming_channel(
ioc, object_get_typename(OBJECT(ioc))); ioc, object_get_typename(OBJECT(ioc)));

View File

@ -18,8 +18,7 @@
#include "io/channel.h" #include "io/channel.h"
void migration_channel_process_incoming(MigrationState *s, void migration_channel_process_incoming(QIOChannel *ioc);
QIOChannel *ioc);
void migration_channel_connect(MigrationState *s, void migration_channel_connect(MigrationState *s,
QIOChannel *ioc, QIOChannel *ioc,

View File

@ -12,7 +12,7 @@
*/ */
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "migration/migration.h" #include "migration.h"
#include "migration/colo.h" #include "migration/colo.h"
#include "migration/vmstate.h" #include "migration/vmstate.h"
#include "trace.h" #include "trace.h"

View File

@ -14,7 +14,7 @@
#include "qemu/timer.h" #include "qemu/timer.h"
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
#include "qemu-file-channel.h" #include "qemu-file-channel.h"
#include "migration/migration.h" #include "migration.h"
#include "qemu-file.h" #include "qemu-file.h"
#include "savevm.h" #include "savevm.h"
#include "migration/colo.h" #include "migration/colo.h"

View File

@ -22,7 +22,7 @@
#include "qemu-common.h" #include "qemu-common.h"
#include "channel.h" #include "channel.h"
#include "exec.h" #include "exec.h"
#include "migration/migration.h" #include "migration.h"
#include "io/channel-command.h" #include "io/channel-command.h"
#include "trace.h" #include "trace.h"
@ -49,7 +49,7 @@ static gboolean exec_accept_incoming_migration(QIOChannel *ioc,
GIOCondition condition, GIOCondition condition,
gpointer opaque) gpointer opaque)
{ {
migration_channel_process_incoming(migrate_get_current(), ioc); migration_channel_process_incoming(ioc);
object_unref(OBJECT(ioc)); object_unref(OBJECT(ioc));
return FALSE; /* unregister */ return FALSE; /* unregister */
} }

View File

@ -19,7 +19,7 @@
#include "qemu-common.h" #include "qemu-common.h"
#include "channel.h" #include "channel.h"
#include "fd.h" #include "fd.h"
#include "migration/migration.h" #include "migration.h"
#include "monitor/monitor.h" #include "monitor/monitor.h"
#include "io/channel-util.h" #include "io/channel-util.h"
#include "trace.h" #include "trace.h"
@ -49,7 +49,7 @@ static gboolean fd_accept_incoming_migration(QIOChannel *ioc,
GIOCondition condition, GIOCondition condition,
gpointer opaque) gpointer opaque)
{ {
migration_channel_process_incoming(migrate_get_current(), ioc); migration_channel_process_incoming(ioc);
object_unref(OBJECT(ioc)); object_unref(OBJECT(ioc));
return FALSE; /* unregister */ return FALSE; /* unregister */
} }

140
migration/global_state.c Normal file
View File

@ -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);
}

View File

@ -23,7 +23,9 @@
#include "socket.h" #include "socket.h"
#include "rdma.h" #include "rdma.h"
#include "ram.h" #include "ram.h"
#include "migration/migration.h" #include "migration/global_state.h"
#include "migration/misc.h"
#include "migration.h"
#include "savevm.h" #include "savevm.h"
#include "qemu-file-channel.h" #include "qemu-file-channel.h"
#include "qemu-file.h" #include "qemu-file.h"
@ -86,6 +88,18 @@ static NotifierList migration_state_notifiers =
static bool deferred_incoming; 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 /* When we add fault tolerance, we could have several
migrations at once. For now we don't need to add migrations at once. For now we don't need to add
dynamic creation of migration */ dynamic creation of migration */
@ -152,126 +166,6 @@ void migration_incoming_state_destroy(void)
qemu_event_destroy(&mis->main_thread_load_event); 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) static void migrate_generate_event(int new_state)
{ {
if (migrate_use_events()) { if (migrate_use_events()) {
@ -292,6 +186,23 @@ static void deferred_incoming_migration(Error **errp)
deferred_incoming = true; 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 /* Request a range of pages from the source VM at the given
* start address. * start address.
* rbname: Name of the RAMBlock to request the page in, if NULL it's the same * rbname: Name of the RAMBlock to request the page in, if NULL it's the same
@ -461,23 +372,6 @@ void migration_fd_process_incoming(QEMUFile *f)
qemu_coroutine_enter(co); qemu_coroutine_enter(co);
} }
/*
* 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 * 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 * to indicate that we've finished with the RP. Non-0 value indicates
@ -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 *qmp_query_migrate(Error **errp)
{ {
MigrationInfo *info = g_malloc0(sizeof(*info)); MigrationInfo *info = g_malloc0(sizeof(*info));
@ -642,28 +547,8 @@ MigrationInfo *qmp_query_migrate(Error **errp)
break; break;
case MIGRATION_STATUS_ACTIVE: case MIGRATION_STATUS_ACTIVE:
case MIGRATION_STATUS_CANCELLING: 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: 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_status = true;
info->has_total_time = true; info->has_total_time = true;
info->total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) 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; info->setup_time = s->setup_time;
populate_ram_info(info, s); populate_ram_info(info, s);
populate_disk_info(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();
}
break; break;
case MIGRATION_STATUS_COLO: case MIGRATION_STATUS_COLO:
info->has_status = true; info->has_status = true;
@ -1179,7 +1056,7 @@ bool migration_is_blocked(Error **errp)
} }
if (migration_blockers) { if (migration_blockers) {
*errp = error_copy(migration_blockers->data); error_propagate(errp, error_copy(migration_blockers->data));
return true; 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 * cleaning everything else up (since if there are no failures
* it will wait for the destination to send it's status in * it will wait for the destination to send it's status in
* a SHUT command). * 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; 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); 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) { if (rp_error) {
goto fail_invalidate; goto fail_invalidate;
} }
@ -1938,13 +1814,15 @@ static void *migration_thread(void *opaque)
qemu_savevm_state_header(s->to_dst_file); 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 */ /* Now tell the dest that it should open its end so it can reply */
qemu_savevm_send_open_return_path(s->to_dst_file); qemu_savevm_send_open_return_path(s->to_dst_file);
/* And do a ping that will make stuff easier to debug */ /* And do a ping that will make stuff easier to debug */
qemu_savevm_send_ping(s->to_dst_file, 1); qemu_savevm_send_ping(s->to_dst_file, 1);
}
if (migrate_postcopy_ram()) {
/* /*
* Tell the destination that we *might* want to do postcopy later; * 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 * if the other end can't do postcopy it should fail now, nice and

View File

@ -22,33 +22,6 @@
#include "exec/cpu-common.h" #include "exec/cpu-common.h"
#include "qemu/coroutine_int.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 */ /* State for the incoming migration */
struct MigrationIncomingState { struct MigrationIncomingState {
QEMUFile *from_src_file; 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 migration_fd_process_incoming(QEMUFile *f);
void qemu_start_incoming_migration(const char *uri, Error **errp);
uint64_t migrate_max_downtime(void); uint64_t migrate_max_downtime(void);
void migrate_fd_error(MigrationState *s, const Error *error); void migrate_fd_error(MigrationState *s, const Error *error);
void migrate_fd_connect(MigrationState *s); 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); MigrationState *migrate_init(void);
bool migration_is_blocked(Error **errp); 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 */ /* True if outgoing migration has entered postcopy phase */
bool migration_in_postcopy(void); bool migration_in_postcopy(void);
/* ...and after the device transmission */
bool migration_in_postcopy_after_devices(MigrationState *);
MigrationState *migrate_get_current(void); MigrationState *migrate_get_current(void);
bool migrate_release_ram(void); bool migrate_release_ram(void);
@ -191,9 +154,6 @@ int migrate_decompress_threads(void);
bool migrate_use_events(void); bool migrate_use_events(void);
/* Sending on the return path - generic and then for each message type */ /* 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, void migrate_send_rp_shut(MigrationIncomingState *mis,
uint32_t value); uint32_t value);
void migrate_send_rp_pong(MigrationIncomingState *mis, 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, void migrate_send_rp_req_pages(MigrationIncomingState *mis, const char* rbname,
ram_addr_t start, size_t len); 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 #endif

View File

@ -20,7 +20,7 @@
#include "qemu-common.h" #include "qemu-common.h"
#include "exec/target_page.h" #include "exec/target_page.h"
#include "migration/migration.h" #include "migration.h"
#include "qemu-file.h" #include "qemu-file.h"
#include "savevm.h" #include "savevm.h"
#include "postcopy-ram.h" #include "postcopy-ram.h"

View File

@ -28,7 +28,7 @@
#include "qemu/iov.h" #include "qemu/iov.h"
#include "qemu/sockets.h" #include "qemu/sockets.h"
#include "qemu/coroutine.h" #include "qemu/coroutine.h"
#include "migration/migration.h" #include "migration.h"
#include "qemu-file.h" #include "qemu-file.h"
#include "trace.h" #include "trace.h"

View File

@ -156,5 +156,22 @@ void qemu_file_set_blocking(QEMUFile *f, bool block);
size_t qemu_get_counted_string(QEMUFile *f, char buf[256]); 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 #endif

View File

@ -37,7 +37,8 @@
#include "qemu/main-loop.h" #include "qemu/main-loop.h"
#include "xbzrle.h" #include "xbzrle.h"
#include "ram.h" #include "ram.h"
#include "migration/migration.h" #include "migration.h"
#include "migration/register.h"
#include "migration/misc.h" #include "migration/misc.h"
#include "qemu-file.h" #include "qemu-file.h"
#include "migration/vmstate.h" #include "migration/vmstate.h"

View File

@ -18,7 +18,7 @@
#include "qemu-common.h" #include "qemu-common.h"
#include "qemu/cutils.h" #include "qemu/cutils.h"
#include "rdma.h" #include "rdma.h"
#include "migration/migration.h" #include "migration.h"
#include "qemu-file.h" #include "qemu-file.h"
#include "ram.h" #include "ram.h"
#include "qemu-file-channel.h" #include "qemu-file-channel.h"

View File

@ -34,8 +34,11 @@
#include "net/net.h" #include "net/net.h"
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
#include "qemu/timer.h" #include "qemu/timer.h"
#include "migration/migration.h" #include "migration.h"
#include "migration/snapshot.h" #include "migration/snapshot.h"
#include "migration/misc.h"
#include "migration/register.h"
#include "migration/global_state.h"
#include "ram.h" #include "ram.h"
#include "qemu-file-channel.h" #include "qemu-file-channel.h"
#include "qemu-file.h" #include "qemu-file.h"

View File

@ -14,6 +14,21 @@
#ifndef MIGRATION_SAVEVM_H #ifndef MIGRATION_SAVEVM_H
#define 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); bool qemu_savevm_state_blocked(Error **errp);
void qemu_savevm_state_begin(QEMUFile *f); void qemu_savevm_state_begin(QEMUFile *f);
void qemu_savevm_state_header(QEMUFile *f); void qemu_savevm_state_header(QEMUFile *f);

View File

@ -21,7 +21,7 @@
#include "qapi/error.h" #include "qapi/error.h"
#include "channel.h" #include "channel.h"
#include "socket.h" #include "socket.h"
#include "migration/migration.h" #include "migration.h"
#include "qemu-file.h" #include "qemu-file.h"
#include "io/channel-socket.h" #include "io/channel-socket.h"
#include "trace.h" #include "trace.h"
@ -148,8 +148,7 @@ static gboolean socket_accept_incoming_migration(QIOChannel *ioc,
trace_migration_socket_incoming_accepted(); trace_migration_socket_incoming_accepted();
qio_channel_set_name(QIO_CHANNEL(sioc), "migration-socket-incoming"); qio_channel_set_name(QIO_CHANNEL(sioc), "migration-socket-incoming");
migration_channel_process_incoming(migrate_get_current(), migration_channel_process_incoming(QIO_CHANNEL(sioc));
QIO_CHANNEL(sioc));
object_unref(OBJECT(sioc)); object_unref(OBJECT(sioc));
out: out:

View File

@ -20,7 +20,7 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "channel.h" #include "channel.h"
#include "migration/migration.h" #include "migration.h"
#include "tls.h" #include "tls.h"
#include "io/channel-tls.h" #include "io/channel-tls.h"
#include "crypto/tlscreds.h" #include "crypto/tlscreds.h"
@ -74,7 +74,7 @@ static void migration_tls_incoming_handshake(QIOTask *task,
error_report_err(err); error_report_err(err);
} else { } else {
trace_migration_tls_incoming_handshake_complete(); trace_migration_tls_incoming_handshake_complete();
migration_channel_process_incoming(migrate_get_current(), ioc); migration_channel_process_incoming(ioc);
} }
object_unref(OBJECT(ioc)); object_unref(OBJECT(ioc));
} }

View File

@ -88,8 +88,8 @@ migrate_send_rp_message(int msg_type, uint16_t len) "%d: len %d"
migration_completion_file_err(void) "" migration_completion_file_err(void) ""
migration_completion_postcopy_end(void) "" migration_completion_postcopy_end(void) ""
migration_completion_postcopy_end_after_complete(void) "" migration_completion_postcopy_end_after_complete(void) ""
migration_completion_postcopy_end_before_rp(void) "" migration_return_path_end_before(void) ""
migration_completion_postcopy_end_after_rp(int rp_error) "%d" migration_return_path_end_after(int rp_error) "%d"
migration_thread_after_loop(void) "" migration_thread_after_loop(void) ""
migration_thread_file_err(void) "" migration_thread_file_err(void) ""
migration_thread_setup_complete(void) "" migration_thread_setup_complete(void) ""

View File

@ -14,7 +14,7 @@
#include "qemu-common.h" #include "qemu-common.h"
#include "exec/cpu-common.h" #include "exec/cpu-common.h"
#include "qemu-file.h" #include "qemu-file.h"
#include "migration/migration.h" #include "migration.h"
#include "migration/vmstate.h" #include "migration/vmstate.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "qemu/queue.h" #include "qemu/queue.h"

View File

@ -12,8 +12,9 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qemu-common.h" #include "qemu-common.h"
#include "migration/migration.h" #include "migration.h"
#include "migration/vmstate.h" #include "migration/vmstate.h"
#include "migration/savevm.h"
#include "qemu-file.h" #include "qemu-file.h"
#include "qemu/bitops.h" #include "qemu/bitops.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"

View File

@ -29,7 +29,7 @@
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "qemu/help_option.h" #include "qemu/help_option.h"
#include "sysemu/block-backend.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 * Aliases were a bad idea from the start. Let's keep them

View File

@ -26,6 +26,7 @@
#include "qemu/timer.h" #include "qemu/timer.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "chardev/char-fe.h" #include "chardev/char-fe.h"
#include "migration/register.h"
#include "slirp.h" #include "slirp.h"
#include "hw/hw.h" #include "hw/hw.h"
#include "qemu/cutils.h" #include "qemu/cutils.h"

View File

@ -25,11 +25,12 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qemu-common.h" #include "qemu-common.h"
#include "migration/migration.h" #include "../migration/migration.h"
#include "migration/vmstate.h" #include "migration/vmstate.h"
#include "migration/qemu-file-types.h" #include "migration/qemu-file-types.h"
#include "../migration/qemu-file.h" #include "../migration/qemu-file.h"
#include "../migration/qemu-file-channel.h" #include "../migration/qemu-file-channel.h"
#include "../migration/savevm.h"
#include "qemu/coroutine.h" #include "qemu/coroutine.h"
#include "io/channel-file.h" #include "io/channel-file.h"

View File

@ -35,7 +35,7 @@
#include "qapi/qmp/qstring.h" #include "qapi/qmp/qstring.h"
#include "qapi/qmp/qjson.h" #include "qapi/qmp/qjson.h"
#include "qemu/notify.h" #include "qemu/notify.h"
#include "migration/migration.h" #include "migration/misc.h"
#include "hw/hw.h" #include "hw/hw.h"
#include "ui/spice-display.h" #include "ui/spice-display.h"
#include "qapi-event.h" #include "qapi-event.h"

2
vl.c
View File

@ -88,11 +88,11 @@ int main(int argc, char **argv)
#include "hw/block/block.h" #include "hw/block/block.h"
#include "migration/misc.h" #include "migration/misc.h"
#include "migration/snapshot.h" #include "migration/snapshot.h"
#include "migration/global_state.h"
#include "sysemu/tpm.h" #include "sysemu/tpm.h"
#include "sysemu/dma.h" #include "sysemu/dma.h"
#include "hw/audio/soundhw.h" #include "hw/audio/soundhw.h"
#include "audio/audio.h" #include "audio/audio.h"
#include "migration/migration.h"
#include "sysemu/cpus.h" #include "sysemu/cpus.h"
#include "migration/colo.h" #include "migration/colo.h"
#include "sysemu/kvm.h" #include "sysemu/kvm.h"