@samitouri / QOSamiQemu / commits / 57036a0cbf

migration: introduce vmstate_load_vmsd() and vmstate_save_vmsd()

Introduce new APIs, returning bool. The analysis https://lore.kernel.org/qemu-devel/aQDdRn8t0B8oE3gf@x1.local/ shows, that vmstate_load_state() return value actually only used to check for success, specific errno values doesn't make sense. With this commit we introduce new functions with modern bool interface, and in following commits we'll update the code base to use them, starting from migration/ code, and finally we will remove old vmstate_load_state() and vmstate_save_state(). This patch reworks existing functions to new one, so that old interfaces are simple wrappers, which will be easy to remove later. Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru> Reviewed-by: Peter Xu <peterx@redhat.com> Link: https://lore.kernel.org/qemu-devel/20260304212303.667141-14-vsementsov@yandex-team.ru Signed-off-by: Fabiano Rosas <farosas@suse.de>

Vladimir Sementsov-Ogievskiy committed Mar 5, 2026 at 00:22 UTC 57036a0cbfda1470018bf5c7f0d98423352a36d9
2 files changed +58 -40
include/migration/vmstate.h
+9
@@ -1257,10 +1257,19 @@ extern const VMStateInfo vmstate_info_qlist;
1257 .flags = VMS_END, \
1258 }
1259
1260 +/*
1261 + * vmstate_load_state() and vmstate_save_state() are
1262 + * depreacated, use vmstate_load_vmsd() and vmstate_save_vmsd()
1263 + * instead.
1264 + */
1265 int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
1266 void *opaque, int version_id, Error **errp);
1267 int vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
1268 void *opaque, JSONWriter *vmdesc, Error **errp);
1269 +bool vmstate_load_vmsd(QEMUFile *f, const VMStateDescription *vmsd,
1270 + void *opaque, int version_id, Error **errp);
1271 +bool vmstate_save_vmsd(QEMUFile *f, const VMStateDescription *vmsd,
1272 + void *opaque, JSONWriter *vmdesc, Error **errp);
1273
1274 bool vmstate_section_needed(const VMStateDescription *vmsd, void *opaque);
1275
migration/vmstate.c
+49 -40
@@ -26,7 +26,7 @@ static bool vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
26 Error **errp);
27 static bool vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
28 void *opaque, Error **errp);
29 -static int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
29 +static bool vmstate_save_vmsd_v(QEMUFile *f, const VMStateDescription *vmsd,
30 void *opaque, JSONWriter *vmdesc,
31 int version_id, Error **errp);
32
@@ -165,11 +165,11 @@ static bool vmstate_load_field(QEMUFile *f, void *pv, size_t size,
165 const VMStateField *field, Error **errp)
166 {
167 if (field->flags & VMS_STRUCT) {
168 - return vmstate_load_state(f, field->vmsd, pv, field->vmsd->version_id,
169 - errp) >= 0;
168 + return vmstate_load_vmsd(f, field->vmsd, pv, field->vmsd->version_id,
169 + errp);
170 } else if (field->flags & VMS_VSTRUCT) {
171 - return vmstate_load_state(f, field->vmsd, pv, field->struct_version_id,
172 - errp) >= 0;
171 + return vmstate_load_vmsd(f, field->vmsd, pv, field->struct_version_id,
172 + errp);
173 } else if (field->info->load) {
174 return field->info->load(f, pv, size, field, errp);
175 }
@@ -211,12 +211,11 @@ static bool vmstate_post_load(const VMStateDescription *vmsd,
211 return true;
212 }
213
214 -int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
214 +bool vmstate_load_vmsd(QEMUFile *f, const VMStateDescription *vmsd,
215 void *opaque, int version_id, Error **errp)
216 {
217 ERRP_GUARD();
218 const VMStateField *field = vmsd->fields;
219 - int ret = 0;
219
220 trace_vmstate_load_state(vmsd->name, version_id);
221
@@ -225,7 +224,7 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
224 "for local version_id %d",
225 vmsd->name, version_id, vmsd->version_id);
226 trace_vmstate_load_state_fail(vmsd->name, "too new");
228 - return -EINVAL;
227 + return false;
228 }
229
230 if (version_id < vmsd->minimum_version_id) {
@@ -233,11 +232,11 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
232 "for local minimum version_id %d",
233 vmsd->name, version_id, vmsd->minimum_version_id);
234 trace_vmstate_load_state_fail(vmsd->name, "too old");
236 - return -EINVAL;
235 + return false;
236 }
237
238 if (!vmstate_pre_load(vmsd, opaque, errp)) {
240 - return -EINVAL;
239 + return false;
240 }
241
242 while (field->name) {
@@ -257,6 +256,7 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
256 }
257
258 for (i = 0; i < n_elems; i++) {
259 + bool ok;
260 void *curr_elem = first_elem + size * i;
261 const VMStateField *inner_field;
262
@@ -275,33 +275,32 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
275 inner_field = field;
276 }
277
278 - ret = vmstate_load_field(f, curr_elem, size, inner_field,
279 - errp) ? 0 : -EINVAL;
278 + ok = vmstate_load_field(f, curr_elem, size, inner_field, errp);
279
280 /* If we used a fake temp field.. free it now */
281 if (inner_field != field) {
282 g_clear_pointer((gpointer *)&inner_field, g_free);
283 }
284
286 - if (ret >= 0) {
287 - ret = qemu_file_get_error(f);
285 + if (ok) {
286 + int ret = qemu_file_get_error(f);
287 if (ret < 0) {
288 error_setg(errp,
289 "Failed to load %s state: stream error: %d",
290 vmsd->name, ret);
291 trace_vmstate_load_field_error(field->name, ret);
293 - return ret;
292 + return false;
293 }
294 } else {
296 - qemu_file_set_error(f, ret);
297 - trace_vmstate_load_field_error(field->name, ret);
298 - return ret;
295 + qemu_file_set_error(f, -EINVAL);
296 + trace_vmstate_load_field_error(field->name, -EINVAL);
297 + return false;
298 }
299 }
300 } else if (field->flags & VMS_MUST_EXIST) {
301 error_setg(errp, "Input validation failed: %s/%s version_id: %d",
302 vmsd->name, field->name, vmsd->version_id);
304 - return -1;
303 + return false;
304 }
305 field++;
306 }
@@ -309,17 +308,16 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
308
309 if (!vmstate_subsection_load(f, vmsd, opaque, errp)) {
310 qemu_file_set_error(f, -EINVAL);
312 - return -EINVAL;
311 + return false;
312 }
313
314 if (!vmstate_post_load(vmsd, opaque, version_id, errp)) {
315 trace_vmstate_load_state_fail(vmsd->name, "post-load");
317 - return -EINVAL;
316 + return false;
317 }
318
319 trace_vmstate_load_state_success(vmsd->name);
321 -
322 - return 0;
320 + return true;
321 }
322
323 static int vmfield_name_num(const VMStateField *start,
@@ -492,11 +490,10 @@ static bool vmstate_save_field(QEMUFile *f, void *pv, size_t size,
490 JSONWriter *vmdesc, Error **errp)
491 {
492 if (field->flags & VMS_STRUCT) {
495 - return vmstate_save_state(f, field->vmsd, pv, vmdesc, errp) >= 0;
493 + return vmstate_save_vmsd(f, field->vmsd, pv, vmdesc, errp);
494 } else if (field->flags & VMS_VSTRUCT) {
497 - return vmstate_save_state_v(f, field->vmsd, pv, vmdesc,
498 - field->struct_version_id,
499 - errp) >= 0;
495 + return vmstate_save_vmsd_v(f, field->vmsd, pv, vmdesc,
496 + field->struct_version_id, errp);
497 } else if (field->info->save) {
498 return field->info->save(f, pv, size, field, vmdesc, errp);
499 }
@@ -509,19 +506,19 @@ static bool vmstate_save_field(QEMUFile *f, void *pv, size_t size,
506 return true;
507 }
508
512 -static int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
509 +static bool vmstate_save_vmsd_v(QEMUFile *f, const VMStateDescription *vmsd,
510 void *opaque, JSONWriter *vmdesc,
511 int version_id, Error **errp)
512 {
513 ERRP_GUARD();
517 - int ret = 0;
514 + bool ok = true;
515 const VMStateField *field = vmsd->fields;
516
517 trace_vmstate_save_state_top(vmsd->name);
518
519 if (!vmstate_pre_save(vmsd, opaque, errp)) {
520 trace_vmstate_save_state_pre_save_fail(vmsd->name);
524 - return -EINVAL;
521 + return false;
522 }
523
524 trace_vmstate_save_state_pre_save_success(vmsd->name);
@@ -602,8 +599,8 @@ static int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
599 vmsd_desc_field_start(vmsd, vmdesc_loop, inner_field,
600 i, max_elems);
601
605 - ret = vmstate_save_field(f, curr_elem, size, inner_field,
606 - vmdesc_loop, errp) ? 0 : -EINVAL;
602 + ok = vmstate_save_field(f, curr_elem, size, inner_field,
603 + vmdesc_loop, errp);
604
605 written_bytes = qemu_file_transferred(f) - old_offset;
606 vmsd_desc_field_end(vmsd, vmdesc_loop, inner_field,
@@ -614,7 +611,7 @@ static int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
611 g_clear_pointer((gpointer *)&inner_field, g_free);
612 }
613
617 - if (ret) {
614 + if (!ok) {
615 error_prepend(errp, "Save of field %s/%s failed: ",
616 vmsd->name, field->name);
617 goto out;
@@ -640,13 +637,13 @@ static int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
637 json_writer_end_array(vmdesc);
638 }
639
643 - ret = vmstate_subsection_save(f, vmsd, opaque, vmdesc, errp) ? 0 : -EINVAL;
640 + ok = vmstate_subsection_save(f, vmsd, opaque, vmdesc, errp);
641
642 out:
643 if (vmsd->post_save) {
644 vmsd->post_save(opaque);
645 }
649 - return ret;
646 + return ok;
647 }
648
649 static const VMStateDescription *
@@ -663,11 +660,11 @@ vmstate_get_subsection(const VMStateDescription * const *sub,
660 return NULL;
661 }
662
666 -int vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
663 +bool vmstate_save_vmsd(QEMUFile *f, const VMStateDescription *vmsd,
664 void *opaque, JSONWriter *vmdesc_id, Error **errp)
665 {
669 - return vmstate_save_state_v(f, vmsd, opaque, vmdesc_id, vmsd->version_id,
670 - errp);
666 + return vmstate_save_vmsd_v(f, vmsd, opaque, vmdesc_id, vmsd->version_id,
667 + errp);
668 }
669
670 static bool vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
@@ -712,7 +709,7 @@ static bool vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
709 qemu_file_skip(f, len); /* idstr */
710 version_id = qemu_get_be32(f);
711
715 - if (vmstate_load_state(f, sub_vmsd, opaque, version_id, errp) < 0) {
712 + if (!vmstate_load_vmsd(f, sub_vmsd, opaque, version_id, errp)) {
713 trace_vmstate_subsection_load_bad(vmsd->name, idstr, "(child)");
714 error_prepend(errp,
715 "Loading VM subsection '%s' in '%s' failed: ",
@@ -754,7 +751,7 @@ static bool vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
751 qemu_put_byte(f, len);
752 qemu_put_buffer(f, (uint8_t *)vmsdsub->name, len);
753 qemu_put_be32(f, vmsdsub->version_id);
757 - if (vmstate_save_state(f, vmsdsub, opaque, vmdesc, errp) < 0) {
754 + if (!vmstate_save_vmsd(f, vmsdsub, opaque, vmdesc, errp)) {
755 return false;
756 }
757
@@ -771,3 +768,15 @@ static bool vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
768
769 return true;
770 }
771 +
772 +int vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
773 + void *opaque, JSONWriter *vmdesc_id, Error **errp)
774 +{
775 + return vmstate_save_vmsd(f, vmsd, opaque, vmdesc_id, errp) ? 0 : -EINVAL;
776 +}
777 +
778 +int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
779 + void *opaque, int version_id, Error **errp)
780 +{
781 + return vmstate_load_vmsd(f, vmsd, opaque, version_id, errp) ? 0 : -EINVAL;
782 +}