@samitouri / QOSamiQemu / commits / 1891d455da

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>

Aadeshveer Singh committed Aug 16, 2026 at 23:16 UTC 1891d455da8cd74aa05deb7c784cb8a7bde23418
1 file changed +27 -6
migration/ram.c
+27 -6
@@ -252,6 +252,17 @@ int foreach_not_ignored_block(RAMBlockIterFunc func, void *opaque)
252 return ret;
253 }
254
255 +static void ramblock_file_bmap_init(void)
256 +{
257 + RAMBlock *rb;
258 +
259 + RAMBLOCK_FOREACH_NOT_IGNORED(rb) {
260 + assert(!rb->file_bmap);
261 + size_t size = rb->max_length >> qemu_target_page_bits();
262 + rb->file_bmap = bitmap_new(size);
263 + }
264 +}
265 +
266 static void ramblock_recv_map_init(void)
267 {
268 RAMBlock *rb;
@@ -3755,6 +3766,9 @@ static int ram_load_setup(QEMUFile *f, void *opaque, Error **errp)
3766 {
3767 xbzrle_load_setup();
3768 ramblock_recv_map_init();
3769 + if (migrate_mapped_ram()) {
3770 + ramblock_file_bmap_init();
3771 + }
3772
3773 return 0;
3774 }
@@ -3772,8 +3786,8 @@ static int ram_load_cleanup(void *opaque)
3786 xbzrle_load_cleanup();
3787
3788 RAMBLOCK_FOREACH_NOT_IGNORED(rb) {
3775 - g_free(rb->receivedmap);
3776 - rb->receivedmap = NULL;
3789 + g_clear_pointer(&rb->receivedmap, g_free);
3790 + g_clear_pointer(&rb->file_bmap, g_free);
3791 }
3792
3793 return 0;
@@ -4148,11 +4162,18 @@ err:
4162 static void parse_ramblock_mapped_ram(QEMUFile *f, RAMBlock *block,
4163 ram_addr_t length, Error **errp)
4164 {
4151 - g_autofree unsigned long *bitmap = NULL;
4165 MappedRamHeader header;
4166 size_t bitmap_size;
4167 long num_pages;
4168
4169 + if (length > block->max_length) {
4170 + error_setg(errp,
4171 + "mapped-ram header length %" PRIu64 " exceeds "
4172 + "RAMBlock(\"%s\") max_length %" PRIu64,
4173 + (uint64_t)length, block->idstr, (uint64_t)block->max_length);
4174 + return;
4175 + }
4176 +
4177 if (!mapped_ram_read_header(f, &header, errp)) {
4178 return;
4179 }
@@ -4180,14 +4201,14 @@ static void parse_ramblock_mapped_ram(QEMUFile *f, RAMBlock *block,
4201 num_pages = length / header.page_size;
4202 bitmap_size = BITS_TO_LONGS(num_pages) * sizeof(unsigned long);
4203
4183 - bitmap = g_malloc0(bitmap_size);
4184 - if (qemu_get_buffer_at(f, (uint8_t *)bitmap, bitmap_size,
4204 + if (qemu_get_buffer_at(f, (uint8_t *)block->file_bmap, bitmap_size,
4205 header.bitmap_offset) != bitmap_size) {
4206 error_setg(errp, "Error reading dirty bitmap");
4207 return;
4208 }
4209
4190 - if (!read_ramblock_mapped_ram(f, block, num_pages, bitmap, errp)) {
4210 + if (!read_ramblock_mapped_ram(f, block, num_pages, block->file_bmap,
4211 + errp)) {
4212 return;
4213 }
4214