From: Sage Weil Date: Thu, 19 May 2016 10:51:09 +0000 (-0400) Subject: os/bluestore/bluestore_types: simpler {calc,verify}_csum methods X-Git-Tag: v11.0.0~359^2~65 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=0bc8066dc7c1992fbbd58dda68bf660ca0029c17;p=ceph.git os/bluestore/bluestore_types: simpler {calc,verify}_csum methods This keeps the CSUM_* definitions local to blob_t, and avoids passing arguments around. Signed-off-by: Sage Weil --- diff --git a/src/common/Checksummer.h b/src/common/Checksummer.h new file mode 100644 index 000000000000..aeb538925fb4 --- /dev/null +++ b/src/common/Checksummer.h @@ -0,0 +1,123 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_OS_BLUESTORE_CHECKSUMMER +#define CEPH_OS_BLUESTORE_CHECKSUMMER + +#include "include/buffer.h" +#include "xxHash/xxhash.h" + +class Checksummer { +public: + struct crc32c { + typedef __le32 value_t; + + // we have no execution context/state. + typedef int state_t; + static void init(state_t *state) { + } + static void fini(state_t *state) { + } + + static value_t calc( + state_t state, + size_t len, + bufferlist::const_iterator& p + ) { + bufferlist t; + p.copy(len, t); + return t.crc32c(-1); + } + }; + + struct xxhash32 { + typedef __le32 value_t; + + typedef XXH32_state_t *state_t; + static void init(state_t *s) { + *s = XXH32_createState(); + } + static void fini(state_t *s) { + XXH32_freeState(*s); + } + + static value_t calc( + state_t state, + size_t len, + bufferlist::const_iterator& p + ) { + XXH32_reset(state, -1); + while (len > 0) { + const char *data; + size_t l = p.get_ptr_and_advance(len, &data); + XXH32_update(state, data, l); + len -= l; + } + return XXH32_digest(state); + } + }; + + template + static int calculate( + size_t csum_block_size, + size_t offset, + size_t length, + const bufferlist &bl, + vector* csum_data + ) { + assert(length % csum_block_size == 0); + size_t blocks = length / csum_block_size; + bufferlist::const_iterator p = bl.begin(); + assert(bl.length() >= length); + + typename Alg::state_t state; + Alg::init(&state); + + assert(csum_data->size() >= (offset + length) / csum_block_size * + sizeof(typename Alg::value_t)); + + typename Alg::value_t *pv = + reinterpret_cast(&(*csum_data)[0]); + pv += offset / csum_block_size; + while (blocks--) { + *pv = Alg::calc(state, csum_block_size, p); + ++pv; + } + Alg::fini(&state); + return 0; + } + + template + static int verify( + size_t csum_block_size, + size_t offset, + size_t length, + const bufferlist &bl, + const vector& csum_data + ) { + assert(length % csum_block_size == 0); + bufferlist::const_iterator p = bl.begin(); + assert(bl.length() >= length); + + typename Alg::state_t state; + Alg::init(&state); + + const typename Alg::value_t *pv = + reinterpret_cast(&csum_data[0]); + pv += offset / csum_block_size; + size_t pos = offset; + while (length > 0) { + typename Alg::value_t v = Alg::calc(state, csum_block_size, p); + if (*pv != v) { + return pos; + } + ++pv; + pos += csum_block_size; + length -= csum_block_size; + } + Alg::fini(&state); + return -1; // no errors + } +}; + +#endif diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 8b30eeadec17..a00859788dc8 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -179,6 +179,7 @@ noinst_LTLIBRARIES += libcommon.la noinst_HEADERS += \ common/BackTrace.h \ + common/Checksummer.h \ common/RefCountedObj.h \ common/HeartbeatMap.h \ common/LogClient.h \ diff --git a/src/os/bluestore/bluestore_types.cc b/src/os/bluestore/bluestore_types.cc index 2d1048e7e80b..adbb536b3445 100644 --- a/src/os/bluestore/bluestore_types.cc +++ b/src/os/bluestore/bluestore_types.cc @@ -14,6 +14,7 @@ #include "bluestore_types.h" #include "common/Formatter.h" +#include "common/Checksummer.h" #include "include/stringify.h" // bluestore_bdev_label_t @@ -521,6 +522,36 @@ ostream& operator<<(ostream& out, const bluestore_blob_t& o) return out; } +void bluestore_blob_t::calc_csum(uint64_t b_off, const bufferlist& bl) +{ + switch (csum_type) { + case CSUM_XXHASH32: + Checksummer::calculate( + get_csum_block_size(), b_off, bl.length(), bl, &csum_data); + break; + case CSUM_CRC32C: + Checksummer::calculate( + get_csum_block_size(), b_off, bl.length(), bl, &csum_data); + break; + } +} + +int bluestore_blob_t::verify_csum(uint64_t b_off, const bufferlist& bl) const +{ + switch (csum_type) { + case CSUM_NONE: + return -1; + case CSUM_XXHASH32: + return Checksummer::verify( + get_csum_block_size(), b_off, bl.length(), bl, csum_data); + case CSUM_CRC32C: + return Checksummer::verify( + get_csum_block_size(), b_off, bl.length(), bl, csum_data); + default: + return -EOPNOTSUPP; + } +} + // bluestore_lextent_t string bluestore_lextent_t::get_flags_string(unsigned flags) diff --git a/src/os/bluestore/bluestore_types.h b/src/os/bluestore/bluestore_types.h index 536accd9064d..c39dd4255653 100644 --- a/src/os/bluestore/bluestore_types.h +++ b/src/os/bluestore/bluestore_types.h @@ -420,6 +420,13 @@ struct bluestore_blob_t { csum_block_order = order; csum_data.resize(get_csum_value_size() * len / get_csum_block_size()); } + + /// calculate csum for the buffer at the given b_off + void calc_csum(uint64_t b_off, const bufferlist& bl); + + /// verify csum: return offset of error, or -1 for no error. + int verify_csum(uint64_t b_off, const bufferlist& bl) const; + }; WRITE_CLASS_ENCODER(bluestore_blob_t) diff --git a/src/test/objectstore/test_bluestore_types.cc b/src/test/objectstore/test_bluestore_types.cc index 68fba229e4c9..bfe24b5abc94 100644 --- a/src/test/objectstore/test_bluestore_types.cc +++ b/src/test/objectstore/test_bluestore_types.cc @@ -188,6 +188,47 @@ TEST(bluestore_extent_ref_map_t, intersects) ASSERT_FALSE(m.intersects(55, 1)); } +TEST(bluestore_blob_t, calc_csum) +{ + bufferlist bl; + bl.append("asdfqwerzxcv"); + bufferlist bl2; + bl2.append("xxxxyyyyzzzz"); + bluestore_blob_t b; + ASSERT_EQ(-1, b.verify_csum(0, bl)); + + b.init_csum(bluestore_blob_t::CSUM_CRC32C, 2, 12); + b.calc_csum(0, bl); + ASSERT_EQ(-1, b.verify_csum(0, bl)); + ASSERT_EQ(0, b.verify_csum(0, bl2)); + + bufferlist f; + f.substr_of(bl, 0, 4); + ASSERT_EQ(-1, b.verify_csum(0, f)); + ASSERT_EQ(4, b.verify_csum(4, f)); + ASSERT_EQ(8, b.verify_csum(8, f)); + + bufferlist m; + m.substr_of(bl, 4, 4); + ASSERT_EQ(0, b.verify_csum(0, m)); + ASSERT_EQ(-1, b.verify_csum(4, m)); + ASSERT_EQ(8, b.verify_csum(8, m)); + + bufferlist e; + e.substr_of(bl, 8, 4); + ASSERT_EQ(0, b.verify_csum(0, e)); + ASSERT_EQ(4, b.verify_csum(4, e)); + ASSERT_EQ(-1, b.verify_csum(8, e)); + + bufferlist n; + n.append("xxxx"); + b.calc_csum(4, n); + ASSERT_EQ(-1, b.verify_csum(0, f)); + ASSERT_EQ(-1, b.verify_csum(4, n)); + ASSERT_EQ(-1, b.verify_csum(8, e)); + ASSERT_EQ(4, b.verify_csum(0, bl)); +} + TEST(bluestore_onode_t, find_lextent) { bluestore_onode_t on;