From: Amit Shah <amit.shah@redhat.com>
To: qemu list <qemu-devel@nongnu.org>
Cc: "Juan Quintela" <quintela@redhat.com>,
"Markus Armbruster" <armbru@redhat.com>,
"Alexander Graf" <agraf@suse.de>,
"Dr. David Alan Gilbert" <dgilbert@redhat.com>,
"Amit Shah" <amit.shah@redhat.com>,
"Paolo Bonzini" <pbonzini@redhat.com>,
"Andreas Färber" <afaerber@suse.de>
Subject: [Qemu-devel] [PATCH v4 01/18] migration: dump vmstate info as a json file for static analysis
Date: Wed, 18 Jun 2014 13:43:35 +0530 [thread overview]
Message-ID: <4ab8ba6bf5de4943288c1ddc565179c807f263e3.1403079139.git.amit.shah@redhat.com> (raw)
In-Reply-To: <cover.1403079139.git.amit.shah@redhat.com>
In-Reply-To: <cover.1403079139.git.amit.shah@redhat.com>
This commit adds a new command, '-dump-vmstate', that takes a filename
as a parameter. When executed, QEMU will dump the vmstate information
for the machine type it's invoked with to the file, and quit.
The JSON-format output can then be used to compare the vmstate info for
different QEMU versions, specifically to test whether live migration
would break due to changes in the vmstate data.
A Python script that compares the output of such JSON dumps is included
in the following commit.
Signed-off-by: Amit Shah <amit.shah@redhat.com>
---
include/migration/vmstate.h | 2 +
qemu-options.hx | 9 +++
savevm.c | 139 ++++++++++++++++++++++++++++++++++++++++++++
vl.c | 13 +++++
4 files changed, 163 insertions(+)
diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index 7e45048..9829c0e 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -778,4 +778,6 @@ void vmstate_register_ram(struct MemoryRegion *memory, DeviceState *dev);
void vmstate_unregister_ram(struct MemoryRegion *memory, DeviceState *dev);
void vmstate_register_ram_global(struct MemoryRegion *memory);
+void dump_vmstate_json_to_file(FILE *out_fp);
+
#endif
diff --git a/qemu-options.hx b/qemu-options.hx
index d0714c4..48d493b 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3221,6 +3221,15 @@ STEXI
prepend a timestamp to each log message.(default:on)
ETEXI
+DEF("dump-vmstate", HAS_ARG, QEMU_OPTION_dump_vmstate,
+ "-dump-vmstate <file>\n" "", QEMU_ARCH_ALL)
+STEXI
+@item -dump-vmstate @var{file}
+@findex -dump-vmstate
+Dump json-encoded vmstate information for current machine type to file
+in @var{file}
+ETEXI
+
HXCOMM This is the last statement. Insert new options before this line!
STEXI
@end table
diff --git a/savevm.c b/savevm.c
index da8aa24..0c8ad45 100644
--- a/savevm.c
+++ b/savevm.c
@@ -24,6 +24,7 @@
#include "config-host.h"
#include "qemu-common.h"
+#include "hw/boards.h"
#include "hw/hw.h"
#include "hw/qdev.h"
#include "net/net.h"
@@ -241,6 +242,144 @@ static QTAILQ_HEAD(savevm_handlers, SaveStateEntry) savevm_handlers =
QTAILQ_HEAD_INITIALIZER(savevm_handlers);
static int global_section_id;
+static void dump_vmstate_vmsd(FILE *out_file,
+ const VMStateDescription *vmsd, int indent,
+ bool is_subsection);
+
+static void dump_vmstate_vmsf(FILE *out_file, const VMStateField *field,
+ int indent)
+{
+ fprintf(out_file, "%*s{\n", indent, "");
+ indent += 2;
+ fprintf(out_file, "%*s\"field\": \"%s\",\n", indent, "", field->name);
+ fprintf(out_file, "%*s\"version_id\": %d,\n", indent, "",
+ field->version_id);
+ fprintf(out_file, "%*s\"field_exists\": %s,\n", indent, "",
+ field->field_exists ? "true" : "false");
+ fprintf(out_file, "%*s\"size\": %zu", indent, "", field->size);
+ if (field->vmsd != NULL) {
+ fprintf(out_file, ",\n");
+ dump_vmstate_vmsd(out_file, field->vmsd, indent, false);
+ }
+ fprintf(out_file, "\n%*s}", indent - 2, "");
+}
+
+static void dump_vmstate_vmss(FILE *out_file,
+ const VMStateSubsection *subsection,
+ int indent)
+{
+ if (subsection->vmsd != NULL) {
+ dump_vmstate_vmsd(out_file, subsection->vmsd, indent, true);
+ }
+}
+
+static void dump_vmstate_vmsd(FILE *out_file,
+ const VMStateDescription *vmsd, int indent,
+ bool is_subsection)
+{
+ if (is_subsection) {
+ fprintf(out_file, "%*s{\n", indent, "");
+ } else {
+ fprintf(out_file, "%*s\"%s\": {\n", indent, "", "Description");
+ }
+ indent += 2;
+ fprintf(out_file, "%*s\"name\": \"%s\",\n", indent, "", vmsd->name);
+ fprintf(out_file, "%*s\"version_id\": %d,\n", indent, "",
+ vmsd->version_id);
+ fprintf(out_file, "%*s\"minimum_version_id\": %d", indent, "",
+ vmsd->minimum_version_id);
+ if (vmsd->fields != NULL) {
+ const VMStateField *field = vmsd->fields;
+ bool first;
+
+ fprintf(out_file, ",\n%*s\"Fields\": [\n", indent, "");
+ first = true;
+ while (field->name != NULL) {
+ if (field->flags & VMS_MUST_EXIST) {
+ /* Ignore VMSTATE_VALIDATE bits; these don't get migrated */
+ field++;
+ continue;
+ }
+ if (!first) {
+ fprintf(out_file, ",\n");
+ }
+ dump_vmstate_vmsf(out_file, field, indent + 2);
+ field++;
+ first = false;
+ }
+ fprintf(out_file, "\n%*s]", indent, "");
+ }
+ if (vmsd->subsections != NULL) {
+ const VMStateSubsection *subsection = vmsd->subsections;
+ bool first;
+
+ fprintf(out_file, ",\n%*s\"Subsections\": [\n", indent, "");
+ first = true;
+ while (subsection->vmsd != NULL) {
+ if (!first) {
+ fprintf(out_file, ",\n");
+ }
+ dump_vmstate_vmss(out_file, subsection, indent + 2);
+ subsection++;
+ first = false;
+ }
+ fprintf(out_file, "\n%*s]", indent, "");
+ }
+ fprintf(out_file, "\n%*s}", indent - 2, "");
+}
+
+static void dump_machine_type(FILE *out_file)
+{
+ MachineClass *mc;
+
+ mc = MACHINE_GET_CLASS(current_machine);
+
+ fprintf(out_file, " \"vmschkmachine\": {\n");
+ fprintf(out_file, " \"Name\": \"%s\"\n", mc->name);
+ fprintf(out_file, " },\n");
+}
+
+void dump_vmstate_json_to_file(FILE *out_file)
+{
+ GSList *list, *elt;
+ bool first;
+
+ fprintf(out_file, "{\n");
+ dump_machine_type(out_file);
+
+ first = true;
+ list = object_class_get_list(TYPE_DEVICE, true);
+ for (elt = list; elt; elt = elt->next) {
+ DeviceClass *dc = OBJECT_CLASS_CHECK(DeviceClass, elt->data,
+ TYPE_DEVICE);
+ const char *name;
+ int indent = 2;
+
+ if (!dc->vmsd) {
+ continue;
+ }
+
+ if (!first) {
+ fprintf(out_file, ",\n");
+ }
+ name = object_class_get_name(OBJECT_CLASS(dc));
+ fprintf(out_file, "%*s\"%s\": {\n", indent, "", name);
+ indent += 2;
+ fprintf(out_file, "%*s\"Name\": \"%s\",\n", indent, "", name);
+ fprintf(out_file, "%*s\"version_id\": %d,\n", indent, "",
+ dc->vmsd->version_id);
+ fprintf(out_file, "%*s\"minimum_version_id\": %d,\n", indent, "",
+ dc->vmsd->minimum_version_id);
+
+ dump_vmstate_vmsd(out_file, dc->vmsd, indent, false);
+
+ fprintf(out_file, "\n%*s}", indent - 2, "");
+ first = false;
+ }
+ fprintf(out_file, "\n}\n");
+ fclose(out_file);
+}
+
static int calculate_new_instance_id(const char *idstr)
{
SaveStateEntry *se;
diff --git a/vl.c b/vl.c
index be69c7f..860541f 100644
--- a/vl.c
+++ b/vl.c
@@ -2991,6 +2991,7 @@ int main(int argc, char **argv, char **envp)
const char *trace_file = NULL;
const ram_addr_t default_ram_size = (ram_addr_t)DEFAULT_RAM_SIZE *
1024 * 1024;
+ FILE *vmstate_dump_file = NULL;
atexit(qemu_run_exit_notifiers);
error_set_progname(argv[0]);
@@ -3957,6 +3958,13 @@ int main(int argc, char **argv, char **envp)
}
configure_msg(opts);
break;
+ case QEMU_OPTION_dump_vmstate:
+ vmstate_dump_file = fopen(optarg, "w");
+ if (vmstate_dump_file == NULL) {
+ fprintf(stderr, "open %s: %s\n", optarg, strerror(errno));
+ exit(1);
+ }
+ break;
default:
os_parse_cmd_args(popt->index, optarg);
}
@@ -4542,6 +4550,11 @@ int main(int argc, char **argv, char **envp)
}
qdev_prop_check_global();
+ if (vmstate_dump_file) {
+ /* dump and exit */
+ dump_vmstate_json_to_file(vmstate_dump_file);
+ return 0;
+ }
if (incoming) {
Error *local_err = NULL;
--
1.9.3
next prev parent reply other threads:[~2014-06-18 8:14 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-06-18 8:13 [Qemu-devel] [PATCH v4 00/18] migration: add static analysis tool to check vmstate compat Amit Shah
2014-06-18 8:13 ` Amit Shah [this message]
2014-06-18 10:24 ` [Qemu-devel] [PATCH v4 01/18] migration: dump vmstate info as a json file for static analysis Juan Quintela
2014-06-18 10:36 ` Amit Shah
2014-06-18 10:56 ` Juan Quintela
2014-06-18 8:13 ` [Qemu-devel] [PATCH v4 02/18] vmstate-static-checker: script to validate vmstate changes Amit Shah
2014-06-18 10:44 ` Juan Quintela
2014-06-18 10:58 ` Amit Shah
2014-06-18 11:25 ` Juan Quintela
2014-06-18 11:32 ` Amit Shah
2014-06-18 8:13 ` [Qemu-devel] [PATCH v4 03/18] tests: vmstate static checker: add dump1 and dump2 files Amit Shah
2014-06-18 10:33 ` Juan Quintela
2014-06-18 8:13 ` [Qemu-devel] [PATCH v4 04/18] tests: vmstate static checker: incompat machine types Amit Shah
2014-06-18 10:33 ` Juan Quintela
2014-06-18 8:13 ` [Qemu-devel] [PATCH v4 05/18] tests: vmstate static checker: add version error in main section Amit Shah
2014-06-18 10:33 ` Juan Quintela
2014-06-18 8:13 ` [Qemu-devel] [PATCH v4 06/18] tests: vmstate static checker: version mismatch inside a Description Amit Shah
2014-06-18 10:34 ` Juan Quintela
2014-06-18 8:13 ` [Qemu-devel] [PATCH v4 07/18] tests: vmstate static checker: minimum_version_id check Amit Shah
2014-06-18 10:34 ` Juan Quintela
2014-06-18 8:13 ` [Qemu-devel] [PATCH v4 08/18] tests: vmstate static checker: remove a section Amit Shah
2014-06-18 10:35 ` Juan Quintela
2014-06-18 8:13 ` [Qemu-devel] [PATCH v4 09/18] tests: vmstate static checker: remove a field Amit Shah
2014-06-18 10:35 ` Juan Quintela
2014-06-18 8:13 ` [Qemu-devel] [PATCH v4 10/18] tests: vmstate static checker: remove last field in a struct Amit Shah
2014-06-18 10:36 ` Juan Quintela
2014-06-18 8:13 ` [Qemu-devel] [PATCH v4 11/18] tests: vmstate static checker: change description name Amit Shah
2014-06-18 10:36 ` Juan Quintela
2014-06-18 8:13 ` [Qemu-devel] [PATCH v4 12/18] tests: vmstate static checker: remove Fields Amit Shah
2014-06-18 10:36 ` Juan Quintela
2014-06-18 8:13 ` [Qemu-devel] [PATCH v4 13/18] tests: vmstate static checker: remove Description Amit Shah
2014-06-18 10:37 ` Juan Quintela
2014-06-18 8:13 ` [Qemu-devel] [PATCH v4 14/18] tests: vmstate static checker: remove Description inside Fields Amit Shah
2014-06-18 10:37 ` Juan Quintela
2014-06-18 8:13 ` [Qemu-devel] [PATCH v4 15/18] tests: vmstate static checker: remove a subsection Amit Shah
2014-06-18 10:37 ` Juan Quintela
2014-06-18 8:13 ` [Qemu-devel] [PATCH v4 16/18] tests: vmstate static checker: remove Subsections Amit Shah
2014-06-18 10:38 ` Juan Quintela
2014-06-18 8:13 ` [Qemu-devel] [PATCH v4 17/18] tests: vmstate static checker: add substructure for usb-kbd for hid section Amit Shah
2014-06-18 10:38 ` Juan Quintela
2014-06-18 8:13 ` [Qemu-devel] [PATCH v4 18/18] tests: vmstate static checker: add size mismatch inside substructure Amit Shah
2014-06-18 10:38 ` Juan Quintela
2014-06-18 10:49 ` [Qemu-devel] [PATCH v4 00/18] migration: add static analysis tool to check vmstate compat Juan Quintela
2014-06-18 11:02 ` Amit Shah
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4ab8ba6bf5de4943288c1ddc565179c807f263e3.1403079139.git.amit.shah@redhat.com \
--to=amit.shah@redhat.com \
--cc=afaerber@suse.de \
--cc=agraf@suse.de \
--cc=armbru@redhat.com \
--cc=dgilbert@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=quintela@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).