@samitouri / QOSamiQemu / commits / f73d6251fb

vmstate: Introduce vmstate_save_field_with_vmdesc()

Introduce a helper to do both the JSON blob generations and save vmstate. This further shrinks the function a bit. More importantly, we'll need to save two fields in one loop very soon in the future with the JSON blob. Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io> Reviewed-by: Fabiano Rosas <farosas@suse.de> Signed-off-by: Peter Xu <peterx@redhat.com> Reviewed-by: Juraj Marcin <jmarcin@redhat.com> Link: https://lore.kernel.org/qemu-devel/20260401202844.673494-7-peterx@redhat.com Signed-off-by: Fabiano Rosas <farosas@suse.de>

Peter Xu committed Apr 1, 2026 at 16:28 UTC f73d6251fbe6c1e6ce57639bf7796683f7df8cda
1 file changed +32 -13
migration/vmstate.c
+32 -13
@@ -514,6 +514,35 @@ static bool vmstate_save_field(QEMUFile *f, void *pv, size_t size,
514 return true;
515 }
516
517 +/*
518 + * Save a whole VMSD field, including its JSON blob separately when @vmdesc
519 + * is specified.
520 + */
521 +static inline bool
522 +vmstate_save_field_with_vmdesc(QEMUFile *f, void *pv, size_t size,
523 + const VMStateDescription *vmsd,
524 + const VMStateField *field, JSONWriter *vmdesc,
525 + int i, int max, Error **errp)
526 +{
527 + uint64_t old_offset, written_bytes;
528 + bool ok;
529 +
530 + vmsd_desc_field_start(vmsd, vmdesc, field, i, max);
531 +
532 + old_offset = qemu_file_transferred(f);
533 + ok = vmstate_save_field(f, pv, size, field, vmdesc, errp);
534 + written_bytes = qemu_file_transferred(f) - old_offset;
535 +
536 + vmsd_desc_field_end(vmsd, vmdesc, field, written_bytes);
537 +
538 + if (!ok) {
539 + error_prepend(errp, "Save of field %s/%s failed: ",
540 + vmsd->name, field->name);
541 + }
542 +
543 + return ok;
544 +}
545 +
546 static bool vmstate_save_vmsd_v(QEMUFile *f, const VMStateDescription *vmsd,
547 void *opaque, JSONWriter *vmdesc,
548 int version_id, Error **errp)
@@ -542,7 +571,6 @@ static bool vmstate_save_vmsd_v(QEMUFile *f, const VMStateDescription *vmsd,
571 void *first_elem = opaque + field->offset;
572 int i, n_elems = vmstate_n_elems(opaque, field);
573 int size = vmstate_size(opaque, field);
545 - uint64_t old_offset, written_bytes;
574 JSONWriter *vmdesc_loop = vmdesc;
575 bool is_prev_null = false;
576
@@ -559,7 +587,6 @@ static bool vmstate_save_vmsd_v(QEMUFile *f, const VMStateDescription *vmsd,
587 /* maximum number of elements to compress in the JSON blob */
588 int max_elems = vmsd_can_compress(field) ? (n_elems - i) : 1;
589
562 - old_offset = qemu_file_transferred(f);
590 if (field->flags & VMS_ARRAY_OF_POINTER) {
591 assert(curr_elem);
592 curr_elem = *(void **)curr_elem;
@@ -606,15 +633,9 @@ static bool vmstate_save_vmsd_v(QEMUFile *f, const VMStateDescription *vmsd,
633 }
634 }
635
609 - vmsd_desc_field_start(vmsd, vmdesc_loop, inner_field,
610 - i, max_elems);
611 -
612 - ok = vmstate_save_field(f, curr_elem, size, inner_field,
613 - vmdesc_loop, errp);
614 -
615 - written_bytes = qemu_file_transferred(f) - old_offset;
616 - vmsd_desc_field_end(vmsd, vmdesc_loop, inner_field,
617 - written_bytes);
636 + ok = vmstate_save_field_with_vmdesc(f, curr_elem, size, vmsd,
637 + inner_field, vmdesc_loop,
638 + i, max_elems, errp);
639
640 /* If we used a fake temp field.. free it now */
641 if (is_null) {
@@ -622,8 +643,6 @@ static bool vmstate_save_vmsd_v(QEMUFile *f, const VMStateDescription *vmsd,
643 }
644
645 if (!ok) {
625 - error_prepend(errp, "Save of field %s/%s failed: ",
626 - vmsd->name, field->name);
646 goto out;
647 }
648