From: Alex Ainscow Date: Wed, 8 Oct 2025 10:54:49 +0000 (+0100) 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=9609410db0df8879af4c8aacf2ff37b141d1bbcd;p=ceph.git osd: Make scrub determine the correct object size. Signed-off-by: Alex Ainscow --- diff --git a/src/osd/ECBackend.h b/src/osd/ECBackend.h index c8b9ccdef971..e23cd127a0c1 100644 --- a/src/osd/ECBackend.h +++ b/src/osd/ECBackend.h @@ -373,8 +373,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 94f165a74dd4..e20aacab5a0c 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 3bef1c8c5e44..40dfc4594095 100644 --- a/src/osd/PG.h +++ b/src/osd/PG.h @@ -1414,8 +1414,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); } bool ec_can_decode(const shard_id_set &available_shards) const final { diff --git a/src/osd/PGBackend.h b/src/osd/PGBackend.h index 768eee302cd4..50a8455c54c1 100644 --- a/src/osd/PGBackend.h +++ b/src/osd/PGBackend.h @@ -624,7 +624,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 a1cd8a84f12a..d814315d95a9 100644 --- a/src/osd/ReplicatedBackend.h +++ b/src/osd/ReplicatedBackend.h @@ -475,7 +475,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 8def2cef7213..98d0dbe65d19 100644 --- a/src/osd/scrubber/scrub_backend.cc +++ b/src/osd/scrubber/scrub_backend.cc @@ -116,9 +116,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; } uint32_t ScrubBackend::generate_zero_buffer_crc(shard_id_t shard_id, @@ -819,7 +839,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)) { @@ -1500,7 +1522,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 {}", @@ -1682,12 +1706,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 7b0bdaf1d9eb..195024261779 100644 --- a/src/osd/scrubber/scrub_backend.h +++ b/src/osd/scrubber/scrub_backend.h @@ -556,7 +556,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; uint32_t generate_zero_buffer_crc(shard_id_t shard_id, int length) const; }; diff --git a/src/osd/scrubber_common.h b/src/osd/scrubber_common.h index b814d01fa85a..76ca94a7085a 100644 --- a/src/osd/scrubber_common.h +++ b/src/osd/scrubber_common.h @@ -266,7 +266,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 4bab20dd889e..42d493375e3f 100644 --- a/src/test/osd/test_scrubber_be.cc +++ b/src/test/osd/test_scrubber_be.cc @@ -95,7 +95,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; }