Commit 1891d455da for qemu.org
commit 1891d455da8cd74aa05deb7c784cb8a7bde23418
Author: Aadeshveer Singh <aadeshveer07@gmail.com>
Date: Sun Aug 16 23:16:24 2026 +0530
migration: Use file_bmap for RAMBlock during incoming file load
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 <aadeshveer07@gmail.com>
Reviewed-by: Peter Xu <peterx@redhat.com>
Reviewed-by: Juraj Marcin <jmarcin@redhat.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Fabiano Rosas <farosas@suse.de>
diff --git a/migration/ram.c b/migration/ram.c
index b6eb842746..7fa4774246 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();
+ rb->file_bmap = bitmap_new(size);
+ }
+}
+
static void ramblock_recv_map_init(void)
{
RAMBlock *rb;
@@ -3755,6 +3766,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;
}
@@ -3772,8 +3786,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;
@@ -4148,11 +4162,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;
}
@@ -4180,14 +4201,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);
- 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;
}