master
c 954 lines 24.2 KB
Raw
1 /*
2 * VMStateInfo's for basic typse
3 *
4 * Copyright (c) 2009-2017 Red Hat Inc
5 *
6 * Authors:
7 * Juan Quintela <quintela@redhat.com>
8 *
9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10 * See the COPYING file in the top-level directory.
11 */
12
13 #include "qemu/osdep.h"
14 #include "qemu/cpu-float.h"
15 #include "qemu-file.h"
16 #include "migration.h"
17 #include "migration/vmstate.h"
18 #include "migration/client-options.h"
19 #include "qemu/error-report.h"
20 #include "qemu/queue.h"
21 #include "trace.h"
22 #include "qapi/error.h"
23
24 /* bool */
25
26 static bool load_bool(QEMUFile *f, void *pv, size_t size,
27 const VMStateField *field, Error **errp)
28 {
29 bool *v = pv;
30 *v = qemu_get_byte(f);
31 return true;
32 }
33
34 static bool save_bool(QEMUFile *f, void *pv, size_t size,
35 const VMStateField *field, JSONWriter *vmdesc,
36 Error **errp)
37 {
38 bool *v = pv;
39 qemu_put_byte(f, *v);
40 return true;
41 }
42
43 const VMStateInfo vmstate_info_bool = {
44 .name = "bool",
45 .load = load_bool,
46 .save = save_bool,
47 };
48
49 /* 8 bit int */
50
51 static bool load_int8(QEMUFile *f, void *pv, size_t size,
52 const VMStateField *field, Error **errp)
53 {
54 int8_t *v = pv;
55 qemu_get_s8s(f, v);
56 return true;
57 }
58
59 static bool save_int8(QEMUFile *f, void *pv, size_t size,
60 const VMStateField *field, JSONWriter *vmdesc,
61 Error **errp)
62 {
63 int8_t *v = pv;
64 qemu_put_s8s(f, v);
65 return true;
66 }
67
68 const VMStateInfo vmstate_info_int8 = {
69 .name = "int8",
70 .load = load_int8,
71 .save = save_int8,
72 };
73
74 /* 16 bit int */
75
76 static bool load_int16(QEMUFile *f, void *pv, size_t size,
77 const VMStateField *field, Error **errp)
78 {
79 int16_t *v = pv;
80 qemu_get_sbe16s(f, v);
81 return true;
82 }
83
84 static bool save_int16(QEMUFile *f, void *pv, size_t size,
85 const VMStateField *field, JSONWriter *vmdesc,
86 Error **errp)
87 {
88 int16_t *v = pv;
89 qemu_put_sbe16s(f, v);
90 return true;
91 }
92
93 const VMStateInfo vmstate_info_int16 = {
94 .name = "int16",
95 .load = load_int16,
96 .save = save_int16,
97 };
98
99 /* 32 bit int */
100
101 static bool load_int32(QEMUFile *f, void *pv, size_t size,
102 const VMStateField *field, Error **errp)
103 {
104 int32_t *v = pv;
105 qemu_get_sbe32s(f, v);
106 return true;
107 }
108
109 static bool save_int32(QEMUFile *f, void *pv, size_t size,
110 const VMStateField *field, JSONWriter *vmdesc,
111 Error **errp)
112 {
113 int32_t *v = pv;
114 qemu_put_sbe32s(f, v);
115 return true;
116 }
117
118 const VMStateInfo vmstate_info_int32 = {
119 .name = "int32",
120 .load = load_int32,
121 .save = save_int32,
122 };
123
124 /* 32 bit int. See that the received value is the same than the one
125 in the field */
126
127 static bool load_int32_equal(QEMUFile *f, void *pv, size_t size,
128 const VMStateField *field, Error **errp)
129 {
130 ERRP_GUARD();
131 int32_t *v = pv;
132 int32_t v2;
133 qemu_get_sbe32s(f, &v2);
134
135 if (*v == v2) {
136 return true;
137 }
138
139 error_setg(errp, "%" PRIx32 " != %" PRIx32, *v, v2);
140 return false;
141 }
142
143 const VMStateInfo vmstate_info_int32_equal = {
144 .name = "int32 equal",
145 .load = load_int32_equal,
146 .save = save_int32,
147 };
148
149 /* 32 bit int. Check that the received value is non-negative
150 * and less than or equal to the one in the field.
151 */
152
153 static bool load_int32_le(QEMUFile *f, void *pv, size_t size,
154 const VMStateField *field, Error **errp)
155 {
156 int32_t *cur = pv;
157 int32_t loaded;
158 qemu_get_sbe32s(f, &loaded);
159
160 if (loaded >= 0 && loaded <= *cur) {
161 *cur = loaded;
162 return true;
163 }
164
165 error_setg(errp, "Invalid value %" PRId32
166 " expecting positive value <= %" PRId32,
167 loaded, *cur);
168 return false;
169 }
170
171 const VMStateInfo vmstate_info_int32_le = {
172 .name = "int32 le",
173 .load = load_int32_le,
174 .save = save_int32,
175 };
176
177 /* 64 bit int */
178
179 static bool load_int64(QEMUFile *f, void *pv, size_t size,
180 const VMStateField *field, Error **errp)
181 {
182 int64_t *v = pv;
183 qemu_get_sbe64s(f, v);
184 return true;
185 }
186
187 static bool save_int64(QEMUFile *f, void *pv, size_t size,
188 const VMStateField *field, JSONWriter *vmdesc,
189 Error **errp)
190 {
191 int64_t *v = pv;
192 qemu_put_sbe64s(f, v);
193 return true;
194 }
195
196 const VMStateInfo vmstate_info_int64 = {
197 .name = "int64",
198 .load = load_int64,
199 .save = save_int64,
200 };
201
202 /* 8 bit unsigned int */
203
204 static bool load_uint8(QEMUFile *f, void *pv, size_t size,
205 const VMStateField *field, Error **errp)
206 {
207 uint8_t *v = pv;
208 qemu_get_8s(f, v);
209 return true;
210 }
211
212 static bool save_uint8(QEMUFile *f, void *pv, size_t size,
213 const VMStateField *field, JSONWriter *vmdesc,
214 Error **errp)
215 {
216 uint8_t *v = pv;
217 qemu_put_8s(f, v);
218 return true;
219 }
220
221 const VMStateInfo vmstate_info_uint8 = {
222 .name = "uint8",
223 .load = load_uint8,
224 .save = save_uint8,
225 };
226
227 /* 16 bit unsigned int */
228
229 static bool load_uint16(QEMUFile *f, void *pv, size_t size,
230 const VMStateField *field, Error **errp)
231 {
232 uint16_t *v = pv;
233 qemu_get_be16s(f, v);
234 return true;
235 }
236
237 static bool save_uint16(QEMUFile *f, void *pv, size_t size,
238 const VMStateField *field, JSONWriter *vmdesc,
239 Error **errp)
240 {
241 uint16_t *v = pv;
242 qemu_put_be16s(f, v);
243 return true;
244 }
245
246 const VMStateInfo vmstate_info_uint16 = {
247 .name = "uint16",
248 .load = load_uint16,
249 .save = save_uint16,
250 };
251
252 /* 32 bit unsigned int */
253
254 static bool load_uint32(QEMUFile *f, void *pv, size_t size,
255 const VMStateField *field, Error **errp)
256 {
257 uint32_t *v = pv;
258 qemu_get_be32s(f, v);
259 return true;
260 }
261
262 static bool save_uint32(QEMUFile *f, void *pv, size_t size,
263 const VMStateField *field, JSONWriter *vmdesc,
264 Error **errp)
265 {
266 uint32_t *v = pv;
267 qemu_put_be32s(f, v);
268 return true;
269 }
270
271 const VMStateInfo vmstate_info_uint32 = {
272 .name = "uint32",
273 .load = load_uint32,
274 .save = save_uint32,
275 };
276
277 /* 32 bit uint. See that the received value is the same than the one
278 in the field */
279
280 static bool load_uint32_equal(QEMUFile *f, void *pv, size_t size,
281 const VMStateField *field, Error **errp)
282 {
283 ERRP_GUARD();
284 uint32_t *v = pv;
285 uint32_t v2;
286 qemu_get_be32s(f, &v2);
287
288 if (*v == v2) {
289 return true;
290 }
291
292 error_setg(errp, "%" PRIx32 " != %" PRIx32, *v, v2);
293 return false;
294 }
295
296 const VMStateInfo vmstate_info_uint32_equal = {
297 .name = "uint32 equal",
298 .load = load_uint32_equal,
299 .save = save_uint32,
300 };
301
302 /* 64 bit unsigned int */
303
304 static bool load_uint64(QEMUFile *f, void *pv, size_t size,
305 const VMStateField *field, Error **errp)
306 {
307 uint64_t *v = pv;
308 qemu_get_be64s(f, v);
309 return true;
310 }
311
312 static bool save_uint64(QEMUFile *f, void *pv, size_t size,
313 const VMStateField *field, JSONWriter *vmdesc,
314 Error **errp)
315 {
316 uint64_t *v = pv;
317 qemu_put_be64s(f, v);
318 return true;
319 }
320
321 const VMStateInfo vmstate_info_uint64 = {
322 .name = "uint64",
323 .load = load_uint64,
324 .save = save_uint64,
325 };
326
327 /* File descriptor communicated via SCM_RIGHTS */
328
329 static bool load_fd(QEMUFile *f, void *pv, size_t size,
330 const VMStateField *field, Error **errp)
331 {
332 int32_t *v = pv;
333
334 if (migrate_mode() == MIG_MODE_CPR_EXEC) {
335 qemu_get_sbe32s(f, v);
336 return true;
337 }
338
339 return qemu_file_get_fd(f, v) >= 0;
340 }
341
342 static bool save_fd(QEMUFile *f, void *pv, size_t size,
343 const VMStateField *field, JSONWriter *vmdesc,
344 Error **errp)
345 {
346 int32_t *v = pv;
347
348 if (migrate_mode() == MIG_MODE_CPR_EXEC) {
349 qemu_put_sbe32s(f, v);
350 return true;
351 }
352
353 return qemu_file_put_fd(f, *v) >= 0;
354 }
355
356 const VMStateInfo vmstate_info_fd = {
357 .name = "fd",
358 .load = load_fd,
359 .save = save_fd,
360 };
361
362 static bool load_ptr_marker(QEMUFile *f, void *pv, size_t size,
363 const VMStateField *field, Error **errp)
364
365 {
366 /*
367 * Load is done in vmstate core, see vmstate_ptr_marker_load().
368 */
369 g_assert_not_reached();
370 return false;
371 }
372
373 static bool save_ptr_marker(QEMUFile *f, void *pv, size_t size,
374 const VMStateField *field, JSONWriter *vmdesc,
375 Error **errp)
376
377 {
378 qemu_put_byte(f, pv ? VMS_MARKER_PTR_VALID : VMS_MARKER_PTR_NULL);
379 return true;
380 }
381
382 const VMStateInfo vmstate_info_ptr_marker = {
383 .name = "ptr-marker",
384 .load = load_ptr_marker,
385 .save = save_ptr_marker,
386 };
387
388 /* 64 bit unsigned int. See that the received value is the same than the one
389 in the field */
390
391 static bool load_uint64_equal(QEMUFile *f, void *pv, size_t size,
392 const VMStateField *field, Error **errp)
393 {
394 ERRP_GUARD();
395 uint64_t *v = pv;
396 uint64_t v2;
397
398 qemu_get_be64s(f, &v2);
399
400 if (*v == v2) {
401 return true;
402 }
403
404 error_setg(errp, "%" PRIx64 " != %" PRIx64, *v, v2);
405 return false;
406 }
407
408 const VMStateInfo vmstate_info_uint64_equal = {
409 .name = "int64 equal",
410 .load = load_uint64_equal,
411 .save = save_uint64,
412 };
413
414 /* 8 bit int. See that the received value is the same than the one
415 in the field */
416
417 static bool load_uint8_equal(QEMUFile *f, void *pv, size_t size,
418 const VMStateField *field, Error **errp)
419 {
420 ERRP_GUARD();
421 uint8_t *v = pv;
422 uint8_t v2;
423
424 qemu_get_8s(f, &v2);
425
426 if (*v == v2) {
427 return true;
428 }
429
430 error_setg(errp, "%x != %x", *v, v2);
431 return false;
432 }
433
434 const VMStateInfo vmstate_info_uint8_equal = {
435 .name = "uint8 equal",
436 .load = load_uint8_equal,
437 .save = save_uint8,
438 };
439
440 /* 16 bit unsigned int int. See that the received value is the same than the one
441 in the field */
442
443 static bool load_uint16_equal(QEMUFile *f, void *pv, size_t size,
444 const VMStateField *field, Error **errp)
445 {
446 ERRP_GUARD();
447 uint16_t *v = pv;
448 uint16_t v2;
449
450 qemu_get_be16s(f, &v2);
451
452 if (*v == v2) {
453 return true;
454 }
455
456 error_setg(errp, "%x != %x", *v, v2);
457 return false;
458 }
459
460 const VMStateInfo vmstate_info_uint16_equal = {
461 .name = "uint16 equal",
462 .load = load_uint16_equal,
463 .save = save_uint16,
464 };
465
466 /* CPU_DoubleU type */
467
468 static bool load_cpudouble(QEMUFile *f, void *pv, size_t size,
469 const VMStateField *field, Error **errp)
470 {
471 CPU_DoubleU *v = pv;
472 qemu_get_be32s(f, &v->l.upper);
473 qemu_get_be32s(f, &v->l.lower);
474 return true;
475 }
476
477 static bool save_cpudouble(QEMUFile *f, void *pv, size_t size,
478 const VMStateField *field, JSONWriter *vmdesc,
479 Error **errp)
480 {
481 CPU_DoubleU *v = pv;
482 qemu_put_be32s(f, &v->l.upper);
483 qemu_put_be32s(f, &v->l.lower);
484 return true;
485 }
486
487 const VMStateInfo vmstate_info_cpudouble = {
488 .name = "CPU_Double_U",
489 .load = load_cpudouble,
490 .save = save_cpudouble,
491 };
492
493 /* uint8_t buffers */
494
495 static bool load_buffer(QEMUFile *f, void *pv, size_t size,
496 const VMStateField *field, Error **errp)
497 {
498 uint8_t *v = pv;
499 qemu_get_buffer(f, v, size);
500 return true;
501 }
502
503 static bool save_buffer(QEMUFile *f, void *pv, size_t size,
504 const VMStateField *field, JSONWriter *vmdesc,
505 Error **errp)
506 {
507 uint8_t *v = pv;
508 qemu_put_buffer(f, v, size);
509 return true;
510 }
511
512 const VMStateInfo vmstate_info_buffer = {
513 .name = "buffer",
514 .load = load_buffer,
515 .save = save_buffer,
516 };
517
518 /* unused buffers: space that was used for some fields that are
519 not useful anymore */
520
521 static bool load_unused_buffer(QEMUFile *f, void *pv, size_t size,
522 const VMStateField *field, Error **errp)
523 {
524 uint8_t buf[1024];
525 int block_len;
526
527 while (size > 0) {
528 block_len = MIN(sizeof(buf), size);
529 size -= block_len;
530 qemu_get_buffer(f, buf, block_len);
531 }
532
533 return true;
534 }
535
536 static bool save_unused_buffer(QEMUFile *f, void *pv, size_t size,
537 const VMStateField *field, JSONWriter *vmdesc,
538 Error **errp)
539 {
540 static const uint8_t buf[1024];
541 int block_len;
542
543 while (size > 0) {
544 block_len = MIN(sizeof(buf), size);
545 size -= block_len;
546 qemu_put_buffer(f, buf, block_len);
547 }
548
549 return true;
550 }
551
552 const VMStateInfo vmstate_info_unused_buffer = {
553 .name = "unused_buffer",
554 .load = load_unused_buffer,
555 .save = save_unused_buffer,
556 };
557
558 /* vmstate_info_tmp, see VMSTATE_WITH_TMP, the idea is that we allocate
559 * a temporary buffer and the pre_load/pre_save methods in the child vmsd
560 * copy stuff from the parent into the child and do calculations to fill
561 * in fields that don't really exist in the parent but need to be in the
562 * stream.
563 */
564 static bool load_tmp(QEMUFile *f, void *pv, size_t size,
565 const VMStateField *field, Error **errp)
566 {
567 const VMStateDescription *vmsd = field->vmsd;
568 int version_id = field->version_id;
569 g_autofree void *tmp = g_malloc(size);
570
571 /* Writes the parent field which is at the start of the tmp */
572 *(void **)tmp = pv;
573 return vmstate_load_vmsd(f, vmsd, tmp, version_id, errp);
574 }
575
576 static bool save_tmp(QEMUFile *f, void *pv, size_t size,
577 const VMStateField *field, JSONWriter *vmdesc,
578 Error **errp)
579 {
580 const VMStateDescription *vmsd = field->vmsd;
581 g_autofree void *tmp = g_malloc(size);
582
583 /* Writes the parent field which is at the start of the tmp */
584 *(void **)tmp = pv;
585 return vmstate_save_vmsd(f, vmsd, tmp, vmdesc, errp);
586 }
587
588 const VMStateInfo vmstate_info_tmp = {
589 .name = "tmp",
590 .load = load_tmp,
591 .save = save_tmp,
592 };
593
594 /* bitmaps (as defined by bitmap.h). Note that size here is the size
595 * of the bitmap in bits. The on-the-wire format of a bitmap is 64
596 * bit words with the bits in big endian order. The in-memory format
597 * is an array of 'unsigned long', which may be either 32 or 64 bits.
598 */
599 /* This is the number of 64 bit words sent over the wire */
600 #define BITS_TO_U64S(nr) DIV_ROUND_UP(nr, 64)
601 static bool load_bitmap(QEMUFile *f, void *pv, size_t size,
602 const VMStateField *field, Error **errp)
603 {
604 unsigned long *bmp = pv;
605 int i, idx = 0;
606
607 for (i = 0; i < BITS_TO_U64S(size); i++) {
608 uint64_t w = qemu_get_be64(f);
609 bmp[idx++] = w;
610 if (sizeof(unsigned long) == 4 && idx < BITS_TO_LONGS(size)) {
611 bmp[idx++] = w >> 32;
612 }
613 }
614
615 return true;
616 }
617
618 static bool save_bitmap(QEMUFile *f, void *pv, size_t size,
619 const VMStateField *field, JSONWriter *vmdesc,
620 Error **errp)
621 {
622 unsigned long *bmp = pv;
623 int i, idx = 0;
624
625 for (i = 0; i < BITS_TO_U64S(size); i++) {
626 uint64_t w = bmp[idx++];
627 if (sizeof(unsigned long) == 4 && idx < BITS_TO_LONGS(size)) {
628 w |= ((uint64_t)bmp[idx++]) << 32;
629 }
630 qemu_put_be64(f, w);
631 }
632
633 return true;
634 }
635
636 const VMStateInfo vmstate_info_bitmap = {
637 .name = "bitmap",
638 .load = load_bitmap,
639 .save = save_bitmap,
640 };
641
642 /* get for QTAILQ
643 * meta data about the QTAILQ is encoded in a VMStateField structure
644 */
645 static bool load_qtailq(QEMUFile *f, void *pv, size_t unused_size,
646 const VMStateField *field, Error **errp)
647 {
648 const VMStateDescription *vmsd = field->vmsd;
649 /* size of a QTAILQ element */
650 size_t size = field->size;
651 /* offset of the QTAILQ entry in a QTAILQ element */
652 size_t entry_offset = field->start;
653 int version_id = field->version_id;
654 void *elm;
655
656 trace_load_qtailq(vmsd->name, version_id);
657 if (version_id > vmsd->version_id) {
658 error_setg(errp, "%s %s", vmsd->name, "too new");
659 return false;
660 }
661 if (version_id < vmsd->minimum_version_id) {
662 error_setg(errp, "%s %s", vmsd->name, "too old");
663 return false;
664 }
665
666 while (qemu_get_byte(f)) {
667 elm = g_malloc(size);
668 if (!vmstate_load_vmsd(f, vmsd, elm, version_id, errp)) {
669 g_free(elm);
670 return false;
671 }
672 QTAILQ_RAW_INSERT_TAIL(pv, elm, entry_offset);
673 }
674
675 trace_load_qtailq_end(vmsd->name);
676 return true;
677 }
678
679 /* save for QTAILQ */
680 static bool save_qtailq(QEMUFile *f, void *pv, size_t unused_size,
681 const VMStateField *field, JSONWriter *vmdesc,
682 Error **errp)
683 {
684 const VMStateDescription *vmsd = field->vmsd;
685 /* offset of the QTAILQ entry in a QTAILQ element*/
686 size_t entry_offset = field->start;
687 void *elm;
688
689 trace_save_qtailq(vmsd->name, vmsd->version_id);
690
691 QTAILQ_RAW_FOREACH(elm, pv, entry_offset) {
692 qemu_put_byte(f, true);
693 if (!vmstate_save_vmsd(f, vmsd, elm, vmdesc, errp)) {
694 return false;
695 }
696 }
697 qemu_put_byte(f, false);
698
699 trace_save_qtailq_end(vmsd->name);
700
701 return true;
702 }
703 const VMStateInfo vmstate_info_qtailq = {
704 .name = "qtailq",
705 .load = load_qtailq,
706 .save = save_qtailq,
707 };
708
709 struct save_gtree_data {
710 QEMUFile *f;
711 const VMStateDescription *key_vmsd;
712 const VMStateDescription *val_vmsd;
713 JSONWriter *vmdesc;
714 Error **errp;
715 bool failed;
716 };
717
718 /*
719 * save_gtree_elem - func for g_tree_foreach, return true to stop
720 * iteration.
721 */
722 static gboolean save_gtree_elem(gpointer key, gpointer value, gpointer data)
723 {
724 struct save_gtree_data *capsule = (struct save_gtree_data *)data;
725 QEMUFile *f = capsule->f;
726
727 qemu_put_byte(f, true);
728
729 /* put the key */
730 if (!capsule->key_vmsd) {
731 qemu_put_be64(f, (uint64_t)(uintptr_t)(key)); /* direct key */
732 } else {
733 if (!vmstate_save_vmsd(f, capsule->key_vmsd, key, capsule->vmdesc,
734 capsule->errp)) {
735 capsule->failed = true;
736 return true;
737 }
738 }
739
740 /* put the data */
741 if (!vmstate_save_vmsd(f, capsule->val_vmsd, value, capsule->vmdesc,
742 capsule->errp)) {
743 capsule->failed = true;
744 return true;
745 }
746 return false;
747 }
748
749 static bool save_gtree(QEMUFile *f, void *pv, size_t unused_size,
750 const VMStateField *field, JSONWriter *vmdesc,
751 Error **errp)
752 {
753 bool direct_key = (!field->start);
754 const VMStateDescription *key_vmsd = direct_key ? NULL : &field->vmsd[1];
755 const VMStateDescription *val_vmsd = &field->vmsd[0];
756 const char *key_vmsd_name = direct_key ? "direct" : key_vmsd->name;
757 struct save_gtree_data capsule = {
758 .f = f,
759 .key_vmsd = key_vmsd,
760 .val_vmsd = val_vmsd,
761 .vmdesc = vmdesc,
762 .errp = errp,
763 .failed = false};
764 GTree **pval = pv;
765 GTree *tree = *pval;
766 uint32_t nnodes = g_tree_nnodes(tree);
767
768 trace_save_gtree(field->name, key_vmsd_name, val_vmsd->name, nnodes);
769 qemu_put_be32(f, nnodes);
770 g_tree_foreach(tree, save_gtree_elem, (gpointer)&capsule);
771 qemu_put_byte(f, false);
772 if (capsule.failed) {
773 trace_save_gtree_end(field->name, key_vmsd_name, val_vmsd->name);
774 return false;
775 }
776
777 trace_save_gtree_end(field->name, key_vmsd_name, val_vmsd->name);
778 return true;
779 }
780
781 static bool load_gtree(QEMUFile *f, void *pv, size_t unused_size,
782 const VMStateField *field, Error **errp)
783 {
784 bool direct_key = (!field->start);
785 const VMStateDescription *key_vmsd = direct_key ? NULL : &field->vmsd[1];
786 const VMStateDescription *val_vmsd = &field->vmsd[0];
787 const char *key_vmsd_name = direct_key ? "direct" : key_vmsd->name;
788 int version_id = field->version_id;
789 size_t key_size = field->start;
790 size_t val_size = field->size;
791 int nnodes, count = 0;
792 GTree **pval = pv;
793 GTree *tree = *pval;
794 void *key, *val;
795
796 /* in case of direct key, the key vmsd can be {}, ie. check fields */
797 if (!direct_key && version_id > key_vmsd->version_id) {
798 error_setg(errp, "%s %s", key_vmsd->name, "too new");
799 return false;
800 }
801 if (!direct_key && version_id < key_vmsd->minimum_version_id) {
802 error_setg(errp, "%s %s", key_vmsd->name, "too old");
803 return false;
804 }
805 if (version_id > val_vmsd->version_id) {
806 error_setg(errp, "%s %s", val_vmsd->name, "too new");
807 return false;
808 }
809 if (version_id < val_vmsd->minimum_version_id) {
810 error_setg(errp, "%s %s", val_vmsd->name, "too old");
811 return false;
812 }
813
814 nnodes = qemu_get_be32(f);
815 trace_load_gtree(field->name, key_vmsd_name, val_vmsd->name, nnodes);
816
817 while (qemu_get_byte(f)) {
818 if ((++count) > nnodes) {
819 break;
820 }
821 if (direct_key) {
822 key = (void *)(uintptr_t)qemu_get_be64(f);
823 } else {
824 key = g_malloc0(key_size);
825 if (!vmstate_load_vmsd(f, key_vmsd, key, version_id, errp)) {
826 goto key_error;
827 }
828 }
829 val = g_malloc0(val_size);
830 if (!vmstate_load_vmsd(f, val_vmsd, val, version_id, errp)) {
831 goto val_error;
832 }
833 g_tree_insert(tree, key, val);
834 }
835 if (count != nnodes) {
836 error_setg(errp, "%s inconsistent stream when loading the gtree",
837 field->name);
838 return false;
839 }
840
841 trace_load_gtree_end(field->name, key_vmsd_name, val_vmsd->name);
842 return true;
843
844 val_error:
845 g_free(val);
846
847 key_error:
848 if (!direct_key) {
849 g_free(key);
850 }
851 return false;
852 }
853
854
855 const VMStateInfo vmstate_info_gtree = {
856 .name = "gtree",
857 .load = load_gtree,
858 .save = save_gtree,
859 };
860
861 static bool save_qlist(QEMUFile *f, void *pv, size_t unused_size,
862 const VMStateField *field, JSONWriter *vmdesc,
863 Error **errp)
864 {
865 const VMStateDescription *vmsd = field->vmsd;
866 /* offset of the QTAILQ entry in a QTAILQ element*/
867 size_t entry_offset = field->start;
868 void *elm;
869
870 trace_save_qlist(field->name, vmsd->name, vmsd->version_id);
871 QLIST_RAW_FOREACH(elm, pv, entry_offset) {
872 qemu_put_byte(f, true);
873 if (!vmstate_save_vmsd(f, vmsd, elm, vmdesc, errp)) {
874 return false;
875 }
876 }
877 qemu_put_byte(f, false);
878 trace_save_qlist_end(field->name, vmsd->name);
879
880 return true;
881 }
882
883 static bool load_qlist(QEMUFile *f, void *pv, size_t unused_size,
884 const VMStateField *field, Error **errp)
885 {
886 const VMStateDescription *vmsd = field->vmsd;
887 /* size of a QLIST element */
888 size_t size = field->size;
889 /* offset of the QLIST entry in a QLIST element */
890 size_t entry_offset = field->start;
891 int version_id = field->version_id;
892 void *elm, *prev = NULL;
893
894 trace_load_qlist(field->name, vmsd->name, vmsd->version_id);
895 if (version_id > vmsd->version_id) {
896 error_setg(errp, "%s %s", vmsd->name, "too new");
897 return false;
898 }
899 if (version_id < vmsd->minimum_version_id) {
900 error_setg(errp, "%s %s", vmsd->name, "too old");
901 return false;
902 }
903
904 while (qemu_get_byte(f)) {
905 elm = g_malloc(size);
906 if (!vmstate_load_vmsd(f, vmsd, elm, version_id, errp)) {
907 g_free(elm);
908 return false;
909 }
910 if (!prev) {
911 QLIST_RAW_INSERT_HEAD(pv, elm, entry_offset);
912 } else {
913 QLIST_RAW_INSERT_AFTER(pv, prev, elm, entry_offset);
914 }
915 prev = elm;
916 }
917 trace_load_qlist_end(field->name, vmsd->name);
918
919 return true;
920 }
921
922 const VMStateInfo vmstate_info_qlist = {
923 .name = "qlist",
924 .load = load_qlist,
925 .save = save_qlist,
926 };
927
928 static int get_g_byte_array(QEMUFile *f, void *pv, size_t size,
929 const VMStateField *field)
930 {
931 GByteArray *byte_array = *(GByteArray **)pv;
932 uint32_t len = qemu_get_be32(f);
933
934 g_byte_array_set_size(byte_array, len);
935 qemu_get_buffer(f, byte_array->data, len);
936 return 0;
937 }
938
939 static int put_g_byte_array(QEMUFile *f, void *pv, size_t size,
940 const VMStateField *field, JSONWriter *vmdesc)
941 {
942 GByteArray *byte_array = *(GByteArray **)pv;
943
944 qemu_put_be32(f, byte_array->len);
945 qemu_put_buffer(f, byte_array->data, byte_array->len);
946
947 return 0;
948 }
949
950 const VMStateInfo vmstate_info_g_byte_array = {
951 .name = "GByteArray",
952 .get = get_g_byte_array,
953 .put = put_g_byte_array,
954 };