1
2
3
4
5
6
7
8
9
10
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
23
24
25static int get_bool(QEMUFile *f, void *pv, size_t size,
26 const VMStateField *field)
27{
28 bool *v = pv;
29 *v = qemu_get_byte(f);
30 return 0;
31}
32
33static int put_bool(QEMUFile *f, void *pv, size_t size,
34 const VMStateField *field, JSONWriter *vmdesc)
35{
36 bool *v = pv;
37 qemu_put_byte(f, *v);
38 return 0;
39}
40
41const VMStateInfo vmstate_info_bool = {
42 .name = "bool",
43 .get = get_bool,
44 .put = put_bool,
45};
46
47
48
49static int get_int8(QEMUFile *f, void *pv, size_t size,
50 const VMStateField *field)
51{
52 int8_t *v = pv;
53 qemu_get_s8s(f, v);
54 return 0;
55}
56
57static int put_int8(QEMUFile *f, void *pv, size_t size,
58 const VMStateField *field, JSONWriter *vmdesc)
59{
60 int8_t *v = pv;
61 qemu_put_s8s(f, v);
62 return 0;
63}
64
65const VMStateInfo vmstate_info_int8 = {
66 .name = "int8",
67 .get = get_int8,
68 .put = put_int8,
69};
70
71
72
73static int get_int16(QEMUFile *f, void *pv, size_t size,
74 const VMStateField *field)
75{
76 int16_t *v = pv;
77 qemu_get_sbe16s(f, v);
78 return 0;
79}
80
81static int put_int16(QEMUFile *f, void *pv, size_t size,
82 const VMStateField *field, JSONWriter *vmdesc)
83{
84 int16_t *v = pv;
85 qemu_put_sbe16s(f, v);
86 return 0;
87}
88
89const VMStateInfo vmstate_info_int16 = {
90 .name = "int16",
91 .get = get_int16,
92 .put = put_int16,
93};
94
95
96
97static int get_int32(QEMUFile *f, void *pv, size_t size,
98 const VMStateField *field)
99{
100 int32_t *v = pv;
101 qemu_get_sbe32s(f, v);
102 return 0;
103}
104
105static int put_int32(QEMUFile *f, void *pv, size_t size,
106 const VMStateField *field, JSONWriter *vmdesc)
107{
108 int32_t *v = pv;
109 qemu_put_sbe32s(f, v);
110 return 0;
111}
112
113const VMStateInfo vmstate_info_int32 = {
114 .name = "int32",
115 .get = get_int32,
116 .put = put_int32,
117};
118
119
120
121
122static int get_int32_equal(QEMUFile *f, void *pv, size_t size,
123 const VMStateField *field)
124{
125 int32_t *v = pv;
126 int32_t v2;
127 qemu_get_sbe32s(f, &v2);
128
129 if (*v == v2) {
130 return 0;
131 }
132 error_report("%" PRIx32 " != %" PRIx32, *v, v2);
133 if (field->err_hint) {
134 error_printf("%s\n", field->err_hint);
135 }
136 return -EINVAL;
137}
138
139const VMStateInfo vmstate_info_int32_equal = {
140 .name = "int32 equal",
141 .get = get_int32_equal,
142 .put = put_int32,
143};
144
145
146
147
148
149static int get_int32_le(QEMUFile *f, void *pv, size_t size,
150 const VMStateField *field)
151{
152 int32_t *cur = pv;
153 int32_t loaded;
154 qemu_get_sbe32s(f, &loaded);
155
156 if (loaded >= 0 && loaded <= *cur) {
157 *cur = loaded;
158 return 0;
159 }
160 error_report("Invalid value %" PRId32
161 " expecting positive value <= %" PRId32,
162 loaded, *cur);
163 return -EINVAL;
164}
165
166const VMStateInfo vmstate_info_int32_le = {
167 .name = "int32 le",
168 .get = get_int32_le,
169 .put = put_int32,
170};
171
172
173
174static int get_int64(QEMUFile *f, void *pv, size_t size,
175 const VMStateField *field)
176{
177 int64_t *v = pv;
178 qemu_get_sbe64s(f, v);
179 return 0;
180}
181
182static int put_int64(QEMUFile *f, void *pv, size_t size,
183 const VMStateField *field, JSONWriter *vmdesc)
184{
185 int64_t *v = pv;
186 qemu_put_sbe64s(f, v);
187 return 0;
188}
189
190const VMStateInfo vmstate_info_int64 = {
191 .name = "int64",
192 .get = get_int64,
193 .put = put_int64,
194};
195
196
197
198static int get_uint8(QEMUFile *f, void *pv, size_t size,
199 const VMStateField *field)
200{
201 uint8_t *v = pv;
202 qemu_get_8s(f, v);
203 return 0;
204}
205
206static int put_uint8(QEMUFile *f, void *pv, size_t size,
207 const VMStateField *field, JSONWriter *vmdesc)
208{
209 uint8_t *v = pv;
210 qemu_put_8s(f, v);
211 return 0;
212}
213
214const VMStateInfo vmstate_info_uint8 = {
215 .name = "uint8",
216 .get = get_uint8,
217 .put = put_uint8,
218};
219
220
221
222static int get_uint16(QEMUFile *f, void *pv, size_t size,
223 const VMStateField *field)
224{
225 uint16_t *v = pv;
226 qemu_get_be16s(f, v);
227 return 0;
228}
229
230static int put_uint16(QEMUFile *f, void *pv, size_t size,
231 const VMStateField *field, JSONWriter *vmdesc)
232{
233 uint16_t *v = pv;
234 qemu_put_be16s(f, v);
235 return 0;
236}
237
238const VMStateInfo vmstate_info_uint16 = {
239 .name = "uint16",
240 .get = get_uint16,
241 .put = put_uint16,
242};
243
244
245
246static int get_uint32(QEMUFile *f, void *pv, size_t size,
247 const VMStateField *field)
248{
249 uint32_t *v = pv;
250 qemu_get_be32s(f, v);
251 return 0;
252}
253
254static int put_uint32(QEMUFile *f, void *pv, size_t size,
255 const VMStateField *field, JSONWriter *vmdesc)
256{
257 uint32_t *v = pv;
258 qemu_put_be32s(f, v);
259 return 0;
260}
261
262const VMStateInfo vmstate_info_uint32 = {
263 .name = "uint32",
264 .get = get_uint32,
265 .put = put_uint32,
266};
267
268
269
270
271static int get_uint32_equal(QEMUFile *f, void *pv, size_t size,
272 const VMStateField *field)
273{
274 uint32_t *v = pv;
275 uint32_t v2;
276 qemu_get_be32s(f, &v2);
277
278 if (*v == v2) {
279 return 0;
280 }
281 error_report("%" PRIx32 " != %" PRIx32, *v, v2);
282 if (field->err_hint) {
283 error_printf("%s\n", field->err_hint);
284 }
285 return -EINVAL;
286}
287
288const VMStateInfo vmstate_info_uint32_equal = {
289 .name = "uint32 equal",
290 .get = get_uint32_equal,
291 .put = put_uint32,
292};
293
294
295
296static int get_uint64(QEMUFile *f, void *pv, size_t size,
297 const VMStateField *field)
298{
299 uint64_t *v = pv;
300 qemu_get_be64s(f, v);
301 return 0;
302}
303
304static int put_uint64(QEMUFile *f, void *pv, size_t size,
305 const VMStateField *field, JSONWriter *vmdesc)
306{
307 uint64_t *v = pv;
308 qemu_put_be64s(f, v);
309 return 0;
310}
311
312const VMStateInfo vmstate_info_uint64 = {
313 .name = "uint64",
314 .get = get_uint64,
315 .put = put_uint64,
316};
317
318
319
320static int get_fd(QEMUFile *f, void *pv, size_t size,
321 const VMStateField *field)
322{
323 int32_t *v = pv;
324 *v = qemu_file_get_fd(f);
325 return 0;
326}
327
328static int put_fd(QEMUFile *f, void *pv, size_t size,
329 const VMStateField *field, JSONWriter *vmdesc)
330{
331 int32_t *v = pv;
332 return qemu_file_put_fd(f, *v);
333}
334
335const VMStateInfo vmstate_info_fd = {
336 .name = "fd",
337 .get = get_fd,
338 .put = put_fd,
339};
340
341static int get_nullptr(QEMUFile *f, void *pv, size_t size,
342 const VMStateField *field)
343
344{
345 if (qemu_get_byte(f) == VMS_NULLPTR_MARKER) {
346 return 0;
347 }
348 error_report("vmstate: get_nullptr expected VMS_NULLPTR_MARKER");
349 return -EINVAL;
350}
351
352static int put_nullptr(QEMUFile *f, void *pv, size_t size,
353 const VMStateField *field, JSONWriter *vmdesc)
354
355{
356 if (pv == NULL) {
357 qemu_put_byte(f, VMS_NULLPTR_MARKER);
358 return 0;
359 }
360 error_report("vmstate: put_nullptr must be called with pv == NULL");
361 return -EINVAL;
362}
363
364const VMStateInfo vmstate_info_nullptr = {
365 .name = "nullptr",
366 .get = get_nullptr,
367 .put = put_nullptr,
368};
369
370
371
372
373static int get_uint64_equal(QEMUFile *f, void *pv, size_t size,
374 const VMStateField *field)
375{
376 uint64_t *v = pv;
377 uint64_t v2;
378 qemu_get_be64s(f, &v2);
379
380 if (*v == v2) {
381 return 0;
382 }
383 error_report("%" PRIx64 " != %" PRIx64, *v, v2);
384 if (field->err_hint) {
385 error_printf("%s\n", field->err_hint);
386 }
387 return -EINVAL;
388}
389
390const VMStateInfo vmstate_info_uint64_equal = {
391 .name = "int64 equal",
392 .get = get_uint64_equal,
393 .put = put_uint64,
394};
395
396
397
398
399static int get_uint8_equal(QEMUFile *f, void *pv, size_t size,
400 const VMStateField *field)
401{
402 uint8_t *v = pv;
403 uint8_t v2;
404 qemu_get_8s(f, &v2);
405
406 if (*v == v2) {
407 return 0;
408 }
409 error_report("%x != %x", *v, v2);
410 if (field->err_hint) {
411 error_printf("%s\n", field->err_hint);
412 }
413 return -EINVAL;
414}
415
416const VMStateInfo vmstate_info_uint8_equal = {
417 .name = "uint8 equal",
418 .get = get_uint8_equal,
419 .put = put_uint8,
420};
421
422
423
424
425static int get_uint16_equal(QEMUFile *f, void *pv, size_t size,
426 const VMStateField *field)
427{
428 uint16_t *v = pv;
429 uint16_t v2;
430 qemu_get_be16s(f, &v2);
431
432 if (*v == v2) {
433 return 0;
434 }
435 error_report("%x != %x", *v, v2);
436 if (field->err_hint) {
437 error_printf("%s\n", field->err_hint);
438 }
439 return -EINVAL;
440}
441
442const VMStateInfo vmstate_info_uint16_equal = {
443 .name = "uint16 equal",
444 .get = get_uint16_equal,
445 .put = put_uint16,
446};
447
448
449
450static int get_cpudouble(QEMUFile *f, void *pv, size_t size,
451 const VMStateField *field)
452{
453 CPU_DoubleU *v = pv;
454 qemu_get_be32s(f, &v->l.upper);
455 qemu_get_be32s(f, &v->l.lower);
456 return 0;
457}
458
459static int put_cpudouble(QEMUFile *f, void *pv, size_t size,
460 const VMStateField *field, JSONWriter *vmdesc)
461{
462 CPU_DoubleU *v = pv;
463 qemu_put_be32s(f, &v->l.upper);
464 qemu_put_be32s(f, &v->l.lower);
465 return 0;
466}
467
468const VMStateInfo vmstate_info_cpudouble = {
469 .name = "CPU_Double_U",
470 .get = get_cpudouble,
471 .put = put_cpudouble,
472};
473
474
475
476static int get_buffer(QEMUFile *f, void *pv, size_t size,
477 const VMStateField *field)
478{
479 uint8_t *v = pv;
480 qemu_get_buffer(f, v, size);
481 return 0;
482}
483
484static int put_buffer(QEMUFile *f, void *pv, size_t size,
485 const VMStateField *field, JSONWriter *vmdesc)
486{
487 uint8_t *v = pv;
488 qemu_put_buffer(f, v, size);
489 return 0;
490}
491
492const VMStateInfo vmstate_info_buffer = {
493 .name = "buffer",
494 .get = get_buffer,
495 .put = put_buffer,
496};
497
498
499
500
501static int get_unused_buffer(QEMUFile *f, void *pv, size_t size,
502 const VMStateField *field)
503{
504 uint8_t buf[1024];
505 int block_len;
506
507 while (size > 0) {
508 block_len = MIN(sizeof(buf), size);
509 size -= block_len;
510 qemu_get_buffer(f, buf, block_len);
511 }
512 return 0;
513}
514
515static int put_unused_buffer(QEMUFile *f, void *pv, size_t size,
516 const VMStateField *field, JSONWriter *vmdesc)
517{
518 static const uint8_t buf[1024];
519 int block_len;
520
521 while (size > 0) {
522 block_len = MIN(sizeof(buf), size);
523 size -= block_len;
524 qemu_put_buffer(f, buf, block_len);
525 }
526
527 return 0;
528}
529
530const VMStateInfo vmstate_info_unused_buffer = {
531 .name = "unused_buffer",
532 .get = get_unused_buffer,
533 .put = put_unused_buffer,
534};
535
536
537
538
539
540
541
542static int get_tmp(QEMUFile *f, void *pv, size_t size,
543 const VMStateField *field)
544{
545 int ret;
546 const VMStateDescription *vmsd = field->vmsd;
547 int version_id = field->version_id;
548 void *tmp = g_malloc(size);
549
550
551 *(void **)tmp = pv;
552 ret = vmstate_load_state(f, vmsd, tmp, version_id);
553 g_free(tmp);
554 return ret;
555}
556
557static int put_tmp(QEMUFile *f, void *pv, size_t size,
558 const VMStateField *field, JSONWriter *vmdesc)
559{
560 const VMStateDescription *vmsd = field->vmsd;
561 void *tmp = g_malloc(size);
562 int ret;
563
564
565 *(void **)tmp = pv;
566 ret = vmstate_save_state(f, vmsd, tmp, vmdesc);
567 g_free(tmp);
568
569 return ret;
570}
571
572const VMStateInfo vmstate_info_tmp = {
573 .name = "tmp",
574 .get = get_tmp,
575 .put = put_tmp,
576};
577
578
579
580
581
582
583
584#define BITS_TO_U64S(nr) DIV_ROUND_UP(nr, 64)
585static int get_bitmap(QEMUFile *f, void *pv, size_t size,
586 const VMStateField *field)
587{
588 unsigned long *bmp = pv;
589 int i, idx = 0;
590 for (i = 0; i < BITS_TO_U64S(size); i++) {
591 uint64_t w = qemu_get_be64(f);
592 bmp[idx++] = w;
593 if (sizeof(unsigned long) == 4 && idx < BITS_TO_LONGS(size)) {
594 bmp[idx++] = w >> 32;
595 }
596 }
597 return 0;
598}
599
600static int put_bitmap(QEMUFile *f, void *pv, size_t size,
601 const VMStateField *field, JSONWriter *vmdesc)
602{
603 unsigned long *bmp = pv;
604 int i, idx = 0;
605 for (i = 0; i < BITS_TO_U64S(size); i++) {
606 uint64_t w = bmp[idx++];
607 if (sizeof(unsigned long) == 4 && idx < BITS_TO_LONGS(size)) {
608 w |= ((uint64_t)bmp[idx++]) << 32;
609 }
610 qemu_put_be64(f, w);
611 }
612
613 return 0;
614}
615
616const VMStateInfo vmstate_info_bitmap = {
617 .name = "bitmap",
618 .get = get_bitmap,
619 .put = put_bitmap,
620};
621
622
623
624
625static int get_qtailq(QEMUFile *f, void *pv, size_t unused_size,
626 const VMStateField *field)
627{
628 int ret = 0;
629 const VMStateDescription *vmsd = field->vmsd;
630
631 size_t size = field->size;
632
633 size_t entry_offset = field->start;
634 int version_id = field->version_id;
635 void *elm;
636
637 trace_get_qtailq(vmsd->name, version_id);
638 if (version_id > vmsd->version_id) {
639 error_report("%s %s", vmsd->name, "too new");
640 trace_get_qtailq_end(vmsd->name, "too new", -EINVAL);
641
642 return -EINVAL;
643 }
644 if (version_id < vmsd->minimum_version_id) {
645 error_report("%s %s", vmsd->name, "too old");
646 trace_get_qtailq_end(vmsd->name, "too old", -EINVAL);
647 return -EINVAL;
648 }
649
650 while (qemu_get_byte(f)) {
651 elm = g_malloc(size);
652 ret = vmstate_load_state(f, vmsd, elm, version_id);
653 if (ret) {
654 return ret;
655 }
656 QTAILQ_RAW_INSERT_TAIL(pv, elm, entry_offset);
657 }
658
659 trace_get_qtailq_end(vmsd->name, "end", ret);
660 return ret;
661}
662
663
664static int put_qtailq(QEMUFile *f, void *pv, size_t unused_size,
665 const VMStateField *field, JSONWriter *vmdesc)
666{
667 const VMStateDescription *vmsd = field->vmsd;
668
669 size_t entry_offset = field->start;
670 void *elm;
671 int ret;
672
673 trace_put_qtailq(vmsd->name, vmsd->version_id);
674
675 QTAILQ_RAW_FOREACH(elm, pv, entry_offset) {
676 qemu_put_byte(f, true);
677 ret = vmstate_save_state(f, vmsd, elm, vmdesc);
678 if (ret) {
679 return ret;
680 }
681 }
682 qemu_put_byte(f, false);
683
684 trace_put_qtailq_end(vmsd->name, "end");
685
686 return 0;
687}
688const VMStateInfo vmstate_info_qtailq = {
689 .name = "qtailq",
690 .get = get_qtailq,
691 .put = put_qtailq,
692};
693
694struct put_gtree_data {
695 QEMUFile *f;
696 const VMStateDescription *key_vmsd;
697 const VMStateDescription *val_vmsd;
698 JSONWriter *vmdesc;
699 int ret;
700};
701
702static gboolean put_gtree_elem(gpointer key, gpointer value, gpointer data)
703{
704 struct put_gtree_data *capsule = (struct put_gtree_data *)data;
705 QEMUFile *f = capsule->f;
706 int ret;
707
708 qemu_put_byte(f, true);
709
710
711 if (!capsule->key_vmsd) {
712 qemu_put_be64(f, (uint64_t)(uintptr_t)(key));
713 } else {
714 ret = vmstate_save_state(f, capsule->key_vmsd, key, capsule->vmdesc);
715 if (ret) {
716 capsule->ret = ret;
717 return true;
718 }
719 }
720
721
722 ret = vmstate_save_state(f, capsule->val_vmsd, value, capsule->vmdesc);
723 if (ret) {
724 capsule->ret = ret;
725 return true;
726 }
727 return false;
728}
729
730static int put_gtree(QEMUFile *f, void *pv, size_t unused_size,
731 const VMStateField *field, JSONWriter *vmdesc)
732{
733 bool direct_key = (!field->start);
734 const VMStateDescription *key_vmsd = direct_key ? NULL : &field->vmsd[1];
735 const VMStateDescription *val_vmsd = &field->vmsd[0];
736 const char *key_vmsd_name = direct_key ? "direct" : key_vmsd->name;
737 struct put_gtree_data capsule = {
738 .f = f,
739 .key_vmsd = key_vmsd,
740 .val_vmsd = val_vmsd,
741 .vmdesc = vmdesc,
742 .ret = 0};
743 GTree **pval = pv;
744 GTree *tree = *pval;
745 uint32_t nnodes = g_tree_nnodes(tree);
746 int ret;
747
748 trace_put_gtree(field->name, key_vmsd_name, val_vmsd->name, nnodes);
749 qemu_put_be32(f, nnodes);
750 g_tree_foreach(tree, put_gtree_elem, (gpointer)&capsule);
751 qemu_put_byte(f, false);
752 ret = capsule.ret;
753 if (ret) {
754 error_report("%s : failed to save gtree (%d)", field->name, ret);
755 }
756 trace_put_gtree_end(field->name, key_vmsd_name, val_vmsd->name, ret);
757 return ret;
758}
759
760static int get_gtree(QEMUFile *f, void *pv, size_t unused_size,
761 const VMStateField *field)
762{
763 bool direct_key = (!field->start);
764 const VMStateDescription *key_vmsd = direct_key ? NULL : &field->vmsd[1];
765 const VMStateDescription *val_vmsd = &field->vmsd[0];
766 const char *key_vmsd_name = direct_key ? "direct" : key_vmsd->name;
767 int version_id = field->version_id;
768 size_t key_size = field->start;
769 size_t val_size = field->size;
770 int nnodes, count = 0;
771 GTree **pval = pv;
772 GTree *tree = *pval;
773 void *key, *val;
774 int ret = 0;
775
776
777 if (!direct_key && version_id > key_vmsd->version_id) {
778 error_report("%s %s", key_vmsd->name, "too new");
779 return -EINVAL;
780 }
781 if (!direct_key && version_id < key_vmsd->minimum_version_id) {
782 error_report("%s %s", key_vmsd->name, "too old");
783 return -EINVAL;
784 }
785 if (version_id > val_vmsd->version_id) {
786 error_report("%s %s", val_vmsd->name, "too new");
787 return -EINVAL;
788 }
789 if (version_id < val_vmsd->minimum_version_id) {
790 error_report("%s %s", val_vmsd->name, "too old");
791 return -EINVAL;
792 }
793
794 nnodes = qemu_get_be32(f);
795 trace_get_gtree(field->name, key_vmsd_name, val_vmsd->name, nnodes);
796
797 while (qemu_get_byte(f)) {
798 if ((++count) > nnodes) {
799 ret = -EINVAL;
800 break;
801 }
802 if (direct_key) {
803 key = (void *)(uintptr_t)qemu_get_be64(f);
804 } else {
805 key = g_malloc0(key_size);
806 ret = vmstate_load_state(f, key_vmsd, key, version_id);
807 if (ret) {
808 error_report("%s : failed to load %s (%d)",
809 field->name, key_vmsd->name, ret);
810 goto key_error;
811 }
812 }
813 val = g_malloc0(val_size);
814 ret = vmstate_load_state(f, val_vmsd, val, version_id);
815 if (ret) {
816 error_report("%s : failed to load %s (%d)",
817 field->name, val_vmsd->name, ret);
818 goto val_error;
819 }
820 g_tree_insert(tree, key, val);
821 }
822 if (count != nnodes) {
823 error_report("%s inconsistent stream when loading the gtree",
824 field->name);
825 return -EINVAL;
826 }
827 trace_get_gtree_end(field->name, key_vmsd_name, val_vmsd->name, ret);
828 return ret;
829val_error:
830 g_free(val);
831key_error:
832 if (!direct_key) {
833 g_free(key);
834 }
835 trace_get_gtree_end(field->name, key_vmsd_name, val_vmsd->name, ret);
836 return ret;
837}
838
839
840const VMStateInfo vmstate_info_gtree = {
841 .name = "gtree",
842 .get = get_gtree,
843 .put = put_gtree,
844};
845
846static int put_qlist(QEMUFile *f, void *pv, size_t unused_size,
847 const VMStateField *field, JSONWriter *vmdesc)
848{
849 const VMStateDescription *vmsd = field->vmsd;
850
851 size_t entry_offset = field->start;
852 void *elm;
853 int ret;
854
855 trace_put_qlist(field->name, vmsd->name, vmsd->version_id);
856 QLIST_RAW_FOREACH(elm, pv, entry_offset) {
857 qemu_put_byte(f, true);
858 ret = vmstate_save_state(f, vmsd, elm, vmdesc);
859 if (ret) {
860 error_report("%s: failed to save %s (%d)", field->name,
861 vmsd->name, ret);
862 return ret;
863 }
864 }
865 qemu_put_byte(f, false);
866 trace_put_qlist_end(field->name, vmsd->name);
867
868 return 0;
869}
870
871static int get_qlist(QEMUFile *f, void *pv, size_t unused_size,
872 const VMStateField *field)
873{
874 int ret = 0;
875 const VMStateDescription *vmsd = field->vmsd;
876
877 size_t size = field->size;
878
879 size_t entry_offset = field->start;
880 int version_id = field->version_id;
881 void *elm, *prev = NULL;
882
883 trace_get_qlist(field->name, vmsd->name, vmsd->version_id);
884 if (version_id > vmsd->version_id) {
885 error_report("%s %s", vmsd->name, "too new");
886 return -EINVAL;
887 }
888 if (version_id < vmsd->minimum_version_id) {
889 error_report("%s %s", vmsd->name, "too old");
890 return -EINVAL;
891 }
892
893 while (qemu_get_byte(f)) {
894 elm = g_malloc(size);
895 ret = vmstate_load_state(f, vmsd, elm, version_id);
896 if (ret) {
897 error_report("%s: failed to load %s (%d)", field->name,
898 vmsd->name, ret);
899 g_free(elm);
900 return ret;
901 }
902 if (!prev) {
903 QLIST_RAW_INSERT_HEAD(pv, elm, entry_offset);
904 } else {
905 QLIST_RAW_INSERT_AFTER(pv, prev, elm, entry_offset);
906 }
907 prev = elm;
908 }
909 trace_get_qlist_end(field->name, vmsd->name);
910
911 return ret;
912}
913
914const VMStateInfo vmstate_info_qlist = {
915 .name = "qlist",
916 .get = get_qlist,
917 .put = put_qlist,
918};
919