From: Marc-André Lureau <[email protected]> ram_block_attributes_destroy() was called from reclaim_ramblock(), which runs as an RCU callback deferred by call_rcu().
However,when the RamDiscardManager is finalized, it will assert that its source_list is empty in the next commit. Since the RCU callback hasn't run yet, the source added by ram_block_attributes_create() is still attached. Move ram_block_attributes_destroy() into qemu_ram_free() so the source is removed synchronously. This is safe because qemu_ram_free() during shutdown runs after pause_all_vcpus(), so no vCPU thread can concurrently access the attributes via kvm_convert_memory(). Reviewed-by: Peter Xu <[email protected]> Signed-off-by: Marc-André Lureau <[email protected]> Link: https://lore.kernel.org/r/[email protected] [peterx: rebase on top of qemu_ram_free() change] Signed-off-by: Peter Xu <[email protected]> --- system/physmem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/physmem.c b/system/physmem.c index db8ad84ab6..c4bfb57625 100644 --- a/system/physmem.c +++ b/system/physmem.c @@ -2582,7 +2582,6 @@ static void reclaim_ramblock(RAMBlock *block) } if (block->guest_memfd >= 0) { - ram_block_attributes_destroy(block->attributes); close(block->guest_memfd); ram_block_coordinated_discard_require(false); } @@ -2610,6 +2609,7 @@ void qemu_ram_free(RAMBlock *block) qatomic_set(&ram_list.mru_block, NULL); /* Write list before version */ qatomic_store_release(&ram_list.version, ram_list.version + 1); + g_clear_pointer(&block->attributes, ram_block_attributes_destroy); call_rcu(block, reclaim_ramblock, rcu); qemu_mutex_unlock_ramlist(); } -- 2.54.0
