[{"id":3675408,"web_url":"http://patchwork.ozlabs.org/comment/3675408/","msgid":"<adfdUBTJweN-V-ZP@fedora>","list_archive_url":null,"date":"2026-04-09T17:10:56","subject":"Re: [PATCH 04/14] migration/treewide: Merge\n @state_pending_{exact|estimate} APIs","submitter":{"id":89058,"url":"http://patchwork.ozlabs.org/api/people/89058/","name":"Juraj Marcin","email":"jmarcin@redhat.com"},"content":"Hi Peter,\n\nOn 2026-04-08 12:55, Peter Xu wrote:\n> These two APIs are a slight duplication.  For example, there're a few users\n> that directly pass in the same function.\n> \n> It might also be error prone to provide two hooks, so that it's easier to\n> happen one module report different things via the two hooks.\n> \n> In reality, they should always report the same thing, only about whether we\n> should use a fast-path when the slow path might be too slow, as QEMU may\n> query these information quite frequently during migration process.\n> \n> Merge it into one API, provide a bool showing if the query is an exact\n> query or not.  No functional change intended.\n> \n> Export qemu_savevm_query_pending().  We should use the new API here\n> provided when there're new users to do the query.  This will happen very\n> soon.\n> \n> Cc: Halil Pasic <pasic@linux.ibm.com>\n> Cc: Christian Borntraeger <borntraeger@linux.ibm.com>\n> Cc: Jason Herne <jjherne@linux.ibm.com>\n> Cc: Eric Farman <farman@linux.ibm.com>\n> Cc: Matthew Rosato <mjrosato@linux.ibm.com>\n> Cc: Richard Henderson <richard.henderson@linaro.org>\n> Cc: Ilya Leoshkevich <iii@linux.ibm.com>\n> Cc: David Hildenbrand <david@kernel.org>\n> Cc: Cornelia Huck <cohuck@redhat.com>\n> Cc: Eric Blake <eblake@redhat.com>\n> Cc: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>\n> Cc: John Snow <jsnow@redhat.com>\n> Signed-off-by: Peter Xu <peterx@redhat.com>\n> ---\n>  docs/devel/migration/main.rst  |  9 ++----\n>  docs/devel/migration/vfio.rst  |  9 ++----\n>  include/migration/register.h   | 52 +++++++++++-----------------------\n>  migration/savevm.h             |  3 ++\n>  hw/s390x/s390-stattrib.c       |  9 +++---\n>  hw/vfio/migration.c            | 48 ++++++++++++++-----------------\n>  migration/block-dirty-bitmap.c | 10 +++----\n>  migration/ram.c                | 33 +++++++--------------\n>  migration/savevm.c             | 42 +++++++++++++--------------\n>  hw/vfio/trace-events           |  3 +-\n>  10 files changed, 84 insertions(+), 134 deletions(-)\n> \n> diff --git a/docs/devel/migration/main.rst b/docs/devel/migration/main.rst\n> index 234d280249..e6a6ca3681 100644\n> --- a/docs/devel/migration/main.rst\n> +++ b/docs/devel/migration/main.rst\n> @@ -515,13 +515,8 @@ An iterative device must provide:\n>    - A ``load_setup`` function that initialises the data structures on the\n>      destination.\n>  \n> -  - A ``state_pending_exact`` function that indicates how much more\n> -    data we must save.  The core migration code will use this to\n> -    determine when to pause the CPUs and complete the migration.\n> -\n> -  - A ``state_pending_estimate`` function that indicates how much more\n> -    data we must save.  When the estimated amount is smaller than the\n> -    threshold, we call ``state_pending_exact``.\n> +  - A ``save_query_pending`` function that indicates how much more\n> +    data we must save.\n>  \n>    - A ``save_live_iterate`` function should send a chunk of data until\n>      the point that stream bandwidth limits tell it to stop.  Each call\n> diff --git a/docs/devel/migration/vfio.rst b/docs/devel/migration/vfio.rst\n> index 0790e5031d..33768c877c 100644\n> --- a/docs/devel/migration/vfio.rst\n> +++ b/docs/devel/migration/vfio.rst\n> @@ -50,13 +50,8 @@ VFIO implements the device hooks for the iterative approach as follows:\n>  * A ``load_setup`` function that sets the VFIO device on the destination in\n>    _RESUMING state.\n>  \n> -* A ``state_pending_estimate`` function that reports an estimate of the\n> -  remaining pre-copy data that the vendor driver has yet to save for the VFIO\n> -  device.\n> -\n> -* A ``state_pending_exact`` function that reads pending_bytes from the vendor\n> -  driver, which indicates the amount of data that the vendor driver has yet to\n> -  save for the VFIO device.\n> +* A ``save_query_pending`` function that reports the remaining pre-copy\n> +  data that the vendor driver has yet to save for the VFIO device.\n>  \n>  * An ``is_active_iterate`` function that indicates ``save_live_iterate`` is\n>    active only when the VFIO device is in pre-copy states.\n> diff --git a/include/migration/register.h b/include/migration/register.h\n> index d0f37f5f43..aba3c9af2f 100644\n> --- a/include/migration/register.h\n> +++ b/include/migration/register.h\n> @@ -16,6 +16,13 @@\n>  \n>  #include \"hw/core/vmstate-if.h\"\n>  \n> +typedef struct MigPendingData {\n> +    /* Amount of pending bytes can be transferred in precopy or stopcopy */\n> +    uint64_t precopy_bytes;\n> +    /* Amount of pending bytes can be transferred in postcopy */\n> +    uint64_t postcopy_bytes;\n> +} MigPendingData;\n> +\n>  /**\n>   * struct SaveVMHandlers: handler structure to finely control\n>   * migration of complex subsystems and devices, such as RAM, block and\n> @@ -197,46 +204,19 @@ typedef struct SaveVMHandlers {\n>      bool (*save_postcopy_prepare)(QEMUFile *f, void *opaque, Error **errp);\n>  \n>      /**\n> -     * @state_pending_estimate\n> -     *\n> -     * This estimates the remaining data to transfer\n> -     *\n> -     * Sum of @can_postcopy and @must_postcopy is the whole amount of\n> -     * pending data.\n> -     *\n> -     * @opaque: data pointer passed to register_savevm_live()\n> -     * @must_precopy: amount of data that must be migrated in precopy\n> -     *                or in stopped state, i.e. that must be migrated\n> -     *                before target start.\n> -     * @can_postcopy: amount of data that can be migrated in postcopy\n> -     *                or in stopped state, i.e. after target start.\n> -     *                Some can also be migrated during precopy (RAM).\n> -     *                Some must be migrated after source stops\n> -     *                (block-dirty-bitmap)\n> -     */\n> -    void (*state_pending_estimate)(void *opaque, uint64_t *must_precopy,\n> -                                   uint64_t *can_postcopy);\n> -\n> -    /**\n> -     * @state_pending_exact\n> -     *\n> -     * This calculates the exact remaining data to transfer\n> +     * @save_query_pending\n>       *\n> -     * Sum of @can_postcopy and @must_postcopy is the whole amount of\n> -     * pending data.\n> +     * This estimates the remaining data to transfer on the source side.\n> +     * It's highly suggested that the module should implement both fastpath\n> +     * and slowpath version of it when it can be slow (for more information\n> +     * please check pending->fastpath field).\n\nThere is no pending->fastpath field anymore.\n\n>       *\n>       * @opaque: data pointer passed to register_savevm_live()\n> -     * @must_precopy: amount of data that must be migrated in precopy\n> -     *                or in stopped state, i.e. that must be migrated\n> -     *                before target start.\n> -     * @can_postcopy: amount of data that can be migrated in postcopy\n> -     *                or in stopped state, i.e. after target start.\n> -     *                Some can also be migrated during precopy (RAM).\n> -     *                Some must be migrated after source stops\n> -     *                (block-dirty-bitmap)\n> +     * @pending: pointer to a MigPendingData struct\n> +     * @exact: set true for an accurate (slow) query\n>       */\n> -    void (*state_pending_exact)(void *opaque, uint64_t *must_precopy,\n> -                                uint64_t *can_postcopy);\n> +    void (*save_query_pending)(void *opaque, MigPendingData *pending,\n> +                               bool exact);\n>  \n>      /**\n>       * @load_state\n> diff --git a/migration/savevm.h b/migration/savevm.h\n> index b3d1e8a13c..e4efd243f3 100644\n> --- a/migration/savevm.h\n> +++ b/migration/savevm.h\n> @@ -14,6 +14,8 @@\n>  #ifndef MIGRATION_SAVEVM_H\n>  #define MIGRATION_SAVEVM_H\n>  \n> +#include \"migration/register.h\"\n> +\n>  #define QEMU_VM_FILE_MAGIC           0x5145564d\n>  #define QEMU_VM_FILE_VERSION_COMPAT  0x00000002\n>  #define QEMU_VM_FILE_VERSION         0x00000003\n> @@ -43,6 +45,7 @@ int qemu_savevm_state_iterate(QEMUFile *f, bool postcopy);\n>  void qemu_savevm_state_cleanup(void);\n>  void qemu_savevm_state_complete_postcopy(QEMUFile *f);\n>  int qemu_savevm_state_complete_precopy(MigrationState *s);\n> +void qemu_savevm_query_pending(MigPendingData *pending, bool exact);\n>  void qemu_savevm_state_pending_exact(uint64_t *must_precopy,\n>                                       uint64_t *can_postcopy);\n>  void qemu_savevm_state_pending_estimate(uint64_t *must_precopy,\n> diff --git a/hw/s390x/s390-stattrib.c b/hw/s390x/s390-stattrib.c\n> index d808ece3b9..a22469a9e9 100644\n> --- a/hw/s390x/s390-stattrib.c\n> +++ b/hw/s390x/s390-stattrib.c\n> @@ -187,15 +187,15 @@ static int cmma_save_setup(QEMUFile *f, void *opaque, Error **errp)\n>      return 0;\n>  }\n>  \n> -static void cmma_state_pending(void *opaque, uint64_t *must_precopy,\n> -                               uint64_t *can_postcopy)\n> +static void cmma_state_pending(void *opaque, MigPendingData *pending,\n> +                               bool exact)\n>  {\n>      S390StAttribState *sas = S390_STATTRIB(opaque);\n>      S390StAttribClass *sac = S390_STATTRIB_GET_CLASS(sas);\n>      long long res = sac->get_dirtycount(sas);\n>  \n>      if (res >= 0) {\n> -        *must_precopy += res;\n> +        pending->precopy_bytes += res;\n>      }\n>  }\n>  \n> @@ -340,8 +340,7 @@ static SaveVMHandlers savevm_s390_stattrib_handlers = {\n>      .save_setup = cmma_save_setup,\n>      .save_live_iterate = cmma_save_iterate,\n>      .save_complete = cmma_save_complete,\n> -    .state_pending_exact = cmma_state_pending,\n> -    .state_pending_estimate = cmma_state_pending,\n> +    .save_query_pending = cmma_state_pending,\n>      .save_cleanup = cmma_save_cleanup,\n>      .load_state = cmma_load,\n>      .is_active = cmma_active,\n> diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c\n> index 5d5fca09bd..1e999f0040 100644\n> --- a/hw/vfio/migration.c\n> +++ b/hw/vfio/migration.c\n> @@ -571,42 +571,39 @@ static void vfio_save_cleanup(void *opaque)\n>      trace_vfio_save_cleanup(vbasedev->name);\n>  }\n>  \n> -static void vfio_state_pending_estimate(void *opaque, uint64_t *must_precopy,\n> -                                        uint64_t *can_postcopy)\n> +static void vfio_state_pending_sync(VFIODevice *vbasedev)\n>  {\n> -    VFIODevice *vbasedev = opaque;\n>      VFIOMigration *migration = vbasedev->migration;\n>  \n> -    if (!vfio_device_state_is_precopy(vbasedev)) {\n> -        return;\n> -    }\n> -\n> -    *must_precopy +=\n> -        migration->precopy_init_size + migration->precopy_dirty_size;\n> +    vfio_query_stop_copy_size(vbasedev);\n>  \n> -    trace_vfio_state_pending_estimate(vbasedev->name, *must_precopy,\n> -                                      *can_postcopy,\n> -                                      migration->precopy_init_size,\n> -                                      migration->precopy_dirty_size);\n> +    if (vfio_device_state_is_precopy(vbasedev)) {\n> +        vfio_query_precopy_size(migration);\n> +    }\n>  }\n>  \n> -static void vfio_state_pending_exact(void *opaque, uint64_t *must_precopy,\n> -                                     uint64_t *can_postcopy)\n> +static void vfio_state_pending(void *opaque, MigPendingData *pending,\n> +                               bool exact)\n>  {\n>      VFIODevice *vbasedev = opaque;\n>      VFIOMigration *migration = vbasedev->migration;\n> +    uint64_t remain;\n>  \n> -    vfio_query_stop_copy_size(vbasedev);\n> -    *must_precopy += migration->stopcopy_size;\n> -\n> -    if (vfio_device_state_is_precopy(vbasedev)) {\n> -        vfio_query_precopy_size(migration);\n> +    if (exact) {\n> +        vfio_state_pending_sync(vbasedev);\n> +        remain = migration->stopcopy_size;\n> +    } else {\n> +        if (!vfio_device_state_is_precopy(vbasedev)) {\n> +            return;\n> +        }\n> +        remain = migration->precopy_init_size + migration->precopy_dirty_size;\n>      }\n>  \n> -    trace_vfio_state_pending_exact(vbasedev->name, *must_precopy, *can_postcopy,\n> -                                   migration->stopcopy_size,\n> -                                   migration->precopy_init_size,\n> -                                   migration->precopy_dirty_size);\n> +    pending->precopy_bytes += remain;\n> +\n> +    trace_vfio_state_pending(vbasedev->name, migration->stopcopy_size,\n> +                             migration->precopy_init_size,\n> +                             migration->precopy_dirty_size);\n>  }\n>  \n>  static bool vfio_is_active_iterate(void *opaque)\n> @@ -851,8 +848,7 @@ static const SaveVMHandlers savevm_vfio_handlers = {\n>      .save_prepare = vfio_save_prepare,\n>      .save_setup = vfio_save_setup,\n>      .save_cleanup = vfio_save_cleanup,\n> -    .state_pending_estimate = vfio_state_pending_estimate,\n> -    .state_pending_exact = vfio_state_pending_exact,\n> +    .save_query_pending = vfio_state_pending,\n>      .is_active_iterate = vfio_is_active_iterate,\n>      .save_live_iterate = vfio_save_iterate,\n>      .save_complete = vfio_save_complete_precopy,\n> diff --git a/migration/block-dirty-bitmap.c b/migration/block-dirty-bitmap.c\n> index a061aad817..15d417013c 100644\n> --- a/migration/block-dirty-bitmap.c\n> +++ b/migration/block-dirty-bitmap.c\n> @@ -766,9 +766,8 @@ static int dirty_bitmap_save_complete(QEMUFile *f, void *opaque)\n>      return 0;\n>  }\n>  \n> -static void dirty_bitmap_state_pending(void *opaque,\n> -                                       uint64_t *must_precopy,\n> -                                       uint64_t *can_postcopy)\n> +static void dirty_bitmap_state_pending(void *opaque, MigPendingData *data,\n> +                                       bool exact)\n>  {\n>      DBMSaveState *s = &((DBMState *)opaque)->save;\n>      SaveBitmapState *dbms;\n> @@ -788,7 +787,7 @@ static void dirty_bitmap_state_pending(void *opaque,\n>  \n>      trace_dirty_bitmap_state_pending(pending);\n>  \n> -    *can_postcopy += pending;\n> +    data->postcopy_bytes += pending;\n>  }\n>  \n>  /* First occurrence of this bitmap. It should be created if doesn't exist */\n> @@ -1250,8 +1249,7 @@ static SaveVMHandlers savevm_dirty_bitmap_handlers = {\n>      .save_setup = dirty_bitmap_save_setup,\n>      .save_complete = dirty_bitmap_save_complete,\n>      .has_postcopy = dirty_bitmap_has_postcopy,\n> -    .state_pending_exact = dirty_bitmap_state_pending,\n> -    .state_pending_estimate = dirty_bitmap_state_pending,\n> +    .save_query_pending = dirty_bitmap_state_pending,\n>      .save_live_iterate = dirty_bitmap_save_iterate,\n>      .is_active_iterate = dirty_bitmap_is_active_iterate,\n>      .load_state = dirty_bitmap_load,\n> diff --git a/migration/ram.c b/migration/ram.c\n> index 979751f61b..e5b7217bf5 100644\n> --- a/migration/ram.c\n> +++ b/migration/ram.c\n> @@ -3443,30 +3443,18 @@ static int ram_save_complete(QEMUFile *f, void *opaque)\n>      return qemu_fflush(f);\n>  }\n>  \n> -static void ram_state_pending_estimate(void *opaque, uint64_t *must_precopy,\n> -                                       uint64_t *can_postcopy)\n> -{\n> -    RAMState **temp = opaque;\n> -    RAMState *rs = *temp;\n> -\n> -    uint64_t remaining_size = rs->migration_dirty_pages * TARGET_PAGE_SIZE;\n> -\n> -    if (migrate_postcopy_ram()) {\n> -        /* We can do postcopy, and all the data is postcopiable */\n> -        *can_postcopy += remaining_size;\n> -    } else {\n> -        *must_precopy += remaining_size;\n> -    }\n> -}\n> -\n> -static void ram_state_pending_exact(void *opaque, uint64_t *must_precopy,\n> -                                    uint64_t *can_postcopy)\n> +static void ram_state_pending(void *opaque, MigPendingData *pending,\n> +                              bool exact)\n>  {\n>      RAMState **temp = opaque;\n>      RAMState *rs = *temp;\n>      uint64_t remaining_size;\n>  \n> -    if (!migration_in_postcopy()) {\n> +    /*\n> +     * Sync is not needed either with: (1) a fast query, or (2) after\n> +     * postcopy has started (no new dirty will generate anymore).\n> +     */\n> +    if (exact && !migration_in_postcopy()) {\n>          bql_lock();\n>          WITH_RCU_READ_LOCK_GUARD() {\n>              migration_bitmap_sync_precopy(false);\n> @@ -3478,9 +3466,9 @@ static void ram_state_pending_exact(void *opaque, uint64_t *must_precopy,\n>  \n>      if (migrate_postcopy_ram()) {\n>          /* We can do postcopy, and all the data is postcopiable */\n> -        *can_postcopy += remaining_size;\n> +        pending->postcopy_bytes += remaining_size;\n>      } else {\n> -        *must_precopy += remaining_size;\n> +        pending->precopy_bytes += remaining_size;\n>      }\n>  }\n>  \n> @@ -4703,8 +4691,7 @@ static SaveVMHandlers savevm_ram_handlers = {\n>      .save_live_iterate = ram_save_iterate,\n>      .save_complete = ram_save_complete,\n>      .has_postcopy = ram_has_postcopy,\n> -    .state_pending_exact = ram_state_pending_exact,\n> -    .state_pending_estimate = ram_state_pending_estimate,\n> +    .save_query_pending = ram_state_pending,\n>      .load_state = ram_load,\n>      .save_cleanup = ram_save_cleanup,\n>      .load_setup = ram_load_setup,\n> diff --git a/migration/savevm.c b/migration/savevm.c\n> index dd58f2a705..392d840955 100644\n> --- a/migration/savevm.c\n> +++ b/migration/savevm.c\n> @@ -1762,46 +1762,44 @@ int qemu_savevm_state_complete_precopy(MigrationState *s)\n>      return qemu_fflush(f);\n>  }\n>  \n> -/* Give an estimate of the amount left to be transferred,\n> - * the result is split into the amount for units that can and\n> - * for units that can't do postcopy.\n> - */\n> -void qemu_savevm_state_pending_estimate(uint64_t *must_precopy,\n> -                                        uint64_t *can_postcopy)\n> +void qemu_savevm_query_pending(MigPendingData *pending, bool exact)\n>  {\n>      SaveStateEntry *se;\n>  \n> -    *must_precopy = 0;\n> -    *can_postcopy = 0;\n> +    pending->precopy_bytes = 0;\n> +    pending->postcopy_bytes = 0;\n>  \n>      QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {\n> -        if (!se->ops || !se->ops->state_pending_estimate) {\n> +        if (!se->ops || !se->ops->save_query_pending) {\n>              continue;\n>          }\n>          if (!qemu_savevm_state_active(se)) {\n>              continue;\n>          }\n> -        se->ops->state_pending_estimate(se->opaque, must_precopy, can_postcopy);\n> +        se->ops->save_query_pending(se->opaque, pending, exact);\n>      }\n>  }\n>  \n> +void qemu_savevm_state_pending_estimate(uint64_t *must_precopy,\n> +                                        uint64_t *can_postcopy)\n> +{\n> +    MigPendingData pending;\n> +\n> +    qemu_savevm_query_pending(&pending, false);\n> +\n> +    *must_precopy = pending.precopy_bytes;\n> +    *can_postcopy = pending.postcopy_bytes;\n> +}\n> +\n>  void qemu_savevm_state_pending_exact(uint64_t *must_precopy,\n>                                       uint64_t *can_postcopy)\n>  {\n> -    SaveStateEntry *se;\n> +    MigPendingData pending;\n>  \n> -    *must_precopy = 0;\n> -    *can_postcopy = 0;\n> +    qemu_savevm_query_pending(&pending, true);\n>  \n> -    QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {\n> -        if (!se->ops || !se->ops->state_pending_exact) {\n> -            continue;\n> -        }\n> -        if (!qemu_savevm_state_active(se)) {\n> -            continue;\n> -        }\n> -        se->ops->state_pending_exact(se->opaque, must_precopy, can_postcopy);\n> -    }\n> +    *must_precopy = pending.precopy_bytes;\n> +    *can_postcopy = pending.postcopy_bytes;\n>  }\n>  \n>  void qemu_savevm_state_cleanup(void)\n> diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events\n> index 846e3625c5..7cf5a9eb2d 100644\n> --- a/hw/vfio/trace-events\n> +++ b/hw/vfio/trace-events\n> @@ -173,8 +173,7 @@ vfio_save_device_config_state(const char *name) \" (%s)\"\n>  vfio_save_iterate(const char *name, uint64_t precopy_init_size, uint64_t precopy_dirty_size) \" (%s) precopy initial size %\"PRIu64\" precopy dirty size %\"PRIu64\n>  vfio_save_iterate_start(const char *name) \" (%s)\"\n>  vfio_save_setup(const char *name, uint64_t data_buffer_size) \" (%s) data buffer size %\"PRIu64\n> -vfio_state_pending_estimate(const char *name, uint64_t precopy, uint64_t postcopy, uint64_t precopy_init_size, uint64_t precopy_dirty_size) \" (%s) precopy %\"PRIu64\" postcopy %\"PRIu64\" precopy initial size %\"PRIu64\" precopy dirty size %\"PRIu64\n> -vfio_state_pending_exact(const char *name, uint64_t precopy, uint64_t postcopy, uint64_t stopcopy_size, uint64_t precopy_init_size, uint64_t precopy_dirty_size) \" (%s) precopy %\"PRIu64\" postcopy %\"PRIu64\" stopcopy size %\"PRIu64\" precopy initial size %\"PRIu64\" precopy dirty size %\"PRIu64\n> +vfio_state_pending(const char *name, uint64_t stopcopy_size, uint64_t precopy_init_size, uint64_t precopy_dirty_size) \" (%s) stopcopy size %\"PRIu64\" precopy initial size %\"PRIu64\" precopy dirty size %\"PRIu64\n>  vfio_vmstate_change(const char *name, int running, const char *reason, const char *dev_state) \" (%s) running %d reason %s device state %s\"\n>  vfio_vmstate_change_prepare(const char *name, int running, const char *reason, const char *dev_state) \" (%s) running %d reason %s device state %s\"\n>  \n> -- \n> 2.53.0\n> \n\nApart from that one comment above, it looks good to me!\n\nReviewed-by: Juraj Marcin <jmarcin@redhat.com>","headers":{"Return-Path":"<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=C6vQT26l;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=google header.b=qlok91z1;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)"],"Received":["from lists.gnu.org (lists1p.gnu.org [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fs6111qrMz1yCv\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 10 Apr 2026 03:11:47 +1000 (AEST)","from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1wAsuK-0002dq-U8; Thu, 09 Apr 2026 13:11:08 -0400","from eggs.gnu.org ([2001:470:142:3::10])\n by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <jmarcin@redhat.com>)\n id 1wAsuJ-0002dh-TL\n for qemu-devel@nongnu.org; Thu, 09 Apr 2026 13:11:07 -0400","from us-smtp-delivery-124.mimecast.com ([170.10.133.124])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <jmarcin@redhat.com>)\n id 1wAsuH-0007m2-0O\n for qemu-devel@nongnu.org; Thu, 09 Apr 2026 13:11:07 -0400","from mail-wm1-f71.google.com (mail-wm1-f71.google.com\n [209.85.128.71]) by relay.mimecast.com with ESMTP with STARTTLS\n (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n us-mta-208-NJckk-rWOamcIv9Z1w1cWg-1; Thu, 09 Apr 2026 13:11:02 -0400","by mail-wm1-f71.google.com with SMTP id\n 5b1f17b1804b1-488c2764f83so9818735e9.2\n for <qemu-devel@nongnu.org>; Thu, 09 Apr 2026 10:11:02 -0700 (PDT)","from fedora (nat-88-212-17-233.antik.sk. [88.212.17.233])\n by smtp.gmail.com with ESMTPSA id\n 5b1f17b1804b1-488d5b56d1asm4104515e9.15.2026.04.09.10.10.58\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Thu, 09 Apr 2026 10:10:59 -0700 (PDT)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1775754664;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n in-reply-to:in-reply-to:references:references;\n bh=+h7jpKdhCTn6mHuXqflXQE1DgwiNoIkqxn9rj7Bxf10=;\n b=C6vQT26l69FwHvfZaq0JNwF76HwwkoXtlTRl/kGy9GR2ghI8c7PF2VnApwPAFh0KVZwa0j\n nfAFa7OU6noFD87qILhshpKjppSDeebSrisdusHzYOUMug/NQu3AL9srROMGAiEJ/kHKID\n GFu7phHnH+YH1ff2VlUTyHOMOsD4qwI=","v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=redhat.com; s=google; t=1775754661; x=1776359461; darn=nongnu.org;\n h=in-reply-to:content-disposition:mime-version:references:message-id\n :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to;\n bh=+h7jpKdhCTn6mHuXqflXQE1DgwiNoIkqxn9rj7Bxf10=;\n b=qlok91z1Ky+YeKFA2jO/KwQ4ChdKSiFvjOZQXZK2o4D+RZouPdXV7U7PvmnvlrVdPr\n bx8Fm2AZgWiIkjNK8f+WFd45QV8fyyQF+1leT78w9A7cqpGEDB9gUIKN1afmIXHNpEBS\n A/EkIc9ZX7n23413Fxu/w48fcFT9v21Co9/8Ufj1jGObScYypXe26da2JJ8CWw+7t/Tu\n 2XH7MaoM/znR189Kmo2lzfvFSvAuN078JzRAmbfR8dpI55NiijD4vZtyJiF9c8KL0yR8\n EwIzdpzeb5yp7UUqzl/k+FckSrLjy+wgxuXh12lgfMzWY/0Eyfodf/r2v6cYCFTemPjS\n 79ZA=="],"X-MC-Unique":"NJckk-rWOamcIv9Z1w1cWg-1","X-Mimecast-MFC-AGG-ID":"NJckk-rWOamcIv9Z1w1cWg_1775754661","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1775754661; x=1776359461;\n h=in-reply-to:content-disposition:mime-version:references:message-id\n :subject:cc:to:from:date:x-gm-gg:x-gm-message-state:from:to:cc\n :subject:date:message-id:reply-to;\n bh=+h7jpKdhCTn6mHuXqflXQE1DgwiNoIkqxn9rj7Bxf10=;\n b=NLwHcXNhuCogAF/uaK0+7ESnEOCXafAgNE3S8zZ2IaWah14PQueEDt/JI4zzydTL0p\n yWJwp/5fkyhUiPEfzCigi8UobXHgQsnlDvwHXkV7J8ECy1Vr7lEKuNaZWrxfcI5suKkO\n j2jN1TnuApEsRf9uBSTHb694mUFpyixa3DDPCqKb80l3tTMS7Qw1d0T6Ia2OnP22tvg2\n qg1uRRhAoRub0OJr7Nf9S/H41IU1Mn8u5ZHkAOawyighscrkOou4nYOTxubuRrrsXLGM\n 8Ggdfms8aFg1pz5MoFGlpr+55E6dogkPyqhnoqCyJmZy98l/NvuLiEDGCCu6yGKsXwAP\n cj0w==","X-Gm-Message-State":"AOJu0YxGd1tZXb7ZlYuZ/S11yFoQ2dPDF+tA7JJIXxOLmhxXX/NfhCqi\n CTinDm1L2t/qM5H8psNF2sy2Xog1sAGhSfo/tMGZh512hRgON2kWly3CxydIE76uQoc/5OaxauP\n p1zHgXbuoLeAizbeXBU/AOVUAAjBxQ+yFy5ggnLRn5Uw93tYGcvKEFKRWaL1wR47OVqs=","X-Gm-Gg":"AeBDieswUQ3FEABYlDqzn2ZfHWlvFGos5o1cC4oweuLF1H7wPb0PKZ60Bo2nblpvVZd\n 3nFnxvjLOgn12MHUebW9OfqGM43/q4v2/9MCqRG3Te3PCEqp2TK7Bj/ETViWv+Oa7m5JAdZswU+\n WGpPCucWMn/f5DP+AMy+6mIQxmRlkIwjr0/GBAUru0zlLPM8A1gMCvbwSWraJmsqhuSsa2zYaj+\n h5xFXWAXsCABYBT+0AbDUmjg5etuwJ4e5syLmhReqAv0SPO1HLg6s9bnnToEzUC4bAUQMX0BAu6\n vh/nkZgoHU+HU+wStobzGkl3qUOSXhq3T7QQ08YmgwJarpOY/R6+RmmEHbhZSnD73mdYnrYw64K\n anUT874oY/PaQ0K18kDeUyjs23YQoroBQ2f1h9DA=","X-Received":["by 2002:a05:600c:4688:b0:488:b187:d8ed with SMTP id\n 5b1f17b1804b1-488b187e4admr221060505e9.2.1775754660505;\n Thu, 09 Apr 2026 10:11:00 -0700 (PDT)","by 2002:a05:600c:4688:b0:488:b187:d8ed with SMTP id\n 5b1f17b1804b1-488b187e4admr221059775e9.2.1775754659919;\n Thu, 09 Apr 2026 10:10:59 -0700 (PDT)"],"Date":"Thu, 9 Apr 2026 19:10:56 +0200","From":"Juraj Marcin <jmarcin@redhat.com>","To":"Peter Xu <peterx@redhat.com>","Cc":"qemu-devel@nongnu.org,\n  \"Maciej S . Szmigiero\" <mail@maciej.szmigiero.name>, Daniel P\n\t=?utf-8?b?LiBCZXJyYW5nw6k=?= <berrange@redhat.com>,\n  Zhiyi Guo <zhguo@redhat.com>, Prasad Pandit <ppandit@redhat.com>,\n  Avihai Horon <avihaih@nvidia.com>, Kirti Wankhede <kwankhede@nvidia.com>,\n\t=?utf-8?q?C=C3=A9dric?= Le Goater <clg@redhat.com>,\n Fabiano Rosas <farosas@suse.de>,  Joao Martins <joao.m.martins@oracle.com>,\n Markus Armbruster <armbru@redhat.com>, Alex Williamson <alex@shazbot.org>,\n Halil Pasic <pasic@linux.ibm.com>,\n  Christian Borntraeger <borntraeger@linux.ibm.com>,\n Jason Herne <jjherne@linux.ibm.com>,  Eric Farman <farman@linux.ibm.com>,\n Matthew Rosato <mjrosato@linux.ibm.com>,\n  Richard Henderson <richard.henderson@linaro.org>,\n Ilya Leoshkevich <iii@linux.ibm.com>,  David Hildenbrand <david@kernel.org>,\n Cornelia Huck <cohuck@redhat.com>,  Eric Blake <eblake@redhat.com>,\n Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>,\n  John Snow <jsnow@redhat.com>","Subject":"Re: [PATCH 04/14] migration/treewide: Merge\n @state_pending_{exact|estimate} APIs","Message-ID":"<adfdUBTJweN-V-ZP@fedora>","References":"<20260408165559.157108-1-peterx@redhat.com>\n <20260408165559.157108-5-peterx@redhat.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=us-ascii","Content-Disposition":"inline","In-Reply-To":"<20260408165559.157108-5-peterx@redhat.com>","Received-SPF":"pass client-ip=170.10.133.124; envelope-from=jmarcin@redhat.com;\n helo=us-smtp-delivery-124.mimecast.com","X-Spam_score_int":"-25","X-Spam_score":"-2.6","X-Spam_bar":"--","X-Spam_report":"(-2.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.54,\n DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1,\n RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=0.001,\n RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001,\n SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no","X-Spam_action":"no action","X-BeenThere":"qemu-devel@nongnu.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"qemu development <qemu-devel.nongnu.org>","List-Unsubscribe":"<https://lists.nongnu.org/mailman/options/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>","List-Archive":"<https://lists.nongnu.org/archive/html/qemu-devel>","List-Post":"<mailto:qemu-devel@nongnu.org>","List-Help":"<mailto:qemu-devel-request@nongnu.org?subject=help>","List-Subscribe":"<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=subscribe>","Errors-To":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org","Sender":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org"}},{"id":3676623,"web_url":"http://patchwork.ozlabs.org/comment/3676623/","msgid":"<3d818473-3c5b-42fc-9cdc-e074394e0103@nvidia.com>","list_archive_url":null,"date":"2026-04-13T09:57:17","subject":"Re: [PATCH 04/14] migration/treewide: Merge\n @state_pending_{exact|estimate} APIs","submitter":{"id":84049,"url":"http://patchwork.ozlabs.org/api/people/84049/","name":"Avihai Horon","email":"avihaih@nvidia.com"},"content":"On 4/8/2026 7:55 PM, Peter Xu wrote:\n> External email: Use caution opening links or attachments\n>\n>\n> These two APIs are a slight duplication.  For example, there're a few users\n> that directly pass in the same function.\n>\n> It might also be error prone to provide two hooks, so that it's easier to\n> happen one module report different things via the two hooks.\n>\n> In reality, they should always report the same thing, only about whether we\n> should use a fast-path when the slow path might be too slow, as QEMU may\n> query these information quite frequently during migration process.\n>\n> Merge it into one API, provide a bool showing if the query is an exact\n> query or not.  No functional change intended.\n>\n> Export qemu_savevm_query_pending().  We should use the new API here\n> provided when there're new users to do the query.  This will happen very\n> soon.\n>\n> Cc: Halil Pasic <pasic@linux.ibm.com>\n> Cc: Christian Borntraeger <borntraeger@linux.ibm.com>\n> Cc: Jason Herne <jjherne@linux.ibm.com>\n> Cc: Eric Farman <farman@linux.ibm.com>\n> Cc: Matthew Rosato <mjrosato@linux.ibm.com>\n> Cc: Richard Henderson <richard.henderson@linaro.org>\n> Cc: Ilya Leoshkevich <iii@linux.ibm.com>\n> Cc: David Hildenbrand <david@kernel.org>\n> Cc: Cornelia Huck <cohuck@redhat.com>\n> Cc: Eric Blake <eblake@redhat.com>\n> Cc: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>\n> Cc: John Snow <jsnow@redhat.com>\n> Signed-off-by: Peter Xu <peterx@redhat.com>\n> ---\n>   docs/devel/migration/main.rst  |  9 ++----\n>   docs/devel/migration/vfio.rst  |  9 ++----\n>   include/migration/register.h   | 52 +++++++++++-----------------------\n>   migration/savevm.h             |  3 ++\n>   hw/s390x/s390-stattrib.c       |  9 +++---\n>   hw/vfio/migration.c            | 48 ++++++++++++++-----------------\n>   migration/block-dirty-bitmap.c | 10 +++----\n>   migration/ram.c                | 33 +++++++--------------\n>   migration/savevm.c             | 42 +++++++++++++--------------\n>   hw/vfio/trace-events           |  3 +-\n>   10 files changed, 84 insertions(+), 134 deletions(-)\n>\n> diff --git a/docs/devel/migration/main.rst b/docs/devel/migration/main.rst\n> index 234d280249..e6a6ca3681 100644\n> --- a/docs/devel/migration/main.rst\n> +++ b/docs/devel/migration/main.rst\n> @@ -515,13 +515,8 @@ An iterative device must provide:\n>     - A ``load_setup`` function that initialises the data structures on the\n>       destination.\n>\n> -  - A ``state_pending_exact`` function that indicates how much more\n> -    data we must save.  The core migration code will use this to\n> -    determine when to pause the CPUs and complete the migration.\n> -\n> -  - A ``state_pending_estimate`` function that indicates how much more\n> -    data we must save.  When the estimated amount is smaller than the\n> -    threshold, we call ``state_pending_exact``.\n> +  - A ``save_query_pending`` function that indicates how much more\n> +    data we must save.\n>\n>     - A ``save_live_iterate`` function should send a chunk of data until\n>       the point that stream bandwidth limits tell it to stop.  Each call\n> diff --git a/docs/devel/migration/vfio.rst b/docs/devel/migration/vfio.rst\n> index 0790e5031d..33768c877c 100644\n> --- a/docs/devel/migration/vfio.rst\n> +++ b/docs/devel/migration/vfio.rst\n> @@ -50,13 +50,8 @@ VFIO implements the device hooks for the iterative approach as follows:\n>   * A ``load_setup`` function that sets the VFIO device on the destination in\n>     _RESUMING state.\n>\n> -* A ``state_pending_estimate`` function that reports an estimate of the\n> -  remaining pre-copy data that the vendor driver has yet to save for the VFIO\n> -  device.\n> -\n> -* A ``state_pending_exact`` function that reads pending_bytes from the vendor\n> -  driver, which indicates the amount of data that the vendor driver has yet to\n> -  save for the VFIO device.\n> +* A ``save_query_pending`` function that reports the remaining pre-copy\n> +  data that the vendor driver has yet to save for the VFIO device.\n\nMaybe drop \"pre-copy\" since we also report stopcopy bytes?\n\n>\n>   * An ``is_active_iterate`` function that indicates ``save_live_iterate`` is\n>     active only when the VFIO device is in pre-copy states.\n> diff --git a/include/migration/register.h b/include/migration/register.h\n> index d0f37f5f43..aba3c9af2f 100644\n> --- a/include/migration/register.h\n> +++ b/include/migration/register.h\n> @@ -16,6 +16,13 @@\n>\n>   #include \"hw/core/vmstate-if.h\"\n>\n> +typedef struct MigPendingData {\n> +    /* Amount of pending bytes can be transferred in precopy or stopcopy */\n> +    uint64_t precopy_bytes;\n> +    /* Amount of pending bytes can be transferred in postcopy */\n> +    uint64_t postcopy_bytes;\n> +} MigPendingData;\n> +\n>   /**\n>    * struct SaveVMHandlers: handler structure to finely control\n>    * migration of complex subsystems and devices, such as RAM, block and\n> @@ -197,46 +204,19 @@ typedef struct SaveVMHandlers {\n>       bool (*save_postcopy_prepare)(QEMUFile *f, void *opaque, Error **errp);\n>\n>       /**\n> -     * @state_pending_estimate\n> -     *\n> -     * This estimates the remaining data to transfer\n> -     *\n> -     * Sum of @can_postcopy and @must_postcopy is the whole amount of\n> -     * pending data.\n> -     *\n> -     * @opaque: data pointer passed to register_savevm_live()\n> -     * @must_precopy: amount of data that must be migrated in precopy\n> -     *                or in stopped state, i.e. that must be migrated\n> -     *                before target start.\n> -     * @can_postcopy: amount of data that can be migrated in postcopy\n> -     *                or in stopped state, i.e. after target start.\n> -     *                Some can also be migrated during precopy (RAM).\n> -     *                Some must be migrated after source stops\n> -     *                (block-dirty-bitmap)\n> -     */\n> -    void (*state_pending_estimate)(void *opaque, uint64_t *must_precopy,\n> -                                   uint64_t *can_postcopy);\n> -\n> -    /**\n> -     * @state_pending_exact\n> -     *\n> -     * This calculates the exact remaining data to transfer\n> +     * @save_query_pending\n>        *\n> -     * Sum of @can_postcopy and @must_postcopy is the whole amount of\n> -     * pending data.\n> +     * This estimates the remaining data to transfer on the source side.\n> +     * It's highly suggested that the module should implement both fastpath\n> +     * and slowpath version of it when it can be slow (for more information\n> +     * please check pending->fastpath field).\n>        *\n>        * @opaque: data pointer passed to register_savevm_live()\n> -     * @must_precopy: amount of data that must be migrated in precopy\n> -     *                or in stopped state, i.e. that must be migrated\n> -     *                before target start.\n> -     * @can_postcopy: amount of data that can be migrated in postcopy\n> -     *                or in stopped state, i.e. after target start.\n> -     *                Some can also be migrated during precopy (RAM).\n> -     *                Some must be migrated after source stops\n> -     *                (block-dirty-bitmap)\n> +     * @pending: pointer to a MigPendingData struct\n> +     * @exact: set true for an accurate (slow) query\n>        */\n> -    void (*state_pending_exact)(void *opaque, uint64_t *must_precopy,\n> -                                uint64_t *can_postcopy);\n> +    void (*save_query_pending)(void *opaque, MigPendingData *pending,\n> +                               bool exact);\n>\n>       /**\n>        * @load_state\n> diff --git a/migration/savevm.h b/migration/savevm.h\n> index b3d1e8a13c..e4efd243f3 100644\n> --- a/migration/savevm.h\n> +++ b/migration/savevm.h\n> @@ -14,6 +14,8 @@\n>   #ifndef MIGRATION_SAVEVM_H\n>   #define MIGRATION_SAVEVM_H\n>\n> +#include \"migration/register.h\"\n> +\n>   #define QEMU_VM_FILE_MAGIC           0x5145564d\n>   #define QEMU_VM_FILE_VERSION_COMPAT  0x00000002\n>   #define QEMU_VM_FILE_VERSION         0x00000003\n> @@ -43,6 +45,7 @@ int qemu_savevm_state_iterate(QEMUFile *f, bool postcopy);\n>   void qemu_savevm_state_cleanup(void);\n>   void qemu_savevm_state_complete_postcopy(QEMUFile *f);\n>   int qemu_savevm_state_complete_precopy(MigrationState *s);\n> +void qemu_savevm_query_pending(MigPendingData *pending, bool exact);\n>   void qemu_savevm_state_pending_exact(uint64_t *must_precopy,\n>                                        uint64_t *can_postcopy);\n>   void qemu_savevm_state_pending_estimate(uint64_t *must_precopy,\n> diff --git a/hw/s390x/s390-stattrib.c b/hw/s390x/s390-stattrib.c\n> index d808ece3b9..a22469a9e9 100644\n> --- a/hw/s390x/s390-stattrib.c\n> +++ b/hw/s390x/s390-stattrib.c\n> @@ -187,15 +187,15 @@ static int cmma_save_setup(QEMUFile *f, void *opaque, Error **errp)\n>       return 0;\n>   }\n>\n> -static void cmma_state_pending(void *opaque, uint64_t *must_precopy,\n> -                               uint64_t *can_postcopy)\n> +static void cmma_state_pending(void *opaque, MigPendingData *pending,\n> +                               bool exact)\n>   {\n>       S390StAttribState *sas = S390_STATTRIB(opaque);\n>       S390StAttribClass *sac = S390_STATTRIB_GET_CLASS(sas);\n>       long long res = sac->get_dirtycount(sas);\n>\n>       if (res >= 0) {\n> -        *must_precopy += res;\n> +        pending->precopy_bytes += res;\n>       }\n>   }\n>\n> @@ -340,8 +340,7 @@ static SaveVMHandlers savevm_s390_stattrib_handlers = {\n>       .save_setup = cmma_save_setup,\n>       .save_live_iterate = cmma_save_iterate,\n>       .save_complete = cmma_save_complete,\n> -    .state_pending_exact = cmma_state_pending,\n> -    .state_pending_estimate = cmma_state_pending,\n> +    .save_query_pending = cmma_state_pending,\n>       .save_cleanup = cmma_save_cleanup,\n>       .load_state = cmma_load,\n>       .is_active = cmma_active,\n> diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c\n> index 5d5fca09bd..1e999f0040 100644\n> --- a/hw/vfio/migration.c\n> +++ b/hw/vfio/migration.c\n> @@ -571,42 +571,39 @@ static void vfio_save_cleanup(void *opaque)\n>       trace_vfio_save_cleanup(vbasedev->name);\n>   }\n>\n> -static void vfio_state_pending_estimate(void *opaque, uint64_t *must_precopy,\n> -                                        uint64_t *can_postcopy)\n> +static void vfio_state_pending_sync(VFIODevice *vbasedev)\n>   {\n> -    VFIODevice *vbasedev = opaque;\n>       VFIOMigration *migration = vbasedev->migration;\n>\n> -    if (!vfio_device_state_is_precopy(vbasedev)) {\n> -        return;\n> -    }\n> -\n> -    *must_precopy +=\n> -        migration->precopy_init_size + migration->precopy_dirty_size;\n> +    vfio_query_stop_copy_size(vbasedev);\n>\n> -    trace_vfio_state_pending_estimate(vbasedev->name, *must_precopy,\n> -                                      *can_postcopy,\n> -                                      migration->precopy_init_size,\n> -                                      migration->precopy_dirty_size);\n> +    if (vfio_device_state_is_precopy(vbasedev)) {\n> +        vfio_query_precopy_size(migration);\n> +    }\n>   }\n>\n> -static void vfio_state_pending_exact(void *opaque, uint64_t *must_precopy,\n> -                                     uint64_t *can_postcopy)\n> +static void vfio_state_pending(void *opaque, MigPendingData *pending,\n> +                               bool exact)\n>   {\n>       VFIODevice *vbasedev = opaque;\n>       VFIOMigration *migration = vbasedev->migration;\n> +    uint64_t remain;\n>\n> -    vfio_query_stop_copy_size(vbasedev);\n> -    *must_precopy += migration->stopcopy_size;\n> -\n> -    if (vfio_device_state_is_precopy(vbasedev)) {\n> -        vfio_query_precopy_size(migration);\n> +    if (exact) {\n> +        vfio_state_pending_sync(vbasedev);\n> +        remain = migration->stopcopy_size;\n> +    } else {\n> +        if (!vfio_device_state_is_precopy(vbasedev)) {\n> +            return;\n> +        }\n> +        remain = migration->precopy_init_size + migration->precopy_dirty_size;\n>       }\n>\n> -    trace_vfio_state_pending_exact(vbasedev->name, *must_precopy, *can_postcopy,\n> -                                   migration->stopcopy_size,\n> -                                   migration->precopy_init_size,\n> -                                   migration->precopy_dirty_size);\n> +    pending->precopy_bytes += remain;\n> +\n> +    trace_vfio_state_pending(vbasedev->name, migration->stopcopy_size,\n> +                             migration->precopy_init_size,\n> +                             migration->precopy_dirty_size);\n\nLet's also log \"exact\", I think it can be useful.\n\nWith this and Juraj's comment fixed:\nReviewed-by: Avihai Horon <avihaih@nvidia.com>\n\n>   }\n>\n>   static bool vfio_is_active_iterate(void *opaque)\n> @@ -851,8 +848,7 @@ static const SaveVMHandlers savevm_vfio_handlers = {\n>       .save_prepare = vfio_save_prepare,\n>       .save_setup = vfio_save_setup,\n>       .save_cleanup = vfio_save_cleanup,\n> -    .state_pending_estimate = vfio_state_pending_estimate,\n> -    .state_pending_exact = vfio_state_pending_exact,\n> +    .save_query_pending = vfio_state_pending,\n>       .is_active_iterate = vfio_is_active_iterate,\n>       .save_live_iterate = vfio_save_iterate,\n>       .save_complete = vfio_save_complete_precopy,\n> diff --git a/migration/block-dirty-bitmap.c b/migration/block-dirty-bitmap.c\n> index a061aad817..15d417013c 100644\n> --- a/migration/block-dirty-bitmap.c\n> +++ b/migration/block-dirty-bitmap.c\n> @@ -766,9 +766,8 @@ static int dirty_bitmap_save_complete(QEMUFile *f, void *opaque)\n>       return 0;\n>   }\n>\n> -static void dirty_bitmap_state_pending(void *opaque,\n> -                                       uint64_t *must_precopy,\n> -                                       uint64_t *can_postcopy)\n> +static void dirty_bitmap_state_pending(void *opaque, MigPendingData *data,\n> +                                       bool exact)\n>   {\n>       DBMSaveState *s = &((DBMState *)opaque)->save;\n>       SaveBitmapState *dbms;\n> @@ -788,7 +787,7 @@ static void dirty_bitmap_state_pending(void *opaque,\n>\n>       trace_dirty_bitmap_state_pending(pending);\n>\n> -    *can_postcopy += pending;\n> +    data->postcopy_bytes += pending;\n>   }\n>\n>   /* First occurrence of this bitmap. It should be created if doesn't exist */\n> @@ -1250,8 +1249,7 @@ static SaveVMHandlers savevm_dirty_bitmap_handlers = {\n>       .save_setup = dirty_bitmap_save_setup,\n>       .save_complete = dirty_bitmap_save_complete,\n>       .has_postcopy = dirty_bitmap_has_postcopy,\n> -    .state_pending_exact = dirty_bitmap_state_pending,\n> -    .state_pending_estimate = dirty_bitmap_state_pending,\n> +    .save_query_pending = dirty_bitmap_state_pending,\n>       .save_live_iterate = dirty_bitmap_save_iterate,\n>       .is_active_iterate = dirty_bitmap_is_active_iterate,\n>       .load_state = dirty_bitmap_load,\n> diff --git a/migration/ram.c b/migration/ram.c\n> index 979751f61b..e5b7217bf5 100644\n> --- a/migration/ram.c\n> +++ b/migration/ram.c\n> @@ -3443,30 +3443,18 @@ static int ram_save_complete(QEMUFile *f, void *opaque)\n>       return qemu_fflush(f);\n>   }\n>\n> -static void ram_state_pending_estimate(void *opaque, uint64_t *must_precopy,\n> -                                       uint64_t *can_postcopy)\n> -{\n> -    RAMState **temp = opaque;\n> -    RAMState *rs = *temp;\n> -\n> -    uint64_t remaining_size = rs->migration_dirty_pages * TARGET_PAGE_SIZE;\n> -\n> -    if (migrate_postcopy_ram()) {\n> -        /* We can do postcopy, and all the data is postcopiable */\n> -        *can_postcopy += remaining_size;\n> -    } else {\n> -        *must_precopy += remaining_size;\n> -    }\n> -}\n> -\n> -static void ram_state_pending_exact(void *opaque, uint64_t *must_precopy,\n> -                                    uint64_t *can_postcopy)\n> +static void ram_state_pending(void *opaque, MigPendingData *pending,\n> +                              bool exact)\n>   {\n>       RAMState **temp = opaque;\n>       RAMState *rs = *temp;\n>       uint64_t remaining_size;\n>\n> -    if (!migration_in_postcopy()) {\n> +    /*\n> +     * Sync is not needed either with: (1) a fast query, or (2) after\n> +     * postcopy has started (no new dirty will generate anymore).\n> +     */\n> +    if (exact && !migration_in_postcopy()) {\n>           bql_lock();\n>           WITH_RCU_READ_LOCK_GUARD() {\n>               migration_bitmap_sync_precopy(false);\n> @@ -3478,9 +3466,9 @@ static void ram_state_pending_exact(void *opaque, uint64_t *must_precopy,\n>\n>       if (migrate_postcopy_ram()) {\n>           /* We can do postcopy, and all the data is postcopiable */\n> -        *can_postcopy += remaining_size;\n> +        pending->postcopy_bytes += remaining_size;\n>       } else {\n> -        *must_precopy += remaining_size;\n> +        pending->precopy_bytes += remaining_size;\n>       }\n>   }\n>\n> @@ -4703,8 +4691,7 @@ static SaveVMHandlers savevm_ram_handlers = {\n>       .save_live_iterate = ram_save_iterate,\n>       .save_complete = ram_save_complete,\n>       .has_postcopy = ram_has_postcopy,\n> -    .state_pending_exact = ram_state_pending_exact,\n> -    .state_pending_estimate = ram_state_pending_estimate,\n> +    .save_query_pending = ram_state_pending,\n>       .load_state = ram_load,\n>       .save_cleanup = ram_save_cleanup,\n>       .load_setup = ram_load_setup,\n> diff --git a/migration/savevm.c b/migration/savevm.c\n> index dd58f2a705..392d840955 100644\n> --- a/migration/savevm.c\n> +++ b/migration/savevm.c\n> @@ -1762,46 +1762,44 @@ int qemu_savevm_state_complete_precopy(MigrationState *s)\n>       return qemu_fflush(f);\n>   }\n>\n> -/* Give an estimate of the amount left to be transferred,\n> - * the result is split into the amount for units that can and\n> - * for units that can't do postcopy.\n> - */\n> -void qemu_savevm_state_pending_estimate(uint64_t *must_precopy,\n> -                                        uint64_t *can_postcopy)\n> +void qemu_savevm_query_pending(MigPendingData *pending, bool exact)\n>   {\n>       SaveStateEntry *se;\n>\n> -    *must_precopy = 0;\n> -    *can_postcopy = 0;\n> +    pending->precopy_bytes = 0;\n> +    pending->postcopy_bytes = 0;\n>\n>       QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {\n> -        if (!se->ops || !se->ops->state_pending_estimate) {\n> +        if (!se->ops || !se->ops->save_query_pending) {\n>               continue;\n>           }\n>           if (!qemu_savevm_state_active(se)) {\n>               continue;\n>           }\n> -        se->ops->state_pending_estimate(se->opaque, must_precopy, can_postcopy);\n> +        se->ops->save_query_pending(se->opaque, pending, exact);\n>       }\n>   }\n>\n> +void qemu_savevm_state_pending_estimate(uint64_t *must_precopy,\n> +                                        uint64_t *can_postcopy)\n> +{\n> +    MigPendingData pending;\n> +\n> +    qemu_savevm_query_pending(&pending, false);\n> +\n> +    *must_precopy = pending.precopy_bytes;\n> +    *can_postcopy = pending.postcopy_bytes;\n> +}\n> +\n>   void qemu_savevm_state_pending_exact(uint64_t *must_precopy,\n>                                        uint64_t *can_postcopy)\n>   {\n> -    SaveStateEntry *se;\n> +    MigPendingData pending;\n>\n> -    *must_precopy = 0;\n> -    *can_postcopy = 0;\n> +    qemu_savevm_query_pending(&pending, true);\n>\n> -    QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {\n> -        if (!se->ops || !se->ops->state_pending_exact) {\n> -            continue;\n> -        }\n> -        if (!qemu_savevm_state_active(se)) {\n> -            continue;\n> -        }\n> -        se->ops->state_pending_exact(se->opaque, must_precopy, can_postcopy);\n> -    }\n> +    *must_precopy = pending.precopy_bytes;\n> +    *can_postcopy = pending.postcopy_bytes;\n>   }\n>\n>   void qemu_savevm_state_cleanup(void)\n> diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events\n> index 846e3625c5..7cf5a9eb2d 100644\n> --- a/hw/vfio/trace-events\n> +++ b/hw/vfio/trace-events\n> @@ -173,8 +173,7 @@ vfio_save_device_config_state(const char *name) \" (%s)\"\n>   vfio_save_iterate(const char *name, uint64_t precopy_init_size, uint64_t precopy_dirty_size) \" (%s) precopy initial size %\"PRIu64\" precopy dirty size %\"PRIu64\n>   vfio_save_iterate_start(const char *name) \" (%s)\"\n>   vfio_save_setup(const char *name, uint64_t data_buffer_size) \" (%s) data buffer size %\"PRIu64\n> -vfio_state_pending_estimate(const char *name, uint64_t precopy, uint64_t postcopy, uint64_t precopy_init_size, uint64_t precopy_dirty_size) \" (%s) precopy %\"PRIu64\" postcopy %\"PRIu64\" precopy initial size %\"PRIu64\" precopy dirty size %\"PRIu64\n> -vfio_state_pending_exact(const char *name, uint64_t precopy, uint64_t postcopy, uint64_t stopcopy_size, uint64_t precopy_init_size, uint64_t precopy_dirty_size) \" (%s) precopy %\"PRIu64\" postcopy %\"PRIu64\" stopcopy size %\"PRIu64\" precopy initial size %\"PRIu64\" precopy dirty size %\"PRIu64\n> +vfio_state_pending(const char *name, uint64_t stopcopy_size, uint64_t precopy_init_size, uint64_t precopy_dirty_size) \" (%s) stopcopy size %\"PRIu64\" precopy initial size %\"PRIu64\" precopy dirty size %\"PRIu64\n>   vfio_vmstate_change(const char *name, int running, const char *reason, const char *dev_state) \" (%s) running %d reason %s device state %s\"\n>   vfio_vmstate_change_prepare(const char *name, int running, const char *reason, const char *dev_state) \" (%s) running %d reason %s device state %s\"\n>\n> --\n> 2.53.0\n>","headers":{"Return-Path":"<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=Nvidia.com header.i=@Nvidia.com header.a=rsa-sha256\n header.s=selector2 header.b=C0PUkdYK;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists1p.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)","dkim=none (message not signed)\n header.d=none;dmarc=none action=none header.from=nvidia.com;"],"Received":["from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fvNCX4gRRz1yDF\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 13 Apr 2026 19:58:47 +1000 (AEST)","from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists1p.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1wCE3Y-00032m-UF; Mon, 13 Apr 2026 05:58:12 -0400","from eggs.gnu.org ([2001:470:142:3::10])\n by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <avihaih@nvidia.com>)\n id 1wCE3T-00032S-Pg\n for qemu-devel@nongnu.org; Mon, 13 Apr 2026 05:58:08 -0400","from\n mail-northcentralusazlp170120005.outbound.protection.outlook.com\n ([2a01:111:f403:c105::5] helo=CH5PR02CU005.outbound.protection.outlook.com)\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <avihaih@nvidia.com>)\n id 1wCE3R-0002uT-0n\n for qemu-devel@nongnu.org; Mon, 13 Apr 2026 05:58:07 -0400","from BL1PR12MB5063.namprd12.prod.outlook.com (2603:10b6:208:31a::11)\n by SA1PR12MB5670.namprd12.prod.outlook.com (2603:10b6:806:239::9)\n with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9818.20; Mon, 13 Apr\n 2026 09:57:24 +0000","from BL1PR12MB5063.namprd12.prod.outlook.com\n ([fe80::a0c2:5681:4aca:90da]) by BL1PR12MB5063.namprd12.prod.outlook.com\n ([fe80::a0c2:5681:4aca:90da%7]) with mapi id 15.20.9818.014; Mon, 13 Apr 2026\n 09:57:24 +0000"],"ARC-Seal":"i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none;\n b=anVJlQ4S4YrhdrvBgkrVW9Cl4udGSTePddxnj1X0yXSlN4biz2+/5Nytm8GHRbpmKkjaVIqED6W7BatPfK6wyo6Ivb/OCsY/I3YAnQEIL+X8BauOrIpPRusbuTvqWsadcUHS5aD39H2ETGx4s1Yb2gI4F7cyLM//Ca+SgLnH8uSdbHG1LEhPFiQA5PUgItdyfE7CAviuwq+s08NaV1xRpmDpjXmkIrWOCOO6T9apEpwWVb4dxsrhUqUhEJziOxEsp5rQpNBmGeLbg/31Z3Njf/wgjZd4glZaDuyFqPu9MJpSclmwummMXXghMPCx1SV7hAtpqhPr45oiYrhmz4ECvg==","ARC-Message-Signature":"i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;\n s=arcselector10001;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1;\n bh=NLXfQnO1TOsGxruuvPmc5b1Mm6MDkR5XLaNsyYLzNOM=;\n b=NhJGIewCcEl5Qu+IUthoWqnzd2HPi9vENd0XnGyu6onpCmwPhjQEAa1tWxiQpQ5xTUQCp0gmS1izctBVOUfkcO/3zSUksP5EoOQjAtEcIhqmoCfNJ+NhOmYY9es48djNB8YiGi94s+tazVZgTXcsiimx2UXtMODijGMoRLE3gEXQc6klWBz5ILOwAQVtphanpNBaLO+bHQOIlFy3NhU6QDoIDZuqUyp3gQNDh28J2n6Lewl04pGBTGv2FJxwRsCNSfRhw6ED3Og+m85+5AgceYGlWEgXAWiC3T+qv+LTj1WgnZ0+nmpZXUSz5KEn6ElVqLxF1kF8jGYuvUMyJLUDKQ==","ARC-Authentication-Results":"i=1; mx.microsoft.com 1; spf=pass\n smtp.mailfrom=nvidia.com; dmarc=pass action=none header.from=nvidia.com;\n dkim=pass header.d=nvidia.com; arc=none","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com;\n s=selector2;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;\n bh=NLXfQnO1TOsGxruuvPmc5b1Mm6MDkR5XLaNsyYLzNOM=;\n b=C0PUkdYKKv2Jk25oTTM4+1fyCS64LO7xS9rJD7bhfM8BuzIk846/+4/YUQcihaaVbkm0tLQqrsB4zRa8r6Pu3UCBFkVrtHy/6acSxb4tLVN362AW5IMXJ0Aonlp6XQfOjp2LjoadXedXpBVxSIy2Os+9wyI92IDoRAAUfmWFfl1SdBrrHWhAMFyRLWlQ3SJwp1+iiTztu/qS4g2jtC51I/v0UPI3wU3adnjB5W8ZkcHuh3Q7YW8wE2lM7JNB+MCgzcyHbm/uv8AcCTuEDn7XC5CJEyi3raFkexQ8mPi5Npf/gw4RQEQvTXOwAa8AW+2FSBus+VpzQ/TD/xgEoI2mNg==","Message-ID":"<3d818473-3c5b-42fc-9cdc-e074394e0103@nvidia.com>","Date":"Mon, 13 Apr 2026 12:57:17 +0300","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH 04/14] migration/treewide: Merge\n @state_pending_{exact|estimate} APIs","To":"Peter Xu <peterx@redhat.com>, qemu-devel@nongnu.org","Cc":"\"Maciej S . Szmigiero\" <mail@maciej.szmigiero.name>, =?utf-8?q?Daniel_P_?=\n\t=?utf-8?q?=2E_Berrang=C3=A9?= <berrange@redhat.com>,\n Zhiyi Guo <zhguo@redhat.com>, Juraj Marcin <jmarcin@redhat.com>,\n Prasad Pandit <ppandit@redhat.com>, Kirti Wankhede <kwankhede@nvidia.com>,\n\t=?utf-8?q?C=C3=A9dric_Le_Goater?= <clg@redhat.com>,\n Fabiano Rosas <farosas@suse.de>, Joao Martins <joao.m.martins@oracle.com>,\n Markus Armbruster <armbru@redhat.com>, Alex Williamson <alex@shazbot.org>,\n Halil Pasic <pasic@linux.ibm.com>,\n Christian Borntraeger <borntraeger@linux.ibm.com>,\n Jason Herne <jjherne@linux.ibm.com>, Eric Farman <farman@linux.ibm.com>,\n Matthew Rosato <mjrosato@linux.ibm.com>,\n Richard Henderson <richard.henderson@linaro.org>,\n Ilya Leoshkevich <iii@linux.ibm.com>, David Hildenbrand <david@kernel.org>,\n Cornelia Huck <cohuck@redhat.com>, Eric Blake <eblake@redhat.com>,\n Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>,\n John Snow <jsnow@redhat.com>","References":"<20260408165559.157108-1-peterx@redhat.com>\n <20260408165559.157108-5-peterx@redhat.com>","Content-Language":"en-US","From":"Avihai Horon <avihaih@nvidia.com>","In-Reply-To":"<20260408165559.157108-5-peterx@redhat.com>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"7bit","X-ClientProxiedBy":"TL2P290CA0028.ISRP290.PROD.OUTLOOK.COM\n (2603:1096:950:3::10) To BL1PR12MB5063.namprd12.prod.outlook.com\n (2603:10b6:208:31a::11)","MIME-Version":"1.0","X-MS-PublicTrafficType":"Email","X-MS-TrafficTypeDiagnostic":"BL1PR12MB5063:EE_|SA1PR12MB5670:EE_","X-MS-Office365-Filtering-Correlation-Id":"8ab2e247-0766-4d2b-287e-08de99430fad","X-MS-Exchange-SenderADCheck":"1","X-MS-Exchange-AntiSpam-Relay":"0","X-Microsoft-Antispam":"BCL:0;\n ARA:13230040|376014|7416014|1800799024|366016|56012099003|18002099003|22082099003;","X-Microsoft-Antispam-Message-Info":"\n iekLOHZvLYmP2nrSyOUkD79FDP5GXE1cYOmNxjAlvbYHWS7mOziIfEg1BNF4lBQieYKpcMjfphUVJSORalxRbmoP/pZ0ps3eihoWl18VxubgwW0CI6NE/3DbV3U94n0EF9PSCgVOlqXmoBc0TnX1uNpztE75Y+wYsFzC468Bf6G/PAXkXDig4xKLtxxklL0z0VrcnvVMVhmXJtDXe38qe8p+Y7B0UEkrHlHXJWw2oaFcVVA9JLG7pvgzT8FQrxwr7uewbbdAKyo0/kfx13N/l+rSBDL2JScC8xo25eUravChNlu8T5dG7ZN0+/39D5PWTeTSc3+u1pPK7UBizuvL9i2ji4MExztTr7dZ43QbOHTePK00WGDDtOozEfrmBAkapNnuf/RttyLAdkZ1GpJb43w7KChHQncQYOxv8vV1c9JpsLQUXRu1kLlHAw1XHdNg2Vud/rBA/hBGTmhaZBSVDaI4yDr1uOU0cJZi+4F0a35gjp+fdUCw1uYmiVnsnbDTiE1NEUoax3wvGQl/5Gbg7DxuOdheTnDUnkD+w3u+gYN5B8NLP2mdkVSgDeWjDNRxx7Q2wpl0KfTT3SQ3vAmt31HMAFPJETF7lwcJ7fU7whmAou9O3U94n6l61Hf1n6Icvl46+uVfa3tMzpfdkFSVerzjr0c/s0jJy/MDr1pikCy4VeukJZtb+oRR9K/cLVdwexGzEBHYJRLecZ3tBnPqmcYZIq2mju6xweTdF6OX4Ek=","X-Forefront-Antispam-Report":"CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:;\n IPV:NLI; SFV:NSPM; H:BL1PR12MB5063.namprd12.prod.outlook.com; PTR:; CAT:NONE;\n SFS:(13230040)(376014)(7416014)(1800799024)(366016)(56012099003)(18002099003)(22082099003);\n DIR:OUT; SFP:1101;","X-MS-Exchange-AntiSpam-MessageData-ChunkCount":"1","X-MS-Exchange-AntiSpam-MessageData-0":"=?utf-8?q?BhwpkCZXqsZSqsqY6sHnXO0Vb5OR?=\n\t=?utf-8?q?O4bRPGz/8L2NoRk7HUxx9NE2+uDgrTnq/LzAuoHr1qrqlkDobvBdrhxzKc/2mXsd7?=\n\t=?utf-8?q?GkvM1edNml2PqMneayGvnyXaVbC92msyrZAg8W0lNbMaxMerSs6X2RgCiQX3v3Nue?=\n\t=?utf-8?q?+z7m6E0Z5nn9ps++683Omvk/GgKeo/tpImJqt5m5dj8w7p6d0umQbPFz7uvUfkZxE?=\n\t=?utf-8?q?6917IjZyk4iN52PncS5/Cn7U+t8CjEh06pnhDbD/0h9L7qW2gc+5WTiz10EC5TEJs?=\n\t=?utf-8?q?m9BsNiXZrGHVPsPmYqxJqgG0NfY4BZDTV+GrVtDbZXZBNO1QIVuELl4Vlpkgtdity?=\n\t=?utf-8?q?PqpIsXWs3LG3crOeQqnRghE3dxVC5QubbfHMqSJEEtip203IsU17Gk0zS7HF8ZyE2?=\n\t=?utf-8?q?fUJfcNZeJiiQKL5/bRxCtmxfVPA4a1QRSRxAOu+5d5EZW7Sy9JixuxpurO9evy1y+?=\n\t=?utf-8?q?tLLKK8jfuYafIz5OrqksDdoXqMFPQOOt/Qv/GyYmMewMG6H3MQtwJH5gZYGsYLNAX?=\n\t=?utf-8?q?8lgH+3uoAGk6jZFhP8A5K2TaGFqs2ivIhM71Simr0jBt3H67QLOlGRNjOmeRdUjYj?=\n\t=?utf-8?q?yWQPjbR22urOx1O7blXkz7HetMnXwaAo69V9D5JiAZaBRd0llV4zIo6Fp18rVXFEZ?=\n\t=?utf-8?q?FzAKB7PG6+AQmzbw8AFg+pqKZuHwXWFGffPtqi0+pRgHc9rue6eAF9QyGgBHqKj02?=\n\t=?utf-8?q?qD4RWoq0OQ7Eplw/zVDe8Ao/91CU5hHNdJx1KsSC8FvojgZ+pLb16Qspa2EM0T5Ck?=\n\t=?utf-8?q?2gwL0nZtfopSPpUCXtlSG70ClVBOf81AVcaM+CWV7IQVjt69Q7covRM6wRSPhfOC2?=\n\t=?utf-8?q?YMmvazmgeNUSaugq+nX3b9KBTvLhhjpuivl2CNbE6Kfv6H1Ytljij2O6sp8ZFhC8E?=\n\t=?utf-8?q?fWJfl0Gz2SV9iEWe3vdNCVVH7CyIEM/XKyDgb/cJfmyuODOXVaCd9DQnmSKMxjly/?=\n\t=?utf-8?q?iKO0TWkq3Odzj6cqxpm7b0k0DTEyXpCtBlXShdoeszWn0KxC+fHlTP6z9sHvCj5YY?=\n\t=?utf-8?q?27/qeNJfa+nUz8lZ+uyVzgZfjp/S9ZoBjoCzP1AqU5Mf73oMxtXjj3CKvp8VZo+t5?=\n\t=?utf-8?q?XiqGiLmhQgN0UcrYE1FPuo1VOFMcpoArIyH6T7AnCf6nGF9dLsfWs7CchyzhuBZIy?=\n\t=?utf-8?q?Xv2We4qW5aH3HhygFcE4/hS9Tf377UNXGDWOo3+bl24EXZtxBJ2wRF0x79Ahpn2Ki?=\n\t=?utf-8?q?JYDsidGkel4W5L/O/NEzvKs9pIyoounBjRzh/qpMHQUgwiWKBilzlZ0VapEvxERZi?=\n\t=?utf-8?q?XKsY2ryzbLAkcrhTeTNx/yNohdkc+h4/7COL1AnoUyAYNYwDokHwHxy7FAGhnJpJq?=\n\t=?utf-8?q?fW/sAuD3Iv+6Mx8CUAKfKgSoi0h15EBy/4MQcMa26V0wj20rKs8L9+aP5NkICUC0c?=\n\t=?utf-8?q?DmtLJlA2GuduAVqcW33tKDSFJM+i+z3AO4FJZ5Q/7fGPdUy/VsNiIGHXgrNiqRQ1j?=\n\t=?utf-8?q?HLgiGY3oO3yiQqfyErUZs6u8VBMoDN7Ga2BZaa7X+ywARxgSk4ZmNjTStx45rXJtR?=\n\t=?utf-8?q?59k/g6aDXu6LlG9dVemGWEuHq0MlS3btxm84hR+QDIsmaznR6OCIWiVpUomN1iGpC?=\n\t=?utf-8?q?CCMoY7BDTieUkyfWuyW9MxiKDCEG5ui+lLRvODKademxsQeDXaR0CEbJ3X1M2iOYI?=\n\t=?utf-8?q?wcnZjMpfBWqCRDFXyUg7au5Vhy2vueGA=3D=3D?=","X-OriginatorOrg":"Nvidia.com","X-MS-Exchange-CrossTenant-Network-Message-Id":"\n 8ab2e247-0766-4d2b-287e-08de99430fad","X-MS-Exchange-CrossTenant-AuthSource":"BL1PR12MB5063.namprd12.prod.outlook.com","X-MS-Exchange-CrossTenant-AuthAs":"Internal","X-MS-Exchange-CrossTenant-OriginalArrivalTime":"13 Apr 2026 09:57:24.2589 (UTC)","X-MS-Exchange-CrossTenant-FromEntityHeader":"Hosted","X-MS-Exchange-CrossTenant-Id":"43083d15-7273-40c1-b7db-39efd9ccc17a","X-MS-Exchange-CrossTenant-MailboxType":"HOSTED","X-MS-Exchange-CrossTenant-UserPrincipalName":"\n gRotXjhxVbC6//Z/+Ryj21XXjjYHQsgzE6QrW4RtnUvDceqTzxRcQF01lznEuW2+jev8YQJzFr96FJEPcohfXw==","X-MS-Exchange-Transport-CrossTenantHeadersStamped":"SA1PR12MB5670","Received-SPF":"permerror client-ip=2a01:111:f403:c105::5;\n envelope-from=avihaih@nvidia.com;\n helo=CH5PR02CU005.outbound.protection.outlook.com","X-Spam_score_int":"-15","X-Spam_score":"-1.6","X-Spam_bar":"-","X-Spam_report":"(-1.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.54,\n DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1,\n FORGED_SPF_HELO=1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_PASS=-0.001,\n SPF_NONE=0.001 autolearn=no autolearn_force=no","X-Spam_action":"no action","X-BeenThere":"qemu-devel@nongnu.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"qemu development <qemu-devel.nongnu.org>","List-Unsubscribe":"<https://lists.nongnu.org/mailman/options/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>","List-Archive":"<https://lists.nongnu.org/archive/html/qemu-devel>","List-Post":"<mailto:qemu-devel@nongnu.org>","List-Help":"<mailto:qemu-devel-request@nongnu.org?subject=help>","List-Subscribe":"<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=subscribe>","Errors-To":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org","Sender":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org"}}]