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