diff --git a/src/common/buffer.cc b/src/common/buffer.cc index b1417591bff5c..9ee2bfedf3411 100644 --- a/src/common/buffer.cc +++ b/src/common/buffer.cc @@ -230,20 +230,23 @@ static simple_spinlock_t buffer_debug_lock = SIMPLE_SPINLOCK_INITIALIZER; }; class buffer::raw_posix_aligned : public buffer::raw { + unsigned align; public: - raw_posix_aligned(unsigned l) : raw(l) { + raw_posix_aligned(unsigned l, unsigned _align) : raw(l) { + align = _align; + assert((align >= sizeof(void *)) && (align & (align - 1)) == 0); #ifdef DARWIN data = (char *) valloc (len); #else data = 0; - int r = ::posix_memalign((void**)(void*)&data, CEPH_PAGE_SIZE, len); + int r = ::posix_memalign((void**)(void*)&data, align, len); if (r) throw bad_alloc(); #endif /* DARWIN */ if (!data) throw bad_alloc(); inc_total_alloc(len); - bdout << "raw_posix_aligned " << this << " alloc " << (void *)data << " " << l << " " << buffer::get_total_alloc() << bendl; + bdout << "raw_posix_aligned " << this << " alloc " << (void *)data << " l=" << l << ", align=" << align << " total_alloc=" << buffer::get_total_alloc() << bendl; } ~raw_posix_aligned() { ::free((void*)data); @@ -251,34 +254,36 @@ static simple_spinlock_t buffer_debug_lock = SIMPLE_SPINLOCK_INITIALIZER; bdout << "raw_posix_aligned " << this << " free " << (void *)data << " " << buffer::get_total_alloc() << bendl; } raw* clone_empty() { - return new raw_posix_aligned(len); + return new raw_posix_aligned(len, align); } }; #endif #ifdef __CYGWIN__ class buffer::raw_hack_aligned : public buffer::raw { + unsigned align; char *realdata; public: - raw_hack_aligned(unsigned l) : raw(l) { - realdata = new char[len+CEPH_PAGE_SIZE-1]; - unsigned off = ((unsigned)realdata) & ~CEPH_PAGE_MASK; + raw_hack_aligned(unsigned l, unsigned _align) : raw(l) { + align = _align; + realdata = new char[len+align-1]; + unsigned off = ((unsigned)realdata) & (align-1); if (off) - data = realdata + CEPH_PAGE_SIZE - off; + data = realdata + align - off; else data = realdata; - inc_total_alloc(len+CEPH_PAGE_SIZE-1); + inc_total_alloc(len+align-1); //cout << "hack aligned " << (unsigned)data //<< " in raw " << (unsigned)realdata //<< " off " << off << std::endl; - assert(((unsigned)data & (CEPH_PAGE_SIZE-1)) == 0); + assert(((unsigned)data & (align-1)) == 0); } ~raw_hack_aligned() { delete[] realdata; - dec_total_alloc(len+CEPH_PAGE_SIZE-1); + dec_total_alloc(len+align-1); } raw* clone_empty() { - return new raw_hack_aligned(len); + return new raw_hack_aligned(len, align); } }; #endif @@ -334,10 +339,6 @@ static simple_spinlock_t buffer_debug_lock = SIMPLE_SPINLOCK_INITIALIZER; return true; } - bool is_page_aligned() { - return false; - } - int set_source(int fd, loff_t *off) { int flags = SPLICE_F_NONBLOCK; ssize_t r = safe_splice(fd, off, pipefds[1], NULL, len, flags); @@ -520,14 +521,17 @@ static simple_spinlock_t buffer_debug_lock = SIMPLE_SPINLOCK_INITIALIZER; buffer::raw* buffer::create_static(unsigned len, char *buf) { return new raw_static(buf, len); } - buffer::raw* buffer::create_page_aligned(unsigned len) { + buffer::raw* buffer::create_aligned(unsigned len, unsigned align) { #ifndef __CYGWIN__ //return new raw_mmap_pages(len); - return new raw_posix_aligned(len); + return new raw_posix_aligned(len, align); #else - return new raw_hack_aligned(len); + return new raw_hack_aligned(len, align); #endif } + buffer::raw* buffer::create_page_aligned(unsigned len) { + return create_aligned(len, CEPH_PAGE_SIZE); + } buffer::raw* buffer::create_zero_copy(unsigned len, int fd, int64_t *offset) { #ifdef CEPH_HAVE_SPLICE @@ -1013,22 +1017,22 @@ static simple_spinlock_t buffer_debug_lock = SIMPLE_SPINLOCK_INITIALIZER; return true; } - bool buffer::list::is_page_aligned() const + bool buffer::list::is_aligned(unsigned align) const { for (std::list::const_iterator it = _buffers.begin(); it != _buffers.end(); ++it) - if (!it->is_page_aligned()) + if (!it->is_aligned(align)) return false; return true; } - bool buffer::list::is_n_page_sized() const + bool buffer::list::is_n_align_sized(unsigned align) const { for (std::list::const_iterator it = _buffers.begin(); it != _buffers.end(); ++it) - if (!it->is_n_page_sized()) + if (!it->is_n_align_sized(align)) return false; return true; } @@ -1078,6 +1082,16 @@ static simple_spinlock_t buffer_debug_lock = SIMPLE_SPINLOCK_INITIALIZER; return &(*_buffers.begin()) == &(*_buffers.rbegin()); } + bool buffer::list::is_n_page_sized() const + { + return is_n_align_sized(CEPH_PAGE_SIZE); + } + + bool buffer::list::is_page_aligned() const + { + return is_aligned(CEPH_PAGE_SIZE); + } + void buffer::list::rebuild() { ptr nb; @@ -1101,16 +1115,16 @@ static simple_spinlock_t buffer_debug_lock = SIMPLE_SPINLOCK_INITIALIZER; _buffers.push_back(nb); } -void buffer::list::rebuild_page_aligned() +void buffer::list::rebuild_aligned(unsigned align) { std::list::iterator p = _buffers.begin(); while (p != _buffers.end()) { - // keep anything that's already page sized+aligned - if (p->is_page_aligned() && p->is_n_page_sized()) { + // keep anything that's already align and sized aligned + if (p->is_aligned(align) && p->is_n_align_sized(align)) { /*cout << " segment " << (void*)p->c_str() - << " offset " << ((unsigned long)p->c_str() & ~CEPH_PAGE_MASK) + << " offset " << ((unsigned long)p->c_str() & (align - 1)) << " length " << p->length() - << " " << (p->length() & ~CEPH_PAGE_MASK) << " ok" << std::endl; + << " " << (p->length() & (align - 1)) << " ok" << std::endl; */ ++p; continue; @@ -1121,26 +1135,31 @@ void buffer::list::rebuild_page_aligned() unsigned offset = 0; do { /*cout << " segment " << (void*)p->c_str() - << " offset " << ((unsigned long)p->c_str() & ~CEPH_PAGE_MASK) - << " length " << p->length() << " " << (p->length() & ~CEPH_PAGE_MASK) - << " overall offset " << offset << " " << (offset & ~CEPH_PAGE_MASK) + << " offset " << ((unsigned long)p->c_str() & (align - 1)) + << " length " << p->length() << " " << (p->length() & (align - 1)) + << " overall offset " << offset << " " << (offset & (align - 1)) << " not ok" << std::endl; */ offset += p->length(); unaligned.push_back(*p); _buffers.erase(p++); } while (p != _buffers.end() && - (!p->is_page_aligned() || - !p->is_n_page_sized() || - (offset & ~CEPH_PAGE_MASK))); - if (!(unaligned.is_contiguous() && unaligned._buffers.front().is_page_aligned())) { - ptr nb(buffer::create_page_aligned(unaligned._len)); + (!p->is_aligned(align) || + !p->is_n_align_sized(align) || + (offset & (align-1)))); + if (!(unaligned.is_contiguous() && unaligned._buffers.front().is_aligned(align))) { + ptr nb(buffer::create_aligned(unaligned._len, align)); unaligned.rebuild(nb); } _buffers.insert(p, unaligned._buffers.front()); } } +void buffer::list::rebuild_page_aligned() +{ + rebuild_aligned(CEPH_PAGE_SIZE); +} + // sort-of-like-assignment-op void buffer::list::claim(list& bl) { diff --git a/src/erasure-code/ErasureCode.cc b/src/erasure-code/ErasureCode.cc index 5953f496392bc..96a6b39c7d383 100644 --- a/src/erasure-code/ErasureCode.cc +++ b/src/erasure-code/ErasureCode.cc @@ -22,6 +22,13 @@ #include "common/strtol.h" #include "ErasureCode.h" +const unsigned ErasureCode::SIMD_ALIGN = 32; + +int ErasureCode::chunk_index(unsigned int i) const +{ + return chunk_mapping.size() > i ? chunk_mapping[i] : i; +} + int ErasureCode::minimum_to_decode(const set &want_to_read, const set &available_chunks, set *minimum) @@ -54,22 +61,46 @@ int ErasureCode::minimum_to_decode_with_cost(const set &want_to_read, } int ErasureCode::encode_prepare(const bufferlist &raw, - bufferlist *prepared) const + map &encoded) const { unsigned int k = get_data_chunk_count(); unsigned int m = get_chunk_count() - k; unsigned blocksize = get_chunk_size(raw.length()); - unsigned padded_length = blocksize * k; - *prepared = raw; - if (padded_length - raw.length() > 0) { - bufferptr pad(padded_length - raw.length()); - pad.zero(); - prepared->push_back(pad); + unsigned pad_len = blocksize * k - raw.length(); + unsigned padded_chunks = k - raw.length() / blocksize; + bufferlist prepared = raw; + + if (!prepared.is_aligned(SIMD_ALIGN)) { + // splice padded chunks off to make the rebuild faster + if (padded_chunks) + prepared.splice((k - padded_chunks) * blocksize, + padded_chunks * blocksize - pad_len); + prepared.rebuild_aligned(SIMD_ALIGN); + } + + for (unsigned int i = 0; i < k - padded_chunks; i++) { + bufferlist &chunk = encoded[chunk_index(i)]; + chunk.substr_of(prepared, i * blocksize, blocksize); } - unsigned coding_length = blocksize * m; - bufferptr coding(buffer::create_page_aligned(coding_length)); - prepared->push_back(coding); - prepared->rebuild_page_aligned(); + if (padded_chunks) { + unsigned remainder = raw.length() - (k - padded_chunks) * blocksize; + bufferptr buf(buffer::create_aligned(blocksize, SIMD_ALIGN)); + + raw.copy((k - padded_chunks) * blocksize, remainder, buf.c_str()); + buf.zero(remainder, blocksize - remainder); + encoded[chunk_index(k-padded_chunks)].push_back(buf); + + for (unsigned int i = k - padded_chunks + 1; i < k; i++) { + bufferptr buf(buffer::create_aligned(blocksize, SIMD_ALIGN)); + buf.zero(); + encoded[chunk_index(i)].push_back(buf); + } + } + for (unsigned int i = k; i < k + m; i++) { + bufferlist &chunk = encoded[chunk_index(i)]; + chunk.push_back(buffer::create_aligned(blocksize, SIMD_ALIGN)); + } + return 0; } @@ -80,15 +111,9 @@ int ErasureCode::encode(const set &want_to_encode, unsigned int k = get_data_chunk_count(); unsigned int m = get_chunk_count() - k; bufferlist out; - int err = encode_prepare(in, &out); + int err = encode_prepare(in, *encoded); if (err) return err; - unsigned blocksize = get_chunk_size(in.length()); - for (unsigned int i = 0; i < k + m; i++) { - int chunk_index = chunk_mapping.size() > 0 ? chunk_mapping[i] : i; - bufferlist &chunk = (*encoded)[chunk_index]; - chunk.substr_of(out, i * blocksize, blocksize); - } encode_chunks(want_to_encode, encoded); for (unsigned int i = 0; i < k + m; i++) { if (want_to_encode.count(i) == 0) @@ -128,11 +153,11 @@ int ErasureCode::decode(const set &want_to_read, unsigned blocksize = (*chunks.begin()).second.length(); for (unsigned int i = 0; i < k + m; i++) { if (chunks.find(i) == chunks.end()) { - bufferptr ptr(buffer::create_page_aligned(blocksize)); + bufferptr ptr(buffer::create_aligned(blocksize, SIMD_ALIGN)); (*decoded)[i].push_front(ptr); } else { (*decoded)[i] = chunks.find(i)->second; - (*decoded)[i].rebuild_page_aligned(); + (*decoded)[i].rebuild_aligned(SIMD_ALIGN); } } return decode_chunks(want_to_read, chunks, decoded); @@ -223,15 +248,13 @@ int ErasureCode::decode_concat(const map &chunks, set want_to_read; for (unsigned int i = 0; i < get_data_chunk_count(); i++) { - int chunk = chunk_mapping.size() > i ? chunk_mapping[i] : i; - want_to_read.insert(chunk); + want_to_read.insert(chunk_index(i)); } map decoded_map; int r = decode(want_to_read, chunks, &decoded_map); if (r == 0) { for (unsigned int i = 0; i < get_data_chunk_count(); i++) { - int chunk = chunk_mapping.size() > i ? chunk_mapping[i] : i; - decoded->claim_append(decoded_map[chunk]); + decoded->claim_append(decoded_map[chunk_index(i)]); } } return r; diff --git a/src/erasure-code/ErasureCode.h b/src/erasure-code/ErasureCode.h index 7aaea951713b6..b135ade99d4d2 100644 --- a/src/erasure-code/ErasureCode.h +++ b/src/erasure-code/ErasureCode.h @@ -30,6 +30,8 @@ namespace ceph { class ErasureCode : public ErasureCodeInterface { public: + static const unsigned SIMD_ALIGN; + vector chunk_mapping; virtual ~ErasureCode() {} @@ -46,7 +48,8 @@ namespace ceph { const map &available, set *minimum); - int encode_prepare(const bufferlist &raw, bufferlist *prepared) const; + int encode_prepare(const bufferlist &raw, + map &encoded) const; virtual int encode(const set &want_to_encode, const bufferlist &in, @@ -85,6 +88,9 @@ namespace ceph { virtual int decode_concat(const map &chunks, bufferlist *decoded); + + private: + int chunk_index(unsigned int i) const; }; } diff --git a/src/include/buffer.h b/src/include/buffer.h index e5c1b50535844..3cd0a7a19a072 100644 --- a/src/include/buffer.h +++ b/src/include/buffer.h @@ -144,6 +144,7 @@ class buffer { static raw* create_malloc(unsigned len); static raw* claim_malloc(unsigned len, char *buf); static raw* create_static(unsigned len, char *buf); + static raw* create_aligned(unsigned len, unsigned align); static raw* create_page_aligned(unsigned len); static raw* create_zero_copy(unsigned len, int fd, int64_t *offset); @@ -177,8 +178,15 @@ class buffer { bool at_buffer_head() const { return _off == 0; } bool at_buffer_tail() const; - bool is_page_aligned() const { return ((long)c_str() & ~CEPH_PAGE_MASK) == 0; } - bool is_n_page_sized() const { return (length() & ~CEPH_PAGE_MASK) == 0; } + bool is_aligned(unsigned align) const { + return ((long)c_str() & (align-1)) == 0; + } + bool is_page_aligned() const { return is_aligned(CEPH_PAGE_SIZE); } + bool is_n_align_sized(unsigned align) const + { + return (length() & (align-1)) == 0; + } + bool is_n_page_sized() const { return is_n_align_sized(CEPH_PAGE_SIZE); } // accessors raw *get_raw() const { return _raw; } @@ -344,7 +352,9 @@ class buffer { bool contents_equal(buffer::list& other); bool can_zero_copy() const; + bool is_aligned(unsigned align) const; bool is_page_aligned() const; + bool is_n_align_sized(unsigned align) const; bool is_n_page_sized() const; bool is_zero() const; @@ -382,6 +392,7 @@ class buffer { bool is_contiguous(); void rebuild(); void rebuild(ptr& nb); + void rebuild_aligned(unsigned align); void rebuild_page_aligned(); // sort-of-like-assignment-op diff --git a/src/test/bufferlist.cc b/src/test/bufferlist.cc index 3b379afded58b..da4d33ff2b4d9 100644 --- a/src/test/bufferlist.cc +++ b/src/test/bufferlist.cc @@ -1122,6 +1122,52 @@ TEST(BufferList, contents_equal) { ASSERT_FALSE(bl1.contents_equal(bl3)); // same length different content } +TEST(BufferList, is_aligned) { + const int SIMD_ALIGN = 32; + { + bufferlist bl; + EXPECT_TRUE(bl.is_aligned(SIMD_ALIGN)); + } + { + bufferlist bl; + bufferptr ptr(buffer::create_aligned(2, SIMD_ALIGN)); + ptr.set_offset(1); + ptr.set_length(1); + bl.append(ptr); + EXPECT_FALSE(bl.is_aligned(SIMD_ALIGN)); + bl.rebuild_aligned(SIMD_ALIGN); + EXPECT_TRUE(bl.is_aligned(SIMD_ALIGN)); + } + { + bufferlist bl; + bufferptr ptr(buffer::create_aligned(SIMD_ALIGN + 1, SIMD_ALIGN)); + ptr.set_offset(1); + ptr.set_length(SIMD_ALIGN); + bl.append(ptr); + EXPECT_FALSE(bl.is_aligned(SIMD_ALIGN)); + bl.rebuild_aligned(SIMD_ALIGN); + EXPECT_TRUE(bl.is_aligned(SIMD_ALIGN)); + } +} + +TEST(BufferList, is_n_align_sized) { + const int SIMD_ALIGN = 32; + { + bufferlist bl; + EXPECT_TRUE(bl.is_n_align_sized(SIMD_ALIGN)); + } + { + bufferlist bl; + bl.append_zero(1); + EXPECT_FALSE(bl.is_n_align_sized(SIMD_ALIGN)); + } + { + bufferlist bl; + bl.append_zero(SIMD_ALIGN); + EXPECT_TRUE(bl.is_n_align_sized(SIMD_ALIGN)); + } +} + TEST(BufferList, is_page_aligned) { { bufferlist bl; diff --git a/src/test/erasure-code/Makefile.am b/src/test/erasure-code/Makefile.am index 6cef35958e710..60f6ee1e967fe 100644 --- a/src/test/erasure-code/Makefile.am +++ b/src/test/erasure-code/Makefile.am @@ -2,6 +2,7 @@ check_SCRIPTS += \ test/erasure-code/test-erasure-code.sh ceph_erasure_code_benchmark_SOURCES = \ + erasure-code/ErasureCode.cc \ test/erasure-code/ceph_erasure_code_benchmark.cc ceph_erasure_code_benchmark_LDADD = $(LIBOSD) $(LIBCOMMON) $(BOOST_PROGRAM_OPTIONS_LIBS) $(CEPH_GLOBAL) if LINUX @@ -9,6 +10,9 @@ ceph_erasure_code_benchmark_LDADD += -ldl endif bin_DEBUGPROGRAMS += ceph_erasure_code_benchmark +noinst_HEADERS += \ + test/erasure-code/ceph_erasure_code_benchmark.h + ceph_erasure_code_SOURCES = \ test/erasure-code/ceph_erasure_code.cc ceph_erasure_code_LDADD = $(LIBOSD) $(LIBCOMMON) $(BOOST_PROGRAM_OPTIONS_LIBS) $(CEPH_GLOBAL) @@ -98,6 +102,13 @@ unittest_erasure_code_plugin_LDADD += -ldl endif check_PROGRAMS += unittest_erasure_code_plugin +unittest_erasure_code_SOURCES = \ + erasure-code/ErasureCode.cc \ + test/erasure-code/TestErasureCode.cc +unittest_erasure_code_CXXFLAGS = $(UNITTEST_CXXFLAGS) +unittest_erasure_code_LDADD = $(LIBOSD) $(LIBCOMMON) $(UNITTEST_LDADD) $(CEPH_GLOBAL) +check_PROGRAMS += unittest_erasure_code + unittest_erasure_code_jerasure_SOURCES = \ test/erasure-code/TestErasureCodeJerasure.cc \ ${jerasure_sources} @@ -170,6 +181,3 @@ noinst_HEADERS += test/erasure-code/ErasureCodeExample.h unittest_erasure_code_example_CXXFLAGS = $(UNITTEST_CXXFLAGS) unittest_erasure_code_example_LDADD = $(LIBOSD) $(LIBCOMMON) $(UNITTEST_LDADD) $(CEPH_GLOBAL) check_PROGRAMS += unittest_erasure_code_example - -noinst_HEADERS += \ - test/erasure-code/ceph_erasure_code_benchmark.h diff --git a/src/test/erasure-code/TestErasureCode.cc b/src/test/erasure-code/TestErasureCode.cc new file mode 100644 index 0000000000000..c572cdc59eabd --- /dev/null +++ b/src/test/erasure-code/TestErasureCode.cc @@ -0,0 +1,134 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph distributed storage system + * + * Copyright (C) 2014 Red Hat + * + * Author: Loic Dachary + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + */ + +#include + +#include "global/global_init.h" +#include "erasure-code/ErasureCode.h" +#include "common/ceph_argparse.h" +#include "global/global_context.h" +#include "gtest/gtest.h" + +class ErasureCodeTest : public ErasureCode { +public: + map encode_chunks_encoded; + unsigned int k; + unsigned int m; + unsigned int chunk_size; + + ErasureCodeTest(unsigned int _k, unsigned int _m, unsigned int _chunk_size) : + k(_k), m(_m), chunk_size(_chunk_size) {} + virtual ~ErasureCodeTest() {} + + virtual unsigned int get_chunk_count() const { return k + m; } + virtual unsigned int get_data_chunk_count() const { return k; } + virtual unsigned int get_chunk_size(unsigned int object_size) const { + return chunk_size; + } + virtual int encode_chunks(const set &want_to_encode, + map *encoded) { + encode_chunks_encoded = *encoded; + return 0; + } + virtual int create_ruleset(const string &name, + CrushWrapper &crush, + ostream *ss) const { return 0; } + +}; + +/* + * If we have a buffer of 5 bytes (X below) and a chunk size of 3 + * bytes, for k=3, m=1 an additional 7 bytes (P and C below) will + * need to be allocated for padding (P) and the 3 coding bytes (C). + * + * X -+ +----------+ +-X + * X | | data 0 | | X + * X | +----------+ | X + * X | +----------+ | X -> +-X + * X -+ | data 1 | +-X -> | X + * P -+ +----------+ | P + * P | +----------+ | P + * P | | data 2 | | P + * P | +----------+ | P + * C | +----------+ | C + * C | | coding 3 | | C + * C -+ +----------+ +-C + * + * The data chunks 1 and 2 (data 1 and data 2 above) overflow the + * original buffer because it needs padding. A new buffer will + * be allocated to contain the chunk that overflows and all other + * chunks after it, including the coding chunk(s). + * + * The following test creates a siguation where the buffer provided + * for encoding is not memory aligned. After encoding it asserts that: + * + * a) each chunk is SIMD aligned + * b) the data 1 chunk content is as expected which implies that its + * content has been copied over. + * + * It is possible for a flawed implementation to pas the test because the + * underlying allocation function enforces it. + */ +TEST(ErasureCodeTest, encode_memory_align) +{ + int k = 3; + int m = 1; + unsigned chunk_size = ErasureCode::SIMD_ALIGN * 7; + ErasureCodeTest erasure_code(k, m, chunk_size); + + set want_to_encode; + for (unsigned int i = 0; i < erasure_code.get_chunk_count(); i++) + want_to_encode.insert(i); + string data(chunk_size + chunk_size / 2, 'X'); // uses 1.5 chunks out of 3 + // make sure nothing is memory aligned + bufferptr ptr(buffer::create_aligned(data.length() + 1, ErasureCode::SIMD_ALIGN)); + ptr.copy_in(1, data.length(), data.c_str()); + ptr.set_offset(1); + ptr.set_length(data.length()); + bufferlist in; + in.append(ptr); + map encoded; + + ASSERT_FALSE(in.is_aligned(ErasureCode::SIMD_ALIGN)); + ASSERT_EQ(0, erasure_code.encode(want_to_encode, in, &encoded)); + for (unsigned int i = 0; i < erasure_code.get_chunk_count(); i++) + ASSERT_TRUE(encoded[i].is_aligned(ErasureCode::SIMD_ALIGN)); + for (unsigned i = 0; i < chunk_size / 2; i++) + ASSERT_EQ(encoded[1][i], 'X'); + ASSERT_NE(encoded[1][chunk_size / 2], 'X'); +} + +int main(int argc, char **argv) +{ + vector args; + argv_to_vec(argc, (const char **)argv, args); + + global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0); + common_init_finish(g_ceph_context); + + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + +/* + * Local Variables: + * compile-command: "cd ../.. ; + * make -j4 unittest_erasure_code && + * valgrind --tool=memcheck --leak-check=full \ + * ./unittest_erasure_code \ + * --gtest_filter=*.* --log-to-stderr=true" + * End: + */ diff --git a/src/test/erasure-code/ceph_erasure_code_benchmark.cc b/src/test/erasure-code/ceph_erasure_code_benchmark.cc index c6a4228bdc1e4..da90d85825bdc 100644 --- a/src/test/erasure-code/ceph_erasure_code_benchmark.cc +++ b/src/test/erasure-code/ceph_erasure_code_benchmark.cc @@ -31,6 +31,7 @@ #include "common/Clock.h" #include "include/utime.h" #include "erasure-code/ErasureCodePlugin.h" +#include "erasure-code/ErasureCode.h" namespace po = boost::program_options; @@ -144,6 +145,7 @@ int ErasureCodeBench::encode() bufferlist in; in.append(string(in_size, 'X')); + in.rebuild_aligned(ErasureCode::SIMD_ALIGN); set want_to_encode; for (int i = 0; i < k + m; i++) { want_to_encode.insert(i); @@ -183,6 +185,7 @@ int ErasureCodeBench::decode() } bufferlist in; in.append(string(in_size, 'X')); + in.rebuild_aligned(ErasureCode::SIMD_ALIGN); set want_to_encode; for (int i = 0; i < k + m; i++) {