master
c 970 lines 30.1 KB
Raw
1 /*
2 * VMState interpreter
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 "migration.h"
15 #include "migration/vmstate.h"
16 #include "savevm.h"
17 #include "qapi/error.h"
18 #include "qobject/json-writer.h"
19 #include "qemu-file.h"
20 #include "qemu/bitops.h"
21 #include "qemu/error-report.h"
22 #include "trace.h"
23
24 static bool vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
25 void *opaque, JSONWriter *vmdesc,
26 Error **errp);
27 static bool vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
28 void *opaque, Error **errp);
29 static bool vmstate_save_vmsd_v(QEMUFile *f, const VMStateDescription *vmsd,
30 void *opaque, JSONWriter *vmdesc,
31 int version_id, Error **errp);
32
33 /* Whether this field should exist for either save or load the VM? */
34 static bool
35 vmstate_field_exists(const VMStateDescription *vmsd, const VMStateField *field,
36 void *opaque, int version_id)
37 {
38 bool result;
39
40 if (field->field_exists) {
41 /* If there's the function checker, that's the solo truth */
42 result = field->field_exists(opaque, version_id);
43 trace_vmstate_field_exists(vmsd->name, field->name, field->version_id,
44 version_id, result);
45 } else {
46 /*
47 * Otherwise, we only save/load if field version is same or older.
48 * For example, when loading from an old binary with old version,
49 * we ignore new fields with newer version_ids.
50 */
51 result = field->version_id <= version_id;
52 }
53
54 return result;
55 }
56
57 /*
58 * Create a ptr marker field when there's a NULL pointer detected in the
59 * array of a VMS_ARRAY_OF_POINTER VMSD field. It's needed because we
60 * can't dereference the NULL pointer.
61 */
62 static void
63 vmsd_init_ptr_marker_field(VMStateField *fake, const VMStateField *field)
64 {
65 /* It can only happen on an array of pointers! */
66 assert(field->flags & VMS_ARRAY_OF_POINTER);
67
68 /* See vmstate_info_ptr_marker - 1 byte represents ptr status */
69 *fake = (VMStateField) {
70 .name = field->name,
71 .version_id = field->version_id,
72 /* Marker always exists, no field_exists callback needed */
73 .field_exists = NULL,
74 .size = 1,
75 .info = &vmstate_info_ptr_marker,
76 .flags = VMS_SINGLE,
77 /* All other fields stay zero-initialised */
78 };
79 }
80
81 static uint64_t vmstate_read_from_offset(const VMStateStructMember *member,
82 void *opaque)
83 {
84 uint8_t *ptr = (uint8_t *)opaque + member->offset;
85
86 switch (member->size) {
87 case 1: {
88 uint8_t v;
89 memcpy(&v, ptr, 1);
90 return v;
91 }
92 case 2: {
93 uint16_t v;
94 memcpy(&v, ptr, 2);
95 return v;
96 }
97 case 4: {
98 uint32_t v;
99 memcpy(&v, ptr, 4);
100 return v;
101 }
102 case 8: {
103 uint64_t v;
104 memcpy(&v, ptr, 8);
105 return v;
106 }
107 }
108 g_assert_not_reached();
109 }
110
111 static uint64_t vmstate_n_elems(void *opaque, const VMStateField *field)
112 {
113 uint64_t n_elems;
114
115 if (field->flags & VMS_ARRAY) {
116 n_elems = field->num;
117 } else if (field->flags & VMS_VARRAY) {
118 n_elems = vmstate_read_from_offset(&field->num_indirect, opaque);
119 } else if (field->flags & VMS_MUST_EXIST && field->flags & VMS_NO_STATE) {
120 n_elems = 0;
121 } else {
122 n_elems = 1;
123 }
124
125 trace_vmstate_n_elems(field->name, n_elems);
126 return n_elems;
127 }
128
129 static bool vmstate_size(void *opaque, const VMStateField *field,
130 uint64_t *sz, Error **errp)
131 {
132 uint64_t size;
133
134 *sz = 0;
135
136 if (field->flags & VMS_VBUFFER) {
137 size = vmstate_read_from_offset(&field->size_indirect, opaque);
138 if ((field->flags & VMS_MULTIPLY) &&
139 umul64_overflow(size, field->size, &size)) {
140 error_setg(errp, "%s: VMState field '%s' multiply overflow",
141 __func__, field->name);
142 return false;
143 }
144 } else if (field->flags & VMS_ARRAY_OF_POINTER) {
145 /*
146 * For an array of pointer, the each element is always size of a
147 * host pointer.
148 */
149 size = sizeof(void *);
150 } else {
151 size = field->size;
152 }
153
154 *sz = size;
155 return true;
156 }
157
158 static bool vmstate_handle_alloc(void *ptr, const VMStateField *field,
159 uint64_t n, uint64_t size, Error **errp)
160 {
161 void *p;
162
163 if (field->flags & VMS_POINTER && field->flags & VMS_ALLOC) {
164 if (size && n) {
165 if (umul64_overflow(size, n, &size)) {
166 error_setg(errp, "%s: field '%s' multiply overflow",
167 __func__, field->name);
168 return false;
169 }
170 p = g_try_malloc(size);
171 if (!p) {
172 error_setg(errp, "%s: Could not allocate memory for field '%s'",
173 __func__, field->name);
174 return false;
175 }
176 *(void **)ptr = p;
177 }
178 }
179 return true;
180 }
181
182 static bool vmstate_ptr_marker_load(QEMUFile *f, bool *load_field,
183 Error **errp)
184 {
185 int byte = qemu_get_byte(f);
186
187 if (byte == VMS_MARKER_PTR_NULL) {
188 /* When it's a null ptr marker, do not continue the load */
189 *load_field = false;
190 return true;
191 }
192
193 if (byte == VMS_MARKER_PTR_VALID) {
194 /* We need to load the field right after the marker */
195 *load_field = true;
196 return true;
197 }
198
199 error_setg(errp, "Unexpected ptr marker: %d", byte);
200 return false;
201 }
202
203 static bool vmstate_pre_load(const VMStateDescription *vmsd, void *opaque,
204 Error **errp)
205 {
206 ERRP_GUARD();
207
208 if (vmsd->pre_load_errp) {
209 if (!vmsd->pre_load_errp(opaque, errp)) {
210 error_prepend(errp, "pre load hook failed for: '%s', "
211 "version_id: %d, minimum version_id: %d: ",
212 vmsd->name, vmsd->version_id,
213 vmsd->minimum_version_id);
214 return false;
215 }
216 } else if (vmsd->pre_load) {
217 int ret = vmsd->pre_load(opaque);
218 if (ret) {
219 error_setg(errp, "pre load hook failed for: '%s', "
220 "version_id: %d, minimum version_id: %d, ret: %d",
221 vmsd->name, vmsd->version_id, vmsd->minimum_version_id,
222 ret);
223 return false;
224 }
225 }
226
227 return true;
228 }
229
230 static bool vmstate_load_field(QEMUFile *f, void *pv, size_t size,
231 const VMStateField *field, Error **errp)
232 {
233 if (field->flags & VMS_STRUCT) {
234 return vmstate_load_vmsd(f, field->vmsd, pv, field->vmsd->version_id,
235 errp);
236 } else if (field->flags & VMS_VSTRUCT) {
237 return vmstate_load_vmsd(f, field->vmsd, pv, field->struct_version_id,
238 errp);
239 } else if (field->info->load) {
240 return field->info->load(f, pv, size, field, errp);
241 }
242
243 if (field->info->get(f, pv, size, field) < 0) {
244 error_setg(errp,
245 "Failed to load element of type %s for %s",
246 field->info->name, field->name);
247 return false;
248 }
249
250 return true;
251 }
252
253 static bool vmstate_post_load(const VMStateDescription *vmsd,
254 void *opaque, int version_id, Error **errp)
255 {
256 ERRP_GUARD();
257
258 if (vmsd->post_load_errp) {
259 if (!vmsd->post_load_errp(opaque, version_id, errp)) {
260 error_prepend(errp, "post load hook failed for: %s, version_id: "
261 "%d, minimum_version: %d: ", vmsd->name,
262 vmsd->version_id, vmsd->minimum_version_id);
263 return false;
264 }
265 } else if (vmsd->post_load) {
266 int ret = vmsd->post_load(opaque, version_id);
267 if (ret < 0) {
268 error_setg(errp,
269 "post load hook failed for: %s, version_id: %d, "
270 "minimum_version: %d, ret: %d",
271 vmsd->name, vmsd->version_id, vmsd->minimum_version_id,
272 ret);
273 return false;
274 }
275 }
276
277 return true;
278 }
279
280 /*
281 * Try to prepare loading the next element, the object pointer to be put
282 * into @next_elem. When @next_elem is NULL, it means we should skip
283 * loading this element.
284 *
285 * Returns false for errors, in which case *errp will be set, migration
286 * must be aborted.
287 */
288 static bool vmstate_load_next(QEMUFile *f, const VMStateField *field,
289 void *first_elem, void **next_elem,
290 int size, int i, Error **errp)
291 {
292 bool auto_alloc = field->flags & VMS_ARRAY_OF_POINTER_AUTO_ALLOC;
293 void *ptr = first_elem + size * i, **pptr;
294 bool load_field;
295
296 if (!(field->flags & VMS_ARRAY_OF_POINTER)) {
297 /* Simplest case, no pointer involved */
298 *next_elem = ptr;
299 return true;
300 }
301
302 /*
303 * We're loading an array of pointers, switch to use pptr to make it
304 * easier to read later
305 */
306 pptr = (void **)ptr;
307
308 /*
309 * If auto_alloc is on, making sure the user provided an array of NULL
310 * pointers to start with
311 */
312 assert(!auto_alloc || *pptr == NULL);
313
314 /*
315 * When pointer is null, we must expect a ptr marker first. Use cases:
316 *
317 * (1) _AUTO_ALLOC implies a ptr marker will always exist, or,
318 *
319 * (2) the element on destination is NULL, which expects the src to send a
320 * NULL-only marker.
321 *
322 * Here, checking against a NULL pointer will work for both.
323 */
324 if (!*pptr) {
325 if (!vmstate_ptr_marker_load(f, &load_field, errp)) {
326 trace_vmstate_load_field_error(field->name, -EINVAL);
327 return false;
328 }
329
330 /*
331 * If loading is needed, do pre-allocation first (otherwise keeping
332 * *pptr==NULL to imply a skip below)
333 */
334 if (load_field) {
335 /* Only applies when auto_alloc=on on the field */
336 assert(auto_alloc);
337 /*
338 * NOTE: do not use vmstate_size() here, because we need the
339 * object size, not entry size of the array.
340 */
341 *pptr = g_malloc0(field->size);
342 }
343 }
344
345 /* Move the cursor to the next element for loading */
346 *next_elem = *pptr;
347 return true;
348 }
349
350 bool vmstate_load_vmsd(QEMUFile *f, const VMStateDescription *vmsd,
351 void *opaque, int version_id, Error **errp)
352 {
353 ERRP_GUARD();
354 const VMStateField *field = vmsd->fields;
355
356 trace_vmstate_load_state(vmsd->name, version_id);
357
358 if (version_id > vmsd->version_id) {
359 error_setg(errp, "%s: incoming version_id %d is too new "
360 "for local version_id %d",
361 vmsd->name, version_id, vmsd->version_id);
362 trace_vmstate_load_state_fail(vmsd->name, "too new");
363 return false;
364 }
365
366 if (version_id < vmsd->minimum_version_id) {
367 error_setg(errp, "%s: incoming version_id %d is too old "
368 "for local minimum version_id %d",
369 vmsd->name, version_id, vmsd->minimum_version_id);
370 trace_vmstate_load_state_fail(vmsd->name, "too old");
371 return false;
372 }
373
374 if (!vmstate_pre_load(vmsd, opaque, errp)) {
375 return false;
376 }
377
378 while (field->name) {
379 bool exists = vmstate_field_exists(vmsd, field, opaque, version_id);
380
381 trace_vmstate_load_state_field(vmsd->name, field->name, exists);
382
383 if (exists) {
384 void *first_elem = opaque + field->offset;
385 int i;
386 uint64_t n_elems = vmstate_n_elems(opaque, field);
387 uint64_t size;
388
389 if (!vmstate_size(opaque, field, &size, errp)) {
390 return false;
391 }
392
393 if (!vmstate_handle_alloc(first_elem, field, n_elems, size, errp)) {
394 return false;
395 }
396 if (field->flags & VMS_POINTER) {
397 first_elem = *(void **)first_elem;
398 assert(first_elem || !n_elems || !size);
399 }
400
401 for (i = 0; i < n_elems; i++) {
402 void *curr_elem;
403 bool ok;
404
405 ok = vmstate_load_next(f, field, first_elem, &curr_elem,
406 size, i, errp);
407 if (!ok) {
408 return false;
409 }
410
411 if (!curr_elem) {
412 /* Implies a skip */
413 continue;
414 }
415
416 ok = vmstate_load_field(f, curr_elem, size, field, errp);
417
418 if (ok) {
419 int ret = qemu_file_get_error(f);
420 if (ret < 0) {
421 error_setg(errp,
422 "Failed to load %s state: stream error: %d",
423 vmsd->name, ret);
424 trace_vmstate_load_field_error(field->name, ret);
425 return false;
426 }
427 } else {
428 qemu_file_set_error(f, -EINVAL);
429 trace_vmstate_load_field_error(field->name, -EINVAL);
430 return false;
431 }
432 }
433 } else if (field->flags & VMS_MUST_EXIST) {
434 error_setg(errp, "Input validation failed: %s/%s version_id: %d",
435 vmsd->name, field->name, vmsd->version_id);
436 return false;
437 }
438 field++;
439 }
440 assert(field->flags == VMS_END);
441
442 if (!vmstate_subsection_load(f, vmsd, opaque, errp)) {
443 qemu_file_set_error(f, -EINVAL);
444 return false;
445 }
446
447 if (!vmstate_post_load(vmsd, opaque, version_id, errp)) {
448 trace_vmstate_load_state_fail(vmsd->name, "post-load");
449 return false;
450 }
451
452 trace_vmstate_load_state_success(vmsd->name);
453 return true;
454 }
455
456 static int vmfield_name_num(const VMStateField *start,
457 const VMStateField *search)
458 {
459 const VMStateField *field;
460 int found = 0;
461
462 for (field = start; field->name; field++) {
463 if (!strcmp(field->name, search->name)) {
464 if (field == search) {
465 return found;
466 }
467 found++;
468 }
469 }
470
471 return -1;
472 }
473
474 static bool vmfield_name_is_unique(const VMStateField *start,
475 const VMStateField *search)
476 {
477 const VMStateField *field;
478 int found = 0;
479
480 for (field = start; field->name; field++) {
481 if (!strcmp(field->name, search->name)) {
482 found++;
483 /* name found more than once, so it's not unique */
484 if (found > 1) {
485 return false;
486 }
487 }
488 }
489
490 return true;
491 }
492
493 static const char *vmfield_get_type_name(const VMStateField *field)
494 {
495 const char *type = "unknown";
496
497 if (field->flags & VMS_STRUCT) {
498 type = "struct";
499 } else if (field->flags & VMS_VSTRUCT) {
500 type = "vstruct";
501 } else if (field->info->name) {
502 type = field->info->name;
503 }
504
505 return type;
506 }
507
508 static bool vmsd_can_compress(const VMStateField *field)
509 {
510 if (field->field_exists) {
511 /* Dynamically existing fields mess up compression */
512 return false;
513 }
514
515 if (field->flags & VMS_ARRAY_OF_POINTER_AUTO_ALLOC) {
516 /*
517 * This may involve two VMSD fields to be saved, one for the
518 * marker to show if the pointer is NULL, followed by the real
519 * vmstate object. To make it simple at least for now, skip
520 * compression for this one.
521 */
522 return false;
523 }
524
525 if (field->flags & VMS_STRUCT) {
526 const VMStateField *sfield = field->vmsd->fields;
527 while (sfield->name) {
528 if (!vmsd_can_compress(sfield)) {
529 /* Child elements can't compress, so can't we */
530 return false;
531 }
532 sfield++;
533 }
534
535 if (field->vmsd->subsections) {
536 /* Subsections may come and go, better don't compress */
537 return false;
538 }
539 }
540
541 return true;
542 }
543
544 static void vmsd_desc_field_start(const VMStateDescription *vmsd,
545 JSONWriter *vmdesc,
546 const VMStateField *field, int i, int max)
547 {
548 char *name, *old_name;
549 bool is_array = max > 1;
550 bool can_compress = vmsd_can_compress(field);
551
552 if (!vmdesc) {
553 return;
554 }
555
556 name = g_strdup(field->name);
557
558 /* Field name is not unique, need to make it unique */
559 if (!vmfield_name_is_unique(vmsd->fields, field)) {
560 int num = vmfield_name_num(vmsd->fields, field);
561 old_name = name;
562 name = g_strdup_printf("%s[%d]", name, num);
563 g_free(old_name);
564 }
565
566 json_writer_start_object(vmdesc, NULL);
567 json_writer_str(vmdesc, "name", name);
568 if (is_array) {
569 if (can_compress) {
570 json_writer_int64(vmdesc, "array_len", max);
571 } else {
572 json_writer_int64(vmdesc, "index", i);
573 }
574 }
575 json_writer_str(vmdesc, "type", vmfield_get_type_name(field));
576
577 if (field->flags & VMS_STRUCT) {
578 json_writer_start_object(vmdesc, "struct");
579 }
580
581 g_free(name);
582 }
583
584 static void vmsd_desc_field_end(const VMStateDescription *vmsd,
585 JSONWriter *vmdesc,
586 const VMStateField *field, size_t size)
587 {
588 if (!vmdesc) {
589 return;
590 }
591
592 if (field->flags & VMS_STRUCT) {
593 /* We printed a struct in between, close its child object */
594 json_writer_end_object(vmdesc);
595 }
596
597 json_writer_int64(vmdesc, "size", size);
598 json_writer_end_object(vmdesc);
599 }
600
601
602 bool vmstate_section_needed(const VMStateDescription *vmsd, void *opaque)
603 {
604 if (vmsd->needed && !vmsd->needed(opaque)) {
605 /* optional section not needed */
606 return false;
607 }
608 return true;
609 }
610
611 static bool vmstate_pre_save(const VMStateDescription *vmsd, void *opaque,
612 Error **errp)
613 {
614 ERRP_GUARD();
615
616 if (vmsd->pre_save_errp) {
617 if (!vmsd->pre_save_errp(opaque, errp)) {
618 error_prepend(errp, "pre-save for %s failed: ", vmsd->name);
619 return false;
620 }
621 } else if (vmsd->pre_save) {
622 if (vmsd->pre_save(opaque) < 0) {
623 error_setg(errp, "pre-save failed: %s", vmsd->name);
624 return false;
625 }
626 }
627
628 return true;
629 }
630
631 static bool vmstate_save_field(QEMUFile *f, void *pv, size_t size,
632 const VMStateField *field,
633 JSONWriter *vmdesc, Error **errp)
634 {
635 if (field->flags & VMS_STRUCT) {
636 return vmstate_save_vmsd(f, field->vmsd, pv, vmdesc, errp);
637 } else if (field->flags & VMS_VSTRUCT) {
638 return vmstate_save_vmsd_v(f, field->vmsd, pv, vmdesc,
639 field->struct_version_id, errp);
640 } else if (field->info->save) {
641 return field->info->save(f, pv, size, field, vmdesc, errp);
642 }
643
644 if (field->info->put(f, pv, size, field, vmdesc) < 0) {
645 error_setg(errp, "put failed");
646 return false;
647 }
648
649 return true;
650 }
651
652 /*
653 * Save a whole VMSD field, including its JSON blob separately when @vmdesc
654 * is specified.
655 */
656 static inline bool
657 vmstate_save_field_with_vmdesc(QEMUFile *f, void *pv, size_t size,
658 const VMStateDescription *vmsd,
659 const VMStateField *field, JSONWriter *vmdesc,
660 int i, int max, Error **errp)
661 {
662 uint64_t old_offset, written_bytes;
663 bool ok;
664
665 vmsd_desc_field_start(vmsd, vmdesc, field, i, max);
666
667 old_offset = qemu_file_transferred(f);
668 ok = vmstate_save_field(f, pv, size, field, vmdesc, errp);
669 written_bytes = qemu_file_transferred(f) - old_offset;
670
671 vmsd_desc_field_end(vmsd, vmdesc, field, written_bytes);
672
673 if (!ok) {
674 error_prepend(errp, "Save of field %s/%s failed: ",
675 vmsd->name, field->name);
676 }
677
678 return ok;
679 }
680
681 static bool vmstate_save_vmsd_v(QEMUFile *f, const VMStateDescription *vmsd,
682 void *opaque, JSONWriter *vmdesc,
683 int version_id, Error **errp)
684 {
685 ERRP_GUARD();
686 bool ok = true;
687 const VMStateField *field = vmsd->fields;
688
689 trace_vmstate_save_state_top(vmsd->name);
690
691 if (!vmstate_pre_save(vmsd, opaque, errp)) {
692 trace_vmstate_save_state_pre_save_fail(vmsd->name);
693 return false;
694 }
695
696 trace_vmstate_save_state_pre_save_success(vmsd->name);
697
698 if (vmdesc) {
699 json_writer_str(vmdesc, "vmsd_name", vmsd->name);
700 json_writer_int64(vmdesc, "version", version_id);
701 json_writer_start_array(vmdesc, "fields");
702 }
703
704 while (field->name) {
705 if (vmstate_field_exists(vmsd, field, opaque, version_id)) {
706 void *first_elem = opaque + field->offset;
707 int i;
708 uint64_t n_elems = vmstate_n_elems(opaque, field);
709 uint64_t size;
710 JSONWriter *vmdesc_loop = vmdesc;
711 bool is_prev_null = false;
712
713 /*
714 * When this is enabled, it means we will always push a ptr
715 * marker first for each element saying if it's populated.
716 */
717 bool use_dynamic_array =
718 field->flags & VMS_ARRAY_OF_POINTER_AUTO_ALLOC;
719
720 if (!vmstate_size(opaque, field, &size, errp)) {
721 return false;
722 }
723
724 trace_vmstate_save_state_loop(vmsd->name, field->name, n_elems);
725 if (field->flags & VMS_POINTER) {
726 first_elem = *(void **)first_elem;
727 assert(first_elem || !n_elems || !size);
728 }
729
730 for (i = 0; i < n_elems; i++) {
731 void *curr_elem = first_elem + size * i;
732 const VMStateField *inner_field;
733 VMStateField marker_field;
734 /* maximum number of elements to compress in the JSON blob */
735 int max_elems = vmsd_can_compress(field) ? (n_elems - i) : 1;
736 bool use_marker_field, is_null = false;
737
738 if (field->flags & VMS_ARRAY_OF_POINTER) {
739 assert(curr_elem);
740 curr_elem = *(void **)curr_elem;
741 is_null = !curr_elem;
742 }
743
744 use_marker_field = use_dynamic_array || is_null;
745
746 if (use_marker_field) {
747 vmsd_init_ptr_marker_field(&marker_field, field);
748 inner_field = &marker_field;
749 } else {
750 inner_field = field;
751 }
752
753 /*
754 * This logic only matters when dumping VM Desc.
755 *
756 * Due to the fake nullptr handling above, if there's mixed
757 * null/non-null data, it doesn't make sense to emit a
758 * compressed array representation spanning the entire array
759 * because the field types will be different (e.g. struct
760 * vs. nullptr). Search ahead for the next null/non-null element
761 * and start a new compressed array if found.
762 */
763 if (vmdesc && max_elems > 1 &&
764 (field->flags & VMS_ARRAY_OF_POINTER) &&
765 is_null != is_prev_null) {
766
767 is_prev_null = is_null;
768 vmdesc_loop = vmdesc;
769
770 for (int j = i + 1; j < n_elems; j++) {
771 void *elem = *(void **)(first_elem + size * j);
772 bool elem_is_null = !elem;
773
774 if (is_null != elem_is_null) {
775 max_elems = j - i;
776 break;
777 }
778 }
779 }
780
781 ok = vmstate_save_field_with_vmdesc(f, curr_elem, size, vmsd,
782 inner_field, vmdesc_loop,
783 i, max_elems, errp);
784
785 if (!ok) {
786 goto out;
787 }
788
789 /*
790 * If we're using dynamic array and the element is
791 * populated, save the real object right after the marker.
792 */
793 if (use_dynamic_array && curr_elem) {
794 /*
795 * NOTE: do not use vmstate_size() here because we want
796 * to save the real VMSD object now.
797 */
798 ok = vmstate_save_field_with_vmdesc(f, curr_elem,
799 field->size, vmsd,
800 field, vmdesc_loop,
801 i, max_elems, errp);
802
803 if (!ok) {
804 goto out;
805 }
806 }
807
808 /* Compressed arrays only care about the first element */
809 if (vmdesc_loop && max_elems > 1) {
810 vmdesc_loop = NULL;
811 }
812 }
813 } else {
814 if (field->flags & VMS_MUST_EXIST) {
815 error_report("Output state validation failed: %s/%s",
816 vmsd->name, field->name);
817 assert(!(field->flags & VMS_MUST_EXIST));
818 }
819 }
820 field++;
821 }
822 assert(field->flags == VMS_END);
823
824 if (vmdesc) {
825 json_writer_end_array(vmdesc);
826 }
827
828 ok = vmstate_subsection_save(f, vmsd, opaque, vmdesc, errp);
829
830 out:
831 if (vmsd->post_save) {
832 vmsd->post_save(opaque);
833 }
834 return ok;
835 }
836
837 static const VMStateDescription *
838 vmstate_get_subsection(const VMStateDescription * const *sub,
839 const char *idstr)
840 {
841 if (sub) {
842 for (const VMStateDescription *s = *sub; s ; s = *++sub) {
843 if (strcmp(idstr, s->name) == 0) {
844 return s;
845 }
846 }
847 }
848 return NULL;
849 }
850
851 bool vmstate_save_vmsd(QEMUFile *f, const VMStateDescription *vmsd,
852 void *opaque, JSONWriter *vmdesc_id, Error **errp)
853 {
854 return vmstate_save_vmsd_v(f, vmsd, opaque, vmdesc_id, vmsd->version_id,
855 errp);
856 }
857
858 static bool vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
859 void *opaque, Error **errp)
860 {
861 ERRP_GUARD();
862 trace_vmstate_subsection_load(vmsd->name);
863
864 while (qemu_peek_byte(f, 0) == QEMU_VM_SUBSECTION) {
865 char idstr[256], *idstr_ret;
866 uint8_t version_id, len, size;
867 const VMStateDescription *sub_vmsd;
868
869 len = qemu_peek_byte(f, 1);
870 if (len < strlen(vmsd->name) + 1) {
871 /* subsection name has to be "section_name/a" */
872 trace_vmstate_subsection_load_bad(vmsd->name, "(short)", "");
873 return true;
874 }
875 size = qemu_peek_buffer(f, (uint8_t **)&idstr_ret, len, 2);
876 if (size != len) {
877 trace_vmstate_subsection_load_bad(vmsd->name, "(peek fail)", "");
878 return true;
879 }
880 memcpy(idstr, idstr_ret, size);
881 idstr[size] = 0;
882
883 if (strncmp(vmsd->name, idstr, strlen(vmsd->name)) != 0) {
884 trace_vmstate_subsection_load_bad(vmsd->name, idstr, "(prefix)");
885 /* it doesn't have a valid subsection name */
886 return true;
887 }
888 sub_vmsd = vmstate_get_subsection(vmsd->subsections, idstr);
889 if (sub_vmsd == NULL) {
890 trace_vmstate_subsection_load_bad(vmsd->name, idstr, "(lookup)");
891 error_setg(errp, "VM subsection '%s' in '%s' does not exist",
892 idstr, vmsd->name);
893 return false;
894 }
895 qemu_file_skip(f, 1); /* subsection */
896 qemu_file_skip(f, 1); /* len */
897 qemu_file_skip(f, len); /* idstr */
898 version_id = qemu_get_be32(f);
899
900 if (!vmstate_load_vmsd(f, sub_vmsd, opaque, version_id, errp)) {
901 trace_vmstate_subsection_load_bad(vmsd->name, idstr, "(child)");
902 error_prepend(errp,
903 "Loading VM subsection '%s' in '%s' failed: ",
904 idstr, vmsd->name);
905 return false;
906 }
907 }
908
909 trace_vmstate_subsection_load_good(vmsd->name);
910 return true;
911 }
912
913 static bool vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
914 void *opaque, JSONWriter *vmdesc,
915 Error **errp)
916 {
917 const VMStateDescription * const *sub = vmsd->subsections;
918 bool vmdesc_has_subsections = false;
919
920 trace_vmstate_subsection_save_top(vmsd->name);
921 while (sub && *sub) {
922 if (vmstate_section_needed(*sub, opaque)) {
923 const VMStateDescription *vmsdsub = *sub;
924 uint8_t len;
925
926 trace_vmstate_subsection_save_loop(vmsd->name, vmsdsub->name);
927 if (vmdesc) {
928 /* Only create subsection array when we have any */
929 if (!vmdesc_has_subsections) {
930 json_writer_start_array(vmdesc, "subsections");
931 vmdesc_has_subsections = true;
932 }
933
934 json_writer_start_object(vmdesc, NULL);
935 }
936
937 qemu_put_byte(f, QEMU_VM_SUBSECTION);
938 len = strlen(vmsdsub->name);
939 qemu_put_byte(f, len);
940 qemu_put_buffer(f, (uint8_t *)vmsdsub->name, len);
941 qemu_put_be32(f, vmsdsub->version_id);
942 if (!vmstate_save_vmsd(f, vmsdsub, opaque, vmdesc, errp)) {
943 return false;
944 }
945
946 if (vmdesc) {
947 json_writer_end_object(vmdesc);
948 }
949 }
950 sub++;
951 }
952
953 if (vmdesc_has_subsections) {
954 json_writer_end_array(vmdesc);
955 }
956
957 return true;
958 }
959
960 int vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
961 void *opaque, JSONWriter *vmdesc_id, Error **errp)
962 {
963 return vmstate_save_vmsd(f, vmsd, opaque, vmdesc_id, errp) ? 0 : -EINVAL;
964 }
965
966 int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
967 void *opaque, int version_id, Error **errp)
968 {
969 return vmstate_load_vmsd(f, vmsd, opaque, version_id, errp) ? 0 : -EINVAL;
970 }