]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
os/bluestore: prototype Checksummer
authorSage Weil <sage@redhat.com>
Tue, 10 May 2016 00:34:13 +0000 (20:34 -0400)
committerSage Weil <sage@redhat.com>
Wed, 1 Jun 2016 15:38:44 +0000 (11:38 -0400)
Signed-off-by: Sage Weil <sage@redhat.com>
src/os/bluestore/BlueStore.cc
src/os/bluestore/Checksummer.h [new file with mode: 0644]

index dff3d8fdb7dc822c9ccb463d80992be05d734e3c..139c42d152e02ae6d2fde69b4b8fcabf1d78f751 100644 (file)
@@ -29,6 +29,7 @@
 #include "FreelistManager.h"
 #include "BlueFS.h"
 #include "BlueRocksEnv.h"
+#include "Checksummer.h"
 
 #define dout_subsys ceph_subsys_bluestore
 
diff --git a/src/os/bluestore/Checksummer.h b/src/os/bluestore/Checksummer.h
new file mode 100644 (file)
index 0000000..6ea4e80
--- /dev/null
@@ -0,0 +1,165 @@
+// -*- 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"
+#include "bluestore_types.h"
+
+class Checksummer {
+
+  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>
+  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>
+  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
+  }
+
+public:
+  int calculate(
+    unsigned type,  // bluestore_blob_t::CSumType
+    size_t csum_block_size,
+    size_t offset,
+    size_t length,
+    const bufferlist &bl,
+    vector<char>* csum_data
+    ) {
+    switch (type) {
+    case bluestore_blob_t::CSUM_NONE:
+      return 0;
+    case bluestore_blob_t::CSUM_XXHASH32:
+      return calculate<xxhash32>(csum_block_size, offset, length, bl, csum_data);
+    case bluestore_blob_t::CSUM_CRC32C:
+      return calculate<crc32c>(csum_block_size, offset, length, bl, csum_data);
+    default:
+      return -EOPNOTSUPP;
+    }
+  }
+  int verify(
+    unsigned type,  // bluestore_blob_t::CSumType
+    size_t csum_block_size,
+    size_t offset,
+    size_t length,
+    const bufferlist &bl,
+    const vector<char>& csum_data
+    ) {
+    switch (type) {
+    case bluestore_blob_t::CSUM_NONE:
+      return 0;
+    case bluestore_blob_t::CSUM_XXHASH32:
+      return verify<xxhash32>(csum_block_size, offset, length, bl, csum_data);
+    case bluestore_blob_t::CSUM_CRC32C:
+      return verify<crc32c>(csum_block_size, offset, length, bl, csum_data);
+    default:
+      return -EOPNOTSUPP;
+    }
+  }
+
+};
+
+#endif