Introduce "xen-save-devices-state"
- add an "is_ram" flag to SaveStateEntry; - register_savevm_live sets is_ram for live_savevm devices; - introduce a "xen-save-devices-state" QAPI command that can be used to save the state of all devices, but not the RAM or the block devices of the VM. Changes in v8: - rename save-devices-state to xen-save-devices-state. Changes in v7: - rename save_devices to save-devices-state. Changes in v6: - remove the is_ram parameter from register_savevm_live and sets is_ram if the device is a live_savevm device; - introduce save_devices as a QAPI command, write a better description for it; - fix CODING_STYLE; - introduce a new doc to explain the save format used by save_devices. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Reviewed-by: Anthony Liguori <aliguori@us.ibm.com> Acked-by: Luiz Capitulino <lcapitulino@redhat.com>
This commit is contained in:
parent
695bb854e8
commit
a7ae8355b4
|
@ -0,0 +1,34 @@
|
||||||
|
= Save Devices =
|
||||||
|
|
||||||
|
QEMU has code to load/save the state of the guest that it is running.
|
||||||
|
These are two complementary operations. Saving the state just does
|
||||||
|
that, saves the state for each device that the guest is running.
|
||||||
|
|
||||||
|
These operations are normally used with migration (see migration.txt),
|
||||||
|
however it is also possible to save the state of all devices to file,
|
||||||
|
without saving the RAM or the block devices of the VM.
|
||||||
|
|
||||||
|
This operation is called "xen-save-devices-state" (see
|
||||||
|
QMP/qmp-commands.txt)
|
||||||
|
|
||||||
|
|
||||||
|
The binary format used in the file is the following:
|
||||||
|
|
||||||
|
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
32 bit big endian: QEMU_VM_FILE_MAGIC
|
||||||
|
32 bit big endian: QEMU_VM_FILE_VERSION
|
||||||
|
|
||||||
|
for_each_device
|
||||||
|
{
|
||||||
|
8 bit: QEMU_VM_SECTION_FULL
|
||||||
|
32 bit big endian: section_id
|
||||||
|
8 bit: idstr (ID string) length
|
||||||
|
string: idstr (ID string)
|
||||||
|
32 bit big endian: instance_id
|
||||||
|
32 bit big endian: version_id
|
||||||
|
buffer: device specific data
|
||||||
|
}
|
||||||
|
|
||||||
|
8 bit: QEMU_VM_EOF
|
|
@ -1593,3 +1593,22 @@
|
||||||
{ 'command': 'qom-list-types',
|
{ 'command': 'qom-list-types',
|
||||||
'data': { '*implements': 'str', '*abstract': 'bool' },
|
'data': { '*implements': 'str', '*abstract': 'bool' },
|
||||||
'returns': [ 'ObjectTypeInfo' ] }
|
'returns': [ 'ObjectTypeInfo' ] }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @xen-save-devices-state:
|
||||||
|
#
|
||||||
|
# Save the state of all devices to file. The RAM and the block devices
|
||||||
|
# of the VM are not saved by this command.
|
||||||
|
#
|
||||||
|
# @filename: the file to save the state of the devices to 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 writing the file, IOError
|
||||||
|
#
|
||||||
|
# Since: 1.1
|
||||||
|
##
|
||||||
|
{ 'command': 'xen-save-devices-state', 'data': {'filename': 'str'} }
|
||||||
|
|
||||||
|
|
|
@ -441,6 +441,33 @@ Example:
|
||||||
Note: inject-nmi is only supported for x86 guest currently, it will
|
Note: inject-nmi is only supported for x86 guest currently, it will
|
||||||
returns "Unsupported" error for non-x86 guest.
|
returns "Unsupported" error for non-x86 guest.
|
||||||
|
|
||||||
|
EQMP
|
||||||
|
|
||||||
|
{
|
||||||
|
.name = "xen-save-devices-state",
|
||||||
|
.args_type = "filename:F",
|
||||||
|
.mhandler.cmd_new = qmp_marshal_input_xen_save_devices_state,
|
||||||
|
},
|
||||||
|
|
||||||
|
SQMP
|
||||||
|
xen-save-devices-state
|
||||||
|
-------
|
||||||
|
|
||||||
|
Save the state of all devices to file. The RAM and the block devices
|
||||||
|
of the VM are not saved by this command.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
- "filename": the file to save the state of the devices to as binary
|
||||||
|
data. See xen-save-devices-state.txt for a description of the binary
|
||||||
|
format.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
-> { "execute": "xen-save-devices-state",
|
||||||
|
"arguments": { "filename": "/tmp/save" } }
|
||||||
|
<- { "return": {} }
|
||||||
|
|
||||||
EQMP
|
EQMP
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
71
savevm.c
71
savevm.c
|
@ -84,6 +84,7 @@
|
||||||
#include "qemu-timer.h"
|
#include "qemu-timer.h"
|
||||||
#include "cpus.h"
|
#include "cpus.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
#include "qmp-commands.h"
|
||||||
|
|
||||||
#define SELF_ANNOUNCE_ROUNDS 5
|
#define SELF_ANNOUNCE_ROUNDS 5
|
||||||
|
|
||||||
|
@ -1177,6 +1178,7 @@ typedef struct SaveStateEntry {
|
||||||
void *opaque;
|
void *opaque;
|
||||||
CompatEntry *compat;
|
CompatEntry *compat;
|
||||||
int no_migrate;
|
int no_migrate;
|
||||||
|
int is_ram;
|
||||||
} SaveStateEntry;
|
} SaveStateEntry;
|
||||||
|
|
||||||
|
|
||||||
|
@ -1241,6 +1243,10 @@ int register_savevm_live(DeviceState *dev,
|
||||||
se->opaque = opaque;
|
se->opaque = opaque;
|
||||||
se->vmsd = NULL;
|
se->vmsd = NULL;
|
||||||
se->no_migrate = 0;
|
se->no_migrate = 0;
|
||||||
|
/* if this is a live_savem then set is_ram */
|
||||||
|
if (save_live_state != NULL) {
|
||||||
|
se->is_ram = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
|
if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
|
||||||
char *id = dev->parent_bus->info->get_dev_path(dev);
|
char *id = dev->parent_bus->info->get_dev_path(dev);
|
||||||
|
@ -1728,6 +1734,45 @@ out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int qemu_save_device_state(QEMUFile *f)
|
||||||
|
{
|
||||||
|
SaveStateEntry *se;
|
||||||
|
|
||||||
|
qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
|
||||||
|
qemu_put_be32(f, QEMU_VM_FILE_VERSION);
|
||||||
|
|
||||||
|
cpu_synchronize_all_states();
|
||||||
|
|
||||||
|
QTAILQ_FOREACH(se, &savevm_handlers, entry) {
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (se->is_ram) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (se->save_state == NULL && se->vmsd == NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Section type */
|
||||||
|
qemu_put_byte(f, QEMU_VM_SECTION_FULL);
|
||||||
|
qemu_put_be32(f, se->section_id);
|
||||||
|
|
||||||
|
/* ID string */
|
||||||
|
len = strlen(se->idstr);
|
||||||
|
qemu_put_byte(f, len);
|
||||||
|
qemu_put_buffer(f, (uint8_t *)se->idstr, len);
|
||||||
|
|
||||||
|
qemu_put_be32(f, se->instance_id);
|
||||||
|
qemu_put_be32(f, se->version_id);
|
||||||
|
|
||||||
|
vmstate_save(f, se);
|
||||||
|
}
|
||||||
|
|
||||||
|
qemu_put_byte(f, QEMU_VM_EOF);
|
||||||
|
|
||||||
|
return qemu_file_get_error(f);
|
||||||
|
}
|
||||||
|
|
||||||
static SaveStateEntry *find_se(const char *idstr, int instance_id)
|
static SaveStateEntry *find_se(const char *idstr, int instance_id)
|
||||||
{
|
{
|
||||||
SaveStateEntry *se;
|
SaveStateEntry *se;
|
||||||
|
@ -2109,6 +2154,32 @@ void do_savevm(Monitor *mon, const QDict *qdict)
|
||||||
vm_start();
|
vm_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void qmp_xen_save_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_SAVE_VM);
|
||||||
|
|
||||||
|
f = qemu_fopen(filename, "wb");
|
||||||
|
if (!f) {
|
||||||
|
error_set(errp, QERR_OPEN_FILE_FAILED, filename);
|
||||||
|
goto the_end;
|
||||||
|
}
|
||||||
|
ret = qemu_save_device_state(f);
|
||||||
|
qemu_fclose(f);
|
||||||
|
if (ret < 0) {
|
||||||
|
error_set(errp, QERR_IO_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
the_end:
|
||||||
|
if (saved_vm_running)
|
||||||
|
vm_start();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int load_vmstate(const char *name)
|
int load_vmstate(const char *name)
|
||||||
{
|
{
|
||||||
BlockDriverState *bs, *bs_vm_state;
|
BlockDriverState *bs, *bs_vm_state;
|
||||||
|
|
Loading…
Reference in New Issue