Patchwork [10/11] vl: add a new -vmstate-dump option to write a VMState JSON schema

login
register
mail settings
Submitter Anthony Liguori
Date March 23, 2011, 12:16 a.m.
Message ID <1300839376-22520-11-git-send-email-aliguori@us.ibm.com>
Download mbox | patch
Permalink /patch/87981/
State New
Headers show

Comments

Anthony Liguori - March 23, 2011, 12:16 a.m.
This ends up being pretty slick as we can store the JSON schema in the tree and
then use a test wrapper to validate whether fields change.

Current schema will come with the test wrapper.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
 hw/hw.h         |    2 +
 qemu-options.hx |   10 ++++++++
 savevm.c        |   62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 vl.c            |   10 ++++++++
 4 files changed, 84 insertions(+), 0 deletions(-)

Patch

diff --git a/hw/hw.h b/hw/hw.h
index 9a9012f..531ee30 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -927,4 +927,6 @@  void vmstate_unregister(DeviceState *dev, const VMStateDescription *vmsd,
 
 void register_vmstate_description(const VMStateDescription *desc);
 
+void vmstate_dump_schema(void);
+
 #endif
diff --git a/qemu-options.hx b/qemu-options.hx
index ef60730..0faaea5 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2368,6 +2368,16 @@  Specify a trace file to log output traces to.
 ETEXI
 #endif
 
+DEF("vmstate-dump", 0, QEMU_OPTION_vmstate_dump,
+    "-vmstate-dump   output the current VMState schema and exit\n",
+    QEMU_ARCH_ALL)
+STEXI
+@item -vmstate-dump
+@findex -vmstate-dump
+This option is only used for an internal test suite.  The output format may
+change in the future.
+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 4a37917..d35ce8d 100644
--- a/savevm.c
+++ b/savevm.c
@@ -82,6 +82,7 @@ 
 #include "migration.h"
 #include "qemu_socket.h"
 #include "qemu-queue.h"
+#include "qemu-objects.h"
 
 #define SELF_ANNOUNCE_ROUNDS 5
 
@@ -1285,8 +1286,69 @@  void vmstate_unregister(DeviceState *dev, const VMStateDescription *vmsd,
     }
 }
 
+typedef struct VmsdEntry
+{
+    const VMStateDescription *desc;
+    QTAILQ_ENTRY(VmsdEntry) node;
+} VmsdEntry;
+
+static QTAILQ_HEAD(, VmsdEntry) vmsd_description_list =
+    QTAILQ_HEAD_INITIALIZER(vmsd_description_list);
+
 void register_vmstate_description(const VMStateDescription *desc)
 {
+    VmsdEntry *e = qemu_mallocz(sizeof(*e));
+
+    e->desc = desc;
+    QTAILQ_INSERT_TAIL(&vmsd_description_list, e, node);
+}
+
+static QDict *vmstate_dump_state(const VMStateDescription *desc)
+{
+    VMStateField *f;
+    QDict *ret;
+
+    ret = qdict_new();
+
+    qdict_put(ret, "__version__", qint_from_int(desc->version_id));
+    for (f = desc->fields; f && f->name; f++) {
+        if (qdict_haskey(ret, f->name)) {
+            fprintf(stderr, "vmstate: duplicate key `%s' in `%s'\n",
+                    f->name, desc->name);
+            exit(1);
+        }
+        if (f->vmsd) {
+            qdict_put(ret, f->name, vmstate_dump_state(f->vmsd));
+        } else {
+            qdict_put(ret, f->name, qstring_from_str(f->info->name));
+        }
+    }
+
+    return ret;
+}
+
+void vmstate_dump_schema(void)
+{
+    QDict *items;
+    QString *str;
+    VmsdEntry *e;
+
+    items = qdict_new();
+
+    QTAILQ_FOREACH(e, &vmsd_description_list, node) {
+        if (qdict_haskey(items, e->desc->name)) {
+            fprintf(stderr, "vmstate: duplicate devices of name `%s'\n",
+                    e->desc->name);
+            exit(1);
+        }
+        qdict_put(items, e->desc->name, vmstate_dump_state(e->desc));
+    }
+
+    str = qobject_to_json_pretty(QOBJECT(items));
+    printf("%s\n", qstring_get_str(str));
+
+    QDECREF(str);
+    QDECREF(items);
 }
 
 static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
diff --git a/vl.c b/vl.c
index dbb927d..f91875b 100644
--- a/vl.c
+++ b/vl.c
@@ -2038,6 +2038,7 @@  int main(int argc, char **argv, char **envp)
 #endif
     int defconfig = 1;
     const char *trace_file = NULL;
+    bool vmstate_dump = false;
 
     atexit(qemu_run_exit_notifiers);
     error_set_progname(argv[0]);
@@ -2876,6 +2877,9 @@  int main(int argc, char **argv, char **envp)
                     fclose(fp);
                     break;
                 }
+            case QEMU_OPTION_vmstate_dump:
+                vmstate_dump = true;
+                break;
             default:
                 os_parse_cmd_args(popt->index, optarg);
             }
@@ -3124,6 +3128,12 @@  int main(int argc, char **argv, char **envp)
     }
     qemu_add_globals();
 
+    if (vmstate_dump) {
+        module_call_init(MODULE_INIT_VMSTATE);
+        vmstate_dump_schema();
+        exit(0);
+    }
+
     machine->init(ram_size, boot_devices,
                   kernel_filename, kernel_cmdline, initrd_filename, cpu_model);