From ac06cb5a959eee1d8545b1b47ac714588e32e870 Mon Sep 17 00:00:00 2001 From: Ronen Friedman Date: Thu, 30 Apr 2026 16:46:58 +0000 Subject: [PATCH] osd/SnapMapper::update_snaps() to handle a missing OBJ_ record by falling back to add_oid() instead of silently creating an inconsistent state (OBJ_ without matching SNA_ entries). This was observed on replicas that had recently recovered objects: the snap mapper entries created during recovery were not visible to a subsequent snap-trim repop's update_snaps() call, leaving the clone with no snap mapper entries. Scrub would then detect and report the inconsistency as an error. Promote snap mapper remove_oid/clear_snaps logging to dout(10) and add apply_op_stats tracing to aid diagnosis of any remaining stat or snap mapper drift. Signed-off-by: Ronen Friedman --- src/osd/SnapMapper.cc | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/osd/SnapMapper.cc b/src/osd/SnapMapper.cc index df2da64b3e49..0faf77a5b390 100644 --- a/src/osd/SnapMapper.cc +++ b/src/osd/SnapMapper.cc @@ -522,7 +522,7 @@ void SnapMapper::clear_snaps( const hobject_t &oid, MapCacher::Transaction *t) { - dout(20) << __func__ << " " << oid << dendl; + dout(10) << __func__ << " " << oid << dendl; ceph_assert(check(oid)); set to_remove; to_remove.insert(to_object_key(oid)); @@ -589,6 +589,15 @@ int SnapMapper::update_snaps( // Tolerate missing keys but not disk errors if (r < 0 && r != -ENOENT) return r; + if (r == -ENOENT) { + // Recently recovered replicas may observe missing snap-mapper state. + // Avoid creating an inconsistent state (OBJ_ without matching SNA_ entries) that + // would be detected by scrub later on - instead rebuild the mapping from scratch. + dout(10) << fmt::format("{}: {} no existing snap mapping, creating for {}", + __func__, oid, new_snaps) << dendl; + add_oid(oid, new_snaps, t); + return 0; + } if (old_snaps_check) ceph_assert(out.snaps == *old_snaps_check); @@ -770,7 +779,7 @@ int SnapMapper::remove_oid( const hobject_t &oid, MapCacher::Transaction *t) { - dout(20) << *this << __func__ << " " << oid << dendl; + dout(10) << *this << __func__ << " " << oid << dendl; ceph_assert(check(oid)); return _remove_oid(oid, t); } -- 2.47.3