]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
os/bluestore/bluestore_types: simpler {calc,verify}_csum methods
authorSage Weil <sage@redhat.com>
Thu, 19 May 2016 10:51:09 +0000 (06:51 -0400)
committerSage Weil <sage@redhat.com>
Wed, 1 Jun 2016 15:38:50 +0000 (11:38 -0400)
This keeps the CSUM_* definitions local to blob_t, and avoids passing
arguments around.

Signed-off-by: Sage Weil <sage@redhat.com>
src/common/Checksummer.h [new file with mode: 0644]
src/common/Makefile.am
src/os/bluestore/bluestore_types.cc
src/os/bluestore/bluestore_types.h
src/test/objectstore/test_bluestore_types.cc

diff --git a/src/common/Checksummer.h b/src/common/Checksummer.h
new file mode 100644 (file)
index 0000000..aeb5389
--- /dev/null
@@ -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<class Alg>
+  static int calculate(
+    size_t csum_block_size,
+    size_t offset,
+    size_t length,
+    const bufferlist &bl,
+    vector<char>* 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<typename Alg::value_t*>(&(*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<class Alg>
+  static int verify(
+    size_t csum_block_size,
+    size_t offset,
+    size_t length,
+    const bufferlist &bl,
+    const vector<char>& 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<const typename Alg::value_t*>(&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
index 8b30eeadec17d05ed305e35266a9aa3c2b521e6d..a00859788dc8ff9d8e848707996c564c4f19b62a 100644 (file)
@@ -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 \
index 2d1048e7e80b457494442a85d77208d15c42a069..adbb536b344559fc837c8dccb64bd70afd5c326e 100644 (file)
@@ -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<Checksummer::xxhash32>(
+      get_csum_block_size(), b_off, bl.length(), bl, &csum_data);
+    break;
+  case CSUM_CRC32C:
+    Checksummer::calculate<Checksummer::crc32c>(
+      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<Checksummer::xxhash32>(
+      get_csum_block_size(), b_off, bl.length(), bl, csum_data);
+  case CSUM_CRC32C:
+    return Checksummer::verify<Checksummer::crc32c>(
+      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)
index 536accd9064d2fd98e7b8b3aaba672d17deca8a8..c39dd4255653d0bb7c3d730f178ff83139a07cc9 100644 (file)
@@ -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)
 
index 68fba229e4c9fdb5b6a7ee4a75320c295e574611..bfe24b5abc9449a0ecb8c33c5e8ab730425e13b6 100644 (file)
@@ -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;