-From ddfc29076293a794f0d9cc74c0c822c144e7ecbc Mon Sep 17 00:00:00 2001
+From 15215ea4cb52cf95d68063289bb185dae7de5433 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Wed, 9 Dec 2015 16:04:32 +0100
Subject: [PATCH 22/47] internal snapshot async
include/block/block.h | 1 +
include/sysemu/sysemu.h | 5 +-
migration/savevm.c | 12 +-
- qapi-schema.json | 46 +++++
+ qapi-schema.json | 68 +++++++
qemu-options.hx | 13 ++
- qmp-commands.hx | 30 +++
- savevm-async.c | 526 ++++++++++++++++++++++++++++++++++++++++++++++++
+ savevm-async.c | 525 ++++++++++++++++++++++++++++++++++++++++++++++++
vl.c | 8 +
- 14 files changed, 743 insertions(+), 8 deletions(-)
+ 13 files changed, 734 insertions(+), 8 deletions(-)
create mode 100644 savevm-async.c
diff --git a/Makefile.objs b/Makefile.objs
-index 845edd0..7d9d2d7 100644
+index 9b12ee6..f5f8dba 100644
--- a/Makefile.objs
+++ b/Makefile.objs
-@@ -53,6 +53,7 @@ common-obj-$(CONFIG_LINUX) += fsdev/
+@@ -51,6 +51,7 @@ common-obj-$(CONFIG_LINUX) += fsdev/
+
common-obj-y += migration/
- common-obj-y += qemu-char.o #aio.o
- common-obj-y += page_cache.o
+ common-obj-y += page_cache.o #aio.o
+common-obj-y += savevm-async.o
common-obj-$(CONFIG_SPICE) += spice-qemu-char.o
diff --git a/block.c b/block.c
-index 30d64e6..95c1d32 100644
+index 6e906ec..5563a4f 100644
--- a/block.c
+++ b/block.c
-@@ -2288,7 +2288,7 @@ void bdrv_replace_in_backing_chain(BlockDriverState *old, BlockDriverState *new)
- bdrv_unref(old);
+@@ -3045,7 +3045,7 @@ out:
+ bdrv_unref(bs_new);
}
-static void bdrv_delete(BlockDriverState *bs)
assert(!bs->job);
assert(bdrv_op_blocker_is_empty(bs));
diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
-index 7616fe2..3046f9d 100644
+index 1a18380..3b5a0f9 100644
--- a/hmp-commands-info.hx
+++ b/hmp-commands-info.hx
-@@ -588,6 +588,19 @@ Show current migration xbzrle cache size.
+@@ -573,6 +573,19 @@ Show current migration xbzrle cache size.
ETEXI
{
+ .args_type = "",
+ .params = "",
+ .help = "show savevm status",
-+ .mhandler.cmd = hmp_info_savevm,
++ .cmd = hmp_info_savevm,
+ },
+
+STEXI
.args_type = "",
.params = "",
diff --git a/hmp-commands.hx b/hmp-commands.hx
-index 0e20ef9..4d735cb 100644
+index 7288203..a2867b5 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
-@@ -1791,3 +1791,35 @@ ETEXI
+@@ -1808,3 +1808,35 @@ ETEXI
STEXI
@end table
ETEXI
+ .args_type = "statefile:s?",
+ .params = "[statefile]",
+ .help = "Prepare for snapshot and halt VM. Save VM state to statefile.",
-+ .mhandler.cmd = hmp_savevm_start,
++ .cmd = hmp_savevm_start,
+ },
+
+ {
+ .args_type = "device:s,name:s",
+ .params = "device name",
+ .help = "Create internal snapshot.",
-+ .mhandler.cmd = hmp_snapshot_drive,
++ .cmd = hmp_snapshot_drive,
+ },
+
+ {
+ .args_type = "device:s,name:s",
+ .params = "device name",
+ .help = "Delete internal snapshot.",
-+ .mhandler.cmd = hmp_delete_drive_snapshot,
++ .cmd = hmp_delete_drive_snapshot,
+ },
+
+ {
+ .args_type = "",
+ .params = "",
+ .help = "Resume VM after snaphot.",
-+ .mhandler.cmd = hmp_savevm_end,
++ .cmd = hmp_savevm_end,
+ },
diff --git a/hmp.c b/hmp.c
-index c23cf2f..030fd97 100644
+index 465d7fa..aaf0de1 100644
--- a/hmp.c
+++ b/hmp.c
-@@ -2117,6 +2117,63 @@ void hmp_info_memory_devices(Monitor *mon, const QDict *qdict)
+@@ -2270,6 +2270,63 @@ void hmp_info_memory_devices(Monitor *mon, const QDict *qdict)
qapi_free_MemoryDeviceInfoList(info_list);
}
{
IOThreadInfoList *info_list = qmp_query_iothreads(NULL);
diff --git a/hmp.h b/hmp.h
-index 9a4c1f6..b74ddbf 100644
+index 17a65b2..8c1b484 100644
--- a/hmp.h
+++ b/hmp.h
@@ -26,6 +26,7 @@ void hmp_info_status(Monitor *mon, const QDict *qdict);
void hmp_info_migrate(Monitor *mon, const QDict *qdict);
void hmp_info_migrate_capabilities(Monitor *mon, const QDict *qdict);
void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict);
-@@ -92,6 +93,10 @@ void hmp_netdev_add(Monitor *mon, const QDict *qdict);
+@@ -95,6 +96,10 @@ void hmp_netdev_add(Monitor *mon, const QDict *qdict);
void hmp_netdev_del(Monitor *mon, const QDict *qdict);
void hmp_getfd(Monitor *mon, const QDict *qdict);
void hmp_closefd(Monitor *mon, const QDict *qdict);
void hmp_screendump(Monitor *mon, const QDict *qdict);
void hmp_nbd_server_start(Monitor *mon, const QDict *qdict);
diff --git a/include/block/block.h b/include/block/block.h
-index acddf3b..0f70a9d 100644
+index 5149260..b29c69d 100644
--- a/include/block/block.h
+++ b/include/block/block.h
-@@ -256,6 +256,7 @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
+@@ -295,6 +295,7 @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
int bdrv_get_backing_file_depth(BlockDriverState *bs);
void bdrv_refresh_filename(BlockDriverState *bs);
- int bdrv_truncate(BlockDriverState *bs, int64_t offset);
+ int bdrv_truncate(BdrvChild *child, int64_t offset);
+void bdrv_delete(BlockDriverState *bs);
int64_t bdrv_nb_sectors(BlockDriverState *bs);
int64_t bdrv_getlength(BlockDriverState *bs);
int64_t bdrv_get_allocated_file_size(BlockDriverState *bs);
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
-index ee7c760..4875441 100644
+index 576c7ce..74623de 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
-@@ -79,6 +79,7 @@ void qemu_remove_machine_init_done_notifier(Notifier *notify);
-
+@@ -78,6 +78,7 @@ void qemu_remove_machine_init_done_notifier(Notifier *notify);
void hmp_savevm(Monitor *mon, const QDict *qdict);
+ int save_vmstate(Monitor *mon, const char *name);
int load_vmstate(const char *name);
+int load_state_from_blockdev(const char *filename);
void hmp_delvm(Monitor *mon, const QDict *qdict);
void hmp_info_snapshots(Monitor *mon, const QDict *qdict);
-@@ -106,13 +107,13 @@ enum qemu_vm_cmd {
+@@ -105,13 +106,13 @@ enum qemu_vm_cmd {
#define MAX_VM_CMD_PACKAGED_SIZE (1ul << 24)
bool qemu_savevm_state_blocked(Error **errp);
uint64_t *res_non_postcopiable,
uint64_t *res_postcopiable);
diff --git a/migration/savevm.c b/migration/savevm.c
-index 33a2911..b1bdfb6 100644
+index 3b19a4a..feb0dc6 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
-@@ -879,11 +879,11 @@ void qemu_savevm_state_header(QEMUFile *f)
+@@ -970,11 +970,11 @@ void qemu_savevm_state_header(QEMUFile *f)
}
trace_savevm_state_begin();
QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
-@@ -911,6 +911,7 @@ void qemu_savevm_state_begin(QEMUFile *f,
+@@ -1002,6 +1002,7 @@ void qemu_savevm_state_begin(QEMUFile *f,
break;
}
}
}
/*
-@@ -1014,7 +1015,7 @@ void qemu_savevm_state_complete_postcopy(QEMUFile *f)
+@@ -1105,7 +1106,7 @@ void qemu_savevm_state_complete_postcopy(QEMUFile *f)
qemu_fflush(f);
}
{
QJSON *vmdesc;
int vmdesc_len;
-@@ -1048,12 +1049,12 @@ void qemu_savevm_state_complete_precopy(QEMUFile *f, bool iterable_only)
+@@ -1139,12 +1140,12 @@ void qemu_savevm_state_complete_precopy(QEMUFile *f, bool iterable_only)
save_section_footer(f, se);
if (ret < 0) {
qemu_file_set_error(f, ret);
}
vmdesc = qjson_new();
-@@ -1100,6 +1101,7 @@ void qemu_savevm_state_complete_precopy(QEMUFile *f, bool iterable_only)
+@@ -1191,6 +1192,7 @@ void qemu_savevm_state_complete_precopy(QEMUFile *f, bool iterable_only)
qjson_destroy(vmdesc);
qemu_fflush(f);
/* Give an estimate of the amount left to be transferred,
diff --git a/qapi-schema.json b/qapi-schema.json
-index 147137d..0c0faf7 100644
+index 1127f2c..c33ebb3 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
-@@ -594,6 +594,42 @@
- '*cpu-throttle-percentage': 'int',
+@@ -813,6 +813,40 @@
'*error-desc': 'str'} }
-+
-+# @SaveVMInfo
+ ##
++# @SaveVMInfo:
+#
+# Information about current migration process.
+#
-+# @status: #optional string describing the current savevm status.
++# @status: string describing the current savevm status.
+# This can be 'active', 'completed', 'failed'.
+# If this field is not returned, no savevm process
+# has been initiated
+#
-+# @error: #optional string containing error message is status is failed.
++# @error: string containing error message is status is failed.
+#
-+# @total-time: #optional total amount of milliseconds since savevm started.
++# @total-time: total amount of milliseconds since savevm started.
+# If savevm has ended, it returns the total save time
+#
-+# @bytes: #optional total amount of data transfered
++# @bytes: total amount of data transfered
+#
+# Since: 1.3
+##
+ '*total-time': 'int', '*bytes': 'int'} }
+
+##
-+# @query-savevm
++# @query-savevm:
+#
+# Returns information about current savevm process.
+#
+{ 'command': 'query-savevm', 'returns': 'SaveVMInfo' }
+
+##
-+
- ##
- # @query-migrate
+ # @query-migrate:
#
-@@ -3286,8 +3322,18 @@
+ # Returns information about current migration process. If migration
+@@ -4828,9 +4862,43 @@
#
# Since: 1.2.0
##
+
{ 'command': 'query-target', 'returns': 'TargetInfo' }
+ ##
++# @savevm-start:
++#
++# Prepare for snapshot and halt VM. Save VM state to statefile.
++#
++##
+{ 'command': 'savevm-start', 'data': { '*statefile': 'str' } }
+
++##
++# @snapshot-drive:
++#
++# Create an internal drive snapshot.
++#
++##
+{ 'command': 'snapshot-drive', 'data': { 'device': 'str', 'name': 'str' } }
+
++##
++# @delete-drive-snapshot:
++#
++# Delete a drive snapshot.
++#
++##
+{ 'command': 'delete-drive-snapshot', 'data': { 'device': 'str', 'name': 'str' } }
+
++##
++# @savevm-end:
++#
++# Resume VM after a snapshot.
++#
++##
+{ 'command': 'savevm-end' }
+
+
- ##
++##
# @QKeyCode:
#
+ # An enumeration of key name.
diff --git a/qemu-options.hx b/qemu-options.hx
-index a71aaf8..37fad3b 100644
+index 99af8ed..10f0e81 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
-@@ -3302,6 +3302,19 @@ STEXI
+@@ -3396,6 +3396,19 @@ STEXI
Start right away with a saved state (@code{loadvm} in monitor)
ETEXI
#ifndef _WIN32
DEF("daemonize", 0, QEMU_OPTION_daemonize, \
"-daemonize daemonize QEMU after initializing\n", QEMU_ARCH_ALL)
-diff --git a/qmp-commands.hx b/qmp-commands.hx
-index a8e8522..6342cd2 100644
---- a/qmp-commands.hx
-+++ b/qmp-commands.hx
-@@ -4904,6 +4904,36 @@ Example:
- EQMP
-
- {
-+ .name = "savevm-start",
-+ .args_type = "statefile:s?",
-+ .mhandler.cmd_new = qmp_marshal_savevm_start,
-+ },
-+
-+ {
-+ .name = "snapshot-drive",
-+ .args_type = "device:s,name:s",
-+ .mhandler.cmd_new = qmp_marshal_snapshot_drive,
-+ },
-+
-+ {
-+ .name = "delete-drive-snapshot",
-+ .args_type = "device:s,name:s",
-+ .mhandler.cmd_new = qmp_marshal_delete_drive_snapshot,
-+ },
-+
-+ {
-+ .name = "savevm-end",
-+ .args_type = "",
-+ .mhandler.cmd_new = qmp_marshal_savevm_end,
-+ },
-+
-+ {
-+ .name = "query-savevm",
-+ .args_type = "",
-+ .mhandler.cmd_new = qmp_marshal_query_savevm,
-+ },
-+
-+ {
- .name = "query-rocker",
- .args_type = "name:s",
- .mhandler.cmd_new = qmp_marshal_query_rocker,
diff --git a/savevm-async.c b/savevm-async.c
new file mode 100644
-index 0000000..ae7ea84
+index 0000000..9704a41
--- /dev/null
+++ b/savevm-async.c
-@@ -0,0 +1,526 @@
+@@ -0,0 +1,525 @@
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qapi/qmp/qerror.h"
+ BlockDriver *drv = NULL;
+ Error *local_err = NULL;
+
-+ int bdrv_oflags = BDRV_O_RDWR;
++ int bdrv_oflags = BDRV_O_RDWR | BDRV_O_RESIZE;
+ int ret;
+
+ if (snap_state.state != SAVE_STATE_DONE) {
+ }
+
+ qemu_system_reset(VMRESET_SILENT);
-+ migration_incoming_state_new(f);
+ ret = qemu_loadvm_state(f);
+
+ qemu_fclose(f);
+ return ret;
+}
diff --git a/vl.c b/vl.c
-index b226e0b..c01b1b5 100644
+index 868c489..19afd47 100644
--- a/vl.c
+++ b/vl.c
-@@ -2962,6 +2962,7 @@ int main(int argc, char **argv, char **envp)
+@@ -2960,6 +2960,7 @@ int main(int argc, char **argv, char **envp)
int optind;
const char *optarg;
const char *loadvm = NULL;
MachineClass *machine_class;
const char *cpu_model;
const char *vga_model = NULL;
-@@ -3603,6 +3604,9 @@ int main(int argc, char **argv, char **envp)
+@@ -3631,6 +3632,9 @@ int main(int argc, char **argv, char **envp)
case QEMU_OPTION_loadvm:
loadvm = optarg;
break;
case QEMU_OPTION_full_screen:
full_screen = 1;
break;
-@@ -4597,6 +4601,10 @@ int main(int argc, char **argv, char **envp)
+@@ -4689,6 +4693,10 @@ int main(int argc, char **argv, char **envp)
if (load_vmstate(loadvm) < 0) {
autostart = 0;
}