From 254650b70886cd26e69f61af682c5daf9fbc4c31 Mon Sep 17 00:00:00 2001 From: Alex Ainscow Date: Fri, 24 Apr 2026 15:57:55 +0100 Subject: [PATCH] osd: Fix incorrect rollback logic for partial write OI Before this fix, when rolling back an OI, the system used the OI from the primary to rollback to. This is wrong if the previous write was a partial write. This may have a few consequences during recovery (although its not clear any are serious) and in EC direct reads, where a false-positive version mismatch will be detected. The test provided recreates the issue. The fix provided modifies the rollback as it is being written. Fixes: https://tracker.ceph.com/issues/76213 Signed-off-by: Alex Ainscow # Conflicts: # src/test/osd/TestECFailoverWithPeering.cc --- src/osd/PGBackend.cc | 29 +++++++++++++++++++---- src/test/osd/TestECFailoverWithPeering.cc | 2 +- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/osd/PGBackend.cc b/src/osd/PGBackend.cc index e17f4f3909d4..bb40c28e66c9 100644 --- a/src/osd/PGBackend.cc +++ b/src/osd/PGBackend.cc @@ -672,11 +672,30 @@ void PGBackend::rollback_setattrs( } } if (only_oi) { - t->setattr( - coll, - ghobject_t(hoid, ghobject_t::NO_GEN, get_parent()->whoami_shard().shard), - OI_ATTR, - to_set[OI_ATTR]); + object_info_t oi; + auto p = to_set[OI_ATTR].cbegin(); + decode(oi, p); + + shard_id_t my_shard = get_parent()->whoami_shard().shard; + if (oi.shard_versions.contains(my_shard) && oi.shard_versions.at(my_shard) != oi.version) { + oi.version = oi.shard_versions.at(my_shard); + oi.shard_versions.clear(); + + bufferlist bl; + encode(oi, bl, get_osdmap()->get_features(CEPH_ENTITY_TYPE_OSD, nullptr)); + + t->setattr( + coll, + ghobject_t(hoid, ghobject_t::NO_GEN, my_shard), + OI_ATTR, + bl); + } else { + t->setattr( + coll, + ghobject_t(hoid, ghobject_t::NO_GEN, my_shard), + OI_ATTR, + to_set[OI_ATTR]); + } } else { t->setattrs( coll, diff --git a/src/test/osd/TestECFailoverWithPeering.cc b/src/test/osd/TestECFailoverWithPeering.cc index 2ac088d3975a..e06ec7b73ff0 100644 --- a/src/test/osd/TestECFailoverWithPeering.cc +++ b/src/test/osd/TestECFailoverWithPeering.cc @@ -453,7 +453,7 @@ TEST_P(TestECFailoverWithPeering, ECSequentialOSDFailoverTest) { * * Recreate https://tracker.ceph.com/issues/76213 */ -TEST_P(TestECFailoverWithPeering, DISABLED_RollbackVersionMismatch) { +TEST_P(TestECFailoverWithPeering, RollbackVersionMismatch) { if (k < 3) { GTEST_SKIP() << "SnapshotTrimRollbackVersionMismatch requires at least 3 data shards"; } -- 2.47.3