From: Alex Ainscow Date: Thu, 13 Nov 2025 11:22:07 +0000 (+0000) Subject: osd: Make scrub determine the correct object size. X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=7cebee360fab9539f86bf36b29597409ae99c5e1;p=ceph-ci.git osd: Make scrub determine the correct object size. Permits shard sizes to be either legacy or new after upgrade Resolves: rhbz#2400427 Signed-off-by: Alex Ainscow (cherry picked from commit 9609410db0df8879af4c8aacf2ff37b141d1bbcd) --- diff --git a/src/osd/ECBackend.h b/src/osd/ECBackend.h index 4d116a582a2..462ff2e9f22 100644 --- a/src/osd/ECBackend.h +++ b/src/osd/ECBackend.h @@ -363,8 +363,12 @@ public: ScrubMap::object &o ); - uint64_t be_get_ondisk_size(uint64_t logical_size, shard_id_t shard_id - ) const { + uint64_t be_get_ondisk_size(uint64_t logical_size, shard_id_t shard_id, + bool object_is_legacy_ec) const { + if (object_is_legacy_ec) { + // In legacy EC, all shards were padded to the next chunk boundry. + return sinfo.ro_offset_to_next_chunk_offset(logical_size); + } return object_size_to_shard_size(logical_size, shard_id); } }; diff --git a/src/osd/ECSwitch.h b/src/osd/ECSwitch.h index 42f405021a8..24e4f9fb7e9 100644 --- a/src/osd/ECSwitch.h +++ b/src/osd/ECSwitch.h @@ -293,10 +293,11 @@ public: } uint64_t be_get_ondisk_size(uint64_t logical_size, - shard_id_t shard_id) const final { + shard_id_t shard_id, + bool object_is_legacy_ec) const final { if (is_optimized()) { - return optimized.be_get_ondisk_size(logical_size, shard_id); + return optimized.be_get_ondisk_size(logical_size, shard_id, object_is_legacy_ec); } return legacy.be_get_ondisk_size(logical_size); } diff --git a/src/osd/PG.h b/src/osd/PG.h index f3e760c1b8f..f8231a72335 100644 --- a/src/osd/PG.h +++ b/src/osd/PG.h @@ -1412,8 +1412,9 @@ public: } uint64_t logical_to_ondisk_size(uint64_t logical_size, - shard_id_t shard_id) const final { - return get_pgbackend()->be_get_ondisk_size(logical_size, shard_id_t(shard_id)); + shard_id_t shard_id, + bool object_is_legacy_ec) const final { + return get_pgbackend()->be_get_ondisk_size(logical_size, shard_id_t(shard_id), object_is_legacy_ec); } }; diff --git a/src/osd/PGBackend.h b/src/osd/PGBackend.h index acbff0745b2..bfddeb4bbc4 100644 --- a/src/osd/PGBackend.h +++ b/src/osd/PGBackend.h @@ -617,7 +617,8 @@ typedef std::shared_ptr OSDMapRef; ScrubMapBuilder &pos); virtual uint64_t be_get_ondisk_size(uint64_t logical_size, - shard_id_t shard_id) const = 0; + shard_id_t shard_id, + bool object_is_legacy_ec) const = 0; virtual int be_deep_scrub( [[maybe_unused]] const Scrub::ScrubCounterSet& io_counters, diff --git a/src/osd/ReplicatedBackend.h b/src/osd/ReplicatedBackend.h index b52fe710181..fc00982d0b1 100644 --- a/src/osd/ReplicatedBackend.h +++ b/src/osd/ReplicatedBackend.h @@ -464,7 +464,8 @@ private: ScrubMap::object &o) override; uint64_t be_get_ondisk_size(uint64_t logical_size, - shard_id_t unused) const final { + shard_id_t unused, + bool unused2) const final { return logical_size; } }; diff --git a/src/osd/scrubber/scrub_backend.cc b/src/osd/scrubber/scrub_backend.cc index ddb95a011f2..2c152d5d0cf 100644 --- a/src/osd/scrubber/scrub_backend.cc +++ b/src/osd/scrubber/scrub_backend.cc @@ -99,9 +99,29 @@ ScrubBackend::ScrubBackend(ScrubBeListener& scrubber, } uint64_t ScrubBackend::logical_to_ondisk_size(uint64_t logical_size, - shard_id_t shard_id) const + shard_id_t shard_id, + bool hinfo_present, + uint64_t expected_size) const { - return m_pg.logical_to_ondisk_size(logical_size, shard_id); + uint64_t ondisk_size = m_pg.logical_to_ondisk_size(logical_size, shard_id, false); + + if (!hinfo_present || ondisk_size == expected_size) { + return ondisk_size; + } + + // This object does not match the expected size, but hinfo is present. In this + // case there are valid reasons for the shard to be *either* size when using + // optimised EC. The following function checks the expected size from legacy + // EC. + uint64_t legacy_ondisk_size = m_pg.logical_to_ondisk_size(logical_size, shard_id, true); + if (expected_size == legacy_ondisk_size) { + return legacy_ondisk_size; + } + + // If this return is reached, then the size is corrupt and what we return + // here is relevant to the error message only. Return the non-legacy value + // as it might be more useful in debug. + return ondisk_size; } void ScrubBackend::update_repair_status(bool should_repair) @@ -732,7 +752,9 @@ shard_as_auth_t ScrubBackend::possible_auth_shard(const hobject_t& obj, } } - uint64_t ondisk_size = logical_to_ondisk_size(oi.size, srd.shard); + uint64_t ondisk_size = logical_to_ondisk_size(oi.size, srd.shard, + smap_obj.attrs.contains(ECUtil::get_hinfo_key()), + smap_obj.size); if (test_error_cond(smap_obj.size != ondisk_size, shard_info, &shard_info_wrapper::set_obj_size_info_mismatch)) { @@ -1327,7 +1349,9 @@ bool ScrubBackend::compare_obj_details(pg_shard_t auth_shard, // ------------------------------------------------------------------------ // sizes: - uint64_t oi_size = logical_to_ondisk_size(auth_oi.size, shard.shard); + uint64_t oi_size = logical_to_ondisk_size(auth_oi.size, shard.shard, + candidate.attrs.contains(ECUtil::get_hinfo_key()), + candidate.size); if (oi_size != candidate.size) { fmt::format_to(std::back_inserter(out), "{}size {} != size {} from auth oi {}", @@ -1509,12 +1533,17 @@ void ScrubBackend::scrub_snapshot_metadata(ScrubMap& map, const pg_shard_t &srd) } if (oi) { - if (logical_to_ondisk_size(oi->size, srd.shard) != p->second.size) { + bool has_hinfo = p->second.attrs.contains( + ECLegacy::ECUtilL::get_hinfo_key()); + if (logical_to_ondisk_size(oi->size, srd.shard, has_hinfo, p->second.size) + != p->second.size) { clog.error() << m_mode_desc << " " << m_pg_id << " " << soid << " : on disk size (" << p->second.size << ") does not match object info size (" << oi->size << ") adjusted for ondisk to (" - << logical_to_ondisk_size(oi->size, srd.shard) << ")"; + << logical_to_ondisk_size(oi->size, srd.shard, + has_hinfo, p->second.size) + << ")"; soid_error.set_size_mismatch(); this_chunk->m_error_counts.shallow_errors++; } diff --git a/src/osd/scrubber/scrub_backend.h b/src/osd/scrubber/scrub_backend.h index 83abd71981c..f8705ca539a 100644 --- a/src/osd/scrubber/scrub_backend.h +++ b/src/osd/scrubber/scrub_backend.h @@ -526,7 +526,9 @@ class ScrubBackend { // accessing the PG backend for this translation service uint64_t logical_to_ondisk_size(uint64_t logical_size, - shard_id_t shard_id) const; + shard_id_t shard_id, + bool object_is_legacy_ec = false, + uint64_t expected_size = 0) const; }; namespace fmt { diff --git a/src/osd/scrubber_common.h b/src/osd/scrubber_common.h index d52b57db4bb..7323502bec8 100644 --- a/src/osd/scrubber_common.h +++ b/src/osd/scrubber_common.h @@ -264,7 +264,8 @@ struct PgScrubBeListener { // query the PG backend for the on-disk size of an object virtual uint64_t logical_to_ondisk_size(uint64_t logical_size, - shard_id_t shard_id) const = 0; + shard_id_t shard_id, + bool object_is_legacy_ec) const = 0; // used to verify our "cleanliness" before scrubbing virtual bool is_waiting_for_unreadable_object() const = 0; diff --git a/src/test/osd/test_scrubber_be.cc b/src/test/osd/test_scrubber_be.cc index fc183a682cf..954fb13343e 100644 --- a/src/test/osd/test_scrubber_be.cc +++ b/src/test/osd/test_scrubber_be.cc @@ -91,7 +91,8 @@ class TestPg : public PgScrubBeListener { const pg_info_t& get_pg_info(ScrubberPasskey) const final { return m_info; } uint64_t logical_to_ondisk_size(uint64_t logical_size, - shard_id_t shard_id) const final + shard_id_t shard_id, + bool unused) const final { return logical_size; }