From: Ronen Friedman Date: Thu, 7 May 2026 10:06:28 +0000 (+0000) Subject: crimson/osd/snap-mapper: flush pending writes on pg interval change X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=dee19fec702feea339575e391e5333613acd6572;p=ceph.git crimson/osd/snap-mapper: flush pending writes on pg interval change When a PG interval changes, the snap-mapper's MapCacher backend is reset to clear any stale state. This change adds a flush-and-reset method that first flushes any pending writes in the MapCacher into the objectstore, then resets the backend. Fixes: https://tracker.ceph.com/issues/76458 Signed-off-by: Ronen Friedman --- diff --git a/src/common/map_cacher.hpp b/src/common/map_cacher.hpp index 3952cf9bb751..ad75c3f52ccc 100644 --- a/src/common/map_cacher.hpp +++ b/src/common/map_cacher.hpp @@ -96,6 +96,31 @@ public: in_progress.reset(); } + /// Flush all pending writes/removals into a Transaction, then reset. + /// This ensures in-flight cached state is persisted before the cache + /// is cleared (e.g. on PG interval change). + void flush_and_reset(Transaction *t) { + std::map to_set; + std::set to_remove; + K key{}; + std::pair> cached; + while (in_progress.get_next(key, &cached)) { + if (cached.second) { + to_set[cached.first] = cached.second.get(); + } else { + to_remove.insert(cached.first); + } + key = cached.first; + } + if (!to_set.empty()) { + t->set_keys(to_set); + } + if (!to_remove.empty()) { + t->remove_keys(to_remove); + } + in_progress.reset(); + } + /// Fetch first key/value std::pair after specified key int get_next( K key, ///< [in] key after which to get next diff --git a/src/crimson/osd/pg.cc b/src/crimson/osd/pg.cc index bf3ea70d157b..8c51956e4258 100644 --- a/src/crimson/osd/pg.cc +++ b/src/crimson/osd/pg.cc @@ -1701,7 +1701,8 @@ void PG::on_change(ceph::os::Transaction &t) { // is save and in time. peering_state.state_clear(PG_STATE_SNAPTRIM); peering_state.state_clear(PG_STATE_SNAPTRIM_ERROR); - snap_mapper.reset_backend(); + auto _t = osdriver.get_transaction(&t); + snap_mapper.flush_and_reset_backend(&_t); reset_pglog_based_recovery_op(); } diff --git a/src/osd/SnapMapper.h b/src/osd/SnapMapper.h index c7cab0c34401..8ff9bf3c6c28 100644 --- a/src/osd/SnapMapper.h +++ b/src/osd/SnapMapper.h @@ -337,9 +337,13 @@ private: return prefix_itr; } - /// reset the MapCacher backend, this should be called on pg interval change - void reset_backend() { - backend.reset(); + /// Flush pending snap-mapper writes into the provided transaction, + /// then reset the MapCacher backend. This should be called on pg + /// interval change to ensure in-flight snap-mapper state is persisted + /// before the cache is cleared. + void flush_and_reset_backend( + MapCacher::Transaction *t) { + backend.flush_and_reset(t); } /// Update snaps for oid, empty new_snaps removes the mapping