migration/next for 20170517

-----BEGIN PGP SIGNATURE-----
 
 iQIcBAABCAAGBQJZHCoMAAoJEPSH7xhYctcjyOcQAN82GDYgXj93k40rU/SmZTP7
 blelisGsY5UNo33bLZq07fVwwdk1vIR0OIZvjMyGVWptAX49QJ6BVwX2E5zmb9LW
 AT3rVeyqz8nnC6OwWBxN9bu+sPJ13ibGs1l2j5Kn9jZ6a9rJCC7LOKdo4Dxbs3Uk
 Obw4f7swsozTQPxeHfrsBgFIvcB8qXLjdxsVhj+IWkmp1KDKVg+TWfNFJx30dK0G
 ktVsV0Xu6exEzcnzpTf93Bcv8vt49JRrCka9N5YryPTZmFuGgW291lqviPWiZg/W
 39F3cga5QfDzcs4Z6Lrz3Qeo/q+2n5G5O23UmrJccZ//UQMdeW9sd5udj211aMeq
 I7UdrarIHWRCCVTVdVL7AGJ8xmMIKHsvKRWstw7FEMHQ+lD/sFSfpWBtYdGhAotF
 mf/yncMKb52QbNyIuanoKi8UjU+RCvuslCac87U3fPqz/qYGvhnmO145S/wai1mR
 +FQQXORJOhdsWDqRRz9q8/uXqPwm173+rHHzMgFa3P1X9u1jfLhjJk0g9sDFtyAb
 If4IzOwfuCLJyelcuzzy9SSOzDsGu1LcrBoRgqTugX+MSJXFjWOKKfA1wxnAKkPf
 T2fQIqny2N7VCfpDB1iaCfxnkizIwrYEI3YRkMuJpYU3489x/BJQIILoLo1yEj4G
 vNhq+qJ9V/Uj8X+X5/cL
 =A5DU
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'quintela/tags/migration/20170517' into staging

migration/next for 20170517

# gpg: Signature made Wed 17 May 2017 11:46:36 AM 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

* quintela/tags/migration/20170517:
  migration: Move check_migratable() into qdev.c
  migration: Move postcopy stuff to postcopy-ram.c
  migration: Move page_cache.c to migration/
  migration: Create migration/blocker.h
  ram: Rename RAM_SAVE_FLAG_COMPRESS to RAM_SAVE_FLAG_ZERO
  migration: Pass Error ** argument to {save,load}_vmstate
  migration: Fix regression with compression threads

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi 2017-05-18 10:05:50 +01:00
commit 2ccbd47c1d
36 changed files with 194 additions and 158 deletions

View File

@ -49,7 +49,6 @@ common-obj-$(CONFIG_POSIX) += os-posix.o
common-obj-$(CONFIG_LINUX) += fsdev/ common-obj-$(CONFIG_LINUX) += fsdev/
common-obj-y += migration/ common-obj-y += migration/
common-obj-y += page_cache.o #aio.o
common-obj-$(CONFIG_SPICE) += spice-qemu-char.o common-obj-$(CONFIG_SPICE) += spice-qemu-char.o

View File

@ -32,7 +32,7 @@
#include <zlib.h> #include <zlib.h>
#include "qapi/qmp/qerror.h" #include "qapi/qmp/qerror.h"
#include "crypto/cipher.h" #include "crypto/cipher.h"
#include "migration/migration.h" #include "migration/blocker.h"
/**************************************************************/ /**************************************************************/
/* QEMU COW block driver with compression and encryption support */ /* QEMU COW block driver with compression and encryption support */

View File

@ -55,7 +55,7 @@
#include "sysemu/block-backend.h" #include "sysemu/block-backend.h"
#include "qemu/module.h" #include "qemu/module.h"
#include "qemu/bswap.h" #include "qemu/bswap.h"
#include "migration/migration.h" #include "migration/blocker.h"
#include "qemu/coroutine.h" #include "qemu/coroutine.h"
#include "qemu/cutils.h" #include "qemu/cutils.h"
#include "qemu/uuid.h" #include "qemu/uuid.h"

View File

@ -24,7 +24,7 @@
#include "qemu/crc32c.h" #include "qemu/crc32c.h"
#include "qemu/bswap.h" #include "qemu/bswap.h"
#include "block/vhdx.h" #include "block/vhdx.h"
#include "migration/migration.h" #include "migration/blocker.h"
#include "qemu/uuid.h" #include "qemu/uuid.h"
/* Options for VHDX creation */ /* Options for VHDX creation */

View File

@ -31,7 +31,7 @@
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "qemu/module.h" #include "qemu/module.h"
#include "qemu/bswap.h" #include "qemu/bswap.h"
#include "migration/migration.h" #include "migration/blocker.h"
#include "qemu/cutils.h" #include "qemu/cutils.h"
#include <zlib.h> #include <zlib.h>

View File

@ -28,7 +28,7 @@
#include "block/block_int.h" #include "block/block_int.h"
#include "sysemu/block-backend.h" #include "sysemu/block-backend.h"
#include "qemu/module.h" #include "qemu/module.h"
#include "migration/migration.h" #include "migration/blocker.h"
#include "qemu/bswap.h" #include "qemu/bswap.h"
#include "qemu/uuid.h" #include "qemu/uuid.h"

View File

@ -28,7 +28,7 @@
#include "block/block_int.h" #include "block/block_int.h"
#include "qemu/module.h" #include "qemu/module.h"
#include "qemu/bswap.h" #include "qemu/bswap.h"
#include "migration/migration.h" #include "migration/blocker.h"
#include "qapi/qmp/qint.h" #include "qapi/qmp/qint.h"
#include "qapi/qmp/qbool.h" #include "qapi/qmp/qbool.h"
#include "qapi/qmp/qstring.h" #include "qapi/qmp/qstring.h"

9
hmp.c
View File

@ -1274,17 +1274,22 @@ void hmp_loadvm(Monitor *mon, const QDict *qdict)
{ {
int saved_vm_running = runstate_is_running(); int saved_vm_running = runstate_is_running();
const char *name = qdict_get_str(qdict, "name"); const char *name = qdict_get_str(qdict, "name");
Error *err = NULL;
vm_stop(RUN_STATE_RESTORE_VM); vm_stop(RUN_STATE_RESTORE_VM);
if (load_vmstate(name) == 0 && saved_vm_running) { if (load_vmstate(name, &err) == 0 && saved_vm_running) {
vm_start(); vm_start();
} }
hmp_handle_error(mon, &err);
} }
void hmp_savevm(Monitor *mon, const QDict *qdict) void hmp_savevm(Monitor *mon, const QDict *qdict)
{ {
save_vmstate(qdict_get_try_str(qdict, "name")); Error *err = NULL;
save_vmstate(qdict_get_try_str(qdict, "name"), &err);
hmp_handle_error(mon, &err);
} }
void hmp_delvm(Monitor *mon, const QDict *qdict) void hmp_delvm(Monitor *mon, const QDict *qdict)

View File

@ -23,7 +23,7 @@
#include "9p-xattr.h" #include "9p-xattr.h"
#include "coth.h" #include "coth.h"
#include "trace.h" #include "trace.h"
#include "migration/migration.h" #include "migration/blocker.h"
int open_fd_hw; int open_fd_hw;
int total_open_fd; int total_open_fd;

View File

@ -37,7 +37,7 @@
#include "hw/boards.h" #include "hw/boards.h"
#include "hw/sysbus.h" #include "hw/sysbus.h"
#include "qapi-event.h" #include "qapi-event.h"
#include "migration/migration.h" #include "migration/vmstate.h"
bool qdev_hotplug = false; bool qdev_hotplug = false;
static bool qdev_hot_added = false; static bool qdev_hot_added = false;
@ -861,6 +861,20 @@ static bool device_get_realized(Object *obj, Error **errp)
return dev->realized; return dev->realized;
} }
static bool check_only_migratable(Object *obj, Error **err)
{
DeviceClass *dc = DEVICE_GET_CLASS(obj);
if (!vmstate_check_only_migratable(dc->vmsd)) {
error_setg(err, "Device %s is not migratable, but "
"--only-migratable was specified",
object_get_typename(obj));
return false;
}
return true;
}
static void device_set_realized(Object *obj, bool value, Error **errp) static void device_set_realized(Object *obj, bool value, Error **errp)
{ {
DeviceState *dev = DEVICE(obj); DeviceState *dev = DEVICE(obj);
@ -870,7 +884,6 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
Error *local_err = NULL; Error *local_err = NULL;
bool unattached_parent = false; bool unattached_parent = false;
static int unattached_count; static int unattached_count;
int ret;
if (dev->hotplugged && !dc->hotpluggable) { if (dev->hotplugged && !dc->hotpluggable) {
error_setg(errp, QERR_DEVICE_NO_HOTPLUG, object_get_typename(obj)); error_setg(errp, QERR_DEVICE_NO_HOTPLUG, object_get_typename(obj));
@ -878,8 +891,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
} }
if (value && !dev->realized) { if (value && !dev->realized) {
ret = check_migratable(obj, &local_err); if (!check_only_migratable(obj, &local_err)) {
if (ret < 0) {
goto fail; goto fail;
} }

View File

@ -26,7 +26,7 @@
#include "qemu/queue.h" #include "qemu/queue.h"
#include "qemu/atomic.h" #include "qemu/atomic.h"
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
#include "migration/migration.h" #include "migration/blocker.h"
#include "trace.h" #include "trace.h"
#include "qxl.h" #include "qxl.h"

View File

@ -19,7 +19,7 @@
#include "hw/virtio/virtio.h" #include "hw/virtio/virtio.h"
#include "hw/virtio/virtio-gpu.h" #include "hw/virtio/virtio-gpu.h"
#include "hw/virtio/virtio-bus.h" #include "hw/virtio/virtio-bus.h"
#include "migration/migration.h" #include "migration/blocker.h"
#include "qemu/log.h" #include "qemu/log.h"
#include "qapi/error.h" #include "qapi/error.h"

View File

@ -24,7 +24,7 @@
#include "qemu-common.h" #include "qemu-common.h"
#include "cpu.h" #include "cpu.h"
#include "hw/sysbus.h" #include "hw/sysbus.h"
#include "migration/migration.h" #include "migration/blocker.h"
#include "sysemu/kvm.h" #include "sysemu/kvm.h"
#include "kvm_arm.h" #include "kvm_arm.h"
#include "gic_internal.h" #include "gic_internal.h"

View File

@ -24,7 +24,7 @@
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
#include "sysemu/kvm.h" #include "sysemu/kvm.h"
#include "kvm_arm.h" #include "kvm_arm.h"
#include "migration/migration.h" #include "migration/blocker.h"
#define TYPE_KVM_ARM_ITS "arm-its-kvm" #define TYPE_KVM_ARM_ITS "arm-its-kvm"
#define KVM_ARM_ITS(obj) OBJECT_CHECK(GICv3ITSState, (obj), TYPE_KVM_ARM_ITS) #define KVM_ARM_ITS(obj) OBJECT_CHECK(GICv3ITSState, (obj), TYPE_KVM_ARM_ITS)

View File

@ -28,7 +28,7 @@
#include "kvm_arm.h" #include "kvm_arm.h"
#include "gicv3_internal.h" #include "gicv3_internal.h"
#include "vgic_common.h" #include "vgic_common.h"
#include "migration/migration.h" #include "migration/blocker.h"
#ifdef DEBUG_GICV3_KVM #ifdef DEBUG_GICV3_KVM
#define DPRINTF(fmt, ...) \ #define DPRINTF(fmt, ...) \

View File

@ -25,7 +25,7 @@
#include "hw/pci/msi.h" #include "hw/pci/msi.h"
#include "hw/pci/msix.h" #include "hw/pci/msix.h"
#include "sysemu/kvm.h" #include "sysemu/kvm.h"
#include "migration/migration.h" #include "migration/blocker.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "qemu/event_notifier.h" #include "qemu/event_notifier.h"
#include "qom/object_interfaces.h" #include "qom/object_interfaces.h"

View File

@ -21,7 +21,7 @@
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "qemu/queue.h" #include "qemu/queue.h"
#include "monitor/monitor.h" #include "monitor/monitor.h"
#include "migration/migration.h" #include "migration/blocker.h"
#include "hw/virtio/vhost-scsi.h" #include "hw/virtio/vhost-scsi.h"
#include "hw/virtio/vhost.h" #include "hw/virtio/vhost.h"
#include "hw/virtio/virtio-scsi.h" #include "hw/virtio/virtio-scsi.h"

View File

@ -25,7 +25,7 @@
#include "exec/address-spaces.h" #include "exec/address-spaces.h"
#include "hw/virtio/virtio-bus.h" #include "hw/virtio/virtio-bus.h"
#include "hw/virtio/virtio-access.h" #include "hw/virtio/virtio-access.h"
#include "migration/migration.h" #include "migration/blocker.h"
#include "sysemu/dma.h" #include "sysemu/dma.h"
/* enabled until disconnected backend stabilizes */ /* enabled until disconnected backend stabilizes */

View File

@ -0,0 +1,35 @@
/*
* QEMU migration blockers
*
* 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_BLOCKER_H
#define MIGRATION_BLOCKER_H
/**
* @migrate_add_blocker - prevent migration from proceeding
*
* @reason - an error to be returned whenever migration is attempted
*
* @errp - [out] The reason (if any) we cannot block migration right now.
*
* @returns - 0 on success, -EBUSY/-EACCES on failure, with errp set.
*/
int migrate_add_blocker(Error *reason, Error **errp);
/**
* @migrate_del_blocker - remove a blocking error from migration
*
* @reason - the error blocking migration
*/
void migrate_del_blocker(Error *reason);
#endif

View File

@ -22,7 +22,6 @@
#include "qapi-types.h" #include "qapi-types.h"
#include "exec/cpu-common.h" #include "exec/cpu-common.h"
#include "qemu/coroutine_int.h" #include "qemu/coroutine_int.h"
#include "qom/object.h"
#define QEMU_VM_FILE_MAGIC 0x5145564d #define QEMU_VM_FILE_MAGIC 0x5145564d
#define QEMU_VM_FILE_VERSION_COMPAT 0x00000002 #define QEMU_VM_FILE_VERSION_COMPAT 0x00000002
@ -39,9 +38,6 @@
#define QEMU_VM_COMMAND 0x08 #define QEMU_VM_COMMAND 0x08
#define QEMU_VM_SECTION_FOOTER 0x7e #define QEMU_VM_SECTION_FOOTER 0x7e
/* for vl.c */
extern int only_migratable;
struct MigrationParams { struct MigrationParams {
bool blk; bool blk;
bool shared; bool shared;
@ -61,28 +57,6 @@ enum mig_rp_message_type {
typedef QLIST_HEAD(, LoadStateEntry) LoadStateEntry_Head; typedef QLIST_HEAD(, LoadStateEntry) LoadStateEntry_Head;
/* The current postcopy state is read/set by postcopy_state_get/set
* which update it atomically.
* The state is updated as postcopy messages are received, and
* in general only one thread should be writing to the state at any one
* time, initially the main thread and then the listen thread;
* Corner cases are where either thread finishes early and/or errors.
* The state is checked as messages are received to ensure that
* the source is sending us messages in the correct order.
* The state is also used by the RAM reception code to know if it
* has to place pages atomically, and the cleanup code at the end of
* the main thread to know if it has to delay cleanup until the end
* of postcopy.
*/
typedef enum {
POSTCOPY_INCOMING_NONE = 0, /* Initial state - no postcopy */
POSTCOPY_INCOMING_ADVISE,
POSTCOPY_INCOMING_DISCARD,
POSTCOPY_INCOMING_LISTENING,
POSTCOPY_INCOMING_RUNNING,
POSTCOPY_INCOMING_END
} PostcopyState;
/* State for the incoming migration */ /* State for the incoming migration */
struct MigrationIncomingState { struct MigrationIncomingState {
QEMUFile *from_src_file; QEMUFile *from_src_file;
@ -275,26 +249,6 @@ int ram_discard_range(const char *block_name, uint64_t start, size_t length);
int ram_postcopy_incoming_init(MigrationIncomingState *mis); int ram_postcopy_incoming_init(MigrationIncomingState *mis);
void ram_postcopy_migrated_memory_release(MigrationState *ms); void ram_postcopy_migrated_memory_release(MigrationState *ms);
/**
* @migrate_add_blocker - prevent migration from proceeding
*
* @reason - an error to be returned whenever migration is attempted
*
* @errp - [out] The reason (if any) we cannot block migration right now.
*
* @returns - 0 on success, -EBUSY/-EACCES on failure, with errp set.
*/
int migrate_add_blocker(Error *reason, Error **errp);
/**
* @migrate_del_blocker - remove a blocking error from migration
*
* @reason - the error blocking migration
*/
void migrate_del_blocker(Error *reason);
int check_migratable(Object *obj, Error **err);
bool migrate_release_ram(void); bool migrate_release_ram(void);
bool migrate_postcopy_ram(void); bool migrate_postcopy_ram(void);
bool migrate_zero_blocks(void); bool migrate_zero_blocks(void);
@ -357,8 +311,4 @@ void global_state_store_running(void);
void migration_page_queue_free(void); void migration_page_queue_free(void);
int ram_save_queue_pages(const char *rbname, ram_addr_t start, ram_addr_t len); int ram_save_queue_pages(const char *rbname, ram_addr_t start, ram_addr_t len);
uint64_t ram_pagesize_summary(void); uint64_t ram_pagesize_summary(void);
PostcopyState postcopy_state_get(void);
/* Set the state and return the old state */
PostcopyState postcopy_state_set(PostcopyState new_state);
#endif #endif

View File

@ -1067,4 +1067,6 @@ int64_t self_announce_delay(int round)
void dump_vmstate_json_to_file(FILE *out_fp); void dump_vmstate_json_to_file(FILE *out_fp);
bool vmstate_check_only_migratable(const VMStateDescription *vmsd);
#endif #endif

View File

@ -15,7 +15,7 @@
/* vl.c */ /* vl.c */
extern const char *bios_name; extern const char *bios_name;
extern int only_migratable;
extern const char *qemu_name; extern const char *qemu_name;
extern QemuUUID qemu_uuid; extern QemuUUID qemu_uuid;
extern bool qemu_uuid_set; extern bool qemu_uuid_set;
@ -75,8 +75,8 @@ void qemu_remove_exit_notifier(Notifier *notify);
void qemu_add_machine_init_done_notifier(Notifier *notify); void qemu_add_machine_init_done_notifier(Notifier *notify);
void qemu_remove_machine_init_done_notifier(Notifier *notify); void qemu_remove_machine_init_done_notifier(Notifier *notify);
int save_vmstate(const char *name); int save_vmstate(const char *name, Error **errp);
int load_vmstate(const char *name); int load_vmstate(const char *name, Error **errp);
void qemu_announce_self(void); void qemu_announce_self(void);

View File

@ -1,7 +1,7 @@
common-obj-y += migration.o socket.o fd.o exec.o common-obj-y += migration.o socket.o fd.o exec.o
common-obj-y += tls.o common-obj-y += tls.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 common-obj-y += vmstate.o page_cache.o
common-obj-y += qemu-file.o common-obj-y += qemu-file.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

View File

@ -17,6 +17,7 @@
#include "qemu/cutils.h" #include "qemu/cutils.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "qemu/main-loop.h" #include "qemu/main-loop.h"
#include "migration/blocker.h"
#include "migration/migration.h" #include "migration/migration.h"
#include "migration/qemu-file.h" #include "migration/qemu-file.h"
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
@ -77,13 +78,6 @@ static NotifierList migration_state_notifiers =
static bool deferred_incoming; static bool deferred_incoming;
/*
* Current state of incoming postcopy; note this is not part of
* MigrationIncomingState since it's state is used during cleanup
* at the end as MIS is being freed.
*/
static PostcopyState incoming_postcopy_state;
/* 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 */
@ -1149,21 +1143,6 @@ void migrate_del_blocker(Error *reason)
migration_blockers = g_slist_remove(migration_blockers, reason); migration_blockers = g_slist_remove(migration_blockers, reason);
} }
int check_migratable(Object *obj, Error **err)
{
DeviceClass *dc = DEVICE_GET_CLASS(obj);
if (only_migratable && dc->vmsd) {
if (dc->vmsd->unmigratable) {
error_setg(err, "Device %s is not migratable, but "
"--only-migratable was specified",
object_get_typename(obj));
return -1;
}
}
return 0;
}
void qmp_migrate_incoming(const char *uri, Error **errp) void qmp_migrate_incoming(const char *uri, Error **errp)
{ {
Error *local_err = NULL; Error *local_err = NULL;
@ -2097,14 +2076,3 @@ void migrate_fd_connect(MigrationState *s)
s->migration_thread_running = true; s->migration_thread_running = true;
} }
PostcopyState postcopy_state_get(void)
{
return atomic_mb_read(&incoming_postcopy_state);
}
/* Set the state and return the old state */
PostcopyState postcopy_state_set(PostcopyState new_state)
{
return atomic_xchg(&incoming_postcopy_state, new_state);
}

View File

@ -784,3 +784,21 @@ void postcopy_discard_send_finish(MigrationState *ms, PostcopyDiscardState *pds)
g_free(pds); g_free(pds);
} }
/*
* Current state of incoming postcopy; note this is not part of
* MigrationIncomingState since it's state is used during cleanup
* at the end as MIS is being freed.
*/
static PostcopyState incoming_postcopy_state;
PostcopyState postcopy_state_get(void)
{
return atomic_mb_read(&incoming_postcopy_state);
}
/* Set the state and return the old state */
PostcopyState postcopy_state_set(PostcopyState new_state)
{
return atomic_xchg(&incoming_postcopy_state, new_state);
}

View File

@ -81,6 +81,28 @@ int postcopy_place_page(MigrationIncomingState *mis, void *host, void *from,
int postcopy_place_page_zero(MigrationIncomingState *mis, void *host, int postcopy_place_page_zero(MigrationIncomingState *mis, void *host,
size_t pagesize); size_t pagesize);
/* The current postcopy state is read/set by postcopy_state_get/set
* which update it atomically.
* The state is updated as postcopy messages are received, and
* in general only one thread should be writing to the state at any one
* time, initially the main thread and then the listen thread;
* Corner cases are where either thread finishes early and/or errors.
* The state is checked as messages are received to ensure that
* the source is sending us messages in the correct order.
* The state is also used by the RAM reception code to know if it
* has to place pages atomically, and the cleanup code at the end of
* the main thread to know if it has to delay cleanup until the end
* of postcopy.
*/
typedef enum {
POSTCOPY_INCOMING_NONE = 0, /* Initial state - no postcopy */
POSTCOPY_INCOMING_ADVISE,
POSTCOPY_INCOMING_DISCARD,
POSTCOPY_INCOMING_LISTENING,
POSTCOPY_INCOMING_RUNNING,
POSTCOPY_INCOMING_END
} PostcopyState;
/* /*
* Allocate a page of memory that can be mapped at a later point in time * Allocate a page of memory that can be mapped at a later point in time
* using postcopy_place_page * using postcopy_place_page
@ -88,4 +110,8 @@ int postcopy_place_page_zero(MigrationIncomingState *mis, void *host,
*/ */
void *postcopy_get_tmp_page(MigrationIncomingState *mis); void *postcopy_get_tmp_page(MigrationIncomingState *mis);
PostcopyState postcopy_state_get(void);
/* Set the state and return the old state */
PostcopyState postcopy_state_set(PostcopyState new_state);
#endif #endif

View File

@ -48,8 +48,14 @@
/***********************************************************/ /***********************************************************/
/* ram save/restore */ /* ram save/restore */
/* RAM_SAVE_FLAG_ZERO used to be named RAM_SAVE_FLAG_COMPRESS, it
* worked for pages that where filled with the same char. We switched
* it to only search for the zero value. And to avoid confusion with
* RAM_SSAVE_FLAG_COMPRESS_PAGE just rename it.
*/
#define RAM_SAVE_FLAG_FULL 0x01 /* Obsolete, not used anymore */ #define RAM_SAVE_FLAG_FULL 0x01 /* Obsolete, not used anymore */
#define RAM_SAVE_FLAG_COMPRESS 0x02 #define RAM_SAVE_FLAG_ZERO 0x02
#define RAM_SAVE_FLAG_MEM_SIZE 0x04 #define RAM_SAVE_FLAG_MEM_SIZE 0x04
#define RAM_SAVE_FLAG_PAGE 0x08 #define RAM_SAVE_FLAG_PAGE 0x08
#define RAM_SAVE_FLAG_EOS 0x10 #define RAM_SAVE_FLAG_EOS 0x10
@ -436,20 +442,21 @@ void migrate_compress_threads_create(void)
* @offset: offset inside the block for the page * @offset: offset inside the block for the page
* in the lower bits, it contains flags * in the lower bits, it contains flags
*/ */
static size_t save_page_header(RAMState *rs, RAMBlock *block, ram_addr_t offset) static size_t save_page_header(RAMState *rs, QEMUFile *f, RAMBlock *block,
ram_addr_t offset)
{ {
size_t size, len; size_t size, len;
if (block == rs->last_sent_block) { if (block == rs->last_sent_block) {
offset |= RAM_SAVE_FLAG_CONTINUE; offset |= RAM_SAVE_FLAG_CONTINUE;
} }
qemu_put_be64(rs->f, offset); qemu_put_be64(f, offset);
size = 8; size = 8;
if (!(offset & RAM_SAVE_FLAG_CONTINUE)) { if (!(offset & RAM_SAVE_FLAG_CONTINUE)) {
len = strlen(block->idstr); len = strlen(block->idstr);
qemu_put_byte(rs->f, len); qemu_put_byte(f, len);
qemu_put_buffer(rs->f, (uint8_t *)block->idstr, len); qemu_put_buffer(f, (uint8_t *)block->idstr, len);
size += 1 + len; size += 1 + len;
rs->last_sent_block = block; rs->last_sent_block = block;
} }
@ -571,7 +578,7 @@ static int save_xbzrle_page(RAMState *rs, uint8_t **current_data,
} }
/* Send XBZRLE based compressed page */ /* Send XBZRLE based compressed page */
bytes_xbzrle = save_page_header(rs, block, bytes_xbzrle = save_page_header(rs, rs->f, block,
offset | RAM_SAVE_FLAG_XBZRLE); offset | RAM_SAVE_FLAG_XBZRLE);
qemu_put_byte(rs->f, ENCODING_FLAG_XBZRLE); qemu_put_byte(rs->f, ENCODING_FLAG_XBZRLE);
qemu_put_be16(rs->f, encoded_len); qemu_put_be16(rs->f, encoded_len);
@ -745,7 +752,7 @@ static int save_zero_page(RAMState *rs, RAMBlock *block, ram_addr_t offset,
if (is_zero_range(p, TARGET_PAGE_SIZE)) { if (is_zero_range(p, TARGET_PAGE_SIZE)) {
rs->zero_pages++; rs->zero_pages++;
rs->bytes_transferred += rs->bytes_transferred +=
save_page_header(rs, block, offset | RAM_SAVE_FLAG_COMPRESS); save_page_header(rs, rs->f, block, offset | RAM_SAVE_FLAG_ZERO);
qemu_put_byte(rs->f, 0); qemu_put_byte(rs->f, 0);
rs->bytes_transferred += 1; rs->bytes_transferred += 1;
pages = 1; pages = 1;
@ -834,7 +841,7 @@ static int ram_save_page(RAMState *rs, PageSearchStatus *pss, bool last_stage)
/* XBZRLE overflow or normal page */ /* XBZRLE overflow or normal page */
if (pages == -1) { if (pages == -1) {
rs->bytes_transferred += save_page_header(rs, block, rs->bytes_transferred += save_page_header(rs, rs->f, block,
offset | RAM_SAVE_FLAG_PAGE); offset | RAM_SAVE_FLAG_PAGE);
if (send_async) { if (send_async) {
qemu_put_buffer_async(rs->f, p, TARGET_PAGE_SIZE, qemu_put_buffer_async(rs->f, p, TARGET_PAGE_SIZE,
@ -860,7 +867,7 @@ static int do_compress_ram_page(QEMUFile *f, RAMBlock *block,
int bytes_sent, blen; int bytes_sent, blen;
uint8_t *p = block->host + (offset & TARGET_PAGE_MASK); uint8_t *p = block->host + (offset & TARGET_PAGE_MASK);
bytes_sent = save_page_header(rs, block, offset | bytes_sent = save_page_header(rs, f, block, offset |
RAM_SAVE_FLAG_COMPRESS_PAGE); RAM_SAVE_FLAG_COMPRESS_PAGE);
blen = qemu_put_compression_data(f, p, TARGET_PAGE_SIZE, blen = qemu_put_compression_data(f, p, TARGET_PAGE_SIZE,
migrate_compress_level()); migrate_compress_level());
@ -991,7 +998,7 @@ static int ram_save_compressed_page(RAMState *rs, PageSearchStatus *pss,
pages = save_zero_page(rs, block, offset, p); pages = save_zero_page(rs, block, offset, p);
if (pages == -1) { if (pages == -1) {
/* Make sure the first page is sent out before other pages */ /* Make sure the first page is sent out before other pages */
bytes_xmit = save_page_header(rs, block, offset | bytes_xmit = save_page_header(rs, rs->f, block, offset |
RAM_SAVE_FLAG_COMPRESS_PAGE); RAM_SAVE_FLAG_COMPRESS_PAGE);
blen = qemu_put_compression_data(rs->f, p, TARGET_PAGE_SIZE, blen = qemu_put_compression_data(rs->f, p, TARGET_PAGE_SIZE,
migrate_compress_level()); migrate_compress_level());
@ -2405,7 +2412,7 @@ static int ram_load_postcopy(QEMUFile *f)
trace_ram_load_postcopy_loop((uint64_t)addr, flags); trace_ram_load_postcopy_loop((uint64_t)addr, flags);
place_needed = false; place_needed = false;
if (flags & (RAM_SAVE_FLAG_COMPRESS | RAM_SAVE_FLAG_PAGE)) { if (flags & (RAM_SAVE_FLAG_ZERO | RAM_SAVE_FLAG_PAGE)) {
block = ram_block_from_stream(f, flags); block = ram_block_from_stream(f, flags);
host = host_from_ram_block_offset(block, addr); host = host_from_ram_block_offset(block, addr);
@ -2452,7 +2459,7 @@ static int ram_load_postcopy(QEMUFile *f)
last_host = host; last_host = host;
switch (flags & ~RAM_SAVE_FLAG_CONTINUE) { switch (flags & ~RAM_SAVE_FLAG_CONTINUE) {
case RAM_SAVE_FLAG_COMPRESS: case RAM_SAVE_FLAG_ZERO:
ch = qemu_get_byte(f); ch = qemu_get_byte(f);
memset(page_buffer, ch, TARGET_PAGE_SIZE); memset(page_buffer, ch, TARGET_PAGE_SIZE);
if (ch) { if (ch) {
@ -2541,7 +2548,7 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
flags = addr & ~TARGET_PAGE_MASK; flags = addr & ~TARGET_PAGE_MASK;
addr &= TARGET_PAGE_MASK; addr &= TARGET_PAGE_MASK;
if (flags & (RAM_SAVE_FLAG_COMPRESS | RAM_SAVE_FLAG_PAGE | if (flags & (RAM_SAVE_FLAG_ZERO | RAM_SAVE_FLAG_PAGE |
RAM_SAVE_FLAG_COMPRESS_PAGE | RAM_SAVE_FLAG_XBZRLE)) { RAM_SAVE_FLAG_COMPRESS_PAGE | RAM_SAVE_FLAG_XBZRLE)) {
RAMBlock *block = ram_block_from_stream(f, flags); RAMBlock *block = ram_block_from_stream(f, flags);
@ -2603,7 +2610,7 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
} }
break; break;
case RAM_SAVE_FLAG_COMPRESS: case RAM_SAVE_FLAG_ZERO:
ch = qemu_get_byte(f); ch = qemu_get_byte(f);
ram_handle_compressed(host, ch, TARGET_PAGE_SIZE); ram_handle_compressed(host, ch, TARGET_PAGE_SIZE);
break; break;

View File

@ -2069,7 +2069,7 @@ int qemu_loadvm_state(QEMUFile *f)
return ret; return ret;
} }
int save_vmstate(const char *name) int save_vmstate(const char *name, Error **errp)
{ {
BlockDriverState *bs, *bs1; BlockDriverState *bs, *bs1;
QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1; QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1;
@ -2079,29 +2079,27 @@ int save_vmstate(const char *name)
uint64_t vm_state_size; uint64_t vm_state_size;
qemu_timeval tv; qemu_timeval tv;
struct tm tm; struct tm tm;
Error *local_err = NULL;
AioContext *aio_context; AioContext *aio_context;
if (!bdrv_all_can_snapshot(&bs)) { if (!bdrv_all_can_snapshot(&bs)) {
error_report("Device '%s' is writable but does not support snapshots", error_setg(errp, "Device '%s' is writable but does not support "
bdrv_get_device_name(bs)); "snapshots", bdrv_get_device_name(bs));
return ret; return ret;
} }
/* Delete old snapshots of the same name */ /* Delete old snapshots of the same name */
if (name) { if (name) {
ret = bdrv_all_delete_snapshot(name, &bs1, &local_err); ret = bdrv_all_delete_snapshot(name, &bs1, errp);
if (ret < 0) { if (ret < 0) {
error_reportf_err(local_err, error_prepend(errp, "Error while deleting snapshot on device "
"Error while deleting snapshot on device '%s': ", "'%s': ", bdrv_get_device_name(bs1));
bdrv_get_device_name(bs1));
return ret; return ret;
} }
} }
bs = bdrv_all_find_vmstate_bs(); bs = bdrv_all_find_vmstate_bs();
if (bs == NULL) { if (bs == NULL) {
error_report("No block device can accept snapshots"); error_setg(errp, "No block device can accept snapshots");
return ret; return ret;
} }
aio_context = bdrv_get_aio_context(bs); aio_context = bdrv_get_aio_context(bs);
@ -2110,7 +2108,7 @@ int save_vmstate(const char *name)
ret = global_state_store(); ret = global_state_store();
if (ret) { if (ret) {
error_report("Error saving global state"); error_setg(errp, "Error saving global state");
return ret; return ret;
} }
vm_stop(RUN_STATE_SAVE_VM); vm_stop(RUN_STATE_SAVE_VM);
@ -2142,21 +2140,20 @@ int save_vmstate(const char *name)
/* save the VM state */ /* save the VM state */
f = qemu_fopen_bdrv(bs, 1); f = qemu_fopen_bdrv(bs, 1);
if (!f) { if (!f) {
error_report("Could not open VM state file"); error_setg(errp, "Could not open VM state file");
goto the_end; goto the_end;
} }
ret = qemu_savevm_state(f, &local_err); ret = qemu_savevm_state(f, errp);
vm_state_size = qemu_ftell(f); vm_state_size = qemu_ftell(f);
qemu_fclose(f); qemu_fclose(f);
if (ret < 0) { if (ret < 0) {
error_report_err(local_err);
goto the_end; goto the_end;
} }
ret = bdrv_all_create_snapshot(sn, bs, vm_state_size, &bs); ret = bdrv_all_create_snapshot(sn, bs, vm_state_size, &bs);
if (ret < 0) { if (ret < 0) {
error_report("Error while creating snapshot on '%s'", error_setg(errp, "Error while creating snapshot on '%s'",
bdrv_get_device_name(bs)); bdrv_get_device_name(bs));
goto the_end; goto the_end;
} }
@ -2229,7 +2226,7 @@ void qmp_xen_load_devices_state(const char *filename, Error **errp)
migration_incoming_state_destroy(); migration_incoming_state_destroy();
} }
int load_vmstate(const char *name) int load_vmstate(const char *name, Error **errp)
{ {
BlockDriverState *bs, *bs_vm_state; BlockDriverState *bs, *bs_vm_state;
QEMUSnapshotInfo sn; QEMUSnapshotInfo sn;
@ -2239,20 +2236,22 @@ int load_vmstate(const char *name)
MigrationIncomingState *mis = migration_incoming_get_current(); MigrationIncomingState *mis = migration_incoming_get_current();
if (!bdrv_all_can_snapshot(&bs)) { if (!bdrv_all_can_snapshot(&bs)) {
error_report("Device '%s' is writable but does not support snapshots", error_setg(errp,
bdrv_get_device_name(bs)); "Device '%s' is writable but does not support snapshots",
bdrv_get_device_name(bs));
return -ENOTSUP; return -ENOTSUP;
} }
ret = bdrv_all_find_snapshot(name, &bs); ret = bdrv_all_find_snapshot(name, &bs);
if (ret < 0) { if (ret < 0) {
error_report("Device '%s' does not have the requested snapshot '%s'", error_setg(errp,
bdrv_get_device_name(bs), name); "Device '%s' does not have the requested snapshot '%s'",
bdrv_get_device_name(bs), name);
return ret; return ret;
} }
bs_vm_state = bdrv_all_find_vmstate_bs(); bs_vm_state = bdrv_all_find_vmstate_bs();
if (!bs_vm_state) { if (!bs_vm_state) {
error_report("No block device supports snapshots"); error_setg(errp, "No block device supports snapshots");
return -ENOTSUP; return -ENOTSUP;
} }
aio_context = bdrv_get_aio_context(bs_vm_state); aio_context = bdrv_get_aio_context(bs_vm_state);
@ -2264,8 +2263,8 @@ int load_vmstate(const char *name)
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} else if (sn.vm_state_size == 0) { } else if (sn.vm_state_size == 0) {
error_report("This is a disk-only snapshot. Revert to it offline " error_setg(errp, "This is a disk-only snapshot. Revert to it "
"using qemu-img."); " offline using qemu-img");
return -EINVAL; return -EINVAL;
} }
@ -2274,7 +2273,7 @@ int load_vmstate(const char *name)
ret = bdrv_all_goto_snapshot(name, &bs); ret = bdrv_all_goto_snapshot(name, &bs);
if (ret < 0) { if (ret < 0) {
error_report("Error %d while activating snapshot '%s' on '%s'", error_setg(errp, "Error %d while activating snapshot '%s' on '%s'",
ret, name, bdrv_get_device_name(bs)); ret, name, bdrv_get_device_name(bs));
return ret; return ret;
} }
@ -2282,7 +2281,7 @@ int load_vmstate(const char *name)
/* restore the VM state */ /* restore the VM state */
f = qemu_fopen_bdrv(bs_vm_state, 0); f = qemu_fopen_bdrv(bs_vm_state, 0);
if (!f) { if (!f) {
error_report("Could not open VM state file"); error_setg(errp, "Could not open VM state file");
return -EINVAL; return -EINVAL;
} }
@ -2296,7 +2295,7 @@ int load_vmstate(const char *name)
migration_incoming_state_destroy(); migration_incoming_state_destroy();
if (ret < 0) { if (ret < 0) {
error_report("Error %d while loading VM state", ret); error_setg(errp, "Error %d while loading VM state", ret);
return ret; return ret;
} }
@ -2318,3 +2317,13 @@ void vmstate_register_ram_global(MemoryRegion *mr)
{ {
vmstate_register_ram(mr, NULL); vmstate_register_ram(mr, NULL);
} }
bool vmstate_check_only_migratable(const VMStateDescription *vmsd)
{
/* check needed if --only-migratable is specified */
if (!only_migratable) {
return true;
}
return !(vmsd && vmsd->unmigratable);
}

View File

@ -62,14 +62,18 @@ void replay_vmstate_register(void)
void replay_vmstate_init(void) void replay_vmstate_init(void)
{ {
Error *err = NULL;
if (replay_snapshot) { if (replay_snapshot) {
if (replay_mode == REPLAY_MODE_RECORD) { if (replay_mode == REPLAY_MODE_RECORD) {
if (save_vmstate(replay_snapshot) != 0) { if (save_vmstate(replay_snapshot, &err) != 0) {
error_report_err(err);
error_report("Could not create snapshot for icount record"); error_report("Could not create snapshot for icount record");
exit(1); exit(1);
} }
} else if (replay_mode == REPLAY_MODE_PLAY) { } else if (replay_mode == REPLAY_MODE_PLAY) {
if (load_vmstate(replay_snapshot) != 0) { if (load_vmstate(replay_snapshot, &err) != 0) {
error_report_err(err);
error_report("Could not load snapshot for icount replay"); error_report("Could not load snapshot for icount replay");
exit(1); exit(1);
} }

View File

@ -1,6 +1,6 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qemu-common.h" #include "qemu-common.h"
#include "migration/migration.h" #include "migration/blocker.h"
int migrate_add_blocker(Error *reason, Error **errp) int migrate_add_blocker(Error *reason, Error **errp)
{ {

View File

@ -1,7 +1,6 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qemu-common.h" #include "qemu-common.h"
#include "migration/vmstate.h" #include "migration/vmstate.h"
#include "migration/migration.h"
const VMStateDescription vmstate_dummy = {}; const VMStateDescription vmstate_dummy = {};
@ -21,7 +20,7 @@ void vmstate_unregister(DeviceState *dev,
{ {
} }
int check_migratable(Object *obj, Error **err) bool vmstate_check_only_migratable(const VMStateDescription *vmsd)
{ {
return 0; return true;
} }

View File

@ -43,7 +43,7 @@
#include "standard-headers/asm-x86/hyperv.h" #include "standard-headers/asm-x86/hyperv.h"
#include "hw/pci/pci.h" #include "hw/pci/pci.h"
#include "hw/pci/msi.h" #include "hw/pci/msi.h"
#include "migration/migration.h" #include "migration/blocker.h"
#include "exec/memattrs.h" #include "exec/memattrs.h"
#include "trace.h" #include "trace.h"

View File

@ -554,7 +554,7 @@ tests/test-thread-pool$(EXESUF): tests/test-thread-pool.o $(test-block-obj-y)
tests/test-iov$(EXESUF): tests/test-iov.o $(test-util-obj-y) tests/test-iov$(EXESUF): tests/test-iov.o $(test-util-obj-y)
tests/test-hbitmap$(EXESUF): tests/test-hbitmap.o $(test-util-obj-y) tests/test-hbitmap$(EXESUF): tests/test-hbitmap.o $(test-util-obj-y)
tests/test-x86-cpuid$(EXESUF): tests/test-x86-cpuid.o tests/test-x86-cpuid$(EXESUF): tests/test-x86-cpuid.o
tests/test-xbzrle$(EXESUF): tests/test-xbzrle.o migration/xbzrle.o page_cache.o $(test-util-obj-y) tests/test-xbzrle$(EXESUF): tests/test-xbzrle.o migration/xbzrle.o migration/page_cache.o $(test-util-obj-y)
tests/test-cutils$(EXESUF): tests/test-cutils.o util/cutils.o tests/test-cutils$(EXESUF): tests/test-cutils.o util/cutils.o
tests/test-int128$(EXESUF): tests/test-int128.o tests/test-int128$(EXESUF): tests/test-int128.o
tests/rcutorture$(EXESUF): tests/rcutorture.o $(test-util-obj-y) tests/rcutorture$(EXESUF): tests/rcutorture.o $(test-util-obj-y)

4
vl.c
View File

@ -4701,7 +4701,9 @@ int main(int argc, char **argv, char **envp)
if (replay_mode != REPLAY_MODE_NONE) { if (replay_mode != REPLAY_MODE_NONE) {
replay_vmstate_init(); replay_vmstate_init();
} else if (loadvm) { } else if (loadvm) {
if (load_vmstate(loadvm) < 0) { Error *local_err = NULL;
if (load_vmstate(loadvm, &local_err) < 0) {
error_report_err(local_err);
autostart = 0; autostart = 0;
} }
} }