diff options
author | Stefan Hajnoczi <stefanha@redhat.com> | 2017-05-18 10:05:50 +0100 |
---|---|---|
committer | Stefan Hajnoczi <stefanha@redhat.com> | 2017-05-18 10:05:52 +0100 |
commit | 2ccbd47c1def618b31af1d88b550f6d2bdd15b0f (patch) | |
tree | 9944ab67319550408e114c6842722e326df7c172 | |
parent | adb354dd1e00aa6b8bd674f0e1f70008badded0f (diff) | |
parent | 1bfe5f0586083747f1602931713111673849cd9d (diff) |
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>
36 files changed, 194 insertions, 158 deletions
diff --git a/Makefile.objs b/Makefile.objs index 6167e7b17d..2100845ce2 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -49,7 +49,6 @@ common-obj-$(CONFIG_POSIX) += os-posix.o common-obj-$(CONFIG_LINUX) += fsdev/ common-obj-y += migration/ -common-obj-y += page_cache.o #aio.o common-obj-$(CONFIG_SPICE) += spice-qemu-char.o diff --git a/block/qcow.c b/block/qcow.c index 5d147b962e..95ab123407 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -32,7 +32,7 @@ #include <zlib.h> #include "qapi/qmp/qerror.h" #include "crypto/cipher.h" -#include "migration/migration.h" +#include "migration/blocker.h" /**************************************************************/ /* QEMU COW block driver with compression and encryption support */ diff --git a/block/vdi.c b/block/vdi.c index d12d9cdc79..79af47763b 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -55,7 +55,7 @@ #include "sysemu/block-backend.h" #include "qemu/module.h" #include "qemu/bswap.h" -#include "migration/migration.h" +#include "migration/blocker.h" #include "qemu/coroutine.h" #include "qemu/cutils.h" #include "qemu/uuid.h" diff --git a/block/vhdx.c b/block/vhdx.c index e8fe3fb5e9..8b270b57c9 100644 --- a/block/vhdx.c +++ b/block/vhdx.c @@ -24,7 +24,7 @@ #include "qemu/crc32c.h" #include "qemu/bswap.h" #include "block/vhdx.h" -#include "migration/migration.h" +#include "migration/blocker.h" #include "qemu/uuid.h" /* Options for VHDX creation */ diff --git a/block/vmdk.c b/block/vmdk.c index c61b9cc8e0..55581b03fe 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -31,7 +31,7 @@ #include "qemu/error-report.h" #include "qemu/module.h" #include "qemu/bswap.h" -#include "migration/migration.h" +#include "migration/blocker.h" #include "qemu/cutils.h" #include <zlib.h> diff --git a/block/vpc.c b/block/vpc.c index ecfee77149..4240ba9d1c 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -28,7 +28,7 @@ #include "block/block_int.h" #include "sysemu/block-backend.h" #include "qemu/module.h" -#include "migration/migration.h" +#include "migration/blocker.h" #include "qemu/bswap.h" #include "qemu/uuid.h" diff --git a/block/vvfat.c b/block/vvfat.c index 9c82371360..426ca70e35 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -28,7 +28,7 @@ #include "block/block_int.h" #include "qemu/module.h" #include "qemu/bswap.h" -#include "migration/migration.h" +#include "migration/blocker.h" #include "qapi/qmp/qint.h" #include "qapi/qmp/qbool.h" #include "qapi/qmp/qstring.h" @@ -1274,17 +1274,22 @@ void hmp_loadvm(Monitor *mon, const QDict *qdict) { int saved_vm_running = runstate_is_running(); const char *name = qdict_get_str(qdict, "name"); + Error *err = NULL; 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(); } + hmp_handle_error(mon, &err); } 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) diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c index c80ba67389..ab3e22f231 100644 --- a/hw/9pfs/9p.c +++ b/hw/9pfs/9p.c @@ -23,7 +23,7 @@ #include "9p-xattr.h" #include "coth.h" #include "trace.h" -#include "migration/migration.h" +#include "migration/blocker.h" int open_fd_hw; int total_open_fd; diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 1863db9d0a..71ff95fd71 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -37,7 +37,7 @@ #include "hw/boards.h" #include "hw/sysbus.h" #include "qapi-event.h" -#include "migration/migration.h" +#include "migration/vmstate.h" bool qdev_hotplug = false; static bool qdev_hot_added = false; @@ -861,6 +861,20 @@ static bool device_get_realized(Object *obj, Error **errp) 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) { DeviceState *dev = DEVICE(obj); @@ -870,7 +884,6 @@ static void device_set_realized(Object *obj, bool value, Error **errp) Error *local_err = NULL; bool unattached_parent = false; static int unattached_count; - int ret; if (dev->hotplugged && !dc->hotpluggable) { 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) { - ret = check_migratable(obj, &local_err); - if (ret < 0) { + if (!check_only_migratable(obj, &local_err)) { goto fail; } diff --git a/hw/display/qxl.c b/hw/display/qxl.c index 4d94cecd72..ad09bb98f9 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -26,7 +26,7 @@ #include "qemu/queue.h" #include "qemu/atomic.h" #include "sysemu/sysemu.h" -#include "migration/migration.h" +#include "migration/blocker.h" #include "trace.h" #include "qxl.h" diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index cfb5dfa336..58dc0b2737 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -19,7 +19,7 @@ #include "hw/virtio/virtio.h" #include "hw/virtio/virtio-gpu.h" #include "hw/virtio/virtio-bus.h" -#include "migration/migration.h" +#include "migration/blocker.h" #include "qemu/log.h" #include "qapi/error.h" diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c index ec952ece93..af5cd367e9 100644 --- a/hw/intc/arm_gic_kvm.c +++ b/hw/intc/arm_gic_kvm.c @@ -24,7 +24,7 @@ #include "qemu-common.h" #include "cpu.h" #include "hw/sysbus.h" -#include "migration/migration.h" +#include "migration/blocker.h" #include "sysemu/kvm.h" #include "kvm_arm.h" #include "gic_internal.h" diff --git a/hw/intc/arm_gicv3_its_kvm.c b/hw/intc/arm_gicv3_its_kvm.c index bd4f3aafc6..a0441d6bd1 100644 --- a/hw/intc/arm_gicv3_its_kvm.c +++ b/hw/intc/arm_gicv3_its_kvm.c @@ -24,7 +24,7 @@ #include "sysemu/sysemu.h" #include "sysemu/kvm.h" #include "kvm_arm.h" -#include "migration/migration.h" +#include "migration/blocker.h" #define TYPE_KVM_ARM_ITS "arm-its-kvm" #define KVM_ARM_ITS(obj) OBJECT_CHECK(GICv3ITSState, (obj), TYPE_KVM_ARM_ITS) diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c index 19aab56072..4ee2baa691 100644 --- a/hw/intc/arm_gicv3_kvm.c +++ b/hw/intc/arm_gicv3_kvm.c @@ -28,7 +28,7 @@ #include "kvm_arm.h" #include "gicv3_internal.h" #include "vgic_common.h" -#include "migration/migration.h" +#include "migration/blocker.h" #ifdef DEBUG_GICV3_KVM #define DPRINTF(fmt, ...) \ diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c index 82ce8378bf..475e36a4c7 100644 --- a/hw/misc/ivshmem.c +++ b/hw/misc/ivshmem.c @@ -25,7 +25,7 @@ #include "hw/pci/msi.h" #include "hw/pci/msix.h" #include "sysemu/kvm.h" -#include "migration/migration.h" +#include "migration/blocker.h" #include "qemu/error-report.h" #include "qemu/event_notifier.h" #include "qom/object_interfaces.h" diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c index 8f53ac3795..cd4ab05233 100644 --- a/hw/scsi/vhost-scsi.c +++ b/hw/scsi/vhost-scsi.c @@ -21,7 +21,7 @@ #include "qemu/error-report.h" #include "qemu/queue.h" #include "monitor/monitor.h" -#include "migration/migration.h" +#include "migration/blocker.h" #include "hw/virtio/vhost-scsi.h" #include "hw/virtio/vhost.h" #include "hw/virtio/virtio-scsi.h" diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 0001e60b77..03a46a7429 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -25,7 +25,7 @@ #include "exec/address-spaces.h" #include "hw/virtio/virtio-bus.h" #include "hw/virtio/virtio-access.h" -#include "migration/migration.h" +#include "migration/blocker.h" #include "sysemu/dma.h" /* enabled until disconnected backend stabilizes */ diff --git a/include/migration/blocker.h b/include/migration/blocker.h new file mode 100644 index 0000000000..acd27018e9 --- /dev/null +++ b/include/migration/blocker.h @@ -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 diff --git a/include/migration/migration.h b/include/migration/migration.h index e29cb0144b..49ec5015e5 100644 --- a/include/migration/migration.h +++ b/include/migration/migration.h @@ -22,7 +22,6 @@ #include "qapi-types.h" #include "exec/cpu-common.h" #include "qemu/coroutine_int.h" -#include "qom/object.h" #define QEMU_VM_FILE_MAGIC 0x5145564d #define QEMU_VM_FILE_VERSION_COMPAT 0x00000002 @@ -39,9 +38,6 @@ #define QEMU_VM_COMMAND 0x08 #define QEMU_VM_SECTION_FOOTER 0x7e -/* for vl.c */ -extern int only_migratable; - struct MigrationParams { bool blk; bool shared; @@ -61,28 +57,6 @@ enum mig_rp_message_type { 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 */ struct MigrationIncomingState { 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); 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_postcopy_ram(void); bool migrate_zero_blocks(void); @@ -357,8 +311,4 @@ void global_state_store_running(void); void migration_page_queue_free(void); int ram_save_queue_pages(const char *rbname, ram_addr_t start, ram_addr_t len); 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 diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h index f4bf3f1b4e..848965963a 100644 --- a/include/migration/vmstate.h +++ b/include/migration/vmstate.h @@ -1067,4 +1067,6 @@ int64_t self_announce_delay(int round) void dump_vmstate_json_to_file(FILE *out_fp); +bool vmstate_check_only_migratable(const VMStateDescription *vmsd); + #endif diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index be9e22c955..83c1ceb33e 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -15,7 +15,7 @@ /* vl.c */ extern const char *bios_name; - +extern int only_migratable; extern const char *qemu_name; extern QemuUUID qemu_uuid; 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_remove_machine_init_done_notifier(Notifier *notify); -int save_vmstate(const char *name); -int load_vmstate(const char *name); +int save_vmstate(const char *name, Error **errp); +int load_vmstate(const char *name, Error **errp); void qemu_announce_self(void); diff --git a/migration/Makefile.objs b/migration/Makefile.objs index 480dd493a9..c1920b6fc0 100644 --- a/migration/Makefile.objs +++ b/migration/Makefile.objs @@ -1,7 +1,7 @@ common-obj-y += migration.o socket.o fd.o exec.o common-obj-y += tls.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-channel.o common-obj-y += xbzrle.o postcopy-ram.o diff --git a/migration/migration.c b/migration/migration.c index a5ade23e24..0304c013f3 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -17,6 +17,7 @@ #include "qemu/cutils.h" #include "qemu/error-report.h" #include "qemu/main-loop.h" +#include "migration/blocker.h" #include "migration/migration.h" #include "migration/qemu-file.h" #include "sysemu/sysemu.h" @@ -77,13 +78,6 @@ static NotifierList migration_state_notifiers = 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 migrations at once. For now we don't need to add dynamic creation of migration */ @@ -1149,21 +1143,6 @@ void migrate_del_blocker(Error *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) { Error *local_err = NULL; @@ -2097,14 +2076,3 @@ void migrate_fd_connect(MigrationState *s) 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); -} - diff --git a/page_cache.c b/migration/page_cache.c index 5f8578736e..5f8578736e 100644 --- a/page_cache.c +++ b/migration/page_cache.c diff --git a/include/migration/page_cache.h b/migration/page_cache.h index 10ed53274c..10ed53274c 100644 --- a/include/migration/page_cache.h +++ b/migration/page_cache.h diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c index cdadaf6578..a0489f6542 100644 --- a/migration/postcopy-ram.c +++ b/migration/postcopy-ram.c @@ -784,3 +784,21 @@ void postcopy_discard_send_finish(MigrationState *ms, PostcopyDiscardState *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); +} diff --git a/migration/postcopy-ram.h b/migration/postcopy-ram.h index 4c25f03be2..52d51e8007 100644 --- a/migration/postcopy-ram.h +++ b/migration/postcopy-ram.h @@ -81,6 +81,28 @@ int postcopy_place_page(MigrationIncomingState *mis, void *host, void *from, int postcopy_place_page_zero(MigrationIncomingState *mis, void *host, 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 * using postcopy_place_page @@ -88,4 +110,8 @@ int postcopy_place_page_zero(MigrationIncomingState *mis, void *host, */ 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 diff --git a/migration/ram.c b/migration/ram.c index 293d27ce83..76c118c271 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -48,8 +48,14 @@ /***********************************************************/ /* 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_COMPRESS 0x02 +#define RAM_SAVE_FLAG_ZERO 0x02 #define RAM_SAVE_FLAG_MEM_SIZE 0x04 #define RAM_SAVE_FLAG_PAGE 0x08 #define RAM_SAVE_FLAG_EOS 0x10 @@ -436,20 +442,21 @@ void migrate_compress_threads_create(void) * @offset: offset inside the block for the page * 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; if (block == rs->last_sent_block) { offset |= RAM_SAVE_FLAG_CONTINUE; } - qemu_put_be64(rs->f, offset); + qemu_put_be64(f, offset); size = 8; if (!(offset & RAM_SAVE_FLAG_CONTINUE)) { len = strlen(block->idstr); - qemu_put_byte(rs->f, len); - qemu_put_buffer(rs->f, (uint8_t *)block->idstr, len); + qemu_put_byte(f, len); + qemu_put_buffer(f, (uint8_t *)block->idstr, len); size += 1 + len; 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 */ - bytes_xbzrle = save_page_header(rs, block, + bytes_xbzrle = save_page_header(rs, rs->f, block, offset | RAM_SAVE_FLAG_XBZRLE); qemu_put_byte(rs->f, ENCODING_FLAG_XBZRLE); 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)) { rs->zero_pages++; 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); rs->bytes_transferred += 1; pages = 1; @@ -834,7 +841,7 @@ static int ram_save_page(RAMState *rs, PageSearchStatus *pss, bool last_stage) /* XBZRLE overflow or normal page */ 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); if (send_async) { 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; 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); blen = qemu_put_compression_data(f, p, TARGET_PAGE_SIZE, 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); if (pages == -1) { /* 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); blen = qemu_put_compression_data(rs->f, p, TARGET_PAGE_SIZE, migrate_compress_level()); @@ -2405,7 +2412,7 @@ static int ram_load_postcopy(QEMUFile *f) trace_ram_load_postcopy_loop((uint64_t)addr, flags); 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); host = host_from_ram_block_offset(block, addr); @@ -2452,7 +2459,7 @@ static int ram_load_postcopy(QEMUFile *f) last_host = host; switch (flags & ~RAM_SAVE_FLAG_CONTINUE) { - case RAM_SAVE_FLAG_COMPRESS: + case RAM_SAVE_FLAG_ZERO: ch = qemu_get_byte(f); memset(page_buffer, ch, TARGET_PAGE_SIZE); if (ch) { @@ -2541,7 +2548,7 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id) flags = 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)) { RAMBlock *block = ram_block_from_stream(f, flags); @@ -2603,7 +2610,7 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id) } break; - case RAM_SAVE_FLAG_COMPRESS: + case RAM_SAVE_FLAG_ZERO: ch = qemu_get_byte(f); ram_handle_compressed(host, ch, TARGET_PAGE_SIZE); break; diff --git a/migration/savevm.c b/migration/savevm.c index 7f66d58a7e..f5e81948e6 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -2069,7 +2069,7 @@ int qemu_loadvm_state(QEMUFile *f) return ret; } -int save_vmstate(const char *name) +int save_vmstate(const char *name, Error **errp) { BlockDriverState *bs, *bs1; 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; qemu_timeval tv; struct tm tm; - Error *local_err = NULL; AioContext *aio_context; if (!bdrv_all_can_snapshot(&bs)) { - error_report("Device '%s' is writable but does not support snapshots", - bdrv_get_device_name(bs)); + error_setg(errp, "Device '%s' is writable but does not support " + "snapshots", bdrv_get_device_name(bs)); return ret; } /* Delete old snapshots of the same name */ if (name) { - ret = bdrv_all_delete_snapshot(name, &bs1, &local_err); + ret = bdrv_all_delete_snapshot(name, &bs1, errp); if (ret < 0) { - error_reportf_err(local_err, - "Error while deleting snapshot on device '%s': ", - bdrv_get_device_name(bs1)); + error_prepend(errp, "Error while deleting snapshot on device " + "'%s': ", bdrv_get_device_name(bs1)); return ret; } } bs = bdrv_all_find_vmstate_bs(); if (bs == NULL) { - error_report("No block device can accept snapshots"); + error_setg(errp, "No block device can accept snapshots"); return ret; } aio_context = bdrv_get_aio_context(bs); @@ -2110,7 +2108,7 @@ int save_vmstate(const char *name) ret = global_state_store(); if (ret) { - error_report("Error saving global state"); + error_setg(errp, "Error saving global state"); return ret; } vm_stop(RUN_STATE_SAVE_VM); @@ -2142,21 +2140,20 @@ int save_vmstate(const char *name) /* save the VM state */ f = qemu_fopen_bdrv(bs, 1); if (!f) { - error_report("Could not open VM state file"); + error_setg(errp, "Could not open VM state file"); goto the_end; } - ret = qemu_savevm_state(f, &local_err); + ret = qemu_savevm_state(f, errp); vm_state_size = qemu_ftell(f); qemu_fclose(f); if (ret < 0) { - error_report_err(local_err); goto the_end; } ret = bdrv_all_create_snapshot(sn, bs, vm_state_size, &bs); if (ret < 0) { - error_report("Error while creating snapshot on '%s'", - bdrv_get_device_name(bs)); + error_setg(errp, "Error while creating snapshot on '%s'", + bdrv_get_device_name(bs)); goto the_end; } @@ -2229,7 +2226,7 @@ void qmp_xen_load_devices_state(const char *filename, Error **errp) migration_incoming_state_destroy(); } -int load_vmstate(const char *name) +int load_vmstate(const char *name, Error **errp) { BlockDriverState *bs, *bs_vm_state; QEMUSnapshotInfo sn; @@ -2239,20 +2236,22 @@ int load_vmstate(const char *name) MigrationIncomingState *mis = migration_incoming_get_current(); if (!bdrv_all_can_snapshot(&bs)) { - error_report("Device '%s' is writable but does not support snapshots", - bdrv_get_device_name(bs)); + error_setg(errp, + "Device '%s' is writable but does not support snapshots", + bdrv_get_device_name(bs)); return -ENOTSUP; } ret = bdrv_all_find_snapshot(name, &bs); if (ret < 0) { - error_report("Device '%s' does not have the requested snapshot '%s'", - bdrv_get_device_name(bs), name); + error_setg(errp, + "Device '%s' does not have the requested snapshot '%s'", + bdrv_get_device_name(bs), name); return ret; } bs_vm_state = bdrv_all_find_vmstate_bs(); if (!bs_vm_state) { - error_report("No block device supports snapshots"); + error_setg(errp, "No block device supports snapshots"); return -ENOTSUP; } aio_context = bdrv_get_aio_context(bs_vm_state); @@ -2264,8 +2263,8 @@ int load_vmstate(const char *name) if (ret < 0) { return ret; } else if (sn.vm_state_size == 0) { - error_report("This is a disk-only snapshot. Revert to it offline " - "using qemu-img."); + error_setg(errp, "This is a disk-only snapshot. Revert to it " + " offline using qemu-img"); return -EINVAL; } @@ -2274,7 +2273,7 @@ int load_vmstate(const char *name) ret = bdrv_all_goto_snapshot(name, &bs); 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)); return ret; } @@ -2282,7 +2281,7 @@ int load_vmstate(const char *name) /* restore the VM state */ f = qemu_fopen_bdrv(bs_vm_state, 0); if (!f) { - error_report("Could not open VM state file"); + error_setg(errp, "Could not open VM state file"); return -EINVAL; } @@ -2296,7 +2295,7 @@ int load_vmstate(const char *name) migration_incoming_state_destroy(); if (ret < 0) { - error_report("Error %d while loading VM state", ret); + error_setg(errp, "Error %d while loading VM state", ret); return ret; } @@ -2318,3 +2317,13 @@ void vmstate_register_ram_global(MemoryRegion *mr) { 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); +} diff --git a/replay/replay-snapshot.c b/replay/replay-snapshot.c index 8cced4604f..c75cd38ece 100644 --- a/replay/replay-snapshot.c +++ b/replay/replay-snapshot.c @@ -62,14 +62,18 @@ void replay_vmstate_register(void) void replay_vmstate_init(void) { + Error *err = NULL; + if (replay_snapshot) { 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"); exit(1); } } 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"); exit(1); } diff --git a/stubs/migr-blocker.c b/stubs/migr-blocker.c index a5ba18f53d..2b64ac9560 100644 --- a/stubs/migr-blocker.c +++ b/stubs/migr-blocker.c @@ -1,6 +1,6 @@ #include "qemu/osdep.h" #include "qemu-common.h" -#include "migration/migration.h" +#include "migration/blocker.h" int migrate_add_blocker(Error *reason, Error **errp) { diff --git a/stubs/vmstate.c b/stubs/vmstate.c index 6d52f29bb2..6399474e49 100644 --- a/stubs/vmstate.c +++ b/stubs/vmstate.c @@ -1,7 +1,6 @@ #include "qemu/osdep.h" #include "qemu-common.h" #include "migration/vmstate.h" -#include "migration/migration.h" 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; } diff --git a/target/i386/kvm.c b/target/i386/kvm.c index 55865dbee0..011d4a55b1 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c @@ -43,7 +43,7 @@ #include "standard-headers/asm-x86/hyperv.h" #include "hw/pci/pci.h" #include "hw/pci/msi.h" -#include "migration/migration.h" +#include "migration/blocker.h" #include "exec/memattrs.h" #include "trace.h" diff --git a/tests/Makefile.include b/tests/Makefile.include index 16ff8f399f..4277597e93 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -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-hbitmap$(EXESUF): tests/test-hbitmap.o $(test-util-obj-y) 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-int128$(EXESUF): tests/test-int128.o tests/rcutorture$(EXESUF): tests/rcutorture.o $(test-util-obj-y) @@ -4701,7 +4701,9 @@ int main(int argc, char **argv, char **envp) if (replay_mode != REPLAY_MODE_NONE) { replay_vmstate_init(); } 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; } } |