]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
crimson/osd/pg: discard watches' states after iterating all cached obcs 53127/head
authorXuehan Xu <xuxuehan@qianxin.com>
Thu, 24 Aug 2023 04:14:13 +0000 (12:14 +0800)
committerXuehan Xu <xxhdx1985126@gmail.com>
Thu, 24 Aug 2023 04:23:53 +0000 (12:23 +0800)
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 <xuxuehan@qianxin.com>
src/crimson/osd/pg.cc

index 85f6116e604b3a121f06976422ea76c4cac391a4..696b6651a37f5255bacf7ff23e23a6f41539fc0c 100644 (file)
@@ -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<seastar::shared_ptr<crimson::osd::Watch>> 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 {