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(); + 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); - 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.55.0
