Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.0/patches/2221047/?format=api
{ "id": 2221047, "url": "http://patchwork.ozlabs.org/api/1.0/patches/2221047/?format=api", "project": { "id": 14, "url": "http://patchwork.ozlabs.org/api/1.0/projects/14/?format=api", "name": "QEMU Development", "link_name": "qemu-devel", "list_id": "qemu-devel.nongnu.org", "list_email": "qemu-devel@nongnu.org", "web_url": "", "scm_url": "", "webscm_url": "" }, "msgid": "<20260408165559.157108-5-peterx@redhat.com>", "date": "2026-04-08T16:55:48", "name": "[04/14] migration/treewide: Merge @state_pending_{exact|estimate} APIs", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "6bcc4d8c9c741376fc869c30d276a905b81d7779", "submitter": { "id": 67717, "url": "http://patchwork.ozlabs.org/api/1.0/people/67717/?format=api", "name": "Peter Xu", "email": "peterx@redhat.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260408165559.157108-5-peterx@redhat.com/mbox/", "series": [ { "id": 499176, "url": "http://patchwork.ozlabs.org/api/1.0/series/499176/?format=api", "date": "2026-04-08T16:55:55", "name": "migration/vfio: Fix a few issues on API misuse or statistic reports", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/499176/mbox/" } ], "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2221047/checks/", "tags": {}, "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=Aw/S1dKn;\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=JM8sXfXE;\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 (unknown [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 4frWs03TdDz1yD6\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 09 Apr 2026 04:32:52 +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 1wAXh8-0007vA-Ie; Wed, 08 Apr 2026 14:32:06 -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 <peterx@redhat.com>) id 1wAXh6-0007go-Vv\n for qemu-devel@nongnu.org; Wed, 08 Apr 2026 14:32:05 -0400", "from us-smtp-delivery-124.mimecast.com ([170.10.129.124])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <peterx@redhat.com>) id 1wAWCI-00027d-W2\n for qemu-devel@nongnu.org; Wed, 08 Apr 2026 12:56:13 -0400", "from mail-qt1-f198.google.com (mail-qt1-f198.google.com\n [209.85.160.198]) by relay.mimecast.com with ESMTP with STARTTLS\n (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n us-mta-659-Dx_eNlwUN92jTqmh11fxEQ-1; Wed, 08 Apr 2026 12:56:09 -0400", "by mail-qt1-f198.google.com with SMTP id\n d75a77b69052e-50b3544bc7bso1160221cf.2\n for <qemu-devel@nongnu.org>; Wed, 08 Apr 2026 09:56:09 -0700 (PDT)", "from x1.com ([142.189.10.167]) by smtp.gmail.com with ESMTPSA id\n d75a77b69052e-50d712c2617sm130491901cf.31.2026.04.08.09.56.05\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Wed, 08 Apr 2026 09:56:06 -0700 (PDT)" ], "DKIM-Signature": [ "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1775667370;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:\n content-transfer-encoding:content-transfer-encoding:\n in-reply-to:in-reply-to:references:references;\n bh=WOqCyr+uacNL0UIuIW1odLrqvT874GQkA9dQ0lHxz1Q=;\n b=Aw/S1dKnUrFWx+UiYbnxAeheMetBnQVwXJQQaSijhjsHp/l62FUeB/EbdCvQGTBpTqsRMb\n uCd5RAXKH3jdHYYLvhfp1b5inBp8lYzG8xPl2ku6nbUdxZPnSwEZBoGWLPFAgq7zei37HD\n FnrtVqvz9yNf6HdN9y8aJc+KUNhn4T0=", "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=redhat.com; s=google; t=1775667368; x=1776272168; darn=nongnu.org;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n :message-id:reply-to;\n bh=WOqCyr+uacNL0UIuIW1odLrqvT874GQkA9dQ0lHxz1Q=;\n b=JM8sXfXEKR5ylJPHZgXzgv7Hui7NhlKHm4ZL+hMQpapy79I/mqli5tX1Y5sYwlo6VZ\n ZbE6reqyU5L3kQA2jzDfCbMXgy1uOwXmYIvPM374eL1BabR+Jvd+0BS1Ii7exedmOpO+\n QDhfIlU1UioIxa8nP7hanqEwe8T55iLKlAhzZ0zKQHGDSJ7waqWeP05A0JBt0bTnt2rP\n 5RKMQgrbkC0mP4AWlSuGOXjEvkpVJ98CQQlS1OVqx77DLptolOmaHYA96GcSAWTjzTVF\n 0eR76TgSHi/kycRi30YSSs99HZNPJmb7I5siWWdWgcgoUst6mhcazdV4f01gfFgwjXQm\n zD0w==" ], "X-MC-Unique": "Dx_eNlwUN92jTqmh11fxEQ-1", "X-Mimecast-MFC-AGG-ID": "Dx_eNlwUN92jTqmh11fxEQ_1775667369", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1775667368; x=1776272168;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n :to:cc:subject:date:message-id:reply-to;\n bh=WOqCyr+uacNL0UIuIW1odLrqvT874GQkA9dQ0lHxz1Q=;\n b=nk5d4BG1zwYPNpfEHj9Yuzp0dKC1qPNoEbmsyk5D30tmKsOoxCwUhxaKGbn0wAY8lG\n LZJQyJxh324Izr9hD6CDvb9V1RF3RPNvS6Rs4lWoeiYj6nGZ0L5gqHplqXzVzn+QHKba\n VJbVfoYCmCe/p9EgE+TV8AnHB9GfL6tT0qPukBeH0eSfiai4dzR7QytoJWZYPe9xfqMr\n 4ewZpunivWX7NtcNiYDEvmuxd1gx0ba3pLQ5JMBlPFc0X9+fd9Gk0ZCt70nhh/4CTMvb\n yF64QrqD1RY1AJUJfXhvsg26d1jI68xbp4UVK9MZYnBiZJlP5uD0e1Q0WXf1O7EIDbME\n RNkQ==", "X-Gm-Message-State": "AOJu0Yxdcm/fYOjab5PUNAUO0M997Du9p9ABdTq5SCqCXbbQJ4V4/hcz\n bpNj2v0ZmUhP4ckNe/PCb4ScDt5n3XrQVOMgChEYJ4l8UZE9+DRMgLea946Rex6IcKYvQsuK5Jv\n 0zaBqxH+Y/RG7ty/ijNfmLtuQieX3mYWhamOfYmXBUYfiOMUpL6fz0Z5Vf3KOa/YdYcxjdzVWs5\n KlTg73/4WmIBIctp/vihYLstVw2fW9b5/IusaAqQ==", "X-Gm-Gg": "AeBDietjPSFOMx+qGS/OKfVL619hLWYS6gZkOl/xbyxQwbJE0ttvuspJMjWCXFJV6yD\n 9otfNcEEsj7krcuWE/2+TFQsAjabohH7mljd4Q4pW9Na3xZCxtCgDxXCvuRX2UrtNcH6xS8qWN5\n 0il6ks5ZuCQdr93G+kzzZsbpYCvHPgsElSSfhn7WYw5LnYNfEblMJ0+b6snrkbMUNQkX36cciLC\n A0rw50U9BaLvEE1kXXGI066/NUrfz9eAajVXTHbM+14tlu9PBpfuQ23+DN2aBNnZUPown+wTw9N\n yeCJKsqn687mjc/0zpjZu06/Xr3Jwt3z04xdTbHR6hYN1LMv1olNsvWC98W07gGbgrLnE08g4bn\n HFCgHqWpxqpU5LP4XZ4tM4xP77aOVnDYxdrYjLS13GvtT", "X-Received": [ "by 2002:a05:622a:5a17:b0:509:372e:35f5 with SMTP id\n d75a77b69052e-50d62b705fcmr315555001cf.55.1775667368206;\n Wed, 08 Apr 2026 09:56:08 -0700 (PDT)", "by 2002:a05:622a:5a17:b0:509:372e:35f5 with SMTP id\n d75a77b69052e-50d62b705fcmr315553971cf.55.1775667367348;\n Wed, 08 Apr 2026 09:56:07 -0700 (PDT)" ], "From": "Peter Xu <peterx@redhat.com>", "To": "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 Peter Xu <peterx@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": "[PATCH 04/14] migration/treewide: Merge\n @state_pending_{exact|estimate} APIs", "Date": "Wed, 8 Apr 2026 12:55:48 -0400", "Message-ID": "<20260408165559.157108-5-peterx@redhat.com>", "X-Mailer": "git-send-email 2.53.0", "In-Reply-To": "<20260408165559.157108-1-peterx@redhat.com>", "References": "<20260408165559.157108-1-peterx@redhat.com>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "Received-SPF": "pass client-ip=170.10.129.124; envelope-from=peterx@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_H4=0.001, RCVD_IN_MSPIKE_WL=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" }, "content": "These two APIs are a slight duplication. For example, there're a few users\nthat directly pass in the same function.\n\nIt might also be error prone to provide two hooks, so that it's easier to\nhappen one module report different things via the two hooks.\n\nIn reality, they should always report the same thing, only about whether we\nshould use a fast-path when the slow path might be too slow, as QEMU may\nquery these information quite frequently during migration process.\n\nMerge it into one API, provide a bool showing if the query is an exact\nquery or not. No functional change intended.\n\nExport qemu_savevm_query_pending(). We should use the new API here\nprovided when there're new users to do the query. This will happen very\nsoon.\n\nCc: Halil Pasic <pasic@linux.ibm.com>\nCc: Christian Borntraeger <borntraeger@linux.ibm.com>\nCc: Jason Herne <jjherne@linux.ibm.com>\nCc: Eric Farman <farman@linux.ibm.com>\nCc: Matthew Rosato <mjrosato@linux.ibm.com>\nCc: Richard Henderson <richard.henderson@linaro.org>\nCc: Ilya Leoshkevich <iii@linux.ibm.com>\nCc: David Hildenbrand <david@kernel.org>\nCc: Cornelia Huck <cohuck@redhat.com>\nCc: Eric Blake <eblake@redhat.com>\nCc: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>\nCc: John Snow <jsnow@redhat.com>\nSigned-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(-)", "diff": "diff --git a/docs/devel/migration/main.rst b/docs/devel/migration/main.rst\nindex 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\ndiff --git a/docs/devel/migration/vfio.rst b/docs/devel/migration/vfio.rst\nindex 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.\ndiff --git a/include/migration/register.h b/include/migration/register.h\nindex 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\ndiff --git a/migration/savevm.h b/migration/savevm.h\nindex 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,\ndiff --git a/hw/s390x/s390-stattrib.c b/hw/s390x/s390-stattrib.c\nindex 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,\ndiff --git a/hw/vfio/migration.c b/hw/vfio/migration.c\nindex 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,\ndiff --git a/migration/block-dirty-bitmap.c b/migration/block-dirty-bitmap.c\nindex 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,\ndiff --git a/migration/ram.c b/migration/ram.c\nindex 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,\ndiff --git a/migration/savevm.c b/migration/savevm.c\nindex 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)\ndiff --git a/hw/vfio/trace-events b/hw/vfio/trace-events\nindex 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", "prefixes": [ "04/14" ] }