mirror of
https://github.com/qemu/qemu.git
synced 2026-07-08 17:46:17 +00:00
system/memory: add RamDiscardManager reference counting and cleanup
Listeners now hold a reference to the RamDiscardManager, ensuring it stays alive while listeners are registered. The RDM is eagerly freed when the last source and listener are removed, and also unreffed during MemoryRegion finalization as a safety net. This completes the TODO left in the previous commit and prevents both use-after-free and memory leaks of the RamDiscardManager. Reviewed-by: Peter Xu <peterx@redhat.com> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> Link: https://lore.kernel.org/r/20260604-rdm5-v5-9-5768e6a0943d@redhat.com Signed-off-by: Peter Xu <peterx@redhat.com>
This commit is contained in:
committed by
Peter Xu
parent
a6f1bc9846
commit
a947cf84c5
@@ -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. */
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user