@samitouri / QOSamiQemu / commits / 29439dff51

vmstate: Update max_elems early and check field compressable once

QEMU has a trick in vmstate_save_vmsd_v(), where it will try to compress multiple JSON entries into one with a count to avoid duplicated entries. That only applies to the cases where vmsd_can_compress() should return true. For example, vmsd_desc_field_start() later (who will take the updated max_elems as the last parameter) will ignore the value passed in when vmsd_can_compress() returns false. Do that check once at the start of loop, and use it to update max_elems, so that max_elems keeps 1 for uncompressable VMSD fields, which is more straightforward. This also paves way to make this counter work for ptr marker VMSD fields too. No functional change intended in this patch alone. Reviewed-by: Fabiano Rosas <farosas@suse.de> Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io> Signed-off-by: Peter Xu <peterx@redhat.com> Reviewed-by: Juraj Marcin <jmarcin@redhat.com> Link: https://lore.kernel.org/qemu-devel/20260401202844.673494-5-peterx@redhat.com Signed-off-by: Fabiano Rosas <farosas@suse.de>

Peter Xu committed Apr 1, 2026 at 16:28 UTC 29439dff51380fc97ddd565e0f05c8e33b597e95
1 file changed +5 -3
migration/vmstate.c
+5 -3
@@ -556,7 +556,8 @@ static bool vmstate_save_vmsd_v(QEMUFile *f, const VMStateDescription *vmsd,
556 void *curr_elem = first_elem + size * i;
557 const VMStateField *inner_field;
558 bool is_null;
559 - int max_elems = n_elems - i;
559 + /* maximum number of elements to compress in the JSON blob */
560 + int max_elems = vmsd_can_compress(field) ? (n_elems - i) : 1;
561
562 old_offset = qemu_file_transferred(f);
563 if (field->flags & VMS_ARRAY_OF_POINTER) {
@@ -587,7 +588,8 @@ static bool vmstate_save_vmsd_v(QEMUFile *f, const VMStateDescription *vmsd,
588 * vs. nullptr). Search ahead for the next null/non-null element
589 * and start a new compressed array if found.
590 */
590 - if (vmdesc && (field->flags & VMS_ARRAY_OF_POINTER) &&
591 + if (vmdesc && max_elems > 1 &&
592 + (field->flags & VMS_ARRAY_OF_POINTER) &&
593 is_null != is_prev_null) {
594
595 is_prev_null = is_null;
@@ -626,7 +628,7 @@ static bool vmstate_save_vmsd_v(QEMUFile *f, const VMStateDescription *vmsd,
628 }
629
630 /* Compressed arrays only care about the first element */
629 - if (vmdesc_loop && vmsd_can_compress(field)) {
631 + if (vmdesc_loop && max_elems > 1) {
632 vmdesc_loop = NULL;
633 }
634 }