From 094af522c7062cb91c87991ec55cbf67ee1da4dc Mon Sep 17 00:00:00 2001 From: Xuehan Xu Date: Thu, 24 Aug 2023 12:14:13 +0800 Subject: [PATCH] crimson/osd/pg: discard watches' states after iterating all cached obcs Discarding watches' states while iterating cached obcs might have the following problem: 1. discard a watch's state 2. the corresponding object context's use_count drops to zero 3. the object context is unreferenced by obc lru 4. obc is deleted from obc lru by lru's evict() 5. obc iteration is corrupted Signed-off-by: Xuehan Xu --- src/crimson/osd/pg.cc | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/crimson/osd/pg.cc b/src/crimson/osd/pg.cc index 85f6116e604b..696b6651a37f 100644 --- a/src/crimson/osd/pg.cc +++ b/src/crimson/osd/pg.cc @@ -1454,14 +1454,19 @@ void PG::on_change(ceph::os::Transaction &t) { } void PG::context_registry_on_change() { - obc_registry.for_each([](ObjectContextRef obc) { - assert(obc); - for (auto j = obc->watchers.begin(); - j != obc->watchers.end(); - j = obc->watchers.erase(j)) { - j->second->discard_state(); - } + std::vector> watchers; + obc_registry.for_each([&watchers](ObjectContextRef obc) { + assert(obc); + for (auto j = obc->watchers.begin(); + j != obc->watchers.end(); + j = obc->watchers.erase(j)) { + watchers.emplace_back(j->second); + } }); + + for (auto &watcher : watchers) { + watcher->discard_state(); + } } bool PG::can_discard_op(const MOSDOp& m) const { -- 2.47.3