From 36c45bfbcb2a207f01a60f04a43cd7de9b337ae3 Mon Sep 17 00:00:00 2001 From: Kefu Chai Date: Fri, 7 Aug 2020 00:28:59 +0800 Subject: [PATCH] crimson/osd: support checksum op Signed-off-by: Kefu Chai --- src/crimson/osd/ops_executer.cc | 4 ++ src/crimson/osd/pg_backend.cc | 96 +++++++++++++++++++++++++++++++++ src/crimson/osd/pg_backend.h | 7 +++ 3 files changed, 107 insertions(+) diff --git a/src/crimson/osd/ops_executer.cc b/src/crimson/osd/ops_executer.cc index 52d02de08b817..9b51714ce1175 100644 --- a/src/crimson/osd/ops_executer.cc +++ b/src/crimson/osd/ops_executer.cc @@ -691,6 +691,10 @@ OpsExecuter::execute_osd_op(OSDOp& osd_op) return osd_op_errorator::now(); }); }); + case CEPH_OSD_OP_CHECKSUM: + return do_read_op([&osd_op] (auto& backend, const auto& os) { + return backend.checksum(os, osd_op); + }); case CEPH_OSD_OP_GETXATTR: return do_read_op([&osd_op] (auto& backend, const auto& os) { return backend.getxattr(os, osd_op); diff --git a/src/crimson/osd/pg_backend.cc b/src/crimson/osd/pg_backend.cc index fa78e13954487..749a0d304d08f 100644 --- a/src/crimson/osd/pg_backend.cc +++ b/src/crimson/osd/pg_backend.cc @@ -13,6 +13,7 @@ #include "messages/MOSDOp.h" #include "os/Transaction.h" +#include "common/Checksummer.h" #include "common/Clock.h" #include "crimson/common/exception.h" @@ -215,6 +216,101 @@ PGBackend::read(const object_info_t& oi, }); } +namespace { + + template + PGBackend::checksum_errorator::future<> + do_checksum(ceph::bufferlist& init_value_bl, + size_t chunk_size, + const ceph::bufferlist& buf, + ceph::bufferlist& result) + { + typename CSum::init_value_t init_value; + auto init_value_p = init_value_bl.cbegin(); + try { + decode(init_value, init_value_p); + // chop off the consumed part + init_value_bl.splice(0, init_value_p.get_off()); + } catch (const ceph::buffer::end_of_buffer&) { + logger().warn("{}: init value not provided", __func__); + return crimson::ct_error::invarg::make(); + } + const uint32_t chunk_count = buf.length() / chunk_size; + ceph::bufferptr csum_data{ + ceph::buffer::create(sizeof(typename CSum::value_t) * chunk_count)}; + Checksummer::calculate( + init_value, chunk_size, 0, buf.length(), buf, &csum_data); + encode(chunk_count, result); + result.append(std::move(csum_data)); + return PGBackend::checksum_errorator::now(); + } +} + +PGBackend::checksum_errorator::future<> +PGBackend::checksum(const ObjectState& os, OSDOp& osd_op) +{ + // sanity tests and normalize the argments + auto& checksum = osd_op.op.checksum; + if (checksum.offset == 0 && checksum.length == 0) { + // zeroed offset+length implies checksum whole object + checksum.length = os.oi.size; + } else if (checksum.offset >= os.oi.size) { + // read size was trimmed to zero, do nothing, + // see PGBackend::read() + return checksum_errorator::now(); + } + if (checksum.chunk_size > 0) { + if (checksum.length == 0) { + logger().warn("{}: length required when chunk size provided", __func__); + return crimson::ct_error::invarg::make(); + } + if (checksum.length % checksum.chunk_size != 0) { + logger().warn("{}: length not aligned to chunk size", __func__); + return crimson::ct_error::invarg::make(); + } + } else { + checksum.chunk_size = checksum.length; + } + if (checksum.length == 0) { + uint32_t count = 0; + encode(count, osd_op.outdata); + return checksum_errorator::now(); + } + + // read the chunk to be checksum'ed + return _read(os.oi.soid, checksum.offset, checksum.length, osd_op.op.flags).safe_then( + [&osd_op](auto&& read_bl) mutable -> checksum_errorator::future<> { + auto& checksum = osd_op.op.checksum; + if (read_bl.length() != checksum.length) { + logger().warn("checksum: bytes read {} != {}", + read_bl.length(), checksum.length); + return crimson::ct_error::invarg::make(); + } + // calculate its checksum and put the result in outdata + switch (checksum.type) { + case CEPH_OSD_CHECKSUM_OP_TYPE_XXHASH32: + return do_checksum(osd_op.indata, + checksum.chunk_size, + read_bl, + osd_op.outdata); + case CEPH_OSD_CHECKSUM_OP_TYPE_XXHASH64: + return do_checksum(osd_op.indata, + checksum.chunk_size, + read_bl, + osd_op.outdata); + case CEPH_OSD_CHECKSUM_OP_TYPE_CRC32C: + return do_checksum(osd_op.indata, + checksum.chunk_size, + read_bl, + osd_op.outdata); + default: + logger().warn("checksum: unknown crc type ({})", + static_cast(checksum.type)); + return crimson::ct_error::invarg::make(); + } + }); +} + PGBackend::stat_errorator::future<> PGBackend::stat( const ObjectState& os, OSDOp& osd_op) diff --git a/src/crimson/osd/pg_backend.h b/src/crimson/osd/pg_backend.h index 47337622db7d4..53ef45ea8a6ef 100644 --- a/src/crimson/osd/pg_backend.h +++ b/src/crimson/osd/pg_backend.h @@ -63,6 +63,13 @@ public: uint32_t truncate_seq, uint32_t flags); + using checksum_errorator = ll_read_errorator::extend< + crimson::ct_error::object_corrupted, + crimson::ct_error::invarg>; + checksum_errorator::future<> checksum( + const ObjectState& os, + OSDOp& osd_op); + using stat_errorator = crimson::errorator; stat_errorator::future<> stat( const ObjectState& os, -- 2.39.5