]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
erasure code: shec performance optimization with SIMD instructions
authorShotaro Kawaguchi <kawaguchi.s@jp.fujitsu.com>
Wed, 15 Jul 2015 08:21:35 +0000 (17:21 +0900)
committerTakeshi Miyamae <miyamae.takeshi@jp.fujitsu.com>
Wed, 15 Jul 2015 08:33:25 +0000 (17:33 +0900)
continued from https://github.com/ceph/ceph/pull/4689

Signed-off-by: Shotaro Kawaguchi <kawaguchi.s@jp.fujitsu.com>
src/erasure-code/shec/ErasureCodePluginSelectShec.cc [new file with mode: 0644]
src/erasure-code/shec/ErasureCodeShec.cc
src/erasure-code/shec/Makefile.am
src/test/erasure-code/Makefile.am
src/test/erasure-code/TestErasureCodePluginShec.cc [new file with mode: 0644]
src/test/erasure-code/TestShecPluginGeneric.cc [new file with mode: 0644]
src/test/erasure-code/TestShecPluginNEON.cc [new file with mode: 0644]
src/test/erasure-code/TestShecPluginSSE3.cc [new file with mode: 0644]
src/test/erasure-code/TestShecPluginSSE4.cc [new file with mode: 0644]

diff --git a/src/erasure-code/shec/ErasureCodePluginSelectShec.cc b/src/erasure-code/shec/ErasureCodePluginSelectShec.cc
new file mode 100644 (file)
index 0000000..1bae15f
--- /dev/null
@@ -0,0 +1,99 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2013,2014 Cloudwatt <libre.licensing@cloudwatt.com>
+ * Copyright (C) 2014 Red Hat <contact@redhat.com>
+ * Copyright (C) 2014,2015 FUJITSU LIMITED
+ *
+ * Author: Loic Dachary <loic@dachary.org>
+ * Author: Shotaro Kawaguchi <kawaguchi.s@jp.fujitsu.com>
+ * Author: Takanori Nakao <nakao.takanori@jp.fujitsu.com>
+ * Author: Takeshi Miyamae <miyamae.takeshi@jp.fujitsu.com>
+ *
+ *  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 "ceph_ver.h"
+#include "common/debug.h"
+#include "arch/probe.h"
+#include "arch/intel.h"
+#include "arch/arm.h"
+#include "erasure-code/ErasureCodePlugin.h"
+
+#define dout_subsys ceph_subsys_osd
+#undef dout_prefix
+#define dout_prefix _prefix(_dout)
+
+static ostream& _prefix(std::ostream* _dout)
+{
+  return *_dout << "ErasureCodePluginSelectShec: ";
+}
+
+static string get_variant() {
+  ceph_arch_probe();
+
+  if (ceph_arch_intel_pclmul &&
+      ceph_arch_intel_sse42 &&
+      ceph_arch_intel_sse41 &&
+      ceph_arch_intel_ssse3 &&
+      ceph_arch_intel_sse3 &&
+      ceph_arch_intel_sse2) {
+    return "sse4";
+  } else if (ceph_arch_intel_ssse3 &&
+            ceph_arch_intel_sse3 &&
+            ceph_arch_intel_sse2) {
+    return "sse3";
+  } else if (ceph_arch_neon) {
+    return "neon";
+  } else {
+    return "generic";
+  }
+}
+
+class ErasureCodePluginSelectShec : public ErasureCodePlugin {
+public:
+  virtual int factory(ErasureCodeProfile &profile,
+                     ErasureCodeInterfaceRef *erasure_code,
+                     ostream *ss) {
+    ErasureCodePluginRegistry &instance = ErasureCodePluginRegistry::instance();
+    int ret;
+    string name = "shec";
+    if (profile.count("shec-name"))
+      name = profile.find("shec-name")->second;
+    if (profile.count("shec-variant")) {
+      dout(10) << "shec-variant "
+              << profile.find("shec-variant")->second << dendl;
+      ret = instance.factory(name + "_" + profile.find("shec-variant")->second,
+                            profile, erasure_code, ss);
+    } else {
+      string variant = get_variant();
+      dout(10) << variant << " plugin" << dendl;
+      ret = instance.factory(name + "_" + variant, profile, erasure_code, ss);
+    }
+    return ret;
+  }
+};
+
+const char *__erasure_code_version() { return CEPH_GIT_NICE_VER; }
+
+int __erasure_code_init(char *plugin_name, char *directory)
+{
+  ErasureCodePluginRegistry &instance = ErasureCodePluginRegistry::instance();
+  string variant = get_variant();
+  ErasureCodePlugin *plugin;
+  stringstream ss;
+  int r = instance.load(plugin_name + string("_") + variant,
+                       directory, &plugin, &ss);
+  if (r) {
+    derr << ss.str() << dendl;
+    return r;
+  }
+  dout(10) << ss.str() << dendl;
+  return instance.add(plugin_name, new ErasureCodePluginSelectShec());
+}
index ffd8e59c594f1af5a98de60dd0ca41824ec58ac8..fc49e7298353a2cbf2e3160dbc3a93c29d135c9b 100644 (file)
@@ -247,7 +247,6 @@ int ErasureCodeShec::decode_chunks(const set<int> &want_to_read,
       }
       avails[i] = 0;
     } else {
-      (*decoded)[i] = chunks.find(i)->second;
       avails[i] = 1;
     }
     if (i < k)
index e4ca5f8e72f561a214254b5f1f3d6927eca55e3d..1449a41ac23296475aebdd303e3225fa16b11323 100644 (file)
@@ -1,6 +1,5 @@
 # SHEC plugin
-
-libec_shec_la_SOURCES = \
+shec_sources = \
        erasure-code/ErasureCode.cc \
        erasure-code/shec/ErasureCodePluginShec.cc \
        erasure-code/shec/ErasureCodeShec.cc \
@@ -22,6 +21,7 @@ libec_shec_la_SOURCES = \
        erasure-code/jerasure/gf-complete/src/gf_w4.c \
        erasure-code/jerasure/gf-complete/src/gf_rand.c \
        erasure-code/jerasure/gf-complete/src/gf_w8.c
+
 noinst_HEADERS += \
        erasure-code/shec/ErasureCodeShec.h \
        erasure-code/shec/ErasureCodeShecTableCache.h \
@@ -38,20 +38,125 @@ noinst_HEADERS += \
 
 erasure-code/shec/ErasureCodePluginShec.cc: ./ceph_ver.h
 
-libec_shec_la_CFLAGS = ${AM_CFLAGS} \
+libec_shec_generic_la_SOURCES = ${shec_sources}
+libec_shec_generic_la_CFLAGS = ${AM_CFLAGS}  \
+       -I$(srcdir)/erasure-code/jerasure/jerasure/include \
+       -I$(srcdir)/erasure-code/jerasure/gf-complete/include \
+       -I$(srcdir)/erasure-code/jerasure \
+       -I$(srcdir)/erasure-code/shec
+libec_shec_generic_la_CXXFLAGS= ${AM_CXXFLAGS} \
+       -I$(srcdir)/erasure-code/jerasure/jerasure/include \
+       -I$(srcdir)/erasure-code/jerasure/gf-complete/include \
+       -I$(srcdir)/erasure-code/jerasure \
+       -I$(srcdir)/erasure-code/shec
+libec_shec_generic_la_LIBADD = $(LIBCRUSH) $(PTHREAD_LIBS) $(EXTRALIBS)
+libec_shec_generic_la_LDFLAGS = ${AM_LDFLAGS} -version-info 1:0:0
+if LINUX
+libec_shec_generic_la_LDFLAGS += -export-symbols-regex '.*__erasure_code_.*'
+endif
+
+erasure_codelib_LTLIBRARIES += libec_shec_generic.la
+
+libec_shec_neon_la_SOURCES = ${shec_sources} \
+       erasure-code/jerasure/gf-complete/src/neon/gf_w4_neon.c \
+       erasure-code/jerasure/gf-complete/src/neon/gf_w8_neon.c \
+       erasure-code/jerasure/gf-complete/src/neon/gf_w16_neon.c \
+       erasure-code/jerasure/gf-complete/src/neon/gf_w32_neon.c \
+       erasure-code/jerasure/gf-complete/src/neon/gf_w64_neon.c
+libec_shec_neon_la_CFLAGS = ${AM_CFLAGS}  \
+       ${ARM_NEON_FLAGS} \
+       -I$(srcdir)/erasure-code/jerasure/jerasure/include \
+       -I$(srcdir)/erasure-code/jerasure/gf-complete/include \
+       -I$(srcdir)/erasure-code/jerasure \
+       -I$(srcdir)/erasure-code/shec
+libec_shec_neon_la_CXXFLAGS= ${AM_CXXFLAGS} \
+       ${ARM_NEON_FLAGS} \
+       -I$(srcdir)/erasure-code/jerasure/jerasure/include \
+       -I$(srcdir)/erasure-code/jerasure/gf-complete/include \
+       -I$(srcdir)/erasure-code/jerasure \
+       -I$(srcdir)/erasure-code/shec
+libec_shec_neon_la_LIBADD = $(LIBCRUSH) $(PTHREAD_LIBS) $(EXTRALIBS)
+libec_shec_neon_la_LDFLAGS = ${AM_LDFLAGS} -version-info 1:0:0
+if LINUX
+libec_shec_neon_la_LDFLAGS += -export-symbols-regex '.*__erasure_code_.*'
+endif
+
+if HAVE_NEON
+erasure_codelib_LTLIBRARIES += libec_shec_neon.la
+endif
+
+libec_shec_sse3_la_SOURCES = ${shec_sources}
+libec_shec_sse3_la_CFLAGS = ${AM_CFLAGS}  \
+       ${INTEL_SSE_FLAGS} \
+       ${INTEL_SSE2_FLAGS} \
+       ${INTEL_SSE3_FLAGS} \
+       ${INTEL_SSSE3_FLAGS} \
+       -I$(srcdir)/erasure-code/jerasure/jerasure/include \
+       -I$(srcdir)/erasure-code/jerasure/gf-complete/include \
+       -I$(srcdir)/erasure-code/jerasure \
+       -I$(srcdir)/erasure-code/shec
+libec_shec_sse3_la_CXXFLAGS= ${AM_CXXFLAGS} \
+       ${INTEL_SSE_FLAGS} \
+       ${INTEL_SSE2_FLAGS} \
+       ${INTEL_SSE3_FLAGS} \
+       ${INTEL_SSSE3_FLAGS} \
+       -I$(srcdir)/erasure-code/jerasure/jerasure/include \
+       -I$(srcdir)/erasure-code/jerasure/gf-complete/include \
+       -I$(srcdir)/erasure-code/jerasure \
+       -I$(srcdir)/erasure-code/shec
+libec_shec_sse3_la_LIBADD = $(LIBCRUSH) $(PTHREAD_LIBS) $(EXTRALIBS)
+libec_shec_sse3_la_LDFLAGS = ${AM_LDFLAGS} -version-info 1:0:0
+if LINUX
+libec_shec_sse3_la_LDFLAGS += -export-symbols-regex '.*__erasure_code_.*'
+endif
+
+if HAVE_SSSE3
+erasure_codelib_LTLIBRARIES += libec_shec_sse3.la
+endif
+
+libec_shec_sse4_la_SOURCES = ${shec_sources}
+libec_shec_sse4_la_CFLAGS = ${AM_CFLAGS}  \
+       ${INTEL_SSE_FLAGS} \
+       ${INTEL_SSE2_FLAGS} \
+       ${INTEL_SSE3_FLAGS} \
+       ${INTEL_SSSE3_FLAGS} \
+       ${INTEL_SSE4_1_FLAGS} \
+       ${INTEL_SSE4_2_FLAGS} \
        -I$(srcdir)/erasure-code/jerasure/jerasure/include \
        -I$(srcdir)/erasure-code/jerasure/gf-complete/include \
        -I$(srcdir)/erasure-code/jerasure \
        -I$(srcdir)/erasure-code/shec
-libec_shec_la_CXXFLAGS= ${AM_CXXFLAGS} \
+libec_shec_sse4_la_CXXFLAGS= ${AM_CXXFLAGS} \
+       ${INTEL_SSE_FLAGS} \
+       ${INTEL_SSE2_FLAGS} \
+       ${INTEL_SSE3_FLAGS} \
+       ${INTEL_SSSE3_FLAGS} \
+       ${INTEL_SSE4_1_FLAGS} \
+       ${INTEL_SSE4_2_FLAGS} \
        -I$(srcdir)/erasure-code/jerasure/jerasure/include \
        -I$(srcdir)/erasure-code/jerasure/gf-complete/include \
        -I$(srcdir)/erasure-code/jerasure \
        -I$(srcdir)/erasure-code/shec
+libec_shec_sse4_la_LIBADD = $(LIBCRUSH) $(PTHREAD_LIBS) $(EXTRALIBS)
+libec_shec_sse4_la_LDFLAGS = ${AM_LDFLAGS} -version-info 1:0:0
+if LINUX
+libec_shec_sse4_la_LDFLAGS += -export-symbols-regex '.*__erasure_code_.*'
+endif
+
+if HAVE_SSE4_PCLMUL
+erasure_codelib_LTLIBRARIES += libec_shec_sse4.la
+endif
+
+libec_shec_la_SOURCES = \
+       erasure-code/shec/ErasureCodePluginSelectShec.cc
+libec_shec_la_CFLAGS = ${AM_CFLAGS}
+libec_shec_la_CXXFLAGS= ${AM_CXXFLAGS}
 libec_shec_la_LIBADD = $(LIBCRUSH) $(PTHREAD_LIBS) $(EXTRALIBS)
 libec_shec_la_LDFLAGS = ${AM_LDFLAGS} -version-info 1:0:0
 if LINUX
 libec_shec_la_LDFLAGS += -export-symbols-regex '.*__erasure_code_.*'
 endif
 
+erasure-code/shec/ErasureCodePluginSelectShec.cc: ./ceph_ver.h
+
 erasure_codelib_LTLIBRARIES += libec_shec.la
index f2d0d18161187b414988437beb46e56e17e9c180..ed0a014eccf33a9b171cb8131d3f10ab0993aa5a 100644 (file)
@@ -200,9 +200,17 @@ check_TESTPROGRAMS += unittest_erasure_code_plugin_lrc
 
 unittest_erasure_code_shec_SOURCES = \
        test/erasure-code/TestErasureCodeShec.cc \
-       ${libec_shec_la_SOURCES}
-unittest_erasure_code_shec_CFLAGS = ${libec_shec_la_CFLAGS}
-unittest_erasure_code_shec_CXXFLAGS = ${libec_shec_la_CXXFLAGS} $(UNITTEST_CXXFLAGS)
+       ${shec_sources}
+unittest_erasure_code_shec_CFLAGS = ${libec_shec_la_CFLAGS} \
+       -I$(srcdir)/erasure-code/jerasure/jerasure/include \
+       -I$(srcdir)/erasure-code/jerasure/gf-complete/include \
+       -I$(srcdir)/erasure-code/jerasure \
+       -I$(srcdir)/erasure-code/shec
+unittest_erasure_code_shec_CXXFLAGS = ${libec_shec_la_CXXFLAGS} $(UNITTEST_CXXFLAGS) \
+       -I$(srcdir)/erasure-code/jerasure/jerasure/include \
+       -I$(srcdir)/erasure-code/jerasure/gf-complete/include \
+       -I$(srcdir)/erasure-code/jerasure \
+       -I$(srcdir)/erasure-code/shec
 unittest_erasure_code_shec_LDADD = $(LIBOSD) $(LIBCOMMON) $(UNITTEST_LDADD) $(CEPH_GLOBAL)
 if LINUX
 unittest_erasure_code_shec_LDADD += -ldl
@@ -211,9 +219,17 @@ check_TESTPROGRAMS += unittest_erasure_code_shec
 
 unittest_erasure_code_shec_all_SOURCES = \
        test/erasure-code/TestErasureCodeShec_all.cc \
-       ${libec_shec_la_SOURCES}
-unittest_erasure_code_shec_all_CFLAGS = ${libec_shec_la_CFLAGS}
-unittest_erasure_code_shec_all_CXXFLAGS = ${libec_shec_la_CXXFLAGS} $(UNITTEST_CXXFLAGS)
+       ${shec_sources}
+unittest_erasure_code_shec_all_CFLAGS = ${libec_shec_la_CFLAGS} \
+       -I$(srcdir)/erasure-code/jerasure/jerasure/include \
+       -I$(srcdir)/erasure-code/jerasure/gf-complete/include \
+       -I$(srcdir)/erasure-code/jerasure \
+       -I$(srcdir)/erasure-code/shec
+unittest_erasure_code_shec_all_CXXFLAGS = ${libec_shec_la_CXXFLAGS} $(UNITTEST_CXXFLAGS) \
+       -I$(srcdir)/erasure-code/jerasure/jerasure/include \
+       -I$(srcdir)/erasure-code/jerasure/gf-complete/include \
+       -I$(srcdir)/erasure-code/jerasure \
+       -I$(srcdir)/erasure-code/shec
 unittest_erasure_code_shec_all_LDADD = $(LIBOSD) $(LIBCOMMON) $(UNITTEST_LDADD) $(CEPH_GLOBAL)
 if LINUX
 unittest_erasure_code_shec_all_LDADD += -ldl
@@ -222,9 +238,17 @@ check_TESTPROGRAMS += unittest_erasure_code_shec_all
 
 unittest_erasure_code_shec_thread_SOURCES = \
        test/erasure-code/TestErasureCodeShec_thread.cc \
-       ${libec_shec_la_SOURCES}
-unittest_erasure_code_shec_thread_CFLAGS = ${libec_shec_la_CFLAGS}
-unittest_erasure_code_shec_thread_CXXFLAGS = ${libec_shec_la_CXXFLAGS} $(UNITTEST_CXXFLAGS)
+       ${shec_sources}
+unittest_erasure_code_shec_thread_CFLAGS = ${libec_shec_la_CFLAGS} \
+       -I$(srcdir)/erasure-code/jerasure/jerasure/include \
+       -I$(srcdir)/erasure-code/jerasure/gf-complete/include \
+       -I$(srcdir)/erasure-code/jerasure \
+       -I$(srcdir)/erasure-code/shec
+unittest_erasure_code_shec_thread_CXXFLAGS = ${libec_shec_la_CXXFLAGS} $(UNITTEST_CXXFLAGS) \
+       -I$(srcdir)/erasure-code/jerasure/jerasure/include \
+       -I$(srcdir)/erasure-code/jerasure/gf-complete/include \
+       -I$(srcdir)/erasure-code/jerasure \
+       -I$(srcdir)/erasure-code/shec
 unittest_erasure_code_shec_thread_LDADD = $(LIBOSD) $(LIBCOMMON) $(UNITTEST_LDADD) $(CEPH_GLOBAL)
 if LINUX
 unittest_erasure_code_shec_thread_LDADD += -ldl
@@ -233,15 +257,64 @@ check_TESTPROGRAMS += unittest_erasure_code_shec_thread
 
 unittest_erasure_code_shec_arguments_SOURCES = \
        test/erasure-code/TestErasureCodeShec_arguments.cc \
-       ${libec_shec_la_SOURCES}
-unittest_erasure_code_shec_arguments_CFLAGS = ${libec_shec_la_CFLAGS}
-unittest_erasure_code_shec_arguments_CXXFLAGS = ${libec_shec_la_CXXFLAGS} $(UNITTEST_CXXFLAGS)
+       ${shec_sources}
+unittest_erasure_code_shec_arguments_CFLAGS = ${libec_shec_la_CFLAGS} \
+       -I$(srcdir)/erasure-code/jerasure/jerasure/include \
+       -I$(srcdir)/erasure-code/jerasure/gf-complete/include \
+       -I$(srcdir)/erasure-code/jerasure \
+       -I$(srcdir)/erasure-code/shec
+unittest_erasure_code_shec_arguments_CXXFLAGS = ${libec_shec_la_CXXFLAGS} $(UNITTEST_CXXFLAGS) \
+       -I$(srcdir)/erasure-code/jerasure/jerasure/include \
+       -I$(srcdir)/erasure-code/jerasure/gf-complete/include \
+       -I$(srcdir)/erasure-code/jerasure \
+       -I$(srcdir)/erasure-code/shec
 unittest_erasure_code_shec_arguments_LDADD = $(LIBOSD) $(LIBCOMMON) $(UNITTEST_LDADD) $(CEPH_GLOBAL)
 if LINUX
 unittest_erasure_code_shec_arguments_LDADD += -ldl
 endif
 check_TESTPROGRAMS += unittest_erasure_code_shec_arguments
 
+unittest_erasure_code_plugin_shec_SOURCES = \
+        test/erasure-code/TestErasureCodePluginShec.cc
+unittest_erasure_code_plugin_shec_CXXFLAGS = ${AM_CXXFLAGS} ${UNITTEST_CXXFLAGS}
+unittest_erasure_code_plugin_shec_LDADD = $(LIBOSD) $(LIBCOMMON) $(UNITTEST_LDADD) $(CEPH_GLOBAL)
+if LINUX
+unittest_erasure_code_plugin_shec_LDADD += -ldl
+endif
+check_TESTPROGRAMS += unittest_erasure_code_plugin_shec
+
+libec_test_shec_neon_la_SOURCES = test/erasure-code/TestShecPluginNEON.cc
+test/erasure-code/TestShecPluginNEON.cc: ./ceph_ver.h
+libec_test_shec_neon_la_CFLAGS = ${AM_CFLAGS}
+libec_test_shec_neon_la_CXXFLAGS= ${AM_CXXFLAGS}
+libec_test_shec_neon_la_LIBADD = $(PTHREAD_LIBS) $(EXTRALIBS)
+libec_test_shec_neon_la_LDFLAGS = ${AM_LDFLAGS} -export-symbols-regex '.*__erasure_code_.*'
+erasure_codelib_LTLIBRARIES += libec_test_shec_neon.la
+
+libec_test_shec_sse4_la_SOURCES = test/erasure-code/TestShecPluginSSE4.cc
+test/erasure-code/TestShecPluginSSE4.cc: ./ceph_ver.h
+libec_test_shec_sse4_la_CFLAGS = ${AM_CFLAGS}
+libec_test_shec_sse4_la_CXXFLAGS= ${AM_CXXFLAGS}
+libec_test_shec_sse4_la_LIBADD = $(PTHREAD_LIBS) $(EXTRALIBS)
+libec_test_shec_sse4_la_LDFLAGS = ${AM_LDFLAGS} -export-symbols-regex '.*__erasure_code_.*'
+erasure_codelib_LTLIBRARIES += libec_test_shec_sse4.la
+
+libec_test_shec_sse3_la_SOURCES = test/erasure-code/TestShecPluginSSE3.cc
+test/erasure-code/TestShecPluginSSE3.cc: ./ceph_ver.h
+libec_test_shec_sse3_la_CFLAGS = ${AM_CFLAGS}
+libec_test_shec_sse3_la_CXXFLAGS= ${AM_CXXFLAGS}
+libec_test_shec_sse3_la_LIBADD = $(PTHREAD_LIBS) $(EXTRALIBS)
+libec_test_shec_sse3_la_LDFLAGS = ${AM_LDFLAGS} -export-symbols-regex '.*__erasure_code_.*'
+erasure_codelib_LTLIBRARIES += libec_test_shec_sse3.la
+
+libec_test_shec_generic_la_SOURCES = test/erasure-code/TestShecPluginGeneric.cc
+test/erasure-code/TestShecPluginGeneric.cc: ./ceph_ver.h
+libec_test_shec_generic_la_CFLAGS = ${AM_CFLAGS}
+libec_test_shec_generic_la_CXXFLAGS= ${AM_CXXFLAGS}
+libec_test_shec_generic_la_LIBADD = $(PTHREAD_LIBS) $(EXTRALIBS)
+libec_test_shec_generic_la_LDFLAGS = ${AM_LDFLAGS} -export-symbols-regex '.*__erasure_code_.*'
+erasure_codelib_LTLIBRARIES += libec_test_shec_generic.la
+
 unittest_erasure_code_example_SOURCES = \
        erasure-code/ErasureCode.cc \
        test/erasure-code/TestErasureCodeExample.cc
diff --git a/src/test/erasure-code/TestErasureCodePluginShec.cc b/src/test/erasure-code/TestErasureCodePluginShec.cc
new file mode 100644 (file)
index 0000000..405aca2
--- /dev/null
@@ -0,0 +1,255 @@
+// -*- 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) 2015 FUJITSU LIMITED
+ *
+ * Author: Shotaro Kawaguchi <kawaguchi.s@jp.fujitsu.com>
+ * Author: Takanori Nakao <nakao.takanori@jp.fujitsu.com>
+ * Author: Takeshi Miyamae <miyamae.takeshi@jp.fujitsu.com>
+ *
+ *  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 <errno.h>
+#include "arch/probe.h"
+#include "arch/intel.h"
+#include "arch/arm.h"
+#include "global/global_init.h"
+#include "erasure-code/ErasureCodePlugin.h"
+#include "common/ceph_argparse.h"
+#include "global/global_context.h"
+#include "gtest/gtest.h"
+
+TEST(ErasureCodePlugin, factory)
+{
+  ErasureCodePluginRegistry &instance = ErasureCodePluginRegistry::instance();
+  map<std::string,std::string> profile;
+  profile["directory"] = ".libs";
+  {
+    ErasureCodeInterfaceRef erasure_code;
+    EXPECT_FALSE(erasure_code);
+    EXPECT_EQ(0, instance.factory("shec", profile,
+                                        &erasure_code, &cerr));
+    EXPECT_TRUE(erasure_code);
+  }
+  const char *techniques[] = {
+    "single",
+    "multiple",
+    0
+  };
+  for(const char **technique = techniques; *technique; technique++) {
+    ErasureCodeInterfaceRef erasure_code;
+    profile["directory"] = ".libs";
+    profile["technique"] = *technique;
+    EXPECT_FALSE(erasure_code);
+    EXPECT_EQ(0, instance.factory("shec", profile,
+                                  &erasure_code, &cerr));
+    EXPECT_TRUE(erasure_code);
+  }
+}
+
+TEST(ErasureCodePlugin, select)
+{
+  ceph_arch_probe();
+  // save probe results
+  int arch_intel_pclmul = ceph_arch_intel_pclmul;
+  int arch_intel_sse42  = ceph_arch_intel_sse42;
+  int arch_intel_sse41  = ceph_arch_intel_sse41;
+  int arch_intel_ssse3  = ceph_arch_intel_ssse3;
+  int arch_intel_sse3   = ceph_arch_intel_sse3;
+  int arch_intel_sse2   = ceph_arch_intel_sse2;
+  int arch_neon                = ceph_arch_neon;
+
+  ErasureCodePluginRegistry &instance = ErasureCodePluginRegistry::instance();
+  map<std::string,std::string> profile;
+  // load test plugins instead of actual plugins to assert the desired side effect
+  // happens
+  profile["shec-name"] = "test_shec";
+  profile["directory"] = ".libs";
+  profile["technique"] = "multiple";
+
+  // all features are available, load the SSE4 plugin
+  {
+    ceph_arch_intel_pclmul = 1;
+    ceph_arch_intel_sse42  = 1;
+    ceph_arch_intel_sse41  = 1;
+    ceph_arch_intel_ssse3  = 1;
+    ceph_arch_intel_sse3   = 1;
+    ceph_arch_intel_sse2   = 1;
+    ceph_arch_neon        = 0;
+
+    ErasureCodeInterfaceRef erasure_code;
+    int sse4_side_effect = -444;
+    EXPECT_EQ(sse4_side_effect, instance.factory("shec", profile,
+                                                 &erasure_code, &cerr));
+  }
+  // pclmul is missing, load the SSE3 plugin
+  {
+    ceph_arch_intel_pclmul = 0;
+    ceph_arch_intel_sse42  = 1;
+    ceph_arch_intel_sse41  = 1;
+    ceph_arch_intel_ssse3  = 1;
+    ceph_arch_intel_sse3   = 1;
+    ceph_arch_intel_sse2   = 1;
+    ceph_arch_neon        = 0;
+
+    ErasureCodeInterfaceRef erasure_code;
+    int sse3_side_effect = -333;
+    EXPECT_EQ(sse3_side_effect, instance.factory("shec", profile,
+                                                 &erasure_code, &cerr));
+  }
+  // pclmul and sse3 are missing, load the generic plugin
+  {
+    ceph_arch_intel_pclmul = 0;
+    ceph_arch_intel_sse42  = 1;
+    ceph_arch_intel_sse41  = 1;
+    ceph_arch_intel_ssse3  = 1;
+    ceph_arch_intel_sse3   = 0;
+    ceph_arch_intel_sse2   = 1;
+    ceph_arch_neon        = 0;
+
+    ErasureCodeInterfaceRef erasure_code;
+    int generic_side_effect = -111;
+    EXPECT_EQ(generic_side_effect, instance.factory("shec", profile,
+                                                   &erasure_code, &cerr));
+  }
+  // neon is set, load the neon plugin
+  {
+    ceph_arch_intel_pclmul = 0;
+    ceph_arch_intel_sse42  = 0;
+    ceph_arch_intel_sse41  = 0;
+    ceph_arch_intel_ssse3  = 0;
+    ceph_arch_intel_sse3   = 0;
+    ceph_arch_intel_sse2   = 0;
+    ceph_arch_neon        = 1;
+
+    ErasureCodeInterfaceRef erasure_code;
+    int generic_side_effect = -555;
+    EXPECT_EQ(generic_side_effect, instance.factory("shec", profile,
+                                                   &erasure_code, &cerr));
+  }
+
+
+  // restore probe results
+  ceph_arch_intel_pclmul = arch_intel_pclmul;
+  ceph_arch_intel_sse42  = arch_intel_sse42;
+  ceph_arch_intel_sse41  = arch_intel_sse41;
+  ceph_arch_intel_ssse3  = arch_intel_ssse3;
+  ceph_arch_intel_sse3   = arch_intel_sse3;
+  ceph_arch_intel_sse2   = arch_intel_sse2;
+  ceph_arch_neon        = arch_neon;
+}
+
+TEST(ErasureCodePlugin, sse)
+{
+  ceph_arch_probe();
+  bool sse4 = ceph_arch_intel_pclmul &&
+    ceph_arch_intel_sse42 && ceph_arch_intel_sse41 &&
+    ceph_arch_intel_ssse3 && ceph_arch_intel_sse3 &&
+    ceph_arch_intel_sse2;
+  bool sse3 = ceph_arch_intel_ssse3 && ceph_arch_intel_sse3 &&
+    ceph_arch_intel_sse2;
+  vector<string> sse_variants;
+  sse_variants.push_back("generic");
+  if (!sse3)
+    cerr << "SKIP sse3 plugin testing because CPU does not support it\n";
+  else
+    sse_variants.push_back("sse3");
+  if (!sse4)
+    cerr << "SKIP sse4 plugin testing because CPU does not support it\n";
+  else
+    sse_variants.push_back("sse4");
+
+#define LARGE_ENOUGH 2048
+  bufferptr in_ptr(buffer::create_page_aligned(LARGE_ENOUGH));
+  in_ptr.zero();
+  in_ptr.set_length(0);
+  const char *payload =
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+  in_ptr.append(payload, strlen(payload));
+  bufferlist in;
+  in.push_front(in_ptr);
+
+  ErasureCodePluginRegistry &instance = ErasureCodePluginRegistry::instance();
+  map<std::string,std::string> profile;
+  profile["directory"] = ".libs";
+  profile["technique"] = "multiple";
+  profile["k"] = "2";
+  profile["m"] = "1";
+  profile["c"] = "1";
+  for (vector<string>::iterator sse_variant = sse_variants.begin();
+       sse_variant != sse_variants.end();
+       ++sse_variant) {
+    //
+    // load the plugin variant
+    //
+    ErasureCodeInterfaceRef erasure_code;
+    EXPECT_FALSE(erasure_code);
+    EXPECT_EQ(0, instance.factory("shec_" + *sse_variant, profile,
+                                  &erasure_code, &cerr));
+    EXPECT_TRUE(erasure_code);
+
+    //
+    // encode
+    //
+    int want_to_encode[] = { 0, 1, 2 };
+    map<int, bufferlist> encoded;
+    EXPECT_EQ(0, erasure_code->encode(set<int>(want_to_encode, want_to_encode+3),
+                                      in,
+                                      &encoded));
+    EXPECT_EQ(3u, encoded.size());
+    unsigned length =  encoded[0].length();
+    EXPECT_EQ(0, strncmp(encoded[0].c_str(), in.c_str(), length));
+    EXPECT_EQ(0, strncmp(encoded[1].c_str(), in.c_str() + length,
+                         in.length() - length));
+
+    //
+    // decode with reconstruction
+    //
+    map<int, bufferlist> degraded = encoded;
+    degraded.erase(1);
+    EXPECT_EQ(2u, degraded.size());
+    int want_to_decode[] = { 0, 1 };
+    map<int, bufferlist> decoded;
+    EXPECT_EQ(0, erasure_code->decode(set<int>(want_to_decode, want_to_decode+2),
+                                      degraded,
+                                      &decoded));
+    EXPECT_EQ(3u, decoded.size());
+    EXPECT_EQ(length, decoded[0].length());
+    EXPECT_EQ(0, strncmp(decoded[0].c_str(), in.c_str(), length));
+    EXPECT_EQ(0, strncmp(decoded[1].c_str(), in.c_str() + length,
+                         in.length() - length));
+
+  }
+}
+
+int main(int argc, char **argv)
+{
+  vector<const char*> 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 &&
+ *   make unittest_erasure_code_plugin_shec &&
+ *   valgrind --tool=memcheck ./unittest_erasure_code_plugin_shec \
+ *      --gtest_filter=*.* --log-to-stderr=true --debug-osd=20"
+ * End:
+ */
diff --git a/src/test/erasure-code/TestShecPluginGeneric.cc b/src/test/erasure-code/TestShecPluginGeneric.cc
new file mode 100644 (file)
index 0000000..0bd063b
--- /dev/null
@@ -0,0 +1,29 @@
+// -*- 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 Cloudwatt <libre.licensing@cloudwatt.com>
+ * Copyright (C) 2014 Red Hat <contact@redhat.com>
+ * Copyright (C) 2015 FUJITSU LIMITED
+ *
+ * Author: Loic Dachary <loic@dachary.org>
+ * Author: Shotaro Kawaguchi <kawaguchi.s@jp.fujitsu.com>
+ * Author: Takanori Nakao <nakao.takanori@jp.fujitsu.com>
+ * Author: Takeshi Miyamae <miyamae.takeshi@jp.fujitsu.com>
+ *
+ *  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 "ceph_ver.h"
+
+extern "C" const char *__erasure_code_version() { return CEPH_GIT_NICE_VER; }
+
+extern "C" int __erasure_code_init(char *plugin_name, char *directory)
+{
+  return -111;
+}
diff --git a/src/test/erasure-code/TestShecPluginNEON.cc b/src/test/erasure-code/TestShecPluginNEON.cc
new file mode 100644 (file)
index 0000000..373f5eb
--- /dev/null
@@ -0,0 +1,29 @@
+// -*- 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 Cloudwatt <libre.licensing@cloudwatt.com>
+ * Copyright (C) 2014 Red Hat <contact@redhat.com>
+ * Copyright (C) 2015 FUJITSU LIMITED
+ *
+ * Author: Loic Dachary <loic@dachary.org>
+ * Author: Shotaro Kawaguchi <kawaguchi.s@jp.fujitsu.com>
+ * Author: Takanori Nakao <nakao.takanori@jp.fujitsu.com>
+ * Author: Takeshi Miyamae <miyamae.takeshi@jp.fujitsu.com>
+ *
+ *  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 "ceph_ver.h"
+
+extern "C" const char *__erasure_code_version() { return CEPH_GIT_NICE_VER; }
+
+extern "C" int __erasure_code_init(char *plugin_name, char *directory)
+{
+  return -555;
+}
diff --git a/src/test/erasure-code/TestShecPluginSSE3.cc b/src/test/erasure-code/TestShecPluginSSE3.cc
new file mode 100644 (file)
index 0000000..220ea7b
--- /dev/null
@@ -0,0 +1,29 @@
+// -*- 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 Cloudwatt <libre.licensing@cloudwatt.com>
+ * Copyright (C) 2014 Red Hat <contact@redhat.com>
+ * Copyright (C) 2015 FUJITSU LIMITED
+ *
+ * Author: Loic Dachary <loic@dachary.org>
+ * Author: Shotaro Kawaguchi <kawaguchi.s@jp.fujitsu.com>
+ * Author: Takanori Nakao <nakao.takanori@jp.fujitsu.com>
+ * Author: Takeshi Miyamae <miyamae.takeshi@jp.fujitsu.com>
+ *
+ *  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 "ceph_ver.h"
+
+extern "C" const char *__erasure_code_version() { return CEPH_GIT_NICE_VER; }
+
+extern "C" int __erasure_code_init(char *plugin_name, char *directory)
+{
+  return -333;
+}
diff --git a/src/test/erasure-code/TestShecPluginSSE4.cc b/src/test/erasure-code/TestShecPluginSSE4.cc
new file mode 100644 (file)
index 0000000..ef8e841
--- /dev/null
@@ -0,0 +1,29 @@
+// -*- 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 Cloudwatt <libre.licensing@cloudwatt.com>
+ * Copyright (C) 2014 Red Hat <contact@redhat.com>
+ * Copyright (C) 2015 FUJITSU LIMITED
+ *
+ * Author: Loic Dachary <loic@dachary.org>
+ * Author: Shotaro Kawaguchi <kawaguchi.s@jp.fujitsu.com>
+ * Author: Takanori Nakao <nakao.takanori@jp.fujitsu.com>
+ * Author: Takeshi Miyamae <miyamae.takeshi@jp.fujitsu.com>
+ *
+ *  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 "ceph_ver.h"
+
+extern "C" const char *__erasure_code_version() { return CEPH_GIT_NICE_VER; }
+
+extern "C" int __erasure_code_init(char *plugin_name, char *directory)
+{
+  return -444;
+}