All of lore.kernel.org
 help / color / mirror / Atom feed
From: Fabiano Rosas <farosas@suse.de>
To: Peter Xu <peterx@redhat.com>
Cc: qemu-devel@nongnu.org,
	Alexander Mikhalitsyn <alexander@mihalicyn.com>,
	Juraj Marcin <jmarcin@redhat.com>
Subject: Re: [RFC PATCH v1 12/17] vmstate: Introduce vmstate_next
Date: Thu, 26 Mar 2026 18:45:46 -0300	[thread overview]
Message-ID: <871ph6jmd1.fsf@suse.de> (raw)
In-Reply-To: <acVARwOjj5gJlmhr@x1.local>

Peter Xu <peterx@redhat.com> writes:

> On Tue, Mar 24, 2026 at 04:43:27PM -0300, Fabiano Rosas wrote:
>> Similarly to vmstate_first(), introduce a vmstate_next(), which does
>> the necessary dereferencing of pointers to get to the leaf element. On
>> the load side, allow the caller to pass a flag indicating whether
>> allocation is expected and call the allocation function if so.
>> 
>> Signed-off-by: Fabiano Rosas <farosas@suse.de>
>> ---
>>  migration/vmstate.c | 84 +++++++++++++++++++++------------------------
>>  1 file changed, 39 insertions(+), 45 deletions(-)
>> 
>> diff --git a/migration/vmstate.c b/migration/vmstate.c
>> index ab7c6fa4ab..c1ad0ef9a5 100644
>> --- a/migration/vmstate.c
>> +++ b/migration/vmstate.c
>> @@ -127,24 +127,51 @@ static void *vmstate_first(void *opaque, const VMStateField *field,
>>      return first;
>>  }
>>  
>> -static bool vmstate_ptr_marker_load(QEMUFile *f, bool *load_field,
>> -                                    Error **errp)
>> +static void *vmstate_next(void **first, const VMStateField *field,
>> +                          int size, int i, bool alloc)
>>  {
>> -    int byte = qemu_get_byte(f);
>> +    void **array_elem;
>> +    void *next;
>> +
>> +    if (!(field->flags & VMS_ARRAY_OF_POINTER)) {
>> +        next = (void *)first + size * i;
>> +        return next;
>> +    }
>> +
>> +    array_elem = first + i;
>> +    next = *array_elem;
>> +
>> +    if (alloc) {
>> +        if (!next || field->flags & VMS_ARRAY_OF_POINTER_AUTO_ALLOC) {
>> +            /*
>> +             * NOTE: do not use vmstate_size() here, because we
>> +             * need the object size, not entry size of the
>> +             * array.
>> +             */
>> +            next = vmstate_handle_alloc(array_elem, field->size, 1);
>> +        }
>> +    }
>> +    return next;
>> +}
>> +
>> +static bool vmstate_ptr_marker_load(QEMUFile *f, bool *load_field)
>> +{
>> +    int byte = qemu_peek_byte(f, 0);
>
> Here, peeking the marker for ...
>
>>  
>>      if (byte == VMS_MARKER_PTR_NULL) {
>>          /* When it's a null ptr marker, do not continue the load */
>>          *load_field = false;
>> +        qemu_file_skip(f, 1);
>>          return true;
>>      }
>>  
>>      if (byte == VMS_MARKER_PTR_VALID) {
>>          /* We need to load this field right after the marker */
>>          *load_field = true;
>> +        qemu_file_skip(f, 1);
>>          return true;
>>      }
>>  
>> -    error_setg(errp, "Unexpected ptr marker: %d", byte);
>>      return false;
>>  }
>>  
>> @@ -273,41 +300,13 @@ bool vmstate_load_vmsd(QEMUFile *f, const VMStateDescription *vmsd,
>>                  void *curr_elem;
>>  
>>                  if (field->flags & VMS_ARRAY_OF_POINTER) {
>
> ... every VMS_ARRAY_OF_POINTER case makes me feel uneasy.
>

There's 32k bytes in the buffer, this is likely to be just a
dereference. But fair enough.

> Note that we only have two use cases that both of them are certain on the
> upcoming byte to come:
>
> (1) for the null-only pointer, which is before this series introduced, both
> src/dst qemu knows 100% which ptr is NULL, so dest QEMU expects that 0x30
> for each null pointer.
>
> (2) for the new _AUTO_ALLOC introduced here, we also know exactly either
> 0x30 or 0x31 will come, and one of them must come before the real field
> dump.
>
> I think we may shoot us in the foot if we see 0x30 but in reality it's just
> the 1st byte of some array field's binary stream.
>

Yeah, that's a good point...

If you can put up with passing QEMUFile into vmstate_next(), we could
get the byte only when we're expecting it. Something like:

diff --git a/migration/vmstate.c b/migration/vmstate.c
index 25fd9e52bc..16d9c1753f 100644
--- a/migration/vmstate.c
+++ b/migration/vmstate.c
@@ -137,7 +137,7 @@ static void *vmstate_first(void *opaque, const VMStateField *field,
 }
 
 static void *vmstate_next(void **first, const VMStateField *field,
-                          int size, int i, bool alloc)
+                          int size, int i, QEMUFile *f)
 {
     void **array_elem;
     void *next;
@@ -150,8 +150,11 @@ static void *vmstate_next(void **first, const VMStateField *field,
     array_elem = first + i;
     next = *array_elem;
 
-    if (alloc) {
-        if (!next || field->flags & VMS_ALLOC) {
+    if (f && (!next || field->flags & VMS_ALLOC)) {
+        bool alloc, ok;
+
+        ok = vmstate_ptr_marker_load(f, &alloc);
+        if (ok & alloc) {
             /*
              * NOTE: do not use vmstate_size() here, because we
              * need the object size, not entry size of the
@@ -315,18 +318,11 @@ bool vmstate_load_vmsd(QEMUFile *f, const VMStateDescription *vmsd,
                              !(field->flags & VMS_ARRAY_OF_POINTER));
 
         for (i = 0; i < n_elems; i++) {
-            /* If we will process the load of field? */
-            bool load_field = true;
             void *curr_elem;
 
-            if (field->flags & VMS_ARRAY_OF_POINTER) {
-                /* Peek a possible pointer marker instead of VMSD first */
-                ok = vmstate_ptr_marker_load(f, &load_field);
-            }
-
-            curr_elem = vmstate_next(head, field, size, i, load_field && ok);
+            curr_elem = vmstate_next(head, field, size, i, f);
 
-            if (load_field) {
+            if (curr_elem) {
                 ok = vmstate_load_field(f, curr_elem, size, field, errp);
             }
 
@@ -673,7 +669,7 @@ static bool vmstate_save_vmsd_v(QEMUFile *f, const VMStateDescription *vmsd,
 
         for (i = 0; i < n_elems; i++) {
             bool save_field = true;
-            void *curr_elem = vmstate_next(head, field, size, i, false);
+            void *curr_elem = vmstate_next(head, field, size, i, NULL);
             int max_elems = n_elems - i;
 
             if (field->flags & VMS_ARRAY_OF_POINTER) {
@@ -711,8 +707,7 @@ static bool vmstate_save_vmsd_v(QEMUFile *f, const VMStateDescription *vmsd,
                         use_vmdesc = true;
 
                         for (int j = i + 1; j < n_elems; j++) {
-                            void *elem = vmstate_next(head, field, size, j,
-                                                      false);
+                            void *elem = vmstate_next(head, field, size, j, NULL);
                             bool elem_is_null = !elem;
 
                             if (is_null != elem_is_null) {
-- 
2.51.0



  reply	other threads:[~2026-03-26 21:46 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-24 19:43 [RFC PATCH v1 00/17] migration: vmstate_save|load changes for peterx Fabiano Rosas
2026-03-24 19:43 ` [RFC PATCH v1 01/17] vmstate: fixup the use of AUTO_ALLOC flag Fabiano Rosas
2026-03-25 16:18   ` Peter Xu
2026-03-24 19:43 ` [RFC PATCH v1 02/17] vmstate: Remove vmstate_use_marker_field Fabiano Rosas
2026-03-25 16:37   ` Peter Xu
2026-03-25 17:51     ` Fabiano Rosas
2026-03-24 19:43 ` [RFC PATCH v1 03/17] vmstate: Stop checking size for nullptr compression Fabiano Rosas
2026-03-24 19:43 ` [RFC PATCH v1 04/17] vmstate: Set error inside of vmstate_save_field_with_vmdesc Fabiano Rosas
2026-03-24 19:43 ` [RFC PATCH v1 05/17] vmstate: Remove vmdesc_loop Fabiano Rosas
2026-03-25 17:07   ` Peter Xu
2026-03-25 18:11     ` Fabiano Rosas
2026-03-25 21:43       ` Peter Xu
2026-03-24 19:43 ` [RFC PATCH v1 06/17] vmstate: Put array of pointers code together Fabiano Rosas
2026-03-24 19:43 ` [RFC PATCH v1 07/17] vmstate: Create and save ptr marker in same function Fabiano Rosas
2026-03-24 19:43 ` [RFC PATCH v1 08/17] vmstate: Don't recompute size and n_elems in vmstate_size Fabiano Rosas
2026-03-24 19:43 ` [RFC PATCH v1 09/17] vmstate: Increase scope of vmstate_handle_alloc Fabiano Rosas
2026-03-24 19:43 ` [RFC PATCH v1 10/17] vmstate: Remove curr_elem_p Fabiano Rosas
2026-03-24 19:43 ` [RFC PATCH v1 11/17] vmstate: Introduce vmstate_first Fabiano Rosas
2026-03-24 19:43 ` [RFC PATCH v1 12/17] vmstate: Introduce vmstate_next Fabiano Rosas
2026-03-26 14:18   ` Peter Xu
2026-03-26 21:45     ` Fabiano Rosas [this message]
2026-03-24 19:43 ` [RFC PATCH v1 13/17] vmstate: Drop VMS_ARRAY_OF_POINTER_AUTO_ALLOC Fabiano Rosas
2026-03-25 19:29   ` Peter Xu
2026-03-25 21:49     ` Peter Xu
2026-03-25 21:57   ` Peter Xu
2026-03-24 19:43 ` [RFC PATCH v1 14/17] vmstate: Move VMS_MUST_EXIST check Fabiano Rosas
2026-03-25 19:38   ` Peter Xu
2026-03-24 19:43 ` [RFC PATCH v1 15/17] vmstate: Invert exists check Fabiano Rosas
2026-03-24 19:43 ` [RFC PATCH v1 16/17] vmstate: Declare variables at the top Fabiano Rosas
2026-03-24 19:43 ` [RFC PATCH v1 17/17] vmstate: Reduce indentation levels Fabiano Rosas
2026-03-25 19:43 ` [RFC PATCH v1 00/17] migration: vmstate_save|load changes for peterx Peter Xu
2026-03-25 20:10   ` Fabiano Rosas
2026-03-26 19:42     ` Peter Xu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=871ph6jmd1.fsf@suse.de \
    --to=farosas@suse.de \
    --cc=alexander@mihalicyn.com \
    --cc=jmarcin@redhat.com \
    --cc=peterx@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.