On Tue, Jun 30, 2026 at 01:49:36PM +0530, Aadeshveer Singh wrote:
> Replace the temporary bitmap with the existing file_bmap attribute of
> the RAMBlock. This acts as a preparatory change for the upcoming fast
> snapshot load feature.
> 
> Reusing this bitmap allows the destination to track page types during
> a postcopy load, enabling faster, direct placement of zero pages.
> 
> Since file_bmap is currently only utilized during the migration save
> phase, it can be safely repurposed during the load phase without
> introducing conflicts.
> 
> Signed-off-by: Aadeshveer Singh <[email protected]>
> ---
>  migration/ram.c | 33 +++++++++++++++++++++++++++------
>  1 file changed, 27 insertions(+), 6 deletions(-)
> 
> diff --git a/migration/ram.c b/migration/ram.c
> index fc38ffbf8a..4728f14d73 100644
> --- a/migration/ram.c
> +++ b/migration/ram.c
> @@ -252,6 +252,17 @@ int foreach_not_ignored_block(RAMBlockIterFunc func, 
> void *opaque)
>      return ret;
>  }
>  
> +static void ramblock_file_bmap_init(void)
> +{
> +    RAMBlock *rb;
> +
> +    RAMBLOCK_FOREACH_NOT_IGNORED(rb) {
> +        assert(!rb->file_bmap);
> +        size_t size = rb->max_length >> qemu_target_page_bits();

Hmm, I just notice mapped-ram always use guest psize for its bitmap.. even
for huge pages.  In that case this is correct.

> +        rb->file_bmap = bitmap_new(size);
> +    }
> +}
> +
>  static void ramblock_recv_map_init(void)
>  {
>      RAMBlock *rb;
> @@ -3749,6 +3760,9 @@ static int ram_load_setup(QEMUFile *f, void *opaque, 
> Error **errp)
>  {
>      xbzrle_load_setup();
>      ramblock_recv_map_init();
> +    if (migrate_mapped_ram()) {
> +        ramblock_file_bmap_init();
> +    }
>  
>      return 0;
>  }
> @@ -3766,8 +3780,8 @@ static int ram_load_cleanup(void *opaque)
>      xbzrle_load_cleanup();
>  
>      RAMBLOCK_FOREACH_NOT_IGNORED(rb) {
> -        g_free(rb->receivedmap);
> -        rb->receivedmap = NULL;
> +        g_clear_pointer(&rb->receivedmap, g_free);
> +        g_clear_pointer(&rb->file_bmap, g_free);
>      }
>  
>      return 0;
> @@ -4142,11 +4156,18 @@ err:
>  static void parse_ramblock_mapped_ram(QEMUFile *f, RAMBlock *block,
>                                        ram_addr_t length, Error **errp)
>  {
> -    g_autofree unsigned long *bitmap = NULL;
>      MappedRamHeader header;
>      size_t bitmap_size;
>      long num_pages;
>  
> +    if (length > block->max_length) {
> +        error_setg(errp,
> +                   "mapped-ram header length %" PRIu64 " exceeds "
> +                   "RAMBlock(\"%s\") max_length %" PRIu64,
> +                   (uint64_t)length, block->idstr, 
> (uint64_t)block->max_length);
> +        return;
> +    }
> +
>      if (!mapped_ram_read_header(f, &header, errp)) {
>          return;
>      }
> @@ -4174,14 +4195,14 @@ static void parse_ramblock_mapped_ram(QEMUFile *f, 
> RAMBlock *block,
>      num_pages = length / header.page_size;
>      bitmap_size = BITS_TO_LONGS(num_pages) * sizeof(unsigned long);

Here I think it would still be good to check the page_size is the same as
what was expected (in this case, guest page size), otherwise we should fail
because then the bitmap_size may still be unpredictable and it can cause
illegal access (beyond the size of bitmap allocated) in worst case.

Now I start to wonder when you're working on huge pages with the feature,
did you stick with the bmap having guest page size, or did you modify it to
be host page size?

Thanks,

>  
> -    bitmap = g_malloc0(bitmap_size);
> -    if (qemu_get_buffer_at(f, (uint8_t *)bitmap, bitmap_size,
> +    if (qemu_get_buffer_at(f, (uint8_t *)block->file_bmap, bitmap_size,
>                             header.bitmap_offset) != bitmap_size) {
>          error_setg(errp, "Error reading dirty bitmap");
>          return;
>      }
>  
> -    if (!read_ramblock_mapped_ram(f, block, num_pages, bitmap, errp)) {
> +    if (!read_ramblock_mapped_ram(f, block, num_pages, block->file_bmap,
> +                                  errp)) {
>          return;
>      }
>  
> -- 
> 2.54.0
> 

-- 
Peter Xu


Reply via email to