[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [RFC Patch v3 23/22] Introduce "xen-load-devices-state"
introduce a "xen-load-devices-state" QAPI command that can be used to load the state of all devices, but not the RAM or the block devices of the VM. Signed-off-by: Wen Congyang <wency@xxxxxxxxxxxxxx> CC: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx> --- qapi-schema.json | 18 ++++++++ qmp-commands.hx | 27 ++++++++++++ savevm.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 171 insertions(+) diff --git a/qapi-schema.json b/qapi-schema.json index 391356f..c569856 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -4689,3 +4689,21 @@ 'btn' : 'InputBtnEvent', 'rel' : 'InputMoveEvent', 'abs' : 'InputMoveEvent' } } + +## +# @xen-load-devices-state: +# +# Load the state of all devices from file. The RAM and the block devices +# of the VM are not loaded by this command. +# +# @filename: the file to load the state of the devices from as binary +# data. See xen-save-devices-state.txt for a description of the binary +# format. +# +# Returns: Nothing on success +# If @filename cannot be opened, OpenFileFailed +# If an I/O error occurs while reading the file, IOError +# +# Since: 2.0 +## +{ 'command': 'xen-load-devices-state', 'data': {'filename': 'str'} } diff --git a/qmp-commands.hx b/qmp-commands.hx index ed3ab92..b796be5 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -586,6 +586,33 @@ Example: EQMP { + .name = "xen-load-devices-state", + .args_type = "filename:F", + .mhandler.cmd_new = qmp_marshal_input_xen_load_devices_state, + }, + +SQMP +xen-load-devices-state +------- + +Load the state of all devices from file. The RAM and the block devices +of the VM are not loaded by this command. + +Arguments: + +- "filename": the file to load the state of the devices from as binary +data. See xen-save-devices-state.txt for a description of the binary +format. + +Example: + +-> { "execute": "xen-load-devices-state", + "arguments": { "filename": "/tmp/resume" } } +<- { "return": {} } + +EQMP + + { .name = "xen-set-global-dirty-log", .args_type = "enable:b", .mhandler.cmd_new = qmp_marshal_input_xen_set_global_dirty_log, diff --git a/savevm.c b/savevm.c index 22123be..c6aa502 100644 --- a/savevm.c +++ b/savevm.c @@ -863,6 +863,105 @@ out: return ret; } +static int qemu_load_devices_state(QEMUFile *f) +{ + uint8_t section_type; + unsigned int v; + int ret; + + if (qemu_savevm_state_blocked(NULL)) { + return -EINVAL; + } + + v = qemu_get_be32(f); + if (v != QEMU_VM_FILE_MAGIC) { + return -EINVAL; + } + + v = qemu_get_be32(f); + if (v == QEMU_VM_FILE_VERSION_COMPAT) { + fprintf(stderr, "SaveVM v2 format is obsolete and don't work anymore\n"); + return -ENOTSUP; + } + if (v != QEMU_VM_FILE_VERSION) { + return -ENOTSUP; + } + + while ((section_type = qemu_get_byte(f)) != QEMU_VM_EOF) { + uint32_t instance_id, version_id, section_id; + SaveStateEntry *se; + char idstr[257]; + int len; + + switch (section_type) { + case QEMU_VM_SECTION_FULL: + /* Read section start */ + section_id = qemu_get_be32(f); + len = qemu_get_byte(f); + qemu_get_buffer(f, (uint8_t *)idstr, len); + idstr[len] = 0; + instance_id = qemu_get_be32(f); + version_id = qemu_get_be32(f); + + /* Find savevm section */ + se = find_se(idstr, instance_id); + if (se == NULL) { + fprintf(stderr, "Unknown savevm section or instance '%s' %d\n", + idstr, instance_id); + ret = -EINVAL; + goto out; + } + + /* Validate version */ + if (version_id > se->version_id) { + fprintf(stderr, "loadvm: unsupported version %d for '%s' v%d\n", + version_id, idstr, se->version_id); + ret = -EINVAL; + goto out; + } + + /* Validate if it is a device's state */ + if (se->is_ram) { + fprintf(stderr, "loadvm: %s is not devices state\n", idstr); + ret = -EINVAL; + goto out; + } + + ret = vmstate_load(f, se, version_id); + if (ret < 0) { + fprintf(stderr, "qemu: warning: error while loading state for instance 0x%x of device '%s'\n", + instance_id, idstr); + goto out; + } + break; + case QEMU_VM_SECTION_START: + case QEMU_VM_SECTION_PART: + case QEMU_VM_SECTION_END: + /* + * The file is saved by the command xen-save-devices-state, + * So it should not contain section start/part/end. + */ + default: + fprintf(stderr, "Unknown savevm section type %d\n", section_type); + ret = -EINVAL; + goto out; + } + } + + cpu_synchronize_all_post_init(); + + ret = 0; + +out: + if (ret == 0) { + if (qemu_file_get_error(f)) { + ret = -EIO; + } + } + + return ret; +} + static BlockDriverState *find_vmstate_bs(void) { BlockDriverState *bs = NULL; @@ -1027,6 +1126,33 @@ void qmp_xen_save_devices_state(const char *filename, Error **errp) } } +void qmp_xen_load_devices_state(const char *filename, Error **errp) +{ + QEMUFile *f; + int saved_vm_running; + int ret; + + saved_vm_running = runstate_is_running(); + vm_stop(RUN_STATE_RESTORE_VM); + + f = qemu_fopen(filename, "rb"); + if (!f) { + error_setg_file_open(errp, errno, filename); + goto out; + } + + ret = qemu_load_devices_state(f); + qemu_fclose(f); + if (ret < 0) { + error_set(errp, QERR_IO_ERROR); + } + +out: + if (saved_vm_running) { + vm_start(); + } +} + int load_vmstate(const char *name) { BlockDriverState *bs, *bs_vm_state; -- 1.9.0 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |