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:
		
						commit
						2ccbd47c1d
					
				| 
						 | 
					@ -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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
								
								
								
								
							
							
						
						
									
										9
									
								
								hmp.c
								
								
								
								
							| 
						 | 
					@ -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)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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, ...) \
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
								
								
								
								
							
							
						
						
									
										4
									
								
								vl.c
								
								
								
								
							| 
						 | 
					@ -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;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue