From: Peter Xu <peterx@redhat.com>
To: Aadeshveer Singh <aadeshveer07@gmail.com>
Cc: qemu-devel@nongnu.org, farosas@suse.de, pbonzini@redhat.com,
philmd@mailo.com, lvivier@redhat.com, ayoub@saferwall.com
Subject: Re: [RFC PATCH v2 5/7] migration: add RAMBlock field and helper for fast snapshot load
Date: Mon, 6 Jul 2026 16:03:19 -0400 [thread overview]
Message-ID: <akwKBx-iGCwGZdGd@x1.local> (raw)
In-Reply-To: <20260630081940.611092-6-aadeshveer07@gmail.com>
On Tue, Jun 30, 2026 at 01:49:38PM +0530, Aadeshveer Singh wrote:
> Add pending_bmap field per RAMBlock which is a Bitmap to store
> internal state of which pages have been read by some thread to ensure
> coordination between fault thread and eager load thread.
>
> Modify parse_ramblock_mapped_ram(), to not load the actual RAMBlocks
> data in postcopy case as that will be loaded by fault thread and eager
> thread after the VM starts running.
>
> Change ram_load() to use new function ram_should_load_postcopy_pages()
> to decide how to load/read RAM.
>
> Signed-off-by: Aadeshveer Singh <aadeshveer07@gmail.com>
> ---
> include/system/ramblock.h | 6 ++++
> migration/ram.c | 59 +++++++++++++++++++++++++++++++++++----
> 2 files changed, 59 insertions(+), 6 deletions(-)
>
> diff --git a/include/system/ramblock.h b/include/system/ramblock.h
> index 4435f8d55f..83187bf44c 100644
> --- a/include/system/ramblock.h
> +++ b/include/system/ramblock.h
> @@ -60,6 +60,12 @@ struct RAMBlock {
>
> /* Bitmap of already received pages. Only used on destination side. */
> unsigned long *receivedmap;
> + /*
> + * Bitmap for pages that are yet to be read from disk. It is required for
> + * fault thread and eager thread to keep note of which pages are currently
> + * being read. Used by fast snapshot load.
> + */
> + unsigned long *pending_bmap;
>
> /*
> * bitmap to track already cleared dirty bitmap. When the bit is
> diff --git a/migration/ram.c b/migration/ram.c
> index 4728f14d73..ffd60b2ac8 100644
> --- a/migration/ram.c
> +++ b/migration/ram.c
> @@ -263,6 +263,18 @@ static void ramblock_file_bmap_init(void)
> }
> }
>
> +static void ramblock_pending_bmap_init(void)
> +{
> + RAMBlock *rb;
> +
> + RAMBLOCK_FOREACH_NOT_IGNORED(rb) {
> + assert(!rb->pending_bmap);
> + size_t size = rb->max_length >> qemu_target_page_bits();
IIUC we should always stick with rb->page_size (aka, host page size) here
rather than guest page size. It's because you want to use that one bit to
serialize the two threads (fault thread, eager thread) when do atomic
test_and_clear, and since UFFDIO_COPY needs to happen at host page size
granule, this needs to match that.
> + rb->pending_bmap = bitmap_new(size);
> + bitmap_set(rb->pending_bmap, 0, size);
> + }
> +}
> +
> static void ramblock_recv_map_init(void)
> {
> RAMBlock *rb;
> @@ -3762,6 +3774,10 @@ static int ram_load_setup(QEMUFile *f, void *opaque, Error **errp)
> ramblock_recv_map_init();
> if (migrate_mapped_ram()) {
> ramblock_file_bmap_init();
> + if (migrate_postcopy_ram()) {
> + /* fast snapshot load */
> + ramblock_pending_bmap_init();
> + }
> }
>
> return 0;
> @@ -3782,6 +3798,7 @@ static int ram_load_cleanup(void *opaque)
> RAMBLOCK_FOREACH_NOT_IGNORED(rb) {
> g_clear_pointer(&rb->receivedmap, g_free);
> g_clear_pointer(&rb->file_bmap, g_free);
> + g_clear_pointer(&rb->pending_bmap, g_free);
> }
>
> return 0;
> @@ -4201,9 +4218,12 @@ static void parse_ramblock_mapped_ram(QEMUFile *f, RAMBlock *block,
> return;
> }
>
> - if (!read_ramblock_mapped_ram(f, block, num_pages, block->file_bmap,
> - errp)) {
> - return;
> + if (!migrate_postcopy_ram()) {
> + /* Do not load RAM during setup for fast snapshot load */
> + if (!read_ramblock_mapped_ram(f, block, num_pages, block->file_bmap,
> + errp)) {
> + return;
> + }
> }
>
> /* Skip pages array */
> @@ -4475,15 +4495,42 @@ static int ram_load_precopy(QEMUFile *f)
> return ret;
> }
>
> +static bool ram_should_load_postcopy_pages(void)
> +{
> + /* This is pure precopy, we don't need to load pages in postcopy way */
> + if (!postcopy_is_running()) {
> + return false;
> + }
> +
> + /*
> + * This is postcopy, but when with mapped-ram, pages are not loaded in the
> + * migration stream here, but done separately in a thread eagerly reading
> + * pages from the snapshot. Here, we only need to read the ram headers,
> + * reusing the precopy code.
> + * TODO: when we have separate function to parse RAM headers we should
> + * switch to that.
> + */
> + if (migrate_mapped_ram()) {
> + return false;
> + }
> +
> + /*
> + * Genuine network postcopy, we will load pages in this current stream and
> + * they need to be done in postcopy way.
> + */
> + return true;
> +}
> +
> static int ram_load(QEMUFile *f, void *opaque, int version_id)
> {
> int ret = 0;
> static uint64_t seq_iter;
> /*
> * If system is running in postcopy mode, page inserts to host memory must
> - * be atomic
> + * be atomic. However, fast snapshot load uses the mapped ram precopy like
> + * path to read block headers and populating bitmaps.
> */
> - bool postcopy_running = postcopy_is_running();
> + bool load_postcopy_pages = ram_should_load_postcopy_pages();
>
> seq_iter++;
>
> @@ -4499,7 +4546,7 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
> */
> trace_ram_load_start();
> WITH_RCU_READ_LOCK_GUARD() {
> - if (postcopy_running) {
> + if (load_postcopy_pages) {
> /*
> * Note! Here RAM_CHANNEL_PRECOPY is the precopy channel of
> * postcopy migration, we have another RAM_CHANNEL_POSTCOPY to
> --
> 2.54.0
>
--
Peter Xu
next prev parent reply other threads:[~2026-07-06 20:03 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-30 8:19 [RFC PATCH v2 0/7] migration: fast snapshot load Aadeshveer Singh
2026-06-30 8:19 ` [RFC PATCH v2 1/7] migration/tests: remove capability conflict test postcopy-ram+mapped-ram Aadeshveer Singh
2026-07-06 19:02 ` Peter Xu
2026-06-30 8:19 ` [RFC PATCH v2 2/7] migration: Propagate error in postcopy setup functions Aadeshveer Singh
2026-07-06 19:13 ` Peter Xu
2026-06-30 8:19 ` [RFC PATCH v2 3/7] migration: Use file_bmap for RAMBlock during incoming file load Aadeshveer Singh
2026-07-06 19:29 ` Peter Xu
2026-06-30 8:19 ` [RFC PATCH v2 4/7] migration: Make qemu_get_buffer_at() thread-safe Aadeshveer Singh
2026-07-06 19:34 ` Peter Xu
2026-06-30 8:19 ` [RFC PATCH v2 5/7] migration: add RAMBlock field and helper for fast snapshot load Aadeshveer Singh
2026-07-06 20:03 ` Peter Xu [this message]
2026-06-30 8:19 ` [RFC PATCH v2 6/7] migration: add support for fault thread to load pages from disk Aadeshveer Singh
2026-07-06 20:35 ` Peter Xu
2026-06-30 8:19 ` [RFC PATCH v2 7/7] migration: add eager load thread and setup for fast snapshot load Aadeshveer Singh
2026-07-06 21:07 ` Peter Xu
2026-07-06 19:16 ` [RFC PATCH v2 0/7] migration: " Peter Xu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=akwKBx-iGCwGZdGd@x1.local \
--to=peterx@redhat.com \
--cc=aadeshveer07@gmail.com \
--cc=ayoub@saferwall.com \
--cc=farosas@suse.de \
--cc=lvivier@redhat.com \
--cc=pbonzini@redhat.com \
--cc=philmd@mailo.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.