diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c index f6e9a1bc86..006d219ad5 100644 --- a/hw/i386/xen/xen-hvm.c +++ b/hw/i386/xen/xen-hvm.c @@ -669,7 +669,7 @@ void xen_hvm_modified_memory(ram_addr_t start, ram_addr_t length) void qmp_xen_set_global_dirty_log(bool enable, Error **errp) { if (enable) { - memory_global_dirty_log_start(GLOBAL_DIRTY_MIGRATION); + memory_global_dirty_log_start(GLOBAL_DIRTY_MIGRATION, errp); } else { memory_global_dirty_log_stop(GLOBAL_DIRTY_MIGRATION); } diff --git a/include/exec/memory.h b/include/exec/memory.h index 5555567bc4..c129ee6db7 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -2570,8 +2570,11 @@ void memory_listener_unregister(MemoryListener *listener); * memory_global_dirty_log_start: begin dirty logging for all regions * * @flags: purpose of starting dirty log, migration or dirty rate + * @errp: pointer to Error*, to store an error if it happens. + * + * Return: true on success, else false setting @errp with error. */ -void memory_global_dirty_log_start(unsigned int flags); +bool memory_global_dirty_log_start(unsigned int flags, Error **errp); /** * memory_global_dirty_log_stop: end dirty logging for all regions diff --git a/migration/dirtyrate.c b/migration/dirtyrate.c index 1d2e85746f..d02d70b7b4 100644 --- a/migration/dirtyrate.c +++ b/migration/dirtyrate.c @@ -90,9 +90,15 @@ static int64_t do_calculate_dirtyrate(DirtyPageRecord dirty_pages, void global_dirty_log_change(unsigned int flag, bool start) { + Error *local_err = NULL; + bool ret; + bql_lock(); if (start) { - memory_global_dirty_log_start(flag); + ret = memory_global_dirty_log_start(flag, &local_err); + if (!ret) { + error_report_err(local_err); + } } else { memory_global_dirty_log_stop(flag); } @@ -608,9 +614,12 @@ static void calculate_dirtyrate_dirty_bitmap(struct DirtyRateConfig config) { int64_t start_time; DirtyPageRecord dirty_pages; + Error *local_err = NULL; bql_lock(); - memory_global_dirty_log_start(GLOBAL_DIRTY_DIRTY_RATE); + if (!memory_global_dirty_log_start(GLOBAL_DIRTY_DIRTY_RATE, &local_err)) { + error_report_err(local_err); + } /* * 1'round of log sync may return all 1 bits with diff --git a/migration/ram.c b/migration/ram.c index f0bd71438a..bade3e9281 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -2862,18 +2862,32 @@ static void migration_bitmap_clear_discarded_pages(RAMState *rs) static void ram_init_bitmaps(RAMState *rs) { + Error *local_err = NULL; + bool ret = true; + qemu_mutex_lock_ramlist(); WITH_RCU_READ_LOCK_GUARD() { ram_list_init_bitmaps(); /* We don't use dirty log with background snapshots */ if (!migrate_background_snapshot()) { - memory_global_dirty_log_start(GLOBAL_DIRTY_MIGRATION); + ret = memory_global_dirty_log_start(GLOBAL_DIRTY_MIGRATION, + &local_err); + if (!ret) { + error_report_err(local_err); + goto out_unlock; + } migration_bitmap_sync_precopy(rs, false); } } +out_unlock: qemu_mutex_unlock_ramlist(); + if (!ret) { + ram_bitmaps_destroy(); + return; + } + /* * After an eventual first bitmap sync, fixup the initial bitmap * containing all 1s to exclude any discarded pages from migration. @@ -3665,6 +3679,8 @@ int colo_init_ram_cache(void) void colo_incoming_start_dirty_log(void) { RAMBlock *block = NULL; + Error *local_err = NULL; + /* For memory_global_dirty_log_start below. */ bql_lock(); qemu_mutex_lock_ramlist(); @@ -3676,7 +3692,10 @@ void colo_incoming_start_dirty_log(void) /* Discard this dirty bitmap record */ bitmap_zero(block->bmap, block->max_length >> TARGET_PAGE_BITS); } - memory_global_dirty_log_start(GLOBAL_DIRTY_MIGRATION); + if (!memory_global_dirty_log_start(GLOBAL_DIRTY_MIGRATION, + &local_err)) { + error_report_err(local_err); + } } ram_state->migration_dirty_pages = 0; qemu_mutex_unlock_ramlist(); diff --git a/system/memory.c b/system/memory.c index 86d6c33180..c02c1d4bed 100644 --- a/system/memory.c +++ b/system/memory.c @@ -2937,10 +2937,9 @@ err: return false; } -void memory_global_dirty_log_start(unsigned int flags) +bool memory_global_dirty_log_start(unsigned int flags, Error **errp) { unsigned int old_flags; - Error *local_err = NULL; assert(flags && !(flags & (~GLOBAL_DIRTY_MASK))); @@ -2952,7 +2951,7 @@ void memory_global_dirty_log_start(unsigned int flags) flags &= ~global_dirty_tracking; if (!flags) { - return; + return true; } old_flags = global_dirty_tracking; @@ -2960,17 +2959,17 @@ void memory_global_dirty_log_start(unsigned int flags) trace_global_dirty_changed(global_dirty_tracking); if (!old_flags) { - if (!memory_global_dirty_log_do_start(&local_err)) { + if (!memory_global_dirty_log_do_start(errp)) { global_dirty_tracking &= ~flags; trace_global_dirty_changed(global_dirty_tracking); - error_report_err(local_err); - return; + return false; } memory_region_transaction_begin(); memory_region_update_pending = true; memory_region_transaction_commit(); } + return true; } static void memory_global_dirty_log_do_stop(unsigned int flags)