[PATCH RFC v2 04/11] vmstate: Update max_elems early and check field compressable once

Peter Xu posted 11 patches 6 days, 21 hours ago
[PATCH RFC v2 04/11] vmstate: Update max_elems early and check field compressable once
Posted by Peter Xu 6 days, 21 hours ago
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.

Signed-off-by: Peter Xu <peterx@redhat.com>
---
 migration/vmstate.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/migration/vmstate.c b/migration/vmstate.c
index e29a8c3f49..05badef42f 100644
--- a/migration/vmstate.c
+++ b/migration/vmstate.c
@@ -556,7 +556,8 @@ static bool vmstate_save_vmsd_v(QEMUFile *f, const VMStateDescription *vmsd,
                 void *curr_elem = first_elem + size * i;
                 const VMStateField *inner_field;
                 bool is_null;
-                int max_elems = n_elems - i;
+                /* maximum number of elements to compress in the JSON blob */
+                int max_elems = vmsd_can_compress(field) ? (n_elems - i) : 1;
 
                 old_offset = qemu_file_transferred(f);
                 if (field->flags & VMS_ARRAY_OF_POINTER) {
@@ -587,7 +588,8 @@ static bool vmstate_save_vmsd_v(QEMUFile *f, const VMStateDescription *vmsd,
                  * vs. nullptr). Search ahead for the next null/non-null element
                  * and start a new compressed array if found.
                  */
-                if (vmdesc && (field->flags & VMS_ARRAY_OF_POINTER) &&
+                if (vmdesc && max_elems > 1 &&
+                    (field->flags & VMS_ARRAY_OF_POINTER) &&
                     is_null != is_prev_null) {
 
                     is_prev_null = is_null;
@@ -626,7 +628,7 @@ static bool vmstate_save_vmsd_v(QEMUFile *f, const VMStateDescription *vmsd,
                 }
 
                 /* Compressed arrays only care about the first element */
-                if (vmdesc_loop && vmsd_can_compress(field)) {
+                if (vmdesc_loop && max_elems > 1) {
                     vmdesc_loop = NULL;
                 }
             }
-- 
2.50.1
Re: [PATCH RFC v2 04/11] vmstate: Update max_elems early and check field compressable once
Posted by Alexander Mikhalitsyn 1 day, 5 hours ago
Am Do., 26. März 2026 um 22:05 Uhr schrieb Peter Xu <peterx@redhat.com>:
>
> 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.
>
> Signed-off-by: Peter Xu <peterx@redhat.com>

Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>

> ---
>  migration/vmstate.c | 8 +++++---
>  1 file changed, 5 insertions(+), 3 deletions(-)
>
> diff --git a/migration/vmstate.c b/migration/vmstate.c
> index e29a8c3f49..05badef42f 100644
> --- a/migration/vmstate.c
> +++ b/migration/vmstate.c
> @@ -556,7 +556,8 @@ static bool vmstate_save_vmsd_v(QEMUFile *f, const VMStateDescription *vmsd,
>                  void *curr_elem = first_elem + size * i;
>                  const VMStateField *inner_field;
>                  bool is_null;
> -                int max_elems = n_elems - i;
> +                /* maximum number of elements to compress in the JSON blob */
> +                int max_elems = vmsd_can_compress(field) ? (n_elems - i) : 1;
>
>                  old_offset = qemu_file_transferred(f);
>                  if (field->flags & VMS_ARRAY_OF_POINTER) {
> @@ -587,7 +588,8 @@ static bool vmstate_save_vmsd_v(QEMUFile *f, const VMStateDescription *vmsd,
>                   * vs. nullptr). Search ahead for the next null/non-null element
>                   * and start a new compressed array if found.
>                   */
> -                if (vmdesc && (field->flags & VMS_ARRAY_OF_POINTER) &&
> +                if (vmdesc && max_elems > 1 &&
> +                    (field->flags & VMS_ARRAY_OF_POINTER) &&
>                      is_null != is_prev_null) {
>
>                      is_prev_null = is_null;
> @@ -626,7 +628,7 @@ static bool vmstate_save_vmsd_v(QEMUFile *f, const VMStateDescription *vmsd,
>                  }
>
>                  /* Compressed arrays only care about the first element */
> -                if (vmdesc_loop && vmsd_can_compress(field)) {
> +                if (vmdesc_loop && max_elems > 1) {
>                      vmdesc_loop = NULL;
>                  }
>              }
> --
> 2.50.1
>
Re: [PATCH RFC v2 04/11] vmstate: Update max_elems early and check field compressable once
Posted by Fabiano Rosas 6 days, 6 hours ago
Peter Xu <peterx@redhat.com> writes:

> 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.
>
> Signed-off-by: Peter Xu <peterx@redhat.com>

Reviewed-by: Fabiano Rosas <farosas@suse.de>