summary refs log tree commit diff stats
path: root/migration
diff options
context:
space:
mode:
Diffstat (limited to 'migration')
-rw-r--r--migration/meson.build1
-rw-r--r--migration/migration.c35
-rw-r--r--migration/postcopy-ram.c7
-rw-r--r--migration/qjson.c114
-rw-r--r--migration/qjson.h29
-rw-r--r--migration/savevm.c64
-rw-r--r--migration/vmstate-types.c38
-rw-r--r--migration/vmstate.c52
8 files changed, 96 insertions, 244 deletions
diff --git a/migration/meson.build b/migration/meson.build
index 980e37865c..291adc1337 100644
--- a/migration/meson.build
+++ b/migration/meson.build
@@ -6,7 +6,6 @@ migration_files = files(
   'vmstate.c',
   'qemu-file-channel.c',
   'qemu-file.c',
-  'qjson.c',
 )
 softmmu_ss.add(migration_files)
 
diff --git a/migration/migration.c b/migration/migration.c
index e0dbde4091..9c7ed12cec 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -406,12 +406,9 @@ int migration_incoming_enable_colo(void)
 void migrate_add_address(SocketAddress *address)
 {
     MigrationIncomingState *mis = migration_incoming_get_current();
-    SocketAddressList *addrs;
 
-    addrs = g_new0(SocketAddressList, 1);
-    addrs->next = mis->socket_address_list;
-    mis->socket_address_list = addrs;
-    addrs->value = QAPI_CLONE(SocketAddress, address);
+    QAPI_LIST_PREPEND(mis->socket_address_list,
+                      QAPI_CLONE(SocketAddress, address));
 }
 
 static void qemu_start_incoming_migration(const char *uri, Error **errp)
@@ -1654,27 +1651,23 @@ void migrate_set_state(int *state, int old_state, int new_state)
     }
 }
 
-static MigrationCapabilityStatusList *migrate_cap_add(
-    MigrationCapabilityStatusList *list,
-    MigrationCapability index,
-    bool state)
+static MigrationCapabilityStatus *migrate_cap_add(MigrationCapability index,
+                                                  bool state)
 {
-    MigrationCapabilityStatusList *cap;
+    MigrationCapabilityStatus *cap;
 
-    cap = g_new0(MigrationCapabilityStatusList, 1);
-    cap->value = g_new0(MigrationCapabilityStatus, 1);
-    cap->value->capability = index;
-    cap->value->state = state;
-    cap->next = list;
+    cap = g_new0(MigrationCapabilityStatus, 1);
+    cap->capability = index;
+    cap->state = state;
 
     return cap;
 }
 
 void migrate_set_block_enabled(bool value, Error **errp)
 {
-    MigrationCapabilityStatusList *cap;
+    MigrationCapabilityStatusList *cap = NULL;
 
-    cap = migrate_cap_add(NULL, MIGRATION_CAPABILITY_BLOCK, value);
+    QAPI_LIST_PREPEND(cap, migrate_cap_add(MIGRATION_CAPABILITY_BLOCK, value));
     qmp_migrate_set_capabilities(cap, errp);
     qapi_free_MigrationCapabilityStatusList(cap);
 }
@@ -2102,6 +2095,12 @@ static bool migrate_prepare(MigrationState *s, bool blk, bool blk_inc,
         return false;
     }
 
+    if (runstate_check(RUN_STATE_POSTMIGRATE)) {
+        error_setg(errp, "Can't migrate the vm that was paused due to "
+                   "previous migration");
+        return false;
+    }
+
     if (migration_is_blocked(errp)) {
         return false;
     }
@@ -3863,7 +3862,7 @@ static bool migration_object_check(MigrationState *ms, Error **errp)
 
     for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
         if (ms->enabled_capabilities[i]) {
-            head = migrate_cap_add(head, i, true);
+            QAPI_LIST_PREPEND(head, migrate_cap_add(i, true));
         }
     }
 
diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c
index d99842eb1b..ab482adef1 100644
--- a/migration/postcopy-ram.c
+++ b/migration/postcopy-ram.c
@@ -145,14 +145,11 @@ static struct PostcopyBlocktimeContext *blocktime_context_new(void)
 static uint32List *get_vcpu_blocktime_list(PostcopyBlocktimeContext *ctx)
 {
     MachineState *ms = MACHINE(qdev_get_machine());
-    uint32List *list = NULL, *entry = NULL;
+    uint32List *list = NULL;
     int i;
 
     for (i = ms->smp.cpus - 1; i >= 0; i--) {
-        entry = g_new0(uint32List, 1);
-        entry->value = ctx->vcpu_blocktime[i];
-        entry->next = list;
-        list = entry;
+        QAPI_LIST_PREPEND(list, ctx->vcpu_blocktime[i]);
     }
 
     return list;
diff --git a/migration/qjson.c b/migration/qjson.c
deleted file mode 100644
index e9889bdcb0..0000000000
--- a/migration/qjson.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * A simple JSON writer
- *
- * Copyright Alexander Graf
- *
- * Authors:
- *  Alexander Graf <agraf@suse.de>
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- *
- */
-
-/*
- * Type QJSON lets you build JSON text.  Its interface mirrors (a
- * subset of) abstract JSON syntax.
- *
- * It does *not* detect incorrect use.  It happily produces invalid
- * JSON then.  This is what migration wants.
- *
- * QAPI output visitors also produce JSON text.  However, they do
- * assert their preconditions and invariants, and therefore abort on
- * incorrect use.
- */
-
-#include "qemu/osdep.h"
-#include "qapi/qmp/qstring.h"
-#include "qjson.h"
-
-struct QJSON {
-    QString *str;
-    bool omit_comma;
-};
-
-static void json_emit_element(QJSON *json, const char *name)
-{
-    /* Check whether we need to print a , before an element */
-    if (json->omit_comma) {
-        json->omit_comma = false;
-    } else {
-        qstring_append(json->str, ", ");
-    }
-
-    if (name) {
-        qstring_append(json->str, "\"");
-        qstring_append(json->str, name);
-        qstring_append(json->str, "\" : ");
-    }
-}
-
-void json_start_object(QJSON *json, const char *name)
-{
-    json_emit_element(json, name);
-    qstring_append(json->str, "{ ");
-    json->omit_comma = true;
-}
-
-void json_end_object(QJSON *json)
-{
-    qstring_append(json->str, " }");
-    json->omit_comma = false;
-}
-
-void json_start_array(QJSON *json, const char *name)
-{
-    json_emit_element(json, name);
-    qstring_append(json->str, "[ ");
-    json->omit_comma = true;
-}
-
-void json_end_array(QJSON *json)
-{
-    qstring_append(json->str, " ]");
-    json->omit_comma = false;
-}
-
-void json_prop_int(QJSON *json, const char *name, int64_t val)
-{
-    json_emit_element(json, name);
-    qstring_append_int(json->str, val);
-}
-
-void json_prop_str(QJSON *json, const char *name, const char *str)
-{
-    json_emit_element(json, name);
-    qstring_append_chr(json->str, '"');
-    qstring_append(json->str, str);
-    qstring_append_chr(json->str, '"');
-}
-
-const char *qjson_get_str(QJSON *json)
-{
-    return qstring_get_str(json->str);
-}
-
-QJSON *qjson_new(void)
-{
-    QJSON *json = g_new0(QJSON, 1);
-
-    json->str = qstring_from_str("{ ");
-    json->omit_comma = true;
-    return json;
-}
-
-void qjson_finish(QJSON *json)
-{
-    json_end_object(json);
-}
-
-void qjson_destroy(QJSON *json)
-{
-    qobject_unref(json->str);
-    g_free(json);
-}
diff --git a/migration/qjson.h b/migration/qjson.h
deleted file mode 100644
index 1786bb5864..0000000000
--- a/migration/qjson.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * QEMU JSON writer
- *
- * Copyright Alexander Graf
- *
- * Authors:
- *  Alexander Graf <agraf@suse.de>
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- *
- */
-#ifndef QEMU_QJSON_H
-#define QEMU_QJSON_H
-
-QJSON *qjson_new(void);
-void qjson_destroy(QJSON *json);
-void json_prop_str(QJSON *json, const char *name, const char *str);
-void json_prop_int(QJSON *json, const char *name, int64_t val);
-void json_end_array(QJSON *json);
-void json_start_array(QJSON *json, const char *name);
-void json_end_object(QJSON *json);
-void json_start_object(QJSON *json, const char *name);
-const char *qjson_get_str(QJSON *json);
-void qjson_finish(QJSON *json);
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(QJSON, qjson_destroy)
-
-#endif /* QEMU_QJSON_H */
diff --git a/migration/savevm.c b/migration/savevm.c
index 5f937a2762..27e842812e 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -42,6 +42,7 @@
 #include "postcopy-ram.h"
 #include "qapi/error.h"
 #include "qapi/qapi-commands-migration.h"
+#include "qapi/qmp/json-writer.h"
 #include "qapi/qmp/qerror.h"
 #include "qemu/error-report.h"
 #include "sysemu/cpus.h"
@@ -58,7 +59,6 @@
 #include "sysemu/runstate.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/xen.h"
-#include "qjson.h"
 #include "migration/colo.h"
 #include "qemu/bitmap.h"
 #include "net/announce.h"
@@ -209,7 +209,7 @@ static int get_timer(QEMUFile *f, void *pv, size_t size,
 }
 
 static int put_timer(QEMUFile *f, void *pv, size_t size,
-                     const VMStateField *field, QJSON *vmdesc)
+                     const VMStateField *field, JSONWriter *vmdesc)
 {
     QEMUTimer *v = pv;
     timer_put(f, v);
@@ -406,7 +406,7 @@ static int get_capability(QEMUFile *f, void *pv, size_t size,
 }
 
 static int put_capability(QEMUFile *f, void *pv, size_t size,
-                          const VMStateField *field, QJSON *vmdesc)
+                          const VMStateField *field, JSONWriter *vmdesc)
 {
     MigrationCapability *capability = pv;
     const char *capability_str = MigrationCapability_str(*capability);
@@ -884,7 +884,8 @@ static int vmstate_load(QEMUFile *f, SaveStateEntry *se)
     return vmstate_load_state(f, se->vmsd, se->opaque, se->load_version_id);
 }
 
-static void vmstate_save_old_style(QEMUFile *f, SaveStateEntry *se, QJSON *vmdesc)
+static void vmstate_save_old_style(QEMUFile *f, SaveStateEntry *se,
+                                   JSONWriter *vmdesc)
 {
     int64_t old_offset, size;
 
@@ -893,18 +894,19 @@ static void vmstate_save_old_style(QEMUFile *f, SaveStateEntry *se, QJSON *vmdes
     size = qemu_ftell_fast(f) - old_offset;
 
     if (vmdesc) {
-        json_prop_int(vmdesc, "size", size);
-        json_start_array(vmdesc, "fields");
-        json_start_object(vmdesc, NULL);
-        json_prop_str(vmdesc, "name", "data");
-        json_prop_int(vmdesc, "size", size);
-        json_prop_str(vmdesc, "type", "buffer");
-        json_end_object(vmdesc);
-        json_end_array(vmdesc);
+        json_writer_int64(vmdesc, "size", size);
+        json_writer_start_array(vmdesc, "fields");
+        json_writer_start_object(vmdesc, NULL);
+        json_writer_str(vmdesc, "name", "data");
+        json_writer_int64(vmdesc, "size", size);
+        json_writer_str(vmdesc, "type", "buffer");
+        json_writer_end_object(vmdesc);
+        json_writer_end_array(vmdesc);
     }
 }
 
-static int vmstate_save(QEMUFile *f, SaveStateEntry *se, QJSON *vmdesc)
+static int vmstate_save(QEMUFile *f, SaveStateEntry *se,
+                        JSONWriter *vmdesc)
 {
     trace_vmstate_save(se->idstr, se->vmsd ? se->vmsd->name : "(old)");
     if (!se->vmsd) {
@@ -1357,14 +1359,15 @@ int qemu_savevm_state_complete_precopy_non_iterable(QEMUFile *f,
                                                     bool in_postcopy,
                                                     bool inactivate_disks)
 {
-    g_autoptr(QJSON) vmdesc = NULL;
+    g_autoptr(JSONWriter) vmdesc = NULL;
     int vmdesc_len;
     SaveStateEntry *se;
     int ret;
 
-    vmdesc = qjson_new();
-    json_prop_int(vmdesc, "page_size", qemu_target_page_size());
-    json_start_array(vmdesc, "devices");
+    vmdesc = json_writer_new(false);
+    json_writer_start_object(vmdesc, NULL);
+    json_writer_int64(vmdesc, "page_size", qemu_target_page_size());
+    json_writer_start_array(vmdesc, "devices");
     QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
 
         if ((!se->ops || !se->ops->save_state) && !se->vmsd) {
@@ -1377,9 +1380,9 @@ int qemu_savevm_state_complete_precopy_non_iterable(QEMUFile *f,
 
         trace_savevm_section_start(se->idstr, se->section_id);
 
-        json_start_object(vmdesc, NULL);
-        json_prop_str(vmdesc, "name", se->idstr);
-        json_prop_int(vmdesc, "instance_id", se->instance_id);
+        json_writer_start_object(vmdesc, NULL);
+        json_writer_str(vmdesc, "name", se->idstr);
+        json_writer_int64(vmdesc, "instance_id", se->instance_id);
 
         save_section_header(f, se, QEMU_VM_SECTION_FULL);
         ret = vmstate_save(f, se, vmdesc);
@@ -1390,7 +1393,7 @@ int qemu_savevm_state_complete_precopy_non_iterable(QEMUFile *f,
         trace_savevm_section_end(se->idstr, se->section_id, 0);
         save_section_footer(f, se);
 
-        json_end_object(vmdesc);
+        json_writer_end_object(vmdesc);
     }
 
     if (inactivate_disks) {
@@ -1409,14 +1412,14 @@ int qemu_savevm_state_complete_precopy_non_iterable(QEMUFile *f,
         qemu_put_byte(f, QEMU_VM_EOF);
     }
 
-    json_end_array(vmdesc);
-    qjson_finish(vmdesc);
-    vmdesc_len = strlen(qjson_get_str(vmdesc));
+    json_writer_end_array(vmdesc);
+    json_writer_end_object(vmdesc);
+    vmdesc_len = strlen(json_writer_get(vmdesc));
 
     if (should_send_vmdesc()) {
         qemu_put_byte(f, QEMU_VM_VMDESCRIPTION);
         qemu_put_be32(f, vmdesc_len);
-        qemu_put_buffer(f, (uint8_t *)qjson_get_str(vmdesc), vmdesc_len);
+        qemu_put_buffer(f, (uint8_t *)json_writer_get(vmdesc), vmdesc_len);
     }
 
     return 0;
@@ -2728,7 +2731,7 @@ int qemu_load_device_state(QEMUFile *f)
 int save_snapshot(const char *name, Error **errp)
 {
     BlockDriverState *bs, *bs1;
-    QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1;
+    QEMUSnapshotInfo sn1, *sn = &sn1;
     int ret = -1, ret2;
     QEMUFile *f;
     int saved_vm_running;
@@ -2797,13 +2800,7 @@ int save_snapshot(const char *name, Error **errp)
     }
 
     if (name) {
-        ret = bdrv_snapshot_find(bs, old_sn, name);
-        if (ret >= 0) {
-            pstrcpy(sn->name, sizeof(sn->name), old_sn->name);
-            pstrcpy(sn->id_str, sizeof(sn->id_str), old_sn->id_str);
-        } else {
-            pstrcpy(sn->name, sizeof(sn->name), name);
-        }
+        pstrcpy(sn->name, sizeof(sn->name), name);
     } else {
         /* cast below needed for OpenBSD where tv_sec is still 'long' */
         localtime_r((const time_t *)&tv.tv_sec, &tm);
@@ -2839,6 +2836,7 @@ int save_snapshot(const char *name, Error **errp)
     if (ret < 0) {
         error_setg(errp, "Error while creating snapshot on '%s'",
                    bdrv_get_device_or_node_name(bs));
+        bdrv_all_delete_snapshot(sn->name, &bs, NULL);
         goto the_end;
     }
 
diff --git a/migration/vmstate-types.c b/migration/vmstate-types.c
index e22d41d73d..bf4d440308 100644
--- a/migration/vmstate-types.c
+++ b/migration/vmstate-types.c
@@ -29,7 +29,7 @@ static int get_bool(QEMUFile *f, void *pv, size_t size,
 }
 
 static int put_bool(QEMUFile *f, void *pv, size_t size,
-                    const VMStateField *field, QJSON *vmdesc)
+                    const VMStateField *field, JSONWriter *vmdesc)
 {
     bool *v = pv;
     qemu_put_byte(f, *v);
@@ -53,7 +53,7 @@ static int get_int8(QEMUFile *f, void *pv, size_t size,
 }
 
 static int put_int8(QEMUFile *f, void *pv, size_t size,
-                    const VMStateField *field, QJSON *vmdesc)
+                    const VMStateField *field, JSONWriter *vmdesc)
 {
     int8_t *v = pv;
     qemu_put_s8s(f, v);
@@ -77,7 +77,7 @@ static int get_int16(QEMUFile *f, void *pv, size_t size,
 }
 
 static int put_int16(QEMUFile *f, void *pv, size_t size,
-                     const VMStateField *field, QJSON *vmdesc)
+                     const VMStateField *field, JSONWriter *vmdesc)
 {
     int16_t *v = pv;
     qemu_put_sbe16s(f, v);
@@ -101,7 +101,7 @@ static int get_int32(QEMUFile *f, void *pv, size_t size,
 }
 
 static int put_int32(QEMUFile *f, void *pv, size_t size,
-                     const VMStateField *field, QJSON *vmdesc)
+                     const VMStateField *field, JSONWriter *vmdesc)
 {
     int32_t *v = pv;
     qemu_put_sbe32s(f, v);
@@ -178,7 +178,7 @@ static int get_int64(QEMUFile *f, void *pv, size_t size,
 }
 
 static int put_int64(QEMUFile *f, void *pv, size_t size,
-                     const VMStateField *field, QJSON *vmdesc)
+                     const VMStateField *field, JSONWriter *vmdesc)
 {
     int64_t *v = pv;
     qemu_put_sbe64s(f, v);
@@ -202,7 +202,7 @@ static int get_uint8(QEMUFile *f, void *pv, size_t size,
 }
 
 static int put_uint8(QEMUFile *f, void *pv, size_t size,
-                     const VMStateField *field, QJSON *vmdesc)
+                     const VMStateField *field, JSONWriter *vmdesc)
 {
     uint8_t *v = pv;
     qemu_put_8s(f, v);
@@ -226,7 +226,7 @@ static int get_uint16(QEMUFile *f, void *pv, size_t size,
 }
 
 static int put_uint16(QEMUFile *f, void *pv, size_t size,
-                      const VMStateField *field, QJSON *vmdesc)
+                      const VMStateField *field, JSONWriter *vmdesc)
 {
     uint16_t *v = pv;
     qemu_put_be16s(f, v);
@@ -250,7 +250,7 @@ static int get_uint32(QEMUFile *f, void *pv, size_t size,
 }
 
 static int put_uint32(QEMUFile *f, void *pv, size_t size,
-                      const VMStateField *field, QJSON *vmdesc)
+                      const VMStateField *field, JSONWriter *vmdesc)
 {
     uint32_t *v = pv;
     qemu_put_be32s(f, v);
@@ -300,7 +300,7 @@ static int get_uint64(QEMUFile *f, void *pv, size_t size,
 }
 
 static int put_uint64(QEMUFile *f, void *pv, size_t size,
-                      const VMStateField *field, QJSON *vmdesc)
+                      const VMStateField *field, JSONWriter *vmdesc)
 {
     uint64_t *v = pv;
     qemu_put_be64s(f, v);
@@ -325,7 +325,7 @@ static int get_nullptr(QEMUFile *f, void *pv, size_t size,
 }
 
 static int put_nullptr(QEMUFile *f, void *pv, size_t size,
-                        const VMStateField *field, QJSON *vmdesc)
+                        const VMStateField *field, JSONWriter *vmdesc)
 
 {
     if (pv == NULL) {
@@ -432,7 +432,7 @@ static int get_cpudouble(QEMUFile *f, void *pv, size_t size,
 }
 
 static int put_cpudouble(QEMUFile *f, void *pv, size_t size,
-                         const VMStateField *field, QJSON *vmdesc)
+                         const VMStateField *field, JSONWriter *vmdesc)
 {
     CPU_DoubleU *v = pv;
     qemu_put_be32s(f, &v->l.upper);
@@ -457,7 +457,7 @@ static int get_buffer(QEMUFile *f, void *pv, size_t size,
 }
 
 static int put_buffer(QEMUFile *f, void *pv, size_t size,
-                      const VMStateField *field, QJSON *vmdesc)
+                      const VMStateField *field, JSONWriter *vmdesc)
 {
     uint8_t *v = pv;
     qemu_put_buffer(f, v, size);
@@ -488,7 +488,7 @@ static int get_unused_buffer(QEMUFile *f, void *pv, size_t size,
 }
 
 static int put_unused_buffer(QEMUFile *f, void *pv, size_t size,
-                             const VMStateField *field, QJSON *vmdesc)
+                             const VMStateField *field, JSONWriter *vmdesc)
 {
     static const uint8_t buf[1024];
     int block_len;
@@ -530,7 +530,7 @@ static int get_tmp(QEMUFile *f, void *pv, size_t size,
 }
 
 static int put_tmp(QEMUFile *f, void *pv, size_t size,
-                   const VMStateField *field, QJSON *vmdesc)
+                   const VMStateField *field, JSONWriter *vmdesc)
 {
     const VMStateDescription *vmsd = field->vmsd;
     void *tmp = g_malloc(size);
@@ -573,7 +573,7 @@ static int get_bitmap(QEMUFile *f, void *pv, size_t size,
 }
 
 static int put_bitmap(QEMUFile *f, void *pv, size_t size,
-                      const VMStateField *field, QJSON *vmdesc)
+                      const VMStateField *field, JSONWriter *vmdesc)
 {
     unsigned long *bmp = pv;
     int i, idx = 0;
@@ -637,7 +637,7 @@ static int get_qtailq(QEMUFile *f, void *pv, size_t unused_size,
 
 /* put for QTAILQ */
 static int put_qtailq(QEMUFile *f, void *pv, size_t unused_size,
-                      const VMStateField *field, QJSON *vmdesc)
+                      const VMStateField *field, JSONWriter *vmdesc)
 {
     const VMStateDescription *vmsd = field->vmsd;
     /* offset of the QTAILQ entry in a QTAILQ element*/
@@ -670,7 +670,7 @@ struct put_gtree_data {
     QEMUFile *f;
     const VMStateDescription *key_vmsd;
     const VMStateDescription *val_vmsd;
-    QJSON *vmdesc;
+    JSONWriter *vmdesc;
     int ret;
 };
 
@@ -703,7 +703,7 @@ static gboolean put_gtree_elem(gpointer key, gpointer value, gpointer data)
 }
 
 static int put_gtree(QEMUFile *f, void *pv, size_t unused_size,
-                     const VMStateField *field, QJSON *vmdesc)
+                     const VMStateField *field, JSONWriter *vmdesc)
 {
     bool direct_key = (!field->start);
     const VMStateDescription *key_vmsd = direct_key ? NULL : &field->vmsd[1];
@@ -819,7 +819,7 @@ const VMStateInfo vmstate_info_gtree = {
 };
 
 static int put_qlist(QEMUFile *f, void *pv, size_t unused_size,
-                     const VMStateField *field, QJSON *vmdesc)
+                     const VMStateField *field, JSONWriter *vmdesc)
 {
     const VMStateDescription *vmsd = field->vmsd;
     /* offset of the QTAILQ entry in a QTAILQ element*/
diff --git a/migration/vmstate.c b/migration/vmstate.c
index e9d2aef66b..05f87cdddc 100644
--- a/migration/vmstate.c
+++ b/migration/vmstate.c
@@ -14,14 +14,14 @@
 #include "migration.h"
 #include "migration/vmstate.h"
 #include "savevm.h"
+#include "qapi/qmp/json-writer.h"
 #include "qemu-file.h"
 #include "qemu/bitops.h"
 #include "qemu/error-report.h"
 #include "trace.h"
-#include "qjson.h"
 
 static int vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
-                                   void *opaque, QJSON *vmdesc);
+                                   void *opaque, JSONWriter *vmdesc);
 static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
                                    void *opaque);
 
@@ -249,7 +249,8 @@ static bool vmsd_can_compress(const VMStateField *field)
     return true;
 }
 
-static void vmsd_desc_field_start(const VMStateDescription *vmsd, QJSON *vmdesc,
+static void vmsd_desc_field_start(const VMStateDescription *vmsd,
+                                  JSONWriter *vmdesc,
                                   const VMStateField *field, int i, int max)
 {
     char *name, *old_name;
@@ -270,25 +271,26 @@ static void vmsd_desc_field_start(const VMStateDescription *vmsd, QJSON *vmdesc,
         g_free(old_name);
     }
 
-    json_start_object(vmdesc, NULL);
-    json_prop_str(vmdesc, "name", name);
+    json_writer_start_object(vmdesc, NULL);
+    json_writer_str(vmdesc, "name", name);
     if (is_array) {
         if (can_compress) {
-            json_prop_int(vmdesc, "array_len", max);
+            json_writer_int64(vmdesc, "array_len", max);
         } else {
-            json_prop_int(vmdesc, "index", i);
+            json_writer_int64(vmdesc, "index", i);
         }
     }
-    json_prop_str(vmdesc, "type", vmfield_get_type_name(field));
+    json_writer_str(vmdesc, "type", vmfield_get_type_name(field));
 
     if (field->flags & VMS_STRUCT) {
-        json_start_object(vmdesc, "struct");
+        json_writer_start_object(vmdesc, "struct");
     }
 
     g_free(name);
 }
 
-static void vmsd_desc_field_end(const VMStateDescription *vmsd, QJSON *vmdesc,
+static void vmsd_desc_field_end(const VMStateDescription *vmsd,
+                                JSONWriter *vmdesc,
                                 const VMStateField *field, size_t size, int i)
 {
     if (!vmdesc) {
@@ -297,11 +299,11 @@ static void vmsd_desc_field_end(const VMStateDescription *vmsd, QJSON *vmdesc,
 
     if (field->flags & VMS_STRUCT) {
         /* We printed a struct in between, close its child object */
-        json_end_object(vmdesc);
+        json_writer_end_object(vmdesc);
     }
 
-    json_prop_int(vmdesc, "size", size);
-    json_end_object(vmdesc);
+    json_writer_int64(vmdesc, "size", size);
+    json_writer_end_object(vmdesc);
 }
 
 
@@ -316,13 +318,13 @@ bool vmstate_save_needed(const VMStateDescription *vmsd, void *opaque)
 
 
 int vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
-                       void *opaque, QJSON *vmdesc_id)
+                       void *opaque, JSONWriter *vmdesc_id)
 {
     return vmstate_save_state_v(f, vmsd, opaque, vmdesc_id, vmsd->version_id);
 }
 
 int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
-                         void *opaque, QJSON *vmdesc, int version_id)
+                         void *opaque, JSONWriter *vmdesc, int version_id)
 {
     int ret = 0;
     const VMStateField *field = vmsd->fields;
@@ -339,9 +341,9 @@ int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
     }
 
     if (vmdesc) {
-        json_prop_str(vmdesc, "vmsd_name", vmsd->name);
-        json_prop_int(vmdesc, "version", version_id);
-        json_start_array(vmdesc, "fields");
+        json_writer_str(vmdesc, "vmsd_name", vmsd->name);
+        json_writer_int64(vmdesc, "version", version_id);
+        json_writer_start_array(vmdesc, "fields");
     }
 
     while (field->name) {
@@ -353,7 +355,7 @@ int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
             int i, n_elems = vmstate_n_elems(opaque, field);
             int size = vmstate_size(opaque, field);
             int64_t old_offset, written_bytes;
-            QJSON *vmdesc_loop = vmdesc;
+            JSONWriter *vmdesc_loop = vmdesc;
 
             trace_vmstate_save_state_loop(vmsd->name, field->name, n_elems);
             if (field->flags & VMS_POINTER) {
@@ -413,7 +415,7 @@ int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
     }
 
     if (vmdesc) {
-        json_end_array(vmdesc);
+        json_writer_end_array(vmdesc);
     }
 
     ret = vmstate_subsection_save(f, vmsd, opaque, vmdesc);
@@ -491,7 +493,7 @@ static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
 }
 
 static int vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
-                                   void *opaque, QJSON *vmdesc)
+                                   void *opaque, JSONWriter *vmdesc)
 {
     const VMStateDescription **sub = vmsd->subsections;
     bool vmdesc_has_subsections = false;
@@ -507,11 +509,11 @@ static int vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
             if (vmdesc) {
                 /* Only create subsection array when we have any */
                 if (!vmdesc_has_subsections) {
-                    json_start_array(vmdesc, "subsections");
+                    json_writer_start_array(vmdesc, "subsections");
                     vmdesc_has_subsections = true;
                 }
 
-                json_start_object(vmdesc, NULL);
+                json_writer_start_object(vmdesc, NULL);
             }
 
             qemu_put_byte(f, QEMU_VM_SUBSECTION);
@@ -525,14 +527,14 @@ static int vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
             }
 
             if (vmdesc) {
-                json_end_object(vmdesc);
+                json_writer_end_object(vmdesc);
             }
         }
         sub++;
     }
 
     if (vmdesc_has_subsections) {
-        json_end_array(vmdesc);
+        json_writer_end_array(vmdesc);
     }
 
     return ret;