From 2176457b3eeff2e0e5e09d5027e8e24212f8f8e4 Mon Sep 17 00:00:00 2001 From: Adam Emerson Date: Wed, 9 Aug 2023 22:00:24 -0400 Subject: [PATCH] neorados: Implement `ReadOp::checksum` Rather than using `buffer::list`s for initial values and hash results, serialize to/from the expected types. Signed-off-by: Adam Emerson --- src/include/neorados/RADOS.hpp | 43 ++++++++++++++++++++++++++ src/neorados/RADOS.cc | 56 ++++++++++++++++++++++++++++++++++ src/osdc/Objecter.h | 17 +++++++++++ 3 files changed, 116 insertions(+) diff --git a/src/include/neorados/RADOS.hpp b/src/include/neorados/RADOS.hpp index 3f86d4fc25f5e..cf7e309c5f233 100644 --- a/src/include/neorados/RADOS.hpp +++ b/src/include/neorados/RADOS.hpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -223,6 +224,33 @@ enum alloc_hint_t { }; } +namespace hash_alg { +struct xxhash32_t { + using init_value = std::uint32_t; + using hash_value = std::uint32_t; +}; +struct xxhash64_t { + using init_value = std::uint64_t; + using hash_value = std::uint64_t; +}; +struct crc32c_t { + using init_value = std::uint32_t; + using hash_value = std::uint32_t; +}; + +inline constexpr xxhash32_t xxhash32; +inline constexpr xxhash64_t xxhash64; +inline constexpr crc32c_t crc32c; +}; + +template +concept HashAlg = requires { + // Just enumerate, what's supported is what's on the OSD. + (std::is_same_v || + std::is_same_v || + std::is_same_v); +}; + class Op; class ReadOp; class WriteOp; @@ -476,6 +504,21 @@ public: return std::move(list_snaps(snaps, ec)); } + template + ReadOp& checksum(T, const typename T::init_value& iv, + std::uint64_t off, std::uint64_t len, + std::uint64_t chunk_size, + std::vector* out, + boost::system::error_code* ec = nullptr) &; + template + ReadOp&& checksum(T t, const typename T::init_value& iv, + std::uint64_t off, std::uint64_t len, + std::uint64_t chunk_size, + std::vector* out, + boost::system::error_code* ec = nullptr) && { + return std::move(checksum(t, iv, off, len, chunk_size, out, ec)); + } + // Chaining versions of functions from Op ReadOp& set_excl() & { Op::set_excl(); diff --git a/src/neorados/RADOS.cc b/src/neorados/RADOS.cc index d78b7cf71a16a..9ea9d95916a05 100644 --- a/src/neorados/RADOS.cc +++ b/src/neorados/RADOS.cc @@ -646,6 +646,62 @@ ReadOp& ReadOp::list_snaps(SnapSet* snaps, return *this; } +inline uint8_t checksum_op_type(hash_alg::xxhash32_t) { + return CEPH_OSD_CHECKSUM_OP_TYPE_XXHASH32; +} +inline uint8_t checksum_op_type(hash_alg::xxhash64_t) { + return CEPH_OSD_CHECKSUM_OP_TYPE_XXHASH64; +} +inline uint8_t checksum_op_type(hash_alg::crc32c_t) { + return CEPH_OSD_CHECKSUM_OP_TYPE_CRC32C; +} + +template +ReadOp& ReadOp::checksum(T t, const typename T::init_value& iv, + std::uint64_t off, std::uint64_t len, + std::uint64_t chunk_size, + std::vector* out, + boost::system::error_code* ec) & { + using ceph::encode; + buffer::list init_bl; + encode(iv, init_bl); + // If this isn't the case we have a programming error + assert(init_bl.length() == sizeof(typename T::init_value)); + reinterpret_cast(&impl)->op. + checksum(checksum_op_type(t), std::move(init_bl), + off, len, chunk_size, + [out](bs::error_code ec, int, const buffer::list& bl) { + if (!ec) { + std::vector v; + auto bi = bl.begin(); + decode(v, bi); + if (out) { + *out = std::move(v); + }; + } + }, ec); + return *this; +} + +template +ReadOp& ReadOp::checksum( + hash_alg::xxhash32_t, const typename hash_alg::xxhash32_t::init_value&, + std::uint64_t off, std::uint64_t len, std::uint64_t chunk_size, + std::vector* out, + boost::system::error_code* ec) &; +template +ReadOp& ReadOp::checksum( + hash_alg::xxhash64_t, const typename hash_alg::xxhash64_t::init_value&, + std::uint64_t off, std::uint64_t len, std::uint64_t chunk_size, + std::vector* out, + boost::system::error_code* ec) &; +template +ReadOp& ReadOp::checksum( + hash_alg::crc32c_t, const typename hash_alg::crc32c_t::init_value&, + std::uint64_t off, std::uint64_t len, std::uint64_t chunk_size, + std::vector* out, + boost::system::error_code* ec) &; + // WriteOp WriteOp& WriteOp::set_mtime(ceph::real_time t) & { diff --git a/src/osdc/Objecter.h b/src/osdc/Objecter.h index 3cfcb2d68800a..7ee4b4de9fe41 100644 --- a/src/osdc/Objecter.h +++ b/src/osdc/Objecter.h @@ -605,6 +605,23 @@ struct ObjectOperation { set_handler(ctx); } + void checksum(uint8_t type, ceph::buffer::list&& init_value, + uint64_t off, uint64_t len, size_t chunk_size, + fu2::unique_function f, + boost::system::error_code* ec) { + OSDOp& osd_op = add_op(CEPH_OSD_OP_CHECKSUM); + osd_op.op.checksum.offset = off; + osd_op.op.checksum.length = len; + osd_op.op.checksum.type = type; + osd_op.op.checksum.chunk_size = chunk_size; + osd_op.indata.append(std::move(init_value)); + + unsigned p = ops.size() - 1; + out_ec[p] = ec; + set_handler(std::move(f)); + } + // object attrs void getxattr(const char *name, ceph::buffer::list *pbl, int *prval) { ceph::buffer::list bl; -- 2.39.5