From b92c919fdb94dc1a284ed9b24d0b4929afa15b7e Mon Sep 17 00:00:00 2001 From: Radoslaw Zarzynski Date: Tue, 26 Nov 2024 00:52:32 +0000 Subject: [PATCH] osd: prepare ScrubMapBuilder::omap_hash for optimization When `get_omap_iterator()` is replaced with `omap_iterate()`, the CRC calculations will be happening in-place, with 0copy. Signed-off-by: Radoslaw Zarzynski --- src/osd/ReplicatedBackend.cc | 39 +++++++++++++++++++++++++++--------- src/osd/osd_types.h | 3 ++- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/osd/ReplicatedBackend.cc b/src/osd/ReplicatedBackend.cc index 9ee549eb165..e11a801cfdc 100644 --- a/src/osd/ReplicatedBackend.cc +++ b/src/osd/ReplicatedBackend.cc @@ -720,6 +720,31 @@ void ReplicatedBackend::do_repop_reply(OpRequestRef op) maybe_kick_pct_update(); } +template +static uint32_t crc32_netstring(const uint32_t orig_crc, T data) +{ + // XXX: This function MUST be compliant with the bufferlist marshalling format! + // Otherwise scrubs-during-upgrade will explode. + __u32 len = data.length(); + auto crc = ceph_crc32c(orig_crc, (unsigned char*)&len, sizeof(len)); + crc = ceph_crc32c(crc, (unsigned char*)data.c_str(), data.length()); + +#ifndef _NDEBUG + // let's verify the compatibility but, due to performance penalty, + // only in debug builds. + ceph::bufferlist bl; + bl.append(data); + ceph::bufferlist bl_encoded; + encode(bl, bl_encoded); + ceph_assert(bl_encoded.crc32c(orig_crc) == crc); + // also as string view -- for the sake of keys + ceph::bufferlist sv_encoded; + encode(data, sv_encoded); + ceph_assert(sv_encoded.crc32c(orig_crc) == crc); +#endif + return crc; +} + int ReplicatedBackend::be_deep_scrub( const hobject_t &poid, ScrubMap &map, @@ -780,7 +805,7 @@ int ReplicatedBackend::be_deep_scrub( // omap header if (pos.omap_pos.empty()) { - pos.omap_hash = bufferhash(-1); + pos.omap_hash = -1; bufferlist hdrbl; r = store->omap_get_header( @@ -797,7 +822,7 @@ int ReplicatedBackend::be_deep_scrub( if (r == 0 && hdrbl.length()) { bool encoded = false; dout(25) << "CRC header " << cleanbin(hdrbl, encoded, true) << dendl; - pos.omap_hash << hdrbl; + pos.omap_hash = hdrbl.crc32c(pos.omap_hash); } } @@ -817,12 +842,8 @@ int ReplicatedBackend::be_deep_scrub( pos.omap_bytes += iter->value().length(); ++pos.omap_keys; --max; - // fixme: we can do this more efficiently. - bufferlist bl; - encode(iter->key(), bl); - encode(iter->value(), bl); - pos.omap_hash << bl; - + pos.omap_hash = crc32_netstring(pos.omap_hash, iter->key()); + pos.omap_hash = crc32_netstring(pos.omap_hash, iter->value()); iter->next(); if (iter->valid() && max == 0) { @@ -844,7 +865,7 @@ int ReplicatedBackend::be_deep_scrub( map.has_large_omap_object_errors = true; } - o.omap_digest = pos.omap_hash.digest(); + o.omap_digest = pos.omap_hash; o.omap_digest_present = true; dout(20) << __func__ << " done with " << poid << " omap_digest " << std::hex << o.omap_digest << std::dec << dendl; diff --git a/src/osd/osd_types.h b/src/osd/osd_types.h index 88f76c609a2..724189ab72c 100644 --- a/src/osd/osd_types.h +++ b/src/osd/osd_types.h @@ -6355,7 +6355,8 @@ struct ScrubMapBuilder { int64_t data_pos = 0; std::string omap_pos; int ret = 0; - ceph::buffer::hash data_hash, omap_hash; ///< accumulatinng hash value + ceph::buffer::hash data_hash; ///< accumulating hash value + uint32_t omap_hash; uint64_t omap_keys = 0; uint64_t omap_bytes = 0; -- 2.39.5