diff --git a/system/memory.c b/system/memory.c index 119fee0d34..5fc36708ec 100644 --- a/system/memory.c +++ b/system/memory.c @@ -1771,6 +1771,7 @@ static void memory_region_finalize(Object *obj) memory_region_clear_coalescing(mr); g_free((char *)mr->name); g_free(mr->ioeventfds); + object_unref(mr->rdm); } Object *memory_region_owner(const MemoryRegion *mr) @@ -2084,11 +2085,18 @@ int memory_region_add_ram_discard_source(MemoryRegion *mr, int memory_region_del_ram_discard_source(MemoryRegion *mr, RamDiscardSource *source) { + int ret; g_assert(mr->rdm); - return ram_discard_manager_del_source(mr->rdm, source); - - /* if there is no source and no listener left, we could free rdm */ + ret = ram_discard_manager_del_source(mr->rdm, source); + if (ret != 0) { + return ret; + } + if (QLIST_EMPTY(&mr->rdm->source_list) && QLIST_EMPTY(&mr->rdm->rdl_list)) { + object_unref(mr->rdm); + mr->rdm = NULL; + } + return 0; } /* Called with rcu_read_lock held. */ diff --git a/system/ram-discard-manager.c b/system/ram-discard-manager.c index 7da91bf648..4e8816e5a2 100644 --- a/system/ram-discard-manager.c +++ b/system/ram-discard-manager.c @@ -549,6 +549,7 @@ void ram_discard_manager_register_listener(RamDiscardManager *rdm, g_assert(section->mr == rdm->mr); + object_ref(rdm); rdl->section = memory_region_section_new_copy(section); QLIST_INSERT_HEAD(&rdm->rdl_list, rdl, next); @@ -570,6 +571,7 @@ void ram_discard_manager_unregister_listener(RamDiscardManager *rdm, memory_region_section_free_copy(rdl->section); rdl->section = NULL; QLIST_REMOVE(rdl, next); + object_unref(rdm); } int ram_discard_manager_replay_populated_to_listeners(RamDiscardManager *rdm)