Skip to content
Snippets Groups Projects
Commit 6f6a5ef3 authored by Paolo Bonzini's avatar Paolo Bonzini
Browse files

memory: include DIRTY_MEMORY_MIGRATION in the dirty log mask


The separate handling of DIRTY_MEMORY_MIGRATION, which does not
call log_start/log_stop callbacks when it changes in a region's
dirty logging mask, has caused several bugs.

One recent example is commit 4cc856fa (kvm-all: Sync dirty-bitmap from
kvm before kvm destroy the corresponding dirty_bitmap, 2015-04-02).
Another performance problem is that KVM keeps tracking dirty pages
after a failed live migration, which causes bad performance due to
disallowing huge page mapping.

This patch removes the root cause of the problem by reporting
DIRTY_MEMORY_MIGRATION changes via log_start and log_stop.
Note that we now have to rebuild the FlatView when global dirty
logging is enabled or disabled; this ensures that log_start and
log_stop callbacks are invoked.

This will also be used to make the setting of bitmaps conditional.
In general, this patch lets users of the memory API ignore the
global state of dirty logging if they handle dirty logging
generically per region.

Reviewed-by: default avatarFam Zheng <famz@redhat.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent ea8cb1a8
No related branches found
No related tags found
No related merge requests found
......@@ -588,7 +588,7 @@ static void render_memory_region(FlatView *view,
remain = clip.size;
fr.mr = mr;
fr.dirty_log_mask = mr->dirty_log_mask;
fr.dirty_log_mask = memory_region_get_dirty_log_mask(mr);
fr.romd_mode = mr->romd_mode;
fr.readonly = readonly;
......@@ -1400,7 +1400,11 @@ bool memory_region_is_skip_dump(MemoryRegion *mr)
uint8_t memory_region_get_dirty_log_mask(MemoryRegion *mr)
{
return mr->dirty_log_mask;
uint8_t mask = mr->dirty_log_mask;
if (global_dirty_log) {
mask |= (1 << DIRTY_MEMORY_MIGRATION);
}
return mask;
}
bool memory_region_is_logging(MemoryRegion *mr, uint8_t client)
......@@ -1962,12 +1966,24 @@ void address_space_sync_dirty_bitmap(AddressSpace *as)
void memory_global_dirty_log_start(void)
{
global_dirty_log = true;
MEMORY_LISTENER_CALL_GLOBAL(log_global_start, Forward);
/* Refresh DIRTY_LOG_MIGRATION bit. */
memory_region_transaction_begin();
memory_region_update_pending = true;
memory_region_transaction_commit();
}
void memory_global_dirty_log_stop(void)
{
global_dirty_log = false;
/* Refresh DIRTY_LOG_MIGRATION bit. */
memory_region_transaction_begin();
memory_region_update_pending = true;
memory_region_transaction_commit();
MEMORY_LISTENER_CALL_GLOBAL(log_global_stop, Reverse);
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment