aboutsummaryrefslogtreecommitdiff
path: root/migration
diff options
context:
space:
mode:
Diffstat (limited to 'migration')
-rw-r--r--migration/trace-events4
-rw-r--r--migration/vmstate.c69
2 files changed, 73 insertions, 0 deletions
diff --git a/migration/trace-events b/migration/trace-events
index 94134f700b..c46f9e98df 100644
--- a/migration/trace-events
+++ b/migration/trace-events
@@ -52,6 +52,10 @@ vmstate_n_elems(const char *name, int n_elems) "%s: %d"
vmstate_subsection_load(const char *parent) "%s"
vmstate_subsection_load_bad(const char *parent, const char *sub, const char *sub2) "%s: %s/%s"
vmstate_subsection_load_good(const char *parent) "%s"
+get_qtailq(const char *name, int version_id) "%s v%d"
+get_qtailq_end(const char *name, const char *reason, int val) "%s %s/%d"
+put_qtailq(const char *name, int version_id) "%s v%d"
+put_qtailq_end(const char *name, const char *reason) "%s %s"
# migration/qemu-file.c
qemu_file_fclose(void) ""
diff --git a/migration/vmstate.c b/migration/vmstate.c
index 7b4bd6e835..2f9d4ba160 100644
--- a/migration/vmstate.c
+++ b/migration/vmstate.c
@@ -5,6 +5,7 @@
#include "migration/vmstate.h"
#include "qemu/bitops.h"
#include "qemu/error-report.h"
+#include "qemu/queue.h"
#include "trace.h"
#include "migration/qjson.h"
@@ -965,3 +966,71 @@ const VMStateInfo vmstate_info_bitmap = {
.get = get_bitmap,
.put = put_bitmap,
};
+
+/* get for QTAILQ
+ * meta data about the QTAILQ is encoded in a VMStateField structure
+ */
+static int get_qtailq(QEMUFile *f, void *pv, size_t unused_size,
+ VMStateField *field)
+{
+ int ret = 0;
+ const VMStateDescription *vmsd = field->vmsd;
+ /* size of a QTAILQ element */
+ size_t size = field->size;
+ /* offset of the QTAILQ entry in a QTAILQ element */
+ size_t entry_offset = field->start;
+ int version_id = field->version_id;
+ void *elm;
+
+ trace_get_qtailq(vmsd->name, version_id);
+ if (version_id > vmsd->version_id) {
+ error_report("%s %s", vmsd->name, "too new");
+ trace_get_qtailq_end(vmsd->name, "too new", -EINVAL);
+
+ return -EINVAL;
+ }
+ if (version_id < vmsd->minimum_version_id) {
+ error_report("%s %s", vmsd->name, "too old");
+ trace_get_qtailq_end(vmsd->name, "too old", -EINVAL);
+ return -EINVAL;
+ }
+
+ while (qemu_get_byte(f)) {
+ elm = g_malloc(size);
+ ret = vmstate_load_state(f, vmsd, elm, version_id);
+ if (ret) {
+ return ret;
+ }
+ QTAILQ_RAW_INSERT_TAIL(pv, elm, entry_offset);
+ }
+
+ trace_get_qtailq_end(vmsd->name, "end", ret);
+ return ret;
+}
+
+/* put for QTAILQ */
+static int put_qtailq(QEMUFile *f, void *pv, size_t unused_size,
+ VMStateField *field, QJSON *vmdesc)
+{
+ const VMStateDescription *vmsd = field->vmsd;
+ /* offset of the QTAILQ entry in a QTAILQ element*/
+ size_t entry_offset = field->start;
+ void *elm;
+
+ trace_put_qtailq(vmsd->name, vmsd->version_id);
+
+ QTAILQ_RAW_FOREACH(elm, pv, entry_offset) {
+ qemu_put_byte(f, true);
+ vmstate_save_state(f, vmsd, elm, vmdesc);
+ }
+ qemu_put_byte(f, false);
+
+ trace_put_qtailq_end(vmsd->name, "end");
+
+ return 0;
+}
+const VMStateInfo vmstate_info_qtailq = {
+ .name = "qtailq",
+ .get = get_qtailq,
+ .put = put_qtailq,
+};