From: Xuehan Xu Date: Thu, 24 Aug 2023 04:14:13 +0000 (+0800) Subject: crimson/osd/pg: discard watches' states after iterating all cached obcs X-Git-Tag: v19.3.0~403^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=094af522c7062cb91c87991ec55cbf67ee1da4dc;p=ceph.git 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 --- diff --git a/src/crimson/osd/pg.cc b/src/crimson/osd/pg.cc index 85f6116e604..696b6651a37 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 {