On Sun, Aug 16, 2026 at 11:16:20PM +0530, Aadeshveer Singh wrote:
> This series implements a "fast snapshot load" mechanism to
> significantly reduce the perceived resume time of a VM from a snapshot
> file.

This series breaks Windows builds... we'll need three fixups into three
patches to fix it.  Attached at the end.

For Aadeshveer: in the future you can check Windows build of your own
patches locally by running this:

  $ make docker-test-build@fedora-win64-cross

I do hit Rust build failures nowadays with Windows, though, so you may need
this if you have enabled rust builds instead (I also normally use J=N for
concurrency):

  $ J=8 EXTRA_CONFIGURE_OPTS=--disable-rust make 
docker-test-build@fedora-win64-cross

For Fabiano: if you want, you can also directly pick up the relevant
patches I queued in my -next branch, or squash the fixups attached, or pick
your own fix. I'll leave that to you to decide.

  https://gitlab.com/peterx/qemu/-/tree/next

Thanks,

===8<===



>From 572b0f8b611e430e5ed8651d99851975878624c7 Mon Sep 17 00:00:00 2001
From: Peter Xu <[email protected]>
Date: Tue, 18 Aug 2026 16:38:08 -0400
Subject: [PATCH 1/3] fixup! migration: Propagate error in postcopy setup
 functions

Signed-off-by: Peter Xu <[email protected]>
---
 migration/postcopy-ram.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c
index 81d06917fe..3c85fa1b19 100644
--- a/migration/postcopy-ram.c
+++ b/migration/postcopy-ram.c
@@ -1906,7 +1906,7 @@ int postcopy_request_shared_page(struct PostCopyFD *pcfd, 
RAMBlock *rb,
     g_assert_not_reached();
 }
 
-int postcopy_ram_incoming_setup(MigrationIncomingState *mis)
+int postcopy_ram_incoming_setup(MigrationIncomingState *mis, Error **errp)
 {
     g_assert_not_reached();
 }
-- 
2.54.0




>From 4273cc6ed223de1781513af9a62c1672c3f5591b Mon Sep 17 00:00:00 2001
From: Peter Xu <[email protected]>
Date: Wed, 19 Aug 2026 10:30:35 -0400
Subject: [PATCH 2/3] fixup! migration: Extract blocktime marking helper

Signed-off-by: Peter Xu <[email protected]>
---
 migration/postcopy-ram.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c
index 3c85fa1b19..fdc65c3545 100644
--- a/migration/postcopy-ram.c
+++ b/migration/postcopy-ram.c
@@ -1934,6 +1934,14 @@ void mark_postcopy_blocktime_begin(uintptr_t addr, 
uint32_t ptid,
                                    RAMBlock *rb)
 {
 }
+
+bool try_mark_postcopy_blocktime_begin(MigrationIncomingState *mis,
+                                       RAMBlock *rb, ram_addr_t start,
+                                       uint64_t haddr, uint32_t tid)
+{
+    g_assert_not_reached();
+    return false;
+}
 #endif
 
 /* ------------------------------------------------------------------------- */
-- 
2.54.0



>From d2d397de73fe39b424b2871fe4ba0df7937cc680 Mon Sep 17 00:00:00 2001
From: Peter Xu <[email protected]>
Date: Tue, 18 Aug 2026 16:43:29 -0400
Subject: [PATCH 3/3] fixup! migration: add eager load thread and setup for
 fast snapshot load

Signed-off-by: Peter Xu <[email protected]>
---
 migration/postcopy-ram.c | 135 ++++++++++++++++++++-------------------
 1 file changed, 71 insertions(+), 64 deletions(-)

diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c
index fdc65c3545..885ab58fca 100644
--- a/migration/postcopy-ram.c
+++ b/migration/postcopy-ram.c
@@ -39,6 +39,8 @@
 #include "qemu/mmap-alloc.h"
 #include "options.h"
 
+static void postcopy_incoming_complete_bh(void *opaque);
+
 /* Arbitrary limit on size of each discard command,
  * keeps them around ~200 bytes
  */
@@ -1872,6 +1874,70 @@ int postcopy_place_page_zero(MigrationIncomingState 
*mis, void *host,
     }
 }
 
+/*
+ * Called by postcopy_ram_eager_load_thread over all blocks to load in all the
+ * pending pages of given ram block
+ */
+static int ram_block_load_eager(RAMBlock *rb, void *opaque)
+{
+    MigrationIncomingState *mis = migration_incoming_get_current();
+    MigrationState *s = migrate_get_current();
+    Error *errp = NULL;
+    void *host = qemu_ram_get_host_addr(rb);
+    void *target;
+
+    for (ram_addr_t page_loc = 0; page_loc < rb->used_length;
+         page_loc += qemu_ram_pagesize(rb)) {
+        target = (uint8_t *)host + page_loc;
+        if (!postcopy_mapped_ram_load_page(mis, rb, page_loc, (uint64_t)target,
+                                           RAM_CHANNEL_PRECOPY, &errp)) {
+            migrate_error_propagate(s, errp);
+            return -1;
+        }
+    }
+    return 0;
+}
+
+/*
+ * Used by fast snapshot load to eagerly load in all pages of RAM and schedule
+ * cleanup after entire RAM is loaded
+ */
+static void *postcopy_ram_eager_load_thread(void *opaque)
+{
+    MigrationIncomingState *mis = opaque;
+    MigrationStatus next_state;
+
+    trace_postcopy_ram_eager_load_thread_entry();
+    rcu_register_thread();
+    qemu_event_set(&mis->thread_sync_event);
+
+    if (foreach_not_ignored_block(ram_block_load_eager, NULL)) {
+        next_state = MIGRATION_STATUS_FAILED;
+    } else {
+        next_state = MIGRATION_STATUS_COMPLETED;
+    }
+    migrate_set_state(&mis->state, MIGRATION_STATUS_POSTCOPY_ACTIVE,
+                      next_state);
+
+    postcopy_state_set(POSTCOPY_INCOMING_END);
+    migration_bh_schedule(postcopy_incoming_complete_bh, mis);
+
+    rcu_unregister_thread();
+    trace_postcopy_ram_eager_load_thread_exit();
+    return NULL;
+}
+
+/*
+ * Create thread for eager loading in fast snapshot load case
+ */
+void postcopy_ram_eager_load_setup(MigrationIncomingState *mis)
+{
+    postcopy_thread_create(
+        mis, &mis->eager_load_thread, MIGRATION_THREAD_DST_SNAPSHOT_LOAD,
+        postcopy_ram_eager_load_thread, QEMU_THREAD_JOINABLE);
+    mis->have_eager_load_thread = true;
+}
+
 #else
 /* No target OS support, stubs just fail */
 void fill_destination_postcopy_migration_info(MigrationInfo *info)
@@ -1942,6 +2008,11 @@ bool 
try_mark_postcopy_blocktime_begin(MigrationIncomingState *mis,
     g_assert_not_reached();
     return false;
 }
+
+void postcopy_ram_eager_load_setup(MigrationIncomingState *mis)
+{
+    g_assert_not_reached();
+}
 #endif
 
 /* ------------------------------------------------------------------------- */
@@ -2426,67 +2497,3 @@ int postcopy_incoming_cleanup(MigrationIncomingState 
*mis)
 
     return rc;
 }
-
-/*
- * Called by postcopy_ram_eager_load_thread over all blocks to load in all the
- * pending pages of given ram block
- */
-static int ram_block_load_eager(RAMBlock *rb, void *opaque)
-{
-    MigrationIncomingState *mis = migration_incoming_get_current();
-    MigrationState *s = migrate_get_current();
-    Error *errp = NULL;
-    void *host = qemu_ram_get_host_addr(rb);
-    void *target;
-
-    for (ram_addr_t page_loc = 0; page_loc < rb->used_length;
-         page_loc += qemu_ram_pagesize(rb)) {
-        target = (uint8_t *)host + page_loc;
-        if (!postcopy_mapped_ram_load_page(mis, rb, page_loc, (uint64_t)target,
-                                           RAM_CHANNEL_PRECOPY, &errp)) {
-            migrate_error_propagate(s, errp);
-            return -1;
-        }
-    }
-    return 0;
-}
-
-/*
- * Used by fast snapshot load to eagerly load in all pages of RAM and schedule
- * cleanup after entire RAM is loaded
- */
-static void *postcopy_ram_eager_load_thread(void *opaque)
-{
-    MigrationIncomingState *mis = opaque;
-    MigrationStatus next_state;
-
-    trace_postcopy_ram_eager_load_thread_entry();
-    rcu_register_thread();
-    qemu_event_set(&mis->thread_sync_event);
-
-    if (foreach_not_ignored_block(ram_block_load_eager, NULL)) {
-        next_state = MIGRATION_STATUS_FAILED;
-    } else {
-        next_state = MIGRATION_STATUS_COMPLETED;
-    }
-    migrate_set_state(&mis->state, MIGRATION_STATUS_POSTCOPY_ACTIVE,
-                      next_state);
-
-    postcopy_state_set(POSTCOPY_INCOMING_END);
-    migration_bh_schedule(postcopy_incoming_complete_bh, mis);
-
-    rcu_unregister_thread();
-    trace_postcopy_ram_eager_load_thread_exit();
-    return NULL;
-}
-
-/*
- * Create thread for eager loading in fast snapshot load case
- */
-void postcopy_ram_eager_load_setup(MigrationIncomingState *mis)
-{
-    postcopy_thread_create(
-        mis, &mis->eager_load_thread, MIGRATION_THREAD_DST_SNAPSHOT_LOAD,
-        postcopy_ram_eager_load_thread, QEMU_THREAD_JOINABLE);
-    mis->have_eager_load_thread = true;
-}
-- 
2.54.0


-- 
Peter Xu


Reply via email to