diff options
Diffstat (limited to 'migration/savevm.c')
| -rw-r--r-- | migration/savevm.c | 64 |
1 files changed, 32 insertions, 32 deletions
diff --git a/migration/savevm.c b/migration/savevm.c index 6bfd4893e0..be3f885119 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -62,8 +62,6 @@ const unsigned int postcopy_ram_discard_version = 0; -static bool skip_section_footers; - /* Subcommands for QEMU_VM_COMMAND */ enum qemu_vm_cmd { MIG_CMD_INVALID = 0, /* Must be 0 */ @@ -287,7 +285,6 @@ typedef struct SaveStateEntry { typedef struct SaveState { QTAILQ_HEAD(, SaveStateEntry) handlers; int global_section_id; - bool skip_configuration; uint32_t len; const char *name; uint32_t target_page_bits; @@ -296,15 +293,8 @@ typedef struct SaveState { static SaveState savevm_state = { .handlers = QTAILQ_HEAD_INITIALIZER(savevm_state.handlers), .global_section_id = 0, - .skip_configuration = false, }; -void savevm_skip_configuration(void) -{ - savevm_state.skip_configuration = true; -} - - static void configuration_pre_save(void *opaque) { SaveState *state = opaque; @@ -769,11 +759,6 @@ static void vmstate_save(QEMUFile *f, SaveStateEntry *se, QJSON *vmdesc) vmstate_save_state(f, se->vmsd, se->opaque, vmdesc); } -void savevm_skip_section_footers(void) -{ - skip_section_footers = true; -} - /* * Write the header for device section (QEMU_VM_SECTION START/END/PART/FULL) */ @@ -801,7 +786,7 @@ static void save_section_header(QEMUFile *f, SaveStateEntry *se, */ static void save_section_footer(QEMUFile *f, SaveStateEntry *se) { - if (!skip_section_footers) { + if (migrate_get_current()->send_section_footer) { qemu_put_byte(f, QEMU_VM_SECTION_FOOTER); qemu_put_be32(f, se->section_id); } @@ -958,23 +943,16 @@ bool qemu_savevm_state_blocked(Error **errp) return false; } -static bool enforce_config_section(void) -{ - MachineState *machine = MACHINE(qdev_get_machine()); - return machine->enforce_config_section; -} - void qemu_savevm_state_header(QEMUFile *f) { trace_savevm_state_header(); qemu_put_be32(f, QEMU_VM_FILE_MAGIC); qemu_put_be32(f, QEMU_VM_FILE_VERSION); - if (!savevm_state.skip_configuration || enforce_config_section()) { + if (migrate_get_current()->send_configuration) { qemu_put_byte(f, QEMU_VM_CONFIGURATION); vmstate_save_state(f, &vmstate_configuration, &savevm_state, 0); } - } void qemu_savevm_state_begin(QEMUFile *f) @@ -1810,7 +1788,7 @@ static bool check_section_footer(QEMUFile *f, SaveStateEntry *se) uint8_t read_mark; uint32_t read_section_id; - if (skip_section_footers) { + if (!migrate_get_current()->send_section_footer) { /* No footer to check */ return true; } @@ -1995,7 +1973,7 @@ int qemu_loadvm_state(QEMUFile *f) return -ENOTSUP; } - if (!savevm_state.skip_configuration || enforce_config_section()) { + if (migrate_get_current()->send_configuration) { if (qemu_get_byte(f) != QEMU_VM_CONFIGURATION) { error_report("Configuration section missing"); return -EINVAL; @@ -2107,6 +2085,8 @@ int save_snapshot(const char *name, Error **errp) } vm_stop(RUN_STATE_SAVE_VM); + bdrv_drain_all_begin(); + aio_context_acquire(aio_context); memset(sn, 0, sizeof(*sn)); @@ -2144,6 +2124,14 @@ int save_snapshot(const char *name, Error **errp) goto the_end; } + /* The bdrv_all_create_snapshot() call that follows acquires the AioContext + * for itself. BDRV_POLL_WHILE() does not support nested locking because + * it only releases the lock once. Therefore synchronous I/O will deadlock + * unless we release the AioContext before bdrv_all_create_snapshot(). + */ + aio_context_release(aio_context); + aio_context = NULL; + ret = bdrv_all_create_snapshot(sn, bs, vm_state_size, &bs); if (ret < 0) { error_setg(errp, "Error while creating snapshot on '%s'", @@ -2154,7 +2142,12 @@ int save_snapshot(const char *name, Error **errp) ret = 0; the_end: - aio_context_release(aio_context); + if (aio_context) { + aio_context_release(aio_context); + } + + bdrv_drain_all_end(); + if (saved_vm_running) { vm_start(); } @@ -2263,20 +2256,21 @@ int load_snapshot(const char *name, Error **errp) } /* Flush all IO requests so they don't interfere with the new state. */ - bdrv_drain_all(); + bdrv_drain_all_begin(); ret = bdrv_all_goto_snapshot(name, &bs); if (ret < 0) { error_setg(errp, "Error %d while activating snapshot '%s' on '%s'", ret, name, bdrv_get_device_name(bs)); - return ret; + goto err_drain; } /* restore the VM state */ f = qemu_fopen_bdrv(bs_vm_state, 0); if (!f) { error_setg(errp, "Could not open VM state file"); - return -EINVAL; + ret = -EINVAL; + goto err_drain; } qemu_system_reset(SHUTDOWN_CAUSE_NONE); @@ -2284,15 +2278,21 @@ int load_snapshot(const char *name, Error **errp) aio_context_acquire(aio_context); ret = qemu_loadvm_state(f); + migration_incoming_state_destroy(); aio_context_release(aio_context); - migration_incoming_state_destroy(); + bdrv_drain_all_end(); + if (ret < 0) { error_setg(errp, "Error %d while loading VM state", ret); return ret; } return 0; + +err_drain: + bdrv_drain_all_end(); + return ret; } void vmstate_register_ram(MemoryRegion *mr, DeviceState *dev) @@ -2314,7 +2314,7 @@ void vmstate_register_ram_global(MemoryRegion *mr) bool vmstate_check_only_migratable(const VMStateDescription *vmsd) { /* check needed if --only-migratable is specified */ - if (!only_migratable) { + if (!migrate_get_current()->only_migratable) { return true; } |