@@ -17,7 +17,11 @@
#include "qapi/qapi-builtin-types.h"
-int save_snapshot(const char *name, strList *exclude, Error **errp);
-int load_snapshot(const char *name, strList *exclude, Error **errp);
+int save_snapshot(const char *name,
+ const char *vmstate, strList *exclude,
+ Error **errp);
+int load_snapshot(const char *name,
+ const char *vmstate, strList *exclude,
+ Error **errp);
#endif
@@ -2624,7 +2624,8 @@ int qemu_load_device_state(QEMUFile *f)
return 0;
}
-int save_snapshot(const char *name, strList *exclude, Error **errp)
+int save_snapshot(const char *name, const char *vmstate,
+ strList *exclude, Error **errp)
{
BlockDriverState *bs, *bs1;
QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1;
@@ -2662,7 +2663,7 @@ int save_snapshot(const char *name, strList *exclude, Error **errp)
}
}
- bs = bdrv_all_find_vmstate_bs(NULL, exclude, errp);
+ bs = bdrv_all_find_vmstate_bs(vmstate, exclude, errp);
if (bs == NULL) {
return ret;
}
@@ -2827,7 +2828,8 @@ void qmp_xen_load_devices_state(const char *filename, Error **errp)
migration_incoming_state_destroy();
}
-int load_snapshot(const char *name, strList *exclude, Error **errp)
+int load_snapshot(const char *name, const char *vmstate,
+ strList *exclude, Error **errp)
{
BlockDriverState *bs, *bs_vm_state;
QEMUSnapshotInfo sn;
@@ -2856,7 +2858,7 @@ int load_snapshot(const char *name, strList *exclude, Error **errp)
return ret;
}
- bs_vm_state = bdrv_all_find_vmstate_bs(NULL, exclude, errp);
+ bs_vm_state = bdrv_all_find_vmstate_bs(vmstate, exclude, errp);
if (!bs_vm_state) {
return -ENOTSUP;
}
@@ -2943,13 +2945,15 @@ bool vmstate_check_only_migratable(const VMStateDescription *vmsd)
}
void qmp_savevm(const char *tag,
+ bool has_vmstate, const char *vmstate,
bool has_exclude, strList *exclude,
Error **errp)
{
- save_snapshot(tag, exclude, errp);
+ save_snapshot(tag, vmstate, exclude, errp);
}
void qmp_loadvm(const char *tag,
+ bool has_vmstate, const char *vmstate,
bool has_exclude, strList *exclude,
Error **errp)
{
@@ -2957,7 +2961,7 @@ void qmp_loadvm(const char *tag,
vm_stop(RUN_STATE_RESTORE_VM);
- if (load_snapshot(tag, exclude, errp) == 0 && saved_vm_running) {
+ if (load_snapshot(tag, vmstate, exclude, errp) == 0 && saved_vm_running) {
vm_start();
}
}
@@ -1091,7 +1091,8 @@ void hmp_loadvm(Monitor *mon, const QDict *qdict)
{
Error *err = NULL;
- qmp_loadvm(qdict_get_str(qdict, "name"), false, NULL, &err);
+ qmp_loadvm(qdict_get_str(qdict, "name"),
+ false, NULL, false, NULL, &err);
hmp_handle_error(mon, err);
}
@@ -1099,7 +1100,8 @@ void hmp_savevm(Monitor *mon, const QDict *qdict)
{
Error *err = NULL;
- qmp_savevm(qdict_get_try_str(qdict, "name"), false, NULL, &err);
+ qmp_savevm(qdict_get_try_str(qdict, "name"),
+ false, NULL, false, NULL, &err);
hmp_handle_error(mon, err);
}
@@ -1630,6 +1630,7 @@
# @tag: name of the snapshot to create. If it already
# exists it will be replaced.
# @exclude: list of block device node names to exclude
+# @vmstate: block device node name to save vmstate to
#
# Note that execution of the VM will be paused during the time
# it takes to save the snapshot
@@ -1641,6 +1642,7 @@
# -> { "execute": "savevm",
# "data": {
# "tag": "my-snap",
+# "vmstate": "disk0",
# "exclude": ["pflash0-vars"]
# }
# }
@@ -1650,6 +1652,7 @@
##
{ 'command': 'savevm',
'data': { 'tag': 'str',
+ '*vmstate': 'str',
'*exclude': ['str'] } }
##
@@ -1659,6 +1662,7 @@
#
# @tag: name of the snapshot to load.
# @exclude: list of block device node names to exclude
+# @vmstate: block device node name to load vmstate from
#
# Returns: nothing
#
@@ -1667,6 +1671,7 @@
# -> { "execute": "loadvm",
# "data": {
# "tag": "my-snap",
+# "vmstate": "disk0",
# "exclude": ["pflash0-vars"]
# }
# }
@@ -1676,6 +1681,7 @@
##
{ 'command': 'loadvm',
'data': { 'tag': 'str',
+ '*vmstate': 'str',
'*exclude': ['str'] } }
##
@@ -77,13 +77,13 @@ void replay_vmstate_init(void)
if (replay_snapshot) {
if (replay_mode == REPLAY_MODE_RECORD) {
- if (save_snapshot(replay_snapshot, NULL, &err) != 0) {
+ if (save_snapshot(replay_snapshot, NULL, NULL, &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_snapshot(replay_snapshot, NULL, &err) != 0) {
+ if (load_snapshot(replay_snapshot, NULL, NULL, &err) != 0) {
error_report_err(err);
error_report("Could not load snapshot for icount replay");
exit(1);
@@ -4452,7 +4452,7 @@ void qemu_init(int argc, char **argv, char **envp)
register_global_state();
if (loadvm) {
Error *local_err = NULL;
- if (load_snapshot(loadvm, NULL, &local_err) < 0) {
+ if (load_snapshot(loadvm, NULL, NULL, &local_err) < 0) {
error_report_err(local_err);
autostart = 0;
exit(1);
This wires up support for a new "vmstate" parameter to the QMP commands for snapshots (savevm, loadvm). This parameter accepts block driver state node name. One use case for this would be a VM using OVMF firmware where the variables store is the first snapshottable disk image. The vmstate snapshot usually wants to be stored in the primary root disk of the VM, not the firmeware varstore. Thus there needs to be a mechanism to override the default choice of disk. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- include/migration/snapshot.h | 8 ++++++-- migration/savevm.c | 16 ++++++++++------ monitor/hmp-cmds.c | 6 ++++-- qapi/migration.json | 6 ++++++ replay/replay-snapshot.c | 4 ++-- softmmu/vl.c | 2 +- 6 files changed, 29 insertions(+), 13 deletions(-)