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