Commit e30d1d8c authored by Dr. David Alan Gilbert's avatar Dr. David Alan Gilbert Committed by Juan Quintela

Count used RAMBlock pages for migration_dirty_pages

This is a fix for a bug* triggered by a migration after hot unplugging
a few virtio-net NICs, that caused migration never to converge, because
'migration_dirty_pages' is incorrectly initialised.

'migration_dirty_pages' is used as a tally of the number of outstanding
dirty pages, to give the migration code an idea of how much more data
will need to be transferred, and thus whether it can end the iterative

It was initialised to the total size of the RAMBlock address space,
however hotunplug can leave this space sparse, and hence
migration_dirty_pages ended up too large.
Signed-off-by: default avatarDr. David Alan Gilbert <>

(* )
Signed-off-by: default avatarJuan Quintela <>
parent 548f52ea
......@@ -726,11 +726,8 @@ static void reset_ram_globals(void)
static int ram_save_setup(QEMUFile *f, void *opaque)
RAMBlock *block;
int64_t ram_pages = last_ram_offset() >> TARGET_PAGE_BITS;
int64_t ram_bitmap_pages; /* Size of bitmap in pages, including gaps */
migration_bitmap = bitmap_new(ram_pages);
bitmap_set(migration_bitmap, 0, ram_pages);
migration_dirty_pages = ram_pages;
mig_throttle_on = false;
dirty_rate_high_cnt = 0;
......@@ -770,6 +767,22 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
bytes_transferred = 0;
ram_bitmap_pages = last_ram_offset() >> TARGET_PAGE_BITS;
migration_bitmap = bitmap_new(ram_bitmap_pages);
bitmap_set(migration_bitmap, 0, ram_bitmap_pages);
* Count the total number of pages used by ram blocks not including any
* gaps due to alignment or unplugs.
migration_dirty_pages = 0;
QTAILQ_FOREACH(block, &ram_list.blocks, next) {
uint64_t block_pages;
block_pages = block->length >> TARGET_PAGE_BITS;
migration_dirty_pages += block_pages;
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment