]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
osd: prepare ScrubMapBuilder::omap_hash for optimization
authorRadoslaw Zarzynski <rzarzyns@redhat.com>
Tue, 26 Nov 2024 00:52:32 +0000 (00:52 +0000)
committerRadoslaw Zarzynski <rzarzyns@redhat.com>
Fri, 4 Apr 2025 18:21:54 +0000 (18:21 +0000)
When `get_omap_iterator()` is replaced with `omap_iterate()`,
the CRC calculations will be happening in-place, with 0copy.

Signed-off-by: Radoslaw Zarzynski <rzarzyns@redhat.com>
src/osd/ReplicatedBackend.cc
src/osd/osd_types.h

index 9ee549eb1658915e2d3336b14926d4da9ba5aa51..e11a801cfdc8c2122ec8690c81bfcb02dfe87d5b 100644 (file)
@@ -720,6 +720,31 @@ void ReplicatedBackend::do_repop_reply(OpRequestRef op)
   maybe_kick_pct_update();
 }
 
+template <class T>
+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;
index 88f76c609a28e9a374f2700801ec1aba9b9cf437..724189ab72c1fbde7c7cf4e60858eab607be14ee 100644 (file)
@@ -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;