[Pkg-ceph-commits] [ceph] 01/01: Imported Upstream version 0.79

Dmitry Smirnov onlyjob at moszumanska.debian.org
Tue Apr 8 07:09:29 UTC 2014


This is an automated email from the git hooks/post-receive script.

onlyjob pushed a commit to branch upstream
in repository ceph.

commit e53c0ed (upstream)
Author: Dmitry Smirnov <onlyjob at member.fsf.org>
Date:   Tue Apr 8 06:53:56 2014

    Imported Upstream version 0.79
---
 Makefile.am                                        |    4 +-
 Makefile.in                                        |   20 +-
 README                                             |    7 +-
 aclocal.m4                                         |    1 +
 ceph.spec                                          |   69 +-
 ceph.spec.in                                       |   67 +-
 configure                                          |  355 ++-
 configure.ac                                       |    5 +-
 m4/ax_intel.m4                                     |   70 +
 man/Makefile.in                                    |   16 +-
 src/.git_version                                   |    4 +-
 src/Makefile-env.am                                |    2 +-
 src/Makefile.am                                    |   21 +-
 src/Makefile.in                                    | 2047 ++++++++++++---
 src/acconfig.h.in                                  |   21 +
 src/arch/intel.c                                   |   45 +-
 src/arch/intel.h                                   |    4 +
 src/auth/Crypto.cc                                 |    2 +-
 src/auth/cephx/CephxProtocol.cc                    |    2 +-
 src/ceph-disk                                      |    2 +-
 src/ceph-post-file.in                              |   91 +-
 src/ceph_mds.cc                                    |   57 +-
 src/client/Client.cc                               |  437 ++--
 src/client/Client.h                                |   25 +-
 src/client/Inode.cc                                |   10 +-
 src/client/Inode.h                                 |   13 +-
 src/client/MetaRequest.h                           |    6 +-
 src/client/ObjecterWriteback.h                     |    4 +-
 src/client/SyntheticClient.cc                      |    2 +-
 src/client/fuse_ll.cc                              |    7 +-
 src/cls/user/cls_user_types.cc                     |    1 +
 src/cls/user/cls_user_types.h                      |    9 +-
 src/common/Formatter.cc                            |    2 +-
 src/common/Formatter.h                             |    2 +-
 src/common/Makefile.am                             |    9 +-
 src/common/OutputDataSocket.cc                     |   14 +-
 src/common/PrioritizedQueue.h                      |   17 +-
 src/common/admin_socket.cc                         |   17 +-
 src/common/buffer.cc                               |   10 +-
 src/common/ceph_argparse.cc                        |    2 +-
 src/common/ceph_crypto.cc                          |    6 +
 src/common/config_opts.h                           |   18 +-
 src/common/hobject.h                               |    5 +
 src/common/lockdep.cc                              |   16 +-
 src/common/pipe.c                                  |    4 +-
 src/common/safe_io.c                               |   10 +-
 src/erasure-code/ErasureCodePlugin.cc              |   64 +-
 src/erasure-code/ErasureCodePlugin.h               |    8 +-
 src/erasure-code/Makefile.am                       |    3 +-
 src/erasure-code/jerasure/ErasureCodeJerasure.cc   |   40 +-
 .../jerasure/ErasureCodePluginJerasure.cc          |    6 +-
 .../jerasure/ErasureCodePluginSelectJerasure.cc    |   69 +
 src/erasure-code/jerasure/Makefile.am              |  116 +-
 src/erasure-code/jerasure/cauchy.h                 |   53 -
 src/erasure-code/jerasure/galois.c                 |  833 ------
 src/erasure-code/jerasure/galois.h                 |  111 -
 .../jerasure/gf-complete/include/gf_complete.h     |  192 ++
 .../jerasure/gf-complete/include/gf_general.h      |   61 +
 .../jerasure/gf-complete/include/gf_int.h          |  200 ++
 .../jerasure/gf-complete/include/gf_method.h       |   20 +
 .../jerasure/gf-complete/include/gf_rand.h         |   22 +
 src/erasure-code/jerasure/gf-complete/src/gf.c     | 1026 ++++++++
 .../jerasure/gf-complete/src/gf_general.c          |  538 ++++
 .../jerasure/gf-complete/src/gf_method.c           |  185 ++
 .../jerasure/gf-complete/src/gf_rand.c             |   80 +
 .../jerasure/gf-complete/src/gf_w128.c             | 1758 +++++++++++++
 src/erasure-code/jerasure/gf-complete/src/gf_w16.c | 2489 ++++++++++++++++++
 src/erasure-code/jerasure/gf-complete/src/gf_w32.c | 2741 ++++++++++++++++++++
 src/erasure-code/jerasure/gf-complete/src/gf_w4.c  | 2081 +++++++++++++++
 src/erasure-code/jerasure/gf-complete/src/gf_w64.c | 2244 ++++++++++++++++
 src/erasure-code/jerasure/gf-complete/src/gf_w8.c  | 2456 ++++++++++++++++++
 .../jerasure/gf-complete/src/gf_wgen.c             | 1019 ++++++++
 .../jerasure/jerasure/include/cauchy.h             |   45 +
 .../jerasure/jerasure/include/galois.h             |   99 +
 .../jerasure/{ => jerasure/include}/jerasure.h     |   86 +-
 .../jerasure/jerasure/include/liberation.h         |   47 +
 .../jerasure/jerasure/include/reed_sol.h           |   50 +
 .../jerasure/{ => jerasure/src}/cauchy.c           |   87 +-
 src/erasure-code/jerasure/jerasure/src/galois.c    |  353 +++
 .../jerasure/{ => jerasure/src}/jerasure.c         |  117 +-
 .../jerasure/{ => jerasure/src}/liberation.c       |   87 +-
 .../jerasure/{ => jerasure/src}/reed_sol.c         |  213 +-
 src/erasure-code/jerasure/liberation.h             |   56 -
 src/erasure-code/jerasure/reed_sol.h               |   59 -
 src/erasure-code/jerasure/vectorop.h               |   51 -
 src/global/global_init.cc                          |   30 +-
 src/global/global_init.h                           |   12 +-
 src/global/pidfile.cc                              |    4 +-
 src/include/ceph_features.h                        |    2 +
 src/include/cephfs/libcephfs.h                     |    6 +
 src/include/compat.h                               |    8 +
 src/include/frag.h                                 |    2 +-
 src/include/msgr.h                                 |    2 +
 src/include/rados/librados.h                       |   11 +
 src/include/types.h                                |    2 +-
 src/init-ceph.in                                   |    6 +-
 src/init-radosgw                                   |    1 +
 src/init-rbdmap                                    |   14 +-
 src/java/Makefile.in                               |   16 +-
 src/java/test/com/ceph/fs/CephMountTest.java       |    9 +-
 src/libcephfs.cc                                   |   45 +
 src/librados/AioCompletionImpl.h                   |    2 +-
 src/librados/IoCtxImpl.cc                          |   10 +-
 src/librados/IoCtxImpl.h                           |    4 +-
 src/librados/RadosClient.cc                        |    4 +-
 src/librados/librados.cc                           |   19 +-
 src/librbd/AioRequest.cc                           |    3 +-
 src/librbd/LibrbdWriteback.cc                      |    2 +-
 src/librbd/LibrbdWriteback.h                       |    4 +-
 src/librbd/internal.cc                             |    7 +
 src/libs3/debian/changelog                         |    5 +
 src/libs3/debian/changelog.Debian                  |    6 +
 src/libs3/debian/control                           |   12 +
 src/libs3/debian/control.dev                       |   26 +
 src/libs3/debian/postinst                          |    3 +
 src/log/Log.cc                                     |    4 +-
 src/logrotate.conf                                 |    1 +
 src/make_version                                   |   11 +-
 src/mds/AnchorServer.h                             |    9 +-
 src/mds/CDir.cc                                    |   29 +-
 src/mds/CDir.h                                     |    8 +-
 src/mds/CInode.cc                                  |  127 +-
 src/mds/CInode.h                                   |    6 +
 src/mds/Capability.h                               |    4 +-
 src/mds/Dumper.cc                                  |  162 +-
 src/mds/Dumper.h                                   |   63 +-
 src/mds/InoTable.cc                                |   31 +
 src/mds/InoTable.h                                 |   13 +-
 src/mds/Locker.cc                                  |   12 +-
 src/mds/LogEvent.h                                 |    1 +
 src/mds/LogSegment.h                               |    2 +-
 src/mds/MDBalancer.cc                              |    7 +-
 src/mds/MDCache.cc                                 |  342 +--
 src/mds/MDCache.h                                  |   37 +-
 src/mds/MDLog.cc                                   |   11 +-
 src/mds/MDS.cc                                     |   19 +-
 src/mds/MDS.h                                      |   10 +-
 src/mds/MDSMap.h                                   |   14 +-
 src/mds/MDSTable.cc                                |    4 +-
 src/mds/MDSTable.h                                 |    2 +-
 src/mds/MDSTableServer.h                           |    4 +-
 src/mds/MDSUtility.cc                              |  160 ++
 src/mds/MDSUtility.h                               |   58 +
 src/mds/Makefile.am                                |    4 +-
 src/mds/Migrator.cc                                |   18 +-
 src/mds/Migrator.h                                 |    5 +-
 src/mds/Mutation.cc                                |    6 +-
 src/mds/Mutation.h                                 |    6 +-
 src/mds/Resetter.cc                                |   80 +-
 src/mds/Resetter.h                                 |   45 +-
 src/mds/Server.cc                                  |  164 +-
 src/mds/SessionMap.h                               |   10 +-
 src/mds/SnapServer.cc                              |   81 +
 src/mds/SnapServer.h                               |   13 +-
 src/mds/events/EMetaBlob.h                         |    4 +-
 src/mds/flock.h                                    |   10 +
 src/mds/journal.cc                                 |   28 +-
 src/mds/mdstypes.cc                                |    4 +-
 src/mds/mdstypes.h                                 |   10 +-
 src/messages/MClientRequest.h                      |    4 +-
 src/messages/MClientRequestForward.h               |    2 +-
 src/messages/MDiscoverReply.h                      |   10 +-
 src/messages/MGetPoolStats.h                       |    2 +-
 src/messages/MGetPoolStatsReply.h                  |    2 +-
 src/messages/MMDSFindIno.h                         |    4 +-
 src/messages/MMDSFindInoReply.h                    |    4 +-
 src/messages/MMDSOpenIno.h                         |    2 +-
 src/messages/MMDSOpenInoReply.h                    |    2 +-
 src/messages/MMDSSlaveRequest.h                    |    3 +-
 src/messages/MMonGetVersion.h                      |    2 +-
 src/messages/MMonGetVersionReply.h                 |    2 +-
 src/messages/MOSDOp.h                              |    2 +-
 src/messages/MOSDSubOp.h                           |    2 +-
 src/messages/MPoolOp.h                             |    4 +-
 src/messages/MPoolOpReply.h                        |    4 +-
 src/messages/MStatfs.h                             |    2 +-
 src/messages/MStatfsReply.h                        |    2 +-
 src/mon/LogMonitor.cc                              |    2 +-
 src/mon/MDSMonitor.cc                              |   15 +-
 src/mon/Makefile.am                                |    2 +-
 src/mon/MonClient.cc                               |   22 +-
 src/mon/MonClient.h                                |    4 +-
 src/mon/MonCommands.h                              |   52 +-
 src/mon/Monitor.cc                                 |   20 +-
 src/mon/Monitor.h                                  |    4 +-
 src/mon/OSDMonitor.cc                              |  586 ++++-
 src/mon/OSDMonitor.h                               |   32 +-
 src/mon/PGMap.cc                                   |   41 +-
 src/mon/PGMap.h                                    |   20 +-
 src/mon/PGMonitor.cc                               |   11 +
 src/mon/Paxos.cc                                   |   15 +-
 src/msg/Accepter.cc                                |    4 +-
 src/msg/DispatchQueue.cc                           |    1 +
 src/msg/DispatchQueue.h                            |    1 +
 src/msg/Message.h                                  |   11 +-
 src/msg/Pipe.cc                                    |   86 +-
 src/msg/Pipe.h                                     |    9 +-
 src/msg/SimpleMessenger.cc                         |   23 +-
 src/ocf/Makefile.in                                |   16 +-
 src/os/FDCache.h                                   |    2 +-
 src/os/FileJournal.cc                              |    6 +-
 src/os/FileStore.cc                                |   68 +-
 src/os/GenericFileStoreBackend.cc                  |    6 +-
 src/os/HashIndex.cc                                |    3 +-
 src/os/HashIndex.h                                 |    5 +-
 src/os/KeyValueStore.cc                            |   18 +-
 src/os/LFNIndex.cc                                 |    2 +-
 src/os/ObjectStore.h                               |  469 +++-
 src/osd/ECBackend.cc                               |   44 +-
 src/osd/ECBackend.h                                |   16 +-
 src/osd/ECMsgTypes.h                               |   14 +-
 src/osd/Makefile.am                                |    2 +-
 src/osd/OSD.cc                                     |   22 +-
 src/osd/OSD.h                                      |   17 +-
 src/osd/OSDMap.cc                                  |   76 +-
 src/osd/OSDMap.h                                   |   46 +-
 src/osd/OpRequest.h                                |    4 +-
 src/osd/PG.cc                                      |   62 +-
 src/osd/PG.h                                       |    3 +-
 src/osd/PGBackend.cc                               |   17 +-
 src/osd/PGBackend.h                                |   13 +-
 src/osd/ReplicatedBackend.cc                       |    8 +-
 src/osd/ReplicatedBackend.h                        |   10 +-
 src/osd/ReplicatedPG.cc                            |  281 +-
 src/osd/ReplicatedPG.h                             |   31 +-
 src/osd/Watch.cc                                   |    4 +-
 src/osd/Watch.h                                    |    4 +-
 src/osd/osd_types.cc                               |   29 +-
 src/osd/osd_types.h                                |   10 +-
 src/osdc/Journaler.h                               |   32 +
 src/osdc/ObjectCacher.cc                           |    8 +-
 src/osdc/ObjectCacher.h                            |   22 +-
 src/osdc/Objecter.cc                               |  137 +-
 src/osdc/Objecter.h                                |  113 +-
 src/osdc/WritebackHandler.h                        |   13 +-
 src/pybind/ceph_argparse.py                        |   12 +-
 src/pybind/rados.py                                |   58 +-
 src/rbd.cc                                         |    8 +-
 src/rgw/logrotate.conf                             |    1 +
 src/rgw/rgw_common.h                               |   63 +-
 src/rgw/rgw_json_enc.cc                            |    4 +
 src/rgw/rgw_main.cc                                |   18 +-
 src/rgw/rgw_op.cc                                  |    7 +
 src/rgw/rgw_rados.cc                               |  401 ++-
 src/rgw/rgw_rados.h                                |   38 +-
 src/rgw/rgw_rest.cc                                |    7 +-
 src/rgw/rgw_rest_s3.cc                             |   18 +-
 src/rgw/rgw_rest_user.cc                           |    2 +-
 src/stop.sh                                        |   89 +-
 src/test/Makefile.am                               |    6 +
 src/test/bench/distribution.h                      |    6 +-
 src/test/crypto_init.cc                            |   48 +
 src/test/encoding/ceph_dencoder.cc                 |   19 +-
 src/test/encoding/types.h                          |   11 +-
 src/test/erasure-code/Makefile.am                  |   30 +-
 src/test/erasure-code/TestErasureCodeJerasure.cc   |   46 +-
 src/test/erasure-code/TestErasureCodePlugin.cc     |   22 +-
 .../erasure-code/TestErasureCodePluginJerasure.cc  |  183 +-
 src/test/erasure-code/TestJerasurePluginGeneric.cc |   23 +
 src/test/erasure-code/TestJerasurePluginSSE3.cc    |   23 +
 src/test/erasure-code/TestJerasurePluginSSE4.cc    |   23 +
 src/test/erasure-code/ceph_erasure_code.cc         |   22 +-
 .../erasure-code/ceph_erasure_code_benchmark.cc    |   24 +-
 src/test/libcephfs/test.cc                         |    3 +
 src/test/librados/TestCase.cc                      |   93 +
 src/test/librados/TestCase.h                       |   37 +
 src/test/librados/aio.cc                           |   17 +-
 src/test/librados/io.cc                            |  459 ++++
 src/test/librados/list.cc                          |  292 +++
 src/test/librados/lock.cc                          |  181 ++
 src/test/librados/snapshots.cc                     |  336 +++
 src/test/librados/stat.cc                          |  118 +
 src/test/librados/test.cc                          |  116 +
 src/test/librados/test.h                           |    5 +
 src/test/librados/tier.cc                          | 2114 +++++++++++++++
 src/test/librados/watch_notify.cc                  |   54 +
 src/test/librbd/test_librbd.cc                     |    2 +
 src/test/mon/PGMap.cc                              |   16 +-
 src/test/mon/mon-test-helpers.sh                   |   35 +-
 src/test/multi_stress_watch.cc                     |  124 +-
 src/test/osd/RadosModel.h                          |   27 +-
 src/test/osd/TestRados.cc                          |    6 +-
 src/test/osd/osd-test-helpers.sh                   |    1 +
 src/test/osdc/FakeWriteback.cc                     |    2 +-
 src/test/osdc/FakeWriteback.h                      |    9 +-
 src/test/system/rados_list_parallel.cc             |    9 +
 src/test/test_filejournal.cc                       |    4 +-
 src/tools/Makefile.am                              |   14 +-
 src/tools/ceph-client-debug.cc                     |  179 ++
 src/tools/ceph_conf.cc                             |    4 +-
 ...ph-filestore-dump.cc => ceph_filestore_dump.cc} |  144 +-
 ...ph-filestore-tool.cc => ceph_filestore_tool.cc} |    0
 .../{ceph-kvstore-tool.cc => ceph_kvstore_tool.cc} |    0
 ...ceph-monstore-tool.cc => ceph_monstore_tool.cc} |    0
 .../{ceph-osdomap-tool.cc => ceph_osdomap_tool.cc} |    0
 src/tools/rados/rados.cc                           |   65 +-
 src/tools/scratchtoolpp.cc                         |    6 +-
 src/vstart.sh                                      |    7 +-
 298 files changed, 29308 insertions(+), 4271 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 8e0c650..cba3af2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -21,8 +21,8 @@ EXTRA_DIST += \
 install-data-local:
 	-mkdir -p $(DESTDIR)$(datadir)/ceph
 	-install -m 644 share/known_hosts_drop.ceph.com $(DESTDIR)$(datadir)/ceph/known_hosts_drop.ceph.com
-	-install -m 644 share/known_hosts_drop.ceph.com $(DESTDIR)$(datadir)/ceph/id_dsa_drop.ceph.com
-	-install -m 644 share/known_hosts_drop.ceph.com $(DESTDIR)$(datadir)/ceph/id_dsa_drop.ceph.com.pub
+	-install -m 644 share/id_dsa_drop.ceph.com $(DESTDIR)$(datadir)/ceph/id_dsa_drop.ceph.com
+	-install -m 644 share/id_dsa_drop.ceph.com.pub $(DESTDIR)$(datadir)/ceph/id_dsa_drop.ceph.com.pub
 
 all-local:
 if WITH_DEBUG
diff --git a/Makefile.in b/Makefile.in
index 0da4246..eb16431 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -51,10 +51,10 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_classpath.m4 \
 	$(top_srcdir)/m4/ax_c_var_func.m4 \
 	$(top_srcdir)/m4/ax_check_compile_flag.m4 \
 	$(top_srcdir)/m4/ax_cxx_static_cast.m4 \
-	$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
-	$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
-	$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
-	$(top_srcdir)/configure.ac
+	$(top_srcdir)/m4/ax_intel.m4 $(top_srcdir)/m4/libtool.m4 \
+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+	$(top_srcdir)/m4/pkg.m4 $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
@@ -173,6 +173,14 @@ INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
 INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTEL_FLAGS = @INTEL_FLAGS@
+INTEL_PCLMUL_FLAGS = @INTEL_PCLMUL_FLAGS@
+INTEL_SSE2_FLAGS = @INTEL_SSE2_FLAGS@
+INTEL_SSE3_FLAGS = @INTEL_SSE3_FLAGS@
+INTEL_SSE4_1_FLAGS = @INTEL_SSE4_1_FLAGS@
+INTEL_SSE4_2_FLAGS = @INTEL_SSE4_2_FLAGS@
+INTEL_SSE_FLAGS = @INTEL_SSE_FLAGS@
+INTEL_SSSE3_FLAGS = @INTEL_SSSE3_FLAGS@
 JAR = @JAR@
 JAVAC = @JAVAC@
 JAVAH = @JAVAH@
@@ -810,8 +818,8 @@ uninstall-am:
 install-data-local:
 	-mkdir -p $(DESTDIR)$(datadir)/ceph
 	-install -m 644 share/known_hosts_drop.ceph.com $(DESTDIR)$(datadir)/ceph/known_hosts_drop.ceph.com
-	-install -m 644 share/known_hosts_drop.ceph.com $(DESTDIR)$(datadir)/ceph/id_dsa_drop.ceph.com
-	-install -m 644 share/known_hosts_drop.ceph.com $(DESTDIR)$(datadir)/ceph/id_dsa_drop.ceph.com.pub
+	-install -m 644 share/id_dsa_drop.ceph.com $(DESTDIR)$(datadir)/ceph/id_dsa_drop.ceph.com
+	-install -m 644 share/id_dsa_drop.ceph.com.pub $(DESTDIR)$(datadir)/ceph/id_dsa_drop.ceph.com.pub
 
 all-local:
 #	We need gtest to build the rados-api tests. We only build those in
diff --git a/README b/README
index cde4bbc..0eb3ac7 100644
--- a/README
+++ b/README
@@ -126,6 +126,7 @@ To build the source code, you must install the following:
 - libblkid-dev
 - libatomic-ops-dev
 - libboost-program-options-dev
+- libboost-system-dev
 - libboost-thread-dev
 - libexpat1-dev
 - libleveldb-dev
@@ -136,7 +137,9 @@ To build the source code, you must install the following:
 
 For example:
 
-	$ apt-get install automake autoconf pkg-config gcc g++ make libboost-dev libedit-dev libssl-dev libtool libfcgi libfcgi-dev xfslibs-dev libfuse-dev linux-kernel-headers libcrypto++-dev libaio-dev libgoogle-perftools-dev libkeyutils-dev uuid-dev libblkid-dev libatomic-ops-dev libboost-program-options-dev libboost-thread-dev libexpat1-dev libleveldb-dev libsnappy-dev libcurl4-gnutls-dev python-argparse python-flask
+	$ apt-get install automake autoconf pkg-config gcc g++ make libboost-dev libedit-dev libssl-dev libtool libfcgi libfcgi-dev xfslibs-dev libfuse-dev linux-kernel-headers libcrypto++-dev libaio-dev libgoogle-perftools-dev libkeyutils-dev uuid-dev libblkid-dev libatomic-ops-dev libboost-program-options-dev libboost-system-dev libboost-thread-dev libexpat1-dev libleveldb-dev libsnappy-dev libcurl4-gnutls-dev python-argparse python-flask python-nose
+
+Note: libsnappy-dev and libleveldb-dev are not available upstream for natty, oneiric, and squeeze.  Backports for Ceph can be found at ceph.com/debian-leveldb.
 
 rpm-based
 ---------
@@ -170,5 +173,5 @@ These are the rpm packages needed to install in an rpm-based OS:
 
 For example:
 
-	$ yum install autoconf automake gcc gcc-c++ make libtool python-argparse python-flask libuuid-devel libblkid-devel keyutils-libs-devel cryptopp-devel nss-devel fcgi-devel expat-devel libcurl-devel xfsprogs-devel fuse-devel gperftools-devel libedit-devel libatomic_ops-devel snappy-devel leveldb-devel libaio-devel boost-devel
+	$ yum install autoconf automake gcc gcc-c++ make libtool python-argparse python-flask libuuid-devel libblkid-devel keyutils-libs-devel cryptopp-devel nss-devel fcgi-devel expat-devel libcurl-devel xfsprogs-devel fuse-devel gperftools-devel libedit-devel libatomic_ops-devel snappy-devel leveldb-devel libaio-devel boost-devel python-nose
 
diff --git a/aclocal.m4 b/aclocal.m4
index 2da43c3..fa0745a 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -1376,6 +1376,7 @@ m4_include([m4/ax_c_pretty_func.m4])
 m4_include([m4/ax_c_var_func.m4])
 m4_include([m4/ax_check_compile_flag.m4])
 m4_include([m4/ax_cxx_static_cast.m4])
+m4_include([m4/ax_intel.m4])
 m4_include([m4/libtool.m4])
 m4_include([m4/ltoptions.m4])
 m4_include([m4/ltsugar.m4])
diff --git a/ceph.spec b/ceph.spec
index 66eb92a..b4f21d0 100644
--- a/ceph.spec
+++ b/ceph.spec
@@ -9,7 +9,7 @@
 # common
 #################################################################################
 Name:		ceph
-Version:	0.78
+Version:	0.79
 Release:	0%{?dist}
 Summary:	User space components of the Ceph file system
 License:	GPL-2.0
@@ -406,6 +406,7 @@ fi
 %{_bindir}/librados-config
 %{_bindir}/rados
 %{_bindir}/rbd
+%{_bindir}/ceph-client-debug
 %{_bindir}/ceph-debugpack
 %{_bindir}/ceph-coverage
 %{_bindir}/ceph_mon_store_converter
@@ -430,13 +431,15 @@ fi
 %{_libdir}/rados-classes/libcls_log.so*
 %{_libdir}/rados-classes/libcls_replica_log.so*
 %{_libdir}/rados-classes/libcls_statelog.so*
+%{_libdir}/rados-classes/libcls_user.so*
 %{_libdir}/rados-classes/libcls_version.so*
 %dir %{_libdir}/ceph/erasure-code
 %{_libdir}/ceph/erasure-code/libec_example.so*
 %{_libdir}/ceph/erasure-code/libec_fail_to_initialize.so*
 %{_libdir}/ceph/erasure-code/libec_fail_to_register.so*
 %{_libdir}/ceph/erasure-code/libec_hangs.so*
-%{_libdir}/ceph/erasure-code/libec_jerasure.so*
+%{_libdir}/ceph/erasure-code/libec_jerasure*.so*
+%{_libdir}/ceph/erasure-code/libec_test_jerasure*.so*
 %{_libdir}/ceph/erasure-code/libec_missing_entry_point.so*
 /lib/udev/rules.d/50-rbd.rules
 /lib/udev/rules.d/60-ceph-partuuid-workaround.rules
@@ -583,6 +586,8 @@ fi
 
 %post -n librbd1
 /sbin/ldconfig
+mkdir -p /usr/lib64/qemu/ 
+ln -sf %{_libdir}/librbd.so.1 /usr/lib64/qemu/librbd.so.1
 
 %postun -n librbd1
 /sbin/ldconfig
@@ -635,65 +640,7 @@ fi
 %{_bindir}/ceph_filestore_dump
 %{_bindir}/ceph_filestore_tool
 %{_bindir}/ceph_streamtest
-%{_bindir}/ceph_test_c_headers
-%{_bindir}/ceph_test_cfuse_cache_invalidate
-%{_bindir}/ceph_test_cls_hello
-%{_bindir}/ceph_test_cls_lock
-%{_bindir}/ceph_test_cls_log
-%{_bindir}/ceph_test_cls_rbd
-%{_bindir}/ceph_test_cls_refcount
-%{_bindir}/ceph_test_cls_replica_log
-%{_bindir}/ceph_test_cls_rgw
-%{_bindir}/ceph_test_cls_rgw_log
-%{_bindir}/ceph_test_cls_rgw_meta
-%{_bindir}/ceph_test_cls_rgw_opstate
-%{_bindir}/ceph_test_cls_statelog
-%{_bindir}/ceph_test_cls_version
-%{_bindir}/ceph_test_cors
-%{_bindir}/ceph_test_filejournal
-%{_bindir}/ceph_test_objectstore
-%{_bindir}/ceph_test_filestore_idempotent
-%{_bindir}/ceph_test_filestore_idempotent_sequence
-%{_bindir}/ceph_test_objectstore_workloadgen
-%{_bindir}/ceph_test_get_blkdev_size
-%{_bindir}/ceph_test_ioctls
-%{_bindir}/ceph_test_keyvaluedb_atomicity
-%{_bindir}/ceph_test_keyvaluedb_iterators
-%{_bindir}/ceph_test_libcephfs
-%{_bindir}/ceph_test_librbd
-%{_bindir}/ceph_test_librbd_fsx
-%{_bindir}/ceph_test_mon_workloadgen
-%{_bindir}/ceph_test_mutate
-%{_bindir}/ceph_test_object_map
-%{_bindir}/ceph_test_objectcacher_stress
-%{_bindir}/ceph_test_rados_api_aio
-%{_bindir}/ceph_test_rados_api_cls
-%{_bindir}/ceph_test_rados_api_c_read_operations
-%{_bindir}/ceph_test_rados_api_c_write_operations
-%{_bindir}/ceph_test_rados_api_cmd
-%{_bindir}/ceph_test_rados_api_io
-%{_bindir}/ceph_test_rados_api_list
-%{_bindir}/ceph_test_rados_api_lock
-%{_bindir}/ceph_test_rados_api_misc
-%{_bindir}/ceph_test_rados_api_tier
-%{_bindir}/ceph_test_rados_api_pool
-%{_bindir}/ceph_test_rados_api_snapshots
-%{_bindir}/ceph_test_rados_api_stat
-%{_bindir}/ceph_test_rados_api_watch_notify
-%{_bindir}/ceph_test_rewrite_latency
-%{_bindir}/ceph_test_stress_watch
-%{_bindir}/ceph_test_trans
-%{_bindir}/ceph_test_crypto
-%{_bindir}/ceph_test_keys
-%{_bindir}/ceph_test_msgr
-%{_bindir}/ceph_test_rados
-%{_bindir}/ceph_test_rados_delete_pools_parallel
-%{_bindir}/ceph_test_rados_list_parallel
-%{_bindir}/ceph_test_rados_open_pools_parallel
-%{_bindir}/ceph_test_rados_watch_notify
-%{_bindir}/ceph_test_signal_handlers
-%{_bindir}/ceph_test_snap_mapper
-%{_bindir}/ceph_test_timers
+%{_bindir}/ceph_test_*
 %{_bindir}/ceph_tpbench
 %{_bindir}/ceph_xattr_bench
 %{_bindir}/ceph-monstore-tool
diff --git a/ceph.spec.in b/ceph.spec.in
index 2f2216f..ee9dbd9 100644
--- a/ceph.spec.in
+++ b/ceph.spec.in
@@ -406,6 +406,7 @@ fi
 %{_bindir}/librados-config
 %{_bindir}/rados
 %{_bindir}/rbd
+%{_bindir}/ceph-client-debug
 %{_bindir}/ceph-debugpack
 %{_bindir}/ceph-coverage
 %{_bindir}/ceph_mon_store_converter
@@ -430,13 +431,15 @@ fi
 %{_libdir}/rados-classes/libcls_log.so*
 %{_libdir}/rados-classes/libcls_replica_log.so*
 %{_libdir}/rados-classes/libcls_statelog.so*
+%{_libdir}/rados-classes/libcls_user.so*
 %{_libdir}/rados-classes/libcls_version.so*
 %dir %{_libdir}/ceph/erasure-code
 %{_libdir}/ceph/erasure-code/libec_example.so*
 %{_libdir}/ceph/erasure-code/libec_fail_to_initialize.so*
 %{_libdir}/ceph/erasure-code/libec_fail_to_register.so*
 %{_libdir}/ceph/erasure-code/libec_hangs.so*
-%{_libdir}/ceph/erasure-code/libec_jerasure.so*
+%{_libdir}/ceph/erasure-code/libec_jerasure*.so*
+%{_libdir}/ceph/erasure-code/libec_test_jerasure*.so*
 %{_libdir}/ceph/erasure-code/libec_missing_entry_point.so*
 /lib/udev/rules.d/50-rbd.rules
 /lib/udev/rules.d/60-ceph-partuuid-workaround.rules
@@ -583,6 +586,8 @@ fi
 
 %post -n librbd1
 /sbin/ldconfig
+mkdir -p /usr/lib64/qemu/ 
+ln -sf %{_libdir}/librbd.so.1 /usr/lib64/qemu/librbd.so.1
 
 %postun -n librbd1
 /sbin/ldconfig
@@ -635,65 +640,7 @@ fi
 %{_bindir}/ceph_filestore_dump
 %{_bindir}/ceph_filestore_tool
 %{_bindir}/ceph_streamtest
-%{_bindir}/ceph_test_c_headers
-%{_bindir}/ceph_test_cfuse_cache_invalidate
-%{_bindir}/ceph_test_cls_hello
-%{_bindir}/ceph_test_cls_lock
-%{_bindir}/ceph_test_cls_log
-%{_bindir}/ceph_test_cls_rbd
-%{_bindir}/ceph_test_cls_refcount
-%{_bindir}/ceph_test_cls_replica_log
-%{_bindir}/ceph_test_cls_rgw
-%{_bindir}/ceph_test_cls_rgw_log
-%{_bindir}/ceph_test_cls_rgw_meta
-%{_bindir}/ceph_test_cls_rgw_opstate
-%{_bindir}/ceph_test_cls_statelog
-%{_bindir}/ceph_test_cls_version
-%{_bindir}/ceph_test_cors
-%{_bindir}/ceph_test_filejournal
-%{_bindir}/ceph_test_objectstore
-%{_bindir}/ceph_test_filestore_idempotent
-%{_bindir}/ceph_test_filestore_idempotent_sequence
-%{_bindir}/ceph_test_objectstore_workloadgen
-%{_bindir}/ceph_test_get_blkdev_size
-%{_bindir}/ceph_test_ioctls
-%{_bindir}/ceph_test_keyvaluedb_atomicity
-%{_bindir}/ceph_test_keyvaluedb_iterators
-%{_bindir}/ceph_test_libcephfs
-%{_bindir}/ceph_test_librbd
-%{_bindir}/ceph_test_librbd_fsx
-%{_bindir}/ceph_test_mon_workloadgen
-%{_bindir}/ceph_test_mutate
-%{_bindir}/ceph_test_object_map
-%{_bindir}/ceph_test_objectcacher_stress
-%{_bindir}/ceph_test_rados_api_aio
-%{_bindir}/ceph_test_rados_api_cls
-%{_bindir}/ceph_test_rados_api_c_read_operations
-%{_bindir}/ceph_test_rados_api_c_write_operations
-%{_bindir}/ceph_test_rados_api_cmd
-%{_bindir}/ceph_test_rados_api_io
-%{_bindir}/ceph_test_rados_api_list
-%{_bindir}/ceph_test_rados_api_lock
-%{_bindir}/ceph_test_rados_api_misc
-%{_bindir}/ceph_test_rados_api_tier
-%{_bindir}/ceph_test_rados_api_pool
-%{_bindir}/ceph_test_rados_api_snapshots
-%{_bindir}/ceph_test_rados_api_stat
-%{_bindir}/ceph_test_rados_api_watch_notify
-%{_bindir}/ceph_test_rewrite_latency
-%{_bindir}/ceph_test_stress_watch
-%{_bindir}/ceph_test_trans
-%{_bindir}/ceph_test_crypto
-%{_bindir}/ceph_test_keys
-%{_bindir}/ceph_test_msgr
-%{_bindir}/ceph_test_rados
-%{_bindir}/ceph_test_rados_delete_pools_parallel
-%{_bindir}/ceph_test_rados_list_parallel
-%{_bindir}/ceph_test_rados_open_pools_parallel
-%{_bindir}/ceph_test_rados_watch_notify
-%{_bindir}/ceph_test_signal_handlers
-%{_bindir}/ceph_test_snap_mapper
-%{_bindir}/ceph_test_timers
+%{_bindir}/ceph_test_*
 %{_bindir}/ceph_tpbench
 %{_bindir}/ceph_xattr_bench
 %{_bindir}/ceph-monstore-tool
diff --git a/configure b/configure
index 10821fa..35653bd 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.68 for ceph 0.78.
+# Generated by GNU Autoconf 2.68 for ceph 0.79.
 #
 # Report bugs to <ceph-devel at vger.kernel.org>.
 #
@@ -570,8 +570,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='ceph'
 PACKAGE_TARNAME='ceph'
-PACKAGE_VERSION='0.78'
-PACKAGE_STRING='ceph 0.78'
+PACKAGE_VERSION='0.79'
+PACKAGE_STRING='ceph 0.79'
 PACKAGE_BUGREPORT='ceph-devel at vger.kernel.org'
 PACKAGE_URL=''
 
@@ -642,6 +642,14 @@ WITH_REST_BENCH_FALSE
 WITH_REST_BENCH_TRUE
 WITH_SYSTEM_LIBS3_FALSE
 WITH_SYSTEM_LIBS3_TRUE
+INTEL_FLAGS
+INTEL_SSE4_2_FLAGS
+INTEL_SSE4_1_FLAGS
+INTEL_PCLMUL_FLAGS
+INTEL_SSSE3_FLAGS
+INTEL_SSE3_FLAGS
+INTEL_SSE2_FLAGS
+INTEL_SSE_FLAGS
 WITH_OCF_FALSE
 WITH_OCF_TRUE
 WITH_LIBATOMIC_FALSE
@@ -1433,7 +1441,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures ceph 0.78 to adapt to many kinds of systems.
+\`configure' configures ceph 0.79 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1504,7 +1512,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of ceph 0.78:";;
+     short | recursive ) echo "Configuration of ceph 0.79:";;
    esac
   cat <<\_ACEOF
 
@@ -1649,7 +1657,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-ceph configure 0.78
+ceph configure 0.79
 generated by GNU Autoconf 2.68
 
 Copyright (C) 2010 Free Software Foundation, Inc.
@@ -2341,7 +2349,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by ceph $as_me 0.78, which was
+It was created by ceph $as_me 0.79, which was
 generated by GNU Autoconf 2.68.  Invocation command line was
 
   $ $0 $@
@@ -4341,7 +4349,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='ceph'
- VERSION='0.78'
+ VERSION='0.79'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -12319,7 +12327,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='ceph'
- VERSION='0.78'
+ VERSION='0.79'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -18743,7 +18751,7 @@ else
 JAVA_TEST=Test.java
 CLASS_TEST=Test.class
 cat << \EOF > $JAVA_TEST
-/* #line 18746 "configure" */
+/* #line 18754 "configure" */
 public class Test {
 }
 EOF
@@ -19239,6 +19247,329 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
 ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
+# Find supported SIMD / SSE extensions supported by the compiler
+
+
+
+  case $target_cpu in
+    i[3456]86*|x86_64*|amd64*)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -msse" >&5
+$as_echo_n "checking whether C compiler accepts -msse... " >&6; }
+if ${ax_cv_check_cflags___msse+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+  ax_check_save_flags=$CFLAGS
+  CFLAGS="$CFLAGS  -msse"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ax_cv_check_cflags___msse=yes
+else
+  ax_cv_check_cflags___msse=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___msse" >&5
+$as_echo "$ax_cv_check_cflags___msse" >&6; }
+if test x"$ax_cv_check_cflags___msse" = xyes; then :
+  ax_cv_support_sse_ext=yes
+else
+  :
+fi
+
+      if test x"$ax_cv_support_sse_ext" = x"yes"; then
+        INTEL_SSE_FLAGS="-msse -DINTEL_SSE"
+
+        INTEL_FLAGS="$INTEL_FLAGS $INTEL_SSE_FLAGS"
+
+$as_echo "#define HAVE_SSE /**/" >>confdefs.h
+
+      fi
+
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -msse2" >&5
+$as_echo_n "checking whether C compiler accepts -msse2... " >&6; }
+if ${ax_cv_check_cflags___msse2+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+  ax_check_save_flags=$CFLAGS
+  CFLAGS="$CFLAGS  -msse2"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ax_cv_check_cflags___msse2=yes
+else
+  ax_cv_check_cflags___msse2=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___msse2" >&5
+$as_echo "$ax_cv_check_cflags___msse2" >&6; }
+if test x"$ax_cv_check_cflags___msse2" = xyes; then :
+  ax_cv_support_sse2_ext=yes
+else
+  :
+fi
+
+      if test x"$ax_cv_support_sse2_ext" = x"yes"; then
+        INTEL_SSE2_FLAGS="-msse2 -DINTEL_SSE2"
+
+        INTEL_FLAGS="$INTEL_FLAGS $INTEL_SSE2_FLAGS"
+
+$as_echo "#define HAVE_SSE2 /**/" >>confdefs.h
+
+      fi
+
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -msse3" >&5
+$as_echo_n "checking whether C compiler accepts -msse3... " >&6; }
+if ${ax_cv_check_cflags___msse3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+  ax_check_save_flags=$CFLAGS
+  CFLAGS="$CFLAGS  -msse3"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ax_cv_check_cflags___msse3=yes
+else
+  ax_cv_check_cflags___msse3=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___msse3" >&5
+$as_echo "$ax_cv_check_cflags___msse3" >&6; }
+if test x"$ax_cv_check_cflags___msse3" = xyes; then :
+  ax_cv_support_sse3_ext=yes
+else
+  :
+fi
+
+      if test x"$ax_cv_support_sse3_ext" = x"yes"; then
+        INTEL_SSE3_FLAGS="-msse3 -DINTEL_SSE3"
+
+        INTEL_FLAGS="$INTEL_FLAGS $INTEL_SSE3_FLAGS"
+
+$as_echo "#define HAVE_SSE3 /**/" >>confdefs.h
+
+      fi
+
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -mssse3" >&5
+$as_echo_n "checking whether C compiler accepts -mssse3... " >&6; }
+if ${ax_cv_check_cflags___mssse3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+  ax_check_save_flags=$CFLAGS
+  CFLAGS="$CFLAGS  -mssse3"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ax_cv_check_cflags___mssse3=yes
+else
+  ax_cv_check_cflags___mssse3=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___mssse3" >&5
+$as_echo "$ax_cv_check_cflags___mssse3" >&6; }
+if test x"$ax_cv_check_cflags___mssse3" = xyes; then :
+  ax_cv_support_ssse3_ext=yes
+else
+  :
+fi
+
+      if test x"$ax_cv_support_ssse3_ext" = x"yes"; then
+        INTEL_SSSE3_FLAGS="-mssse3 -DINTEL_SSSE3"
+
+        INTEL_FLAGS="$INTEL_FLAGS $INTEL_SSSE3_FLAGS"
+
+$as_echo "#define HAVE_SSSE3 /**/" >>confdefs.h
+
+      fi
+    ;;
+  esac
+
+  case $target_cpu in
+  x86_64*|amd64*)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -mpclmul" >&5
+$as_echo_n "checking whether C compiler accepts -mpclmul... " >&6; }
+if ${ax_cv_check_cflags___mpclmul+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+  ax_check_save_flags=$CFLAGS
+  CFLAGS="$CFLAGS  -mpclmul"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ax_cv_check_cflags___mpclmul=yes
+else
+  ax_cv_check_cflags___mpclmul=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___mpclmul" >&5
+$as_echo "$ax_cv_check_cflags___mpclmul" >&6; }
+if test x"$ax_cv_check_cflags___mpclmul" = xyes; then :
+  ax_cv_support_pclmuldq_ext=yes
+else
+  :
+fi
+
+      if test x"$ax_cv_support_pclmuldq_ext" = x"yes"; then
+        INTEL_PCLMUL_FLAGS="-mpclmul -DINTEL_SSE4_PCLMUL"
+
+        INTEL_FLAGS="$INTEL_FLAGS $INTEL_PCLMUL_FLAGS"
+
+$as_echo "#define HAVE_PCLMUL /**/" >>confdefs.h
+
+      fi
+
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -msse4.1" >&5
+$as_echo_n "checking whether C compiler accepts -msse4.1... " >&6; }
+if ${ax_cv_check_cflags___msse4_1+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+  ax_check_save_flags=$CFLAGS
+  CFLAGS="$CFLAGS  -msse4.1"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ax_cv_check_cflags___msse4_1=yes
+else
+  ax_cv_check_cflags___msse4_1=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___msse4_1" >&5
+$as_echo "$ax_cv_check_cflags___msse4_1" >&6; }
+if test x"$ax_cv_check_cflags___msse4_1" = xyes; then :
+  ax_cv_support_sse41_ext=yes
+else
+  :
+fi
+
+      if test x"$ax_cv_support_sse41_ext" = x"yes"; then
+        INTEL_SSE4_1_FLAGS="-msse4.1 -DINTEL_SSE4"
+
+        INTEL_FLAGS="$INTEL_FLAGS $INTEL_SSE4_1_FLAGS"
+
+$as_echo "#define HAVE_SSE4_1 /**/" >>confdefs.h
+
+      fi
+
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -msse4.2" >&5
+$as_echo_n "checking whether C compiler accepts -msse4.2... " >&6; }
+if ${ax_cv_check_cflags___msse4_2+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+  ax_check_save_flags=$CFLAGS
+  CFLAGS="$CFLAGS  -msse4.2"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ax_cv_check_cflags___msse4_2=yes
+else
+  ax_cv_check_cflags___msse4_2=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___msse4_2" >&5
+$as_echo "$ax_cv_check_cflags___msse4_2" >&6; }
+if test x"$ax_cv_check_cflags___msse4_2" = xyes; then :
+  ax_cv_support_sse42_ext=yes
+else
+  :
+fi
+
+      if test x"$ax_cv_support_sse42_ext" = x"yes"; then
+        INTEL_SSE4_2_FLAGS="-msse4.2 -DINTEL_SSE4"
+
+        INTEL_FLAGS="$INTEL_FLAGS $INTEL_SSE4_2_FLAGS"
+
+$as_echo "#define HAVE_SSE4_2 /**/" >>confdefs.h
+
+      fi
+    ;;
+  esac
+
+
+
+
 # use system libs3?
 
 # Check whether --with-system-libs3 was given.
@@ -21666,7 +21997,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by ceph $as_me 0.78, which was
+This file was extended by ceph $as_me 0.79, which was
 generated by GNU Autoconf 2.68.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -21732,7 +22063,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-ceph config.status 0.78
+ceph config.status 0.79
 configured by $0, generated by GNU Autoconf 2.68,
   with options \\"\$ac_cs_config\\"
 
diff --git a/configure.ac b/configure.ac
index 4e5ebf6..035f525 100644
--- a/configure.ac
+++ b/configure.ac
@@ -8,7 +8,7 @@ AC_PREREQ(2.59)
 # VERSION define is not used by the code.  It gets a version string
 # from 'git describe'; see src/ceph_ver.[ch]
 
-AC_INIT([ceph], [0.78], [ceph-devel at vger.kernel.org])
+AC_INIT([ceph], [0.79], [ceph-devel at vger.kernel.org])
 
 # Create release string.  Used with VERSION for RPMs.
 RPM_RELEASE=0
@@ -498,6 +498,9 @@ AC_LANG_PUSH([C++])
 AC_CHECK_HEADER([leveldb/filter_policy.h], [AC_DEFINE([HAVE_LEVELDB_FILTER_POLICY], [1], [Defined if LevelDB supports bloom filters ])])
 AC_LANG_POP([C++])
 
+# Find supported SIMD / SSE extensions supported by the compiler
+AX_INTEL_FEATURES()
+
 # use system libs3?
 AC_ARG_WITH([system-libs3],
 	[AS_HELP_STRING([--with-system-libs3], [use system libs3])],
diff --git a/m4/ax_intel.m4 b/m4/ax_intel.m4
new file mode 100644
index 0000000..347a3a6
--- /dev/null
+++ b/m4/ax_intel.m4
@@ -0,0 +1,70 @@
+AC_DEFUN([AX_INTEL_FEATURES],
+[
+  AC_REQUIRE([AC_CANONICAL_HOST])
+
+  case $target_cpu in 
+    i[[3456]]86*|x86_64*|amd64*)
+      AX_CHECK_COMPILE_FLAG(-msse, ax_cv_support_sse_ext=yes, [])
+      if test x"$ax_cv_support_sse_ext" = x"yes"; then
+        INTEL_SSE_FLAGS="-msse -DINTEL_SSE"
+        AC_SUBST(INTEL_SSE_FLAGS)
+        INTEL_FLAGS="$INTEL_FLAGS $INTEL_SSE_FLAGS"
+        AC_DEFINE(HAVE_SSE,,[Support SSE (Streaming SIMD Extensions) instructions])
+      fi
+    
+      AX_CHECK_COMPILE_FLAG(-msse2, ax_cv_support_sse2_ext=yes, [])
+      if test x"$ax_cv_support_sse2_ext" = x"yes"; then
+        INTEL_SSE2_FLAGS="-msse2 -DINTEL_SSE2"
+        AC_SUBST(INTEL_SSE2_FLAGS)
+        INTEL_FLAGS="$INTEL_FLAGS $INTEL_SSE2_FLAGS"
+        AC_DEFINE(HAVE_SSE2,,[Support SSE2 (Streaming SIMD Extensions 2) instructions])
+      fi
+    
+      AX_CHECK_COMPILE_FLAG(-msse3, ax_cv_support_sse3_ext=yes, [])
+      if test x"$ax_cv_support_sse3_ext" = x"yes"; then
+        INTEL_SSE3_FLAGS="-msse3 -DINTEL_SSE3"
+        AC_SUBST(INTEL_SSE3_FLAGS)
+        INTEL_FLAGS="$INTEL_FLAGS $INTEL_SSE3_FLAGS"
+        AC_DEFINE(HAVE_SSE3,,[Support SSE3 (Streaming SIMD Extensions 3) instructions])
+      fi
+    
+      AX_CHECK_COMPILE_FLAG(-mssse3, ax_cv_support_ssse3_ext=yes, [])
+      if test x"$ax_cv_support_ssse3_ext" = x"yes"; then
+        INTEL_SSSE3_FLAGS="-mssse3 -DINTEL_SSSE3"
+        AC_SUBST(INTEL_SSSE3_FLAGS)
+        INTEL_FLAGS="$INTEL_FLAGS $INTEL_SSSE3_FLAGS"
+        AC_DEFINE(HAVE_SSSE3,,[Support SSSE3 (Supplemental Streaming SIMD Extensions 3) instructions])
+      fi
+    ;;
+  esac
+
+  case $target_cpu in
+  x86_64*|amd64*)
+      AX_CHECK_COMPILE_FLAG(-mpclmul, ax_cv_support_pclmuldq_ext=yes, [])
+      if test x"$ax_cv_support_pclmuldq_ext" = x"yes"; then
+        INTEL_PCLMUL_FLAGS="-mpclmul -DINTEL_SSE4_PCLMUL"
+        AC_SUBST(INTEL_PCLMUL_FLAGS)
+        INTEL_FLAGS="$INTEL_FLAGS $INTEL_PCLMUL_FLAGS"
+        AC_DEFINE(HAVE_PCLMUL,,[Support (PCLMUL) Carry-Free Muliplication])
+      fi
+    
+      AX_CHECK_COMPILE_FLAG(-msse4.1, ax_cv_support_sse41_ext=yes, [])
+      if test x"$ax_cv_support_sse41_ext" = x"yes"; then
+        INTEL_SSE4_1_FLAGS="-msse4.1 -DINTEL_SSE4"
+        AC_SUBST(INTEL_SSE4_1_FLAGS)
+        INTEL_FLAGS="$INTEL_FLAGS $INTEL_SSE4_1_FLAGS"
+        AC_DEFINE(HAVE_SSE4_1,,[Support SSE4.1 (Streaming SIMD Extensions 4.1) instructions])
+      fi
+    
+      AX_CHECK_COMPILE_FLAG(-msse4.2, ax_cv_support_sse42_ext=yes, [])
+      if test x"$ax_cv_support_sse42_ext" = x"yes"; then
+        INTEL_SSE4_2_FLAGS="-msse4.2 -DINTEL_SSE4"
+        AC_SUBST(INTEL_SSE4_2_FLAGS)
+        INTEL_FLAGS="$INTEL_FLAGS $INTEL_SSE4_2_FLAGS"
+        AC_DEFINE(HAVE_SSE4_2,,[Support SSE4.2 (Streaming SIMD Extensions 4.2) instructions])
+      fi
+    ;;
+  esac
+
+  AC_SUBST(INTEL_FLAGS)
+])
diff --git a/man/Makefile.in b/man/Makefile.in
index dab2731..e573231 100644
--- a/man/Makefile.in
+++ b/man/Makefile.in
@@ -48,10 +48,10 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_classpath.m4 \
 	$(top_srcdir)/m4/ax_c_var_func.m4 \
 	$(top_srcdir)/m4/ax_check_compile_flag.m4 \
 	$(top_srcdir)/m4/ax_cxx_static_cast.m4 \
-	$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
-	$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
-	$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
-	$(top_srcdir)/configure.ac
+	$(top_srcdir)/m4/ax_intel.m4 $(top_srcdir)/m4/libtool.m4 \
+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+	$(top_srcdir)/m4/pkg.m4 $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
@@ -145,6 +145,14 @@ INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
 INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTEL_FLAGS = @INTEL_FLAGS@
+INTEL_PCLMUL_FLAGS = @INTEL_PCLMUL_FLAGS@
+INTEL_SSE2_FLAGS = @INTEL_SSE2_FLAGS@
+INTEL_SSE3_FLAGS = @INTEL_SSE3_FLAGS@
+INTEL_SSE4_1_FLAGS = @INTEL_SSE4_1_FLAGS@
+INTEL_SSE4_2_FLAGS = @INTEL_SSE4_2_FLAGS@
+INTEL_SSE_FLAGS = @INTEL_SSE_FLAGS@
+INTEL_SSSE3_FLAGS = @INTEL_SSSE3_FLAGS@
 JAR = @JAR@
 JAVAC = @JAVAC@
 JAVAH = @JAVAH@
diff --git a/src/.git_version b/src/.git_version
index 2676f1e..28b5254 100644
--- a/src/.git_version
+++ b/src/.git_version
@@ -1,2 +1,2 @@
-f6c746c314d7b87b8419b6e584c94bfe4511dbd4
-v0.78
+4c2d73a5095f527c3a2168deb5fa54b3c8991a6e
+v0.79
diff --git a/src/Makefile-env.am b/src/Makefile-env.am
index 95ac36e..e1ba4a8 100644
--- a/src/Makefile-env.am
+++ b/src/Makefile-env.am
@@ -116,7 +116,7 @@ AM_CCASFLAGS = -f elf64
 #####################
 ## library definitions and dependencies
 
-EXTRALIBS = -luuid -lm $(KEYUTILS_LIB)
+EXTRALIBS = -luuid -lm
 if FREEBSD
 EXTRALIBS += -lexecinfo
 endif # FREEBSD
diff --git a/src/Makefile.am b/src/Makefile.am
index 599cb57..edec05e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -54,8 +54,8 @@ bin_PROGRAMS += ceph-mds
 
 # user tools
 
-mount_ceph_SOURCES = mount/mount.ceph.c
-mount_ceph_LDADD = $(LIBCOMMON)
+mount_ceph_SOURCES = mount/mount.ceph.c common/secret.c
+mount_ceph_LDADD = $(LIBCOMMON) $(KEYUTILS_LIB)
 if LINUX
 su_sbin_PROGRAMS += mount.ceph
 endif # LINUX
@@ -74,8 +74,8 @@ ceph_syn_SOURCES += client/SyntheticClient.cc # uses g_conf.. needs cleanup
 ceph_syn_LDADD = $(LIBCLIENT) $(CEPH_GLOBAL)
 bin_PROGRAMS += ceph-syn
 
-rbd_SOURCES = rbd.cc
-rbd_LDADD = $(LIBRBD) $(LIBRADOS) $(CEPH_GLOBAL) -lblkid
+rbd_SOURCES = rbd.cc common/secret.c
+rbd_LDADD = $(LIBRBD) $(LIBRADOS) $(CEPH_GLOBAL) -lblkid $(KEYUTILS_LIB)
 if LINUX
 bin_PROGRAMS += rbd
 endif #LINUX
@@ -276,8 +276,19 @@ base: core-daemons admin-tools \
 FORCE:
 .git_version: FORCE
 	$(srcdir)/check_version $(srcdir)/.git_version
+
+# if NO_VERSION is set, only generate a new ceph_ver.h if there currently 
+# is none, and call "make_version -n" to fill it with a fixed string.
+# Otherwise, set it from the contents of .git_version.
+
 ceph_ver.h: .git_version
-	$(srcdir)/make_version $(srcdir)/.git_version ./ceph_ver.h
+	if [ -n "$$NO_VERSION" ] ; then \
+	    if [ ! -f ./ceph_ver.h ] ; then \
+	        $(srcdir)/make_version -n ./ceph_ver.h ; \
+	    fi; \
+        else \
+	    $(srcdir)/make_version $(srcdir)/.git_version ./ceph_ver.h ; \
+	fi
 
 ceph_ver.c: ./ceph_ver.h
 common/version.cc: ./ceph_ver.h
diff --git a/src/Makefile.in b/src/Makefile.in
index d1fb014..533b12c 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -93,15 +93,15 @@ check_PROGRAMS = unittest_erasure_code_plugin$(EXEEXT) \
 	unittest_simple_spin$(EXEEXT) unittest_librados$(EXEEXT) \
 	unittest_bufferlist$(EXEEXT) unittest_crc32c$(EXEEXT) \
 	unittest_arch$(EXEEXT) unittest_crypto$(EXEEXT) \
-	unittest_perf_counters$(EXEEXT) unittest_admin_socket$(EXEEXT) \
-	unittest_ceph_crypto$(EXEEXT) unittest_utf8$(EXEEXT) \
-	unittest_mime$(EXEEXT) unittest_escape$(EXEEXT) \
-	unittest_chain_xattr$(EXEEXT) unittest_flatindex$(EXEEXT) \
-	unittest_strtol$(EXEEXT) unittest_confutils$(EXEEXT) \
-	unittest_config$(EXEEXT) unittest_context$(EXEEXT) \
-	unittest_heartbeatmap$(EXEEXT) unittest_formatter$(EXEEXT) \
-	unittest_libcephfs_config$(EXEEXT) unittest_lfnindex$(EXEEXT) \
-	unittest_librados_config$(EXEEXT) \
+	unittest_crypto_init$(EXEEXT) unittest_perf_counters$(EXEEXT) \
+	unittest_admin_socket$(EXEEXT) unittest_ceph_crypto$(EXEEXT) \
+	unittest_utf8$(EXEEXT) unittest_mime$(EXEEXT) \
+	unittest_escape$(EXEEXT) unittest_chain_xattr$(EXEEXT) \
+	unittest_flatindex$(EXEEXT) unittest_strtol$(EXEEXT) \
+	unittest_confutils$(EXEEXT) unittest_config$(EXEEXT) \
+	unittest_context$(EXEEXT) unittest_heartbeatmap$(EXEEXT) \
+	unittest_formatter$(EXEEXT) unittest_libcephfs_config$(EXEEXT) \
+	unittest_lfnindex$(EXEEXT) unittest_librados_config$(EXEEXT) \
 	unittest_daemon_config$(EXEEXT) unittest_osd_osdcap$(EXEEXT) \
 	unittest_mon_moncap$(EXEEXT) unittest_mon_pgmap$(EXEEXT) \
 	unittest_ipaddr$(EXEEXT) unittest_texttable$(EXEEXT) \
@@ -127,24 +127,23 @@ check_PROGRAMS = unittest_erasure_code_plugin$(EXEEXT) \
 @WITH_LIBZFS_TRUE at am__append_17 = libos_zfs.a
 @WITH_LIBZFS_TRUE at am__append_18 = os/ZFS.h
 @LINUX_TRUE at am__append_19 = -export-symbols-regex '.*__erasure_code_.*'
- at LINUX_TRUE@am__append_20 = -ldl
- at WITH_FUSE_TRUE@am__append_21 = libclient_fuse.la
- at WITH_FUSE_TRUE@am__append_22 = client/fuse_ll.h
- at WITH_TCMALLOC_TRUE@am__append_23 = perfglue/heap_profiler.cc
- at WITH_TCMALLOC_TRUE@am__append_24 = -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free
- at WITH_TCMALLOC_TRUE@am__append_25 = -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free
- at WITH_TCMALLOC_FALSE@am__append_26 = perfglue/disabled_heap_profiler.cc
- at WITH_PROFILER_TRUE@am__append_27 = perfglue/cpu_profiler.cc
- at WITH_PROFILER_FALSE@am__append_28 = perfglue/disabled_stubs.cc
- at LINUX_TRUE@am__append_29 = \
- at LINUX_TRUE@	common/secret.c
-
- at WITH_GOOD_YASM_ELF64_TRUE@am__append_30 = common/crc32c_intel_fast_asm.S common/crc32c_intel_fast_zero_asm.S
- at LINUX_TRUE@am__append_31 = -lrt
- at LINUX_TRUE@am__append_32 = -export-symbols-regex '^rados_.*'
- at LINUX_TRUE@am__append_33 = -export-symbols-regex '^rbd_.*'
- at WITH_RADOSGW_TRUE@am__append_34 = librgw.la
- at WITH_RADOSGW_TRUE@am__append_35 = \
+ at LINUX_TRUE@am__append_20 = -export-symbols-regex '.*__erasure_code_.*'
+ at LINUX_TRUE@am__append_21 = -export-symbols-regex '.*__erasure_code_.*'
+ at LINUX_TRUE@am__append_22 = -export-symbols-regex '.*__erasure_code_.*'
+ at WITH_FUSE_TRUE@am__append_23 = libclient_fuse.la
+ at WITH_FUSE_TRUE@am__append_24 = client/fuse_ll.h
+ at WITH_TCMALLOC_TRUE@am__append_25 = perfglue/heap_profiler.cc
+ at WITH_TCMALLOC_TRUE@am__append_26 = -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free
+ at WITH_TCMALLOC_TRUE@am__append_27 = -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free
+ at WITH_TCMALLOC_FALSE@am__append_28 = perfglue/disabled_heap_profiler.cc
+ at WITH_PROFILER_TRUE@am__append_29 = perfglue/cpu_profiler.cc
+ at WITH_PROFILER_FALSE@am__append_30 = perfglue/disabled_stubs.cc
+ at WITH_GOOD_YASM_ELF64_TRUE@am__append_31 = common/crc32c_intel_fast_asm.S common/crc32c_intel_fast_zero_asm.S
+ at LINUX_TRUE@am__append_32 = -lrt
+ at LINUX_TRUE@am__append_33 = -export-symbols-regex '^rados_.*'
+ at LINUX_TRUE@am__append_34 = -export-symbols-regex '^rbd_.*'
+ at WITH_RADOSGW_TRUE@am__append_35 = librgw.la
+ at WITH_RADOSGW_TRUE@am__append_36 = \
 @WITH_RADOSGW_TRUE@	$(LIBRADOS) \
 @WITH_RADOSGW_TRUE@	libcls_rgw_client.la \
 @WITH_RADOSGW_TRUE@	libcls_log_client.a \
@@ -160,55 +159,55 @@ check_PROGRAMS = unittest_erasure_code_plugin$(EXEEXT) \
 @WITH_RADOSGW_TRUE@	-lfcgi \
 @WITH_RADOSGW_TRUE@	-ldl
 
- at WITH_RADOSGW_TRUE@am__append_36 = radosgw radosgw-admin
- at WITH_RADOSGW_TRUE@am__append_37 = ceph_rgw_multiparser \
+ at WITH_RADOSGW_TRUE@am__append_37 = radosgw radosgw-admin
+ at WITH_RADOSGW_TRUE@am__append_38 = ceph_rgw_multiparser \
 @WITH_RADOSGW_TRUE@	ceph_rgw_jsonparser
 
 # inject rgw stuff in the decoder testcase
- at WITH_RADOSGW_TRUE@am__append_38 = \
+ at WITH_RADOSGW_TRUE@am__append_39 = \
 @WITH_RADOSGW_TRUE@	rgw/rgw_dencoder.cc \
 @WITH_RADOSGW_TRUE@	rgw/rgw_acl.cc \
 @WITH_RADOSGW_TRUE@	rgw/rgw_common.cc \
 @WITH_RADOSGW_TRUE@	rgw/rgw_env.cc \
 @WITH_RADOSGW_TRUE@	rgw/rgw_json_enc.cc
 
- at LINUX_TRUE@am__append_39 = libcls_kvs.la
- at LINUX_TRUE@am__append_40 = -ldl
+ at LINUX_TRUE@am__append_40 = libcls_kvs.la
 @LINUX_TRUE at am__append_41 = -ldl
 @LINUX_TRUE at am__append_42 = -ldl
 @LINUX_TRUE at am__append_43 = -ldl
 @LINUX_TRUE at am__append_44 = -ldl
- at WITH_RADOSGW_TRUE@am__append_45 = $(LIBRGW) $(LIBRGW_DEPS)
- at COMPILER_HAS_VTA_TRUE@am__append_46 = -fno-var-tracking-assignments
+ at LINUX_TRUE@am__append_45 = -ldl
+ at WITH_RADOSGW_TRUE@am__append_46 = $(LIBRGW) $(LIBRGW_DEPS)
 @COMPILER_HAS_VTA_TRUE at am__append_47 = -fno-var-tracking-assignments
- at WITH_BUILD_TESTS_TRUE@am__append_48 = test_build_libcommon \
+ at COMPILER_HAS_VTA_TRUE@am__append_48 = -fno-var-tracking-assignments
+ at WITH_BUILD_TESTS_TRUE@am__append_49 = test_build_libcommon \
 @WITH_BUILD_TESTS_TRUE@	test_build_librados test_build_librgw \
 @WITH_BUILD_TESTS_TRUE@	test_build_libcephfs
- at LINUX_TRUE@am__append_49 = ceph_kvstorebench \
+ at LINUX_TRUE@am__append_50 = ceph_kvstorebench \
 @LINUX_TRUE@	ceph_test_rados_list_parallel \
 @LINUX_TRUE@	ceph_test_rados_open_pools_parallel \
 @LINUX_TRUE@	ceph_test_rados_delete_pools_parallel \
 @LINUX_TRUE@	ceph_test_rados_watch_notify
- at LINUX_TRUE@am__append_50 = libsystest.la
- at LINUX_TRUE@am__append_51 = -ldl
- at WITH_RADOSGW_TRUE@am__append_52 = ceph_test_cors \
+ at LINUX_TRUE@am__append_51 = libsystest.la
+ at LINUX_TRUE@am__append_52 = -ldl
+ at WITH_RADOSGW_TRUE@am__append_53 = ceph_test_cors \
 @WITH_RADOSGW_TRUE@	ceph_test_rgw_manifest \
 @WITH_RADOSGW_TRUE@	ceph_test_cls_rgw_meta \
 @WITH_RADOSGW_TRUE@	ceph_test_cls_rgw_log \
 @WITH_RADOSGW_TRUE@	ceph_test_cls_rgw_opstate
- at LINUX_TRUE@am__append_53 = ceph_test_librbd_fsx
- at WITH_RADOSGW_TRUE@am__append_54 = ceph_test_cls_rgw
- at LINUX_TRUE@am__append_55 = ceph_test_objectstore
- at LINUX_TRUE@am__append_56 = -ldl
+ at LINUX_TRUE@am__append_54 = ceph_test_librbd_fsx
+ at WITH_RADOSGW_TRUE@am__append_55 = ceph_test_cls_rgw
+ at LINUX_TRUE@am__append_56 = ceph_test_objectstore
 @LINUX_TRUE at am__append_57 = -ldl
- at WITH_REST_BENCH_TRUE@am__append_58 = rest-bench
- at WITH_REST_BENCH_TRUE@@WITH_SYSTEM_LIBS3_TRUE at am__append_59 = -ls3
- at WITH_REST_BENCH_TRUE@@WITH_SYSTEM_LIBS3_FALSE at am__append_60 = libs3/build/lib/libs3.a -lcurl -lxml2
- at WITH_REST_BENCH_TRUE@@WITH_SYSTEM_LIBS3_FALSE at am__append_61 = libs3
- at LINUX_TRUE@am__append_62 = mount.ceph
- at LINUX_TRUE@am__append_63 = rbd
- at WITH_FUSE_TRUE@am__append_64 = ceph-fuse rbd-fuse
- at ENABLE_CEPHFS_JAVA_TRUE@am__append_65 = libcephfs_jni.la
+ at LINUX_TRUE@am__append_58 = -ldl
+ at WITH_REST_BENCH_TRUE@am__append_59 = rest-bench
+ at WITH_REST_BENCH_TRUE@@WITH_SYSTEM_LIBS3_TRUE at am__append_60 = -ls3
+ at WITH_REST_BENCH_TRUE@@WITH_SYSTEM_LIBS3_FALSE at am__append_61 = libs3/build/lib/libs3.a -lcurl -lxml2
+ at WITH_REST_BENCH_TRUE@@WITH_SYSTEM_LIBS3_FALSE at am__append_62 = libs3
+ at LINUX_TRUE@am__append_63 = mount.ceph
+ at LINUX_TRUE@am__append_64 = rbd
+ at WITH_FUSE_TRUE@am__append_65 = ceph-fuse rbd-fuse
+ at ENABLE_CEPHFS_JAVA_TRUE@am__append_66 = libcephfs_jni.la
 subdir = src
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_classpath.m4 \
@@ -221,10 +220,10 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_classpath.m4 \
 	$(top_srcdir)/m4/ax_c_var_func.m4 \
 	$(top_srcdir)/m4/ax_check_compile_flag.m4 \
 	$(top_srcdir)/m4/ax_cxx_static_cast.m4 \
-	$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
-	$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
-	$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
-	$(top_srcdir)/configure.ac
+	$(top_srcdir)/m4/ax_intel.m4 $(top_srcdir)/m4/libtool.m4 \
+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+	$(top_srcdir)/m4/pkg.m4 $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
@@ -337,8 +336,7 @@ am_libauth_la_OBJECTS = auth/AuthAuthorizeHandler.lo \
 libauth_la_OBJECTS = $(am_libauth_la_OBJECTS)
 am__DEPENDENCIES_1 =
 am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
-	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
-	$(am__DEPENDENCIES_1)
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 libcephfs_la_DEPENDENCIES = $(LIBCLIENT) $(LIBCOMMON) \
 	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
 	$(am__DEPENDENCIES_2)
@@ -480,40 +478,10 @@ libcls_version_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
 	$(AM_CXXFLAGS) $(CXXFLAGS) $(libcls_version_la_LDFLAGS) \
 	$(LDFLAGS) -o $@
-am__DEPENDENCIES_3 = libcommon_crc.la $(LIBMSG) $(LIBAUTH) $(LIBCRUSH) \
-	$(LIBJSON_SPIRIT) $(LIBLOG) $(LIBARCH) $(am__DEPENDENCIES_1) \
+am__DEPENDENCIES_3 = libcommon_crc.la $(LIBERASURE_CODE) $(LIBMSG) \
+	$(LIBAUTH) $(LIBCRUSH) $(LIBJSON_SPIRIT) $(LIBLOG) $(LIBARCH) \
 	$(am__DEPENDENCIES_1)
 libcommon_la_DEPENDENCIES = $(am__DEPENDENCIES_3)
-am__libcommon_la_SOURCES_DIST = ceph_ver.c common/DecayCounter.cc \
-	common/LogClient.cc common/LogEntry.cc \
-	common/PrebufferedStreambuf.cc common/SloppyCRCMap.cc \
-	common/BackTrace.cc common/perf_counters.cc common/Mutex.cc \
-	common/OutputDataSocket.cc common/admin_socket.cc \
-	common/admin_socket_client.cc common/cmdparse.cc \
-	common/escape.c common/Clock.cc common/Throttle.cc \
-	common/Timer.cc common/Finisher.cc common/environment.cc \
-	common/assert.cc common/run_cmd.cc common/WorkQueue.cc \
-	common/ConfUtils.cc common/MemoryModel.cc common/armor.c \
-	common/fd.cc common/xattr.c common/safe_io.c \
-	common/snap_types.cc common/str_list.cc common/str_map.cc \
-	common/errno.cc common/RefCountedObj.cc common/blkdev.cc \
-	common/common_init.cc common/pipe.c common/ceph_argparse.cc \
-	common/ceph_context.cc common/buffer.cc \
-	common/code_environment.cc common/dout.cc common/histogram.cc \
-	common/signal.cc common/simple_spin.cc common/Thread.cc \
-	common/Formatter.cc common/HeartbeatMap.cc common/config.cc \
-	common/utf8.c common/mime.c common/strtol.cc common/page.cc \
-	common/lockdep.cc common/version.cc common/hex.cc \
-	common/entity_name.cc common/ceph_crypto.cc \
-	common/ceph_crypto_cms.cc common/ceph_json.cc common/ipaddr.cc \
-	common/pick_address.cc common/util.cc common/TextTable.cc \
-	common/ceph_fs.cc common/ceph_hash.cc common/ceph_strings.cc \
-	common/ceph_frag.cc common/addr_parsing.c common/hobject.cc \
-	common/bloom_filter.cc common/linux_version.c common/secret.c \
-	mon/MonCap.cc mon/MonClient.cc mon/MonMap.cc osd/OSDMap.cc \
-	osd/osd_types.cc osd/ECMsgTypes.cc osd/HitSet.cc mds/MDSMap.cc \
-	mds/inode_backtrace.cc mds/mdstypes.cc
- at LINUX_TRUE@am__objects_1 = common/secret.lo
 am_libcommon_la_OBJECTS = ceph_ver.lo common/DecayCounter.lo \
 	common/LogClient.lo common/LogEntry.lo \
 	common/PrebufferedStreambuf.lo common/SloppyCRCMap.lo \
@@ -539,22 +507,22 @@ am_libcommon_la_OBJECTS = ceph_ver.lo common/DecayCounter.lo \
 	common/pick_address.lo common/util.lo common/TextTable.lo \
 	common/ceph_fs.lo common/ceph_hash.lo common/ceph_strings.lo \
 	common/ceph_frag.lo common/addr_parsing.lo common/hobject.lo \
-	common/bloom_filter.lo common/linux_version.lo \
-	$(am__objects_1) mon/MonCap.lo mon/MonClient.lo mon/MonMap.lo \
-	osd/OSDMap.lo osd/osd_types.lo osd/ECMsgTypes.lo osd/HitSet.lo \
-	mds/MDSMap.lo mds/inode_backtrace.lo mds/mdstypes.lo
+	common/bloom_filter.lo common/linux_version.lo mon/MonCap.lo \
+	mon/MonClient.lo mon/MonMap.lo osd/OSDMap.lo osd/osd_types.lo \
+	osd/ECMsgTypes.lo osd/HitSet.lo mds/MDSMap.lo \
+	mds/inode_backtrace.lo mds/mdstypes.lo
 libcommon_la_OBJECTS = $(am_libcommon_la_OBJECTS)
 libcommon_crc_la_LIBADD =
 am__libcommon_crc_la_SOURCES_DIST = common/sctp_crc32.c \
 	common/crc32c.cc common/crc32c_intel_baseline.c \
 	common/crc32c_intel_fast.c common/crc32c_intel_fast_asm.S \
 	common/crc32c_intel_fast_zero_asm.S
- at WITH_GOOD_YASM_ELF64_TRUE@am__objects_2 = common/libcommon_crc_la-crc32c_intel_fast_asm.lo \
+ at WITH_GOOD_YASM_ELF64_TRUE@am__objects_1 = common/libcommon_crc_la-crc32c_intel_fast_asm.lo \
 @WITH_GOOD_YASM_ELF64_TRUE@	common/libcommon_crc_la-crc32c_intel_fast_zero_asm.lo
 am_libcommon_crc_la_OBJECTS = common/libcommon_crc_la-sctp_crc32.lo \
 	common/libcommon_crc_la-crc32c.lo \
 	common/libcommon_crc_la-crc32c_intel_baseline.lo \
-	common/libcommon_crc_la-crc32c_intel_fast.lo $(am__objects_2)
+	common/libcommon_crc_la-crc32c_intel_fast.lo $(am__objects_1)
 libcommon_crc_la_OBJECTS = $(am_libcommon_crc_la_OBJECTS)
 libcommon_crc_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
 	$(libcommon_crc_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \
@@ -602,18 +570,91 @@ libec_hangs_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
 	$(libec_hangs_la_LDFLAGS) $(LDFLAGS) -o $@
 libec_jerasure_la_DEPENDENCIES = $(LIBCRUSH) $(am__DEPENDENCIES_1) \
 	$(am__DEPENDENCIES_2)
-am_libec_jerasure_la_OBJECTS = erasure-code/jerasure/libec_jerasure_la-ErasureCodePluginJerasure.lo \
-	erasure-code/jerasure/libec_jerasure_la-ErasureCodeJerasure.lo \
-	erasure-code/jerasure/libec_jerasure_la-cauchy.lo \
-	erasure-code/jerasure/libec_jerasure_la-galois.lo \
-	erasure-code/jerasure/libec_jerasure_la-jerasure.lo \
-	erasure-code/jerasure/libec_jerasure_la-liberation.lo \
-	erasure-code/jerasure/libec_jerasure_la-reed_sol.lo
+am_libec_jerasure_la_OBJECTS = erasure-code/jerasure/libec_jerasure_la-ErasureCodePluginSelectJerasure.lo
 libec_jerasure_la_OBJECTS = $(am_libec_jerasure_la_OBJECTS)
 libec_jerasure_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
 	$(libec_jerasure_la_CXXFLAGS) $(CXXFLAGS) \
 	$(libec_jerasure_la_LDFLAGS) $(LDFLAGS) -o $@
+libec_jerasure_generic_la_DEPENDENCIES = $(LIBCRUSH) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
+am__objects_2 = erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-cauchy.lo \
+	erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-galois.lo \
+	erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-jerasure.lo \
+	erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-liberation.lo \
+	erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-reed_sol.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_wgen.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_method.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w16.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w32.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w64.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w128.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_general.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w4.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_rand.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w8.lo \
+	erasure-code/jerasure/libec_jerasure_generic_la-ErasureCodePluginJerasure.lo \
+	erasure-code/jerasure/libec_jerasure_generic_la-ErasureCodeJerasure.lo
+am_libec_jerasure_generic_la_OBJECTS = $(am__objects_2)
+libec_jerasure_generic_la_OBJECTS =  \
+	$(am_libec_jerasure_generic_la_OBJECTS)
+libec_jerasure_generic_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+	$(libec_jerasure_generic_la_CXXFLAGS) $(CXXFLAGS) \
+	$(libec_jerasure_generic_la_LDFLAGS) $(LDFLAGS) -o $@
+libec_jerasure_sse3_la_DEPENDENCIES = $(LIBCRUSH) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
+am__objects_3 = erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-cauchy.lo \
+	erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-galois.lo \
+	erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-jerasure.lo \
+	erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-liberation.lo \
+	erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-reed_sol.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_wgen.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_method.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w16.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w32.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w64.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w128.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_general.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w4.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_rand.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w8.lo \
+	erasure-code/jerasure/libec_jerasure_sse3_la-ErasureCodePluginJerasure.lo \
+	erasure-code/jerasure/libec_jerasure_sse3_la-ErasureCodeJerasure.lo
+am_libec_jerasure_sse3_la_OBJECTS = $(am__objects_3)
+libec_jerasure_sse3_la_OBJECTS = $(am_libec_jerasure_sse3_la_OBJECTS)
+libec_jerasure_sse3_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+	$(libec_jerasure_sse3_la_CXXFLAGS) $(CXXFLAGS) \
+	$(libec_jerasure_sse3_la_LDFLAGS) $(LDFLAGS) -o $@
+libec_jerasure_sse4_la_DEPENDENCIES = $(LIBCRUSH) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
+am__objects_4 = erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-cauchy.lo \
+	erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-galois.lo \
+	erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-jerasure.lo \
+	erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-liberation.lo \
+	erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-reed_sol.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_wgen.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_method.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w16.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w32.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w64.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w128.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_general.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w4.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_rand.lo \
+	erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w8.lo \
+	erasure-code/jerasure/libec_jerasure_sse4_la-ErasureCodePluginJerasure.lo \
+	erasure-code/jerasure/libec_jerasure_sse4_la-ErasureCodeJerasure.lo
+am_libec_jerasure_sse4_la_OBJECTS = $(am__objects_4)
+libec_jerasure_sse4_la_OBJECTS = $(am_libec_jerasure_sse4_la_OBJECTS)
+libec_jerasure_sse4_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+	$(libec_jerasure_sse4_la_CXXFLAGS) $(CXXFLAGS) \
+	$(libec_jerasure_sse4_la_LDFLAGS) $(LDFLAGS) -o $@
 libec_missing_entry_point_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
 	$(am__DEPENDENCIES_2)
 am_libec_missing_entry_point_la_OBJECTS = test/erasure-code/libec_missing_entry_point_la-ErasureCodePluginMissingEntryPoint.lo
@@ -623,11 +664,34 @@ libec_missing_entry_point_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
 	$(libec_missing_entry_point_la_CXXFLAGS) $(CXXFLAGS) \
 	$(libec_missing_entry_point_la_LDFLAGS) $(LDFLAGS) -o $@
- at WITH_LIBZFS_TRUE@am__DEPENDENCIES_4 = libos_zfs.a
-am__DEPENDENCIES_5 = libos.la $(am__DEPENDENCIES_1) \
-	$(am__DEPENDENCIES_4)
-liberasure_code_la_DEPENDENCIES = $(LIBOSDC) $(am__DEPENDENCIES_5) \
-	$(am__DEPENDENCIES_1)
+libec_test_jerasure_generic_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_2)
+am_libec_test_jerasure_generic_la_OBJECTS = test/erasure-code/libec_test_jerasure_generic_la-TestJerasurePluginGeneric.lo
+libec_test_jerasure_generic_la_OBJECTS =  \
+	$(am_libec_test_jerasure_generic_la_OBJECTS)
+libec_test_jerasure_generic_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+	$(libec_test_jerasure_generic_la_CXXFLAGS) $(CXXFLAGS) \
+	$(libec_test_jerasure_generic_la_LDFLAGS) $(LDFLAGS) -o $@
+libec_test_jerasure_sse3_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_2)
+am_libec_test_jerasure_sse3_la_OBJECTS = test/erasure-code/libec_test_jerasure_sse3_la-TestJerasurePluginSSE3.lo
+libec_test_jerasure_sse3_la_OBJECTS =  \
+	$(am_libec_test_jerasure_sse3_la_OBJECTS)
+libec_test_jerasure_sse3_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+	$(libec_test_jerasure_sse3_la_CXXFLAGS) $(CXXFLAGS) \
+	$(libec_test_jerasure_sse3_la_LDFLAGS) $(LDFLAGS) -o $@
+libec_test_jerasure_sse4_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_2)
+am_libec_test_jerasure_sse4_la_OBJECTS = test/erasure-code/libec_test_jerasure_sse4_la-TestJerasurePluginSSE4.lo
+libec_test_jerasure_sse4_la_OBJECTS =  \
+	$(am_libec_test_jerasure_sse4_la_OBJECTS)
+libec_test_jerasure_sse4_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+	$(libec_test_jerasure_sse4_la_CXXFLAGS) $(CXXFLAGS) \
+	$(libec_test_jerasure_sse4_la_LDFLAGS) $(LDFLAGS) -o $@
+liberasure_code_la_DEPENDENCIES =
 am_liberasure_code_la_OBJECTS = erasure-code/ErasureCodePlugin.lo
 liberasure_code_la_OBJECTS = $(am_liberasure_code_la_OBJECTS)
 libglobal_la_DEPENDENCIES = $(LIBCOMMON)
@@ -650,10 +714,13 @@ am_libmds_la_OBJECTS = mds/Anchor.lo mds/Capability.lo mds/Dumper.lo \
 	mds/CDir.lo mds/CInode.lo mds/LogEvent.lo mds/MDSTable.lo \
 	mds/InoTable.lo mds/MDSTableClient.lo mds/MDSTableServer.lo \
 	mds/AnchorServer.lo mds/AnchorClient.lo mds/SnapRealm.lo \
-	mds/SnapServer.lo mds/snap.lo mds/SessionMap.lo mds/MDLog.lo
+	mds/SnapServer.lo mds/snap.lo mds/SessionMap.lo mds/MDLog.lo \
+	mds/MDSUtility.lo
 libmds_la_OBJECTS = $(am_libmds_la_OBJECTS)
-libmon_la_DEPENDENCIES = $(LIBAUTH) $(LIBCOMMON) $(am__DEPENDENCIES_5) \
-	$(LIBERASURE_CODE)
+ at WITH_LIBZFS_TRUE@am__DEPENDENCIES_4 = libos_zfs.a
+am__DEPENDENCIES_5 = libos.la $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_4)
+libmon_la_DEPENDENCIES = $(LIBAUTH) $(LIBCOMMON) $(am__DEPENDENCIES_5)
 am_libmon_la_OBJECTS = mon/Monitor.lo mon/Paxos.lo mon/PaxosService.lo \
 	mon/OSDMonitor.lo mon/MDSMonitor.lo mon/MonmapMonitor.lo \
 	mon/PGMonitor.lo mon/PGMap.lo mon/LogMonitor.lo \
@@ -675,20 +742,19 @@ am__libos_la_SOURCES_DIST = os/chain_xattr.cc os/DBObjectMap.cc \
 	os/KeyValueStore.cc os/ObjectStore.cc os/WBThrottle.cc \
 	common/TrackedOp.cc os/BtrfsFileStoreBackend.cc \
 	os/XfsFileStoreBackend.cc os/ZFSFileStoreBackend.cc
- at LINUX_TRUE@am__objects_3 = os/BtrfsFileStoreBackend.lo
- at WITH_LIBXFS_TRUE@am__objects_4 = os/XfsFileStoreBackend.lo
- at WITH_LIBZFS_TRUE@am__objects_5 = os/ZFSFileStoreBackend.lo
+ at LINUX_TRUE@am__objects_5 = os/BtrfsFileStoreBackend.lo
+ at WITH_LIBXFS_TRUE@am__objects_6 = os/XfsFileStoreBackend.lo
+ at WITH_LIBZFS_TRUE@am__objects_7 = os/ZFSFileStoreBackend.lo
 am_libos_la_OBJECTS = os/chain_xattr.lo os/DBObjectMap.lo \
 	os/GenericObjectMap.lo os/FileJournal.lo os/FileStore.lo \
 	os/FlatIndex.lo os/GenericFileStoreBackend.lo os/HashIndex.lo \
 	os/IndexManager.lo os/JournalingObjectStore.lo \
 	os/LevelDBStore.lo os/LFNIndex.lo os/MemStore.lo \
 	os/KeyValueStore.lo os/ObjectStore.lo os/WBThrottle.lo \
-	common/TrackedOp.lo $(am__objects_3) $(am__objects_4) \
-	$(am__objects_5)
+	common/TrackedOp.lo $(am__objects_5) $(am__objects_6) \
+	$(am__objects_7)
 libos_la_OBJECTS = $(am_libos_la_OBJECTS)
-libosd_la_DEPENDENCIES = $(LIBOSDC) $(am__DEPENDENCIES_5) \
-	$(LIBERASURE_CODE)
+libosd_la_DEPENDENCIES = $(LIBOSDC) $(am__DEPENDENCIES_5)
 am_libosd_la_OBJECTS = osd/PG.lo osd/PGLog.lo osd/ReplicatedPG.lo \
 	osd/ReplicatedBackend.lo osd/ECBackend.lo osd/ECMsgTypes.lo \
 	osd/ECTransaction.lo osd/PGBackend.lo osd/Ager.lo \
@@ -705,13 +771,13 @@ libperfglue_la_DEPENDENCIES =
 am__libperfglue_la_SOURCES_DIST = perfglue/heap_profiler.cc \
 	perfglue/disabled_heap_profiler.cc perfglue/cpu_profiler.cc \
 	perfglue/disabled_stubs.cc
- at WITH_TCMALLOC_TRUE@am__objects_6 = perfglue/heap_profiler.lo
- at WITH_TCMALLOC_FALSE@am__objects_7 =  \
+ at WITH_TCMALLOC_TRUE@am__objects_8 = perfglue/heap_profiler.lo
+ at WITH_TCMALLOC_FALSE@am__objects_9 =  \
 @WITH_TCMALLOC_FALSE@	perfglue/disabled_heap_profiler.lo
- at WITH_PROFILER_TRUE@am__objects_8 = perfglue/cpu_profiler.lo
- at WITH_PROFILER_FALSE@am__objects_9 = perfglue/disabled_stubs.lo
-am_libperfglue_la_OBJECTS = $(am__objects_6) $(am__objects_7) \
-	$(am__objects_8) $(am__objects_9)
+ at WITH_PROFILER_TRUE@am__objects_10 = perfglue/cpu_profiler.lo
+ at WITH_PROFILER_FALSE@am__objects_11 = perfglue/disabled_stubs.lo
+am_libperfglue_la_OBJECTS = $(am__objects_8) $(am__objects_9) \
+	$(am__objects_10) $(am__objects_11)
 libperfglue_la_OBJECTS = $(am_libperfglue_la_OBJECTS)
 librados_la_DEPENDENCIES = $(LIBRADOS_DEPS) $(am__DEPENDENCIES_1) \
 	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
@@ -871,7 +937,7 @@ am__EXEEXT_8 = ceph_test_ioctls$(EXEEXT) $(am__EXEEXT_1) \
 	ceph-monstore-tool$(EXEEXT) ceph-kvstore-tool$(EXEEXT) \
 	ceph_scratchtool$(EXEEXT) ceph_scratchtoolpp$(EXEEXT) \
 	ceph_psim$(EXEEXT) ceph_dupstore$(EXEEXT) \
-	ceph_radosacl$(EXEEXT)
+	ceph_radosacl$(EXEEXT) ceph-client-debug$(EXEEXT)
 @WITH_DEBUG_TRUE at am__EXEEXT_9 = $(am__EXEEXT_8)
 @WITH_RADOSGW_TRUE at am__EXEEXT_10 = radosgw$(EXEEXT) \
 @WITH_RADOSGW_TRUE@	radosgw-admin$(EXEEXT)
@@ -884,22 +950,26 @@ PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) $(sbin_PROGRAMS) \
 am_ceph_authtool_OBJECTS = tools/ceph_authtool.$(OBJEXT)
 ceph_authtool_OBJECTS = $(am_ceph_authtool_OBJECTS)
 ceph_authtool_DEPENDENCIES = $(am__DEPENDENCIES_6) $(LIBCOMMON)
+am_ceph_client_debug_OBJECTS = tools/ceph-client-debug.$(OBJEXT)
+ceph_client_debug_OBJECTS = $(am_ceph_client_debug_OBJECTS)
+ceph_client_debug_DEPENDENCIES = $(LIBCEPHFS) $(am__DEPENDENCIES_6) \
+	$(LIBCOMMON)
 am_ceph_conf_OBJECTS = tools/ceph_conf.$(OBJEXT)
 ceph_conf_OBJECTS = $(am_ceph_conf_OBJECTS)
 ceph_conf_DEPENDENCIES = $(am__DEPENDENCIES_6) $(LIBCOMMON)
 am__ceph_dencoder_SOURCES_DIST = test/encoding/ceph_dencoder.cc \
 	rgw/rgw_dencoder.cc rgw/rgw_acl.cc rgw/rgw_common.cc \
 	rgw/rgw_env.cc rgw/rgw_json_enc.cc
- at WITH_RADOSGW_TRUE@am__objects_10 =  \
+ at WITH_RADOSGW_TRUE@am__objects_12 =  \
 @WITH_RADOSGW_TRUE@	rgw/ceph_dencoder-rgw_dencoder.$(OBJEXT) \
 @WITH_RADOSGW_TRUE@	rgw/ceph_dencoder-rgw_acl.$(OBJEXT) \
 @WITH_RADOSGW_TRUE@	rgw/ceph_dencoder-rgw_common.$(OBJEXT) \
 @WITH_RADOSGW_TRUE@	rgw/ceph_dencoder-rgw_env.$(OBJEXT) \
 @WITH_RADOSGW_TRUE@	rgw/ceph_dencoder-rgw_json_enc.$(OBJEXT)
-am__objects_11 = $(am__objects_10)
+am__objects_13 = $(am__objects_12)
 am_ceph_dencoder_OBJECTS =  \
 	test/encoding/ceph_dencoder-ceph_dencoder.$(OBJEXT) \
-	$(am__objects_11)
+	$(am__objects_13)
 ceph_dencoder_OBJECTS = $(am_ceph_dencoder_OBJECTS)
 am__DEPENDENCIES_7 = libperfglue.la $(am__DEPENDENCIES_1)
 am__DEPENDENCIES_8 = libosd.la $(LIBOSDC) $(am__DEPENDENCIES_5) \
@@ -930,7 +1000,7 @@ ceph_fuse_OBJECTS = $(am_ceph_fuse_OBJECTS)
 @WITH_FUSE_TRUE at ceph_fuse_DEPENDENCIES = $(LIBCLIENT_FUSE) \
 @WITH_FUSE_TRUE@	$(am__DEPENDENCIES_6)
 am_ceph_kvstore_tool_OBJECTS =  \
-	tools/ceph_kvstore_tool-ceph-kvstore-tool.$(OBJEXT)
+	tools/ceph_kvstore_tool-ceph_kvstore_tool.$(OBJEXT)
 ceph_kvstore_tool_OBJECTS = $(am_ceph_kvstore_tool_OBJECTS)
 ceph_kvstore_tool_DEPENDENCIES = $(am__DEPENDENCIES_5) \
 	$(am__DEPENDENCIES_6)
@@ -946,7 +1016,7 @@ am_ceph_mon_OBJECTS = ceph_mon.$(OBJEXT)
 ceph_mon_OBJECTS = $(am_ceph_mon_OBJECTS)
 ceph_mon_DEPENDENCIES = $(am__DEPENDENCIES_10) $(am__DEPENDENCIES_5) \
 	$(am__DEPENDENCIES_6) $(LIBCOMMON)
-am_ceph_monstore_tool_OBJECTS = tools/ceph-monstore-tool.$(OBJEXT)
+am_ceph_monstore_tool_OBJECTS = tools/ceph_monstore_tool.$(OBJEXT)
 ceph_monstore_tool_OBJECTS = $(am_ceph_monstore_tool_OBJECTS)
 ceph_monstore_tool_DEPENDENCIES = $(am__DEPENDENCIES_5) \
 	$(am__DEPENDENCIES_6) $(am__DEPENDENCIES_1)
@@ -954,7 +1024,7 @@ am_ceph_osd_OBJECTS = ceph_osd.$(OBJEXT)
 ceph_osd_OBJECTS = $(am_ceph_osd_OBJECTS)
 ceph_osd_DEPENDENCIES = $(am__DEPENDENCIES_8) $(am__DEPENDENCIES_6) \
 	$(LIBCOMMON)
-am_ceph_osdomap_tool_OBJECTS = tools/ceph-osdomap-tool.$(OBJEXT)
+am_ceph_osdomap_tool_OBJECTS = tools/ceph_osdomap_tool.$(OBJEXT)
 ceph_osdomap_tool_OBJECTS = $(am_ceph_osdomap_tool_OBJECTS)
 ceph_osdomap_tool_DEPENDENCIES = $(am__DEPENDENCIES_5) \
 	$(am__DEPENDENCIES_6) $(am__DEPENDENCIES_1)
@@ -982,12 +1052,12 @@ ceph_erasure_code_benchmark_OBJECTS =  \
 ceph_erasure_code_benchmark_DEPENDENCIES = $(am__DEPENDENCIES_8) \
 	$(LIBCOMMON) $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_6) \
 	$(am__DEPENDENCIES_1)
-am_ceph_filestore_dump_OBJECTS = tools/ceph-filestore-dump.$(OBJEXT)
+am_ceph_filestore_dump_OBJECTS = tools/ceph_filestore_dump.$(OBJEXT)
 ceph_filestore_dump_OBJECTS = $(am_ceph_filestore_dump_OBJECTS)
 ceph_filestore_dump_DEPENDENCIES = $(am__DEPENDENCIES_8) \
 	$(am__DEPENDENCIES_5) $(am__DEPENDENCIES_6) \
 	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
-am_ceph_filestore_tool_OBJECTS = tools/ceph-filestore-tool.$(OBJEXT)
+am_ceph_filestore_tool_OBJECTS = tools/ceph_filestore_tool.$(OBJEXT)
 ceph_filestore_tool_OBJECTS = $(am_ceph_filestore_tool_OBJECTS)
 ceph_filestore_tool_DEPENDENCIES = $(am__DEPENDENCIES_8) \
 	$(am__DEPENDENCIES_5) $(am__DEPENDENCIES_6) \
@@ -1653,9 +1723,10 @@ librados_config_DEPENDENCIES = $(LIBRADOS) $(am__DEPENDENCIES_6)
 am_monmaptool_OBJECTS = tools/monmaptool.$(OBJEXT)
 monmaptool_OBJECTS = $(am_monmaptool_OBJECTS)
 monmaptool_DEPENDENCIES = $(am__DEPENDENCIES_6) $(LIBCOMMON)
-am_mount_ceph_OBJECTS = mount/mount.ceph.$(OBJEXT)
+am_mount_ceph_OBJECTS = mount/mount.ceph.$(OBJEXT) \
+	common/secret.$(OBJEXT)
 mount_ceph_OBJECTS = $(am_mount_ceph_OBJECTS)
-mount_ceph_DEPENDENCIES = $(LIBCOMMON)
+mount_ceph_DEPENDENCIES = $(LIBCOMMON) $(am__DEPENDENCIES_1)
 am_osdmaptool_OBJECTS = tools/osdmaptool.$(OBJEXT)
 osdmaptool_OBJECTS = $(am_osdmaptool_OBJECTS)
 osdmaptool_DEPENDENCIES = $(am__DEPENDENCIES_6)
@@ -1705,9 +1776,10 @@ radosgw_admin_OBJECTS = $(am_radosgw_admin_OBJECTS)
 @WITH_RADOSGW_TRUE at radosgw_admin_DEPENDENCIES = $(LIBRGW) \
 @WITH_RADOSGW_TRUE@	$(am__DEPENDENCIES_12) \
 @WITH_RADOSGW_TRUE@	$(am__DEPENDENCIES_6)
-am_rbd_OBJECTS = rbd.$(OBJEXT)
+am_rbd_OBJECTS = rbd.$(OBJEXT) common/secret.$(OBJEXT)
 rbd_OBJECTS = $(am_rbd_OBJECTS)
-rbd_DEPENDENCIES = $(LIBRBD) $(LIBRADOS) $(am__DEPENDENCIES_6)
+rbd_DEPENDENCIES = $(LIBRBD) $(LIBRADOS) $(am__DEPENDENCIES_6) \
+	$(am__DEPENDENCIES_1)
 am__rbd_fuse_SOURCES_DIST = rbd_fuse/rbd-fuse.c
 @WITH_FUSE_TRUE at am_rbd_fuse_OBJECTS = rbd_fuse/rbd-fuse.$(OBJEXT)
 rbd_fuse_OBJECTS = $(am_rbd_fuse_OBJECTS)
@@ -1729,13 +1801,13 @@ rest_bench_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
 am__test_build_libcephfs_SOURCES_DIST = test/buildtest_skeleton.cc \
 	osdc/Objecter.cc osdc/ObjectCacher.cc osdc/Filer.cc \
 	osdc/Striper.cc osdc/Journaler.cc
-am__objects_12 = osdc/test_build_libcephfs-Objecter.$(OBJEXT) \
+am__objects_14 = osdc/test_build_libcephfs-Objecter.$(OBJEXT) \
 	osdc/test_build_libcephfs-ObjectCacher.$(OBJEXT) \
 	osdc/test_build_libcephfs-Filer.$(OBJEXT) \
 	osdc/test_build_libcephfs-Striper.$(OBJEXT) \
 	osdc/test_build_libcephfs-Journaler.$(OBJEXT)
 @WITH_BUILD_TESTS_TRUE at am_test_build_libcephfs_OBJECTS = test/test_build_libcephfs-buildtest_skeleton.$(OBJEXT) \
- at WITH_BUILD_TESTS_TRUE@	$(am__objects_12)
+ at WITH_BUILD_TESTS_TRUE@	$(am__objects_14)
 test_build_libcephfs_OBJECTS = $(am_test_build_libcephfs_OBJECTS)
 @WITH_BUILD_TESTS_TRUE at test_build_libcephfs_DEPENDENCIES =  \
 @WITH_BUILD_TESTS_TRUE@	$(LIBCEPHFS) $(am__DEPENDENCIES_1) \
@@ -1771,13 +1843,11 @@ am__test_build_libcommon_SOURCES_DIST = test/buildtest_skeleton.cc \
 	common/pick_address.cc common/util.cc common/TextTable.cc \
 	common/ceph_fs.cc common/ceph_hash.cc common/ceph_strings.cc \
 	common/ceph_frag.cc common/addr_parsing.c common/hobject.cc \
-	common/bloom_filter.cc common/linux_version.c common/secret.c \
-	mon/MonCap.cc mon/MonClient.cc mon/MonMap.cc osd/OSDMap.cc \
-	osd/osd_types.cc osd/ECMsgTypes.cc osd/HitSet.cc mds/MDSMap.cc \
+	common/bloom_filter.cc common/linux_version.c mon/MonCap.cc \
+	mon/MonClient.cc mon/MonMap.cc osd/OSDMap.cc osd/osd_types.cc \
+	osd/ECMsgTypes.cc osd/HitSet.cc mds/MDSMap.cc \
 	mds/inode_backtrace.cc mds/mdstypes.cc
- at LINUX_TRUE@am__objects_13 =  \
- at LINUX_TRUE@	common/test_build_libcommon-secret.$(OBJEXT)
-am__objects_14 = test_build_libcommon-ceph_ver.$(OBJEXT) \
+am__objects_15 = test_build_libcommon-ceph_ver.$(OBJEXT) \
 	common/test_build_libcommon-DecayCounter.$(OBJEXT) \
 	common/test_build_libcommon-LogClient.$(OBJEXT) \
 	common/test_build_libcommon-LogEntry.$(OBJEXT) \
@@ -1848,7 +1918,7 @@ am__objects_14 = test_build_libcommon-ceph_ver.$(OBJEXT) \
 	common/test_build_libcommon-hobject.$(OBJEXT) \
 	common/test_build_libcommon-bloom_filter.$(OBJEXT) \
 	common/test_build_libcommon-linux_version.$(OBJEXT) \
-	$(am__objects_13) mon/test_build_libcommon-MonCap.$(OBJEXT) \
+	mon/test_build_libcommon-MonCap.$(OBJEXT) \
 	mon/test_build_libcommon-MonClient.$(OBJEXT) \
 	mon/test_build_libcommon-MonMap.$(OBJEXT) \
 	osd/test_build_libcommon-OSDMap.$(OBJEXT) \
@@ -1859,7 +1929,7 @@ am__objects_14 = test_build_libcommon-ceph_ver.$(OBJEXT) \
 	mds/test_build_libcommon-inode_backtrace.$(OBJEXT) \
 	mds/test_build_libcommon-mdstypes.$(OBJEXT)
 @WITH_BUILD_TESTS_TRUE at am_test_build_libcommon_OBJECTS = test/test_build_libcommon-buildtest_skeleton.$(OBJEXT) \
- at WITH_BUILD_TESTS_TRUE@	$(am__objects_14)
+ at WITH_BUILD_TESTS_TRUE@	$(am__objects_15)
 test_build_libcommon_OBJECTS = $(am_test_build_libcommon_OBJECTS)
 @WITH_BUILD_TESTS_TRUE at test_build_libcommon_DEPENDENCIES =  \
 @WITH_BUILD_TESTS_TRUE@	$(am__DEPENDENCIES_3) \
@@ -1873,12 +1943,12 @@ test_build_libcommon_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
 am__test_build_librados_SOURCES_DIST = test/buildtest_skeleton.cc \
 	librados/librados.cc librados/RadosClient.cc \
 	librados/IoCtxImpl.cc librados/snap_set_diff.cc
-am__objects_15 = librados/test_build_librados-librados.$(OBJEXT) \
+am__objects_16 = librados/test_build_librados-librados.$(OBJEXT) \
 	librados/test_build_librados-RadosClient.$(OBJEXT) \
 	librados/test_build_librados-IoCtxImpl.$(OBJEXT) \
 	librados/test_build_librados-snap_set_diff.$(OBJEXT)
 @WITH_BUILD_TESTS_TRUE at am_test_build_librados_OBJECTS = test/test_build_librados-buildtest_skeleton.$(OBJEXT) \
- at WITH_BUILD_TESTS_TRUE@	$(am__objects_15)
+ at WITH_BUILD_TESTS_TRUE@	$(am__objects_16)
 test_build_librados_OBJECTS = $(am_test_build_librados_OBJECTS)
 @WITH_BUILD_TESTS_TRUE at test_build_librados_DEPENDENCIES =  \
 @WITH_BUILD_TESTS_TRUE@	$(LIBRADOS_DEPS) $(am__DEPENDENCIES_1) \
@@ -1900,7 +1970,7 @@ am__test_build_librgw_SOURCES_DIST = test/buildtest_skeleton.cc \
 	rgw/rgw_multi_del.cc rgw/rgw_env.cc rgw/rgw_cors.cc \
 	rgw/rgw_cors_s3.cc rgw/rgw_auth_s3.cc rgw/rgw_metadata.cc \
 	rgw/rgw_replica_log.cc rgw/rgw_keystone.cc rgw/rgw_quota.cc
- at WITH_RADOSGW_TRUE@am__objects_16 =  \
+ at WITH_RADOSGW_TRUE@am__objects_17 =  \
 @WITH_RADOSGW_TRUE@	rgw/test_build_librgw-librgw.$(OBJEXT) \
 @WITH_RADOSGW_TRUE@	rgw/test_build_librgw-rgw_acl.$(OBJEXT) \
 @WITH_RADOSGW_TRUE@	rgw/test_build_librgw-rgw_acl_s3.$(OBJEXT) \
@@ -1935,7 +2005,7 @@ am__test_build_librgw_SOURCES_DIST = test/buildtest_skeleton.cc \
 @WITH_RADOSGW_TRUE@	rgw/test_build_librgw-rgw_keystone.$(OBJEXT) \
 @WITH_RADOSGW_TRUE@	rgw/test_build_librgw-rgw_quota.$(OBJEXT)
 @WITH_BUILD_TESTS_TRUE at am_test_build_librgw_OBJECTS = test/test_build_librgw-buildtest_skeleton.$(OBJEXT) \
- at WITH_BUILD_TESTS_TRUE@	$(am__objects_16)
+ at WITH_BUILD_TESTS_TRUE@	$(am__objects_17)
 test_build_librgw_OBJECTS = $(am_test_build_librgw_OBJECTS)
 @WITH_BUILD_TESTS_TRUE at test_build_librgw_DEPENDENCIES =  \
 @WITH_BUILD_TESTS_TRUE@	$(am__DEPENDENCIES_12) \
@@ -2097,6 +2167,15 @@ unittest_crypto_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
 	$(unittest_crypto_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
 	$(LDFLAGS) -o $@
+am_unittest_crypto_init_OBJECTS =  \
+	test/unittest_crypto_init-crypto_init.$(OBJEXT)
+unittest_crypto_init_OBJECTS = $(am_unittest_crypto_init_OBJECTS)
+unittest_crypto_init_DEPENDENCIES = $(am__DEPENDENCIES_14) \
+	$(am__DEPENDENCIES_6)
+unittest_crypto_init_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+	$(unittest_crypto_init_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
 am_unittest_daemon_config_OBJECTS =  \
 	test/unittest_daemon_config-daemon_config.$(OBJEXT)
 unittest_daemon_config_OBJECTS = $(am_unittest_daemon_config_OBJECTS)
@@ -2133,15 +2212,26 @@ unittest_erasure_code_example_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
 	$(unittest_erasure_code_example_CXXFLAGS) $(CXXFLAGS) \
 	$(AM_LDFLAGS) $(LDFLAGS) -o $@
-am__objects_17 = erasure-code/jerasure/unittest_erasure_code_jerasure-ErasureCodePluginJerasure.$(OBJEXT) \
-	erasure-code/jerasure/unittest_erasure_code_jerasure-ErasureCodeJerasure.$(OBJEXT) \
-	erasure-code/jerasure/cauchy.$(OBJEXT) \
-	erasure-code/jerasure/galois.$(OBJEXT) \
-	erasure-code/jerasure/jerasure.$(OBJEXT) \
-	erasure-code/jerasure/liberation.$(OBJEXT) \
-	erasure-code/jerasure/reed_sol.$(OBJEXT)
+am__objects_18 = erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-cauchy.$(OBJEXT) \
+	erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-galois.$(OBJEXT) \
+	erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-jerasure.$(OBJEXT) \
+	erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-liberation.$(OBJEXT) \
+	erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-reed_sol.$(OBJEXT) \
+	erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_wgen.$(OBJEXT) \
+	erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_method.$(OBJEXT) \
+	erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w16.$(OBJEXT) \
+	erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf.$(OBJEXT) \
+	erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w32.$(OBJEXT) \
+	erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w64.$(OBJEXT) \
+	erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w128.$(OBJEXT) \
+	erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_general.$(OBJEXT) \
+	erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w4.$(OBJEXT) \
+	erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_rand.$(OBJEXT) \
+	erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w8.$(OBJEXT) \
+	erasure-code/jerasure/unittest_erasure_code_jerasure-ErasureCodePluginJerasure.$(OBJEXT) \
+	erasure-code/jerasure/unittest_erasure_code_jerasure-ErasureCodeJerasure.$(OBJEXT)
 am_unittest_erasure_code_jerasure_OBJECTS = test/erasure-code/unittest_erasure_code_jerasure-TestErasureCodeJerasure.$(OBJEXT) \
-	$(am__objects_17)
+	$(am__objects_18)
 unittest_erasure_code_jerasure_OBJECTS =  \
 	$(am_unittest_erasure_code_jerasure_OBJECTS)
 unittest_erasure_code_jerasure_DEPENDENCIES = $(am__DEPENDENCIES_8) \
@@ -2559,7 +2649,13 @@ SOURCES = $(libcls_log_client_a_SOURCES) \
 	$(libec_fail_to_initialize_la_SOURCES) \
 	$(libec_fail_to_register_la_SOURCES) $(libec_hangs_la_SOURCES) \
 	$(libec_jerasure_la_SOURCES) \
+	$(libec_jerasure_generic_la_SOURCES) \
+	$(libec_jerasure_sse3_la_SOURCES) \
+	$(libec_jerasure_sse4_la_SOURCES) \
 	$(libec_missing_entry_point_la_SOURCES) \
+	$(libec_test_jerasure_generic_la_SOURCES) \
+	$(libec_test_jerasure_sse3_la_SOURCES) \
+	$(libec_test_jerasure_sse4_la_SOURCES) \
 	$(liberasure_code_la_SOURCES) $(libglobal_la_SOURCES) \
 	$(libjson_spirit_la_SOURCES) $(liblog_la_SOURCES) \
 	$(libmds_la_SOURCES) $(libmon_la_SOURCES) $(libmsg_la_SOURCES) \
@@ -2567,13 +2663,14 @@ SOURCES = $(libcls_log_client_a_SOURCES) \
 	$(libperfglue_la_SOURCES) $(librados_la_SOURCES) \
 	$(libradostest_la_SOURCES) $(librbd_la_SOURCES) \
 	$(librgw_la_SOURCES) $(libsystest_la_SOURCES) \
-	$(ceph_authtool_SOURCES) $(ceph_conf_SOURCES) \
-	$(ceph_dencoder_SOURCES) $(ceph_fuse_SOURCES) \
-	$(ceph_kvstore_tool_SOURCES) $(ceph_mds_SOURCES) \
-	$(ceph_mon_SOURCES) $(ceph_monstore_tool_SOURCES) \
-	$(ceph_osd_SOURCES) $(ceph_osdomap_tool_SOURCES) \
-	$(ceph_syn_SOURCES) $(ceph_bench_log_SOURCES) \
-	$(ceph_dupstore_SOURCES) $(ceph_erasure_code_SOURCES) \
+	$(ceph_authtool_SOURCES) $(ceph_client_debug_SOURCES) \
+	$(ceph_conf_SOURCES) $(ceph_dencoder_SOURCES) \
+	$(ceph_fuse_SOURCES) $(ceph_kvstore_tool_SOURCES) \
+	$(ceph_mds_SOURCES) $(ceph_mon_SOURCES) \
+	$(ceph_monstore_tool_SOURCES) $(ceph_osd_SOURCES) \
+	$(ceph_osdomap_tool_SOURCES) $(ceph_syn_SOURCES) \
+	$(ceph_bench_log_SOURCES) $(ceph_dupstore_SOURCES) \
+	$(ceph_erasure_code_SOURCES) \
 	$(ceph_erasure_code_benchmark_SOURCES) \
 	$(ceph_filestore_dump_SOURCES) $(ceph_filestore_tool_SOURCES) \
 	$(ceph_kvstorebench_SOURCES) \
@@ -2652,6 +2749,7 @@ SOURCES = $(libcls_log_client_a_SOURCES) \
 	$(unittest_confutils_SOURCES) $(unittest_context_SOURCES) \
 	$(unittest_crc32c_SOURCES) $(unittest_crush_indep_SOURCES) \
 	$(unittest_crush_wrapper_SOURCES) $(unittest_crypto_SOURCES) \
+	$(unittest_crypto_init_SOURCES) \
 	$(unittest_daemon_config_SOURCES) \
 	$(unittest_ecbackend_SOURCES) $(unittest_encoding_SOURCES) \
 	$(unittest_erasure_code_example_SOURCES) \
@@ -2698,13 +2796,18 @@ DIST_SOURCES = $(libcls_log_client_a_SOURCES) \
 	$(libcls_replica_log_la_SOURCES) $(libcls_rgw_la_SOURCES) \
 	$(libcls_rgw_client_la_SOURCES) $(libcls_statelog_la_SOURCES) \
 	$(libcls_user_la_SOURCES) $(libcls_version_la_SOURCES) \
-	$(am__libcommon_la_SOURCES_DIST) \
-	$(am__libcommon_crc_la_SOURCES_DIST) $(libcrush_la_SOURCES) \
-	$(libec_example_la_SOURCES) \
+	$(libcommon_la_SOURCES) $(am__libcommon_crc_la_SOURCES_DIST) \
+	$(libcrush_la_SOURCES) $(libec_example_la_SOURCES) \
 	$(libec_fail_to_initialize_la_SOURCES) \
 	$(libec_fail_to_register_la_SOURCES) $(libec_hangs_la_SOURCES) \
 	$(libec_jerasure_la_SOURCES) \
+	$(libec_jerasure_generic_la_SOURCES) \
+	$(libec_jerasure_sse3_la_SOURCES) \
+	$(libec_jerasure_sse4_la_SOURCES) \
 	$(libec_missing_entry_point_la_SOURCES) \
+	$(libec_test_jerasure_generic_la_SOURCES) \
+	$(libec_test_jerasure_sse3_la_SOURCES) \
+	$(libec_test_jerasure_sse4_la_SOURCES) \
 	$(liberasure_code_la_SOURCES) $(libglobal_la_SOURCES) \
 	$(libjson_spirit_la_SOURCES) $(liblog_la_SOURCES) \
 	$(libmds_la_SOURCES) $(libmon_la_SOURCES) $(libmsg_la_SOURCES) \
@@ -2713,7 +2816,8 @@ DIST_SOURCES = $(libcls_log_client_a_SOURCES) \
 	$(librados_la_SOURCES) $(libradostest_la_SOURCES) \
 	$(librbd_la_SOURCES) $(am__librgw_la_SOURCES_DIST) \
 	$(am__libsystest_la_SOURCES_DIST) $(ceph_authtool_SOURCES) \
-	$(ceph_conf_SOURCES) $(am__ceph_dencoder_SOURCES_DIST) \
+	$(ceph_client_debug_SOURCES) $(ceph_conf_SOURCES) \
+	$(am__ceph_dencoder_SOURCES_DIST) \
 	$(am__ceph_fuse_SOURCES_DIST) $(ceph_kvstore_tool_SOURCES) \
 	$(ceph_mds_SOURCES) $(ceph_mon_SOURCES) \
 	$(ceph_monstore_tool_SOURCES) $(ceph_osd_SOURCES) \
@@ -2804,6 +2908,7 @@ DIST_SOURCES = $(libcls_log_client_a_SOURCES) \
 	$(unittest_confutils_SOURCES) $(unittest_context_SOURCES) \
 	$(unittest_crc32c_SOURCES) $(unittest_crush_indep_SOURCES) \
 	$(unittest_crush_wrapper_SOURCES) $(unittest_crypto_SOURCES) \
+	$(unittest_crypto_init_SOURCES) \
 	$(unittest_daemon_config_SOURCES) \
 	$(unittest_ecbackend_SOURCES) $(unittest_encoding_SOURCES) \
 	$(unittest_erasure_code_example_SOURCES) \
@@ -2880,21 +2985,22 @@ am__noinst_HEADERS_DIST = arch/intel.h arch/neon.h arch/probe.h \
 	mds/Dumper.h mds/InoTable.h mds/LocalLock.h mds/Locker.h \
 	mds/LogEvent.h mds/LogSegment.h mds/MDBalancer.h mds/MDCache.h \
 	mds/MDLog.h mds/MDS.h mds/MDSMap.h mds/MDSTable.h \
-	mds/MDSTableServer.h mds/MDSTableClient.h mds/Mutation.h \
-	mds/Migrator.h mds/Resetter.h mds/ScatterLock.h mds/Server.h \
-	mds/SessionMap.h mds/SimpleLock.h mds/SnapClient.h \
-	mds/SnapRealm.h mds/SnapServer.h mds/mds_table_types.h \
-	mds/mdstypes.h mds/snap.h mds/events/ECommitted.h \
-	mds/events/EExport.h mds/events/EFragment.h \
-	mds/events/EImportFinish.h mds/events/EImportStart.h \
-	mds/events/EMetaBlob.h mds/events/EOpen.h \
-	mds/events/EResetJournal.h mds/events/ESession.h \
-	mds/events/ESessions.h mds/events/ESlaveUpdate.h \
-	mds/events/ESubtreeMap.h mds/events/ETableClient.h \
-	mds/events/ETableServer.h mds/events/EUpdate.h \
-	os/btrfs_ioctl.h os/chain_xattr.h os/BtrfsFileStoreBackend.h \
-	os/CollectionIndex.h os/DBObjectMap.h os/GenericObjectMap.h \
-	os/FileJournal.h os/FileStore.h os/FlatIndex.h os/FDCache.h \
+	mds/MDSTableServer.h mds/MDSTableClient.h mds/MDSUtility.h \
+	mds/Mutation.h mds/Migrator.h mds/Resetter.h mds/ScatterLock.h \
+	mds/Server.h mds/SessionMap.h mds/SimpleLock.h \
+	mds/SnapClient.h mds/SnapRealm.h mds/SnapServer.h \
+	mds/mds_table_types.h mds/mdstypes.h mds/snap.h \
+	mds/events/ECommitted.h mds/events/EExport.h \
+	mds/events/EFragment.h mds/events/EImportFinish.h \
+	mds/events/EImportStart.h mds/events/EMetaBlob.h \
+	mds/events/EOpen.h mds/events/EResetJournal.h \
+	mds/events/ESession.h mds/events/ESessions.h \
+	mds/events/ESlaveUpdate.h mds/events/ESubtreeMap.h \
+	mds/events/ETableClient.h mds/events/ETableServer.h \
+	mds/events/EUpdate.h os/btrfs_ioctl.h os/chain_xattr.h \
+	os/BtrfsFileStoreBackend.h os/CollectionIndex.h \
+	os/DBObjectMap.h os/GenericObjectMap.h os/FileJournal.h \
+	os/FileStore.h os/FlatIndex.h os/FDCache.h \
 	os/GenericFileStoreBackend.h os/HashIndex.h os/IndexManager.h \
 	os/Journal.h os/JournalingObjectStore.h os/KeyValueDB.h \
 	os/LevelDBStore.h os/LFNIndex.h os/MemStore.h \
@@ -2907,12 +3013,18 @@ am__noinst_HEADERS_DIST = arch/intel.h arch/neon.h arch/probe.h \
 	osd/ReplicatedPG.h osd/PGBackend.h osd/ReplicatedBackend.h \
 	osd/TierAgentState.h osd/ECBackend.h osd/ECUtil.h \
 	osd/ECMsgTypes.h osd/ECTransaction.h osd/Watch.h \
-	osd/osd_types.h erasure-code/jerasure/ErasureCodeJerasure.h \
-	erasure-code/jerasure/cauchy.h erasure-code/jerasure/galois.h \
-	erasure-code/jerasure/jerasure.h \
-	erasure-code/jerasure/liberation.h \
-	erasure-code/jerasure/reed_sol.h \
-	erasure-code/jerasure/vectorop.h \
+	osd/osd_types.h \
+	erasure-code/jerasure/jerasure/include/cauchy.h \
+	erasure-code/jerasure/jerasure/include/galois.h \
+	erasure-code/jerasure/jerasure/include/jerasure.h \
+	erasure-code/jerasure/jerasure/include/liberation.h \
+	erasure-code/jerasure/jerasure/include/reed_sol.h \
+	erasure-code/jerasure/gf-complete/include/gf_int.h \
+	erasure-code/jerasure/gf-complete/include/gf_complete.h \
+	erasure-code/jerasure/gf-complete/include/gf_rand.h \
+	erasure-code/jerasure/gf-complete/include/gf_method.h \
+	erasure-code/jerasure/gf-complete/include/gf_general.h \
+	erasure-code/jerasure/ErasureCodeJerasure.h \
 	erasure-code/ErasureCodeInterface.h \
 	erasure-code/ErasureCodePlugin.h osdc/Blinker.h osdc/Filer.h \
 	osdc/Journaler.h osdc/ObjectCacher.h osdc/Objecter.h \
@@ -3160,7 +3272,7 @@ ACLOCAL = @ACLOCAL@
 AMTAR = @AMTAR@
 AM_CXXFLAGS = @AM_CXXFLAGS@ $(AM_COMMON_CFLAGS) -ftemplate-depth-1024 \
 	-Wnon-virtual-dtor -Wno-invalid-offsetof $(am__append_3) \
-	$(am__append_6) $(am__append_25)
+	$(am__append_6) $(am__append_27)
 AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
 AR = @AR@
 AUTOCONF = @AUTOCONF@
@@ -3205,6 +3317,14 @@ INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
 INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTEL_FLAGS = @INTEL_FLAGS@
+INTEL_PCLMUL_FLAGS = @INTEL_PCLMUL_FLAGS@
+INTEL_SSE2_FLAGS = @INTEL_SSE2_FLAGS@
+INTEL_SSE3_FLAGS = @INTEL_SSE3_FLAGS@
+INTEL_SSE4_1_FLAGS = @INTEL_SSE4_1_FLAGS@
+INTEL_SSE4_2_FLAGS = @INTEL_SSE4_2_FLAGS@
+INTEL_SSE_FLAGS = @INTEL_SSE_FLAGS@
+INTEL_SSSE3_FLAGS = @INTEL_SSSE3_FLAGS@
 JAR = @JAR@
 JAVAC = @JAVAC@
 JAVAH = @JAVAH@
@@ -3328,7 +3448,7 @@ top_build_prefix = @top_build_prefix@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 AUTOMAKE_OPTIONS = gnu subdir-objects
-SUBDIRS = ocf java $(am__append_61)
+SUBDIRS = ocf java $(am__append_62)
 DIST_SUBDIRS = gtest ocf libs3 java
 BUILT_SOURCES = init-ceph
 
@@ -3370,6 +3490,8 @@ EXTRA_DIST = brag/server brag/README.md brag/client \
 	libs3/mswin libs3/src libs3/test unittest_bufferlist.sh
 CLEANFILES = $(shell_scripts) ceph_ver.h sample.fetch_config
 
+# jerasure plugin
+
 # everything else we want to include in a 'make dist'
 noinst_HEADERS = arch/intel.h arch/neon.h arch/probe.h \
 	auth/cephx/CephxAuthorizeHandler.h auth/cephx/CephxKeyServer.h \
@@ -3407,12 +3529,12 @@ noinst_HEADERS = arch/intel.h arch/neon.h arch/probe.h \
 	mds/Dumper.h mds/InoTable.h mds/LocalLock.h mds/Locker.h \
 	mds/LogEvent.h mds/LogSegment.h mds/MDBalancer.h mds/MDCache.h \
 	mds/MDLog.h mds/MDS.h mds/MDSMap.h mds/MDSTable.h \
-	mds/MDSTableServer.h mds/MDSTableClient.h mds/Mutation.h \
-	mds/Migrator.h mds/Resetter.h mds/ScatterLock.h mds/Server.h \
-	mds/SessionMap.h mds/SimpleLock.h mds/SnapClient.h \
-	mds/SnapRealm.h mds/SnapServer.h mds/inode_backtrace.h \
-	mds/mds_table_types.h mds/mdstypes.h mds/snap.h \
-	mds/events/ECommitted.h mds/events/EExport.h \
+	mds/MDSTableServer.h mds/MDSTableClient.h mds/MDSUtility.h \
+	mds/Mutation.h mds/Migrator.h mds/Resetter.h mds/ScatterLock.h \
+	mds/Server.h mds/SessionMap.h mds/SimpleLock.h \
+	mds/SnapClient.h mds/SnapRealm.h mds/SnapServer.h \
+	mds/inode_backtrace.h mds/mds_table_types.h mds/mdstypes.h \
+	mds/snap.h mds/events/ECommitted.h mds/events/EExport.h \
 	mds/events/EFragment.h mds/events/EImportFinish.h \
 	mds/events/EImportStart.h mds/events/EMetaBlob.h \
 	mds/events/EOpen.h mds/events/EResetJournal.h \
@@ -3435,12 +3557,18 @@ noinst_HEADERS = arch/intel.h arch/neon.h arch/probe.h \
 	osd/ReplicatedPG.h osd/PGBackend.h osd/ReplicatedBackend.h \
 	osd/TierAgentState.h osd/ECBackend.h osd/ECUtil.h \
 	osd/ECMsgTypes.h osd/ECTransaction.h osd/Watch.h \
-	osd/osd_types.h erasure-code/jerasure/ErasureCodeJerasure.h \
-	erasure-code/jerasure/cauchy.h erasure-code/jerasure/galois.h \
-	erasure-code/jerasure/jerasure.h \
-	erasure-code/jerasure/liberation.h \
-	erasure-code/jerasure/reed_sol.h \
-	erasure-code/jerasure/vectorop.h \
+	osd/osd_types.h \
+	erasure-code/jerasure/jerasure/include/cauchy.h \
+	erasure-code/jerasure/jerasure/include/galois.h \
+	erasure-code/jerasure/jerasure/include/jerasure.h \
+	erasure-code/jerasure/jerasure/include/liberation.h \
+	erasure-code/jerasure/jerasure/include/reed_sol.h \
+	erasure-code/jerasure/gf-complete/include/gf_int.h \
+	erasure-code/jerasure/gf-complete/include/gf_complete.h \
+	erasure-code/jerasure/gf-complete/include/gf_rand.h \
+	erasure-code/jerasure/gf-complete/include/gf_method.h \
+	erasure-code/jerasure/gf-complete/include/gf_general.h \
+	erasure-code/jerasure/ErasureCodeJerasure.h \
 	erasure-code/ErasureCodeInterface.h \
 	erasure-code/ErasureCodePlugin.h osdc/Blinker.h osdc/Filer.h \
 	osdc/Journaler.h osdc/ObjectCacher.h osdc/Objecter.h \
@@ -3449,7 +3577,7 @@ noinst_HEADERS = arch/intel.h arch/neon.h arch/probe.h \
 	client/MetaRequest.h client/MetaSession.h \
 	client/ClientSnapRealm.h client/SyntheticClient.h \
 	client/Trace.h client/ioctl.h client/ObjecterWriteback.h \
-	$(am__append_22) global/pidfile.h global/global_init.h \
+	$(am__append_24) global/pidfile.h global/global_init.h \
 	global/global_context.h global/signal_handler.h \
 	json_spirit/json_spirit.h \
 	json_spirit/json_spirit_error_position.h \
@@ -3654,36 +3782,36 @@ bin_SCRIPTS = brag/client/ceph-brag ceph ceph-run ceph-rest-api \
 sbin_SCRIPTS = 
 su_sbin_SCRIPTS = mount.fuse.ceph mkcephfs
 dist_bin_SCRIPTS = 
-lib_LTLIBRARIES = librados.la librbd.la libcephfs.la $(am__append_65)
+lib_LTLIBRARIES = librados.la librbd.la libcephfs.la $(am__append_66)
 noinst_LTLIBRARIES = libarch.la libauth.la libcrush.la libmon.la \
 	libmds.la libos.la libosd.la liberasure_code.la libosdc.la \
-	libclient.la $(am__append_21) libglobal.la libjson_spirit.la \
+	libclient.la $(am__append_23) libglobal.la libjson_spirit.la \
 	liblog.la libperfglue.la libcommon_crc.la libcommon.la \
-	libmsg.la $(am__append_34) libcls_lock_client.la \
+	libmsg.la $(am__append_35) libcls_lock_client.la \
 	libcls_refcount_client.la libcls_rgw_client.la \
-	libcls_rbd_client.la $(am__append_50) libradostest.la
+	libcls_rbd_client.la $(am__append_51) libradostest.la
 noinst_LIBRARIES = $(am__append_17) libcls_version_client.a \
 	libcls_log_client.a libcls_statelog_client.a \
 	libcls_replica_log_client.a libcls_user_client.a
 radoslib_LTLIBRARIES = libcls_hello.la libcls_rbd.la libcls_lock.la \
 	libcls_refcount.la libcls_version.la libcls_log.la \
 	libcls_statelog.la libcls_replica_log.la libcls_user.la \
-	libcls_rgw.la $(am__append_39)
+	libcls_rgw.la $(am__append_40)
 
 # like bin_PROGRAMS, but these targets are only built for debug builds
-bin_DEBUGPROGRAMS = ceph_test_ioctls $(am__append_37) \
+bin_DEBUGPROGRAMS = ceph_test_ioctls $(am__append_38) \
 	ceph_erasure_code_benchmark ceph_erasure_code ceph_test_timers \
 	ceph_test_signal_handlers ceph_test_rados ceph_test_mutate \
 	ceph_test_rewrite_latency ceph_test_msgr ceph_streamtest \
 	ceph_test_trans ceph_test_crypto ceph_test_keys \
-	$(am__append_48) ceph_smalliobench ceph_smalliobenchfs \
+	$(am__append_49) ceph_smalliobench ceph_smalliobenchfs \
 	ceph_smalliobenchdumb ceph_smalliobenchrbd ceph_tpbench \
-	ceph_omapbench $(am__append_49) ceph_bench_log \
-	$(am__append_52) ceph_multi_stress_watch ceph_test_librbd \
-	$(am__append_53) ceph_test_cls_rbd ceph_test_cls_refcount \
+	ceph_omapbench $(am__append_50) ceph_bench_log \
+	$(am__append_53) ceph_multi_stress_watch ceph_test_librbd \
+	$(am__append_54) ceph_test_cls_rbd ceph_test_cls_refcount \
 	ceph_test_cls_version ceph_test_cls_log ceph_test_cls_statelog \
 	ceph_test_cls_replica_log ceph_test_cls_lock \
-	ceph_test_cls_hello $(am__append_54) ceph_test_mon_workloadgen \
+	ceph_test_cls_hello $(am__append_55) ceph_test_mon_workloadgen \
 	ceph_test_rados_api_cmd ceph_test_rados_api_io \
 	ceph_test_rados_api_c_write_operations \
 	ceph_test_rados_api_c_read_operations ceph_test_rados_api_aio \
@@ -3691,7 +3819,7 @@ bin_DEBUGPROGRAMS = ceph_test_ioctls $(am__append_37) \
 	ceph_test_rados_api_stat ceph_test_rados_api_watch_notify \
 	ceph_test_rados_api_snapshots ceph_test_rados_api_cls \
 	ceph_test_rados_api_misc ceph_test_rados_api_tier \
-	ceph_test_rados_api_lock ceph_test_libcephfs $(am__append_55) \
+	ceph_test_rados_api_lock ceph_test_libcephfs $(am__append_56) \
 	ceph_test_objectstore_workloadgen \
 	ceph_test_filestore_idempotent \
 	ceph_test_filestore_idempotent_sequence ceph_xattr_bench \
@@ -3702,7 +3830,7 @@ bin_DEBUGPROGRAMS = ceph_test_ioctls $(am__append_37) \
 	ceph_test_cfuse_cache_invalidate ceph_test_c_headers \
 	ceph_test_get_blkdev_size ceph-osdomap-tool ceph-monstore-tool \
 	ceph-kvstore-tool ceph_scratchtool ceph_scratchtoolpp \
-	ceph_psim ceph_dupstore ceph_radosacl
+	ceph_psim ceph_dupstore ceph_radosacl ceph-client-debug
 
 # like sbin_SCRIPTS but can be used to install to e.g. /usr/sbin
 ceph_sbindir = $(sbindir)
@@ -3714,7 +3842,8 @@ su_sbindir = /sbin
 check_SCRIPTS = test/erasure-code/test-erasure-code.sh \
 	unittest_bufferlist.sh test/encoding/check-generated.sh \
 	test/mon/osd-pool-create.sh test/mon/misc.sh \
-	test/mon/osd-crush.sh test/mon/mkfs.sh test/ceph-disk.sh \
+	test/mon/osd-crush.sh test/mon/osd-erasure-code-profile.sh \
+	test/mon/mkfs.sh test/ceph-disk.sh \
 	test/mon/mon-handle-forward.sh test/vstart_wrapped_tests.sh \
 	test/pybind/test_ceph_argparse.py
 
@@ -3740,7 +3869,7 @@ AM_COMMON_CFLAGS = \
 	-fno-strict-aliasing \
 	-fsigned-char
 
-AM_CFLAGS = $(AM_COMMON_CFLAGS) $(am__append_5) $(am__append_24)
+AM_CFLAGS = $(AM_COMMON_CFLAGS) $(am__append_5) $(am__append_26)
 AM_CPPFLAGS = $(AM_COMMON_CPPFLAGS)
 
 # note: this is position dependant, it affects the -l options that
@@ -3755,8 +3884,8 @@ AM_LDFLAGS = $(am__append_2) $(am__append_4)
 AM_CCASFLAGS = -f elf64
 
 #####################
-EXTRALIBS = -luuid -lm $(KEYUTILS_LIB) $(am__append_7) $(am__append_8) \
-	$(am__append_9) $(am__append_13)
+EXTRALIBS = -luuid -lm $(am__append_7) $(am__append_8) $(am__append_9) \
+	$(am__append_13)
 LIBGLOBAL = libglobal.la
 LIBCOMMON = libcommon.la
 LIBARCH = libarch.la
@@ -3791,14 +3920,14 @@ CEPH_GLOBAL = $(LIBGLOBAL) $(LIBCOMMON) $(PTHREAD_LIBS) -lm $(CRYPTO_LIBS) $(EXT
 # This is set by [lib]/Makefile.am and used for build tests
 
 # important; libmsg before libauth!
-LIBCOMMON_DEPS = libcommon_crc.la $(LIBMSG) $(LIBAUTH) $(LIBCRUSH) \
-	$(LIBJSON_SPIRIT) $(LIBLOG) $(LIBARCH) $(KEYUTILS_LIB) \
-	$(am__append_31)
+LIBCOMMON_DEPS = libcommon_crc.la $(LIBERASURE_CODE) $(LIBMSG) \
+	$(LIBAUTH) $(LIBCRUSH) $(LIBJSON_SPIRIT) $(LIBLOG) $(LIBARCH) \
+	$(am__append_32)
 LIBRADOS_DEPS = libcls_lock_client.la $(LIBOSDC) $(LIBCOMMON)
-LIBRGW_DEPS = $(am__append_35)
+LIBRGW_DEPS = $(am__append_36)
 
 # This is used by the dencoder test
-DENCODER_SOURCES = $(am__append_38)
+DENCODER_SOURCES = $(am__append_39)
 DENCODER_DEPS = libcls_lock_client.la libcls_refcount_client.la \
 	libcls_replica_log_client.a libcls_rgw_client.la \
 	libcls_user_client.a
@@ -3852,7 +3981,7 @@ libmon_la_SOURCES = \
 	mon/DataHealthService.cc \
 	mon/ConfigKeyService.cc
 
-libmon_la_LIBADD = $(LIBAUTH) $(LIBCOMMON) $(LIBOS) $(LIBERASURE_CODE)
+libmon_la_LIBADD = $(LIBAUTH) $(LIBCOMMON) $(LIBOS)
 libmds_la_SOURCES = \
 	mds/Anchor.cc \
 	mds/Capability.cc \
@@ -3882,7 +4011,8 @@ libmds_la_SOURCES = \
 	mds/SnapServer.cc \
 	mds/snap.cc \
 	mds/SessionMap.cc \
-	mds/MDLog.cc 
+	mds/MDLog.cc \
+	mds/MDSUtility.cc
 
 libmds_la_LIBADD = $(LIBOSDC)
 libos_la_SOURCES = os/chain_xattr.cc os/DBObjectMap.cc \
@@ -3917,31 +4047,103 @@ libosd_la_SOURCES = \
 	osd/ECUtil.cc \
 	objclass/class_api.cc
 
-libosd_la_LIBADD = $(LIBOSDC) $(LIBOS) $(LIBERASURE_CODE)
+libosd_la_LIBADD = $(LIBOSDC) $(LIBOS)
 erasure_codelibdir = $(pkglibdir)/erasure-code
-erasure_codelib_LTLIBRARIES = libec_jerasure.la libec_example.la \
+erasure_codelib_LTLIBRARIES = libec_jerasure_generic.la \
+	libec_jerasure_sse3.la libec_jerasure_sse4.la \
+	libec_jerasure.la libec_example.la \
 	libec_missing_entry_point.la libec_hangs.la \
-	libec_fail_to_initialize.la libec_fail_to_register.la
+	libec_fail_to_initialize.la libec_fail_to_register.la \
+	libec_test_jerasure_sse4.la libec_test_jerasure_sse3.la \
+	libec_test_jerasure_generic.la
+jerasure_sources = \
+  erasure-code/jerasure/jerasure/src/cauchy.c \
+  erasure-code/jerasure/jerasure/src/galois.c \
+  erasure-code/jerasure/jerasure/src/jerasure.c \
+  erasure-code/jerasure/jerasure/src/liberation.c \
+  erasure-code/jerasure/jerasure/src/reed_sol.c \
+  erasure-code/jerasure/gf-complete/src/gf_wgen.c \
+  erasure-code/jerasure/gf-complete/src/gf_method.c \
+  erasure-code/jerasure/gf-complete/src/gf_w16.c \
+  erasure-code/jerasure/gf-complete/src/gf.c \
+  erasure-code/jerasure/gf-complete/src/gf_w32.c \
+  erasure-code/jerasure/gf-complete/src/gf_w64.c \
+  erasure-code/jerasure/gf-complete/src/gf_w128.c \
+  erasure-code/jerasure/gf-complete/src/gf_general.c \
+  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 \
+  erasure-code/jerasure/ErasureCodePluginJerasure.cc \
+  erasure-code/jerasure/ErasureCodeJerasure.cc
 
-# jerasure plugin
+libec_jerasure_generic_la_SOURCES = ${jerasure_sources}
+libec_jerasure_generic_la_CFLAGS = ${AM_CFLAGS}  \
+	-Ierasure-code/jerasure/gf-complete/include \
+	-Ierasure-code/jerasure/jerasure/include
+
+libec_jerasure_generic_la_CXXFLAGS = ${AM_CXXFLAGS} \
+	-Ierasure-code/jerasure/gf-complete/include \
+	-Ierasure-code/jerasure/jerasure/include
+
+libec_jerasure_generic_la_LIBADD = $(LIBCRUSH) $(PTHREAD_LIBS) $(EXTRALIBS)
+libec_jerasure_generic_la_LDFLAGS = ${AM_LDFLAGS} -version-info 2:0:0 \
+	$(am__append_19)
+libec_jerasure_sse3_la_SOURCES = ${jerasure_sources}
+libec_jerasure_sse3_la_CFLAGS = ${AM_CFLAGS}  \
+	${INTEL_SSE_FLAGS} \
+	${INTEL_SSE2_FLAGS} \
+	${INTEL_SSE3_FLAGS} \
+	${INTEL_SSSE3_FLAGS} \
+	-Ierasure-code/jerasure/gf-complete/include \
+	-Ierasure-code/jerasure/jerasure/include
+
+libec_jerasure_sse3_la_CXXFLAGS = ${AM_CXXFLAGS} \
+	${INTEL_SSE_FLAGS} \
+	${INTEL_SSE2_FLAGS} \
+	${INTEL_SSE3_FLAGS} \
+	${INTEL_SSSE3_FLAGS} \
+	-Ierasure-code/jerasure/gf-complete/include \
+	-Ierasure-code/jerasure/jerasure/include
+
+libec_jerasure_sse3_la_LIBADD = $(LIBCRUSH) $(PTHREAD_LIBS) $(EXTRALIBS)
+libec_jerasure_sse3_la_LDFLAGS = ${AM_LDFLAGS} -version-info 2:0:0 \
+	$(am__append_20)
+libec_jerasure_sse4_la_SOURCES = ${jerasure_sources}
+libec_jerasure_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} \
+	-Ierasure-code/jerasure/gf-complete/include \
+	-Ierasure-code/jerasure/jerasure/include
+
+libec_jerasure_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} \
+	-Ierasure-code/jerasure/gf-complete/include \
+	-Ierasure-code/jerasure/jerasure/include
+
+libec_jerasure_sse4_la_LIBADD = $(LIBCRUSH) $(PTHREAD_LIBS) $(EXTRALIBS)
+libec_jerasure_sse4_la_LDFLAGS = ${AM_LDFLAGS} -version-info 2:0:0 \
+	$(am__append_21)
 libec_jerasure_la_SOURCES = \
-  erasure-code/jerasure/ErasureCodePluginJerasure.cc \
-  erasure-code/jerasure/ErasureCodeJerasure.cc \
-  erasure-code/jerasure/cauchy.c \
-  erasure-code/jerasure/galois.c \
-  erasure-code/jerasure/jerasure.c \
-  erasure-code/jerasure/liberation.c \
-  erasure-code/jerasure/reed_sol.c
+	erasure-code/jerasure/ErasureCodePluginSelectJerasure.cc
 
 libec_jerasure_la_CFLAGS = ${AM_CFLAGS} 
-libec_jerasure_la_CXXFLAGS = ${AM_CXXFLAGS} 
+libec_jerasure_la_CXXFLAGS = ${AM_CXXFLAGS}
 libec_jerasure_la_LIBADD = $(LIBCRUSH) $(PTHREAD_LIBS) $(EXTRALIBS)
-libec_jerasure_la_LDFLAGS = ${AM_LDFLAGS} -version-info 1:0:0 \
-	$(am__append_19)
+libec_jerasure_la_LDFLAGS = ${AM_LDFLAGS} -version-info 2:0:0 \
+	$(am__append_22)
 liberasure_code_la_SOURCES = \
 	erasure-code/ErasureCodePlugin.cc
 
-liberasure_code_la_LIBADD = $(LIBOSDC) $(LIBOS) $(am__append_20)
+ at LINUX_TRUE@liberasure_code_la_LIBADD = -ldl
 libosdc_la_SOURCES = \
 	osdc/Objecter.cc \
 	osdc/ObjectCacher.cc \
@@ -3977,8 +4179,8 @@ liblog_la_SOURCES = \
 	log/Log.cc \
 	log/SubsystemMap.cc
 
-libperfglue_la_SOURCES = $(am__append_23) $(am__append_26) \
-	$(am__append_27) $(am__append_28)
+libperfglue_la_SOURCES = $(am__append_25) $(am__append_28) \
+	$(am__append_29) $(am__append_30)
 @WITH_TCMALLOC_TRUE at libperfglue_la_LIBADD = -ltcmalloc
 
 # these should go out of libcommon
@@ -4007,15 +4209,15 @@ libcommon_la_SOURCES = ceph_ver.c common/DecayCounter.cc \
 	common/pick_address.cc common/util.cc common/TextTable.cc \
 	common/ceph_fs.cc common/ceph_hash.cc common/ceph_strings.cc \
 	common/ceph_frag.cc common/addr_parsing.c common/hobject.cc \
-	common/bloom_filter.cc common/linux_version.c $(am__append_29) \
-	mon/MonCap.cc mon/MonClient.cc mon/MonMap.cc osd/OSDMap.cc \
-	osd/osd_types.cc osd/ECMsgTypes.cc osd/HitSet.cc mds/MDSMap.cc \
+	common/bloom_filter.cc common/linux_version.c mon/MonCap.cc \
+	mon/MonClient.cc mon/MonMap.cc osd/OSDMap.cc osd/osd_types.cc \
+	osd/ECMsgTypes.cc osd/HitSet.cc mds/MDSMap.cc \
 	mds/inode_backtrace.cc mds/mdstypes.cc
 
 # inject crc in common
 libcommon_crc_la_SOURCES = common/sctp_crc32.c common/crc32c.cc \
 	common/crc32c_intel_baseline.c common/crc32c_intel_fast.c \
-	$(am__append_30)
+	$(am__append_31)
 @WITH_GOOD_YASM_ELF64_TRUE at libcommon_crc_la_LIBTOOLFLAGS = --tag=CC
 libcommon_la_LIBADD = $(LIBCOMMON_DEPS)
 libmsg_la_SOURCES = \
@@ -4057,7 +4259,7 @@ librados_la_SOURCES = \
 librados_la_CXXFLAGS = ${AM_CXXFLAGS}
 librados_la_LIBADD = $(LIBRADOS_DEPS) $(PTHREAD_LIBS) $(CRYPTO_LIBS) $(EXTRALIBS)
 librados_la_LDFLAGS = ${AM_LDFLAGS} -version-info 2:0:0 \
-	$(am__append_32)
+	$(am__append_33)
 librbd_la_SOURCES = \
 	librbd/librbd.cc \
 	librbd/AioCompletion.cc \
@@ -4072,7 +4274,7 @@ librbd_la_LIBADD = \
 	libcls_rbd_client.la libcls_lock_client.la \
 	$(PTHREAD_LIBS) $(EXTRALIBS)
 
-librbd_la_LDFLAGS = ${AM_LDFLAGS} -version-info 1:0:0 $(am__append_33)
+librbd_la_LDFLAGS = ${AM_LDFLAGS} -version-info 1:0:0 $(am__append_34)
 @WITH_RADOSGW_TRUE at librgw_la_SOURCES = \
 @WITH_RADOSGW_TRUE@	rgw/librgw.cc \
 @WITH_RADOSGW_TRUE@	rgw/rgw_acl.cc \
@@ -4220,12 +4422,12 @@ ceph_erasure_code_benchmark_SOURCES = \
 	test/erasure-code/ceph_erasure_code_benchmark.cc
 
 ceph_erasure_code_benchmark_LDADD = $(LIBOSD) $(LIBCOMMON) \
-	$(BOOST_PROGRAM_OPTIONS_LIBS) $(CEPH_GLOBAL) $(am__append_40)
+	$(BOOST_PROGRAM_OPTIONS_LIBS) $(CEPH_GLOBAL) $(am__append_41)
 ceph_erasure_code_SOURCES = \
 	test/erasure-code/ceph_erasure_code.cc
 
 ceph_erasure_code_LDADD = $(LIBOSD) $(LIBCOMMON) \
-	$(BOOST_PROGRAM_OPTIONS_LIBS) $(CEPH_GLOBAL) $(am__append_41)
+	$(BOOST_PROGRAM_OPTIONS_LIBS) $(CEPH_GLOBAL) $(am__append_42)
 libec_example_la_SOURCES = test/erasure-code/ErasureCodePluginExample.cc
 libec_example_la_CFLAGS = ${AM_CFLAGS}
 libec_example_la_CXXFLAGS = ${AM_CXXFLAGS}
@@ -4251,23 +4453,45 @@ libec_fail_to_register_la_CFLAGS = ${AM_CFLAGS}
 libec_fail_to_register_la_CXXFLAGS = ${AM_CXXFLAGS}
 libec_fail_to_register_la_LIBADD = $(PTHREAD_LIBS) $(EXTRALIBS)
 libec_fail_to_register_la_LDFLAGS = ${AM_LDFLAGS} -export-symbols-regex '.*__erasure_code_.*'
+libec_test_jerasure_sse4_la_SOURCES = test/erasure-code/TestJerasurePluginSSE4.cc
+libec_test_jerasure_sse4_la_CFLAGS = ${AM_CFLAGS}
+libec_test_jerasure_sse4_la_CXXFLAGS = ${AM_CXXFLAGS}
+libec_test_jerasure_sse4_la_LIBADD = $(PTHREAD_LIBS) $(EXTRALIBS)
+libec_test_jerasure_sse4_la_LDFLAGS = ${AM_LDFLAGS} -export-symbols-regex '.*__erasure_code_.*'
+libec_test_jerasure_sse3_la_SOURCES = test/erasure-code/TestJerasurePluginSSE3.cc
+libec_test_jerasure_sse3_la_CFLAGS = ${AM_CFLAGS}
+libec_test_jerasure_sse3_la_CXXFLAGS = ${AM_CXXFLAGS}
+libec_test_jerasure_sse3_la_LIBADD = $(PTHREAD_LIBS) $(EXTRALIBS)
+libec_test_jerasure_sse3_la_LDFLAGS = ${AM_LDFLAGS} -export-symbols-regex '.*__erasure_code_.*'
+libec_test_jerasure_generic_la_SOURCES = test/erasure-code/TestJerasurePluginGeneric.cc
+libec_test_jerasure_generic_la_CFLAGS = ${AM_CFLAGS}
+libec_test_jerasure_generic_la_CXXFLAGS = ${AM_CXXFLAGS}
+libec_test_jerasure_generic_la_LIBADD = $(PTHREAD_LIBS) $(EXTRALIBS)
+libec_test_jerasure_generic_la_LDFLAGS = ${AM_LDFLAGS} -export-symbols-regex '.*__erasure_code_.*'
 unittest_erasure_code_plugin_SOURCES = test/erasure-code/TestErasureCodePlugin.cc 
 unittest_erasure_code_plugin_CXXFLAGS = $(UNITTEST_CXXFLAGS)
 unittest_erasure_code_plugin_LDADD = $(LIBOSD) $(LIBCOMMON) \
-	$(UNITTEST_LDADD) $(CEPH_GLOBAL) $(am__append_42)
+	$(UNITTEST_LDADD) $(CEPH_GLOBAL) $(am__append_43)
 unittest_erasure_code_jerasure_SOURCES = \
 	test/erasure-code/TestErasureCodeJerasure.cc \
-	$(libec_jerasure_la_SOURCES)
+	${jerasure_sources}
+
+unittest_erasure_code_jerasure_CFLAGS = $(AM_CFLAGS) \
+	-Ierasure-code/jerasure/gf-complete/include \
+	-Ierasure-code/jerasure/jerasure/include
+
+unittest_erasure_code_jerasure_CXXFLAGS = $(UNITTEST_CXXFLAGS) \
+	-Ierasure-code/jerasure/gf-complete/include \
+	-Ierasure-code/jerasure/jerasure/include
 
-unittest_erasure_code_jerasure_CXXFLAGS = $(UNITTEST_CXXFLAGS)
 unittest_erasure_code_jerasure_LDADD = $(LIBOSD) $(LIBCOMMON) \
-	$(UNITTEST_LDADD) $(CEPH_GLOBAL) $(am__append_43)
+	$(UNITTEST_LDADD) $(CEPH_GLOBAL) $(am__append_44)
 unittest_erasure_code_plugin_jerasure_SOURCES = \
 	test/erasure-code/TestErasureCodePluginJerasure.cc
 
 unittest_erasure_code_plugin_jerasure_CXXFLAGS = ${AM_CXXFLAGS} ${UNITTEST_CXXFLAGS}
 unittest_erasure_code_plugin_jerasure_LDADD = $(LIBOSD) $(LIBCOMMON) \
-	$(UNITTEST_LDADD) $(CEPH_GLOBAL) $(am__append_44)
+	$(UNITTEST_LDADD) $(CEPH_GLOBAL) $(am__append_45)
 unittest_erasure_code_example_SOURCES = test/erasure-code/TestErasureCodeExample.cc 
 unittest_erasure_code_example_CXXFLAGS = $(UNITTEST_CXXFLAGS)
 unittest_erasure_code_example_LDADD = $(LIBOSD) $(LIBCOMMON) $(UNITTEST_LDADD) $(CEPH_GLOBAL)
@@ -4301,11 +4525,11 @@ ceph_dencoder_SOURCES = \
 	$(DENCODER_SOURCES)
 
 ceph_dencoder_LDADD = $(LIBOSD) $(LIBMDS) $(LIBMON) $(DENCODER_DEPS) \
-	$(CEPH_GLOBAL) $(am__append_45)
+	$(CEPH_GLOBAL) $(am__append_46)
 
 # These should always use explicit _CFLAGS/_CXXFLAGS so avoid basename conflicts
-ceph_dencoder_CFLAGS = ${AM_CFLAGS} $(am__append_46)
-ceph_dencoder_CXXFLAGS = ${AM_CXXFLAGS} $(am__append_47)
+ceph_dencoder_CFLAGS = ${AM_CFLAGS} $(am__append_47)
+ceph_dencoder_CXXFLAGS = ${AM_CXXFLAGS} $(am__append_48)
 get_command_descriptions_SOURCES = test/common/get_command_descriptions.cc
 get_command_descriptions_LDADD = $(LIBMON) $(LIBCOMMON) $(CEPH_GLOBAL)
 
@@ -4508,7 +4732,7 @@ unittest_osd_types_LDADD = $(UNITTEST_LDADD) $(CEPH_GLOBAL)
 unittest_pglog_SOURCES = test/osd/TestPGLog.cc
 unittest_pglog_CXXFLAGS = $(UNITTEST_CXXFLAGS)
 unittest_pglog_LDADD = $(LIBOSD) $(UNITTEST_LDADD) $(CEPH_GLOBAL) \
-	$(am__append_51)
+	$(am__append_52)
 unittest_ecbackend_SOURCES = test/osd/TestECBackend.cc
 unittest_ecbackend_CXXFLAGS = $(UNITTEST_CXXFLAGS)
 unittest_ecbackend_LDADD = $(LIBOSD) $(UNITTEST_LDADD) $(CEPH_GLOBAL)
@@ -4542,6 +4766,9 @@ unittest_arch_CXXFLAGS = $(UNITTEST_CXXFLAGS)
 unittest_crypto_SOURCES = test/crypto.cc
 unittest_crypto_LDADD = $(UNITTEST_LDADD) $(CEPH_GLOBAL)
 unittest_crypto_CXXFLAGS = $(UNITTEST_CXXFLAGS)
+unittest_crypto_init_SOURCES = test/crypto_init.cc
+unittest_crypto_init_LDADD = $(UNITTEST_LDADD) $(CEPH_GLOBAL)
+unittest_crypto_init_CXXFLAGS = $(UNITTEST_CXXFLAGS)
 unittest_perf_counters_SOURCES = test/perf_counters.cc
 unittest_perf_counters_LDADD = $(UNITTEST_LDADD) $(CEPH_GLOBAL)
 unittest_perf_counters_CXXFLAGS = $(UNITTEST_CXXFLAGS)
@@ -4840,19 +5067,19 @@ ceph_test_c_headers_SOURCES = test/test_c_headers.c
 ceph_test_c_headers_LDADD = $(LIBRADOS) $(LIBCEPHFS)
 ceph_test_get_blkdev_size_SOURCES = test/test_get_blkdev_size.cc
 ceph_test_get_blkdev_size_LDADD = $(LIBCOMMON)
-ceph_osdomap_tool_SOURCES = tools/ceph-osdomap-tool.cc
+ceph_osdomap_tool_SOURCES = tools/ceph_osdomap_tool.cc
 ceph_osdomap_tool_LDADD = $(LIBOS) $(CEPH_GLOBAL) $(BOOST_PROGRAM_OPTIONS_LIBS)
-ceph_monstore_tool_SOURCES = tools/ceph-monstore-tool.cc
+ceph_monstore_tool_SOURCES = tools/ceph_monstore_tool.cc
 ceph_monstore_tool_LDADD = $(LIBOS) $(CEPH_GLOBAL) $(BOOST_PROGRAM_OPTIONS_LIBS)
-ceph_kvstore_tool_SOURCES = tools/ceph-kvstore-tool.cc
+ceph_kvstore_tool_SOURCES = tools/ceph_kvstore_tool.cc
 ceph_kvstore_tool_LDADD = $(LIBOS) $(CEPH_GLOBAL)
 ceph_kvstore_tool_CXXFLAGS = $(UNITTEST_CXXFLAGS)
-ceph_filestore_tool_SOURCES = tools/ceph-filestore-tool.cc
+ceph_filestore_tool_SOURCES = tools/ceph_filestore_tool.cc
 ceph_filestore_tool_LDADD = $(LIBOSD) $(LIBOS) $(CEPH_GLOBAL) \
-	-lboost_program_options $(am__append_56)
-ceph_filestore_dump_SOURCES = tools/ceph-filestore-dump.cc
+	-lboost_program_options $(am__append_57)
+ceph_filestore_dump_SOURCES = tools/ceph_filestore_dump.cc
 ceph_filestore_dump_LDADD = $(LIBOSD) $(LIBOS) $(CEPH_GLOBAL) \
-	$(BOOST_PROGRAM_OPTIONS_LIBS) $(am__append_57)
+	$(BOOST_PROGRAM_OPTIONS_LIBS) $(am__append_58)
 monmaptool_SOURCES = tools/monmaptool.cc
 monmaptool_LDADD = $(CEPH_GLOBAL) $(LIBCOMMON)
 crushtool_SOURCES = tools/crushtool.cc
@@ -4869,6 +5096,8 @@ ceph_dupstore_SOURCES = tools/dupstore.cc
 ceph_dupstore_LDADD = $(LIBOS) $(CEPH_GLOBAL)
 ceph_radosacl_SOURCES = tools/radosacl.cc
 ceph_radosacl_LDADD = $(LIBRADOS) $(CEPH_GLOBAL)
+ceph_client_debug_SOURCES = tools/ceph-client-debug.cc
+ceph_client_debug_LDADD = $(LIBCEPHFS) $(CEPH_GLOBAL) $(LIBCOMMON)
 rados_SOURCES = tools/rados/rados.cc tools/rados/rados_import.cc \
 	tools/rados/rados_export.cc tools/rados/rados_sync.cc \
 	common/obj_bencher.cc # needs cleanup so it can go in \
@@ -4878,7 +5107,7 @@ rados_LDADD = libcls_lock_client.la $(LIBRADOS) $(CEPH_GLOBAL)
 @WITH_REST_BENCH_TRUE@	common/obj_bencher.cc # needs cleanup so \
 @WITH_REST_BENCH_TRUE@	it can go in libcommon.la
 @WITH_REST_BENCH_TRUE at rest_bench_LDADD = $(CEPH_GLOBAL) \
- at WITH_REST_BENCH_TRUE@	$(am__append_59) $(am__append_60)
+ at WITH_REST_BENCH_TRUE@	$(am__append_60) $(am__append_61)
 @WITH_REST_BENCH_TRUE@@WITH_SYSTEM_LIBS3_FALSE at rest_bench_CXXFLAGS = ${AM_CXXFLAGS} -I$(top_srcdir)/src/libs3/inc
 ceph_conf_SOURCES = tools/ceph_conf.cc
 ceph_conf_LDADD = $(CEPH_GLOBAL) $(LIBCOMMON)
@@ -4900,8 +5129,8 @@ ceph_mds_LDADD = $(LIBMDS) $(LIBOSDC) $(CEPH_GLOBAL) $(LIBCOMMON)
 # admin tools
 
 # user tools
-mount_ceph_SOURCES = mount/mount.ceph.c
-mount_ceph_LDADD = $(LIBCOMMON)
+mount_ceph_SOURCES = mount/mount.ceph.c common/secret.c
+mount_ceph_LDADD = $(LIBCOMMON) $(KEYUTILS_LIB)
 cephfs_SOURCES = cephfs.cc
 cephfs_LDADD = $(LIBCOMMON)
 librados_config_SOURCES = librados-config.cc
@@ -4909,8 +5138,8 @@ librados_config_LDADD = $(LIBRADOS) $(CEPH_GLOBAL)
 ceph_syn_SOURCES = ceph_syn.cc client/SyntheticClient.cc # uses \
 	g_conf.. needs cleanup
 ceph_syn_LDADD = $(LIBCLIENT) $(CEPH_GLOBAL)
-rbd_SOURCES = rbd.cc
-rbd_LDADD = $(LIBRBD) $(LIBRADOS) $(CEPH_GLOBAL) -lblkid
+rbd_SOURCES = rbd.cc common/secret.c
+rbd_LDADD = $(LIBRBD) $(LIBRADOS) $(CEPH_GLOBAL) -lblkid $(KEYUTILS_LIB)
 
 # Fuse targets
 @WITH_FUSE_TRUE at ceph_fuse_SOURCES = ceph_fuse.cc
@@ -5587,8 +5816,6 @@ common/bloom_filter.lo: common/$(am__dirstamp) \
 	common/$(DEPDIR)/$(am__dirstamp)
 common/linux_version.lo: common/$(am__dirstamp) \
 	common/$(DEPDIR)/$(am__dirstamp)
-common/secret.lo: common/$(am__dirstamp) \
-	common/$(DEPDIR)/$(am__dirstamp)
 mon/$(am__dirstamp):
 	@$(MKDIR_P) mon
 	@: > mon/$(am__dirstamp)
@@ -5685,34 +5912,211 @@ erasure-code/jerasure/$(am__dirstamp):
 erasure-code/jerasure/$(DEPDIR)/$(am__dirstamp):
 	@$(MKDIR_P) erasure-code/jerasure/$(DEPDIR)
 	@: > erasure-code/jerasure/$(DEPDIR)/$(am__dirstamp)
-erasure-code/jerasure/libec_jerasure_la-ErasureCodePluginJerasure.lo:  \
+erasure-code/jerasure/libec_jerasure_la-ErasureCodePluginSelectJerasure.lo:  \
 	erasure-code/jerasure/$(am__dirstamp) \
 	erasure-code/jerasure/$(DEPDIR)/$(am__dirstamp)
-erasure-code/jerasure/libec_jerasure_la-ErasureCodeJerasure.lo:  \
+libec_jerasure.la: $(libec_jerasure_la_OBJECTS) $(libec_jerasure_la_DEPENDENCIES) $(EXTRA_libec_jerasure_la_DEPENDENCIES) 
+	$(AM_V_CXXLD)$(libec_jerasure_la_LINK) -rpath $(erasure_codelibdir) $(libec_jerasure_la_OBJECTS) $(libec_jerasure_la_LIBADD) $(LIBS)
+erasure-code/jerasure/jerasure/src/$(am__dirstamp):
+	@$(MKDIR_P) erasure-code/jerasure/jerasure/src
+	@: > erasure-code/jerasure/jerasure/src/$(am__dirstamp)
+erasure-code/jerasure/jerasure/src/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) erasure-code/jerasure/jerasure/src/$(DEPDIR)
+	@: > erasure-code/jerasure/jerasure/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-cauchy.lo:  \
+	erasure-code/jerasure/jerasure/src/$(am__dirstamp) \
+	erasure-code/jerasure/jerasure/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-galois.lo:  \
+	erasure-code/jerasure/jerasure/src/$(am__dirstamp) \
+	erasure-code/jerasure/jerasure/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-jerasure.lo:  \
+	erasure-code/jerasure/jerasure/src/$(am__dirstamp) \
+	erasure-code/jerasure/jerasure/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-liberation.lo:  \
+	erasure-code/jerasure/jerasure/src/$(am__dirstamp) \
+	erasure-code/jerasure/jerasure/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-reed_sol.lo:  \
+	erasure-code/jerasure/jerasure/src/$(am__dirstamp) \
+	erasure-code/jerasure/jerasure/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/$(am__dirstamp):
+	@$(MKDIR_P) erasure-code/jerasure/gf-complete/src
+	@: > erasure-code/jerasure/gf-complete/src/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) erasure-code/jerasure/gf-complete/src/$(DEPDIR)
+	@: > erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_wgen.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_method.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w16.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w32.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w64.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w128.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_general.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w4.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_rand.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w8.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/libec_jerasure_generic_la-ErasureCodePluginJerasure.lo:  \
 	erasure-code/jerasure/$(am__dirstamp) \
 	erasure-code/jerasure/$(DEPDIR)/$(am__dirstamp)
-erasure-code/jerasure/libec_jerasure_la-cauchy.lo:  \
+erasure-code/jerasure/libec_jerasure_generic_la-ErasureCodeJerasure.lo:  \
 	erasure-code/jerasure/$(am__dirstamp) \
 	erasure-code/jerasure/$(DEPDIR)/$(am__dirstamp)
-erasure-code/jerasure/libec_jerasure_la-galois.lo:  \
+libec_jerasure_generic.la: $(libec_jerasure_generic_la_OBJECTS) $(libec_jerasure_generic_la_DEPENDENCIES) $(EXTRA_libec_jerasure_generic_la_DEPENDENCIES) 
+	$(AM_V_CXXLD)$(libec_jerasure_generic_la_LINK) -rpath $(erasure_codelibdir) $(libec_jerasure_generic_la_OBJECTS) $(libec_jerasure_generic_la_LIBADD) $(LIBS)
+erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-cauchy.lo:  \
+	erasure-code/jerasure/jerasure/src/$(am__dirstamp) \
+	erasure-code/jerasure/jerasure/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-galois.lo:  \
+	erasure-code/jerasure/jerasure/src/$(am__dirstamp) \
+	erasure-code/jerasure/jerasure/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-jerasure.lo:  \
+	erasure-code/jerasure/jerasure/src/$(am__dirstamp) \
+	erasure-code/jerasure/jerasure/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-liberation.lo:  \
+	erasure-code/jerasure/jerasure/src/$(am__dirstamp) \
+	erasure-code/jerasure/jerasure/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-reed_sol.lo:  \
+	erasure-code/jerasure/jerasure/src/$(am__dirstamp) \
+	erasure-code/jerasure/jerasure/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_wgen.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_method.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w16.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w32.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w64.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w128.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_general.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w4.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_rand.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w8.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/libec_jerasure_sse3_la-ErasureCodePluginJerasure.lo:  \
 	erasure-code/jerasure/$(am__dirstamp) \
 	erasure-code/jerasure/$(DEPDIR)/$(am__dirstamp)
-erasure-code/jerasure/libec_jerasure_la-jerasure.lo:  \
+erasure-code/jerasure/libec_jerasure_sse3_la-ErasureCodeJerasure.lo:  \
 	erasure-code/jerasure/$(am__dirstamp) \
 	erasure-code/jerasure/$(DEPDIR)/$(am__dirstamp)
-erasure-code/jerasure/libec_jerasure_la-liberation.lo:  \
+libec_jerasure_sse3.la: $(libec_jerasure_sse3_la_OBJECTS) $(libec_jerasure_sse3_la_DEPENDENCIES) $(EXTRA_libec_jerasure_sse3_la_DEPENDENCIES) 
+	$(AM_V_CXXLD)$(libec_jerasure_sse3_la_LINK) -rpath $(erasure_codelibdir) $(libec_jerasure_sse3_la_OBJECTS) $(libec_jerasure_sse3_la_LIBADD) $(LIBS)
+erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-cauchy.lo:  \
+	erasure-code/jerasure/jerasure/src/$(am__dirstamp) \
+	erasure-code/jerasure/jerasure/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-galois.lo:  \
+	erasure-code/jerasure/jerasure/src/$(am__dirstamp) \
+	erasure-code/jerasure/jerasure/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-jerasure.lo:  \
+	erasure-code/jerasure/jerasure/src/$(am__dirstamp) \
+	erasure-code/jerasure/jerasure/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-liberation.lo:  \
+	erasure-code/jerasure/jerasure/src/$(am__dirstamp) \
+	erasure-code/jerasure/jerasure/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-reed_sol.lo:  \
+	erasure-code/jerasure/jerasure/src/$(am__dirstamp) \
+	erasure-code/jerasure/jerasure/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_wgen.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_method.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w16.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w32.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w64.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w128.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_general.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w4.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_rand.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w8.lo:  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/libec_jerasure_sse4_la-ErasureCodePluginJerasure.lo:  \
 	erasure-code/jerasure/$(am__dirstamp) \
 	erasure-code/jerasure/$(DEPDIR)/$(am__dirstamp)
-erasure-code/jerasure/libec_jerasure_la-reed_sol.lo:  \
+erasure-code/jerasure/libec_jerasure_sse4_la-ErasureCodeJerasure.lo:  \
 	erasure-code/jerasure/$(am__dirstamp) \
 	erasure-code/jerasure/$(DEPDIR)/$(am__dirstamp)
-libec_jerasure.la: $(libec_jerasure_la_OBJECTS) $(libec_jerasure_la_DEPENDENCIES) $(EXTRA_libec_jerasure_la_DEPENDENCIES) 
-	$(AM_V_CXXLD)$(libec_jerasure_la_LINK) -rpath $(erasure_codelibdir) $(libec_jerasure_la_OBJECTS) $(libec_jerasure_la_LIBADD) $(LIBS)
+libec_jerasure_sse4.la: $(libec_jerasure_sse4_la_OBJECTS) $(libec_jerasure_sse4_la_DEPENDENCIES) $(EXTRA_libec_jerasure_sse4_la_DEPENDENCIES) 
+	$(AM_V_CXXLD)$(libec_jerasure_sse4_la_LINK) -rpath $(erasure_codelibdir) $(libec_jerasure_sse4_la_OBJECTS) $(libec_jerasure_sse4_la_LIBADD) $(LIBS)
 test/erasure-code/libec_missing_entry_point_la-ErasureCodePluginMissingEntryPoint.lo:  \
 	test/erasure-code/$(am__dirstamp) \
 	test/erasure-code/$(DEPDIR)/$(am__dirstamp)
 libec_missing_entry_point.la: $(libec_missing_entry_point_la_OBJECTS) $(libec_missing_entry_point_la_DEPENDENCIES) $(EXTRA_libec_missing_entry_point_la_DEPENDENCIES) 
 	$(AM_V_CXXLD)$(libec_missing_entry_point_la_LINK) -rpath $(erasure_codelibdir) $(libec_missing_entry_point_la_OBJECTS) $(libec_missing_entry_point_la_LIBADD) $(LIBS)
+test/erasure-code/libec_test_jerasure_generic_la-TestJerasurePluginGeneric.lo:  \
+	test/erasure-code/$(am__dirstamp) \
+	test/erasure-code/$(DEPDIR)/$(am__dirstamp)
+libec_test_jerasure_generic.la: $(libec_test_jerasure_generic_la_OBJECTS) $(libec_test_jerasure_generic_la_DEPENDENCIES) $(EXTRA_libec_test_jerasure_generic_la_DEPENDENCIES) 
+	$(AM_V_CXXLD)$(libec_test_jerasure_generic_la_LINK) -rpath $(erasure_codelibdir) $(libec_test_jerasure_generic_la_OBJECTS) $(libec_test_jerasure_generic_la_LIBADD) $(LIBS)
+test/erasure-code/libec_test_jerasure_sse3_la-TestJerasurePluginSSE3.lo:  \
+	test/erasure-code/$(am__dirstamp) \
+	test/erasure-code/$(DEPDIR)/$(am__dirstamp)
+libec_test_jerasure_sse3.la: $(libec_test_jerasure_sse3_la_OBJECTS) $(libec_test_jerasure_sse3_la_DEPENDENCIES) $(EXTRA_libec_test_jerasure_sse3_la_DEPENDENCIES) 
+	$(AM_V_CXXLD)$(libec_test_jerasure_sse3_la_LINK) -rpath $(erasure_codelibdir) $(libec_test_jerasure_sse3_la_OBJECTS) $(libec_test_jerasure_sse3_la_LIBADD) $(LIBS)
+test/erasure-code/libec_test_jerasure_sse4_la-TestJerasurePluginSSE4.lo:  \
+	test/erasure-code/$(am__dirstamp) \
+	test/erasure-code/$(DEPDIR)/$(am__dirstamp)
+libec_test_jerasure_sse4.la: $(libec_test_jerasure_sse4_la_OBJECTS) $(libec_test_jerasure_sse4_la_DEPENDENCIES) $(EXTRA_libec_test_jerasure_sse4_la_DEPENDENCIES) 
+	$(AM_V_CXXLD)$(libec_test_jerasure_sse4_la_LINK) -rpath $(erasure_codelibdir) $(libec_test_jerasure_sse4_la_OBJECTS) $(libec_test_jerasure_sse4_la_LIBADD) $(LIBS)
 erasure-code/$(am__dirstamp):
 	@$(MKDIR_P) erasure-code
 	@: > erasure-code/$(am__dirstamp)
@@ -5792,6 +6196,7 @@ mds/SnapServer.lo: mds/$(am__dirstamp) mds/$(DEPDIR)/$(am__dirstamp)
 mds/snap.lo: mds/$(am__dirstamp) mds/$(DEPDIR)/$(am__dirstamp)
 mds/SessionMap.lo: mds/$(am__dirstamp) mds/$(DEPDIR)/$(am__dirstamp)
 mds/MDLog.lo: mds/$(am__dirstamp) mds/$(DEPDIR)/$(am__dirstamp)
+mds/MDSUtility.lo: mds/$(am__dirstamp) mds/$(DEPDIR)/$(am__dirstamp)
 libmds.la: $(libmds_la_OBJECTS) $(libmds_la_DEPENDENCIES) $(EXTRA_libmds_la_DEPENDENCIES) 
 	$(AM_V_CXXLD)$(CXXLINK)  $(libmds_la_OBJECTS) $(libmds_la_LIBADD) $(LIBS)
 mon/Monitor.lo: mon/$(am__dirstamp) mon/$(DEPDIR)/$(am__dirstamp)
@@ -6215,6 +6620,11 @@ tools/ceph_authtool.$(OBJEXT): tools/$(am__dirstamp) \
 ceph-authtool$(EXEEXT): $(ceph_authtool_OBJECTS) $(ceph_authtool_DEPENDENCIES) $(EXTRA_ceph_authtool_DEPENDENCIES) 
 	@rm -f ceph-authtool$(EXEEXT)
 	$(AM_V_CXXLD)$(CXXLINK) $(ceph_authtool_OBJECTS) $(ceph_authtool_LDADD) $(LIBS)
+tools/ceph-client-debug.$(OBJEXT): tools/$(am__dirstamp) \
+	tools/$(DEPDIR)/$(am__dirstamp)
+ceph-client-debug$(EXEEXT): $(ceph_client_debug_OBJECTS) $(ceph_client_debug_DEPENDENCIES) $(EXTRA_ceph_client_debug_DEPENDENCIES) 
+	@rm -f ceph-client-debug$(EXEEXT)
+	$(AM_V_CXXLD)$(CXXLINK) $(ceph_client_debug_OBJECTS) $(ceph_client_debug_LDADD) $(LIBS)
 tools/ceph_conf.$(OBJEXT): tools/$(am__dirstamp) \
 	tools/$(DEPDIR)/$(am__dirstamp)
 ceph-conf$(EXEEXT): $(ceph_conf_OBJECTS) $(ceph_conf_DEPENDENCIES) $(EXTRA_ceph_conf_DEPENDENCIES) 
@@ -6245,7 +6655,7 @@ ceph-dencoder$(EXEEXT): $(ceph_dencoder_OBJECTS) $(ceph_dencoder_DEPENDENCIES) $
 ceph-fuse$(EXEEXT): $(ceph_fuse_OBJECTS) $(ceph_fuse_DEPENDENCIES) $(EXTRA_ceph_fuse_DEPENDENCIES) 
 	@rm -f ceph-fuse$(EXEEXT)
 	$(AM_V_CXXLD)$(CXXLINK) $(ceph_fuse_OBJECTS) $(ceph_fuse_LDADD) $(LIBS)
-tools/ceph_kvstore_tool-ceph-kvstore-tool.$(OBJEXT):  \
+tools/ceph_kvstore_tool-ceph_kvstore_tool.$(OBJEXT):  \
 	tools/$(am__dirstamp) tools/$(DEPDIR)/$(am__dirstamp)
 ceph-kvstore-tool$(EXEEXT): $(ceph_kvstore_tool_OBJECTS) $(ceph_kvstore_tool_DEPENDENCIES) $(EXTRA_ceph_kvstore_tool_DEPENDENCIES) 
 	@rm -f ceph-kvstore-tool$(EXEEXT)
@@ -6256,7 +6666,7 @@ ceph-mds$(EXEEXT): $(ceph_mds_OBJECTS) $(ceph_mds_DEPENDENCIES) $(EXTRA_ceph_mds
 ceph-mon$(EXEEXT): $(ceph_mon_OBJECTS) $(ceph_mon_DEPENDENCIES) $(EXTRA_ceph_mon_DEPENDENCIES) 
 	@rm -f ceph-mon$(EXEEXT)
 	$(AM_V_CXXLD)$(CXXLINK) $(ceph_mon_OBJECTS) $(ceph_mon_LDADD) $(LIBS)
-tools/ceph-monstore-tool.$(OBJEXT): tools/$(am__dirstamp) \
+tools/ceph_monstore_tool.$(OBJEXT): tools/$(am__dirstamp) \
 	tools/$(DEPDIR)/$(am__dirstamp)
 ceph-monstore-tool$(EXEEXT): $(ceph_monstore_tool_OBJECTS) $(ceph_monstore_tool_DEPENDENCIES) $(EXTRA_ceph_monstore_tool_DEPENDENCIES) 
 	@rm -f ceph-monstore-tool$(EXEEXT)
@@ -6264,7 +6674,7 @@ ceph-monstore-tool$(EXEEXT): $(ceph_monstore_tool_OBJECTS) $(ceph_monstore_tool_
 ceph-osd$(EXEEXT): $(ceph_osd_OBJECTS) $(ceph_osd_DEPENDENCIES) $(EXTRA_ceph_osd_DEPENDENCIES) 
 	@rm -f ceph-osd$(EXEEXT)
 	$(AM_V_CXXLD)$(CXXLINK) $(ceph_osd_OBJECTS) $(ceph_osd_LDADD) $(LIBS)
-tools/ceph-osdomap-tool.$(OBJEXT): tools/$(am__dirstamp) \
+tools/ceph_osdomap_tool.$(OBJEXT): tools/$(am__dirstamp) \
 	tools/$(DEPDIR)/$(am__dirstamp)
 ceph-osdomap-tool$(EXEEXT): $(ceph_osdomap_tool_OBJECTS) $(ceph_osdomap_tool_DEPENDENCIES) $(EXTRA_ceph_osdomap_tool_DEPENDENCIES) 
 	@rm -f ceph-osdomap-tool$(EXEEXT)
@@ -6302,12 +6712,12 @@ test/erasure-code/ceph_erasure_code_benchmark.$(OBJEXT):  \
 ceph_erasure_code_benchmark$(EXEEXT): $(ceph_erasure_code_benchmark_OBJECTS) $(ceph_erasure_code_benchmark_DEPENDENCIES) $(EXTRA_ceph_erasure_code_benchmark_DEPENDENCIES) 
 	@rm -f ceph_erasure_code_benchmark$(EXEEXT)
 	$(AM_V_CXXLD)$(CXXLINK) $(ceph_erasure_code_benchmark_OBJECTS) $(ceph_erasure_code_benchmark_LDADD) $(LIBS)
-tools/ceph-filestore-dump.$(OBJEXT): tools/$(am__dirstamp) \
+tools/ceph_filestore_dump.$(OBJEXT): tools/$(am__dirstamp) \
 	tools/$(DEPDIR)/$(am__dirstamp)
 ceph_filestore_dump$(EXEEXT): $(ceph_filestore_dump_OBJECTS) $(ceph_filestore_dump_DEPENDENCIES) $(EXTRA_ceph_filestore_dump_DEPENDENCIES) 
 	@rm -f ceph_filestore_dump$(EXEEXT)
 	$(AM_V_CXXLD)$(CXXLINK) $(ceph_filestore_dump_OBJECTS) $(ceph_filestore_dump_LDADD) $(LIBS)
-tools/ceph-filestore-tool.$(OBJEXT): tools/$(am__dirstamp) \
+tools/ceph_filestore_tool.$(OBJEXT): tools/$(am__dirstamp) \
 	tools/$(DEPDIR)/$(am__dirstamp)
 ceph_filestore_tool$(EXEEXT): $(ceph_filestore_tool_OBJECTS) $(ceph_filestore_tool_DEPENDENCIES) $(EXTRA_ceph_filestore_tool_DEPENDENCIES) 
 	@rm -f ceph_filestore_tool$(EXEEXT)
@@ -6955,6 +7365,8 @@ mount/$(DEPDIR)/$(am__dirstamp):
 	@: > mount/$(DEPDIR)/$(am__dirstamp)
 mount/mount.ceph.$(OBJEXT): mount/$(am__dirstamp) \
 	mount/$(DEPDIR)/$(am__dirstamp)
+common/secret.$(OBJEXT): common/$(am__dirstamp) \
+	common/$(DEPDIR)/$(am__dirstamp)
 mount.ceph$(EXEEXT): $(mount_ceph_OBJECTS) $(mount_ceph_DEPENDENCIES) $(EXTRA_mount_ceph_DEPENDENCIES) 
 	@rm -f mount.ceph$(EXEEXT)
 	$(AM_V_CCLD)$(LINK) $(mount_ceph_OBJECTS) $(mount_ceph_LDADD) $(LIBS)
@@ -7214,8 +7626,6 @@ common/test_build_libcommon-bloom_filter.$(OBJEXT):  \
 	common/$(am__dirstamp) common/$(DEPDIR)/$(am__dirstamp)
 common/test_build_libcommon-linux_version.$(OBJEXT):  \
 	common/$(am__dirstamp) common/$(DEPDIR)/$(am__dirstamp)
-common/test_build_libcommon-secret.$(OBJEXT): common/$(am__dirstamp) \
-	common/$(DEPDIR)/$(am__dirstamp)
 mon/test_build_libcommon-MonCap.$(OBJEXT): mon/$(am__dirstamp) \
 	mon/$(DEPDIR)/$(am__dirstamp)
 mon/test_build_libcommon-MonClient.$(OBJEXT): mon/$(am__dirstamp) \
@@ -7421,6 +7831,11 @@ test/unittest_crypto-crypto.$(OBJEXT): test/$(am__dirstamp) \
 unittest_crypto$(EXEEXT): $(unittest_crypto_OBJECTS) $(unittest_crypto_DEPENDENCIES) $(EXTRA_unittest_crypto_DEPENDENCIES) 
 	@rm -f unittest_crypto$(EXEEXT)
 	$(AM_V_CXXLD)$(unittest_crypto_LINK) $(unittest_crypto_OBJECTS) $(unittest_crypto_LDADD) $(LIBS)
+test/unittest_crypto_init-crypto_init.$(OBJEXT): test/$(am__dirstamp) \
+	test/$(DEPDIR)/$(am__dirstamp)
+unittest_crypto_init$(EXEEXT): $(unittest_crypto_init_OBJECTS) $(unittest_crypto_init_DEPENDENCIES) $(EXTRA_unittest_crypto_init_DEPENDENCIES) 
+	@rm -f unittest_crypto_init$(EXEEXT)
+	$(AM_V_CXXLD)$(unittest_crypto_init_LINK) $(unittest_crypto_init_OBJECTS) $(unittest_crypto_init_LDADD) $(LIBS)
 test/unittest_daemon_config-daemon_config.$(OBJEXT):  \
 	test/$(am__dirstamp) test/$(DEPDIR)/$(am__dirstamp)
 unittest_daemon_config$(EXEEXT): $(unittest_daemon_config_OBJECTS) $(unittest_daemon_config_DEPENDENCIES) $(EXTRA_unittest_daemon_config_DEPENDENCIES) 
@@ -7445,27 +7860,60 @@ unittest_erasure_code_example$(EXEEXT): $(unittest_erasure_code_example_OBJECTS)
 test/erasure-code/unittest_erasure_code_jerasure-TestErasureCodeJerasure.$(OBJEXT):  \
 	test/erasure-code/$(am__dirstamp) \
 	test/erasure-code/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-cauchy.$(OBJEXT):  \
+	erasure-code/jerasure/jerasure/src/$(am__dirstamp) \
+	erasure-code/jerasure/jerasure/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-galois.$(OBJEXT):  \
+	erasure-code/jerasure/jerasure/src/$(am__dirstamp) \
+	erasure-code/jerasure/jerasure/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-jerasure.$(OBJEXT):  \
+	erasure-code/jerasure/jerasure/src/$(am__dirstamp) \
+	erasure-code/jerasure/jerasure/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-liberation.$(OBJEXT):  \
+	erasure-code/jerasure/jerasure/src/$(am__dirstamp) \
+	erasure-code/jerasure/jerasure/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-reed_sol.$(OBJEXT):  \
+	erasure-code/jerasure/jerasure/src/$(am__dirstamp) \
+	erasure-code/jerasure/jerasure/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_wgen.$(OBJEXT):  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_method.$(OBJEXT):  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w16.$(OBJEXT):  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf.$(OBJEXT):  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w32.$(OBJEXT):  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w64.$(OBJEXT):  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w128.$(OBJEXT):  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_general.$(OBJEXT):  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w4.$(OBJEXT):  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_rand.$(OBJEXT):  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w8.$(OBJEXT):  \
+	erasure-code/jerasure/gf-complete/src/$(am__dirstamp) \
+	erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
 erasure-code/jerasure/unittest_erasure_code_jerasure-ErasureCodePluginJerasure.$(OBJEXT):  \
 	erasure-code/jerasure/$(am__dirstamp) \
 	erasure-code/jerasure/$(DEPDIR)/$(am__dirstamp)
 erasure-code/jerasure/unittest_erasure_code_jerasure-ErasureCodeJerasure.$(OBJEXT):  \
 	erasure-code/jerasure/$(am__dirstamp) \
 	erasure-code/jerasure/$(DEPDIR)/$(am__dirstamp)
-erasure-code/jerasure/cauchy.$(OBJEXT):  \
-	erasure-code/jerasure/$(am__dirstamp) \
-	erasure-code/jerasure/$(DEPDIR)/$(am__dirstamp)
-erasure-code/jerasure/galois.$(OBJEXT):  \
-	erasure-code/jerasure/$(am__dirstamp) \
-	erasure-code/jerasure/$(DEPDIR)/$(am__dirstamp)
-erasure-code/jerasure/jerasure.$(OBJEXT):  \
-	erasure-code/jerasure/$(am__dirstamp) \
-	erasure-code/jerasure/$(DEPDIR)/$(am__dirstamp)
-erasure-code/jerasure/liberation.$(OBJEXT):  \
-	erasure-code/jerasure/$(am__dirstamp) \
-	erasure-code/jerasure/$(DEPDIR)/$(am__dirstamp)
-erasure-code/jerasure/reed_sol.$(OBJEXT):  \
-	erasure-code/jerasure/$(am__dirstamp) \
-	erasure-code/jerasure/$(DEPDIR)/$(am__dirstamp)
 unittest_erasure_code_jerasure$(EXEEXT): $(unittest_erasure_code_jerasure_OBJECTS) $(unittest_erasure_code_jerasure_DEPENDENCIES) $(EXTRA_unittest_erasure_code_jerasure_DEPENDENCIES) 
 	@rm -f unittest_erasure_code_jerasure$(EXEEXT)
 	$(AM_V_CXXLD)$(unittest_erasure_code_jerasure_LINK) $(unittest_erasure_code_jerasure_OBJECTS) $(unittest_erasure_code_jerasure_LDADD) $(LIBS)
@@ -8119,7 +8567,6 @@ mostlyclean-compile:
 	-rm -f common/safe_io.$(OBJEXT)
 	-rm -f common/safe_io.lo
 	-rm -f common/secret.$(OBJEXT)
-	-rm -f common/secret.lo
 	-rm -f common/signal.$(OBJEXT)
 	-rm -f common/signal.lo
 	-rm -f common/simple_spin.$(OBJEXT)
@@ -8192,7 +8639,6 @@ mostlyclean-compile:
 	-rm -f common/test_build_libcommon-pipe.$(OBJEXT)
 	-rm -f common/test_build_libcommon-run_cmd.$(OBJEXT)
 	-rm -f common/test_build_libcommon-safe_io.$(OBJEXT)
-	-rm -f common/test_build_libcommon-secret.$(OBJEXT)
 	-rm -f common/test_build_libcommon-signal.$(OBJEXT)
 	-rm -f common/test_build_libcommon-simple_spin.$(OBJEXT)
 	-rm -f common/test_build_libcommon-snap_types.$(OBJEXT)
@@ -8227,25 +8673,132 @@ mostlyclean-compile:
 	-rm -f crush/mapper.lo
 	-rm -f erasure-code/ErasureCodePlugin.$(OBJEXT)
 	-rm -f erasure-code/ErasureCodePlugin.lo
-	-rm -f erasure-code/jerasure/cauchy.$(OBJEXT)
-	-rm -f erasure-code/jerasure/galois.$(OBJEXT)
-	-rm -f erasure-code/jerasure/jerasure.$(OBJEXT)
-	-rm -f erasure-code/jerasure/libec_jerasure_la-ErasureCodeJerasure.$(OBJEXT)
-	-rm -f erasure-code/jerasure/libec_jerasure_la-ErasureCodeJerasure.lo
-	-rm -f erasure-code/jerasure/libec_jerasure_la-ErasureCodePluginJerasure.$(OBJEXT)
-	-rm -f erasure-code/jerasure/libec_jerasure_la-ErasureCodePluginJerasure.lo
-	-rm -f erasure-code/jerasure/libec_jerasure_la-cauchy.$(OBJEXT)
-	-rm -f erasure-code/jerasure/libec_jerasure_la-cauchy.lo
-	-rm -f erasure-code/jerasure/libec_jerasure_la-galois.$(OBJEXT)
-	-rm -f erasure-code/jerasure/libec_jerasure_la-galois.lo
-	-rm -f erasure-code/jerasure/libec_jerasure_la-jerasure.$(OBJEXT)
-	-rm -f erasure-code/jerasure/libec_jerasure_la-jerasure.lo
-	-rm -f erasure-code/jerasure/libec_jerasure_la-liberation.$(OBJEXT)
-	-rm -f erasure-code/jerasure/libec_jerasure_la-liberation.lo
-	-rm -f erasure-code/jerasure/libec_jerasure_la-reed_sol.$(OBJEXT)
-	-rm -f erasure-code/jerasure/libec_jerasure_la-reed_sol.lo
-	-rm -f erasure-code/jerasure/liberation.$(OBJEXT)
-	-rm -f erasure-code/jerasure/reed_sol.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_general.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_general.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_method.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_method.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_rand.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_rand.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w128.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w128.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w16.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w16.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w32.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w32.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w4.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w4.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w64.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w64.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w8.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w8.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_wgen.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_wgen.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_general.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_general.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_method.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_method.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_rand.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_rand.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w128.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w128.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w16.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w16.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w32.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w32.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w4.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w4.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w64.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w64.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w8.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w8.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_wgen.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_wgen.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_general.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_general.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_method.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_method.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_rand.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_rand.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w128.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w128.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w16.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w16.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w32.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w32.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w4.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w4.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w64.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w64.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w8.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w8.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_wgen.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_wgen.lo
+	-rm -f erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_general.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_method.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_rand.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w128.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w16.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w32.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w4.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w64.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w8.$(OBJEXT)
+	-rm -f erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_wgen.$(OBJEXT)
+	-rm -f erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-cauchy.$(OBJEXT)
+	-rm -f erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-cauchy.lo
+	-rm -f erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-galois.$(OBJEXT)
+	-rm -f erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-galois.lo
+	-rm -f erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-jerasure.$(OBJEXT)
+	-rm -f erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-jerasure.lo
+	-rm -f erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-liberation.$(OBJEXT)
+	-rm -f erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-liberation.lo
+	-rm -f erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-reed_sol.$(OBJEXT)
+	-rm -f erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-reed_sol.lo
+	-rm -f erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-cauchy.$(OBJEXT)
+	-rm -f erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-cauchy.lo
+	-rm -f erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-galois.$(OBJEXT)
+	-rm -f erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-galois.lo
+	-rm -f erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-jerasure.$(OBJEXT)
+	-rm -f erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-jerasure.lo
+	-rm -f erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-liberation.$(OBJEXT)
+	-rm -f erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-liberation.lo
+	-rm -f erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-reed_sol.$(OBJEXT)
+	-rm -f erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-reed_sol.lo
+	-rm -f erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-cauchy.$(OBJEXT)
+	-rm -f erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-cauchy.lo
+	-rm -f erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-galois.$(OBJEXT)
+	-rm -f erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-galois.lo
+	-rm -f erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-jerasure.$(OBJEXT)
+	-rm -f erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-jerasure.lo
+	-rm -f erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-liberation.$(OBJEXT)
+	-rm -f erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-liberation.lo
+	-rm -f erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-reed_sol.$(OBJEXT)
+	-rm -f erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-reed_sol.lo
+	-rm -f erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-cauchy.$(OBJEXT)
+	-rm -f erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-galois.$(OBJEXT)
+	-rm -f erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-jerasure.$(OBJEXT)
+	-rm -f erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-liberation.$(OBJEXT)
+	-rm -f erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-reed_sol.$(OBJEXT)
+	-rm -f erasure-code/jerasure/libec_jerasure_generic_la-ErasureCodeJerasure.$(OBJEXT)
+	-rm -f erasure-code/jerasure/libec_jerasure_generic_la-ErasureCodeJerasure.lo
+	-rm -f erasure-code/jerasure/libec_jerasure_generic_la-ErasureCodePluginJerasure.$(OBJEXT)
+	-rm -f erasure-code/jerasure/libec_jerasure_generic_la-ErasureCodePluginJerasure.lo
+	-rm -f erasure-code/jerasure/libec_jerasure_la-ErasureCodePluginSelectJerasure.$(OBJEXT)
+	-rm -f erasure-code/jerasure/libec_jerasure_la-ErasureCodePluginSelectJerasure.lo
+	-rm -f erasure-code/jerasure/libec_jerasure_sse3_la-ErasureCodeJerasure.$(OBJEXT)
+	-rm -f erasure-code/jerasure/libec_jerasure_sse3_la-ErasureCodeJerasure.lo
+	-rm -f erasure-code/jerasure/libec_jerasure_sse3_la-ErasureCodePluginJerasure.$(OBJEXT)
+	-rm -f erasure-code/jerasure/libec_jerasure_sse3_la-ErasureCodePluginJerasure.lo
+	-rm -f erasure-code/jerasure/libec_jerasure_sse4_la-ErasureCodeJerasure.$(OBJEXT)
+	-rm -f erasure-code/jerasure/libec_jerasure_sse4_la-ErasureCodeJerasure.lo
+	-rm -f erasure-code/jerasure/libec_jerasure_sse4_la-ErasureCodePluginJerasure.$(OBJEXT)
+	-rm -f erasure-code/jerasure/libec_jerasure_sse4_la-ErasureCodePluginJerasure.lo
 	-rm -f erasure-code/jerasure/unittest_erasure_code_jerasure-ErasureCodeJerasure.$(OBJEXT)
 	-rm -f erasure-code/jerasure/unittest_erasure_code_jerasure-ErasureCodePluginJerasure.$(OBJEXT)
 	-rm -f global/global_context.$(OBJEXT)
@@ -8336,6 +8889,8 @@ mostlyclean-compile:
 	-rm -f mds/MDSTableClient.lo
 	-rm -f mds/MDSTableServer.$(OBJEXT)
 	-rm -f mds/MDSTableServer.lo
+	-rm -f mds/MDSUtility.$(OBJEXT)
+	-rm -f mds/MDSUtility.lo
 	-rm -f mds/Migrator.$(OBJEXT)
 	-rm -f mds/Migrator.lo
 	-rm -f mds/Mutation.$(OBJEXT)
@@ -8720,6 +9275,12 @@ mostlyclean-compile:
 	-rm -f test/erasure-code/libec_hangs_la-ErasureCodePluginHangs.lo
 	-rm -f test/erasure-code/libec_missing_entry_point_la-ErasureCodePluginMissingEntryPoint.$(OBJEXT)
 	-rm -f test/erasure-code/libec_missing_entry_point_la-ErasureCodePluginMissingEntryPoint.lo
+	-rm -f test/erasure-code/libec_test_jerasure_generic_la-TestJerasurePluginGeneric.$(OBJEXT)
+	-rm -f test/erasure-code/libec_test_jerasure_generic_la-TestJerasurePluginGeneric.lo
+	-rm -f test/erasure-code/libec_test_jerasure_sse3_la-TestJerasurePluginSSE3.$(OBJEXT)
+	-rm -f test/erasure-code/libec_test_jerasure_sse3_la-TestJerasurePluginSSE3.lo
+	-rm -f test/erasure-code/libec_test_jerasure_sse4_la-TestJerasurePluginSSE4.$(OBJEXT)
+	-rm -f test/erasure-code/libec_test_jerasure_sse4_la-TestJerasurePluginSSE4.lo
 	-rm -f test/erasure-code/unittest_erasure_code_example-TestErasureCodeExample.$(OBJEXT)
 	-rm -f test/erasure-code/unittest_erasure_code_jerasure-TestErasureCodeJerasure.$(OBJEXT)
 	-rm -f test/erasure-code/unittest_erasure_code_plugin-TestErasureCodePlugin.$(OBJEXT)
@@ -8821,6 +9382,7 @@ mostlyclean-compile:
 	-rm -f test/unittest_ceph_crypto-ceph_crypto.$(OBJEXT)
 	-rm -f test/unittest_confutils-confutils.$(OBJEXT)
 	-rm -f test/unittest_crypto-crypto.$(OBJEXT)
+	-rm -f test/unittest_crypto_init-crypto_init.$(OBJEXT)
 	-rm -f test/unittest_daemon_config-daemon_config.$(OBJEXT)
 	-rm -f test/unittest_encoding-encoding.$(OBJEXT)
 	-rm -f test/unittest_escape-escape.$(OBJEXT)
@@ -8841,13 +9403,14 @@ mostlyclean-compile:
 	-rm -f test/unittest_texttable-test_texttable.$(OBJEXT)
 	-rm -f test/unittest_utf8-utf8.$(OBJEXT)
 	-rm -f test/unittest_workqueue-test_workqueue.$(OBJEXT)
-	-rm -f tools/ceph-filestore-dump.$(OBJEXT)
-	-rm -f tools/ceph-filestore-tool.$(OBJEXT)
-	-rm -f tools/ceph-monstore-tool.$(OBJEXT)
-	-rm -f tools/ceph-osdomap-tool.$(OBJEXT)
+	-rm -f tools/ceph-client-debug.$(OBJEXT)
 	-rm -f tools/ceph_authtool.$(OBJEXT)
 	-rm -f tools/ceph_conf.$(OBJEXT)
-	-rm -f tools/ceph_kvstore_tool-ceph-kvstore-tool.$(OBJEXT)
+	-rm -f tools/ceph_filestore_dump.$(OBJEXT)
+	-rm -f tools/ceph_filestore_tool.$(OBJEXT)
+	-rm -f tools/ceph_kvstore_tool-ceph_kvstore_tool.$(OBJEXT)
+	-rm -f tools/ceph_monstore_tool.$(OBJEXT)
+	-rm -f tools/ceph_osdomap_tool.$(OBJEXT)
 	-rm -f tools/crushtool.$(OBJEXT)
 	-rm -f tools/dupstore.$(OBJEXT)
 	-rm -f tools/mon_store_converter.$(OBJEXT)
@@ -9005,7 +9568,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at common/$(DEPDIR)/rest_bench-obj_bencher.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at common/$(DEPDIR)/run_cmd.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at common/$(DEPDIR)/safe_io.Plo at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at common/$(DEPDIR)/secret.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at common/$(DEPDIR)/secret.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at common/$(DEPDIR)/signal.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at common/$(DEPDIR)/simple_spin.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at common/$(DEPDIR)/snap_types.Plo at am__quote@
@@ -9072,7 +9635,6 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at common/$(DEPDIR)/test_build_libcommon-pipe.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at common/$(DEPDIR)/test_build_libcommon-run_cmd.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at common/$(DEPDIR)/test_build_libcommon-safe_io.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at common/$(DEPDIR)/test_build_libcommon-secret.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at common/$(DEPDIR)/test_build_libcommon-signal.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at common/$(DEPDIR)/test_build_libcommon-simple_spin.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at common/$(DEPDIR)/test_build_libcommon-snap_types.Po at am__quote@
@@ -9095,20 +9657,79 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at crush/$(DEPDIR)/hash.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at crush/$(DEPDIR)/mapper.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at erasure-code/$(DEPDIR)/ErasureCodePlugin.Plo at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/$(DEPDIR)/cauchy.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/$(DEPDIR)/galois.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/$(DEPDIR)/jerasure.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/$(DEPDIR)/libec_jerasure_la-ErasureCodeJerasure.Plo at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/$(DEPDIR)/libec_jerasure_la-ErasureCodePluginJerasure.Plo at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/$(DEPDIR)/libec_jerasure_la-cauchy.Plo at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/$(DEPDIR)/libec_jerasure_la-galois.Plo at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/$(DEPDIR)/libec_jerasure_la-jerasure.Plo at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/$(DEPDIR)/libec_jerasure_la-liberation.Plo at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/$(DEPDIR)/libec_jerasure_la-reed_sol.Plo at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/$(DEPDIR)/liberation.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/$(DEPDIR)/reed_sol.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/$(DEPDIR)/libec_jerasure_generic_la-ErasureCodeJerasure.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/$(DEPDIR)/libec_jerasure_generic_la-ErasureCodePluginJerasure.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/$(DEPDIR)/libec_jerasure_la-ErasureCodePluginSelectJerasure.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/$(DEPDIR)/libec_jerasure_sse3_la-ErasureCodeJerasure.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/$(DEPDIR)/libec_jerasure_sse3_la-ErasureCodePluginJerasure.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/$(DEPDIR)/libec_jerasure_sse4_la-ErasureCodeJerasure.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/$(DEPDIR)/libec_jerasure_sse4_la-ErasureCodePluginJerasure.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/$(DEPDIR)/unittest_erasure_code_jerasure-ErasureCodeJerasure.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/$(DEPDIR)/unittest_erasure_code_jerasure-ErasureCodePluginJerasure.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_general.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_method.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_rand.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_w128.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_w16.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_w32.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_w4.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_w64.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_w8.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_wgen.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_general.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_method.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_rand.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_w128.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_w16.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_w32.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_w4.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_w64.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_w8.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_wgen.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_general.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_method.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_rand.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_w128.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_w16.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_w32.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_w4.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_w64.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_w8.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_wgen.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_general.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_method.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_rand.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w128.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w16.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w32.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w4.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w64.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w8.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_wgen.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_generic_la-cauchy.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_generic_la-galois.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_generic_la-jerasure.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_generic_la-liberation.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_generic_la-reed_sol.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse3_la-cauchy.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse3_la-galois.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse3_la-jerasure.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse3_la-liberation.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse3_la-reed_sol.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse4_la-cauchy.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse4_la-galois.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse4_la-jerasure.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse4_la-liberation.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse4_la-reed_sol.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-cauchy.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-galois.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-jerasure.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-liberation.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-reed_sol.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at global/$(DEPDIR)/global_context.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at global/$(DEPDIR)/global_init.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at global/$(DEPDIR)/pidfile.Plo at am__quote@
@@ -9156,6 +9777,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at mds/$(DEPDIR)/MDSTable.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at mds/$(DEPDIR)/MDSTableClient.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at mds/$(DEPDIR)/MDSTableServer.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at mds/$(DEPDIR)/MDSUtility.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at mds/$(DEPDIR)/Migrator.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at mds/$(DEPDIR)/Mutation.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at mds/$(DEPDIR)/Resetter.Plo at am__quote@
@@ -9397,6 +10019,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at test/$(DEPDIR)/unittest_ceph_crypto-ceph_crypto.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test/$(DEPDIR)/unittest_confutils-confutils.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test/$(DEPDIR)/unittest_crypto-crypto.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at test/$(DEPDIR)/unittest_crypto_init-crypto_init.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test/$(DEPDIR)/unittest_daemon_config-daemon_config.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test/$(DEPDIR)/unittest_encoding-encoding.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test/$(DEPDIR)/unittest_escape-escape.Po at am__quote@
@@ -9464,6 +10087,9 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at test/erasure-code/$(DEPDIR)/libec_fail_to_register_la-ErasureCodePluginFailToRegister.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test/erasure-code/$(DEPDIR)/libec_hangs_la-ErasureCodePluginHangs.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test/erasure-code/$(DEPDIR)/libec_missing_entry_point_la-ErasureCodePluginMissingEntryPoint.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at test/erasure-code/$(DEPDIR)/libec_test_jerasure_generic_la-TestJerasurePluginGeneric.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at test/erasure-code/$(DEPDIR)/libec_test_jerasure_sse3_la-TestJerasurePluginSSE3.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at test/erasure-code/$(DEPDIR)/libec_test_jerasure_sse4_la-TestJerasurePluginSSE4.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test/erasure-code/$(DEPDIR)/unittest_erasure_code_example-TestErasureCodeExample.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test/erasure-code/$(DEPDIR)/unittest_erasure_code_jerasure-TestErasureCodeJerasure.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test/erasure-code/$(DEPDIR)/unittest_erasure_code_plugin-TestErasureCodePlugin.Po at am__quote@
@@ -9532,13 +10158,14 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at test/system/$(DEPDIR)/st_rados_watch.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test/system/$(DEPDIR)/systest_runnable.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test/system/$(DEPDIR)/systest_settings.Plo at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at tools/$(DEPDIR)/ceph-filestore-dump.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at tools/$(DEPDIR)/ceph-filestore-tool.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at tools/$(DEPDIR)/ceph-monstore-tool.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at tools/$(DEPDIR)/ceph-osdomap-tool.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at tools/$(DEPDIR)/ceph-client-debug.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at tools/$(DEPDIR)/ceph_authtool.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at tools/$(DEPDIR)/ceph_conf.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at tools/$(DEPDIR)/ceph_kvstore_tool-ceph-kvstore-tool.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at tools/$(DEPDIR)/ceph_filestore_dump.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at tools/$(DEPDIR)/ceph_filestore_tool.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at tools/$(DEPDIR)/ceph_kvstore_tool-ceph_kvstore_tool.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at tools/$(DEPDIR)/ceph_monstore_tool.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at tools/$(DEPDIR)/ceph_osdomap_tool.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at tools/$(DEPDIR)/crushtool.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at tools/$(DEPDIR)/dupstore.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at tools/$(DEPDIR)/mon_store_converter.Po at am__quote@
@@ -9637,40 +10264,341 @@ common/libcommon_crc_la-crc32c_intel_fast.lo: common/crc32c_intel_fast.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libcommon_crc_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libcommon_crc_la-crc32c_intel_fast.lo `test -f 'common/crc32c_intel_fast.c' || echo '$(srcdir)/'`common/crc32c_intel_fast.c
 
-erasure-code/jerasure/libec_jerasure_la-cauchy.lo: erasure-code/jerasure/cauchy.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/libec_jerasure_la-cauchy.lo -MD -MP -MF erasure-code/jerasure/$(DEPDIR)/libec_jerasure_la-cauchy.Tpo -c -o erasure-code/jerasure/libec_jerasure_la-cauchy.lo `test -f 'erasure-code/jerasure/cauchy.c' || echo '$(srcdir)/'`erasure-code/jerasure/cauchy.c
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/$(DEPDIR)/libec_jerasure_la-cauchy.Tpo erasure-code/jerasure/$(DEPDIR)/libec_jerasure_la-cauchy.Plo
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/cauchy.c' object='erasure-code/jerasure/libec_jerasure_la-cauchy.lo' libtool=yes @AMDEPBACKSLASH@
+erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-cauchy.lo: erasure-code/jerasure/jerasure/src/cauchy.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-cauchy.lo -MD -MP -MF erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_generic_la-cauchy.Tpo -c -o erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-cauchy.lo `test -f 'erasu [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_generic_la-cauchy.Tpo erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_generic_la-cauchy.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/jerasure/src/cauchy.c' object='erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-cauchy.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-cauchy.lo `test -f 'erasure-code/jerasure/jerasure/src/cauchy.c' || echo '$(srcdir)/'`erasure-code/jerasure/jerasure/src/cauchy.c
+
+erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-galois.lo: erasure-code/jerasure/jerasure/src/galois.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-galois.lo -MD -MP -MF erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_generic_la-galois.Tpo -c -o erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-galois.lo `test -f 'erasu [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_generic_la-galois.Tpo erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_generic_la-galois.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/jerasure/src/galois.c' object='erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-galois.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-galois.lo `test -f 'erasure-code/jerasure/jerasure/src/galois.c' || echo '$(srcdir)/'`erasure-code/jerasure/jerasure/src/galois.c
+
+erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-jerasure.lo: erasure-code/jerasure/jerasure/src/jerasure.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-jerasure.lo -MD -MP -MF erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_generic_la-jerasure.Tpo -c -o erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-jerasure.lo `test -f  [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_generic_la-jerasure.Tpo erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_generic_la-jerasure.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/jerasure/src/jerasure.c' object='erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-jerasure.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-jerasure.lo `test -f 'erasure-code/jerasure/jerasure/src/jerasure.c' || echo '$(srcdir)/'`erasure-code/jerasure/jerasure/src/jerasure.c
+
+erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-liberation.lo: erasure-code/jerasure/jerasure/src/liberation.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-liberation.lo -MD -MP -MF erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_generic_la-liberation.Tpo -c -o erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-liberation.lo `te [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_generic_la-liberation.Tpo erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_generic_la-liberation.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/jerasure/src/liberation.c' object='erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-liberation.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-liberation.lo `test -f 'erasure-code/jerasure/jerasure/src/liberation.c' || echo '$(srcdir)/'`erasure-code/jerasure/jerasure/src/liberation.c
+
+erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-reed_sol.lo: erasure-code/jerasure/jerasure/src/reed_sol.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-reed_sol.lo -MD -MP -MF erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_generic_la-reed_sol.Tpo -c -o erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-reed_sol.lo `test -f  [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_generic_la-reed_sol.Tpo erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_generic_la-reed_sol.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/jerasure/src/reed_sol.c' object='erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-reed_sol.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/jerasure/src/libec_jerasure_generic_la-reed_sol.lo `test -f 'erasure-code/jerasure/jerasure/src/reed_sol.c' || echo '$(srcdir)/'`erasure-code/jerasure/jerasure/src/reed_sol.c
+
+erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_wgen.lo: erasure-code/jerasure/gf-complete/src/gf_wgen.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_wgen.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_wgen.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_wgen.lo `te [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_wgen.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_wgen.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_wgen.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_wgen.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_wgen.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf_wgen.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_wgen.c
+
+erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_method.lo: erasure-code/jerasure/gf-complete/src/gf_method.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_method.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_method.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_method. [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_method.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_method.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_method.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_method.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_method.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf_method.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_method.c
+
+erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w16.lo: erasure-code/jerasure/gf-complete/src/gf_w16.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w16.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_w16.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w16.lo `test  [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_w16.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_w16.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_w16.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w16.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w16.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf_w16.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_w16.c
+
+erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf.lo: erasure-code/jerasure/gf-complete/src/gf.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf.lo `test -f 'erasure- [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf.c
+
+erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w32.lo: erasure-code/jerasure/gf-complete/src/gf_w32.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w32.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_w32.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w32.lo `test  [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_w32.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_w32.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_w32.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w32.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w32.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf_w32.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_w32.c
+
+erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w64.lo: erasure-code/jerasure/gf-complete/src/gf_w64.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w64.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_w64.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w64.lo `test  [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_w64.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_w64.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_w64.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w64.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w64.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf_w64.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_w64.c
+
+erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w128.lo: erasure-code/jerasure/gf-complete/src/gf_w128.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w128.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_w128.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w128.lo `te [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_w128.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_w128.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_w128.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w128.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w128.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf_w128.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_w128.c
+
+erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_general.lo: erasure-code/jerasure/gf-complete/src/gf_general.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_general.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_general.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_gener [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_general.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_general.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_general.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_general.lo' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/libec_jerasure_la-cauchy.lo `test -f 'erasure-code/jerasure/cauchy.c' || echo '$(srcdir)/'`erasure-code/jerasure/cauchy.c
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_general.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf_general.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_general.c
 
-erasure-code/jerasure/libec_jerasure_la-galois.lo: erasure-code/jerasure/galois.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/libec_jerasure_la-galois.lo -MD -MP -MF erasure-code/jerasure/$(DEPDIR)/libec_jerasure_la-galois.Tpo -c -o erasure-code/jerasure/libec_jerasure_la-galois.lo `test -f 'erasure-code/jerasure/galois.c' || echo '$(srcdir)/'`erasure-code/jerasure/galois.c
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/$(DEPDIR)/libec_jerasure_la-galois.Tpo erasure-code/jerasure/$(DEPDIR)/libec_jerasure_la-galois.Plo
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/galois.c' object='erasure-code/jerasure/libec_jerasure_la-galois.lo' libtool=yes @AMDEPBACKSLASH@
+erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w4.lo: erasure-code/jerasure/gf-complete/src/gf_w4.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w4.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_w4.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w4.lo `test -f  [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_w4.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_w4.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_w4.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w4.lo' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/libec_jerasure_la-galois.lo `test -f 'erasure-code/jerasure/galois.c' || echo '$(srcdir)/'`erasure-code/jerasure/galois.c
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w4.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf_w4.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_w4.c
 
-erasure-code/jerasure/libec_jerasure_la-jerasure.lo: erasure-code/jerasure/jerasure.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/libec_jerasure_la-jerasure.lo -MD -MP -MF erasure-code/jerasure/$(DEPDIR)/libec_jerasure_la-jerasure.Tpo -c -o erasure-code/jerasure/libec_jerasure_la-jerasure.lo `test -f 'erasure-code/jerasure/jerasure.c' || echo '$(srcdir)/'`erasure-code/je [...]
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/$(DEPDIR)/libec_jerasure_la-jerasure.Tpo erasure-code/jerasure/$(DEPDIR)/libec_jerasure_la-jerasure.Plo
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/jerasure.c' object='erasure-code/jerasure/libec_jerasure_la-jerasure.lo' libtool=yes @AMDEPBACKSLASH@
+erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_rand.lo: erasure-code/jerasure/gf-complete/src/gf_rand.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_rand.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_rand.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_rand.lo `te [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_rand.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_rand.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_rand.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_rand.lo' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/libec_jerasure_la-jerasure.lo `test -f 'erasure-code/jerasure/jerasure.c' || echo '$(srcdir)/'`erasure-code/jerasure/jerasure.c
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_rand.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf_rand.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_rand.c
 
-erasure-code/jerasure/libec_jerasure_la-liberation.lo: erasure-code/jerasure/liberation.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/libec_jerasure_la-liberation.lo -MD -MP -MF erasure-code/jerasure/$(DEPDIR)/libec_jerasure_la-liberation.Tpo -c -o erasure-code/jerasure/libec_jerasure_la-liberation.lo `test -f 'erasure-code/jerasure/liberation.c' || echo '$(srcdir)/'`erasure [...]
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/$(DEPDIR)/libec_jerasure_la-liberation.Tpo erasure-code/jerasure/$(DEPDIR)/libec_jerasure_la-liberation.Plo
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/liberation.c' object='erasure-code/jerasure/libec_jerasure_la-liberation.lo' libtool=yes @AMDEPBACKSLASH@
+erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w8.lo: erasure-code/jerasure/gf-complete/src/gf_w8.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w8.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_w8.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w8.lo `test -f  [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_w8.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_generic_la-gf_w8.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_w8.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w8.lo' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/libec_jerasure_la-liberation.lo `test -f 'erasure-code/jerasure/liberation.c' || echo '$(srcdir)/'`erasure-code/jerasure/liberation.c
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_generic_la-gf_w8.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf_w8.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_w8.c
 
-erasure-code/jerasure/libec_jerasure_la-reed_sol.lo: erasure-code/jerasure/reed_sol.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/libec_jerasure_la-reed_sol.lo -MD -MP -MF erasure-code/jerasure/$(DEPDIR)/libec_jerasure_la-reed_sol.Tpo -c -o erasure-code/jerasure/libec_jerasure_la-reed_sol.lo `test -f 'erasure-code/jerasure/reed_sol.c' || echo '$(srcdir)/'`erasure-code/je [...]
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/$(DEPDIR)/libec_jerasure_la-reed_sol.Tpo erasure-code/jerasure/$(DEPDIR)/libec_jerasure_la-reed_sol.Plo
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/reed_sol.c' object='erasure-code/jerasure/libec_jerasure_la-reed_sol.lo' libtool=yes @AMDEPBACKSLASH@
+erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-cauchy.lo: erasure-code/jerasure/jerasure/src/cauchy.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-cauchy.lo -MD -MP -MF erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse3_la-cauchy.Tpo -c -o erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-cauchy.lo `test -f 'erasure-code/jera [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse3_la-cauchy.Tpo erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse3_la-cauchy.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/jerasure/src/cauchy.c' object='erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-cauchy.lo' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/libec_jerasure_la-reed_sol.lo `test -f 'erasure-code/jerasure/reed_sol.c' || echo '$(srcdir)/'`erasure-code/jerasure/reed_sol.c
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-cauchy.lo `test -f 'erasure-code/jerasure/jerasure/src/cauchy.c' || echo '$(srcdir)/'`erasure-code/jerasure/jerasure/src/cauchy.c
+
+erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-galois.lo: erasure-code/jerasure/jerasure/src/galois.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-galois.lo -MD -MP -MF erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse3_la-galois.Tpo -c -o erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-galois.lo `test -f 'erasure-code/jera [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse3_la-galois.Tpo erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse3_la-galois.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/jerasure/src/galois.c' object='erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-galois.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-galois.lo `test -f 'erasure-code/jerasure/jerasure/src/galois.c' || echo '$(srcdir)/'`erasure-code/jerasure/jerasure/src/galois.c
+
+erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-jerasure.lo: erasure-code/jerasure/jerasure/src/jerasure.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-jerasure.lo -MD -MP -MF erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse3_la-jerasure.Tpo -c -o erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-jerasure.lo `test -f 'erasure-cod [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse3_la-jerasure.Tpo erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse3_la-jerasure.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/jerasure/src/jerasure.c' object='erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-jerasure.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-jerasure.lo `test -f 'erasure-code/jerasure/jerasure/src/jerasure.c' || echo '$(srcdir)/'`erasure-code/jerasure/jerasure/src/jerasure.c
+
+erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-liberation.lo: erasure-code/jerasure/jerasure/src/liberation.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-liberation.lo -MD -MP -MF erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse3_la-liberation.Tpo -c -o erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-liberation.lo `test -f 'erasu [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse3_la-liberation.Tpo erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse3_la-liberation.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/jerasure/src/liberation.c' object='erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-liberation.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-liberation.lo `test -f 'erasure-code/jerasure/jerasure/src/liberation.c' || echo '$(srcdir)/'`erasure-code/jerasure/jerasure/src/liberation.c
+
+erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-reed_sol.lo: erasure-code/jerasure/jerasure/src/reed_sol.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-reed_sol.lo -MD -MP -MF erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse3_la-reed_sol.Tpo -c -o erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-reed_sol.lo `test -f 'erasure-cod [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse3_la-reed_sol.Tpo erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse3_la-reed_sol.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/jerasure/src/reed_sol.c' object='erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-reed_sol.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/jerasure/src/libec_jerasure_sse3_la-reed_sol.lo `test -f 'erasure-code/jerasure/jerasure/src/reed_sol.c' || echo '$(srcdir)/'`erasure-code/jerasure/jerasure/src/reed_sol.c
+
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_wgen.lo: erasure-code/jerasure/gf-complete/src/gf_wgen.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_wgen.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_wgen.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_wgen.lo `test -f 'erasu [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_wgen.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_wgen.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_wgen.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_wgen.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_wgen.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf_wgen.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_wgen.c
+
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_method.lo: erasure-code/jerasure/gf-complete/src/gf_method.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_method.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_method.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_method.lo `test -f  [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_method.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_method.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_method.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_method.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_method.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf_method.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_method.c
+
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w16.lo: erasure-code/jerasure/gf-complete/src/gf_w16.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w16.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_w16.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w16.lo `test -f 'erasure- [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_w16.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_w16.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_w16.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w16.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w16.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf_w16.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_w16.c
+
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf.lo: erasure-code/jerasure/gf-complete/src/gf.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf.lo `test -f 'erasure-code/jerasur [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf.c
+
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w32.lo: erasure-code/jerasure/gf-complete/src/gf_w32.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w32.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_w32.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w32.lo `test -f 'erasure- [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_w32.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_w32.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_w32.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w32.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w32.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf_w32.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_w32.c
+
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w64.lo: erasure-code/jerasure/gf-complete/src/gf_w64.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w64.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_w64.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w64.lo `test -f 'erasure- [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_w64.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_w64.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_w64.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w64.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w64.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf_w64.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_w64.c
+
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w128.lo: erasure-code/jerasure/gf-complete/src/gf_w128.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w128.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_w128.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w128.lo `test -f 'erasu [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_w128.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_w128.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_w128.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w128.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w128.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf_w128.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_w128.c
+
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_general.lo: erasure-code/jerasure/gf-complete/src/gf_general.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_general.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_general.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_general.lo `test  [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_general.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_general.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_general.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_general.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_general.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf_general.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_general.c
+
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w4.lo: erasure-code/jerasure/gf-complete/src/gf_w4.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w4.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_w4.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w4.lo `test -f 'erasure-cod [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_w4.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_w4.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_w4.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w4.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w4.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf_w4.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_w4.c
+
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_rand.lo: erasure-code/jerasure/gf-complete/src/gf_rand.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_rand.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_rand.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_rand.lo `test -f 'erasu [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_rand.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_rand.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_rand.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_rand.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_rand.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf_rand.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_rand.c
+
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w8.lo: erasure-code/jerasure/gf-complete/src/gf_w8.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w8.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_w8.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w8.lo `test -f 'erasure-cod [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_w8.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse3_la-gf_w8.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_w8.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w8.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse3_la-gf_w8.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf_w8.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_w8.c
+
+erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-cauchy.lo: erasure-code/jerasure/jerasure/src/cauchy.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-cauchy.lo -MD -MP -MF erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse4_la-cauchy.Tpo -c -o erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-cauchy.lo `test -f 'erasure-code/jera [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse4_la-cauchy.Tpo erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse4_la-cauchy.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/jerasure/src/cauchy.c' object='erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-cauchy.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-cauchy.lo `test -f 'erasure-code/jerasure/jerasure/src/cauchy.c' || echo '$(srcdir)/'`erasure-code/jerasure/jerasure/src/cauchy.c
+
+erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-galois.lo: erasure-code/jerasure/jerasure/src/galois.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-galois.lo -MD -MP -MF erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse4_la-galois.Tpo -c -o erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-galois.lo `test -f 'erasure-code/jera [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse4_la-galois.Tpo erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse4_la-galois.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/jerasure/src/galois.c' object='erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-galois.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-galois.lo `test -f 'erasure-code/jerasure/jerasure/src/galois.c' || echo '$(srcdir)/'`erasure-code/jerasure/jerasure/src/galois.c
+
+erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-jerasure.lo: erasure-code/jerasure/jerasure/src/jerasure.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-jerasure.lo -MD -MP -MF erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse4_la-jerasure.Tpo -c -o erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-jerasure.lo `test -f 'erasure-cod [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse4_la-jerasure.Tpo erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse4_la-jerasure.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/jerasure/src/jerasure.c' object='erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-jerasure.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-jerasure.lo `test -f 'erasure-code/jerasure/jerasure/src/jerasure.c' || echo '$(srcdir)/'`erasure-code/jerasure/jerasure/src/jerasure.c
+
+erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-liberation.lo: erasure-code/jerasure/jerasure/src/liberation.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-liberation.lo -MD -MP -MF erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse4_la-liberation.Tpo -c -o erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-liberation.lo `test -f 'erasu [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse4_la-liberation.Tpo erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse4_la-liberation.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/jerasure/src/liberation.c' object='erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-liberation.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-liberation.lo `test -f 'erasure-code/jerasure/jerasure/src/liberation.c' || echo '$(srcdir)/'`erasure-code/jerasure/jerasure/src/liberation.c
+
+erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-reed_sol.lo: erasure-code/jerasure/jerasure/src/reed_sol.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-reed_sol.lo -MD -MP -MF erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse4_la-reed_sol.Tpo -c -o erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-reed_sol.lo `test -f 'erasure-cod [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse4_la-reed_sol.Tpo erasure-code/jerasure/jerasure/src/$(DEPDIR)/libec_jerasure_sse4_la-reed_sol.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/jerasure/src/reed_sol.c' object='erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-reed_sol.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/jerasure/src/libec_jerasure_sse4_la-reed_sol.lo `test -f 'erasure-code/jerasure/jerasure/src/reed_sol.c' || echo '$(srcdir)/'`erasure-code/jerasure/jerasure/src/reed_sol.c
+
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_wgen.lo: erasure-code/jerasure/gf-complete/src/gf_wgen.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_wgen.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_wgen.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_wgen.lo `test -f 'erasu [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_wgen.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_wgen.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_wgen.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_wgen.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_wgen.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf_wgen.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_wgen.c
+
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_method.lo: erasure-code/jerasure/gf-complete/src/gf_method.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_method.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_method.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_method.lo `test -f  [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_method.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_method.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_method.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_method.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_method.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf_method.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_method.c
+
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w16.lo: erasure-code/jerasure/gf-complete/src/gf_w16.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w16.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_w16.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w16.lo `test -f 'erasure- [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_w16.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_w16.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_w16.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w16.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w16.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf_w16.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_w16.c
+
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf.lo: erasure-code/jerasure/gf-complete/src/gf.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf.lo `test -f 'erasure-code/jerasur [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf.c
+
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w32.lo: erasure-code/jerasure/gf-complete/src/gf_w32.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w32.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_w32.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w32.lo `test -f 'erasure- [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_w32.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_w32.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_w32.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w32.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w32.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf_w32.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_w32.c
+
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w64.lo: erasure-code/jerasure/gf-complete/src/gf_w64.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w64.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_w64.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w64.lo `test -f 'erasure- [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_w64.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_w64.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_w64.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w64.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w64.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf_w64.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_w64.c
+
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w128.lo: erasure-code/jerasure/gf-complete/src/gf_w128.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w128.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_w128.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w128.lo `test -f 'erasu [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_w128.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_w128.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_w128.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w128.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w128.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf_w128.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_w128.c
+
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_general.lo: erasure-code/jerasure/gf-complete/src/gf_general.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_general.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_general.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_general.lo `test  [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_general.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_general.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_general.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_general.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_general.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf_general.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_general.c
+
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w4.lo: erasure-code/jerasure/gf-complete/src/gf_w4.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w4.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_w4.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w4.lo `test -f 'erasure-cod [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_w4.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_w4.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_w4.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w4.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w4.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf_w4.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_w4.c
+
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_rand.lo: erasure-code/jerasure/gf-complete/src/gf_rand.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_rand.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_rand.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_rand.lo `test -f 'erasu [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_rand.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_rand.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_rand.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_rand.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_rand.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf_rand.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_rand.c
+
+erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w8.lo: erasure-code/jerasure/gf-complete/src/gf_w8.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w8.lo -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_w8.Tpo -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w8.lo `test -f 'erasure-cod [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_w8.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/libec_jerasure_sse4_la-gf_w8.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_w8.c' object='erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w8.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/libec_jerasure_sse4_la-gf_w8.lo `test -f 'erasure-code/jerasure/gf-complete/src/gf_w8.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_w8.c
 
 test/librbd/ceph_test_librbd_fsx-fsx.o: test/librbd/fsx.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ceph_test_librbd_fsx_CFLAGS) $(CFLAGS) -MT test/librbd/ceph_test_librbd_fsx-fsx.o -MD -MP -MF test/librbd/$(DEPDIR)/ceph_test_librbd_fsx-fsx.Tpo -c -o test/librbd/ceph_test_librbd_fsx-fsx.o `test -f 'test/librbd/fsx.c' || echo '$(srcdir)/'`test/librbd/fsx.c
@@ -9840,19 +10768,229 @@ common/test_build_libcommon-linux_version.obj: common/linux_version.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_build_libcommon_CFLAGS) $(CFLAGS) -c -o common/test_build_libcommon-linux_version.obj `if test -f 'common/linux_version.c'; then $(CYGPATH_W) 'common/linux_version.c'; else $(CYGPATH_W) '$(srcdir)/common/linux_version.c'; fi`
 
-common/test_build_libcommon-secret.o: common/secret.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_build_libcommon_CFLAGS) $(CFLAGS) -MT common/test_build_libcommon-secret.o -MD -MP -MF common/$(DEPDIR)/test_build_libcommon-secret.Tpo -c -o common/test_build_libcommon-secret.o `test -f 'common/secret.c' || echo '$(srcdir)/'`common/secret.c
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) common/$(DEPDIR)/test_build_libcommon-secret.Tpo common/$(DEPDIR)/test_build_libcommon-secret.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='common/secret.c' object='common/test_build_libcommon-secret.o' libtool=no @AMDEPBACKSLASH@
+erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-cauchy.o: erasure-code/jerasure/jerasure/src/cauchy.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-cauchy.o -MD -MP -MF erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-cauchy.Tpo -c -o erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-cauchy.o `test -f 'erasure-code/jerasure/jerasure/src/cauchy.c' || echo '$(srcdir)/'`er [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-cauchy.Tpo erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-cauchy.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/jerasure/src/cauchy.c' object='erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-cauchy.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-cauchy.o `test -f 'erasure-code/jerasure/jerasure/src/cauchy.c' || echo '$(srcdir)/'`erasure-code/jerasure/jerasure/src/cauchy.c
+
+erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-cauchy.obj: erasure-code/jerasure/jerasure/src/cauchy.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-cauchy.obj -MD -MP -MF erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-cauchy.Tpo -c -o erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-cauchy.obj `if test -f 'erasure-code/jerasure/jerasure/src/cauchy.c'; then $(CYGPATH_ [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-cauchy.Tpo erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-cauchy.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/jerasure/src/cauchy.c' object='erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-cauchy.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-cauchy.obj `if test -f 'erasure-code/jerasure/jerasure/src/cauchy.c'; then $(CYGPATH_W) 'erasure-code/jerasure/jerasure/src/cauchy.c'; else $(CYGPATH_W) '$(srcdir)/erasure-code/jerasure/jerasure/src/cauchy.c'; fi`
+
+erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-galois.o: erasure-code/jerasure/jerasure/src/galois.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-galois.o -MD -MP -MF erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-galois.Tpo -c -o erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-galois.o `test -f 'erasure-code/jerasure/jerasure/src/galois.c' || echo '$(srcdir)/'`er [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-galois.Tpo erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-galois.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/jerasure/src/galois.c' object='erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-galois.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-galois.o `test -f 'erasure-code/jerasure/jerasure/src/galois.c' || echo '$(srcdir)/'`erasure-code/jerasure/jerasure/src/galois.c
+
+erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-galois.obj: erasure-code/jerasure/jerasure/src/galois.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-galois.obj -MD -MP -MF erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-galois.Tpo -c -o erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-galois.obj `if test -f 'erasure-code/jerasure/jerasure/src/galois.c'; then $(CYGPATH_ [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-galois.Tpo erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-galois.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/jerasure/src/galois.c' object='erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-galois.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-galois.obj `if test -f 'erasure-code/jerasure/jerasure/src/galois.c'; then $(CYGPATH_W) 'erasure-code/jerasure/jerasure/src/galois.c'; else $(CYGPATH_W) '$(srcdir)/erasure-code/jerasure/jerasure/src/galois.c'; fi`
+
+erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-jerasure.o: erasure-code/jerasure/jerasure/src/jerasure.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-jerasure.o -MD -MP -MF erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-jerasure.Tpo -c -o erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-jerasure.o `test -f 'erasure-code/jerasure/jerasure/src/jerasure.c' || echo '$(srcd [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-jerasure.Tpo erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-jerasure.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/jerasure/src/jerasure.c' object='erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-jerasure.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-jerasure.o `test -f 'erasure-code/jerasure/jerasure/src/jerasure.c' || echo '$(srcdir)/'`erasure-code/jerasure/jerasure/src/jerasure.c
+
+erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-jerasure.obj: erasure-code/jerasure/jerasure/src/jerasure.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-jerasure.obj -MD -MP -MF erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-jerasure.Tpo -c -o erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-jerasure.obj `if test -f 'erasure-code/jerasure/jerasure/src/jerasure.c'; then $( [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-jerasure.Tpo erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-jerasure.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/jerasure/src/jerasure.c' object='erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-jerasure.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-jerasure.obj `if test -f 'erasure-code/jerasure/jerasure/src/jerasure.c'; then $(CYGPATH_W) 'erasure-code/jerasure/jerasure/src/jerasure.c'; else $(CYGPATH_W) '$(srcdir)/erasure-code/jerasure/jerasure/src/jerasure.c'; fi`
+
+erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-liberation.o: erasure-code/jerasure/jerasure/src/liberation.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-liberation.o -MD -MP -MF erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-liberation.Tpo -c -o erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-liberation.o `test -f 'erasure-code/jerasure/jerasure/src/liberation.c' || echo [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-liberation.Tpo erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-liberation.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/jerasure/src/liberation.c' object='erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-liberation.o' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_build_libcommon_CFLAGS) $(CFLAGS) -c -o common/test_build_libcommon-secret.o `test -f 'common/secret.c' || echo '$(srcdir)/'`common/secret.c
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-liberation.o `test -f 'erasure-code/jerasure/jerasure/src/liberation.c' || echo '$(srcdir)/'`erasure-code/jerasure/jerasure/src/liberation.c
 
-common/test_build_libcommon-secret.obj: common/secret.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_build_libcommon_CFLAGS) $(CFLAGS) -MT common/test_build_libcommon-secret.obj -MD -MP -MF common/$(DEPDIR)/test_build_libcommon-secret.Tpo -c -o common/test_build_libcommon-secret.obj `if test -f 'common/secret.c'; then $(CYGPATH_W) 'common/secret.c'; else $(CYGPATH_W) '$(srcdir)/common/secret.c'; fi`
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) common/$(DEPDIR)/test_build_libcommon-secret.Tpo common/$(DEPDIR)/test_build_libcommon-secret.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='common/secret.c' object='common/test_build_libcommon-secret.obj' libtool=no @AMDEPBACKSLASH@
+erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-liberation.obj: erasure-code/jerasure/jerasure/src/liberation.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-liberation.obj -MD -MP -MF erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-liberation.Tpo -c -o erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-liberation.obj `if test -f 'erasure-code/jerasure/jerasure/src/liberation.c'; [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-liberation.Tpo erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-liberation.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/jerasure/src/liberation.c' object='erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-liberation.obj' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_build_libcommon_CFLAGS) $(CFLAGS) -c -o common/test_build_libcommon-secret.obj `if test -f 'common/secret.c'; then $(CYGPATH_W) 'common/secret.c'; else $(CYGPATH_W) '$(srcdir)/common/secret.c'; fi`
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-liberation.obj `if test -f 'erasure-code/jerasure/jerasure/src/liberation.c'; then $(CYGPATH_W) 'erasure-code/jerasure/jerasure/src/liberation.c'; else $(CYGPATH_W) '$(srcdir)/erasure-code/jerasure/jerasure/src/liberation.c'; fi`
+
+erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-reed_sol.o: erasure-code/jerasure/jerasure/src/reed_sol.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-reed_sol.o -MD -MP -MF erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-reed_sol.Tpo -c -o erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-reed_sol.o `test -f 'erasure-code/jerasure/jerasure/src/reed_sol.c' || echo '$(srcd [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-reed_sol.Tpo erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-reed_sol.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/jerasure/src/reed_sol.c' object='erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-reed_sol.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-reed_sol.o `test -f 'erasure-code/jerasure/jerasure/src/reed_sol.c' || echo '$(srcdir)/'`erasure-code/jerasure/jerasure/src/reed_sol.c
+
+erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-reed_sol.obj: erasure-code/jerasure/jerasure/src/reed_sol.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-reed_sol.obj -MD -MP -MF erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-reed_sol.Tpo -c -o erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-reed_sol.obj `if test -f 'erasure-code/jerasure/jerasure/src/reed_sol.c'; then $( [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-reed_sol.Tpo erasure-code/jerasure/jerasure/src/$(DEPDIR)/unittest_erasure_code_jerasure-reed_sol.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/jerasure/src/reed_sol.c' object='erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-reed_sol.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-reed_sol.obj `if test -f 'erasure-code/jerasure/jerasure/src/reed_sol.c'; then $(CYGPATH_W) 'erasure-code/jerasure/jerasure/src/reed_sol.c'; else $(CYGPATH_W) '$(srcdir)/erasure-code/jerasure/jerasure/src/reed_sol.c'; fi`
+
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_wgen.o: erasure-code/jerasure/gf-complete/src/gf_wgen.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_wgen.o -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_wgen.Tpo -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_wgen.o `test -f 'erasure-code/jerasure/gf-complete/src/gf_wgen.c' || echo [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_wgen.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_wgen.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_wgen.c' object='erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_wgen.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_wgen.o `test -f 'erasure-code/jerasure/gf-complete/src/gf_wgen.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_wgen.c
+
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_wgen.obj: erasure-code/jerasure/gf-complete/src/gf_wgen.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_wgen.obj -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_wgen.Tpo -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_wgen.obj `if test -f 'erasure-code/jerasure/gf-complete/src/gf_wgen.c'; [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_wgen.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_wgen.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_wgen.c' object='erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_wgen.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_wgen.obj `if test -f 'erasure-code/jerasure/gf-complete/src/gf_wgen.c'; then $(CYGPATH_W) 'erasure-code/jerasure/gf-complete/src/gf_wgen.c'; else $(CYGPATH_W) '$(srcdir)/erasure-code/jerasure/gf-complete/src/gf_wgen.c'; fi`
+
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_method.o: erasure-code/jerasure/gf-complete/src/gf_method.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_method.o -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_method.Tpo -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_method.o `test -f 'erasure-code/jerasure/gf-complete/src/gf_method.c' [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_method.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_method.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_method.c' object='erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_method.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_method.o `test -f 'erasure-code/jerasure/gf-complete/src/gf_method.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_method.c
+
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_method.obj: erasure-code/jerasure/gf-complete/src/gf_method.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_method.obj -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_method.Tpo -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_method.obj `if test -f 'erasure-code/jerasure/gf-complete/src/gf_me [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_method.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_method.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_method.c' object='erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_method.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_method.obj `if test -f 'erasure-code/jerasure/gf-complete/src/gf_method.c'; then $(CYGPATH_W) 'erasure-code/jerasure/gf-complete/src/gf_method.c'; else $(CYGPATH_W) '$(srcdir)/erasure-code/jerasure/gf-complete/src/gf_method.c'; fi`
+
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w16.o: erasure-code/jerasure/gf-complete/src/gf_w16.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w16.o -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w16.Tpo -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w16.o `test -f 'erasure-code/jerasure/gf-complete/src/gf_w16.c' || echo '$( [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w16.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w16.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_w16.c' object='erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w16.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w16.o `test -f 'erasure-code/jerasure/gf-complete/src/gf_w16.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_w16.c
+
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w16.obj: erasure-code/jerasure/gf-complete/src/gf_w16.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w16.obj -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w16.Tpo -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w16.obj `if test -f 'erasure-code/jerasure/gf-complete/src/gf_w16.c'; the [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w16.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w16.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_w16.c' object='erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w16.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w16.obj `if test -f 'erasure-code/jerasure/gf-complete/src/gf_w16.c'; then $(CYGPATH_W) 'erasure-code/jerasure/gf-complete/src/gf_w16.c'; else $(CYGPATH_W) '$(srcdir)/erasure-code/jerasure/gf-complete/src/gf_w16.c'; fi`
+
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf.o: erasure-code/jerasure/gf-complete/src/gf.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf.o -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf.Tpo -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf.o `test -f 'erasure-code/jerasure/gf-complete/src/gf.c' || echo '$(srcdir)/'`erasur [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf.c' object='erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf.o `test -f 'erasure-code/jerasure/gf-complete/src/gf.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf.c
+
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf.obj: erasure-code/jerasure/gf-complete/src/gf.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf.obj -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf.Tpo -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf.obj `if test -f 'erasure-code/jerasure/gf-complete/src/gf.c'; then $(CYGPATH_W) ' [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf.c' object='erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf.obj `if test -f 'erasure-code/jerasure/gf-complete/src/gf.c'; then $(CYGPATH_W) 'erasure-code/jerasure/gf-complete/src/gf.c'; else $(CYGPATH_W) '$(srcdir)/erasure-code/jerasure/gf-complete/src/gf.c'; fi`
+
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w32.o: erasure-code/jerasure/gf-complete/src/gf_w32.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w32.o -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w32.Tpo -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w32.o `test -f 'erasure-code/jerasure/gf-complete/src/gf_w32.c' || echo '$( [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w32.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w32.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_w32.c' object='erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w32.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w32.o `test -f 'erasure-code/jerasure/gf-complete/src/gf_w32.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_w32.c
+
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w32.obj: erasure-code/jerasure/gf-complete/src/gf_w32.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w32.obj -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w32.Tpo -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w32.obj `if test -f 'erasure-code/jerasure/gf-complete/src/gf_w32.c'; the [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w32.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w32.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_w32.c' object='erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w32.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w32.obj `if test -f 'erasure-code/jerasure/gf-complete/src/gf_w32.c'; then $(CYGPATH_W) 'erasure-code/jerasure/gf-complete/src/gf_w32.c'; else $(CYGPATH_W) '$(srcdir)/erasure-code/jerasure/gf-complete/src/gf_w32.c'; fi`
+
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w64.o: erasure-code/jerasure/gf-complete/src/gf_w64.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w64.o -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w64.Tpo -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w64.o `test -f 'erasure-code/jerasure/gf-complete/src/gf_w64.c' || echo '$( [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w64.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w64.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_w64.c' object='erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w64.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w64.o `test -f 'erasure-code/jerasure/gf-complete/src/gf_w64.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_w64.c
+
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w64.obj: erasure-code/jerasure/gf-complete/src/gf_w64.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w64.obj -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w64.Tpo -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w64.obj `if test -f 'erasure-code/jerasure/gf-complete/src/gf_w64.c'; the [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w64.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w64.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_w64.c' object='erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w64.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w64.obj `if test -f 'erasure-code/jerasure/gf-complete/src/gf_w64.c'; then $(CYGPATH_W) 'erasure-code/jerasure/gf-complete/src/gf_w64.c'; else $(CYGPATH_W) '$(srcdir)/erasure-code/jerasure/gf-complete/src/gf_w64.c'; fi`
+
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w128.o: erasure-code/jerasure/gf-complete/src/gf_w128.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w128.o -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w128.Tpo -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w128.o `test -f 'erasure-code/jerasure/gf-complete/src/gf_w128.c' || echo [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w128.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w128.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_w128.c' object='erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w128.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w128.o `test -f 'erasure-code/jerasure/gf-complete/src/gf_w128.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_w128.c
+
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w128.obj: erasure-code/jerasure/gf-complete/src/gf_w128.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w128.obj -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w128.Tpo -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w128.obj `if test -f 'erasure-code/jerasure/gf-complete/src/gf_w128.c'; [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w128.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w128.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_w128.c' object='erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w128.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w128.obj `if test -f 'erasure-code/jerasure/gf-complete/src/gf_w128.c'; then $(CYGPATH_W) 'erasure-code/jerasure/gf-complete/src/gf_w128.c'; else $(CYGPATH_W) '$(srcdir)/erasure-code/jerasure/gf-complete/src/gf_w128.c'; fi`
+
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_general.o: erasure-code/jerasure/gf-complete/src/gf_general.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_general.o -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_general.Tpo -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_general.o `test -f 'erasure-code/jerasure/gf-complete/src/gf_genera [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_general.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_general.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_general.c' object='erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_general.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_general.o `test -f 'erasure-code/jerasure/gf-complete/src/gf_general.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_general.c
+
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_general.obj: erasure-code/jerasure/gf-complete/src/gf_general.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_general.obj -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_general.Tpo -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_general.obj `if test -f 'erasure-code/jerasure/gf-complete/src/gf [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_general.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_general.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_general.c' object='erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_general.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_general.obj `if test -f 'erasure-code/jerasure/gf-complete/src/gf_general.c'; then $(CYGPATH_W) 'erasure-code/jerasure/gf-complete/src/gf_general.c'; else $(CYGPATH_W) '$(srcdir)/erasure-code/jerasure/gf-complete/src/gf_general.c'; fi`
+
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w4.o: erasure-code/jerasure/gf-complete/src/gf_w4.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w4.o -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w4.Tpo -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w4.o `test -f 'erasure-code/jerasure/gf-complete/src/gf_w4.c' || echo '$(srcd [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w4.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w4.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_w4.c' object='erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w4.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w4.o `test -f 'erasure-code/jerasure/gf-complete/src/gf_w4.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_w4.c
+
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w4.obj: erasure-code/jerasure/gf-complete/src/gf_w4.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w4.obj -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w4.Tpo -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w4.obj `if test -f 'erasure-code/jerasure/gf-complete/src/gf_w4.c'; then $( [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w4.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w4.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_w4.c' object='erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w4.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w4.obj `if test -f 'erasure-code/jerasure/gf-complete/src/gf_w4.c'; then $(CYGPATH_W) 'erasure-code/jerasure/gf-complete/src/gf_w4.c'; else $(CYGPATH_W) '$(srcdir)/erasure-code/jerasure/gf-complete/src/gf_w4.c'; fi`
+
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_rand.o: erasure-code/jerasure/gf-complete/src/gf_rand.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_rand.o -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_rand.Tpo -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_rand.o `test -f 'erasure-code/jerasure/gf-complete/src/gf_rand.c' || echo [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_rand.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_rand.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_rand.c' object='erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_rand.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_rand.o `test -f 'erasure-code/jerasure/gf-complete/src/gf_rand.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_rand.c
+
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_rand.obj: erasure-code/jerasure/gf-complete/src/gf_rand.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_rand.obj -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_rand.Tpo -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_rand.obj `if test -f 'erasure-code/jerasure/gf-complete/src/gf_rand.c'; [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_rand.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_rand.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_rand.c' object='erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_rand.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_rand.obj `if test -f 'erasure-code/jerasure/gf-complete/src/gf_rand.c'; then $(CYGPATH_W) 'erasure-code/jerasure/gf-complete/src/gf_rand.c'; else $(CYGPATH_W) '$(srcdir)/erasure-code/jerasure/gf-complete/src/gf_rand.c'; fi`
+
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w8.o: erasure-code/jerasure/gf-complete/src/gf_w8.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w8.o -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w8.Tpo -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w8.o `test -f 'erasure-code/jerasure/gf-complete/src/gf_w8.c' || echo '$(srcd [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w8.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w8.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_w8.c' object='erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w8.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w8.o `test -f 'erasure-code/jerasure/gf-complete/src/gf_w8.c' || echo '$(srcdir)/'`erasure-code/jerasure/gf-complete/src/gf_w8.c
+
+erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w8.obj: erasure-code/jerasure/gf-complete/src/gf_w8.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -MT erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w8.obj -MD -MP -MF erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w8.Tpo -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w8.obj `if test -f 'erasure-code/jerasure/gf-complete/src/gf_w8.c'; then $( [...]
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w8.Tpo erasure-code/jerasure/gf-complete/src/$(DEPDIR)/unittest_erasure_code_jerasure-gf_w8.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='erasure-code/jerasure/gf-complete/src/gf_w8.c' object='erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w8.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_jerasure_CFLAGS) $(CFLAGS) -c -o erasure-code/jerasure/gf-complete/src/unittest_erasure_code_jerasure-gf_w8.obj `if test -f 'erasure-code/jerasure/gf-complete/src/gf_w8.c'; then $(CYGPATH_W) 'erasure-code/jerasure/gf-complete/src/gf_w8.c'; else $(CYGPATH_W) '$(srcdir)/erasure-code/jerasure/gf-complete/src/gf_w8.c'; fi`
 
 .cc.o:
 @am__fastdepCXX_TRUE@	$(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
@@ -9941,19 +11079,54 @@ test/erasure-code/libec_hangs_la-ErasureCodePluginHangs.lo: test/erasure-code/Er
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_hangs_la_CXXFLAGS) $(CXXFLAGS) -c -o test/erasure-code/libec_hangs_la-ErasureCodePluginHangs.lo `test -f 'test/erasure-code/ErasureCodePluginHangs.cc' || echo '$(srcdir)/'`test/erasure-code/ErasureCodePluginHangs.cc
 
-erasure-code/jerasure/libec_jerasure_la-ErasureCodePluginJerasure.lo: erasure-code/jerasure/ErasureCodePluginJerasure.cc
- at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_la_CXXFLAGS) $(CXXFLAGS) -MT erasure-code/jerasure/libec_jerasure_la-ErasureCodePluginJerasure.lo -MD -MP -MF erasure-code/jerasure/$(DEPDIR)/libec_jerasure_la-ErasureCodePluginJerasure.Tpo -c -o erasure-code/jerasure/libec_jerasure_la-ErasureCodePluginJerasure.lo `test -f 'erasure-cod [...]
- at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/$(DEPDIR)/libec_jerasure_la-ErasureCodePluginJerasure.Tpo erasure-code/jerasure/$(DEPDIR)/libec_jerasure_la-ErasureCodePluginJerasure.Plo
- at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='erasure-code/jerasure/ErasureCodePluginJerasure.cc' object='erasure-code/jerasure/libec_jerasure_la-ErasureCodePluginJerasure.lo' libtool=yes @AMDEPBACKSLASH@
+erasure-code/jerasure/libec_jerasure_la-ErasureCodePluginSelectJerasure.lo: erasure-code/jerasure/ErasureCodePluginSelectJerasure.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_la_CXXFLAGS) $(CXXFLAGS) -MT erasure-code/jerasure/libec_jerasure_la-ErasureCodePluginSelectJerasure.lo -MD -MP -MF erasure-code/jerasure/$(DEPDIR)/libec_jerasure_la-ErasureCodePluginSelectJerasure.Tpo -c -o erasure-code/jerasure/libec_jerasure_la-ErasureCodePluginSelectJerasure.lo `te [...]
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/$(DEPDIR)/libec_jerasure_la-ErasureCodePluginSelectJerasure.Tpo erasure-code/jerasure/$(DEPDIR)/libec_jerasure_la-ErasureCodePluginSelectJerasure.Plo
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='erasure-code/jerasure/ErasureCodePluginSelectJerasure.cc' object='erasure-code/jerasure/libec_jerasure_la-ErasureCodePluginSelectJerasure.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_la_CXXFLAGS) $(CXXFLAGS) -c -o erasure-code/jerasure/libec_jerasure_la-ErasureCodePluginSelectJerasure.lo `test -f 'erasure-code/jerasure/ErasureCodePluginSelectJerasure.cc' || echo '$(srcdir)/'`erasure-code/jerasure/ErasureCodePluginSelectJerasure.cc
+
+erasure-code/jerasure/libec_jerasure_generic_la-ErasureCodePluginJerasure.lo: erasure-code/jerasure/ErasureCodePluginJerasure.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CXXFLAGS) $(CXXFLAGS) -MT erasure-code/jerasure/libec_jerasure_generic_la-ErasureCodePluginJerasure.lo -MD -MP -MF erasure-code/jerasure/$(DEPDIR)/libec_jerasure_generic_la-ErasureCodePluginJerasure.Tpo -c -o erasure-code/jerasure/libec_jerasure_generic_la-ErasureCodePluginJ [...]
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/$(DEPDIR)/libec_jerasure_generic_la-ErasureCodePluginJerasure.Tpo erasure-code/jerasure/$(DEPDIR)/libec_jerasure_generic_la-ErasureCodePluginJerasure.Plo
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='erasure-code/jerasure/ErasureCodePluginJerasure.cc' object='erasure-code/jerasure/libec_jerasure_generic_la-ErasureCodePluginJerasure.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CXXFLAGS) $(CXXFLAGS) -c -o erasure-code/jerasure/libec_jerasure_generic_la-ErasureCodePluginJerasure.lo `test -f 'erasure-code/jerasure/ErasureCodePluginJerasure.cc' || echo '$(srcdir)/'`erasure-code/jerasure/ErasureCodePluginJerasure.cc
+
+erasure-code/jerasure/libec_jerasure_generic_la-ErasureCodeJerasure.lo: erasure-code/jerasure/ErasureCodeJerasure.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CXXFLAGS) $(CXXFLAGS) -MT erasure-code/jerasure/libec_jerasure_generic_la-ErasureCodeJerasure.lo -MD -MP -MF erasure-code/jerasure/$(DEPDIR)/libec_jerasure_generic_la-ErasureCodeJerasure.Tpo -c -o erasure-code/jerasure/libec_jerasure_generic_la-ErasureCodeJerasure.lo `test - [...]
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/$(DEPDIR)/libec_jerasure_generic_la-ErasureCodeJerasure.Tpo erasure-code/jerasure/$(DEPDIR)/libec_jerasure_generic_la-ErasureCodeJerasure.Plo
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='erasure-code/jerasure/ErasureCodeJerasure.cc' object='erasure-code/jerasure/libec_jerasure_generic_la-ErasureCodeJerasure.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_generic_la_CXXFLAGS) $(CXXFLAGS) -c -o erasure-code/jerasure/libec_jerasure_generic_la-ErasureCodeJerasure.lo `test -f 'erasure-code/jerasure/ErasureCodeJerasure.cc' || echo '$(srcdir)/'`erasure-code/jerasure/ErasureCodeJerasure.cc
+
+erasure-code/jerasure/libec_jerasure_sse3_la-ErasureCodePluginJerasure.lo: erasure-code/jerasure/ErasureCodePluginJerasure.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CXXFLAGS) $(CXXFLAGS) -MT erasure-code/jerasure/libec_jerasure_sse3_la-ErasureCodePluginJerasure.lo -MD -MP -MF erasure-code/jerasure/$(DEPDIR)/libec_jerasure_sse3_la-ErasureCodePluginJerasure.Tpo -c -o erasure-code/jerasure/libec_jerasure_sse3_la-ErasureCodePluginJerasure.lo ` [...]
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/$(DEPDIR)/libec_jerasure_sse3_la-ErasureCodePluginJerasure.Tpo erasure-code/jerasure/$(DEPDIR)/libec_jerasure_sse3_la-ErasureCodePluginJerasure.Plo
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='erasure-code/jerasure/ErasureCodePluginJerasure.cc' object='erasure-code/jerasure/libec_jerasure_sse3_la-ErasureCodePluginJerasure.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CXXFLAGS) $(CXXFLAGS) -c -o erasure-code/jerasure/libec_jerasure_sse3_la-ErasureCodePluginJerasure.lo `test -f 'erasure-code/jerasure/ErasureCodePluginJerasure.cc' || echo '$(srcdir)/'`erasure-code/jerasure/ErasureCodePluginJerasure.cc
+
+erasure-code/jerasure/libec_jerasure_sse3_la-ErasureCodeJerasure.lo: erasure-code/jerasure/ErasureCodeJerasure.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CXXFLAGS) $(CXXFLAGS) -MT erasure-code/jerasure/libec_jerasure_sse3_la-ErasureCodeJerasure.lo -MD -MP -MF erasure-code/jerasure/$(DEPDIR)/libec_jerasure_sse3_la-ErasureCodeJerasure.Tpo -c -o erasure-code/jerasure/libec_jerasure_sse3_la-ErasureCodeJerasure.lo `test -f 'erasure-c [...]
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/$(DEPDIR)/libec_jerasure_sse3_la-ErasureCodeJerasure.Tpo erasure-code/jerasure/$(DEPDIR)/libec_jerasure_sse3_la-ErasureCodeJerasure.Plo
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='erasure-code/jerasure/ErasureCodeJerasure.cc' object='erasure-code/jerasure/libec_jerasure_sse3_la-ErasureCodeJerasure.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse3_la_CXXFLAGS) $(CXXFLAGS) -c -o erasure-code/jerasure/libec_jerasure_sse3_la-ErasureCodeJerasure.lo `test -f 'erasure-code/jerasure/ErasureCodeJerasure.cc' || echo '$(srcdir)/'`erasure-code/jerasure/ErasureCodeJerasure.cc
+
+erasure-code/jerasure/libec_jerasure_sse4_la-ErasureCodePluginJerasure.lo: erasure-code/jerasure/ErasureCodePluginJerasure.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CXXFLAGS) $(CXXFLAGS) -MT erasure-code/jerasure/libec_jerasure_sse4_la-ErasureCodePluginJerasure.lo -MD -MP -MF erasure-code/jerasure/$(DEPDIR)/libec_jerasure_sse4_la-ErasureCodePluginJerasure.Tpo -c -o erasure-code/jerasure/libec_jerasure_sse4_la-ErasureCodePluginJerasure.lo ` [...]
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/$(DEPDIR)/libec_jerasure_sse4_la-ErasureCodePluginJerasure.Tpo erasure-code/jerasure/$(DEPDIR)/libec_jerasure_sse4_la-ErasureCodePluginJerasure.Plo
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='erasure-code/jerasure/ErasureCodePluginJerasure.cc' object='erasure-code/jerasure/libec_jerasure_sse4_la-ErasureCodePluginJerasure.lo' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_la_CXXFLAGS) $(CXXFLAGS) -c -o erasure-code/jerasure/libec_jerasure_la-ErasureCodePluginJerasure.lo `test -f 'erasure-code/jerasure/ErasureCodePluginJerasure.cc' || echo '$(srcdir)/'`erasure-code/jerasure/ErasureCodePluginJerasure.cc
+ at am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CXXFLAGS) $(CXXFLAGS) -c -o erasure-code/jerasure/libec_jerasure_sse4_la-ErasureCodePluginJerasure.lo `test -f 'erasure-code/jerasure/ErasureCodePluginJerasure.cc' || echo '$(srcdir)/'`erasure-code/jerasure/ErasureCodePluginJerasure.cc
 
-erasure-code/jerasure/libec_jerasure_la-ErasureCodeJerasure.lo: erasure-code/jerasure/ErasureCodeJerasure.cc
- at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_la_CXXFLAGS) $(CXXFLAGS) -MT erasure-code/jerasure/libec_jerasure_la-ErasureCodeJerasure.lo -MD -MP -MF erasure-code/jerasure/$(DEPDIR)/libec_jerasure_la-ErasureCodeJerasure.Tpo -c -o erasure-code/jerasure/libec_jerasure_la-ErasureCodeJerasure.lo `test -f 'erasure-code/jerasure/Erasure [...]
- at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/$(DEPDIR)/libec_jerasure_la-ErasureCodeJerasure.Tpo erasure-code/jerasure/$(DEPDIR)/libec_jerasure_la-ErasureCodeJerasure.Plo
- at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='erasure-code/jerasure/ErasureCodeJerasure.cc' object='erasure-code/jerasure/libec_jerasure_la-ErasureCodeJerasure.lo' libtool=yes @AMDEPBACKSLASH@
+erasure-code/jerasure/libec_jerasure_sse4_la-ErasureCodeJerasure.lo: erasure-code/jerasure/ErasureCodeJerasure.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CXXFLAGS) $(CXXFLAGS) -MT erasure-code/jerasure/libec_jerasure_sse4_la-ErasureCodeJerasure.lo -MD -MP -MF erasure-code/jerasure/$(DEPDIR)/libec_jerasure_sse4_la-ErasureCodeJerasure.Tpo -c -o erasure-code/jerasure/libec_jerasure_sse4_la-ErasureCodeJerasure.lo `test -f 'erasure-c [...]
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) erasure-code/jerasure/$(DEPDIR)/libec_jerasure_sse4_la-ErasureCodeJerasure.Tpo erasure-code/jerasure/$(DEPDIR)/libec_jerasure_sse4_la-ErasureCodeJerasure.Plo
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='erasure-code/jerasure/ErasureCodeJerasure.cc' object='erasure-code/jerasure/libec_jerasure_sse4_la-ErasureCodeJerasure.lo' libtool=yes @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_la_CXXFLAGS) $(CXXFLAGS) -c -o erasure-code/jerasure/libec_jerasure_la-ErasureCodeJerasure.lo `test -f 'erasure-code/jerasure/ErasureCodeJerasure.cc' || echo '$(srcdir)/'`erasure-code/jerasure/ErasureCodeJerasure.cc
+ at am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_jerasure_sse4_la_CXXFLAGS) $(CXXFLAGS) -c -o erasure-code/jerasure/libec_jerasure_sse4_la-ErasureCodeJerasure.lo `test -f 'erasure-code/jerasure/ErasureCodeJerasure.cc' || echo '$(srcdir)/'`erasure-code/jerasure/ErasureCodeJerasure.cc
 
 test/erasure-code/libec_missing_entry_point_la-ErasureCodePluginMissingEntryPoint.lo: test/erasure-code/ErasureCodePluginMissingEntryPoint.cc
 @am__fastdepCXX_TRUE@	$(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_missing_entry_point_la_CXXFLAGS) $(CXXFLAGS) -MT test/erasure-code/libec_missing_entry_point_la-ErasureCodePluginMissingEntryPoint.lo -MD -MP -MF test/erasure-code/$(DEPDIR)/libec_missing_entry_point_la-ErasureCodePluginMissingEntryPoint.Tpo -c -o test/erasure-code/libec_missing_entry_point_la- [...]
@@ -9962,6 +11135,27 @@ test/erasure-code/libec_missing_entry_point_la-ErasureCodePluginMissingEntryPoin
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_missing_entry_point_la_CXXFLAGS) $(CXXFLAGS) -c -o test/erasure-code/libec_missing_entry_point_la-ErasureCodePluginMissingEntryPoint.lo `test -f 'test/erasure-code/ErasureCodePluginMissingEntryPoint.cc' || echo '$(srcdir)/'`test/erasure-code/ErasureCodePluginMissingEntryPoint.cc
 
+test/erasure-code/libec_test_jerasure_generic_la-TestJerasurePluginGeneric.lo: test/erasure-code/TestJerasurePluginGeneric.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_test_jerasure_generic_la_CXXFLAGS) $(CXXFLAGS) -MT test/erasure-code/libec_test_jerasure_generic_la-TestJerasurePluginGeneric.lo -MD -MP -MF test/erasure-code/$(DEPDIR)/libec_test_jerasure_generic_la-TestJerasurePluginGeneric.Tpo -c -o test/erasure-code/libec_test_jerasure_generic_la-TestJerasu [...]
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) test/erasure-code/$(DEPDIR)/libec_test_jerasure_generic_la-TestJerasurePluginGeneric.Tpo test/erasure-code/$(DEPDIR)/libec_test_jerasure_generic_la-TestJerasurePluginGeneric.Plo
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='test/erasure-code/TestJerasurePluginGeneric.cc' object='test/erasure-code/libec_test_jerasure_generic_la-TestJerasurePluginGeneric.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_test_jerasure_generic_la_CXXFLAGS) $(CXXFLAGS) -c -o test/erasure-code/libec_test_jerasure_generic_la-TestJerasurePluginGeneric.lo `test -f 'test/erasure-code/TestJerasurePluginGeneric.cc' || echo '$(srcdir)/'`test/erasure-code/TestJerasurePluginGeneric.cc
+
+test/erasure-code/libec_test_jerasure_sse3_la-TestJerasurePluginSSE3.lo: test/erasure-code/TestJerasurePluginSSE3.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_test_jerasure_sse3_la_CXXFLAGS) $(CXXFLAGS) -MT test/erasure-code/libec_test_jerasure_sse3_la-TestJerasurePluginSSE3.lo -MD -MP -MF test/erasure-code/$(DEPDIR)/libec_test_jerasure_sse3_la-TestJerasurePluginSSE3.Tpo -c -o test/erasure-code/libec_test_jerasure_sse3_la-TestJerasurePluginSSE3.lo `t [...]
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) test/erasure-code/$(DEPDIR)/libec_test_jerasure_sse3_la-TestJerasurePluginSSE3.Tpo test/erasure-code/$(DEPDIR)/libec_test_jerasure_sse3_la-TestJerasurePluginSSE3.Plo
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='test/erasure-code/TestJerasurePluginSSE3.cc' object='test/erasure-code/libec_test_jerasure_sse3_la-TestJerasurePluginSSE3.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_test_jerasure_sse3_la_CXXFLAGS) $(CXXFLAGS) -c -o test/erasure-code/libec_test_jerasure_sse3_la-TestJerasurePluginSSE3.lo `test -f 'test/erasure-code/TestJerasurePluginSSE3.cc' || echo '$(srcdir)/'`test/erasure-code/TestJerasurePluginSSE3.cc
+
+test/erasure-code/libec_test_jerasure_sse4_la-TestJerasurePluginSSE4.lo: test/erasure-code/TestJerasurePluginSSE4.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_test_jerasure_sse4_la_CXXFLAGS) $(CXXFLAGS) -MT test/erasure-code/libec_test_jerasure_sse4_la-TestJerasurePluginSSE4.lo -MD -MP -MF test/erasure-code/$(DEPDIR)/libec_test_jerasure_sse4_la-TestJerasurePluginSSE4.Tpo -c -o test/erasure-code/libec_test_jerasure_sse4_la-TestJerasurePluginSSE4.lo `t [...]
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) test/erasure-code/$(DEPDIR)/libec_test_jerasure_sse4_la-TestJerasurePluginSSE4.Tpo test/erasure-code/$(DEPDIR)/libec_test_jerasure_sse4_la-TestJerasurePluginSSE4.Plo
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='test/erasure-code/TestJerasurePluginSSE4.cc' object='test/erasure-code/libec_test_jerasure_sse4_la-TestJerasurePluginSSE4.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libec_test_jerasure_sse4_la_CXXFLAGS) $(CXXFLAGS) -c -o test/erasure-code/libec_test_jerasure_sse4_la-TestJerasurePluginSSE4.lo `test -f 'test/erasure-code/TestJerasurePluginSSE4.cc' || echo '$(srcdir)/'`test/erasure-code/TestJerasurePluginSSE4.cc
+
 librados/librados_la-librados.lo: librados/librados.cc
 @am__fastdepCXX_TRUE@	$(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(librados_la_CXXFLAGS) $(CXXFLAGS) -MT librados/librados_la-librados.lo -MD -MP -MF librados/$(DEPDIR)/librados_la-librados.Tpo -c -o librados/librados_la-librados.lo `test -f 'librados/librados.cc' || echo '$(srcdir)/'`librados/librados.cc
 @am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) librados/$(DEPDIR)/librados_la-librados.Tpo librados/$(DEPDIR)/librados_la-librados.Plo
@@ -10319,19 +11513,19 @@ rgw/ceph_dencoder-rgw_json_enc.obj: rgw/rgw_json_enc.cc
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ceph_dencoder_CXXFLAGS) $(CXXFLAGS) -c -o rgw/ceph_dencoder-rgw_json_enc.obj `if test -f 'rgw/rgw_json_enc.cc'; then $(CYGPATH_W) 'rgw/rgw_json_enc.cc'; else $(CYGPATH_W) '$(srcdir)/rgw/rgw_json_enc.cc'; fi`
 
-tools/ceph_kvstore_tool-ceph-kvstore-tool.o: tools/ceph-kvstore-tool.cc
- at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ceph_kvstore_tool_CXXFLAGS) $(CXXFLAGS) -MT tools/ceph_kvstore_tool-ceph-kvstore-tool.o -MD -MP -MF tools/$(DEPDIR)/ceph_kvstore_tool-ceph-kvstore-tool.Tpo -c -o tools/ceph_kvstore_tool-ceph-kvstore-tool.o `test -f 'tools/ceph-kvstore-tool.cc' || echo '$(srcdir)/'`tools/ceph-kvstore-tool.cc
- at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) tools/$(DEPDIR)/ceph_kvstore_tool-ceph-kvstore-tool.Tpo tools/$(DEPDIR)/ceph_kvstore_tool-ceph-kvstore-tool.Po
- at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='tools/ceph-kvstore-tool.cc' object='tools/ceph_kvstore_tool-ceph-kvstore-tool.o' libtool=no @AMDEPBACKSLASH@
+tools/ceph_kvstore_tool-ceph_kvstore_tool.o: tools/ceph_kvstore_tool.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ceph_kvstore_tool_CXXFLAGS) $(CXXFLAGS) -MT tools/ceph_kvstore_tool-ceph_kvstore_tool.o -MD -MP -MF tools/$(DEPDIR)/ceph_kvstore_tool-ceph_kvstore_tool.Tpo -c -o tools/ceph_kvstore_tool-ceph_kvstore_tool.o `test -f 'tools/ceph_kvstore_tool.cc' || echo '$(srcdir)/'`tools/ceph_kvstore_tool.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) tools/$(DEPDIR)/ceph_kvstore_tool-ceph_kvstore_tool.Tpo tools/$(DEPDIR)/ceph_kvstore_tool-ceph_kvstore_tool.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='tools/ceph_kvstore_tool.cc' object='tools/ceph_kvstore_tool-ceph_kvstore_tool.o' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ceph_kvstore_tool_CXXFLAGS) $(CXXFLAGS) -c -o tools/ceph_kvstore_tool-ceph-kvstore-tool.o `test -f 'tools/ceph-kvstore-tool.cc' || echo '$(srcdir)/'`tools/ceph-kvstore-tool.cc
+ at am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ceph_kvstore_tool_CXXFLAGS) $(CXXFLAGS) -c -o tools/ceph_kvstore_tool-ceph_kvstore_tool.o `test -f 'tools/ceph_kvstore_tool.cc' || echo '$(srcdir)/'`tools/ceph_kvstore_tool.cc
 
-tools/ceph_kvstore_tool-ceph-kvstore-tool.obj: tools/ceph-kvstore-tool.cc
- at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ceph_kvstore_tool_CXXFLAGS) $(CXXFLAGS) -MT tools/ceph_kvstore_tool-ceph-kvstore-tool.obj -MD -MP -MF tools/$(DEPDIR)/ceph_kvstore_tool-ceph-kvstore-tool.Tpo -c -o tools/ceph_kvstore_tool-ceph-kvstore-tool.obj `if test -f 'tools/ceph-kvstore-tool.cc'; then $(CYGPATH_W) 'tools/ceph-kvstore-tool.cc'; else $(CYGPATH_W) '$(srcdir)/tools/ceph-kvstore-tool.cc'; fi`
- at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) tools/$(DEPDIR)/ceph_kvstore_tool-ceph-kvstore-tool.Tpo tools/$(DEPDIR)/ceph_kvstore_tool-ceph-kvstore-tool.Po
- at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='tools/ceph-kvstore-tool.cc' object='tools/ceph_kvstore_tool-ceph-kvstore-tool.obj' libtool=no @AMDEPBACKSLASH@
+tools/ceph_kvstore_tool-ceph_kvstore_tool.obj: tools/ceph_kvstore_tool.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ceph_kvstore_tool_CXXFLAGS) $(CXXFLAGS) -MT tools/ceph_kvstore_tool-ceph_kvstore_tool.obj -MD -MP -MF tools/$(DEPDIR)/ceph_kvstore_tool-ceph_kvstore_tool.Tpo -c -o tools/ceph_kvstore_tool-ceph_kvstore_tool.obj `if test -f 'tools/ceph_kvstore_tool.cc'; then $(CYGPATH_W) 'tools/ceph_kvstore_tool.cc'; else $(CYGPATH_W) '$(srcdir)/tools/ceph_kvstore_tool.cc'; fi`
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) tools/$(DEPDIR)/ceph_kvstore_tool-ceph_kvstore_tool.Tpo tools/$(DEPDIR)/ceph_kvstore_tool-ceph_kvstore_tool.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='tools/ceph_kvstore_tool.cc' object='tools/ceph_kvstore_tool-ceph_kvstore_tool.obj' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ceph_kvstore_tool_CXXFLAGS) $(CXXFLAGS) -c -o tools/ceph_kvstore_tool-ceph-kvstore-tool.obj `if test -f 'tools/ceph-kvstore-tool.cc'; then $(CYGPATH_W) 'tools/ceph-kvstore-tool.cc'; else $(CYGPATH_W) '$(srcdir)/tools/ceph-kvstore-tool.cc'; fi`
+ at am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ceph_kvstore_tool_CXXFLAGS) $(CXXFLAGS) -c -o tools/ceph_kvstore_tool-ceph_kvstore_tool.obj `if test -f 'tools/ceph_kvstore_tool.cc'; then $(CYGPATH_W) 'tools/ceph_kvstore_tool.cc'; else $(CYGPATH_W) '$(srcdir)/tools/ceph_kvstore_tool.cc'; fi`
 
 test/cls_hello/ceph_test_cls_hello-test_cls_hello.o: test/cls_hello/test_cls_hello.cc
 @am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ceph_test_cls_hello_CXXFLAGS) $(CXXFLAGS) -MT test/cls_hello/ceph_test_cls_hello-test_cls_hello.o -MD -MP -MF test/cls_hello/$(DEPDIR)/ceph_test_cls_hello-test_cls_hello.Tpo -c -o test/cls_hello/ceph_test_cls_hello-test_cls_hello.o `test -f 'test/cls_hello/test_cls_hello.cc' || echo '$(srcdir)/'`test/cls_hello/test_cls_hello.cc
@@ -12853,6 +14047,20 @@ test/unittest_crypto-crypto.obj: test/crypto.cc
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_crypto_CXXFLAGS) $(CXXFLAGS) -c -o test/unittest_crypto-crypto.obj `if test -f 'test/crypto.cc'; then $(CYGPATH_W) 'test/crypto.cc'; else $(CYGPATH_W) '$(srcdir)/test/crypto.cc'; fi`
 
+test/unittest_crypto_init-crypto_init.o: test/crypto_init.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_crypto_init_CXXFLAGS) $(CXXFLAGS) -MT test/unittest_crypto_init-crypto_init.o -MD -MP -MF test/$(DEPDIR)/unittest_crypto_init-crypto_init.Tpo -c -o test/unittest_crypto_init-crypto_init.o `test -f 'test/crypto_init.cc' || echo '$(srcdir)/'`test/crypto_init.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) test/$(DEPDIR)/unittest_crypto_init-crypto_init.Tpo test/$(DEPDIR)/unittest_crypto_init-crypto_init.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='test/crypto_init.cc' object='test/unittest_crypto_init-crypto_init.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_crypto_init_CXXFLAGS) $(CXXFLAGS) -c -o test/unittest_crypto_init-crypto_init.o `test -f 'test/crypto_init.cc' || echo '$(srcdir)/'`test/crypto_init.cc
+
+test/unittest_crypto_init-crypto_init.obj: test/crypto_init.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_crypto_init_CXXFLAGS) $(CXXFLAGS) -MT test/unittest_crypto_init-crypto_init.obj -MD -MP -MF test/$(DEPDIR)/unittest_crypto_init-crypto_init.Tpo -c -o test/unittest_crypto_init-crypto_init.obj `if test -f 'test/crypto_init.cc'; then $(CYGPATH_W) 'test/crypto_init.cc'; else $(CYGPATH_W) '$(srcdir)/test/crypto_init.cc'; fi`
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) test/$(DEPDIR)/unittest_crypto_init-crypto_init.Tpo test/$(DEPDIR)/unittest_crypto_init-crypto_init.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='test/crypto_init.cc' object='test/unittest_crypto_init-crypto_init.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_crypto_init_CXXFLAGS) $(CXXFLAGS) -c -o test/unittest_crypto_init-crypto_init.obj `if test -f 'test/crypto_init.cc'; then $(CYGPATH_W) 'test/crypto_init.cc'; else $(CYGPATH_W) '$(srcdir)/test/crypto_init.cc'; fi`
+
 test/unittest_daemon_config-daemon_config.o: test/daemon_config.cc
 @am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_daemon_config_CXXFLAGS) $(CXXFLAGS) -MT test/unittest_daemon_config-daemon_config.o -MD -MP -MF test/$(DEPDIR)/unittest_daemon_config-daemon_config.Tpo -c -o test/unittest_daemon_config-daemon_config.o `test -f 'test/daemon_config.cc' || echo '$(srcdir)/'`test/daemon_config.cc
 @am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) test/$(DEPDIR)/unittest_daemon_config-daemon_config.Tpo test/$(DEPDIR)/unittest_daemon_config-daemon_config.Po
@@ -13546,6 +14754,8 @@ clean-libtool:
 	-rm -rf crush/.libs crush/_libs
 	-rm -rf erasure-code/.libs erasure-code/_libs
 	-rm -rf erasure-code/jerasure/.libs erasure-code/jerasure/_libs
+	-rm -rf erasure-code/jerasure/gf-complete/src/.libs erasure-code/jerasure/gf-complete/src/_libs
+	-rm -rf erasure-code/jerasure/jerasure/src/.libs erasure-code/jerasure/jerasure/src/_libs
 	-rm -rf global/.libs global/_libs
 	-rm -rf java/native/.libs java/native/_libs
 	-rm -rf json_spirit/.libs json_spirit/_libs
@@ -14064,6 +15274,10 @@ distclean-generic:
 	-rm -f erasure-code/$(am__dirstamp)
 	-rm -f erasure-code/jerasure/$(DEPDIR)/$(am__dirstamp)
 	-rm -f erasure-code/jerasure/$(am__dirstamp)
+	-rm -f erasure-code/jerasure/gf-complete/src/$(DEPDIR)/$(am__dirstamp)
+	-rm -f erasure-code/jerasure/gf-complete/src/$(am__dirstamp)
+	-rm -f erasure-code/jerasure/jerasure/src/$(DEPDIR)/$(am__dirstamp)
+	-rm -f erasure-code/jerasure/jerasure/src/$(am__dirstamp)
 	-rm -f global/$(DEPDIR)/$(am__dirstamp)
 	-rm -f global/$(am__dirstamp)
 	-rm -f java/native/$(DEPDIR)/$(am__dirstamp)
@@ -14171,7 +15385,7 @@ clean-am: clean-binPROGRAMS clean-checkPROGRAMS \
 	clean-sbinPROGRAMS clean-su_sbinPROGRAMS mostlyclean-am
 
 distclean: distclean-recursive
-	-rm -rf ./$(DEPDIR) arch/$(DEPDIR) auth/$(DEPDIR) auth/cephx/$(DEPDIR) auth/none/$(DEPDIR) auth/unknown/$(DEPDIR) civetweb/src/$(DEPDIR) client/$(DEPDIR) cls/hello/$(DEPDIR) cls/lock/$(DEPDIR) cls/log/$(DEPDIR) cls/rbd/$(DEPDIR) cls/refcount/$(DEPDIR) cls/replica_log/$(DEPDIR) cls/rgw/$(DEPDIR) cls/statelog/$(DEPDIR) cls/user/$(DEPDIR) cls/version/$(DEPDIR) common/$(DEPDIR) crush/$(DEPDIR) erasure-code/$(DEPDIR) erasure-code/jerasure/$(DEPDIR) global/$(DEPDIR) java/native/$(DEPDIR) json [...]
+	-rm -rf ./$(DEPDIR) arch/$(DEPDIR) auth/$(DEPDIR) auth/cephx/$(DEPDIR) auth/none/$(DEPDIR) auth/unknown/$(DEPDIR) civetweb/src/$(DEPDIR) client/$(DEPDIR) cls/hello/$(DEPDIR) cls/lock/$(DEPDIR) cls/log/$(DEPDIR) cls/rbd/$(DEPDIR) cls/refcount/$(DEPDIR) cls/replica_log/$(DEPDIR) cls/rgw/$(DEPDIR) cls/statelog/$(DEPDIR) cls/user/$(DEPDIR) cls/version/$(DEPDIR) common/$(DEPDIR) crush/$(DEPDIR) erasure-code/$(DEPDIR) erasure-code/jerasure/$(DEPDIR) erasure-code/jerasure/gf-complete/src/$(DEP [...]
 	-rm -f Makefile
 distclean-am: clean-am distclean-compile distclean-generic \
 	distclean-hdr distclean-tags
@@ -14225,7 +15439,7 @@ install-ps-am:
 installcheck-am:
 
 maintainer-clean: maintainer-clean-recursive
-	-rm -rf ./$(DEPDIR) arch/$(DEPDIR) auth/$(DEPDIR) auth/cephx/$(DEPDIR) auth/none/$(DEPDIR) auth/unknown/$(DEPDIR) civetweb/src/$(DEPDIR) client/$(DEPDIR) cls/hello/$(DEPDIR) cls/lock/$(DEPDIR) cls/log/$(DEPDIR) cls/rbd/$(DEPDIR) cls/refcount/$(DEPDIR) cls/replica_log/$(DEPDIR) cls/rgw/$(DEPDIR) cls/statelog/$(DEPDIR) cls/user/$(DEPDIR) cls/version/$(DEPDIR) common/$(DEPDIR) crush/$(DEPDIR) erasure-code/$(DEPDIR) erasure-code/jerasure/$(DEPDIR) global/$(DEPDIR) java/native/$(DEPDIR) json [...]
+	-rm -rf ./$(DEPDIR) arch/$(DEPDIR) auth/$(DEPDIR) auth/cephx/$(DEPDIR) auth/none/$(DEPDIR) auth/unknown/$(DEPDIR) civetweb/src/$(DEPDIR) client/$(DEPDIR) cls/hello/$(DEPDIR) cls/lock/$(DEPDIR) cls/log/$(DEPDIR) cls/rbd/$(DEPDIR) cls/refcount/$(DEPDIR) cls/replica_log/$(DEPDIR) cls/rgw/$(DEPDIR) cls/statelog/$(DEPDIR) cls/user/$(DEPDIR) cls/version/$(DEPDIR) common/$(DEPDIR) crush/$(DEPDIR) erasure-code/$(DEPDIR) erasure-code/jerasure/$(DEPDIR) erasure-code/jerasure/gf-complete/src/$(DEP [...]
 	-rm -f Makefile
 maintainer-clean-am: distclean-am maintainer-clean-generic
 
@@ -14340,8 +15554,19 @@ base: core-daemons admin-tools \
 FORCE:
 .git_version: FORCE
 	$(srcdir)/check_version $(srcdir)/.git_version
+
+# if NO_VERSION is set, only generate a new ceph_ver.h if there currently 
+# is none, and call "make_version -n" to fill it with a fixed string.
+# Otherwise, set it from the contents of .git_version.
+
 ceph_ver.h: .git_version
-	$(srcdir)/make_version $(srcdir)/.git_version ./ceph_ver.h
+	if [ -n "$$NO_VERSION" ] ; then \
+	    if [ ! -f ./ceph_ver.h ] ; then \
+	        $(srcdir)/make_version -n ./ceph_ver.h ; \
+	    fi; \
+        else \
+	    $(srcdir)/make_version $(srcdir)/.git_version ./ceph_ver.h ; \
+	fi
 
 ceph_ver.c: ./ceph_ver.h
 common/version.cc: ./ceph_ver.h
diff --git a/src/acconfig.h.in b/src/acconfig.h.in
index c3c132f..21baa07 100644
--- a/src/acconfig.h.in
+++ b/src/acconfig.h.in
@@ -137,6 +137,9 @@
 /* Define to 1 if you have the <netinet/in.h> header file. */
 #undef HAVE_NETINET_IN_H
 
+/* Support (PCLMUL) Carry-Free Muliplication */
+#undef HAVE_PCLMUL
+
 /* Define to 1 if you have the `pipe2' function. */
 #undef HAVE_PIPE2
 
@@ -161,6 +164,24 @@
 /* Define if you have pthread_spin_init */
 #undef HAVE_PTHREAD_SPINLOCK
 
+/* Support SSE (Streaming SIMD Extensions) instructions */
+#undef HAVE_SSE
+
+/* Support SSE2 (Streaming SIMD Extensions 2) instructions */
+#undef HAVE_SSE2
+
+/* Support SSE3 (Streaming SIMD Extensions 3) instructions */
+#undef HAVE_SSE3
+
+/* Support SSE4.1 (Streaming SIMD Extensions 4.1) instructions */
+#undef HAVE_SSE4_1
+
+/* Support SSE4.2 (Streaming SIMD Extensions 4.2) instructions */
+#undef HAVE_SSE4_2
+
+/* Support SSSE3 (Supplemental Streaming SIMD Extensions 3) instructions */
+#undef HAVE_SSSE3
+
 /* define if the compiler supports static_cast<> */
 #undef HAVE_STATIC_CAST
 
diff --git a/src/arch/intel.c b/src/arch/intel.c
index 9f2d3e4..e487da4 100644
--- a/src/arch/intel.c
+++ b/src/arch/intel.c
@@ -1,11 +1,31 @@
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2013,2014 Inktank Storage, Inc.
+ * Copyright (C) 2014 Cloudwatt <libre.licensing at cloudwatt.com>
+ *
+ * Author: Loic Dachary <loic at dachary.org>
+ *
+ *  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 <stdio.h>
 #include "arch/probe.h"
 
 /* flags we export */
+int ceph_arch_intel_pclmul = 0;
 int ceph_arch_intel_sse42 = 0;
+int ceph_arch_intel_sse41 = 0;
+int ceph_arch_intel_ssse3 = 0;
+int ceph_arch_intel_sse3 = 0;
 int ceph_arch_intel_sse2 = 0;
 
 #ifdef __x86_64__
 
+/* Note: valgrind redefines cpuid : it is different from the native processor. */
 /* intel cpu? */
 static void do_cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx,
                      unsigned int *edx)
@@ -23,15 +43,36 @@ static void do_cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx,
                 : "eax", "ebx", "ecx", "edx");
 }
 
+/* http://en.wikipedia.org/wiki/CPUID#EAX.3D1:_Processor_Info_and_Feature_Bits */
+
+#define CPUID_PCLMUL	(1 << 1)
+#define CPUID_SSE42	(1 << 20)
+#define CPUID_SSE41	(1 << 19)
+#define CPUID_SSSE3	(1 << 9)
+#define CPUID_SSE3	(1)
+#define CPUID_SSE2	(1 << 26)
+
 int ceph_arch_intel_probe(void)
 {
 	/* i know how to check this on x86_64... */
 	unsigned int eax = 1, ebx, ecx, edx;
 	do_cpuid(&eax, &ebx, &ecx, &edx);
-	if ((ecx & (1 << 20)) != 0) {
+	if ((ecx & CPUID_PCLMUL) != 0) {
+		ceph_arch_intel_pclmul = 1;
+	}
+	if ((ecx & CPUID_SSE42) != 0) {
 		ceph_arch_intel_sse42 = 1;
 	}
-	if ((edx & (1 << 26)) != 0) {
+	if ((ecx & CPUID_SSE41) != 0) {
+		ceph_arch_intel_sse41 = 1;
+	}
+	if ((ecx & CPUID_SSSE3) != 0) {
+	        ceph_arch_intel_ssse3 = 1;
+	}
+	if ((ecx & CPUID_SSE3) != 0) {
+	        ceph_arch_intel_sse3 = 1;
+	}
+	if ((edx & CPUID_SSE2) != 0) {
 	        ceph_arch_intel_sse2 = 1;
 	}
 
diff --git a/src/arch/intel.h b/src/arch/intel.h
index 7703bd7..2c3b809 100644
--- a/src/arch/intel.h
+++ b/src/arch/intel.h
@@ -5,7 +5,11 @@
 extern "C" {
 #endif
 
+extern int ceph_arch_intel_pclmul; /* true if we have PCLMUL features */
 extern int ceph_arch_intel_sse42;  /* true if we have sse 4.2 features */
+extern int ceph_arch_intel_sse41;  /* true if we have sse 4.1 features */
+extern int ceph_arch_intel_ssse3;  /* true if we have ssse 3 features */
+extern int ceph_arch_intel_sse3;   /* true if we have sse 3 features */
 extern int ceph_arch_intel_sse2;   /* true if we have sse 2 features */
 extern int ceph_arch_intel_probe(void);
 
diff --git a/src/auth/Crypto.cc b/src/auth/Crypto.cc
index 7c74b80..e401c96 100644
--- a/src/auth/Crypto.cc
+++ b/src/auth/Crypto.cc
@@ -42,7 +42,7 @@ int get_random_bytes(char *buf, int len)
   if (fd < 0)
     return -errno;
   int ret = safe_read_exact(fd, buf, len);
-  TEMP_FAILURE_RETRY(::close(fd));
+  VOID_TEMP_FAILURE_RETRY(::close(fd));
   return ret;
 }
 
diff --git a/src/auth/cephx/CephxProtocol.cc b/src/auth/cephx/CephxProtocol.cc
index 5c17dea..6956f45 100644
--- a/src/auth/cephx/CephxProtocol.cc
+++ b/src/auth/cephx/CephxProtocol.cc
@@ -39,7 +39,7 @@ void cephx_calc_client_server_challenge(CephContext *cct, CryptoKey& secret, uin
   uint64_t k = 0;
   const uint64_t *p = (const uint64_t *)enc.c_str();
   for (int pos = 0; pos + sizeof(k) <= enc.length(); pos+=sizeof(k), p++)
-    k ^= *p;
+    k ^= mswab64(*p);
   *key = k;
 }
 
diff --git a/src/ceph-disk b/src/ceph-disk
index 5a03639..f79e341 100755
--- a/src/ceph-disk
+++ b/src/ceph-disk
@@ -42,7 +42,7 @@ Prepare:
  - triggered by administrator or ceph-deploy, e.g.  'ceph-disk <data disk> [journal disk]
 
 Activate:
- - mount the volume in a temp loation
+ - mount the volume in a temp location
  - allocate an osd id (if needed)
  - remount in the correct location /var/lib/ceph/osd/$cluster-$id
  - start ceph-osd
diff --git a/src/ceph-post-file.in b/src/ceph-post-file.in
index ba366db..9b922a6 100755
--- a/src/ceph-post-file.in
+++ b/src/ceph-post-file.in
@@ -30,17 +30,17 @@ WARNING:
   directories that contain Ceph secrets).
 
 Options:
-  -d <description>  Description for this post
-                      [Default: none]
-  -u <user>         User identifier
-                      [Default: \`whoami\`@\`hostname -f\`]
-  -r <user at host>    Remote to upload to
-                      [Default: postfile at drop.ceph.com]
-  -k <path>         known_hosts file
-                      [Default: /usr/share/ceph/known_hosts_drop.ceph.com]
+  -d|--description <desc>    Description for this post
+                               [Default: none]
+  -u|--user <user>           User identifier
+                               [Default: \`whoami\`@\`hostname -f\`]
+  -r|--remote <user at host>    Remote to upload to
+                               [Default: postfile at drop.ceph.com]
+  -k|--known_hosts <path>    known_hosts file
+                               [Default: /usr/share/ceph/known_hosts_drop.ceph.com]
   -i <path>         Ssh identity file
                       [Default: /usr/share/ceph/id_dsa_drop.ceph.com]
-  -h                Show this usage information
+  -h|--help         Show this usage information
 "
 }
 
@@ -52,37 +52,48 @@ fi
 description=""
 user="`whoami`@`hostname -f`"
 remote="postfile at drop.ceph.com"
-case $1 in
-    -d | --description)
-	description="$2"
-	shift
-	shift
-	;;
-    -u | --user)
-	user="$2"
-	shift
-	shift
-	;;
-    -h | --help)
-	usage
-	exit 0
-	;;
-    -k | --known-hosts)
-	known_hosts="$1"
-	shift
-	shift
-	;;
-    -i)
-	ssh_key="$1"
-	shift
-	shift
-	;;
-    -r | --remote)
-	remote="$1"
-	shift
-	shift
-	;;
-esac
+
+ARGS=$(getopt -n "ceph-post-file" -o 'd:u:hk:i:r:' -l "description:,user:,help,known-hosts:,remote:" -- "$@")
+eval set -- $ARGS
+
+while true; do
+	echo "args: $@"
+	case $1 in
+	    -d | --description)
+		description="$2"
+		shift
+		shift
+		;;
+	    -u | --user)
+		user="$2"
+		shift
+		shift
+		;;
+	    -h | --help)
+		usage
+		exit 0
+		;;
+	    -k | --known-hosts)
+		known_hosts="$2"
+		shift
+		shift
+		;;
+	    -i)
+		ssh_key="$2"
+		shift
+		shift
+		;;
+	    -r | --remote)
+		remote="$2"
+		shift
+		shift
+		;;
+	    --)
+		shift
+		break
+		;;
+	esac
+done
 
 # this id should be shared
 id=`uuidgen`
diff --git a/src/ceph_mds.cc b/src/ceph_mds.cc
index 2cfe285..1f1fbd3 100644
--- a/src/ceph_mds.cc
+++ b/src/ceph_mds.cc
@@ -56,7 +56,9 @@ void usage()
        << "  --debug_mds n\n"
        << "        debug MDS level (e.g. 10)\n"
        << "  --dump-journal rank filename\n"
-       << "        dump the MDS journal for rank.\n"
+       << "        dump the MDS journal (binary) for rank.\n"
+       << "  --dump-journal-entries rank filename\n"
+       << "        dump the MDS journal (JSON) for rank.\n"
        << "  --journal-check rank\n"
        << "        replay the journal for rank, then exit\n"
        << "  --hot-standby rank\n"
@@ -71,39 +73,32 @@ void usage()
 static int do_cmds_special_action(const std::string &action,
 				  const std::string &dump_file, int rank)
 {
-  common_init_finish(g_ceph_context);
-  Messenger *messenger = Messenger::create(g_ceph_context,
-					   entity_name_t::CLIENT(), "mds",
-					   getpid());
-  int r = messenger->bind(g_conf->public_addr);
-  if (r < 0)
-    return r;
-  MonClient mc(g_ceph_context);
-  if (mc.build_initial_monmap() < 0)
-    return -1;
+  common_init_finish(g_ceph_context, CINIT_FLAG_NO_DAEMON_ACTIONS);
 
   if (action == "dump-journal") {
     dout(0) << "dumping journal for mds." << rank << " to " << dump_file << dendl;
-    Dumper *journal_dumper = new Dumper(messenger, &mc);
-    journal_dumper->init(rank);
-    journal_dumper->dump(dump_file.c_str());
-    mc.shutdown();
-  }
-  else if (action == "undump-journal") {
+    Dumper journal_dumper;
+    journal_dumper.init(rank);
+    journal_dumper.dump(dump_file.c_str());
+    journal_dumper.shutdown();
+  } else if (action == "dump-journal-entries") {
+    Dumper journal_dumper;
+    journal_dumper.init(rank);
+    journal_dumper.dump_entries();
+    journal_dumper.shutdown();
+  } else if (action == "undump-journal") {
     dout(0) << "undumping journal for mds." << rank << " from " << dump_file << dendl;
-    Dumper *journal_dumper = new Dumper(messenger, &mc);
-    journal_dumper->init(rank);
-    journal_dumper->undump(dump_file.c_str());
-    mc.shutdown();
-  }
-  else if (action == "reset-journal") {
+    Dumper journal_dumper;
+    journal_dumper.init(rank);
+    journal_dumper.undump(dump_file.c_str());
+    journal_dumper.shutdown();
+  } else if (action == "reset-journal") {
     dout(0) << "resetting journal" << dendl;
-    Resetter *jr = new Resetter(messenger, &mc);
-    jr->init(rank);
-    jr->reset();
-    mc.shutdown();
-  }
-  else {
+    Resetter resetter;
+    resetter.init(rank);
+    resetter.reset();
+    resetter.shutdown();
+  } else {
     assert(0);
   }
   return 0;
@@ -183,6 +178,10 @@ int main(int argc, const char **argv)
       }
       dump_file = *i++;
     }
+    else if (ceph_argparse_witharg(args, i, &val, "--dump-journal-entries", (char*)NULL)){
+      set_special_action(action, "dump-journal-entries");
+      rank = parse_rank("dump-journal-entries", val);
+    }
     else if (ceph_argparse_witharg(args, i, &val, "--reset-journal", (char*)NULL)) {
       set_special_action(action, "reset-journal");
       rank = parse_rank("reset-journal", val);
diff --git a/src/client/Client.cc b/src/client/Client.cc
index c770286..49c9c6f 100644
--- a/src/client/Client.cc
+++ b/src/client/Client.cc
@@ -598,6 +598,15 @@ void Client::update_inode_file_bits(Inode *in,
   }
 }
 
+void Client::_fragmap_remove_non_leaves(Inode *in)
+{
+  for (map<frag_t,int>::iterator p = in->fragmap.begin(); p != in->fragmap.end(); )
+    if (!in->dirfragtree.is_leaf(p->first))
+      in->fragmap.erase(p++);
+    else
+      ++p;
+}
+
 Inode * Client::add_update_inode(InodeStat *st, utime_t from,
 				 MetaSession *session)
 {
@@ -672,8 +681,6 @@ Inode * Client::add_update_inode(InodeStat *st, utime_t from,
     }
 
     in->layout = st->layout;
-    in->ctime = st->ctime;
-    in->max_size = st->max_size;  // right?
 
     update_inode_file_bits(in, st->truncate_seq, st->truncate_size, st->size,
 			   st->time_warp_seq, st->ctime, st->mtime, st->atime,
@@ -685,11 +692,16 @@ Inode * Client::add_update_inode(InodeStat *st, utime_t from,
   }
 
   // move me if/when version reflects fragtree changes.
-  in->dirfragtree = st->dirfragtree;
+  if (in->dirfragtree != st->dirfragtree) {
+    in->dirfragtree = st->dirfragtree;
+    _fragmap_remove_non_leaves(in);
+  }
 
-  if (in->snapid == CEPH_NOSNAP)
+  if (in->snapid == CEPH_NOSNAP) {
     add_update_cap(in, session, st->cap.cap_id, st->cap.caps, st->cap.seq, st->cap.mseq, inodeno_t(st->cap.realm), st->cap.flags);
-  else
+    if (in->auth_cap && in->auth_cap->session == session)
+      in->max_size = st->max_size;
+  } else
     in->snap_caps |= st->cap.caps;
 
   // setting I_COMPLETE needs to happen after adding the cap
@@ -793,7 +805,10 @@ void Client::update_dir_dist(Inode *in, DirStat *dst)
   } else {
     in->fragmap.erase(dst->frag);
   }
-  assert(in->dirfragtree.is_leaf(dst->frag));
+  if (!in->dirfragtree.is_leaf(dst->frag)) {
+    in->dirfragtree.force_to_leaf(cct, dst->frag);
+    _fragmap_remove_non_leaves(in);
+  }
 
   // replicated
   in->dir_replicated = !dst->dist.empty();  // FIXME that's just one frag!
@@ -880,8 +895,7 @@ void Client::insert_readdir_results(MetaRequest *request, MetaSession *session,
       // remove any skipped names
       while (pd != dir->dentry_map.end() && pd->first < dname) {
 	if (pd->first < dname &&
-	    diri->dirfragtree[ceph_str_hash_linux(pd->first.c_str(),
-						  pd->first.length())] == fg) {  // do not remove items in earlier frags
+	    fg.contains(diri->hash_dentry_name(pd->first))) {  // do not remove items in earlier frags
 	  ldout(cct, 15) << "insert_trace  unlink '" << pd->first << "'" << dendl;
 	  Dentry *dn = pd->second;
 	  ++pd;
@@ -930,8 +944,7 @@ void Client::insert_readdir_results(MetaRequest *request, MetaSession *session,
     // remove trailing names
     if (end) {
       while (pd != dir->dentry_map.end()) {
-	if (diri->dirfragtree[ceph_str_hash_linux(pd->first.c_str(),
-						  pd->first.length())] == fg) {
+	if (fg.contains(diri->hash_dentry_name(pd->first))) {
 	  ldout(cct, 15) << "insert_trace  unlink '" << pd->first << "'" << dendl;
 	  Dentry *dn = pd->second;
 	  ++pd;
@@ -1084,9 +1097,7 @@ int Client::choose_target_mds(MetaRequest *req)
   if (in) {
     ldout(cct, 20) << "choose_target_mds starting with req->inode " << *in << dendl;
     if (req->path.depth()) {
-      hash = ceph_str_hash(in->dir_layout.dl_dir_hash,
-			   req->path[0].data(),
-			   req->path[0].length());
+      hash = in->hash_dentry_name(req->path[0]);
       ldout(cct, 20) << "choose_target_mds inode dir hash is " << (int)in->dir_layout.dl_dir_hash
 	       << " on " << req->path[0]
 	       << " => " << hash << dendl;
@@ -1098,9 +1109,7 @@ int Client::choose_target_mds(MetaRequest *req)
       ldout(cct, 20) << "choose_target_mds starting with req->dentry inode " << *in << dendl;
     } else {
       in = de->dir->parent_inode;
-      hash = ceph_str_hash(in->dir_layout.dl_dir_hash,
-			   de->name.data(),
-			   de->name.length());
+      hash = in->hash_dentry_name(de->name);
       ldout(cct, 20) << "choose_target_mds dentry dir hash is " << (int)in->dir_layout.dl_dir_hash
 	       << " on " << de->name
 	       << " => " << hash << dendl;
@@ -1193,7 +1202,7 @@ void Client::dump_mds_sessions(Formatter *f)
 }
 void Client::dump_mds_requests(Formatter *f)
 {
-  for (map<tid_t, MetaRequest*>::iterator p = mds_requests.begin();
+  for (map<ceph_tid_t, MetaRequest*>::iterator p = mds_requests.begin();
        p != mds_requests.end();
        ++p) {
     f->open_object_section("request");
@@ -1306,7 +1315,7 @@ int Client::make_request(MetaRequest *request,
   int r = 0;
 
   // assign a unique tid
-  tid_t tid = ++last_tid;
+  ceph_tid_t tid = ++last_tid;
   request->set_tid(tid);
   // make note
   mds_requests[tid] = request->get();
@@ -1717,7 +1726,7 @@ void Client::handle_client_request_forward(MClientRequestForward *fwd)
     fwd->put();
     return;
   }
-  tid_t tid = fwd->get_tid();
+  ceph_tid_t tid = fwd->get_tid();
 
   if (mds_requests.count(tid) == 0) {
     ldout(cct, 10) << "handle_client_request_forward no pending request on tid " << tid << dendl;
@@ -1756,7 +1765,7 @@ void Client::handle_client_reply(MClientReply *reply)
     return;
   }
 
-  tid_t tid = reply->get_tid();
+  ceph_tid_t tid = reply->get_tid();
   bool is_safe = reply->is_safe();
 
   if (mds_requests.count(tid) == 0) {
@@ -2001,6 +2010,7 @@ void Client::send_reconnect(MetaSession *session)
 
       in->caps[mds]->seq = 0;  // reset seq.
       in->caps[mds]->issue_seq = 0;  // reset seq.
+      in->caps[mds]->mseq = 0;  // reset seq.
       m->add_cap(p->first.ino, 
 		 in->caps[mds]->cap_id,
 		 path.get_ino(), path.get_path(),   // ino
@@ -2014,18 +2024,6 @@ void Client::send_reconnect(MetaSession *session)
 	did_snaprealm.insert(in->snaprealm->ino);
       }	
     }
-    if (in->exporting_mds == mds) {
-      ldout(cct, 10) << " clearing exporting_caps on " << p->first << dendl;
-      in->exporting_mds = -1;
-      in->exporting_issued = 0;
-      in->exporting_mseq = 0;
-      if (!in->is_any_caps()) {
-	ldout(cct, 10) << "  removing last cap, closing snaprealm" << dendl;
-	in->snaprealm_item.remove_myself();
-	put_snap_realm(in->snaprealm);
-	in->snaprealm = 0;
-      }
-    }
   }
   
   // reset my cap seq number
@@ -2045,7 +2043,7 @@ void Client::send_reconnect(MetaSession *session)
 void Client::kick_requests(MetaSession *session)
 {
   ldout(cct, 10) << "kick_requests for mds." << session->mds_num << dendl;
-  for (map<tid_t, MetaRequest*>::iterator p = mds_requests.begin();
+  for (map<ceph_tid_t, MetaRequest*>::iterator p = mds_requests.begin();
        p != mds_requests.end();
        ++p) {
     if (p->second->mds == session->mds_num) {
@@ -2065,7 +2063,7 @@ void Client::resend_unsafe_requests(MetaSession *session)
 void Client::kick_requests_closed(MetaSession *session)
 {
   ldout(cct, 10) << "kick_requests_closed for mds." << session->mds_num << dendl;
-  for (map<tid_t, MetaRequest*>::iterator p = mds_requests.begin();
+  for (map<ceph_tid_t, MetaRequest*>::iterator p = mds_requests.begin();
        p != mds_requests.end();
        ++p) {
     if (p->second->mds == session->mds_num) {
@@ -2437,6 +2435,7 @@ void Client::check_caps(Inode *in, bool is_delayed)
 {
   unsigned wanted = in->caps_wanted();
   unsigned used = in->caps_used();
+  unsigned cap_used;
 
   int retain = wanted | CEPH_CAP_PIN;
   if (!unmounting) {
@@ -2477,6 +2476,10 @@ void Client::check_caps(Inode *in, bool is_delayed)
     MetaSession *session = mds_sessions[mds];
     assert(session);
 
+    cap_used = used;
+    if (in->auth_cap && cap != in->auth_cap)
+      cap_used &= ~in->auth_cap->issued;
+
     int revoking = cap->implemented & ~cap->issued;
     
     ldout(cct, 10) << " cap mds." << mds
@@ -2500,12 +2503,16 @@ void Client::check_caps(Inode *in, bool is_delayed)
     }
 
     /* completed revocation? */
-    if (revoking && (revoking & used) == 0) {
+    if (revoking && (revoking & cap_used) == 0) {
       ldout(cct, 10) << "completed revocation of " << ccap_string(cap->implemented & ~cap->issued) << dendl;
       goto ack;
     }
 
-    if (!revoking && unmounting && (used == 0))
+    /* want more caps from mds? */
+    if (wanted & ~(cap->wanted | cap->issued))
+      goto ack;
+
+    if (!revoking && unmounting && (cap_used == 0))
       goto ack;
 
     if (wanted == cap->wanted &&         // mds knows what we want.
@@ -2525,7 +2532,7 @@ void Client::check_caps(Inode *in, bool is_delayed)
     else
       flushing = 0;
 
-    send_cap(in, session, cap, used, wanted, retain, flushing);
+    send_cap(in, session, cap, cap_used, wanted, retain, flushing);
   }
 }
 
@@ -2891,6 +2898,24 @@ void Client::add_update_cap(Inode *in, MetaSession *mds_session, uint64_t cap_id
   int mds = mds_session->mds_num;
   if (in->caps.count(mds)) {
     cap = in->caps[mds];
+
+    /*
+     * auth mds of the inode changed. we received the cap export
+     * message, but still haven't received the cap import message.
+     * handle_cap_export() updated the new auth MDS' cap.
+     *
+     * "ceph_seq_cmp(seq, cap->seq) <= 0" means we are processing
+     * a message that was send before the cap import message. So
+     * don't remove caps.
+     */
+    if (ceph_seq_cmp(seq, cap->seq) <= 0) {
+      assert(cap == in->auth_cap);
+      assert(cap->cap_id == cap_id);
+      seq = cap->seq;
+      mseq = cap->mseq;
+      issued |= cap->issued;
+      flags |= CEPH_CAP_FLAG_AUTH;
+    }
   } else {
     mds_session->num_caps++;
     if (!in->is_any_caps()) {
@@ -2899,12 +2924,6 @@ void Client::add_update_cap(Inode *in, MetaSession *mds_session, uint64_t cap_id
       in->snaprealm->inodes_with_caps.push_back(&in->snaprealm_item);
       ldout(cct, 15) << "add_update_cap first one, opened snaprealm " << in->snaprealm << dendl;
     }
-    if (in->exporting_mds == mds) {
-      ldout(cct, 10) << "add_update_cap clearing exporting_caps on " << mds << dendl;
-      in->exporting_mds = -1;
-      in->exporting_issued = 0;
-      in->exporting_mseq = 0;
-    }
     in->caps[mds] = cap = new Cap;
     mds_session->caps.push_back(&cap->cap_item);
     cap->session = mds_session;
@@ -2917,10 +2936,11 @@ void Client::add_update_cap(Inode *in, MetaSession *mds_session, uint64_t cap_id
 
   if (flags & CEPH_CAP_FLAG_AUTH) {
     if (in->auth_cap != cap &&
-        (!in->auth_cap || in->auth_cap->mseq < mseq)) {
+        (!in->auth_cap || ceph_seq_cmp(in->auth_cap->mseq, mseq) < 0)) {
       if (in->auth_cap && in->flushing_cap_item.is_on_list()) {
-	ldout(cct, 10) << "add_update_cap changing auth cap: removing myself from flush_caps list" << dendl;
-	in->flushing_cap_item.remove_myself();
+	ldout(cct, 10) << "add_update_cap changing auth cap: "
+		       << "add myself to new auth MDS' flushing caps list" << dendl;
+	mds_session->flushing_caps.push_back(&in->flushing_cap_item);
       }
       in->auth_cap = cap;
     }
@@ -2938,11 +2958,23 @@ void Client::add_update_cap(Inode *in, MetaSession *mds_session, uint64_t cap_id
 	   << " on " << *in
 	   << dendl;
 
+  if ((issued & ~old_caps) && in->auth_cap == cap) {
+    // non-auth MDS is revoking the newly grant caps ?
+    for (map<int,Cap*>::iterator it = in->caps.begin(); it != in->caps.end(); ++it) {
+      if (it->second == cap)
+	continue;
+      if (it->second->implemented & ~it->second->issued & issued) {
+	check_caps(in, true);
+	break;
+      }
+    }
+  }
+
   if (issued & ~old_caps)
     signal_cond_list(in->waitfor_caps);
 }
 
-void Client::remove_cap(Cap *cap)
+void Client::remove_cap(Cap *cap, bool queue_release)
 {
   Inode *in = cap->inode;
   MetaSession *session = cap->session;
@@ -2950,14 +2982,16 @@ void Client::remove_cap(Cap *cap)
 
   ldout(cct, 10) << "remove_cap mds." << mds << " on " << *in << dendl;
   
-  if (!session->release)
-    session->release = new MClientCapRelease;
-  ceph_mds_cap_item i;
-  i.ino = in->ino;
-  i.cap_id = cap->cap_id;
-  i.seq = cap->issue_seq;
-  i.migrate_seq = cap->mseq;
-  session->release->caps.push_back(i);
+  if (queue_release) {
+    if (!session->release)
+      session->release = new MClientCapRelease;
+    ceph_mds_cap_item i;
+    i.ino = in->ino;
+    i.cap_id = cap->cap_id;
+    i.seq = cap->issue_seq;
+    i.migrate_seq = cap->mseq;
+    session->release->caps.push_back(i);
+  }
 
   if (in->auth_cap == cap) {
     if (in->flushing_cap_item.is_on_list()) {
@@ -2987,14 +3021,14 @@ void Client::remove_cap(Cap *cap)
 void Client::remove_all_caps(Inode *in)
 {
   while (!in->caps.empty())
-    remove_cap(in->caps.begin()->second);
+    remove_cap(in->caps.begin()->second, true);
 }
 
 void Client::remove_session_caps(MetaSession *mds) 
 {
   while (mds->caps.size()) {
     Cap *cap = *mds->caps.begin();
-    remove_cap(cap);
+    remove_cap(cap, false);
   }
 }
 
@@ -3010,15 +3044,14 @@ void Client::trim_caps(MetaSession *s, int max)
     s->s_cap_iterator = cap;
     Inode *in = cap->inode;
     if (in->caps.size() > 1 && cap != in->auth_cap) {
+      int mine = cap->issued | cap->implemented;
+      int oissued = in->auth_cap ? in->auth_cap->issued : 0;
       // disposable non-auth cap
-      if (in->caps_used() || in->caps_dirty()) {
-	ldout(cct, 20) << " keeping cap on " << *in << " used " << ccap_string(in->caps_used())
-		       << " dirty " << ccap_string(in->caps_dirty()) << dendl;
-	continue;
+      if (!(in->caps_used() & ~oissued & mine)) {
+	ldout(cct, 20) << " removing unused, unneeded non-auth cap on " << *in << dendl;
+	remove_cap(cap, true);
+	trimmed++;
       }
-      ldout(cct, 20) << " removing unused, unneeded non-auth cap on " << *in << dendl;
-      remove_cap(cap);
-      trimmed++;
     } else {
       ldout(cct, 20) << " trying to trim dentries for " << *in << dendl;
       bool all = true;
@@ -3444,9 +3477,12 @@ void Client::handle_caps(MClientCaps *m)
   }
 
   switch (m->get_op()) {
-  case CEPH_CAP_OP_IMPORT: return handle_cap_import(session, in, m);
-  case CEPH_CAP_OP_EXPORT: return handle_cap_export(session, in, m);
-  case CEPH_CAP_OP_FLUSHSNAP_ACK: return handle_cap_flushsnap_ack(session, in, m);
+  case CEPH_CAP_OP_EXPORT:
+    return handle_cap_export(session, in, m);
+  case CEPH_CAP_OP_FLUSHSNAP_ACK:
+    return handle_cap_flushsnap_ack(session, in, m);
+  case CEPH_CAP_OP_IMPORT:
+    handle_cap_import(session, in, m);
   }
 
   if (in->caps.count(mds) == 0) {
@@ -3459,6 +3495,7 @@ void Client::handle_caps(MClientCaps *m)
 
   switch (m->get_op()) {
   case CEPH_CAP_OP_TRUNC: return handle_cap_trunc(session, in, m);
+  case CEPH_CAP_OP_IMPORT:
   case CEPH_CAP_OP_REVOKE:
   case CEPH_CAP_OP_GRANT: return handle_cap_grant(session, in, cap, m);
   case CEPH_CAP_OP_FLUSH_ACK: return handle_cap_flush_ack(session, in, cap, m);
@@ -3471,11 +3508,20 @@ void Client::handle_cap_import(MetaSession *session, Inode *in, MClientCaps *m)
 {
   int mds = session->mds_num;
 
+  ldout(cct, 5) << "handle_cap_import ino " << m->get_ino() << " mseq " << m->get_mseq()
+		<< " IMPORT from mds." << mds << dendl;
+
   // add/update it
   update_snap_trace(m->snapbl);
   add_update_cap(in, session, m->get_cap_id(),
 		 m->get_caps(), m->get_seq(), m->get_mseq(), m->get_realm(),
 		 CEPH_CAP_FLAG_AUTH);
+
+  if (m->peer.cap_id && in->caps.count(m->peer.mds)) {
+    Cap *cap = in->caps[m->peer.mds];
+    if (cap && cap->cap_id == m->peer.cap_id)
+      remove_cap(cap, (m->peer.flags & CEPH_CAP_FLAG_RELEASE));
+  }
   
   if (in->auth_cap && in->auth_cap->session->mds_num == mds) {
     // reflush any/all caps (if we are now the auth_cap)
@@ -3484,65 +3530,44 @@ void Client::handle_cap_import(MetaSession *session, Inode *in, MClientCaps *m)
     if (in->flushing_caps)
       flush_caps(in, session);
   }
-
-  if (m->get_mseq() > in->exporting_mseq) {
-    ldout(cct, 5) << "handle_cap_import ino " << m->get_ino() << " mseq " << m->get_mseq()
-	    << " IMPORT from mds." << mds
-	    << ", clearing exporting_issued " << ccap_string(in->exporting_issued) 
-	    << " mseq " << in->exporting_mseq << dendl;
-    in->exporting_issued = 0;
-    in->exporting_mseq = 0;
-    in->exporting_mds = -1;
-  } else {
-    ldout(cct, 5) << "handle_cap_import ino " << m->get_ino() << " mseq " << m->get_mseq()
-	    << " IMPORT from mds." << mds 
-	    << ", keeping exporting_issued " << ccap_string(in->exporting_issued) 
-	    << " mseq " << in->exporting_mseq << " by mds." << in->exporting_mds << dendl;
-  }
-  m->put();
 }
 
 void Client::handle_cap_export(MetaSession *session, Inode *in, MClientCaps *m)
 {
   int mds = session->mds_num;
-  Cap *cap = NULL;
 
-  // note?
-  bool found_higher_mseq = false;
-  for (map<int,Cap*>::iterator p = in->caps.begin();
-       p != in->caps.end();
-       ++p) {
-    if (p->first == mds)
-      cap = p->second;
-    if (p->second->mseq > m->get_mseq()) {
-      found_higher_mseq = true;
-      ldout(cct, 5) << "handle_cap_export ino " << m->get_ino() << " mseq " << m->get_mseq() 
-	      << " EXPORT from mds." << mds
-	      << ", but mds." << p->first << " has higher mseq " << p->second->mseq << dendl;
-    }
-  }
-
-  if (cap) {
-    if (!found_higher_mseq) {
-      ldout(cct, 5) << "handle_cap_export ino " << m->get_ino() << " mseq " << m->get_mseq() 
-	      << " EXPORT from mds." << mds
-	      << ", setting exporting_issued " << ccap_string(cap->issued) << dendl;
-      in->exporting_issued = cap->issued;
-      in->exporting_mseq = m->get_mseq();
-      in->exporting_mds = mds;
-    } else 
-      ldout(cct, 5) << "handle_cap_export ino " << m->get_ino() << " mseq " << m->get_mseq() 
-	      << " EXPORT from mds." << mds
-	      << ", just removing old cap" << dendl;
-
-    remove_cap(cap);
-  }
-  // else we already released it
-
-  // open export targets, so we'll get the matching IMPORT, even if we
-  // have seen a newer import (or have released the cap entirely), as there
-  // may be an intervening revocation that will otherwise get blocked up.
-  connect_mds_targets(mds);
+  ldout(cct, 5) << "handle_cap_export ino " << m->get_ino() << " mseq " << m->get_mseq()
+		<< " EXPORT from mds." << mds << dendl;
+
+  if (in->caps.count(mds)) {
+    Cap *cap = in->caps[mds];
+
+    if (m->peer.cap_id) {
+      MetaSession *tsession = _get_or_open_mds_session(m->peer.mds);
+      if (in->caps.count(m->peer.mds)) {
+	Cap *tcap = in->caps[m->peer.mds];
+	if (tcap->cap_id != m->peer.cap_id ||
+	    ceph_seq_cmp(tcap->seq, m->peer.seq) < 0) {
+	  tcap->cap_id = m->peer.cap_id;
+	  tcap->seq = m->peer.seq - 1;
+	  tcap->issue_seq = tcap->seq;
+	  tcap->mseq = m->peer.mseq;
+	  tcap->issued |= cap->issued;
+	  tcap->implemented |= cap->issued;
+	  if (cap == in->auth_cap)
+	    in->auth_cap = tcap;
+	  if (in->auth_cap == tcap && in->flushing_cap_item.is_on_list())
+	    tsession->flushing_caps.push_back(&in->flushing_cap_item);
+	}
+      } else {
+	add_update_cap(in, tsession, m->peer.cap_id, cap->issued,
+		       m->peer.seq - 1, m->peer.mseq, (uint64_t)-1,
+		       cap == in->auth_cap ? CEPH_CAP_FLAG_AUTH : 0);
+      }
+    }
+
+    remove_cap(cap, false);
+  }
 
   m->put();
 }
@@ -3676,6 +3701,7 @@ void Client::handle_cap_grant(MetaSession *session, Inode *in, Cap *cap, MClient
 {
   int mds = session->mds_num;
   int used = in->caps_used();
+  int wanted = in->caps_wanted();
 
   const int old_caps = cap->issued;
   const int new_caps = m->get_caps();
@@ -3726,6 +3752,10 @@ void Client::handle_cap_grant(MetaSession *session, Inode *in, Cap *cap, MClient
     }
   }
 
+  bool check = false;
+  if (m->get_op() == CEPH_CAP_OP_IMPORT && m->get_wanted() != wanted)
+    check = true;
+
   check_cap_issue(in, cap, issued);
 
   // update caps
@@ -3742,7 +3772,7 @@ void Client::handle_cap_grant(MetaSession *session, Inode *in, Cap *cap, MClient
       // waitin' for flush
     } else {
       cap->wanted = 0; // don't let check_caps skip sending a response to MDS
-      check_caps(in, true);
+      check = true;
     }
 
   } else if (old_caps == new_caps) {
@@ -3751,8 +3781,23 @@ void Client::handle_cap_grant(MetaSession *session, Inode *in, Cap *cap, MClient
     ldout(cct, 10) << "  grant, new caps are " << ccap_string(new_caps & ~old_caps) << dendl;
     cap->issued = new_caps;
     cap->implemented |= new_caps;
+
+    if (cap == in->auth_cap) {
+      // non-auth MDS is revoking the newly grant caps ?
+      for (map<int,Cap*>::iterator it = in->caps.begin(); it != in->caps.end(); ++it) {
+	if (it->second == cap)
+	  continue;
+	if (it->second->implemented & ~it->second->issued & new_caps) {
+	  check = true;
+	  break;
+	}
+      }
+    }
   }
 
+  if (check)
+    check_caps(in, true);
+
   // wake up waiters
   if (new_caps)
     signal_cond_list(in->waitfor_caps);
@@ -4120,30 +4165,34 @@ int Client::_lookup(Inode *dir, const string& dname, Inode **target)
 	     << " seq " << dn->lease_seq
 	     << dendl;
 
-    // is dn lease valid?
-    utime_t now = ceph_clock_now(cct);
-    if (dn->lease_mds >= 0 &&
-	dn->lease_ttl > now &&
-	mds_sessions.count(dn->lease_mds)) {
-      MetaSession *s = mds_sessions[dn->lease_mds];
-      if (s->cap_ttl > now &&
-	  s->cap_gen == dn->lease_gen) {
+    if (!dn->inode || dn->inode->is_any_caps()) {
+      // is dn lease valid?
+      utime_t now = ceph_clock_now(cct);
+      if (dn->lease_mds >= 0 &&
+	  dn->lease_ttl > now &&
+	  mds_sessions.count(dn->lease_mds)) {
+	MetaSession *s = mds_sessions[dn->lease_mds];
+	if (s->cap_ttl > now &&
+	    s->cap_gen == dn->lease_gen) {
+	  *target = dn->inode;
+	  // touch this mds's dir cap too, even though we don't _explicitly_ use it here, to
+	  // make trim_caps() behave.
+	  dir->try_touch_cap(dn->lease_mds);
+	  touch_dn(dn);
+	  goto done;
+	}
+	ldout(cct, 20) << " bad lease, cap_ttl " << s->cap_ttl << ", cap_gen " << s->cap_gen
+		       << " vs lease_gen " << dn->lease_gen << dendl;
+      }
+      // dir lease?
+      if (dir->caps_issued_mask(CEPH_CAP_FILE_SHARED) &&
+	  dn->cap_shared_gen == dir->shared_gen) {
 	*target = dn->inode;
-	// touch this mds's dir cap too, even though we don't _explicitly_ use it here, to
-	// make trim_caps() behave.
-	dir->try_touch_cap(dn->lease_mds);
 	touch_dn(dn);
 	goto done;
       }
-      ldout(cct, 20) << " bad lease, cap_ttl " << s->cap_ttl << ", cap_gen " << s->cap_gen
-	       << " vs lease_gen " << dn->lease_gen << dendl;
-    }
-    // dir lease?
-    if (dir->caps_issued_mask(CEPH_CAP_FILE_SHARED) &&
-	dn->cap_shared_gen == dir->shared_gen) {
-      *target = dn->inode;
-      touch_dn(dn);
-      goto done;
+    } else {
+      ldout(cct, 20) << " no cap on " << dn->inode->vino() << dendl;
     }
   } else {
     // can we conclude ENOENT locally?
@@ -5618,7 +5667,15 @@ int Client::lookup_hash(inodeno_t ino, inodeno_t dirino, const char *name)
   return r;
 }
 
-int Client::lookup_ino(inodeno_t ino)
+
+/**
+ * Load inode into local cache.
+ *
+ * If inode pointer is non-NULL, and take a reference on
+ * the resulting Inode object in one operation, so that caller
+ * can safely assume inode will still be there after return.
+ */
+int Client::lookup_ino(inodeno_t ino, Inode **inode)
 {
   Mutex::Locker lock(client_lock);
   ldout(cct, 3) << "lookup_ino enter(" << ino << ") = " << dendl;
@@ -5628,10 +5685,77 @@ int Client::lookup_ino(inodeno_t ino)
   req->set_filepath(path);
 
   int r = make_request(req, -1, -1, NULL, NULL, rand() % mdsmap->get_num_in_mds());
+  if (r == 0 && inode != NULL) {
+    vinodeno_t vino(ino, CEPH_NOSNAP);
+    unordered_map<vinodeno_t,Inode*>::iterator p = inode_map.find(vino);
+    assert(p != inode_map.end());
+    *inode = p->second;
+    _ll_get(*inode);
+  }
   ldout(cct, 3) << "lookup_ino exit(" << ino << ") = " << r << dendl;
   return r;
 }
 
+
+
+/**
+ * Find the parent inode of `ino` and insert it into
+ * our cache.  Conditionally also set `parent` to a referenced
+ * Inode* if caller provides non-NULL value.
+ */
+int Client::lookup_parent(Inode *ino, Inode **parent)
+{
+  Mutex::Locker lock(client_lock);
+  ldout(cct, 3) << "lookup_parent enter(" << ino->ino << ") = " << dendl;
+
+  if (!ino->dn_set.empty()) {
+    ldout(cct, 3) << "lookup_parent dentry already present" << dendl;
+    return 0;
+  }
+
+  MetaRequest *req = new MetaRequest(CEPH_MDS_OP_LOOKUPPARENT);
+  filepath path(ino->ino);
+  req->set_filepath(path);
+  req->set_inode(ino);
+
+  int r = make_request(req, -1, -1, NULL, NULL, rand() % mdsmap->get_num_in_mds());
+  // Give caller a reference to the parent ino if they provided a pointer.
+  if (parent != NULL) {
+    if (r == 0) {
+      *parent = req->target;
+      _ll_get(*parent);
+      ldout(cct, 3) << "lookup_parent found parent " << (*parent)->ino << dendl;
+    } else {
+      *parent = NULL;
+    }
+  }
+  ldout(cct, 3) << "lookup_parent exit(" << ino->ino << ") = " << r << dendl;
+  return r;
+}
+
+
+/**
+ * Populate the parent dentry for `ino`, provided it is
+ * a child of `parent`.
+ */
+int Client::lookup_name(Inode *ino, Inode *parent)
+{
+  assert(parent->is_dir());
+
+  Mutex::Locker lock(client_lock);
+  ldout(cct, 3) << "lookup_name enter(" << ino->ino << ") = " << dendl;
+
+  MetaRequest *req = new MetaRequest(CEPH_MDS_OP_LOOKUPNAME);
+  req->set_filepath2(filepath(parent->ino));
+  req->set_filepath(filepath(ino->ino));
+  req->set_inode(ino);
+
+  int r = make_request(req, -1, -1, NULL, NULL, rand() % mdsmap->get_num_in_mds());
+  ldout(cct, 3) << "lookup_name exit(" << ino->ino << ") = " << r << dendl;
+  return r;
+}
+
+
 Fh *Client::_create_fh(Inode *in, int flags, int cmode)
 {
   // yay
@@ -6066,8 +6190,17 @@ int Client::_read_async(Fh *f, uint64_t off, uint64_t len, bufferlist *bl)
       if (objectcacher->file_is_cached(&in->oset, &in->layout, in->snapid, off, min))
 	ldout(cct, 20) << "readahead already have min" << dendl;
       else {
-	objectcacher->file_read(&in->oset, &in->layout, in->snapid, off, l, NULL, 0, 0);
-	ldout(cct, 20) << "readahead initiated" << dendl;
+	Context *onfinish = new C_Readahead(this, in);
+	int r = objectcacher->file_read(&in->oset, &in->layout, in->snapid,
+					off, l,
+					NULL, 0, onfinish);
+	if (r == 0) {
+	  ldout(cct, 20) << "readahead initiated, c " << onfinish << dendl;
+	  in->get();
+	} else {
+	  ldout(cct, 20) << "readahead was no-op, already cached" << dendl;
+	  delete onfinish;
+	}
       }
     }
   }
@@ -6464,7 +6597,7 @@ int Client::_fsync(Fh *f, bool syncdataonly)
   int r = 0;
 
   Inode *in = f->inode;
-  tid_t wait_on_flush = 0;
+  ceph_tid_t wait_on_flush = 0;
   bool flushed_metadata = false;
   Mutex lock("Client::_fsync::lock");
   Cond cond;
@@ -7193,18 +7326,11 @@ int Client::_listxattr(Inode *in, char *name, size_t size, int uid, int gid)
 {
   int r = _getattr(in, CEPH_STAT_CAP_XATTR, uid, gid);
   if (r == 0) {
-    const char file_vxattrs[] = "ceph.file.layout";
-    const char dir_vxattrs[] = "ceph.dir.layout";
     for (map<string,bufferptr>::iterator p = in->xattrs.begin();
 	 p != in->xattrs.end();
 	 ++p)
       r += p->first.length() + 1;
 
-    if (in->is_file())
-      r += sizeof(file_vxattrs);
-    else if (in->is_dir() && in->has_dir_layout())
-      r += sizeof(dir_vxattrs);
-
     if (size != 0) {
       if (size >= (unsigned)r) {
 	for (map<string,bufferptr>::iterator p = in->xattrs.begin();
@@ -7215,13 +7341,6 @@ int Client::_listxattr(Inode *in, char *name, size_t size, int uid, int gid)
 	  *name = '\0';
 	  name++;
 	}
-	if (in->is_file()) {
-	  memcpy(name, file_vxattrs, sizeof(file_vxattrs));
-	  name += sizeof(file_vxattrs);
-	} else if (in->is_dir() && in->has_dir_layout()) {
-	  memcpy(name, dir_vxattrs, sizeof(dir_vxattrs));
-	  name += sizeof(dir_vxattrs);
-	}
       } else
 	r = -ERANGE;
     }
diff --git a/src/client/Client.h b/src/client/Client.h
index bd30c09..458dd4c 100644
--- a/src/client/Client.h
+++ b/src/client/Client.h
@@ -255,8 +255,8 @@ public:
   void resend_unsafe_requests(MetaSession *s);
 
   // mds requests
-  tid_t last_tid, last_flush_seq;
-  map<tid_t, MetaRequest*> mds_requests;
+  ceph_tid_t last_tid, last_flush_seq;
+  map<ceph_tid_t, MetaRequest*> mds_requests;
   set<int>                 failed_mds;
 
   void dump_mds_requests(Formatter *f);
@@ -445,7 +445,7 @@ protected:
   void add_update_cap(Inode *in, MetaSession *session, uint64_t cap_id,
 		      unsigned issued, unsigned seq, unsigned mseq, inodeno_t realm,
 		      int flags);
-  void remove_cap(Cap *cap);
+  void remove_cap(Cap *cap, bool queue_release);
   void remove_all_caps(Inode *in);
   void remove_session_caps(MetaSession *session);
   void mark_caps_dirty(Inode *in, int caps);
@@ -547,6 +547,8 @@ private:
   void _closedir(dir_result_t *dirp);
 
   // other helpers
+  void _fragmap_remove_non_leaves(Inode *in);
+
   void _ll_get(Inode *in);
   int _ll_put(Inode *in, int num);
   void _ll_drop_pins();
@@ -554,6 +556,19 @@ private:
   Fh *_create_fh(Inode *in, int flags, int cmode);
   int _release_fh(Fh *fh);
 
+
+  struct C_Readahead : public Context {
+    Client *client;
+    Inode *inode;
+    C_Readahead(Client *c, Inode *i)
+      : client(c),
+	inode(i) { }
+    void finish(int r) {
+      lsubdout(client->cct, client, 20) << "C_Readahead on " << inode << dendl;
+      client->put_inode(inode, 1);
+    }
+  };
+
   int _read_sync(Fh *f, uint64_t off, uint64_t len, bufferlist *bl);
   int _read_async(Fh *f, uint64_t off, uint64_t len, bufferlist *bl);
 
@@ -680,7 +695,9 @@ public:
   int open(const char *path, int flags, mode_t mode=0);
   int open(const char *path, int flags, mode_t mode, int stripe_unit, int stripe_count, int object_size, const char *data_pool);
   int lookup_hash(inodeno_t ino, inodeno_t dirino, const char *name);
-  int lookup_ino(inodeno_t ino);
+  int lookup_ino(inodeno_t ino, Inode **inode=NULL);
+  int lookup_parent(Inode *in, Inode **parent=NULL);
+  int lookup_name(Inode *in, Inode *parent);
   int close(int fd);
   loff_t lseek(int fd, loff_t offset, int whence);
   int read(int fd, char *buf, loff_t size, loff_t offset=-1);
diff --git a/src/client/Inode.cc b/src/client/Inode.cc
index 4e53e14..0d9d9d9 100644
--- a/src/client/Inode.cc
+++ b/src/client/Inode.cc
@@ -137,7 +137,7 @@ bool Inode::put_cap_ref(int cap)
 
 bool Inode::is_any_caps()
 {
-  return caps.size() || exporting_mds >= 0;
+  return caps.size();
 }
 
 bool Inode::cap_is_valid(Cap* cap)
@@ -155,7 +155,7 @@ bool Inode::cap_is_valid(Cap* cap)
 
 int Inode::caps_issued(int *implemented)
 {
-  int c = exporting_issued | snap_caps;
+  int c = snap_caps;
   int i = 0;
   for (map<int,Cap*>::iterator it = caps.begin();
        it != caps.end();
@@ -183,7 +183,7 @@ void Inode::try_touch_cap(int mds)
 
 bool Inode::caps_issued_mask(unsigned mask)
 {
-  int c = exporting_issued | snap_caps;
+  int c = snap_caps;
   if ((c & mask) == mask)
     return true;
   // prefer auth cap
@@ -390,10 +390,6 @@ void Inode::dump(Formatter *f) const
     f->dump_int("snap_caps", snap_caps);
     f->dump_int("snap_cap_refs", snap_cap_refs);
   }
-  if (exporting_issued || exporting_mseq) {
-    f->dump_stream("exporting_issued") << ccap_string(exporting_issued);
-    f->dump_int("exporting_mseq", exporting_mds);
-  }
 
   f->dump_stream("hold_caps_until") << hold_caps_until;
   f->dump_unsigned("last_flush_tid", last_flush_tid);
diff --git a/src/client/Inode.h b/src/client/Inode.h
index b6c7a38..d8e001f 100644
--- a/src/client/Inode.h
+++ b/src/client/Inode.h
@@ -126,6 +126,13 @@ class Inode {
     return false;
   }
 
+  __u32 hash_dentry_name(const string &dn) {
+    int which = dir_layout.dl_dir_hash;
+    if (!which)
+      which = CEPH_STR_HASH_LINUX;
+    return ceph_str_hash(which, dn.data(), dn.length());
+  }
+
   unsigned flags;
 
   // about the dir (if this is one!)
@@ -140,12 +147,9 @@ class Inode {
   __u16 flushing_cap_tid[CEPH_CAP_BITS];
   int shared_gen, cache_gen;
   int snap_caps, snap_cap_refs;
-  unsigned exporting_issued;
-  int exporting_mds;
-  ceph_seq_t exporting_mseq;
   utime_t hold_caps_until;
   xlist<Inode*>::item cap_item, flushing_cap_item;
-  tid_t last_flush_tid;
+  ceph_tid_t last_flush_tid;
 
   SnapRealm *snaprealm;
   xlist<Inode*>::item snaprealm_item;
@@ -216,7 +220,6 @@ class Inode {
       dir_hashed(false), dir_replicated(false), auth_cap(NULL),
       dirty_caps(0), flushing_caps(0), flushing_cap_seq(0), shared_gen(0), cache_gen(0),
       snap_caps(0), snap_cap_refs(0),
-      exporting_issued(0), exporting_mds(-1), exporting_mseq(0),
       cap_item(this), flushing_cap_item(this), last_flush_tid(0),
       snaprealm(0), snaprealm_item(this), snapdir_parent(0),
       oset((void *)this, newlayout->fl_pg_pool, ino),
diff --git a/src/client/MetaRequest.h b/src/client/MetaRequest.h
index 5583cd1..45a90dc 100644
--- a/src/client/MetaRequest.h
+++ b/src/client/MetaRequest.h
@@ -140,8 +140,8 @@ public:
   }
 
   // normal fields
-  void set_tid(tid_t t) { tid = t; }
-  void set_oldest_client_tid(tid_t t) { head.oldest_client_tid = t; }
+  void set_tid(ceph_tid_t t) { tid = t; }
+  void set_oldest_client_tid(ceph_tid_t t) { head.oldest_client_tid = t; }
   void inc_num_fwd() { head.num_fwd = head.num_fwd + 1; }
   void set_retry_attempt(int a) { head.num_retry = a; }
   void set_filepath(const filepath& fp) { path = fp; }
@@ -154,7 +154,7 @@ public:
     head.flags = head.flags | CEPH_MDS_FLAG_WANT_DENTRY;
   }
   int get_op() { return head.op; }
-  tid_t get_tid() { return tid; }
+  ceph_tid_t get_tid() { return tid; }
   filepath& get_filepath() { return path; }
   filepath& get_filepath2() { return path2; }
 
diff --git a/src/client/ObjecterWriteback.h b/src/client/ObjecterWriteback.h
index 9a10fb4..f2d903a 100644
--- a/src/client/ObjecterWriteback.h
+++ b/src/client/ObjecterWriteback.h
@@ -23,7 +23,7 @@ class ObjecterWriteback : public WritebackHandler {
     return false;
   }
 
-  virtual tid_t write(const object_t& oid, const object_locator_t& oloc,
+  virtual ceph_tid_t write(const object_t& oid, const object_locator_t& oloc,
 		      uint64_t off, uint64_t len, const SnapContext& snapc,
 		      const bufferlist &bl, utime_t mtime, uint64_t trunc_size,
 		      __u32 trunc_seq, Context *oncommit) {
@@ -31,7 +31,7 @@ class ObjecterWriteback : public WritebackHandler {
 				   trunc_size, trunc_seq, NULL, oncommit);
   }
 
-  virtual tid_t lock(const object_t& oid, const object_locator_t& oloc, int op,
+  virtual ceph_tid_t lock(const object_t& oid, const object_locator_t& oloc, int op,
 		     int flags, Context *onack, Context *oncommit) {
     return m_objecter->lock(oid, oloc, op, flags, onack, oncommit);
   }
diff --git a/src/client/SyntheticClient.cc b/src/client/SyntheticClient.cc
index 7129a5c..44dd2a8 100644
--- a/src/client/SyntheticClient.cc
+++ b/src/client/SyntheticClient.cc
@@ -1269,8 +1269,8 @@ int SyntheticClient::play_trace(Trace& t, string& prefix, bool metadata_only)
       }
     } else if (strcmp(op, "ll_readlink") == 0) {
       int64_t i = t.get_int();
-      char buf[PATH_MAX];
       if (ll_inos.count(i)) {
+        char buf[PATH_MAX];
 	i1 = client->ll_get_inode(vinodeno_t(ll_inos[i],CEPH_NOSNAP));
 	client->ll_readlink(i1, buf, sizeof(buf));
 	client->ll_put(i1);
diff --git a/src/client/fuse_ll.cc b/src/client/fuse_ll.cc
index d9f6a8d..14cb6d4 100644
--- a/src/client/fuse_ll.cc
+++ b/src/client/fuse_ll.cc
@@ -591,6 +591,11 @@ static void fuse_ll_releasedir(fuse_req_t req, fuse_ino_t ino,
   fuse_reply_err(req, 0);
 }
 
+static void fuse_ll_access(fuse_req_t req, fuse_ino_t ino, int mask)
+{
+  fuse_reply_err(req, 0);
+}
+
 static void fuse_ll_create(fuse_req_t req, fuse_ino_t parent, const char *name,
 			   mode_t mode, struct fuse_file_info *fi)
 {
@@ -733,7 +738,7 @@ const static struct fuse_lowlevel_ops fuse_ll_oper = {
  getxattr: fuse_ll_getxattr,
  listxattr: fuse_ll_listxattr,
  removexattr: fuse_ll_removexattr,
- access: 0,
+ access: fuse_ll_access,
  create: fuse_ll_create,
  getlk: 0,
  setlk: 0,
diff --git a/src/cls/user/cls_user_types.cc b/src/cls/user/cls_user_types.cc
index 1ccd19b..b3a00f0 100644
--- a/src/cls/user/cls_user_types.cc
+++ b/src/cls/user/cls_user_types.cc
@@ -21,6 +21,7 @@ void cls_user_bucket::dump(Formatter *f) const
 {
   encode_json("name", name, f);
   encode_json("data_pool", data_pool,f);
+  encode_json("data_extra_pool", data_extra_pool,f);
   encode_json("index_pool", index_pool,f);
   encode_json("marker", marker,f);
   encode_json("bucket_id", bucket_id,f);
diff --git a/src/cls/user/cls_user_types.h b/src/cls/user/cls_user_types.h
index fce25c3..5abb488 100644
--- a/src/cls/user/cls_user_types.h
+++ b/src/cls/user/cls_user_types.h
@@ -17,18 +17,20 @@ struct cls_user_bucket {
   std::string index_pool;
   std::string marker;
   std::string bucket_id;
+  std::string data_extra_pool;
 
   void encode(bufferlist& bl) const {
-     ENCODE_START(6, 3, bl);
+     ENCODE_START(7, 3, bl);
     ::encode(name, bl);
     ::encode(data_pool, bl);
     ::encode(marker, bl);
     ::encode(bucket_id, bl);
     ::encode(index_pool, bl);
+    ::encode(data_extra_pool, bl);
     ENCODE_FINISH(bl);
   }
   void decode(bufferlist::iterator& bl) {
-    DECODE_START_LEGACY_COMPAT_LEN(6, 3, 3, bl);
+    DECODE_START_LEGACY_COMPAT_LEN(7, 3, 3, bl);
     ::decode(name, bl);
     ::decode(data_pool, bl);
     if (struct_v >= 2) {
@@ -48,6 +50,9 @@ struct cls_user_bucket {
     } else {
       index_pool = data_pool;
     }
+    if (struct_v >= 7) {
+      ::decode(data_extra_pool, bl);
+    }
     DECODE_FINISH(bl);
   }
 
diff --git a/src/common/Formatter.cc b/src/common/Formatter.cc
index 4ef833a..8a6aed2 100644
--- a/src/common/Formatter.cc
+++ b/src/common/Formatter.cc
@@ -63,7 +63,7 @@ Formatter::~Formatter()
 }
 
 Formatter *
-new_formatter(const std::string type)
+new_formatter(const std::string &type)
 {
     std::string mytype = type;
     if (mytype == "")
diff --git a/src/common/Formatter.h b/src/common/Formatter.h
index ac68b7f..87b225a 100644
--- a/src/common/Formatter.h
+++ b/src/common/Formatter.h
@@ -65,7 +65,7 @@ class Formatter {
   }
 };
 
-Formatter *new_formatter(const std::string type);
+Formatter *new_formatter(const std::string &type);
 
 class JSONFormatter : public Formatter {
  public:
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index f39ab4e..9769e2f 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -71,11 +71,6 @@ libcommon_la_SOURCES = \
 	common/bloom_filter.cc \
 	common/linux_version.c
 
-if LINUX
-libcommon_la_SOURCES += \
-	common/secret.c
-endif
-
 # these should go out of libcommon
 libcommon_la_SOURCES += \
 	mon/MonCap.cc \
@@ -112,9 +107,9 @@ noinst_HEADERS += \
 
 # important; libmsg before libauth!
 LIBCOMMON_DEPS += \
+	$(LIBERASURE_CODE) \
 	$(LIBMSG) $(LIBAUTH) \
-	$(LIBCRUSH) $(LIBJSON_SPIRIT) $(LIBLOG) $(LIBARCH) \
-	$(KEYUTILS_LIB)
+	$(LIBCRUSH) $(LIBJSON_SPIRIT) $(LIBLOG) $(LIBARCH)
 
 if LINUX
 LIBCOMMON_DEPS += -lrt
diff --git a/src/common/OutputDataSocket.cc b/src/common/OutputDataSocket.cc
index 3051ca0..2c4526d 100644
--- a/src/common/OutputDataSocket.cc
+++ b/src/common/OutputDataSocket.cc
@@ -62,7 +62,7 @@ static bool cleanup_atexit = false;
 static void remove_cleanup_file(const char *file)
 {
   pthread_mutex_lock(&cleanup_lock);
-  TEMP_FAILURE_RETRY(unlink(file));
+  VOID_TEMP_FAILURE_RETRY(unlink(file));
   for (std::vector <const char*>::iterator i = cleanup_files.begin();
        i != cleanup_files.end(); ++i) {
     if (strcmp(file, *i) == 0) {
@@ -79,7 +79,7 @@ static void remove_all_cleanup_files()
   pthread_mutex_lock(&cleanup_lock);
   for (std::vector <const char*>::iterator i = cleanup_files.begin();
        i != cleanup_files.end(); ++i) {
-    TEMP_FAILURE_RETRY(unlink(*i));
+    VOID_TEMP_FAILURE_RETRY(unlink(*i));
     free((void*)*i);
   }
   cleanup_files.clear();
@@ -170,7 +170,7 @@ std::string OutputDataSocket::bind_and_listen(const std::string &sock_path, int
   int r = fcntl(sock_fd, F_SETFD, FD_CLOEXEC);
   if (r < 0) {
     r = errno;
-    TEMP_FAILURE_RETRY(::close(sock_fd));
+    VOID_TEMP_FAILURE_RETRY(::close(sock_fd));
     ostringstream oss;
     oss << "OutputDataSocket::bind_and_listen: failed to fcntl on socket: " << cpp_strerror(r);
     return oss.str();
@@ -185,7 +185,7 @@ std::string OutputDataSocket::bind_and_listen(const std::string &sock_path, int
     if (err == EADDRINUSE) {
       // The old UNIX domain socket must still be there.
       // Let's unlink it and try again.
-      TEMP_FAILURE_RETRY(unlink(sock_path.c_str()));
+      VOID_TEMP_FAILURE_RETRY(unlink(sock_path.c_str()));
       if (bind(sock_fd, (struct sockaddr*)&address,
 	       sizeof(struct sockaddr_un)) == 0) {
 	err = 0;
@@ -209,7 +209,7 @@ std::string OutputDataSocket::bind_and_listen(const std::string &sock_path, int
     oss << "OutputDataSocket::bind_and_listen: "
 	  << "failed to listen to socket: " << cpp_strerror(err);
     close(sock_fd);
-    TEMP_FAILURE_RETRY(unlink(sock_path.c_str()));
+    VOID_TEMP_FAILURE_RETRY(unlink(sock_path.c_str()));
     return oss.str();
   }
   *fd = sock_fd;
@@ -342,7 +342,7 @@ int OutputDataSocket::dump_data(int fd)
 
 void OutputDataSocket::close_connection(int fd)
 {
-  TEMP_FAILURE_RETRY(close(fd));
+  VOID_TEMP_FAILURE_RETRY(close(fd));
 }
 
 bool OutputDataSocket::init(const std::string &path)
@@ -391,7 +391,7 @@ void OutputDataSocket::shutdown()
   // Send a byte to the shutdown pipe that the thread is listening to
   char buf[1] = { 0x0 };
   int ret = safe_write(m_shutdown_wr_fd, buf, sizeof(buf));
-  TEMP_FAILURE_RETRY(close(m_shutdown_wr_fd));
+  VOID_TEMP_FAILURE_RETRY(close(m_shutdown_wr_fd));
   m_shutdown_wr_fd = -1;
 
   if (ret == 0) {
diff --git a/src/common/PrioritizedQueue.h b/src/common/PrioritizedQueue.h
index d936d5d..ee1dc9c 100644
--- a/src/common/PrioritizedQueue.h
+++ b/src/common/PrioritizedQueue.h
@@ -171,11 +171,8 @@ class PrioritizedQueue {
       if (i == q.end())
 	return;
       size -= i->second.size();
-      if (i == cur) {
+      if (i == cur)
 	++cur;
-	if (cur == q.end())
-	  cur = q.begin();
-      }
       if (out) {
 	for (typename list<pair<unsigned, T> >::reverse_iterator j =
 	       i->second.rbegin();
@@ -185,6 +182,8 @@ class PrioritizedQueue {
 	}
       }
       q.erase(i);
+      if (cur == q.end())
+	cur = q.begin();
     }
 
     void dump(Formatter *f) const {
@@ -192,6 +191,8 @@ class PrioritizedQueue {
       f->dump_int("max_tokens", max_tokens);
       f->dump_int("size", size);
       f->dump_int("num_keys", q.size());
+      if (!empty())
+	f->dump_int("first_item_cost", front().first);
     }
   };
   map<unsigned, SubQueue> high_queue;
@@ -231,15 +232,15 @@ public:
       min_cost(min_c)
   {}
 
-  unsigned length() {
+  unsigned length() const {
     unsigned total = 0;
-    for (typename map<unsigned, SubQueue>::iterator i = queue.begin();
+    for (typename map<unsigned, SubQueue>::const_iterator i = queue.begin();
 	 i != queue.end();
 	 ++i) {
       assert(i->second.length());
       total += i->second.length();
     }
-    for (typename map<unsigned, SubQueue>::iterator i = high_queue.begin();
+    for (typename map<unsigned, SubQueue>::const_iterator i = high_queue.begin();
 	 i != high_queue.end();
 	 ++i) {
       assert(i->second.length());
@@ -324,7 +325,7 @@ public:
     create_queue(priority)->enqueue_front(cl, cost, item);
   }
 
-  bool empty() {
+  bool empty() const {
     assert(total_priority >= 0);
     assert((total_priority == 0) || !(queue.empty()));
     return queue.empty() && high_queue.empty();
diff --git a/src/common/admin_socket.cc b/src/common/admin_socket.cc
index 1190b6d..4af2904 100644
--- a/src/common/admin_socket.cc
+++ b/src/common/admin_socket.cc
@@ -65,7 +65,7 @@ static bool cleanup_atexit = false;
 static void remove_cleanup_file(const char *file)
 {
   pthread_mutex_lock(&cleanup_lock);
-  TEMP_FAILURE_RETRY(unlink(file));
+  VOID_TEMP_FAILURE_RETRY(unlink(file));
   for (std::vector <const char*>::iterator i = cleanup_files.begin();
        i != cleanup_files.end(); ++i) {
     if (strcmp(file, *i) == 0) {
@@ -82,7 +82,7 @@ static void remove_all_cleanup_files()
   pthread_mutex_lock(&cleanup_lock);
   for (std::vector <const char*>::iterator i = cleanup_files.begin();
        i != cleanup_files.end(); ++i) {
-    TEMP_FAILURE_RETRY(unlink(*i));
+    VOID_TEMP_FAILURE_RETRY(unlink(*i));
     free((void*)*i);
   }
   cleanup_files.clear();
@@ -111,7 +111,8 @@ AdminSocket::AdminSocket(CephContext *cct)
     m_shutdown_wr_fd(-1),
     m_lock("AdminSocket::m_lock"),
     m_version_hook(NULL),
-    m_help_hook(NULL)
+    m_help_hook(NULL),
+    m_getdescs_hook(NULL)
 {
 }
 
@@ -172,7 +173,7 @@ std::string AdminSocket::bind_and_listen(const std::string &sock_path, int *fd)
   int r = fcntl(sock_fd, F_SETFD, FD_CLOEXEC);
   if (r < 0) {
     r = errno;
-    TEMP_FAILURE_RETRY(::close(sock_fd));
+    VOID_TEMP_FAILURE_RETRY(::close(sock_fd));
     ostringstream oss;
     oss << "AdminSocket::bind_and_listen: failed to fcntl on socket: " << cpp_strerror(r);
     return oss.str();
@@ -193,7 +194,7 @@ std::string AdminSocket::bind_and_listen(const std::string &sock_path, int *fd)
 	err = EEXIST;
       } else {
 	ldout(m_cct, 20) << "unlink stale file " << sock_path << dendl;
-	TEMP_FAILURE_RETRY(unlink(sock_path.c_str()));
+	VOID_TEMP_FAILURE_RETRY(unlink(sock_path.c_str()));
 	if (bind(sock_fd, (struct sockaddr*)&address,
 		 sizeof(struct sockaddr_un)) == 0) {
 	  err = 0;
@@ -217,7 +218,7 @@ std::string AdminSocket::bind_and_listen(const std::string &sock_path, int *fd)
     oss << "AdminSocket::bind_and_listen: "
 	  << "failed to listen to socket: " << cpp_strerror(err);
     close(sock_fd);
-    TEMP_FAILURE_RETRY(unlink(sock_path.c_str()));
+    VOID_TEMP_FAILURE_RETRY(unlink(sock_path.c_str()));
     return oss.str();
   }
   *fd = sock_fd;
@@ -386,7 +387,7 @@ bool AdminSocket::do_accept()
   }
   m_lock.Unlock();
 
-  TEMP_FAILURE_RETRY(close(connection_fd));
+  VOID_TEMP_FAILURE_RETRY(close(connection_fd));
   return rval;
 }
 
@@ -551,7 +552,7 @@ void AdminSocket::shutdown()
   // Send a byte to the shutdown pipe that the thread is listening to
   char buf[1] = { 0x0 };
   int ret = safe_write(m_shutdown_wr_fd, buf, sizeof(buf));
-  TEMP_FAILURE_RETRY(close(m_shutdown_wr_fd));
+  VOID_TEMP_FAILURE_RETRY(close(m_shutdown_wr_fd));
   m_shutdown_wr_fd = -1;
 
   if (ret == 0) {
diff --git a/src/common/buffer.cc b/src/common/buffer.cc
index e6f989c..71f665d 100644
--- a/src/common/buffer.cc
+++ b/src/common/buffer.cc
@@ -399,9 +399,9 @@ static uint32_t simple_spinlock_t buffer_debug_lock = SIMPLE_SPINLOCK_INITIALIZE
 
     void close_pipe(int *fds) {
       if (fds[0] >= 0)
-	TEMP_FAILURE_RETRY(::close(fds[0]));
+	VOID_TEMP_FAILURE_RETRY(::close(fds[0]));
       if (fds[1] >= 0)
-	TEMP_FAILURE_RETRY(::close(fds[1]));
+	VOID_TEMP_FAILURE_RETRY(::close(fds[1]));
     }
     char *copy_pipe(int *fds) {
       /* preserve original pipe contents by copying into a temporary
@@ -1496,7 +1496,7 @@ int buffer::list::read_file(const char *fn, std::string *error)
     oss << "bufferlist::read_file(" << fn << "): read error:"
 	<< cpp_strerror(ret);
     *error = oss.str();
-    TEMP_FAILURE_RETRY(::close(fd));
+    VOID_TEMP_FAILURE_RETRY(::close(fd));
     return ret;
   }
   else if (ret != st.st_size) {
@@ -1507,7 +1507,7 @@ int buffer::list::read_file(const char *fn, std::string *error)
     *error = oss.str();
     // not actually an error, but weird
   }
-  TEMP_FAILURE_RETRY(::close(fd));
+  VOID_TEMP_FAILURE_RETRY(::close(fd));
   return 0;
 }
 
@@ -1559,7 +1559,7 @@ int buffer::list::write_file(const char *fn, int mode)
   if (ret) {
     cerr << "bufferlist::write_fd(" << fn << "): write_fd error: "
 	 << cpp_strerror(ret) << std::endl;
-    TEMP_FAILURE_RETRY(::close(fd));
+    VOID_TEMP_FAILURE_RETRY(::close(fd));
     return ret;
   }
   if (TEMP_FAILURE_RETRY(::close(fd))) {
diff --git a/src/common/ceph_argparse.cc b/src/common/ceph_argparse.cc
index eb000dc..a76c424 100644
--- a/src/common/ceph_argparse.cc
+++ b/src/common/ceph_argparse.cc
@@ -62,7 +62,7 @@ bool split_dashdash(const std::vector<const char*>& args,
   bool dashdash = false;
   for (std::vector<const char*>::const_iterator i = args.begin();
        i != args.end();
-       i++) {
+       ++i) {
     if (dashdash) {
       arguments.push_back(*i);
     } else {
diff --git a/src/common/ceph_crypto.cc b/src/common/ceph_crypto.cc
index 96fa157..b81ffdf 100644
--- a/src/common/ceph_crypto.cc
+++ b/src/common/ceph_crypto.cc
@@ -37,14 +37,20 @@ ceph::crypto::HMACSHA1::~HMACSHA1()
 
 #elif USE_NSS
 
+// Initialization of NSS requires a mutex due to a race condition in
+// NSS_NoDB_Init.
+static pthread_mutex_t crypto_init_mutex = PTHREAD_MUTEX_INITIALIZER;
+
 void ceph::crypto::init(CephContext *cct)
 {
   SECStatus s;
+  pthread_mutex_lock(&crypto_init_mutex);
   if (cct->_conf->nss_db_path.empty()) {
     s = NSS_NoDB_Init(NULL);
   } else {
     s = NSS_Init(cct->_conf->nss_db_path.c_str());
   }
+  pthread_mutex_unlock(&crypto_init_mutex);
   assert(s == SECSuccess);
 }
 
diff --git a/src/common/config_opts.h b/src/common/config_opts.h
index f8711e0..ff674cf 100644
--- a/src/common/config_opts.h
+++ b/src/common/config_opts.h
@@ -126,6 +126,7 @@ OPTION(ms_inject_delay_msg_type, OPT_STR, "")      // the type of message to del
 OPTION(ms_inject_delay_max, OPT_DOUBLE, 1)         // seconds
 OPTION(ms_inject_delay_probability, OPT_DOUBLE, 0) // range [0, 1]
 OPTION(ms_inject_internal_delays, OPT_DOUBLE, 0)   // seconds
+OPTION(ms_dump_on_send, OPT_BOOL, false)           // hexdump msg to log on send
 
 OPTION(inject_early_sigterm, OPT_BOOL, false)
 
@@ -151,6 +152,7 @@ OPTION(mon_osd_min_up_ratio, OPT_DOUBLE, .3)    // min osds required to be up to
 OPTION(mon_osd_min_in_ratio, OPT_DOUBLE, .3)   // min osds required to be in to mark things out
 OPTION(mon_osd_max_op_age, OPT_DOUBLE, 32)     // max op age before we get concerned (make it a power of 2)
 OPTION(mon_osd_max_split_count, OPT_INT, 32) // largest number of PGs per "involved" OSD to let split create
+OPTION(mon_osd_allow_primary_temp, OPT_BOOL, false)  // allow primary_temp to be set in the osdmap
 OPTION(mon_osd_allow_primary_affinity, OPT_BOOL, false)  // allow primary_affinity to be set in the osdmap
 OPTION(mon_stat_smooth_intervals, OPT_INT, 2)  // smooth stats over last N PGMap maps
 OPTION(mon_lease, OPT_FLOAT, 5)       // lease interval
@@ -241,6 +243,7 @@ OPTION(auth_service_ticket_ttl, OPT_DOUBLE, 60*60)
 OPTION(auth_debug, OPT_BOOL, false)          // if true, assert when weird things happen
 OPTION(mon_client_hunt_interval, OPT_DOUBLE, 3.0)   // try new mon every N seconds until we connect
 OPTION(mon_client_ping_interval, OPT_DOUBLE, 10.0)  // ping every N seconds
+OPTION(mon_client_ping_timeout, OPT_DOUBLE, 30.0)   // fail if we don't hear back
 OPTION(mon_client_hunt_interval_backoff, OPT_DOUBLE, 2.0) // each time we reconnect to a monitor, double our timeout
 OPTION(mon_client_hunt_interval_max_multiple, OPT_DOUBLE, 10.0) // up to a max of 10*default (30 seconds)
 OPTION(mon_client_max_log_entries_per_message, OPT_INT, 1000)
@@ -365,6 +368,7 @@ OPTION(mds_kill_openc_at, OPT_INT, 0)
 OPTION(mds_kill_journal_at, OPT_INT, 0)
 OPTION(mds_kill_journal_expire_at, OPT_INT, 0)
 OPTION(mds_kill_journal_replay_at, OPT_INT, 0)
+OPTION(mds_kill_create_at, OPT_INT, 0)
 OPTION(mds_open_remote_link_mode, OPT_INT, 0)
 OPTION(mds_inject_traceless_reply_probability, OPT_DOUBLE, 0) /* percentage
 				of MDS modify replies to skip sending the
@@ -420,12 +424,12 @@ OPTION(osd_pool_default_min_size, OPT_INT, 0)  // 0 means no specific default; c
 OPTION(osd_pool_default_pg_num, OPT_INT, 8) // number of PGs for new pools. Configure in global or mon section of ceph.conf
 OPTION(osd_pool_default_pgp_num, OPT_INT, 8) // number of PGs for placement purposes. Should be equal to pg_num
 OPTION(osd_pool_default_erasure_code_directory, OPT_STR, CEPH_PKGLIBDIR"/erasure-code") // default for the erasure-code-directory=XXX property of osd pool create
-OPTION(osd_pool_default_erasure_code_properties,
+OPTION(osd_pool_default_erasure_code_profile,
        OPT_STR,
-       "erasure-code-plugin=jerasure "
-       "erasure-code-technique=reed_sol_van "
-       "erasure-code-k=4 "
-       "erasure-code-m=2 "
+       "plugin=jerasure "
+       "technique=reed_sol_van "
+       "k=2 "
+       "m=1 "
        ) // default properties of osd pool create
 OPTION(osd_pool_default_flags, OPT_INT, 0)   // default flags for new pools
 OPTION(osd_pool_default_flag_hashpspool, OPT_BOOL, true)   // use new pg hashing to prevent pool/pg overlap
@@ -531,6 +535,7 @@ OPTION(osd_debug_op_order, OPT_BOOL, false)
 OPTION(osd_debug_verify_snaps_on_info, OPT_BOOL, false)
 OPTION(osd_debug_verify_stray_on_activate, OPT_BOOL, false)
 OPTION(osd_debug_skip_full_check_in_backfill_reservation, OPT_BOOL, false)
+OPTION(osd_debug_reject_backfill_probability, OPT_DOUBLE, 0)
 OPTION(osd_enable_op_tracker, OPT_BOOL, true) // enable/disable OSD op tracking
 OPTION(osd_op_history_size, OPT_U32, 20)    // Max number of completed ops to track
 OPTION(osd_op_history_duration, OPT_U32, 600) // Oldest completed op to track
@@ -729,6 +734,9 @@ OPTION(rbd_default_features, OPT_INT, 3) // 1 for layering, 3 for layering+strip
 
 OPTION(nss_db_path, OPT_STR, "") // path to nss db
 
+
+OPTION(rgw_max_chunk_size, OPT_INT, 512 * 1024)
+
 OPTION(rgw_data, OPT_STR, "/var/lib/ceph/radosgw/$cluster-$id")
 OPTION(rgw_enable_apis, OPT_STR, "s3, swift, swift_auth, admin")
 OPTION(rgw_cache_enabled, OPT_BOOL, true)   // rgw cache enabled
diff --git a/src/common/hobject.h b/src/common/hobject.h
index 2933483..fc12c9f 100644
--- a/src/common/hobject.h
+++ b/src/common/hobject.h
@@ -102,6 +102,11 @@ public:
     return ret;
   }
 
+  /// @return true if object is snapdir
+  bool is_snapdir() const {
+    return snap == CEPH_SNAPDIR;
+  }
+
   /// @return true if object is head
   bool is_head() const {
     return snap == CEPH_NOSNAP;
diff --git a/src/common/lockdep.cc b/src/common/lockdep.cc
index 5c2ee55..6a8a1fa 100644
--- a/src/common/lockdep.cc
+++ b/src/common/lockdep.cc
@@ -61,7 +61,10 @@ static BackTrace *follows[MAX_LOCKS][MAX_LOCKS];       // follows[a][b] means b
 void lockdep_register_ceph_context(CephContext *cct)
 {
   pthread_mutex_lock(&lockdep_mutex);
-  g_lockdep_ceph_ctx = cct;
+  if (g_lockdep_ceph_ctx == NULL) {
+    g_lockdep_ceph_ctx = cct;
+    lockdep_dout(0) << "lockdep start" << dendl;
+  }
   pthread_mutex_unlock(&lockdep_mutex);
 }
 
@@ -69,9 +72,19 @@ void lockdep_unregister_ceph_context(CephContext *cct)
 {
   pthread_mutex_lock(&lockdep_mutex);
   if (cct == g_lockdep_ceph_ctx) {
+    lockdep_dout(0) << "lockdep stop" << dendl;
     // this cct is going away; shut it down!
     g_lockdep = false;
     g_lockdep_ceph_ctx = NULL;
+
+    // blow away all of our state, too, in case it starts up again.
+    held.clear();
+    for (unsigned i = 0; i < MAX_LOCKS; ++i)
+      for (unsigned j = 0; j < MAX_LOCKS; ++j)
+	follows[i][j] = NULL;
+    lock_names.clear();
+    lock_ids.clear();
+    last_id = 0;
   }
   pthread_mutex_unlock(&lockdep_mutex);
 }
@@ -104,7 +117,6 @@ int lockdep_register(const char *name)
   int id;
 
   pthread_mutex_lock(&lockdep_mutex);
-
   if (last_id == 0)
     for (int i=0; i<MAX_LOCKS; i++)
       for (int j=0; j<MAX_LOCKS; j++)
diff --git a/src/common/pipe.c b/src/common/pipe.c
index 8144558..4d22f24 100644
--- a/src/common/pipe.c
+++ b/src/common/pipe.c
@@ -53,8 +53,8 @@ int pipe_cloexec(int pipefd[2])
 	return 0;
 
 out:
-	TEMP_FAILURE_RETRY(close(pipefd[0]));
-	TEMP_FAILURE_RETRY(close(pipefd[1]));
+	VOID_TEMP_FAILURE_RETRY(close(pipefd[0]));
+	VOID_TEMP_FAILURE_RETRY(close(pipefd[1]));
 
 	return ret;
 #endif
diff --git a/src/common/safe_io.c b/src/common/safe_io.c
index 0b31157..4922349 100644
--- a/src/common/safe_io.c
+++ b/src/common/safe_io.c
@@ -175,13 +175,13 @@ int safe_write_file(const char *base, const char *file,
   }
   ret = safe_write(fd, val, vallen);
   if (ret) {
-    TEMP_FAILURE_RETRY(close(fd));
+    VOID_TEMP_FAILURE_RETRY(close(fd));
     return ret;
   }
 
   ret = fsync(fd);
   if (ret < 0) ret = -errno;
-  TEMP_FAILURE_RETRY(close(fd));
+  VOID_TEMP_FAILURE_RETRY(close(fd));
   if (ret < 0) {
     unlink(tmp);
     return ret;
@@ -200,7 +200,7 @@ int safe_write_file(const char *base, const char *file,
   }
   ret = fsync(fd);
   if (ret < 0) ret = -errno;
-  TEMP_FAILURE_RETRY(close(fd));
+  VOID_TEMP_FAILURE_RETRY(close(fd));
 
   return ret;
 }
@@ -218,11 +218,11 @@ int safe_read_file(const char *base, const char *file,
   }
   len = safe_read(fd, val, vallen - 1);
   if (len < 0) {
-    TEMP_FAILURE_RETRY(close(fd));
+    VOID_TEMP_FAILURE_RETRY(close(fd));
     return len;
   }
   // close sometimes returns errors, but only after write()
-  TEMP_FAILURE_RETRY(close(fd));
+  VOID_TEMP_FAILURE_RETRY(close(fd));
 
   val[len] = 0;
   return len;
diff --git a/src/erasure-code/ErasureCodePlugin.cc b/src/erasure-code/ErasureCodePlugin.cc
index d31b197..6349441 100644
--- a/src/erasure-code/ErasureCodePlugin.cc
+++ b/src/erasure-code/ErasureCodePlugin.cc
@@ -3,7 +3,7 @@
 /*
  * Ceph - scalable distributed file system
  *
- * Copyright (C) 2013 Cloudwatt <libre.licensing at cloudwatt.com>
+ * Copyright (C) 2013,2014 Cloudwatt <libre.licensing at cloudwatt.com>
  *
  * Author: Loic Dachary <loic at dachary.org>
  *
@@ -14,21 +14,11 @@
  * 
  */
 
-#include "common/debug.h"
-
+#include <errno.h>
 #include <dlfcn.h>
 
 #include "ErasureCodePlugin.h"
 
-#define dout_subsys ceph_subsys_osd
-#undef dout_prefix
-#define dout_prefix _prefix(_dout)
-
-static ostream& _prefix(std::ostream* _dout)
-{
-  return *_dout << "ErasureCodePlugin: ";
-}
-
 #define PLUGIN_PREFIX "libec_"
 #define PLUGIN_SUFFIX ".so"
 #define PLUGIN_INIT_FUNCTION "__erasure_code_init"
@@ -75,17 +65,21 @@ ErasureCodePlugin *ErasureCodePluginRegistry::get(const std::string &name)
 
 int ErasureCodePluginRegistry::factory(const std::string &plugin_name,
 				       const map<std::string,std::string> &parameters,
-				       ErasureCodeInterfaceRef *erasure_code)
+				       ErasureCodeInterfaceRef *erasure_code,
+				       ostream &ss)
 {
-  Mutex::Locker l(lock);
-  int r = 0;
-  ErasureCodePlugin *plugin = get(plugin_name);
-  if (plugin == 0) {
-    loading = true;
-    r = load(plugin_name, parameters, &plugin);
-    loading = false;
-    if (r != 0)
-      return r;
+  ErasureCodePlugin *plugin;
+  {
+    Mutex::Locker l(lock);
+    int r = 0;
+    plugin = get(plugin_name);
+    if (plugin == 0) {
+      loading = true;
+      r = load(plugin_name, parameters, &plugin, ss);
+      loading = false;
+      if (r != 0)
+	return r;
+    }
   }
 
   return plugin->factory(parameters, erasure_code);
@@ -93,18 +87,16 @@ int ErasureCodePluginRegistry::factory(const std::string &plugin_name,
 
 int ErasureCodePluginRegistry::load(const std::string &plugin_name,
 				    const map<std::string,std::string> &parameters,
-				    ErasureCodePlugin **plugin)
+				    ErasureCodePlugin **plugin,
+				    ostream &ss)
 {
-  assert(parameters.count("erasure-code-directory") != 0);
-  std::string fname = parameters.find("erasure-code-directory")->second
+  assert(parameters.count("directory") != 0);
+  std::string fname = parameters.find("directory")->second
     + "/" PLUGIN_PREFIX
     + plugin_name + PLUGIN_SUFFIX;
-  dout(10) << "load " << plugin_name << " from " << fname << dendl;
-
   void *library = dlopen(fname.c_str(), RTLD_NOW);
   if (!library) {
-    derr << "load dlopen(" << fname
-	 << "): " << dlerror() << dendl;
+    ss << "load dlopen(" << fname << "): " << dlerror();
     return -EIO;
   }
 
@@ -114,23 +106,23 @@ int ErasureCodePluginRegistry::load(const std::string &plugin_name,
     std::string name = plugin_name;
     int r = erasure_code_init(name.c_str());
     if (r != 0) {
-      derr << "erasure_code_init(" << plugin_name
-           << "): " << strerror(-r) << dendl;
+      ss << "erasure_code_init(" << plugin_name
+	 << "): " << strerror(-r);
       dlclose(library);
       return r;
     }
   } else {
-    derr << "load dlsym(" << fname
-	 << ", " << PLUGIN_INIT_FUNCTION
-	 << "): " << dlerror() << dendl;
+    ss << "load dlsym(" << fname
+       << ", " << PLUGIN_INIT_FUNCTION
+       << "): " << dlerror();
     dlclose(library);
     return -ENOENT;
   }
 
   *plugin = get(plugin_name);
   if (*plugin == 0) {
-    derr << "load " << PLUGIN_INIT_FUNCTION << "()"
-         << "did not register " << plugin_name << dendl;
+    ss << "load " << PLUGIN_INIT_FUNCTION << "()"
+       << "did not register " << plugin_name;
     dlclose(library);
     return -EBADF;
   }
diff --git a/src/erasure-code/ErasureCodePlugin.h b/src/erasure-code/ErasureCodePlugin.h
index 1f5e46c..e891079 100644
--- a/src/erasure-code/ErasureCodePlugin.h
+++ b/src/erasure-code/ErasureCodePlugin.h
@@ -3,7 +3,7 @@
 /*
  * Ceph - scalable distributed file system
  *
- * Copyright (C) 2013 Cloudwatt <libre.licensing at cloudwatt.com>
+ * Copyright (C) 2013,2014 Cloudwatt <libre.licensing at cloudwatt.com>
  *
  * Author: Loic Dachary <loic at dachary.org>
  *
@@ -56,14 +56,16 @@ namespace ceph {
 
     int factory(const std::string &plugin,
 		const map<std::string,std::string> &parameters,
-		ErasureCodeInterfaceRef *erasure_code);
+		ErasureCodeInterfaceRef *erasure_code,
+		ostream &ss);
 
     int add(const std::string &name, ErasureCodePlugin *plugin);
     ErasureCodePlugin *get(const std::string &name);
 
     int load(const std::string &plugin_name,
 	     const map<std::string,std::string> &parameters,
-	     ErasureCodePlugin **plugin);
+	     ErasureCodePlugin **plugin,
+	     ostream &ss);
 
   };
 }
diff --git a/src/erasure-code/Makefile.am b/src/erasure-code/Makefile.am
index d9f0382..ea13bcf 100644
--- a/src/erasure-code/Makefile.am
+++ b/src/erasure-code/Makefile.am
@@ -6,9 +6,8 @@ include erasure-code/jerasure/Makefile.am
 
 liberasure_code_la_SOURCES = \
 	erasure-code/ErasureCodePlugin.cc
-liberasure_code_la_LIBADD = $(LIBOSDC) $(LIBOS)
 if LINUX
-liberasure_code_la_LIBADD += -ldl
+liberasure_code_la_LIBADD = -ldl
 endif # LINUX
 noinst_LTLIBRARIES += liberasure_code.la
 
diff --git a/src/erasure-code/jerasure/ErasureCodeJerasure.cc b/src/erasure-code/jerasure/ErasureCodeJerasure.cc
index 26f978d..6d0f653 100644
--- a/src/erasure-code/jerasure/ErasureCodeJerasure.cc
+++ b/src/erasure-code/jerasure/ErasureCodeJerasure.cc
@@ -3,7 +3,7 @@
 /*
  * Ceph - scalable distributed file system
  *
- * Copyright (C) 2013 Cloudwatt <libre.licensing at cloudwatt.com>
+ * Copyright (C) 2013,2014 Cloudwatt <libre.licensing at cloudwatt.com>
  *
  * Author: Loic Dachary <loic at dachary.org>
  *
@@ -20,7 +20,6 @@
 #include "ErasureCodeJerasure.h"
 #include "crush/CrushWrapper.h"
 #include "osd/osd_types.h"
-#include "vectorop.h"
 extern "C" {
 #include "jerasure.h"
 #include "reed_sol.h"
@@ -29,6 +28,9 @@ extern "C" {
 #include "liberation.h"
 }
 
+// FIXME(loic) this may be too conservative, check back with feedback from Andreas 
+#define LARGEST_VECTOR_WORDSIZE 16
+
 #define dout_subsys ceph_subsys_osd
 #undef dout_prefix
 #define dout_prefix _prefix(_dout)
@@ -50,10 +52,10 @@ void ErasureCodeJerasure::init(const map<string,string> &parameters)
 {
   dout(10) << "technique=" << technique << dendl;
   map<string,string>::const_iterator parameter;
-  parameter = parameters.find("erasure-code-ruleset-root");
+  parameter = parameters.find("ruleset-root");
   if (parameter != parameters.end())
     ruleset_root = parameter->second;
-  parameter = parameters.find("erasure-code-ruleset-failure-domain");
+  parameter = parameters.find("ruleset-failure-domain");
   if (parameter != parameters.end())
     ruleset_failure_domain = parameter->second;
   parse(parameters);
@@ -248,9 +250,9 @@ unsigned ErasureCodeJerasureReedSolomonVandermonde::get_alignment() const
 
 void ErasureCodeJerasureReedSolomonVandermonde::parse(const map<std::string,std::string> &parameters)
 {
-  k = to_int("erasure-code-k", parameters, DEFAULT_K);
-  m = to_int("erasure-code-m", parameters, DEFAULT_M);
-  w = to_int("erasure-code-w", parameters, DEFAULT_W);
+  k = to_int("k", parameters, DEFAULT_K);
+  m = to_int("m", parameters, DEFAULT_M);
+  w = to_int("w", parameters, DEFAULT_W);
   if (w != 8 && w != 16 && w != 32) {
     derr << "ReedSolomonVandermonde: w=" << w
 	 << " must be one of {8, 16, 32} : revert to 8 " << dendl;
@@ -291,9 +293,9 @@ unsigned ErasureCodeJerasureReedSolomonRAID6::get_alignment() const
 
 void ErasureCodeJerasureReedSolomonRAID6::parse(const map<std::string,std::string> &parameters)
 {
-  k = to_int("erasure-code-k", parameters, DEFAULT_K);
+  k = to_int("k", parameters, DEFAULT_K);
   m = 2;
-  w = to_int("erasure-code-w", parameters, DEFAULT_W);
+  w = to_int("w", parameters, DEFAULT_W);
   if (w != 8 && w != 16 && w != 32) {
     derr << "ReedSolomonRAID6: w=" << w
 	 << " must be one of {8, 16, 32} : revert to 8 " << dendl;
@@ -336,10 +338,10 @@ unsigned ErasureCodeJerasureCauchy::get_alignment() const
 
 void ErasureCodeJerasureCauchy::parse(const map<std::string,std::string> &parameters)
 {
-  k = to_int("erasure-code-k", parameters, DEFAULT_K);
-  m = to_int("erasure-code-m", parameters, DEFAULT_M);
-  w = to_int("erasure-code-w", parameters, DEFAULT_W);
-  packetsize = to_int("erasure-code-packetsize", parameters, DEFAULT_PACKETSIZE);
+  k = to_int("k", parameters, DEFAULT_K);
+  m = to_int("m", parameters, DEFAULT_M);
+  w = to_int("w", parameters, DEFAULT_W);
+  packetsize = to_int("packetsize", parameters, DEFAULT_PACKETSIZE);
 }
 
 void ErasureCodeJerasureCauchy::prepare_schedule(int *matrix)
@@ -406,10 +408,10 @@ unsigned ErasureCodeJerasureLiberation::get_alignment() const
 
 void ErasureCodeJerasureLiberation::parse(const map<std::string,std::string> &parameters)
 {
-  k = to_int("erasure-code-k", parameters, DEFAULT_K);
-  m = to_int("erasure-code-m", parameters, DEFAULT_M);
-  w = to_int("erasure-code-w", parameters, DEFAULT_W);
-  packetsize = to_int("erasure-code-packetsize", parameters, DEFAULT_PACKETSIZE);
+  k = to_int("k", parameters, DEFAULT_K);
+  m = to_int("m", parameters, DEFAULT_M);
+  w = to_int("w", parameters, DEFAULT_W);
+  packetsize = to_int("packetsize", parameters, DEFAULT_PACKETSIZE);
 
   bool error = false;
   if (k > w) {
@@ -458,10 +460,10 @@ void ErasureCodeJerasureBlaumRoth::prepare()
 //
 void ErasureCodeJerasureLiber8tion::parse(const map<std::string,std::string> &parameters)
 {
-  k = to_int("erasure-code-k", parameters, DEFAULT_K);
+  k = to_int("k", parameters, DEFAULT_K);
   m = DEFAULT_M;
   w = DEFAULT_W;
-  packetsize = to_int("erasure-code-packetsize", parameters, DEFAULT_PACKETSIZE);
+  packetsize = to_int("packetsize", parameters, DEFAULT_PACKETSIZE);
 
   bool error = false;
   if (k > w) {
diff --git a/src/erasure-code/jerasure/ErasureCodePluginJerasure.cc b/src/erasure-code/jerasure/ErasureCodePluginJerasure.cc
index a8e0510..b5da3c0 100644
--- a/src/erasure-code/jerasure/ErasureCodePluginJerasure.cc
+++ b/src/erasure-code/jerasure/ErasureCodePluginJerasure.cc
@@ -3,7 +3,7 @@
 /*
  * Ceph - scalable distributed file system
  *
- * Copyright (C) 2013 Cloudwatt <libre.licensing at cloudwatt.com>
+ * Copyright (C) 2013,2014 Cloudwatt <libre.licensing at cloudwatt.com>
  *
  * Author: Loic Dachary <loic at dachary.org>
  *
@@ -33,8 +33,8 @@ public:
 		      ErasureCodeInterfaceRef *erasure_code) {
     ErasureCodeJerasure *interface;
     std::string t;
-    if (parameters.find("erasure-code-technique") != parameters.end())
-      t = parameters.find("erasure-code-technique")->second;
+    if (parameters.find("technique") != parameters.end())
+      t = parameters.find("technique")->second;
     if (t == "reed_sol_van") {
       interface = new ErasureCodeJerasureReedSolomonVandermonde();
     } else if (t == "reed_sol_r6_op") {
diff --git a/src/erasure-code/jerasure/ErasureCodePluginSelectJerasure.cc b/src/erasure-code/jerasure/ErasureCodePluginSelectJerasure.cc
new file mode 100644
index 0000000..6e2f16c
--- /dev/null
+++ b/src/erasure-code/jerasure/ErasureCodePluginSelectJerasure.cc
@@ -0,0 +1,69 @@
+// -*- 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) 2014 Cloudwatt <libre.licensing at cloudwatt.com>
+ *
+ * Author: Loic Dachary <loic at dachary.org>
+ *
+ *  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 "common/debug.h"
+#include "arch/probe.h"
+#include "arch/intel.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 << "ErasureCodePluginSelectJerasure: ";
+}
+
+class ErasureCodePluginSelectJerasure : public ErasureCodePlugin {
+public:
+  virtual int factory(const map<std::string,std::string> &parameters,
+		      ErasureCodeInterfaceRef *erasure_code) {
+    ErasureCodePluginRegistry &instance = ErasureCodePluginRegistry::instance();
+    stringstream ss;
+    int ret;
+    ceph_arch_probe();
+    string name = "jerasure";
+    if (parameters.count("jerasure-name"))
+      name = parameters.find("jerasure-name")->second;
+    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) {
+      dout(10) << "SSE4 plugin" << dendl;
+      ret = instance.factory(name + "_sse4", parameters, erasure_code, ss);
+    } else if (ceph_arch_intel_ssse3 &&
+	       ceph_arch_intel_sse3 &&
+	       ceph_arch_intel_sse2) {
+      dout(10) << "SSE3 plugin" << dendl;
+      ret = instance.factory(name + "_sse3", parameters, erasure_code, ss);
+    } else {
+      dout(10) << "generic plugin" << dendl;
+      ret = instance.factory(name + "_generic", parameters, erasure_code, ss);
+    }
+    if (ret)
+      derr << ss.str() << dendl;
+    return ret;
+  }
+};
+
+int __erasure_code_init(char *plugin_name)
+{
+  ErasureCodePluginRegistry &instance = ErasureCodePluginRegistry::instance();
+  return instance.add(plugin_name, new ErasureCodePluginSelectJerasure());
+}
diff --git a/src/erasure-code/jerasure/Makefile.am b/src/erasure-code/jerasure/Makefile.am
index 4e85404..e16fe07 100644
--- a/src/erasure-code/jerasure/Makefile.am
+++ b/src/erasure-code/jerasure/Makefile.am
@@ -1,26 +1,108 @@
 # jerasure plugin
-libec_jerasure_la_SOURCES = \
+noinst_HEADERS += \
+  erasure-code/jerasure/jerasure/include/cauchy.h \
+  erasure-code/jerasure/jerasure/include/galois.h \
+  erasure-code/jerasure/jerasure/include/jerasure.h \
+  erasure-code/jerasure/jerasure/include/liberation.h \
+  erasure-code/jerasure/jerasure/include/reed_sol.h \
+  erasure-code/jerasure/gf-complete/include/gf_int.h \
+  erasure-code/jerasure/gf-complete/include/gf_complete.h \
+  erasure-code/jerasure/gf-complete/include/gf_rand.h \
+  erasure-code/jerasure/gf-complete/include/gf_method.h \
+  erasure-code/jerasure/gf-complete/include/gf_general.h \
+  erasure-code/jerasure/ErasureCodeJerasure.h
+
+jerasure_sources = \
+  erasure-code/jerasure/jerasure/src/cauchy.c \
+  erasure-code/jerasure/jerasure/src/galois.c \
+  erasure-code/jerasure/jerasure/src/jerasure.c \
+  erasure-code/jerasure/jerasure/src/liberation.c \
+  erasure-code/jerasure/jerasure/src/reed_sol.c \
+  erasure-code/jerasure/gf-complete/src/gf_wgen.c \
+  erasure-code/jerasure/gf-complete/src/gf_method.c \
+  erasure-code/jerasure/gf-complete/src/gf_w16.c \
+  erasure-code/jerasure/gf-complete/src/gf.c \
+  erasure-code/jerasure/gf-complete/src/gf_w32.c \
+  erasure-code/jerasure/gf-complete/src/gf_w64.c \
+  erasure-code/jerasure/gf-complete/src/gf_w128.c \
+  erasure-code/jerasure/gf-complete/src/gf_general.c \
+  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 \
   erasure-code/jerasure/ErasureCodePluginJerasure.cc \
-  erasure-code/jerasure/ErasureCodeJerasure.cc \
-  erasure-code/jerasure/cauchy.c \
-  erasure-code/jerasure/galois.c \
-  erasure-code/jerasure/jerasure.c \
-  erasure-code/jerasure/liberation.c \
-  erasure-code/jerasure/reed_sol.c
+  erasure-code/jerasure/ErasureCodeJerasure.cc
 
-noinst_HEADERS += \
-  erasure-code/jerasure/ErasureCodeJerasure.h \
-  erasure-code/jerasure/cauchy.h \
-  erasure-code/jerasure/galois.h \
-  erasure-code/jerasure/jerasure.h \
-  erasure-code/jerasure/liberation.h \
-  erasure-code/jerasure/reed_sol.h \
-  erasure-code/jerasure/vectorop.h
+libec_jerasure_generic_la_SOURCES = ${jerasure_sources}
+libec_jerasure_generic_la_CFLAGS = ${AM_CFLAGS}  \
+	-Ierasure-code/jerasure/gf-complete/include \
+	-Ierasure-code/jerasure/jerasure/include
+libec_jerasure_generic_la_CXXFLAGS= ${AM_CXXFLAGS} \
+	-Ierasure-code/jerasure/gf-complete/include \
+	-Ierasure-code/jerasure/jerasure/include
+libec_jerasure_generic_la_LIBADD = $(LIBCRUSH) $(PTHREAD_LIBS) $(EXTRALIBS)
+libec_jerasure_generic_la_LDFLAGS = ${AM_LDFLAGS} -version-info 2:0:0
+if LINUX
+libec_jerasure_generic_la_LDFLAGS += -export-symbols-regex '.*__erasure_code_.*'
+endif
+
+erasure_codelib_LTLIBRARIES += libec_jerasure_generic.la
+
+libec_jerasure_sse3_la_SOURCES = ${jerasure_sources}
+libec_jerasure_sse3_la_CFLAGS = ${AM_CFLAGS}  \
+	${INTEL_SSE_FLAGS} \
+	${INTEL_SSE2_FLAGS} \
+	${INTEL_SSE3_FLAGS} \
+	${INTEL_SSSE3_FLAGS} \
+	-Ierasure-code/jerasure/gf-complete/include \
+	-Ierasure-code/jerasure/jerasure/include
+libec_jerasure_sse3_la_CXXFLAGS= ${AM_CXXFLAGS} \
+	${INTEL_SSE_FLAGS} \
+	${INTEL_SSE2_FLAGS} \
+	${INTEL_SSE3_FLAGS} \
+	${INTEL_SSSE3_FLAGS} \
+	-Ierasure-code/jerasure/gf-complete/include \
+	-Ierasure-code/jerasure/jerasure/include
+libec_jerasure_sse3_la_LIBADD = $(LIBCRUSH) $(PTHREAD_LIBS) $(EXTRALIBS)
+libec_jerasure_sse3_la_LDFLAGS = ${AM_LDFLAGS} -version-info 2:0:0
+if LINUX
+libec_jerasure_sse3_la_LDFLAGS += -export-symbols-regex '.*__erasure_code_.*'
+endif
+
+erasure_codelib_LTLIBRARIES += libec_jerasure_sse3.la
+
+libec_jerasure_sse4_la_SOURCES = ${jerasure_sources}
+libec_jerasure_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} \
+	-Ierasure-code/jerasure/gf-complete/include \
+	-Ierasure-code/jerasure/jerasure/include
+libec_jerasure_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} \
+	-Ierasure-code/jerasure/gf-complete/include \
+	-Ierasure-code/jerasure/jerasure/include
+libec_jerasure_sse4_la_LIBADD = $(LIBCRUSH) $(PTHREAD_LIBS) $(EXTRALIBS)
+libec_jerasure_sse4_la_LDFLAGS = ${AM_LDFLAGS} -version-info 2:0:0
+if LINUX
+libec_jerasure_sse4_la_LDFLAGS += -export-symbols-regex '.*__erasure_code_.*'
+endif
 
+erasure_codelib_LTLIBRARIES += libec_jerasure_sse4.la
+
+libec_jerasure_la_SOURCES = \
+	erasure-code/jerasure/ErasureCodePluginSelectJerasure.cc
 libec_jerasure_la_CFLAGS = ${AM_CFLAGS} 
-libec_jerasure_la_CXXFLAGS= ${AM_CXXFLAGS} 
+libec_jerasure_la_CXXFLAGS= ${AM_CXXFLAGS}
 libec_jerasure_la_LIBADD = $(LIBCRUSH) $(PTHREAD_LIBS) $(EXTRALIBS)
-libec_jerasure_la_LDFLAGS = ${AM_LDFLAGS} -version-info 1:0:0
+libec_jerasure_la_LDFLAGS = ${AM_LDFLAGS} -version-info 2:0:0
 if LINUX
 libec_jerasure_la_LDFLAGS += -export-symbols-regex '.*__erasure_code_.*'
 endif
diff --git a/src/erasure-code/jerasure/cauchy.h b/src/erasure-code/jerasure/cauchy.h
deleted file mode 100644
index 67fbf3b..0000000
--- a/src/erasure-code/jerasure/cauchy.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* cauchy.h
- * James S. Plank
-
-Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure Coding Techniques
-
-Revision 1.2A
-May 24, 2011
-
-James S. Plank
-Department of Electrical Engineering and Computer Science
-University of Tennessee
-Knoxville, TN 37996
-plank at cs.utk.edu
-
-Copyright (c) 2011, James S. Plank
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
- - Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
- - Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in
-   the documentation and/or other materials provided with the
-   distribution.
-
- - Neither the name of the University of Tennessee nor the names of its
-   contributors may be used to endorse or promote products derived
-   from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
-WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-
-*/
-
-extern int *cauchy_original_coding_matrix(int k, int m, int w);
-extern int *cauchy_xy_coding_matrix(int k, int m, int w, int *x, int *y);
-extern void cauchy_improve_coding_matrix(int k, int m, int w, int *matrix);
-extern int *cauchy_good_general_coding_matrix(int k, int m, int w);
-extern int cauchy_n_ones(int n, int w);
diff --git a/src/erasure-code/jerasure/galois.c b/src/erasure-code/jerasure/galois.c
deleted file mode 100644
index 9981353..0000000
--- a/src/erasure-code/jerasure/galois.c
+++ /dev/null
@@ -1,833 +0,0 @@
-/* Galois.c
- * James S. Plank
-
-Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure Coding Techniques
-
-Revision 1.2A
-May 24, 2011
-
-James S. Plank
-Department of Electrical Engineering and Computer Science
-University of Tennessee
-Knoxville, TN 37996
-plank at cs.utk.edu
-
-Copyright (c) 2011, James S. Plank
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
- - Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
- - Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in
-   the documentation and/or other materials provided with the
-   distribution.
-
- - Neither the name of the University of Tennessee nor the names of its
-   contributors may be used to endorse or promote products derived
-   from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
-WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <stdint.h>
-
-#include "galois.h"
-#include "vectorop.h"
-
-#define NONE (10)
-#define TABLE (11)
-#define SHIFT (12)
-#define LOGS (13)
-#define SPLITW8 (14)
-
-static int prim_poly[33] = 
-{ 0, 
-/*  1 */     1, 
-/*  2 */    07,
-/*  3 */    013,
-/*  4 */    023,
-/*  5 */    045,
-/*  6 */    0103,
-/*  7 */    0211,
-/*  8 */    0435,
-/*  9 */    01021,
-/* 10 */    02011,
-/* 11 */    04005,
-/* 12 */    010123,
-/* 13 */    020033,
-/* 14 */    042103,
-/* 15 */    0100003,
-/* 16 */    0210013,
-/* 17 */    0400011,
-/* 18 */    01000201,
-/* 19 */    02000047,
-/* 20 */    04000011,
-/* 21 */    010000005,
-/* 22 */    020000003,
-/* 23 */    040000041,
-/* 24 */    0100000207,
-/* 25 */    0200000011,
-/* 26 */    0400000107,
-/* 27 */    01000000047,
-/* 28 */    02000000011,
-/* 29 */    04000000005,
-/* 30 */    010040000007,
-/* 31 */    020000000011, 
-/* 32 */    00020000007 };  /* Really 40020000007, but we're omitting the high order bit */
-
-static int mult_type[33] = 
-{ NONE, 
-/*  1 */   TABLE, 
-/*  2 */   TABLE,
-/*  3 */   TABLE,
-/*  4 */   TABLE,
-/*  5 */   TABLE,
-/*  6 */   TABLE,
-/*  7 */   TABLE,
-/*  8 */   TABLE,
-/*  9 */   TABLE,
-/* 10 */   LOGS,
-/* 11 */   LOGS,
-/* 12 */   LOGS,
-/* 13 */   LOGS,
-/* 14 */   LOGS,
-/* 15 */   LOGS,
-/* 16 */   LOGS,
-/* 17 */   LOGS,
-/* 18 */   LOGS,
-/* 19 */   LOGS,
-/* 20 */   LOGS,
-/* 21 */   LOGS,
-/* 22 */   LOGS,
-/* 23 */   SHIFT,
-/* 24 */   SHIFT,
-/* 25 */   SHIFT,
-/* 26 */   SHIFT,
-/* 27 */   SHIFT,
-/* 28 */   SHIFT,
-/* 29 */   SHIFT,
-/* 30 */   SHIFT,
-/* 31 */   SHIFT,
-/* 32 */   SPLITW8 };
-
-static int nw[33] = { 0, (1 << 1), (1 << 2), (1 << 3), (1 << 4), 
-(1 << 5), (1 << 6), (1 << 7), (1 << 8), (1 << 9), (1 << 10),
-(1 << 11), (1 << 12), (1 << 13), (1 << 14), (1 << 15), (1 << 16),
-(1 << 17), (1 << 18), (1 << 19), (1 << 20), (1 << 21), (1 << 22),
-(1 << 23), (1 << 24), (1 << 25), (1 << 26), (1 << 27), (1 << 28),
-(1 << 29), (1 << 30), (1 << 31), -1 };
-
-static int nwm1[33] = { 0, (1 << 1)-1, (1 << 2)-1, (1 << 3)-1, (1 << 4)-1, 
-(1 << 5)-1, (1 << 6)-1, (1 << 7)-1, (1 << 8)-1, (1 << 9)-1, (1 << 10)-1,
-(1 << 11)-1, (1 << 12)-1, (1 << 13)-1, (1 << 14)-1, (1 << 15)-1, (1 << 16)-1,
-(1 << 17)-1, (1 << 18)-1, (1 << 19)-1, (1 << 20)-1, (1 << 21)-1, (1 << 22)-1,
-(1 << 23)-1, (1 << 24)-1, (1 << 25)-1, (1 << 26)-1, (1 << 27)-1, (1 << 28)-1,
-(1 << 29)-1, (1 << 30)-1, 0x7fffffff, 0xffffffff };
-   
-static int *galois_log_tables[33] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
-
-static int *galois_ilog_tables[33] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
-
-static int *galois_mult_tables[33] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
-
-static int *galois_div_tables[33] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
-
-/* Special case for w = 32 */
-
-static int *galois_split_w8[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
-
-int galois_create_log_tables(int w)
-{
-  int j, b;
-
-  if (w > 30) return -1;
-  if (galois_log_tables[w] != NULL) return 0;
-  galois_log_tables[w] = (int *) malloc(sizeof(int)*nw[w]);
-  if (galois_log_tables[w] == NULL) return -1; 
-  
-  galois_ilog_tables[w] = (int *) malloc(sizeof(int)*nw[w]*3);
-  if (galois_ilog_tables[w] == NULL) { 
-    free(galois_log_tables[w]);
-    galois_log_tables[w] = NULL;
-    return -1;
-  }
-  
-  for (j = 0; j < nw[w]; j++) {
-    galois_log_tables[w][j] = nwm1[w];
-    galois_ilog_tables[w][j] = 0;
-  } 
-  
-  b = 1;
-  for (j = 0; j < nwm1[w]; j++) {
-    if (galois_log_tables[w][b] != nwm1[w]) {
-      fprintf(stderr, "Galois_create_log_tables Error: j=%d, b=%d, B->J[b]=%d, J->B[j]=%d (0%o)\n",
-              j, b, galois_log_tables[w][b], galois_ilog_tables[w][j], (b << 1) ^ prim_poly[w]);
-      exit(1);
-    }
-    galois_log_tables[w][b] = j;
-    galois_ilog_tables[w][j] = b;
-    b = b << 1;
-    if (b & nw[w]) b = (b ^ prim_poly[w]) & nwm1[w];
-  }
-  for (j = 0; j < nwm1[w]; j++) {
-    galois_ilog_tables[w][j+nwm1[w]] = galois_ilog_tables[w][j];
-    galois_ilog_tables[w][j+nwm1[w]*2] = galois_ilog_tables[w][j];
-  } 
-  galois_ilog_tables[w] += nwm1[w];
-  return 0;
-}
-
-int galois_logtable_multiply(int x, int y, int w)
-{
-  int sum_j;
-
-  if (x == 0 || y == 0) return 0;
-  
-  sum_j = galois_log_tables[w][x] + galois_log_tables[w][y];
-  /* if (sum_j >= nwm1[w]) sum_j -= nwm1[w];    Don't need to do this, 
-                                   because we replicate the ilog table twice.  */
-  return galois_ilog_tables[w][sum_j];
-}
-
-int galois_logtable_divide(int x, int y, int w)
-{
-  int sum_j;
-  int z;
-
-  if (y == 0) return -1;
-  if (x == 0) return 0; 
-  sum_j = galois_log_tables[w][x] - galois_log_tables[w][y];
-  /* if (sum_j < 0) sum_j += nwm1[w];   Don't need to do this, because we replicate the ilog table twice.   */
-  z = galois_ilog_tables[w][sum_j];
-  return z;
-}
-
-int galois_create_mult_tables(int w)
-{
-  int j, x, y, logx;
-
-  if (w >= 14) return -1;
-
-  if (galois_mult_tables[w] != NULL) return 0;
-  galois_mult_tables[w] = (int *) malloc(sizeof(int) * nw[w] * nw[w]);
-  if (galois_mult_tables[w] == NULL) return -1;
-  
-  galois_div_tables[w] = (int *) malloc(sizeof(int) * nw[w] * nw[w]);
-  if (galois_div_tables[w] == NULL) {
-    free(galois_mult_tables[w]);
-    galois_mult_tables[w] = NULL;
-    return -1;
-  }
-  if (galois_log_tables[w] == NULL) {
-    if (galois_create_log_tables(w) < 0) {
-      free(galois_mult_tables[w]);
-      free(galois_div_tables[w]);
-      galois_mult_tables[w] = NULL;
-      galois_div_tables[w] = NULL;
-      return -1;
-    }
-  }
-
- /* Set mult/div tables for x = 0 */
-  j = 0;
-  galois_mult_tables[w][j] = 0;   /* y = 0 */
-  galois_div_tables[w][j] = -1;
-  j++;
-  for (y = 1; y < nw[w]; y++) {   /* y > 0 */
-    galois_mult_tables[w][j] = 0;
-    galois_div_tables[w][j] = 0;
-    j++;
-  }
-  
-  for (x = 1; x < nw[w]; x++) {  /* x > 0 */
-    galois_mult_tables[w][j] = 0; /* y = 0 */
-    galois_div_tables[w][j] = -1;
-    j++;
-    logx = galois_log_tables[w][x];
-    for (y = 1; y < nw[w]; y++) {  /* y > 0 */
-      galois_mult_tables[w][j] = galois_ilog_tables[w][logx+galois_log_tables[w][y]]; 
-      galois_div_tables[w][j] = galois_ilog_tables[w][logx-galois_log_tables[w][y]]; 
-      j++;
-    }
-  }
-  return 0;
-}
-
-int galois_ilog(int value, int w)
-{
-  if (galois_ilog_tables[w] == NULL) {
-    if (galois_create_log_tables(w) < 0) {
-      fprintf(stderr, "Error: galois_ilog - w is too big.  Sorry\n");
-      exit(1);
-    }
-  }
-  return galois_ilog_tables[w][value];
-}
-
-int galois_log(int value, int w)
-{
-  if (galois_log_tables[w] == NULL) {
-    if (galois_create_log_tables(w) < 0) {
-      fprintf(stderr, "Error: galois_log - w is too big.  Sorry\n");
-      exit(1);
-    }
-  }
-  return galois_log_tables[w][value];
-}
-
-
-int galois_shift_multiply(int x, int y, int w)
-{
-  int prod;
-  int i, j, ind;
-  int k;
-  int scratch[33];
-
-  prod = 0;
-  for (i = 0; i < w; i++) {
-    scratch[i] = y;
-    if (y & (1 << (w-1))) {
-      y = y << 1;
-      y = (y ^ prim_poly[w]) & nwm1[w];
-    } else {
-      y = y << 1;
-    }
-  }
-  for (i = 0; i < w; i++) {
-    ind = (1 << i);
-    if (ind & x) {
-      j = 1;
-      for (k = 0; k < w; k++) {
-        prod = prod ^ (j & scratch[i]);
-        j = (j << 1);
-      }
-    }
-  }
-  return prod;
-}
-
-int galois_single_multiply(int x, int y, int w)
-{
-  int sum_j;
-  int z;
-
-  if (x == 0 || y == 0) return 0;
-  
-  if (mult_type[w] == TABLE) {
-    if (galois_mult_tables[w] == NULL) {
-      if (galois_create_mult_tables(w) < 0) {
-        fprintf(stderr, "ERROR -- cannot make multiplication tables for w=%d\n", w);
-        exit(1);
-      }
-    }
-    return galois_mult_tables[w][(x<<w)|y];
-  } else if (mult_type[w] == LOGS) {
-    if (galois_log_tables[w] == NULL) {
-      if (galois_create_log_tables(w) < 0) {
-        fprintf(stderr, "ERROR -- cannot make log tables for w=%d\n", w);
-        exit(1);
-      }
-    }
-    sum_j = galois_log_tables[w][x] + galois_log_tables[w][y];
-    z = galois_ilog_tables[w][sum_j];
-    return z;
-  } else if (mult_type[w] == SPLITW8) {
-    if (galois_split_w8[0] == NULL) {
-      if (galois_create_split_w8_tables() < 0) {
-        fprintf(stderr, "ERROR -- cannot make log split_w8_tables for w=%d\n", w);
-        exit(1);
-      }
-    }
-    return galois_split_w8_multiply(x, y);
-  } else if (mult_type[w] == SHIFT) {
-    return galois_shift_multiply(x, y, w);
-  }
-  fprintf(stderr, "Galois_single_multiply - no implementation for w=%d\n", w);
-  exit(1);
-}
-
-int galois_multtable_multiply(int x, int y, int w)
-{
-  return galois_mult_tables[w][(x<<w)|y];
-}
-
-int galois_single_divide(int a, int b, int w)
-{
-  int sum_j;
-
-  if (mult_type[w] == TABLE) {
-    if (galois_div_tables[w] == NULL) {
-      if (galois_create_mult_tables(w) < 0) {
-        fprintf(stderr, "ERROR -- cannot make multiplication tables for w=%d\n", w);
-        exit(1);
-      }
-    }
-    return galois_div_tables[w][(a<<w)|b];
-  } else if (mult_type[w] == LOGS) {
-    if (b == 0) return -1;
-    if (a == 0) return 0;
-    if (galois_log_tables[w] == NULL) {
-      if (galois_create_log_tables(w) < 0) {
-        fprintf(stderr, "ERROR -- cannot make log tables for w=%d\n", w);
-        exit(1);
-      }
-    }
-    sum_j = galois_log_tables[w][a] - galois_log_tables[w][b];
-    return galois_ilog_tables[w][sum_j];
-  } else {
-    if (b == 0) return -1;
-    if (a == 0) return 0;
-    sum_j = galois_inverse(b, w);
-    return galois_single_multiply(a, sum_j, w);
-  }
-  fprintf(stderr, "Galois_single_divide - no implementation for w=%d\n", w);
-  exit(1);
-}
-
-int galois_shift_divide(int a, int b, int w)
-{
-  int inverse;
-
-  if (b == 0) return -1;
-  if (a == 0) return 0;
-  inverse = galois_shift_inverse(b, w);
-  return galois_shift_multiply(a, inverse, w);
-}
-
-int galois_multtable_divide(int x, int y, int w)
-{
-  return galois_div_tables[w][(x<<w)|y];
-}
-
-void galois_w08_region_multiply(char *region,      /* Region to multiply */
-                                  int multby,       /* Number to multiply by */
-                                  int nbytes,        /* Number of bytes in region */
-                                  char *r2,          /* If r2 != NULL, products go here */
-                                  int add)
-{
-  unsigned char *ur1, *ur2, *cp;
-  unsigned char prod;
-  int i, srow, j;
-  unsigned long l, *lp2;
-  unsigned char *lp;
-  int sol;
-
-  ur1 = (unsigned char *) region;
-  ur2 = (r2 == NULL) ? ur1 : (unsigned char *) r2;
-
-/* This is used to test its performance with respect to just calling galois_single_multiply 
-  if (r2 == NULL || !add) {
-    for (i = 0; i < nbytes; i++) ur2[i] = galois_single_multiply(ur1[i], multby, 8);
-  } else {
-    for (i = 0; i < nbytes; i++) {
-      ur2[i] = (ur2[i]^galois_single_multiply(ur1[i], multby, 8));
-    }
-  }
- */
-
-  if (galois_mult_tables[8] == NULL) {
-    if (galois_create_mult_tables(8) < 0) {
-      fprintf(stderr, "galois_08_region_multiply -- couldn't make multiplication tables\n");
-      exit(1);
-    }
-  }
-  srow = multby * nw[8];
-  if (r2 == NULL || !add) {
-    for (i = 0; i < nbytes; i++) {
-      prod = galois_mult_tables[8][srow+ur1[i]];
-      ur2[i] = prod;
-    }
-  } else {
-    sol = sizeof(long);
-    lp2 = &l;
-    lp = (unsigned char *) lp2;
-    for (i = 0; i < nbytes; i += sol) {
-      cp = ur2+i;
-      lp2 = (unsigned long *) cp;
-      for (j = 0; j < sol; j++) {
-        prod = galois_mult_tables[8][srow+ur1[i+j]];
-        lp[j] = prod;
-      }
-      *lp2 = (*lp2) ^ l;
-    }
-  }
-  return;
-}
-
-void galois_w16_region_multiply(char *region,      /* Region to multiply */
-                                  int multby,       /* Number to multiply by */
-                                  int nbytes,        /* Number of bytes in region */
-                                  char *r2,          /* If r2 != NULL, products go here */
-                                  int add)
-{
-  unsigned short *ur1, *ur2, *cp;
-  int prod;
-  int i, log1, j, log2;
-  unsigned long l, *lp2, *lptop;
-  unsigned short *lp;
-  int sol;
-
-  ur1 = (unsigned short *) region;
-  ur2 = (r2 == NULL) ? ur1 : (unsigned short *) r2;
-  nbytes /= 2;
-
-
-/* This is used to test its performance with respect to just calling galois_single_multiply */
-/*
-  if (r2 == NULL || !add) {
-    for (i = 0; i < nbytes; i++) ur2[i] = galois_single_multiply(ur1[i], multby, 16);
-  } else {
-    for (i = 0; i < nbytes; i++) {
-      ur2[i] = (ur2[i]^galois_single_multiply(ur1[i], multby, 16));
-    }
-  }
-  return;
-  */
-
-  if (multby == 0) {
-    if (!add) {
-      lp2 = (unsigned long *) ur2;
-      ur2 += nbytes;
-      lptop = (unsigned long *) ur2;
-      while (lp2 < lptop) { *lp2 = 0; lp2++; }
-    }
-    return;
-  }
-    
-  if (galois_log_tables[16] == NULL) {
-    if (galois_create_log_tables(16) < 0) {
-      fprintf(stderr, "galois_16_region_multiply -- couldn't make log tables\n");
-      exit(1);
-    }
-  }
-  log1 = galois_log_tables[16][multby];
-
-  if (r2 == NULL || !add) {
-    for (i = 0; i < nbytes; i++) {
-      if (ur1[i] == 0) {
-        ur2[i] = 0;
-      } else {
-        prod = galois_log_tables[16][ur1[i]] + log1;
-        ur2[i] = galois_ilog_tables[16][prod];
-      }
-    }
-  } else {
-    sol = sizeof(long)/2;
-    lp2 = &l;
-    lp = (unsigned short *) lp2;
-    for (i = 0; i < nbytes; i += sol) {
-      cp = ur2+i;
-      lp2 = (unsigned long *) cp;
-      for (j = 0; j < sol; j++) {
-        if (ur1[i+j] == 0) {
-          lp[j] = 0;
-        } else {
-          log2 = galois_log_tables[16][ur1[i+j]];
-          prod = log2 + log1;
-          lp[j] = galois_ilog_tables[16][prod];
-        }
-      }
-      *lp2 = (*lp2) ^ l;
-    }
-  }
-  return; 
-}
-
-/* This will destroy mat, by the way */
-
-void galois_invert_binary_matrix(int *mat, int *inv, int rows)
-{
-  int cols, i, j;
-  int tmp;
- 
-  cols = rows;
-
-  for (i = 0; i < rows; i++) inv[i] = (1 << i);
-
-  /* First -- convert into upper triangular */
-
-  for (i = 0; i < cols; i++) {
-
-    /* Swap rows if we ave a zero i,i element.  If we can't swap, then the 
-       matrix was not invertible */
-
-    if ((mat[i] & (1 << i)) == 0) { 
-      for (j = i+1; j < rows && (mat[j] & (1 << i)) == 0; j++) ;
-      if (j == rows) {
-        fprintf(stderr, "galois_invert_matrix: Matrix not invertible!!\n");
-        exit(1);
-      }
-      tmp = mat[i]; mat[i] = mat[j]; mat[j] = tmp;
-      tmp = inv[i]; inv[i] = inv[j]; inv[j] = tmp;
-    }
- 
-    /* Now for each j>i, add A_ji*Ai to Aj */
-    for (j = i+1; j != rows; j++) {
-      if ((mat[j] & (1 << i)) != 0) {
-        mat[j] ^= mat[i]; 
-        inv[j] ^= inv[i];
-      }
-    }
-  }
-
-  /* Now the matrix is upper triangular.  Start at the top and multiply down */
-
-  for (i = rows-1; i >= 0; i--) {
-    for (j = 0; j < i; j++) {
-      if (mat[j] & (1 << i)) {
-/*        mat[j] ^= mat[i]; */
-        inv[j] ^= inv[i];
-      }
-    }
-  } 
-}
-
-int galois_inverse(int y, int w)
-{
-
-  if (y == 0) return -1;
-  if (mult_type[w] == SHIFT || mult_type[w] == SPLITW8) return galois_shift_inverse(y, w);
-  return galois_single_divide(1, y, w);
-}
-
-int galois_shift_inverse(int y, int w)
-{
-  int mat2[32];
-  int inv2[32];
-  int i;
- 
-  for (i = 0; i < w; i++) {
-    mat2[i] = y;
-
-    if (y & nw[w-1]) {
-      y = y << 1;
-      y = (y ^ prim_poly[w]) & nwm1[w];
-    } else {
-      y = y << 1;
-    }
-  }
-
-  galois_invert_binary_matrix(mat2, inv2, w);
-
-  return inv2[0]; 
-}
-
-int *galois_get_mult_table(int w)
-{
-  if (galois_mult_tables[w] == NULL) {
-    if (galois_create_mult_tables(w)) {
-      return NULL;
-    }
-  }
-  return galois_mult_tables[w];
-}
-
-int *galois_get_div_table(int w) 
-{
-  if (galois_mult_tables[w] == NULL) {
-    if (galois_create_mult_tables(w)) {
-      return NULL;
-    }
-  }
-  return galois_div_tables[w];
-}
-
-int *galois_get_log_table(int w)
-{
-  if (galois_log_tables[w] == NULL) {
-    if (galois_create_log_tables(w)) {
-      return NULL;
-    }
-  }
-  return galois_log_tables[w];
-}
-
-int *galois_get_ilog_table(int w)
-{
-  if (galois_ilog_tables[w] == NULL) {
-    if (galois_create_log_tables(w)) {
-      return NULL;
-    }
-  }
-  return galois_ilog_tables[w];
-}
-
-void galois_w32_region_multiply(char *region,      /* Region to multiply */
-                                  int multby,       /* Number to multiply by */
-                                  int nbytes,        /* Number of bytes in region */
-                                  char *r2,          /* If r2 != NULL, products go here */
-                                  int add)
-{
-  unsigned int *ur1, *ur2;
-  int i, j, a, b, accumulator, i8, j8, k;
-  int acache[4];
-
-  ur1 = (unsigned int *) region;
-  ur2 = (r2 == NULL) ? ur1 : (unsigned int *) r2;
-  nbytes /= sizeof(int);
-
-  if (galois_split_w8[0]== NULL) {
-    if (galois_create_split_w8_tables() < 0) {
-      fprintf(stderr, "galois_32_region_multiply -- couldn't make split multiplication tables\n");
-      exit(1);
-    }
-  }
-
-  /* If we're overwriting r2, then we can't do better than just calling split_multiply.
-     We'll inline it here to save on the procedure call overhead */
-
-  i8 = 0;
-  for (i = 0; i < 4; i++) {
-    acache[i] = (((multby >> i8) & 255) << 8);
-    i8 += 8;
-  }
-  if (!add) {
-    for (k = 0; k < nbytes; k++) {
-      accumulator = 0;
-      for (i = 0; i < 4; i++) {
-        a = acache[i];
-        j8 = 0;
-        for (j = 0; j < 4; j++) {
-          b = ((ur1[k] >> j8) & 255);
-          accumulator ^= galois_split_w8[i+j][a|b];
-          j8 += 8;
-        }
-      }
-      ur2[k] = accumulator;
-    }
-  } else {
-    for (k = 0; k < nbytes; k++) {
-      accumulator = 0;
-      for (i = 0; i < 4; i++) {
-        a = acache[i];
-        j8 = 0;
-        for (j = 0; j < 4; j++) {
-          b = ((ur1[k] >> j8) & 255);
-          accumulator ^= galois_split_w8[i+j][a|b];
-          j8 += 8;
-        }
-      }
-      ur2[k] = (ur2[k] ^ accumulator);
-    }
-  }
-  return;
-}
-
-#define is_aligned(POINTER, BYTE_COUNT) \
-    (((uintptr_t)(const void *)(POINTER)) % (BYTE_COUNT) == 0)
-
-void galois_region_xor(           char *r1,         /* Region 1 */
-                                  char *r2,         /* Region 2 */
-                                  char *r3,         /* Sum region (r3 = r1 ^ r2) -- can be r1 or r2 */
-                                  int nbytes)       /* Number of bytes in region */
-{
-  if (nbytes%VECTOR_WORDSIZE) {
-    assert(is_aligned(r1, sizeof(long)));
-    assert(is_aligned(r2, sizeof(long)));
-    assert(is_aligned(r3, sizeof(long)));
-    long* l1 = (long*)r1;
-    long* l2 = (long*)r2;
-    long* l3 = (long*)r3;
-    char *ctop = r1 + nbytes;
-    long* ltop = (long*)ctop;
-    while (l1 < ltop) {
-      *l3++ = ((*l1++)  ^ (*l2++));
-    }
-  } else {
-    assert(is_aligned(r1, VECTOR_WORDSIZE));
-    assert(is_aligned(r2, VECTOR_WORDSIZE));
-    assert(is_aligned(r3, VECTOR_WORDSIZE));
-    vector_op_t* l1 = (vector_op_t*)r1;
-    vector_op_t* l2 = (vector_op_t*)r2;
-    vector_op_t* l3 = (vector_op_t*)r3;
-    char *ctop = r1 + nbytes;
-    vector_op_t* ltop = (vector_op_t*)ctop;
-    while (l1 < ltop) {
-      *l3++ = ((*l1++)  ^ (*l2++));
-    }
-  }
-}
-
-int galois_create_split_w8_tables()
-{
-  int p1, p2, i, j, p1elt, p2elt, index, ishift, jshift, *table;
-
-  if (galois_split_w8[0] != NULL) return 0;
-
-  if (galois_create_mult_tables(8) < 0) return -1;
-
-  for (i = 0; i < 7; i++) {
-    galois_split_w8[i] = (int *) malloc(sizeof(int) * (1 << 16));
-    if (galois_split_w8[i] == NULL) {
-      for (i--; i >= 0; i--) free(galois_split_w8[i]);
-      return -1;
-    }
-  }
-
-  for (i = 0; i < 4; i += 3) {
-    ishift = i * 8;
-    for (j = ((i == 0) ? 0 : 1) ; j < 4; j++) {
-      jshift = j * 8;
-      table = galois_split_w8[i+j];
-      index = 0;
-      for (p1 = 0; p1 < 256; p1++) {
-        p1elt = (p1 << ishift);
-        for (p2 = 0; p2 < 256; p2++) {
-          p2elt = (p2 << jshift);
-          table[index] = galois_shift_multiply(p1elt, p2elt, 32);
-          index++;
-        }
-      }
-    }
-  }
-  return 0;
-}
-
-int galois_split_w8_multiply(int x, int y)
-{
-  int i, j, a, b, accumulator, i8, j8;
-
-  accumulator = 0;
-  
-  i8 = 0;
-  for (i = 0; i < 4; i++) {
-    a = (((x >> i8) & 255) << 8);
-    j8 = 0;
-    for (j = 0; j < 4; j++) {
-      b = ((y >> j8) & 255);
-      accumulator ^= galois_split_w8[i+j][a|b];
-      j8 += 8;
-    }
-    i8 += 8;
-  }
-  return accumulator;
-}
diff --git a/src/erasure-code/jerasure/galois.h b/src/erasure-code/jerasure/galois.h
deleted file mode 100644
index b08fd94..0000000
--- a/src/erasure-code/jerasure/galois.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/* Galois.h
- * James S. Plank
-
-Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure Coding Techniques
-
-Revision 1.2A
-May 24, 2011
-
-James S. Plank
-Department of Electrical Engineering and Computer Science
-University of Tennessee
-Knoxville, TN 37996
-plank at cs.utk.edu
-
-Copyright (c) 2011, James S. Plank
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
- - Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
- - Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in
-   the documentation and/or other materials provided with the
-   distribution.
-
- - Neither the name of the University of Tennessee nor the names of its
-   contributors may be used to endorse or promote products derived
-   from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
-WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-
- */
-
-#ifndef _GALOIS_H
-#define _GALOIS_H
-
-#include <stdio.h>
-#include <stdlib.h>
-
-extern int galois_single_multiply(int a, int b, int w);
-extern int galois_single_divide(int a, int b, int w);
-extern int galois_log(int value, int w);
-extern int galois_ilog(int value, int w);
-
-extern int galois_create_log_tables(int w);   /* Returns 0 on success, -1 on failure */
-extern int galois_logtable_multiply(int x, int y, int w);
-extern int galois_logtable_divide(int x, int y, int w);
-
-extern int galois_create_mult_tables(int w);   /* Returns 0 on success, -1 on failure */
-extern int galois_multtable_multiply(int x, int y, int w);
-extern int galois_multtable_divide(int x, int y, int w);
-
-extern int galois_shift_multiply(int x, int y, int w);
-extern int galois_shift_divide(int x, int y, int w);
-
-extern int galois_create_split_w8_tables();
-extern int galois_split_w8_multiply(int x, int y);
-
-extern int galois_inverse(int x, int w);
-extern int galois_shift_inverse(int y, int w);
-
-extern int *galois_get_mult_table(int w);
-extern int *galois_get_div_table(int w);
-extern int *galois_get_log_table(int w);
-extern int *galois_get_ilog_table(int w);
-
-void galois_region_xor(           char *r1,         /* Region 1 */
-                                  char *r2,         /* Region 2 */
-                                  char *r3,         /* Sum region (r3 = r1 ^ r2) -- can be r1 or r2 */
-                                  int nbytes);      /* Number of bytes in region */
-
-/* These multiply regions in w=8, w=16 and w=32.  They are much faster
-   than calling galois_single_multiply.  The regions must be long word aligned. */
-
-void galois_w08_region_multiply(char *region,       /* Region to multiply */
-                                  int multby,       /* Number to multiply by */
-                                  int nbytes,       /* Number of bytes in region */
-                                  char *r2,         /* If r2 != NULL, products go here.  
-                                                       Otherwise region is overwritten */
-                                  int add);         /* If (r2 != NULL && add) the produce is XOR'd with r2 */
-
-void galois_w16_region_multiply(char *region,       /* Region to multiply */
-                                  int multby,       /* Number to multiply by */
-                                  int nbytes,       /* Number of bytes in region */
-                                  char *r2,         /* If r2 != NULL, products go here.  
-                                                       Otherwise region is overwritten */
-                                  int add);         /* If (r2 != NULL && add) the produce is XOR'd with r2 */
-
-void galois_w32_region_multiply(char *region,       /* Region to multiply */
-                                  int multby,       /* Number to multiply by */
-                                  int nbytes,       /* Number of bytes in region */
-                                  char *r2,         /* If r2 != NULL, products go here.  
-                                                       Otherwise region is overwritten */
-                                  int add);         /* If (r2 != NULL && add) the produce is XOR'd with r2 */
-
-#endif
diff --git a/src/erasure-code/jerasure/gf-complete/include/gf_complete.h b/src/erasure-code/jerasure/gf-complete/include/gf_complete.h
new file mode 100644
index 0000000..57b439e
--- /dev/null
+++ b/src/erasure-code/jerasure/gf-complete/include/gf_complete.h
@@ -0,0 +1,192 @@
+/* 
+ * GF-Complete: A Comprehensive Open Source Library for Galois Field Arithmetic
+ * James S. Plank, Ethan L. Miller, Kevin M. Greenan,
+ * Benjamin A. Arnold, John A. Burnum, Adam W. Disney, Allen C. McBride.
+ *
+ * gf_complete.h
+ *
+ * The main include file for gf_complete. 
+ */
+
+#ifndef _GF_COMPLETE_H_
+#define _GF_COMPLETE_H_
+#include <stdint.h>
+
+#ifdef INTEL_SSE4
+  #include <nmmintrin.h>
+#endif
+
+#ifdef INTEL_SSSE3
+  #include <tmmintrin.h>
+#endif
+
+#ifdef INTEL_SSE2
+  #include <emmintrin.h>
+#endif
+
+#ifdef INTEL_SSE4_PCLMUL
+  #include <wmmintrin.h>
+#endif
+
+
+/* These are the different ways to perform multiplication.
+   Not all are implemented for all values of w.
+   See the paper for an explanation of how they work. */
+
+typedef enum {GF_MULT_DEFAULT,   
+              GF_MULT_SHIFT,   
+              GF_MULT_CARRY_FREE,   
+              GF_MULT_GROUP,   
+              GF_MULT_BYTWO_p,
+              GF_MULT_BYTWO_b,
+              GF_MULT_TABLE,   
+              GF_MULT_LOG_TABLE,   
+              GF_MULT_LOG_ZERO,
+              GF_MULT_LOG_ZERO_EXT,
+              GF_MULT_SPLIT_TABLE,   
+              GF_MULT_COMPOSITE } gf_mult_type_t;
+
+/* These are the different ways to optimize region 
+   operations.  They are bits because you can compose them.
+   Certain optimizations only apply to certain gf_mult_type_t's.  
+   Again, please see documentation for how to use these */
+   
+#define GF_REGION_DEFAULT      (0x0)
+#define GF_REGION_DOUBLE_TABLE (0x1)
+#define GF_REGION_QUAD_TABLE   (0x2)
+#define GF_REGION_LAZY         (0x4)
+#define GF_REGION_SSE          (0x8)
+#define GF_REGION_NOSSE        (0x10)
+#define GF_REGION_ALTMAP       (0x20)
+#define GF_REGION_CAUCHY       (0x40)
+
+typedef uint32_t gf_region_type_t;
+
+/* These are different ways to implement division.
+   Once again, it's best to use "DEFAULT".  However,
+   there are times when you may want to experiment
+   with the others. */
+
+typedef enum { GF_DIVIDE_DEFAULT,
+               GF_DIVIDE_MATRIX,
+               GF_DIVIDE_EUCLID } gf_division_type_t;
+
+/* We support w=4,8,16,32,64 and 128 with their own data types and
+   operations for multiplication, division, etc.  We also support
+   a "gen" type so that you can do general gf arithmetic for any 
+   value of w from 1 to 32.  You can perform a "region" operation
+   on these if you use "CAUCHY" as the mapping. 
+ */
+
+typedef uint32_t    gf_val_32_t;
+typedef uint64_t    gf_val_64_t;
+typedef uint64_t   *gf_val_128_t;
+
+extern int _gf_errno;
+extern void gf_error();
+
+typedef struct gf *GFP;
+
+typedef union gf_func_a_b {
+    gf_val_32_t  (*w32) (GFP gf, gf_val_32_t a,  gf_val_32_t b);
+    gf_val_64_t  (*w64) (GFP gf, gf_val_64_t a,  gf_val_64_t b);
+    void         (*w128)(GFP gf, gf_val_128_t a, gf_val_128_t b, gf_val_128_t c);
+} gf_func_a_b;
+  
+typedef union {
+  gf_val_32_t  (*w32) (GFP gf, gf_val_32_t a);
+  gf_val_64_t  (*w64) (GFP gf, gf_val_64_t a);
+  void         (*w128)(GFP gf, gf_val_128_t a, gf_val_128_t b);
+} gf_func_a;
+  
+typedef union {
+  void  (*w32) (GFP gf, void *src, void *dest, gf_val_32_t val,  int bytes, int add);
+  void  (*w64) (GFP gf, void *src, void *dest, gf_val_64_t val,  int bytes, int add);
+  void  (*w128)(GFP gf, void *src, void *dest, gf_val_128_t val, int bytes, int add);
+} gf_region;
+
+typedef union {
+  gf_val_32_t  (*w32) (GFP gf, void *start, int bytes, int index);
+  gf_val_64_t  (*w64) (GFP gf, void *start, int bytes, int index);
+  void         (*w128)(GFP gf, void *start, int bytes, int index, gf_val_128_t rv);
+} gf_extract;
+
+typedef struct gf {
+  gf_func_a_b    multiply;
+  gf_func_a_b    divide;
+  gf_func_a      inverse;
+  gf_region      multiply_region;
+  gf_extract     extract_word;
+  void           *scratch;
+} gf_t;
+    
+/* Initializes the GF to defaults.  Pass it a pointer to a gf_t.
+   Returns 0 on failure, 1 on success. */
+
+extern int gf_init_easy(GFP gf, int w);
+
+/* Initializes the GF changing the defaults.
+   Returns 0 on failure, 1 on success.
+   Pass it a pointer to a gf_t.
+   For mult_type and divide_type, use one of gf_mult_type_t gf_divide_type_t .  
+   For region_type, OR together the GF_REGION_xxx's defined above.  
+   Use 0 as prim_poly for defaults.  Otherwise, the leading 1 is optional.
+   Use NULL for scratch_memory to have init_hard allocate memory.  Otherwise,
+   use gf_scratch_size() to determine how big scratch_memory has to be.
+ */
+
+extern int gf_init_hard(GFP gf, 
+                        int w, 
+                        int mult_type, 
+                        int region_type, 
+                        int divide_type, 
+                        uint64_t prim_poly,
+                        int arg1, 
+                        int arg2,
+                        GFP base_gf,
+                        void *scratch_memory);
+
+/* Determines the size for scratch_memory.  
+   Returns 0 on failure and non-zero on success. */
+
+extern int gf_scratch_size(int w, 
+                           int mult_type, 
+                           int region_type, 
+                           int divide_type, 
+                           int arg1, 
+                           int arg2);
+
+/* This reports the gf_scratch_size of a gf_t that has already been created */
+
+extern int gf_size(GFP gf);
+
+/* Frees scratch memory if gf_init_easy/gf_init_hard called malloc.
+   If recursive = 1, then it calls itself recursively on base_gf. */
+
+extern int gf_free(GFP gf, int recursive);
+
+/* This is support for inline single multiplications and divisions.
+   I know it's yucky, but if you've got to be fast, you've got to be fast.
+   We support inlining for w=4, w=8 and w=16.  
+
+   To use inline multiplication and division with w=4 or 8, you should use the 
+   default gf_t, or one with a single table.  Otherwise, gf_w4/8_get_mult_table()
+   will return NULL. Similarly, with w=16, the gf_t must be LOG */
+
+uint8_t *gf_w4_get_mult_table(GFP gf);
+uint8_t *gf_w4_get_div_table(GFP gf);
+
+#define GF_W4_INLINE_MULTDIV(table, a, b) (table[((a)<<4)|(b)])
+
+uint8_t *gf_w8_get_mult_table(GFP gf);
+uint8_t *gf_w8_get_div_table(GFP gf);
+
+#define GF_W8_INLINE_MULTDIV(table, a, b) (table[(((uint32_t) (a))<<8)|(b)])
+
+uint16_t *gf_w16_get_log_table(GFP gf);
+uint16_t *gf_w16_get_mult_alog_table(GFP gf);
+uint16_t *gf_w16_get_div_alog_table(GFP gf);
+
+#define GF_W16_INLINE_MULT(log, alog, a, b) ((a) == 0 || (b) == 0) ? 0 : (alog[(uint32_t)log[a]+(uint32_t)log[b]])
+#define GF_W16_INLINE_DIV(log, alog, a, b) ((a) == 0 || (b) == 0) ? 0 : (alog[(int)log[a]-(int)log[b]])
+#endif
diff --git a/src/erasure-code/jerasure/gf-complete/include/gf_general.h b/src/erasure-code/jerasure/gf-complete/include/gf_general.h
new file mode 100644
index 0000000..9a5de52
--- /dev/null
+++ b/src/erasure-code/jerasure/gf-complete/include/gf_general.h
@@ -0,0 +1,61 @@
+/*
+ * GF-Complete: A Comprehensive Open Source Library for Galois Field Arithmetic
+ * James S. Plank, Ethan L. Miller, Kevin M. Greenan,
+ * Benjamin A. Arnold, John A. Burnum, Adam W. Disney, Allen C. McBride.
+ *
+ * gf_general.h
+ *
+ * This file has helper routines for doing basic GF operations with any
+ * legal value of w.  The problem is that w <= 32, w=64 and w=128 all have
+ * different data types, which is a pain.  The procedures in this file try
+ * to alleviate that pain.  They are used in gf_unit and gf_time.
+ */
+
+#pragma once
+
+#include <stdio.h>
+#include <getopt.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "gf_complete.h"
+
+typedef union {
+  uint32_t w32;
+  uint64_t w64;
+  uint64_t w128[2];
+} gf_general_t;
+
+void gf_general_set_zero(gf_general_t *v, int w);
+void gf_general_set_one(gf_general_t *v, int w);
+void gf_general_set_two(gf_general_t *v, int w);
+
+int gf_general_is_zero(gf_general_t *v, int w);
+int gf_general_is_one(gf_general_t *v, int w);
+int gf_general_are_equal(gf_general_t *v1, gf_general_t *v2, int w);
+
+void gf_general_val_to_s(gf_general_t *v, int w, char *s, int hex);
+int  gf_general_s_to_val(gf_general_t *v, int w, char *s, int hex);
+
+void gf_general_set_random(gf_general_t *v, int w, int zero_ok);
+
+void gf_general_add(gf_t *gf, gf_general_t *a, gf_general_t *b, gf_general_t *c);
+void gf_general_multiply(gf_t *gf, gf_general_t *a, gf_general_t *b, gf_general_t *c);
+void gf_general_divide(gf_t *gf, gf_general_t *a, gf_general_t *b, gf_general_t *c);
+void gf_general_inverse(gf_t *gf, gf_general_t *a, gf_general_t *b);
+
+void gf_general_do_region_multiply(gf_t *gf, gf_general_t *a, 
+                                   void *ra, void *rb, 
+                                   int bytes, int xor);
+
+void gf_general_do_region_check(gf_t *gf, gf_general_t *a, 
+                                void *orig_a, void *orig_target, void *final_target, 
+                                int bytes, int xor);
+
+
+/* Which is M, D or I for multiply, divide or inverse. */
+
+void gf_general_set_up_single_timing_test(int w, void *ra, void *rb, int size);
+int  gf_general_do_single_timing_test(gf_t *gf, void *ra, void *rb, int size, char which);
diff --git a/src/erasure-code/jerasure/gf-complete/include/gf_int.h b/src/erasure-code/jerasure/gf-complete/include/gf_int.h
new file mode 100644
index 0000000..9221569
--- /dev/null
+++ b/src/erasure-code/jerasure/gf-complete/include/gf_int.h
@@ -0,0 +1,200 @@
+/*
+ * GF-Complete: A Comprehensive Open Source Library for Galois Field Arithmetic
+ * James S. Plank, Ethan L. Miller, Kevin M. Greenan,
+ * Benjamin A. Arnold, John A. Burnum, Adam W. Disney, Allen C. McBride.
+ *
+ * gf_int.h
+ *
+ * Internal code for Galois field routines.  This is not meant for 
+ * users to include, but for the internal GF files to use. 
+ */
+
+#pragma once
+
+#include "gf_complete.h"
+
+#include <string.h>
+
+extern void     timer_start (double *t);
+extern double   timer_split (const double *t);
+extern void     galois_fill_random (void *buf, int len, unsigned int seed);
+
+typedef struct {
+  int mult_type;
+  int region_type;
+  int divide_type;
+  int w;
+  uint64_t prim_poly;
+  int free_me;
+  int arg1;
+  int arg2;
+  gf_t *base_gf;
+  void *private;
+} gf_internal_t;
+
+extern int gf_w4_init (gf_t *gf);
+extern int gf_w4_scratch_size(int mult_type, int region_type, int divide_type, int arg1, int arg2);
+
+extern int gf_w8_init (gf_t *gf);
+extern int gf_w8_scratch_size(int mult_type, int region_type, int divide_type, int arg1, int arg2);
+
+extern int gf_w16_init (gf_t *gf);
+extern int gf_w16_scratch_size(int mult_type, int region_type, int divide_type, int arg1, int arg2);
+
+extern int gf_w32_init (gf_t *gf);
+extern int gf_w32_scratch_size(int mult_type, int region_type, int divide_type, int arg1, int arg2);
+
+extern int gf_w64_init (gf_t *gf);
+extern int gf_w64_scratch_size(int mult_type, int region_type, int divide_type, int arg1, int arg2);
+
+extern int gf_w128_init (gf_t *gf);
+extern int gf_w128_scratch_size(int mult_type, int region_type, int divide_type, int arg1, int arg2);
+
+extern int gf_wgen_init (gf_t *gf);
+extern int gf_wgen_scratch_size(int w, int mult_type, int region_type, int divide_type, int arg1, int arg2);
+
+void gf_wgen_cauchy_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor);
+gf_val_32_t gf_wgen_extract_word(gf_t *gf, void *start, int bytes, int index);
+
+extern void gf_alignment_error(char *s, int a);
+
+extern uint32_t gf_bitmatrix_inverse(uint32_t y, int w, uint32_t pp);
+
+/* This returns the correct default for prim_poly when base is used as the base
+   field for COMPOSITE.  It returns 0 if we don't have a default prim_poly. */
+
+extern uint64_t gf_composite_get_default_poly(gf_t *base);
+
+/* This structure lets you define a region multiply.  It helps because you can handle
+   unaligned portions of the data with the procedures below, which really cleans
+   up the code. */
+
+typedef struct {
+  gf_t *gf;
+  void *src;
+  void *dest;
+  int bytes;
+  uint64_t val;
+  int xor;
+  int align;           /* The number of bytes to which to align. */
+  void *s_start;       /* The start and the top of the aligned region. */
+  void *d_start;
+  void *s_top;
+  void *d_top;
+} gf_region_data;
+
+/* This lets you set up one of these in one call. It also sets the start/top pointers. */
+
+void gf_set_region_data(gf_region_data *rd,
+                        gf_t *gf,
+                        void *src,
+                        void *dest,
+                        int bytes,
+                        uint64_t val,
+                        int xor,
+                        int align);
+
+/* This performs gf->multiply.32() on all of the unaligned bytes in the beginning of the region */
+
+extern void gf_do_initial_region_alignment(gf_region_data *rd);
+
+/* This performs gf->multiply.32() on all of the unaligned bytes in the end of the region */
+
+extern void gf_do_final_region_alignment(gf_region_data *rd);
+
+extern void gf_two_byte_region_table_multiply(gf_region_data *rd, uint16_t *base);
+
+extern void gf_multby_zero(void *dest, int bytes, int xor);
+extern void gf_multby_one(void *src, void *dest, int bytes, int xor);
+
+typedef enum {GF_E_MDEFDIV, /* Dev != Default && Mult == Default */
+              GF_E_MDEFREG, /* Reg != Default && Mult == Default */
+              GF_E_MDEFARG, /* Args != Default && Mult == Default */
+              GF_E_DIVCOMP, /* Mult == Composite && Div != Default */
+              GF_E_CAUCOMP, /* Mult == Composite && Reg == CAUCHY */
+              GF_E_DOUQUAD, /* Reg == DOUBLE && Reg == QUAD */
+              GF_E_SSE__NO, /* Reg == SSE && Reg == NOSSE */
+              GF_E_CAUCHYB, /* Reg == CAUCHY && Other Reg */
+              GF_E_CAUGT32, /* Reg == CAUCHY && w > 32*/
+              GF_E_ARG1SET, /* Arg1 != 0 && Mult \notin COMPOSITE/SPLIT/GROUP */
+              GF_E_ARG2SET, /* Arg2 != 0 && Mult \notin SPLIT/GROUP */
+              GF_E_MATRIXW, /* Div == MATRIX && w > 32 */
+              GF_E_BAD___W, /* Illegal w */
+              GF_E_DOUBLET, /* Reg == DOUBLE && Mult != TABLE */
+              GF_E_DOUBLEW, /* Reg == DOUBLE && w \notin {4,8} */
+              GF_E_DOUBLEJ, /* Reg == DOUBLE && other Reg */
+              GF_E_DOUBLEL, /* Reg == DOUBLE & LAZY but w = 4 */
+              GF_E_QUAD__T, /* Reg == QUAD && Mult != TABLE */
+              GF_E_QUAD__W, /* Reg == QUAD && w != 4 */
+              GF_E_QUAD__J, /* Reg == QUAD && other Reg */
+              GF_E_LAZY__X, /* Reg == LAZY && not DOUBLE or QUAD*/
+              GF_E_ALTSHIF, /* Mult == Shift && Reg == ALTMAP */
+              GF_E_SSESHIF, /* Mult == Shift && Reg == SSE|NOSSE */
+              GF_E_ALT_CFM, /* Mult == CARRY_FREE && Reg == ALTMAP */
+              GF_E_SSE_CFM, /* Mult == CARRY_FREE && Reg == SSE|NOSSE */
+              GF_E_PCLMULX, /* Mult == Carry_Free && No PCLMUL */
+              GF_E_ALT_BY2, /* Mult == Bytwo_x && Reg == ALTMAP */
+              GF_E_BY2_SSE, /* Mult == Bytwo_x && Reg == SSE && No SSE2 */
+              GF_E_LOGBADW, /* Mult == LOGx, w too big*/
+              GF_E_LOG___J, /* Mult == LOGx, && Reg == SSE|ALTMAP|NOSSE */
+              GF_E_ZERBADW, /* Mult == LOG_ZERO, w \notin {8,16} */
+              GF_E_ZEXBADW, /* Mult == LOG_ZERO_EXT, w != 8 */
+              GF_E_LOGPOLY, /* Mult == LOG & poly not primitive */
+              GF_E_GR_ARGX, /* Mult == GROUP, Bad arg1/2 */
+              GF_E_GR_W_48, /* Mult == GROUP, w \in { 4, 8 } */
+              GF_E_GR_W_16, /* Mult == GROUP, w == 16, arg1 != 4 || arg2 != 4 */
+              GF_E_GR_128A, /* Mult == GROUP, w == 128, bad args */
+              GF_E_GR_A_27, /* Mult == GROUP, either arg > 27 */
+              GF_E_GR_AR_W, /* Mult == GROUP, either arg > w  */
+              GF_E_GR____J, /* Mult == GROUP, Reg == SSE|ALTMAP|NOSSE */
+              GF_E_TABLE_W, /* Mult == TABLE, w too big */
+              GF_E_TAB_SSE, /* Mult == TABLE, SSE|NOSSE only apply to w == 4 */
+              GF_E_TABSSE3, /* Mult == TABLE, Need SSSE3 for SSE */
+              GF_E_TAB_ALT, /* Mult == TABLE, Reg == ALTMAP */
+              GF_E_SP128AR, /* Mult == SPLIT, w=128, Bad arg1/arg2 */
+              GF_E_SP128AL, /* Mult == SPLIT, w=128, SSE requires ALTMAP */
+              GF_E_SP128AS, /* Mult == SPLIT, w=128, ALTMAP requires SSE */
+              GF_E_SP128_A, /* Mult == SPLIT, w=128, SSE only with 4/128 */
+              GF_E_SP128_S, /* Mult == SPLIT, w=128, ALTMAP only with 4/128 */
+              GF_E_SPLIT_W, /* Mult == SPLIT, Bad w (8, 16, 32, 64, 128)  */
+              GF_E_SP_16AR, /* Mult == SPLIT, w=16, Bad arg1/arg2 */
+              GF_E_SP_16_A, /* Mult == SPLIT, w=16, ALTMAP only with 4/16 */
+              GF_E_SP_16_S, /* Mult == SPLIT, w=16, SSE only with 4/16 */
+              GF_E_SP_32AR, /* Mult == SPLIT, w=32, Bad arg1/arg2 */
+              GF_E_SP_32AS, /* Mult == SPLIT, w=32, ALTMAP requires SSE */
+              GF_E_SP_32_A, /* Mult == SPLIT, w=32, ALTMAP only with 4/32 */
+              GF_E_SP_32_S, /* Mult == SPLIT, w=32, SSE only with 4/32 */
+              GF_E_SP_64AR, /* Mult == SPLIT, w=64, Bad arg1/arg2 */
+              GF_E_SP_64AS, /* Mult == SPLIT, w=64, ALTMAP requires SSE */
+              GF_E_SP_64_A, /* Mult == SPLIT, w=64, ALTMAP only with 4/64 */
+              GF_E_SP_64_S, /* Mult == SPLIT, w=64, SSE only with 4/64 */
+              GF_E_SP_8_AR, /* Mult == SPLIT, w=8, Bad arg1/arg2 */
+              GF_E_SP_8__A, /* Mult == SPLIT, w=8, no ALTMAP */
+              GF_E_SP_SSE3, /* Mult == SPLIT, Need SSSE3 for SSE */
+              GF_E_COMP_A2, /* Mult == COMP, arg1 must be = 2 */
+              GF_E_COMP_SS, /* Mult == COMP, SSE|NOSSE */
+              GF_E_COMP__W, /* Mult == COMP, Bad w. */
+              GF_E_UNKFLAG, /* Unknown flag in create_from.... */
+              GF_E_UNKNOWN, /* Unknown mult_type. */
+              GF_E_UNK_REG, /* Unknown region_type. */
+              GF_E_UNK_DIV, /* Unknown divide_type. */
+              GF_E_CFM___W, /* Mult == CFM,  Bad w. */
+              GF_E_CFM4POL, /* Mult == CFM & Prim Poly has high bits set. */
+              GF_E_CFM8POL, /* Mult == CFM & Prim Poly has high bits set. */
+              GF_E_CF16POL, /* Mult == CFM & Prim Poly has high bits set. */
+              GF_E_CF32POL, /* Mult == CFM & Prim Poly has high bits set. */
+              GF_E_CF64POL, /* Mult == CFM & Prim Poly has high bits set. */
+              GF_E_FEWARGS, /* Too few args in argc/argv. */
+              GF_E_BADPOLY, /* Bad primitive polynomial -- too many bits set. */
+              GF_E_COMP_PP, /* Bad primitive polynomial -- bigger than sub-field. */
+              GF_E_COMPXPP, /* Can't derive a default pp for composite field. */
+              GF_E_BASE__W, /* Composite -- Base field is the wrong size. */
+              GF_E_TWOMULT, /* In create_from... two -m's. */
+              GF_E_TWO_DIV, /* In create_from... two -d's. */
+              GF_E_POLYSPC, /* Bad numbera after -p. */
+              GF_E_SPLITAR, /* Ran out of arguments in SPLIT */
+              GF_E_SPLITNU, /* Arguments not integers in SPLIT. */
+              GF_E_GROUPAR, /* Ran out of arguments in GROUP */
+              GF_E_GROUPNU, /* Arguments not integers in GROUP. */
+              GF_E_DEFAULT } gf_error_type_t;
+
diff --git a/src/erasure-code/jerasure/gf-complete/include/gf_method.h b/src/erasure-code/jerasure/gf-complete/include/gf_method.h
new file mode 100644
index 0000000..880b349
--- /dev/null
+++ b/src/erasure-code/jerasure/gf-complete/include/gf_method.h
@@ -0,0 +1,20 @@
+/*
+ * GF-Complete: A Comprehensive Open Source Library for Galois Field Arithmetic
+ * James S. Plank, Ethan L. Miller, Kevin M. Greenan,
+ * Benjamin A. Arnold, John A. Burnum, Adam W. Disney, Allen C. McBride.
+ *
+ * gf_method.h
+ *
+ * Parses argv to figure out the flags and arguments.  Creates the gf.
+ */
+
+#pragma once
+
+#include "gf_complete.h"
+
+/* Parses argv starting at "starting".  
+   
+   Returns 0 on failure.
+   On success, it returns one past the last argument it read in argv. */
+
+extern int create_gf_from_argv(gf_t *gf, int w, int argc, char **argv, int starting);
diff --git a/src/erasure-code/jerasure/gf-complete/include/gf_rand.h b/src/erasure-code/jerasure/gf-complete/include/gf_rand.h
new file mode 100644
index 0000000..24294ad
--- /dev/null
+++ b/src/erasure-code/jerasure/gf-complete/include/gf_rand.h
@@ -0,0 +1,22 @@
+/* 
+ * GF-Complete: A Comprehensive Open Source Library for Galois Field Arithmetic
+ * James S. Plank, Ethan L. Miller, Kevin M. Greenan,
+ * Benjamin A. Arnold, John A. Burnum, Adam W. Disney, Allen C. McBride.
+ *
+ * gf_rand.h
+ *
+ * Random number generation, using the "Mother of All" random number generator.  */
+
+#pragma once
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/* These are all pretty self-explanatory */
+uint32_t MOA_Random_32();
+uint64_t MOA_Random_64();
+void     MOA_Random_128(uint64_t *x);
+uint32_t MOA_Random_W(int w, int zero_ok);
+void MOA_Fill_Random_Region (void *reg, int size);   /* reg should be aligned to 4 bytes, but
+                                                        size can be anything. */
+void     MOA_Seed(uint32_t seed);
diff --git a/src/erasure-code/jerasure/gf-complete/src/gf.c b/src/erasure-code/jerasure/gf-complete/src/gf.c
new file mode 100644
index 0000000..701739b
--- /dev/null
+++ b/src/erasure-code/jerasure/gf-complete/src/gf.c
@@ -0,0 +1,1026 @@
+/*
+ * GF-Complete: A Comprehensive Open Source Library for Galois Field Arithmetic
+ * James S. Plank, Ethan L. Miller, Kevin M. Greenan,
+ * Benjamin A. Arnold, John A. Burnum, Adam W. Disney, Allen C. McBride.
+ *
+ * gf.c
+ *
+ * Generic routines for Galois fields
+ */
+
+#include "gf_int.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+int _gf_errno = GF_E_DEFAULT;
+
+void gf_error()
+{
+  char *s;
+
+  switch(_gf_errno) {
+    case GF_E_DEFAULT: s = "No Error."; break;
+    case GF_E_TWOMULT: s = "Cannot specify two -m's."; break;
+    case GF_E_TWO_DIV: s = "Cannot specify two -d's."; break;
+    case GF_E_POLYSPC: s = "-p needs to be followed by a number in hex (0x optional)."; break;
+    case GF_E_GROUPAR: s = "Ran out of arguments in -m GROUP."; break;
+    case GF_E_GROUPNU: s = "In -m GROUP g_s g_r -- g_s and g_r need to be numbers."; break;
+    case GF_E_SPLITAR: s = "Ran out of arguments in -m SPLIT."; break;
+    case GF_E_SPLITNU: s = "In -m SPLIT w_a w_b -- w_a and w_b need to be numbers."; break;
+    case GF_E_FEWARGS: s = "Not enough arguments (Perhaps end with '-'?)"; break;
+    case GF_E_CFM___W: s = "-m CARRY_FREE, w must be 4, 8, 16, 32, 64 or 128."; break;
+    case GF_E_COMPXPP: s = "-m COMPOSITE, No poly specified, and we don't have a default for the given sub-field."; break;
+    case GF_E_BASE__W: s = "-m COMPOSITE and the base field is not for w/2."; break;
+    case GF_E_CFM4POL: s = "-m CARRY_FREE, w=4. (Prim-poly & 0xc) must equal 0."; break;
+    case GF_E_CFM8POL: s = "-m CARRY_FREE, w=8. (Prim-poly & 0x80) must equal 0."; break;
+    case GF_E_CF16POL: s = "-m CARRY_FREE, w=16. (Prim-poly & 0xe000) must equal 0."; break;
+    case GF_E_CF32POL: s = "-m CARRY_FREE, w=32. (Prim-poly & 0xfe000000) must equal 0."; break;
+    case GF_E_CF64POL: s = "-m CARRY_FREE, w=64. (Prim-poly & 0xfffe000000000000ULL) must equal 0."; break;
+    case GF_E_MDEFDIV: s = "If multiplication method == default, can't change division."; break;
+    case GF_E_MDEFREG: s = "If multiplication method == default, can't change region."; break;
+    case GF_E_MDEFARG: s = "If multiplication method == default, can't use arg1/arg2."; break;
+    case GF_E_DIVCOMP: s = "Cannot change the division technique with -m COMPOSITE."; break;
+    case GF_E_DOUQUAD: s = "Cannot specify -r DOUBLE and -r QUAD."; break;
+    case GF_E_SSE__NO: s = "Cannot specify -r SSE and -r NOSSE."; break;
+    case GF_E_CAUCHYB: s = "Cannot specify -r CAUCHY and any other -r."; break;
+    case GF_E_CAUCOMP: s = "Cannot specify -m COMPOSITE and -r CAUCHY."; break;
+    case GF_E_CAUGT32: s = "Cannot specify -r CAUCHY with w > 32."; break;
+    case GF_E_ARG1SET: s = "Only use arg1 with SPLIT, GROUP or COMPOSITE."; break;
+    case GF_E_ARG2SET: s = "Only use arg2 with SPLIT or GROUP."; break;
+    case GF_E_MATRIXW: s = "Cannot specify -d MATRIX with w > 32."; break;
+    case GF_E_BAD___W: s = "W must be 1-32, 64 or 128."; break;
+    case GF_E_DOUBLET: s = "Can only specify -r DOUBLE with -m TABLE."; break;
+    case GF_E_DOUBLEW: s = "Can only specify -r DOUBLE w = 4 or w = 8."; break;
+    case GF_E_DOUBLEJ: s = "Cannot specify -r DOUBLE with -r ALTMAP|SSE|NOSSE."; break;
+    case GF_E_DOUBLEL: s = "Can only specify -r DOUBLE -r LAZY with w = 8"; break;
+    case GF_E_QUAD__T: s = "Can only specify -r QUAD with -m TABLE."; break;
+    case GF_E_QUAD__W: s = "Can only specify -r QUAD w = 4."; break;
+    case GF_E_QUAD__J: s = "Cannot specify -r QUAD with -r ALTMAP|SSE|NOSSE."; break;
+    case GF_E_BADPOLY: s = "Bad primitive polynomial (high bits set)."; break;
+    case GF_E_COMP_PP: s = "Bad primitive polynomial -- bigger than sub-field."; break;
+    case GF_E_LAZY__X: s = "If -r LAZY, then -r must be DOUBLE or QUAD."; break;
+    case GF_E_ALTSHIF: s = "Cannot specify -m SHIFT and -r ALTMAP."; break;
+    case GF_E_SSESHIF: s = "Cannot specify -m SHIFT and -r SSE|NOSSE."; break;
+    case GF_E_ALT_CFM: s = "Cannot specify -m CARRY_FREE and -r ALTMAP."; break;
+    case GF_E_SSE_CFM: s = "Cannot specify -m CARRY_FREE and -r SSE|NOSSE."; break;
+    case GF_E_PCLMULX: s = "Specified -m CARRY_FREE, but PCLMUL is not supported."; break;
+    case GF_E_ALT_BY2: s = "Cannot specify -m BYTWO_x and -r ALTMAP."; break;
+    case GF_E_BY2_SSE: s = "Specified -m BYTWO_x -r SSE, but SSE2 is not supported."; break;
+    case GF_E_LOGBADW: s = "With Log Tables, w must be <= 27."; break;
+    case GF_E_LOG___J: s = "Cannot use Log tables with -r ALTMAP|SSE|NOSSE."; break;
+    case GF_E_LOGPOLY: s = "Cannot use Log tables because the polynomial is not primitive."; break;
+    case GF_E_ZERBADW: s = "With -m LOG_ZERO, w must be 8 or 16."; break;
+    case GF_E_ZEXBADW: s = "With -m LOG_ZERO_EXT, w must be 8."; break;
+    case GF_E_GR_ARGX: s = "With -m GROUP, arg1 and arg2 must be >= 0."; break;
+    case GF_E_GR_W_48: s = "With -m GROUP, w cannot be 4 or 8."; break;
+    case GF_E_GR_W_16: s = "With -m GROUP, w == 16, arg1 and arg2 must be 4."; break;
+    case GF_E_GR_128A: s = "With -m GROUP, w == 128, arg1 must be 4, and arg2 in { 4,8,16 }."; break;
+    case GF_E_GR_A_27: s = "With -m GROUP, arg1 and arg2 must be <= 27."; break;
+    case GF_E_GR_AR_W: s = "With -m GROUP, arg1 and arg2 must be <= w."; break;
+    case GF_E_GR____J: s = "Cannot use GROUP with -r ALTMAP|SSE|NOSSE."; break;
+    case GF_E_TABLE_W: s = "With -m TABLE, w must be < 15, or == 16."; break;
+    case GF_E_TAB_SSE: s = "With -m TABLE, SSE|NOSSE only applies to w=4."; break;
+    case GF_E_TABSSE3: s = "With -m TABLE, -r SSE, you need SSSE3 supported."; break;
+    case GF_E_TAB_ALT: s = "With -m TABLE, you cannot use ALTMAP."; break;
+    case GF_E_SP128AR: s = "With -m SPLIT, w=128, bad arg1/arg2."; break;
+    case GF_E_SP128AL: s = "With -m SPLIT, w=128, -r SSE requires -r ALTMAP."; break;
+    case GF_E_SP128AS: s = "With -m SPLIT, w=128, ALTMAP needs SSSE3 supported."; break;
+    case GF_E_SP128_A: s = "With -m SPLIT, w=128, -r SSE|NOSSE only with arg1/arg2 = 4/128."; break;
+    case GF_E_SP128_S: s = "With -m SPLIT, w=128, -r ALTMAP only with arg1/arg2 = 4/128."; break;
+    case GF_E_SPLIT_W: s = "With -m SPLIT, w must be in {8, 16, 32, 64, 128}."; break;
+    case GF_E_SP_16AR: s = "With -m SPLIT, w=16, Bad arg1/arg2."; break;
+    case GF_E_SP_16_A: s = "With -m SPLIT, w=16, -r ALTMAP only with arg1/arg2 = 4/16."; break;
+    case GF_E_SP_16_S: s = "With -m SPLIT, w=16, -r SSE|NOSSE only with arg1/arg2 = 4/16."; break;
+    case GF_E_SP_32AR: s = "With -m SPLIT, w=32, Bad arg1/arg2."; break;
+    case GF_E_SP_32AS: s = "With -m SPLIT, w=32, -r ALTMAP needs SSSE3 supported."; break;
+    case GF_E_SP_32_A: s = "With -m SPLIT, w=32, -r ALTMAP only with arg1/arg2 = 4/32."; break;
+    case GF_E_SP_32_S: s = "With -m SPLIT, w=32, -r SSE|NOSSE only with arg1/arg2 = 4/32."; break;
+    case GF_E_SP_64AR: s = "With -m SPLIT, w=64, Bad arg1/arg2."; break;
+    case GF_E_SP_64AS: s = "With -m SPLIT, w=64, -r ALTMAP needs SSSE3 supported."; break;
+    case GF_E_SP_64_A: s = "With -m SPLIT, w=64, -r ALTMAP only with arg1/arg2 = 4/64."; break;
+    case GF_E_SP_64_S: s = "With -m SPLIT, w=64, -r SSE|NOSSE only with arg1/arg2 = 4/64."; break;
+    case GF_E_SP_8_AR: s = "With -m SPLIT, w=8, Bad arg1/arg2."; break;
+    case GF_E_SP_8__A: s = "With -m SPLIT, w=8, Can't have -r ALTMAP."; break;
+    case GF_E_SP_SSE3: s = "With -m SPLIT, Need SSSE3 support for SSE."; break;
+    case GF_E_COMP_A2: s = "With -m COMPOSITE, arg1 must equal 2."; break;
+    case GF_E_COMP_SS: s = "With -m COMPOSITE, -r SSE and -r NOSSE do not apply."; break;
+    case GF_E_COMP__W: s = "With -m COMPOSITE, w must be 8, 16, 32, 64 or 128."; break;
+    case GF_E_UNKFLAG: s = "Unknown method flag - should be -m, -d, -r or -p."; break;
+    case GF_E_UNKNOWN: s = "Unknown multiplication type."; break;
+    case GF_E_UNK_REG: s = "Unknown region type."; break;
+    case GF_E_UNK_DIV: s = "Unknown division type."; break;
+    default: s = "Undefined error.";
+  }
+
+  fprintf(stderr, "%s\n", s);
+}
+
+uint64_t gf_composite_get_default_poly(gf_t *base) 
+{
+  gf_internal_t *h;
+  int rv;
+
+  h = (gf_internal_t *) base->scratch;
+  if (h->w == 4) {
+    if (h->mult_type == GF_MULT_COMPOSITE) return 0;
+    if (h->prim_poly == 0x13) return 2;
+    return 0;
+  } 
+  if (h->w == 8) {
+    if (h->mult_type == GF_MULT_COMPOSITE) return 0;
+    if (h->prim_poly == 0x11d) return 3;
+    return 0;
+  }
+  if (h->w == 16) {
+    if (h->mult_type == GF_MULT_COMPOSITE) {
+      rv = gf_composite_get_default_poly(h->base_gf);
+      if (rv != h->prim_poly) return 0;
+      if (rv == 3) return 0x105;
+      return 0;
+    } else {
+      if (h->prim_poly == 0x1100b) return 2;
+      if (h->prim_poly == 0x1002d) return 7;
+      return 0;
+    }
+  }
+  if (h->w == 32) {
+    if (h->mult_type == GF_MULT_COMPOSITE) {
+      rv = gf_composite_get_default_poly(h->base_gf);
+      if (rv != h->prim_poly) return 0;
+      if (rv == 2) return 0x10005;
+      if (rv == 7) return 0x10008;
+      if (rv == 0x105) return 0x10002;
+      return 0;
+    } else {
+      if (h->prim_poly == 0x400007) return 2;
+      if (h->prim_poly == 0xc5) return 3;
+      return 0;
+    }
+  }
+  if (h->w == 64) {
+    if (h->mult_type == GF_MULT_COMPOSITE) {
+      rv = gf_composite_get_default_poly(h->base_gf);
+      if (rv != h->prim_poly) return 0;
+      if (rv == 3) return 0x100000009ULL;
+      if (rv == 2) return 0x100000004ULL;
+      if (rv == 0x10005) return 0x100000003ULL;
+      if (rv == 0x10002) return 0x100000005ULL;
+      if (rv == 0x10008) return 0x100000006ULL;  /* JSP: (0x0x100000003 works too, 
+                                                    but I want to differentiate cases). */
+      return 0;
+    } else {
+      if (h->prim_poly == 0x1bULL) return 2;
+      return 0;
+    }
+  }
+  return 0;
+}
+
+int gf_error_check(int w, int mult_type, int region_type, int divide_type,
+                   int arg1, int arg2, uint64_t poly, gf_t *base)
+{
+  int sse3 = 0;
+  int sse2 = 0;
+  int pclmul = 0;
+  int rdouble, rquad, rlazy, rsse, rnosse, raltmap, rcauchy, tmp;
+  gf_internal_t *sub;
+
+  rdouble = (region_type & GF_REGION_DOUBLE_TABLE);
+  rquad   = (region_type & GF_REGION_QUAD_TABLE);
+  rlazy   = (region_type & GF_REGION_LAZY);
+  rsse    = (region_type & GF_REGION_SSE);
+  rnosse  = (region_type & GF_REGION_NOSSE);
+  raltmap = (region_type & GF_REGION_ALTMAP);
+  rcauchy = (region_type & GF_REGION_CAUCHY);
+
+  if (divide_type != GF_DIVIDE_DEFAULT &&
+      divide_type != GF_DIVIDE_MATRIX && 
+      divide_type != GF_DIVIDE_EUCLID) {
+    _gf_errno = GF_E_UNK_DIV;
+    return 0;
+  }
+
+  tmp = ( GF_REGION_DOUBLE_TABLE | GF_REGION_QUAD_TABLE | GF_REGION_LAZY |
+          GF_REGION_SSE | GF_REGION_NOSSE | GF_REGION_ALTMAP | GF_REGION_CAUCHY );
+  if (region_type & (~tmp)) { _gf_errno = GF_E_UNK_REG; return 0; }
+
+#ifdef INTEL_SSE2
+  sse2 = 1;
+#endif
+
+#ifdef INTEL_SSSE3
+  sse3 = 1;
+#endif
+
+#ifdef INTEL_SSE4_PCLMUL
+  pclmul = 1;
+#endif
+
+
+  if (w < 1 || (w > 32 && w != 64 && w != 128)) { _gf_errno = GF_E_BAD___W; return 0; }
+    
+  if (mult_type != GF_MULT_COMPOSITE && w < 64) {
+    if ((poly >> (w+1)) != 0)                   { _gf_errno = GF_E_BADPOLY; return 0; }
+  }
+
+  if (mult_type == GF_MULT_DEFAULT) {
+    if (divide_type != GF_DIVIDE_DEFAULT) { _gf_errno = GF_E_MDEFDIV; return 0; }
+    if (region_type != GF_REGION_DEFAULT) { _gf_errno = GF_E_MDEFREG; return 0; }
+    if (arg1 != 0 || arg2 != 0)           { _gf_errno = GF_E_MDEFARG; return 0; }
+    return 1;
+  }
+  
+  if (rsse && rnosse)                                { _gf_errno = GF_E_SSE__NO; return 0; }
+  if (rcauchy && w > 32)                             { _gf_errno = GF_E_CAUGT32; return 0; }
+  if (rcauchy && region_type != GF_REGION_CAUCHY)    { _gf_errno = GF_E_CAUCHYB; return 0; }
+  if (rcauchy && mult_type == GF_MULT_COMPOSITE)     { _gf_errno = GF_E_CAUCOMP; return 0; }
+
+  if (arg1 != 0 && mult_type != GF_MULT_COMPOSITE && 
+      mult_type != GF_MULT_SPLIT_TABLE && mult_type != GF_MULT_GROUP) {
+    _gf_errno = GF_E_ARG1SET;
+    return 0;
+  }
+
+  if (arg2 != 0 && mult_type != GF_MULT_SPLIT_TABLE && mult_type != GF_MULT_GROUP) {
+    _gf_errno = GF_E_ARG2SET;
+    return 0;
+  }
+
+  if (divide_type == GF_DIVIDE_MATRIX && w > 32) { _gf_errno = GF_E_MATRIXW; return 0; }
+
+  if (rdouble) {
+    if (rquad)                      { _gf_errno = GF_E_DOUQUAD; return 0; }
+    if (mult_type != GF_MULT_TABLE) { _gf_errno = GF_E_DOUBLET; return 0; }
+    if (w != 4 && w != 8)           { _gf_errno = GF_E_DOUBLEW; return 0; }
+    if (rsse || rnosse || raltmap)  { _gf_errno = GF_E_DOUBLEJ; return 0; }
+    if (rlazy && w == 4)            { _gf_errno = GF_E_DOUBLEL; return 0; }
+    return 1;
+  }
+
+  if (rquad) {
+    if (mult_type != GF_MULT_TABLE) { _gf_errno = GF_E_QUAD__T; return 0; }
+    if (w != 4)                     { _gf_errno = GF_E_QUAD__W; return 0; }
+    if (rsse || rnosse || raltmap)  { _gf_errno = GF_E_QUAD__J; return 0; }
+    return 1;
+  }
+
+  if (rlazy)                        { _gf_errno = GF_E_LAZY__X; return 0; }
+
+  if (mult_type == GF_MULT_SHIFT) {
+    if (raltmap)                    { _gf_errno = GF_E_ALTSHIF; return 0; }
+    if (rsse || rnosse)             { _gf_errno = GF_E_SSESHIF; return 0; }
+    return 1;
+  }
+
+  if (mult_type == GF_MULT_CARRY_FREE) {
+    if (w != 4 && w != 8 && w != 16 &&
+        w != 32 && w != 64 && w != 128)            { _gf_errno = GF_E_CFM___W; return 0; }
+    if (w == 4 && (poly & 0xc))                    { _gf_errno = GF_E_CFM4POL; return 0; }
+    if (w == 8 && (poly & 0x80))                   { _gf_errno = GF_E_CFM8POL; return 0; }
+    if (w == 16 && (poly & 0xe000))                { _gf_errno = GF_E_CF16POL; return 0; }
+    if (w == 32 && (poly & 0xfe000000))            { _gf_errno = GF_E_CF32POL; return 0; }
+    if (w == 64 && (poly & 0xfffe000000000000ULL)) { _gf_errno = GF_E_CF64POL; return 0; }
+    if (raltmap)                                   { _gf_errno = GF_E_ALT_CFM; return 0; }
+    if (rsse || rnosse)                            { _gf_errno = GF_E_SSE_CFM; return 0; }
+    if (!pclmul)                                   { _gf_errno = GF_E_PCLMULX; return 0; }
+    return 1;
+  }
+
+  if (mult_type == GF_MULT_BYTWO_p || mult_type == GF_MULT_BYTWO_b) {
+    if (raltmap)                    { _gf_errno = GF_E_ALT_BY2; return 0; }
+    if (rsse && !sse2)              { _gf_errno = GF_E_BY2_SSE; return 0; }
+    return 1;
+  }
+
+  if (mult_type == GF_MULT_LOG_TABLE || mult_type == GF_MULT_LOG_ZERO
+                                     || mult_type == GF_MULT_LOG_ZERO_EXT ) {
+    if (w > 27)                     { _gf_errno = GF_E_LOGBADW; return 0; }
+    if (raltmap || rsse || rnosse)  { _gf_errno = GF_E_LOG___J; return 0; }
+
+    if (mult_type == GF_MULT_LOG_TABLE) return 1;
+
+    if (w != 8 && w != 16)          { _gf_errno = GF_E_ZERBADW; return 0; }
+
+    if (mult_type == GF_MULT_LOG_ZERO) return 1;
+
+    if (w != 8)                     { _gf_errno = GF_E_ZEXBADW; return 0; }
+    return 1;
+  }
+
+  if (mult_type == GF_MULT_GROUP) {
+    if (arg1 <= 0 || arg2 <= 0)                 { _gf_errno = GF_E_GR_ARGX; return 0; }
+    if (w == 4 || w == 8)                       { _gf_errno = GF_E_GR_W_48; return 0; }
+    if (w == 16 && (arg1 != 4 || arg2 != 4))     { _gf_errno = GF_E_GR_W_16; return 0; }
+    if (w == 128 && (arg1 != 4 || 
+       (arg2 != 4 && arg2 != 8 && arg2 != 16))) { _gf_errno = GF_E_GR_128A; return 0; }
+    if (arg1 > 27 || arg2 > 27)                 { _gf_errno = GF_E_GR_A_27; return 0; }
+    if (arg1 > w || arg2 > w)                   { _gf_errno = GF_E_GR_AR_W; return 0; }
+    if (raltmap || rsse || rnosse)              { _gf_errno = GF_E_GR____J; return 0; }
+    return 1;
+  }
+  
+  if (mult_type == GF_MULT_TABLE) {
+    if (w != 16 && w >= 15)                     { _gf_errno = GF_E_TABLE_W; return 0; }
+    if (w != 4 && (rsse || rnosse))             { _gf_errno = GF_E_TAB_SSE; return 0; }
+    if (rsse && !sse3)                          { _gf_errno = GF_E_TABSSE3; return 0; }
+    if (raltmap)                                { _gf_errno = GF_E_TAB_ALT; return 0; }
+    return 1;
+  }
+
+  if (mult_type == GF_MULT_SPLIT_TABLE) {
+    if (arg1 > arg2) {
+      tmp = arg1;
+      arg1 = arg2;
+      arg2 = tmp;
+    }
+    if (w == 8) {
+      if (arg1 != 4 || arg2 != 8)               { _gf_errno = GF_E_SP_8_AR; return 0; }
+      if (rsse && !sse3)                        { _gf_errno = GF_E_SP_SSE3; return 0; }
+      if (raltmap)                              { _gf_errno = GF_E_SP_8__A; return 0; }
+    } else if (w == 16) {
+      if (arg1 == 4 && arg2 == 16) {
+        if (rsse && !sse3)                      { _gf_errno = GF_E_SP_SSE3; return 0; }
+      } else if (arg1 == 8 && (arg2 == 16 || arg2 == 8)) {
+        if (rsse || rnosse)                     { _gf_errno = GF_E_SP_16_S; return 0; }
+        if (raltmap)                            { _gf_errno = GF_E_SP_16_A; return 0; }
+      } else                                    { _gf_errno = GF_E_SP_16AR; return 0; }
+    } else if (w == 32) {
+      if ((arg1 == 8 && arg2 == 8) ||
+          (arg1 == 8 && arg2 == 32) ||
+          (arg1 == 16 && arg2 == 32)) {
+        if (rsse || rnosse)                     { _gf_errno = GF_E_SP_32_S; return 0; }
+        if (raltmap)                            { _gf_errno = GF_E_SP_32_A; return 0; }
+      } else if ((arg1 == 4 && arg2 == 32) ||
+          (arg1 == 4 && arg2 == 32)) {
+        if (rsse && !sse3)                      { _gf_errno = GF_E_SP_SSE3; return 0; }
+        if (raltmap && arg1 != 4)               { _gf_errno = GF_E_SP_32_A; return 0; }
+        if (raltmap && !sse3)                   { _gf_errno = GF_E_SP_32AS; return 0; }
+        if (raltmap && rnosse)                  { _gf_errno = GF_E_SP_32AS; return 0; }
+      } else                                    { _gf_errno = GF_E_SP_32AR; return 0; }
+    } else if (w == 64) {
+      if ((arg1 == 8 && arg2 == 8) ||
+          (arg1 == 8 && arg2 == 64) ||
+          (arg1 == 16 && arg2 == 64)) {
+        if (rsse || rnosse)                     { _gf_errno = GF_E_SP_64_S; return 0; }
+        if (raltmap)                            { _gf_errno = GF_E_SP_64_A; return 0; }
+      } else if (arg1 == 4 && arg2 == 64) {
+        if (rsse && !sse3)                      { _gf_errno = GF_E_SP_SSE3; return 0; }
+        if (raltmap && !sse3)                   { _gf_errno = GF_E_SP_64AS; return 0; }
+        if (raltmap && rnosse)                  { _gf_errno = GF_E_SP_64AS; return 0; }
+      } else                                    { _gf_errno = GF_E_SP_64AR; return 0; }
+    } else if (w == 128) {
+      if (arg1 == 8 && arg2 == 128) {
+        if (rsse || rnosse)                     { _gf_errno = GF_E_SP128_S; return 0; }
+        if (raltmap)                            { _gf_errno = GF_E_SP128_A; return 0; }
+      } else if (arg1 == 4 && arg2 == 128) {
+        if (rsse && !sse3)                      { _gf_errno = GF_E_SP_SSE3; return 0; }
+        if (raltmap && !sse3)                   { _gf_errno = GF_E_SP128AS; return 0; }
+        if (raltmap && rnosse)                  { _gf_errno = GF_E_SP128AS; return 0; }
+      } else                                    { _gf_errno = GF_E_SP128AR; return 0; }
+    } else                                      { _gf_errno = GF_E_SPLIT_W; return 0; }
+    return 1;
+  }
+
+  if (mult_type == GF_MULT_COMPOSITE) {
+    if (w != 8 && w != 16 && w != 32 
+               && w != 64 && w != 128)          { _gf_errno = GF_E_COMP__W; return 0; }
+    if ((poly >> (w/2)) != 0)                   { _gf_errno = GF_E_COMP_PP; return 0; }
+    if (divide_type != GF_DIVIDE_DEFAULT)       { _gf_errno = GF_E_DIVCOMP; return 0; }
+    if (arg1 != 2)                              { _gf_errno = GF_E_COMP_A2; return 0; }
+    if (rsse || rnosse)                         { _gf_errno = GF_E_COMP_SS; return 0; }
+    if (base != NULL) {
+      sub = (gf_internal_t *) base->scratch;
+      if (sub->w != w/2)                      { _gf_errno = GF_E_BASE__W; return 0; }
+      if (poly == 0) {
+        if (gf_composite_get_default_poly(base) == 0) { _gf_errno = GF_E_COMPXPP; return 0; }
+      }
+    }
+    return 1;
+  }
+
+  _gf_errno = GF_E_UNKNOWN; 
+  return 0;
+}
+
+int gf_scratch_size(int w, 
+                    int mult_type, 
+                    int region_type, 
+                    int divide_type, 
+                    int arg1, 
+                    int arg2)
+{
+  if (gf_error_check(w, mult_type, region_type, divide_type, arg1, arg2, 0, NULL) == 0) return 0;
+
+  switch(w) {
+    case 4: return gf_w4_scratch_size(mult_type, region_type, divide_type, arg1, arg2);
+    case 8: return gf_w8_scratch_size(mult_type, region_type, divide_type, arg1, arg2);
+    case 16: return gf_w16_scratch_size(mult_type, region_type, divide_type, arg1, arg2);
+    case 32: return gf_w32_scratch_size(mult_type, region_type, divide_type, arg1, arg2);
+    case 64: return gf_w64_scratch_size(mult_type, region_type, divide_type, arg1, arg2);
+    case 128: return gf_w128_scratch_size(mult_type, region_type, divide_type, arg1, arg2);
+    default: return gf_wgen_scratch_size(w, mult_type, region_type, divide_type, arg1, arg2);
+  }
+}
+
+extern int gf_size(gf_t *gf)
+{
+  gf_internal_t *h;
+  int s;
+
+  s = sizeof(gf_t);
+  h = (gf_internal_t *) gf->scratch;
+  s += gf_scratch_size(h->w, h->mult_type, h->region_type, h->divide_type, h->arg1, h->arg2);
+  if (h->mult_type == GF_MULT_COMPOSITE) s += gf_size(h->base_gf);
+  return s;
+}
+
+
+int gf_init_easy(gf_t *gf, int w)
+{
+  return gf_init_hard(gf, w, GF_MULT_DEFAULT, GF_REGION_DEFAULT, GF_DIVIDE_DEFAULT, 
+                      0, 0, 0, NULL, NULL);
+}
+
+/* Allen: What's going on here is this function is putting info into the
+       scratch mem of gf, and then calling the relevant REAL init
+       func for the word size.  Probably done this way to consolidate
+       those aspects of initialization that don't rely on word size,
+       and then take care of word-size-specific stuff. */
+
+int gf_init_hard(gf_t *gf, int w, int mult_type, 
+                        int region_type,
+                        int divide_type,
+                        uint64_t prim_poly,
+                        int arg1, int arg2,
+                        gf_t *base_gf,
+                        void *scratch_memory) 
+{
+  int sz;
+  gf_internal_t *h;
+ 
+  if (gf_error_check(w, mult_type, region_type, divide_type, 
+                     arg1, arg2, prim_poly, base_gf) == 0) return 0;
+
+  sz = gf_scratch_size(w, mult_type, region_type, divide_type, arg1, arg2);
+  if (sz <= 0) return 0;  /* This shouldn't happen, as all errors should get caught
+                             in gf_error_check() */
+  
+  if (scratch_memory == NULL) {
+    h = (gf_internal_t *) malloc(sz);
+    h->free_me = 1;
+  } else {
+    h = scratch_memory;
+    h->free_me = 0;
+  }
+  gf->scratch = (void *) h;
+  h->mult_type = mult_type;
+  h->region_type = region_type;
+  h->divide_type = divide_type;
+  h->w = w;
+  h->prim_poly = prim_poly;
+  h->arg1 = arg1;
+  h->arg2 = arg2;
+  h->base_gf = base_gf;
+  h->private = (void *) gf->scratch;
+  h->private = (char*)h->private + (sizeof(gf_internal_t));
+  gf->extract_word.w32 = NULL;
+
+  switch(w) {
+    case 4: return gf_w4_init(gf);
+    case 8: return gf_w8_init(gf);
+    case 16: return gf_w16_init(gf);
+    case 32: return gf_w32_init(gf);
+    case 64: return gf_w64_init(gf);
+    case 128: return gf_w128_init(gf);
+    default: return gf_wgen_init(gf);
+  }
+}
+
+int gf_free(gf_t *gf, int recursive)
+{
+  gf_internal_t *h;
+
+  h = (gf_internal_t *) gf->scratch;
+  if (recursive && h->base_gf != NULL) {
+    gf_free(h->base_gf, 1);
+    free(h->base_gf);
+  }
+  if (h->free_me) free(h);
+  return 0; /* Making compiler happy */
+}
+
+void gf_alignment_error(char *s, int a)
+{
+  fprintf(stderr, "Alignment error in %s:\n", s);
+  fprintf(stderr, "   The source and destination buffers must be aligned to each other,\n");
+  fprintf(stderr, "   and they must be aligned to a %d-byte address.\n", a);
+  exit(1);
+}
+
+static 
+void gf_invert_binary_matrix(uint32_t *mat, uint32_t *inv, int rows) {
+  int cols, i, j;
+  uint32_t tmp;
+
+  cols = rows;
+
+  for (i = 0; i < rows; i++) inv[i] = (1 << i);
+
+  /* First -- convert into upper triangular */
+
+  for (i = 0; i < cols; i++) {
+
+    /* Swap rows if we ave a zero i,i element.  If we can't swap, then the
+       matrix was not invertible */
+
+    if ((mat[i] & (1 << i)) == 0) {
+      for (j = i+1; j < rows && (mat[j] & (1 << i)) == 0; j++) ;
+      if (j == rows) {
+        fprintf(stderr, "galois_invert_matrix: Matrix not invertible!!\n");
+        exit(1);
+      }
+      tmp = mat[i]; mat[i] = mat[j]; mat[j] = tmp;
+      tmp = inv[i]; inv[i] = inv[j]; inv[j] = tmp;
+    }
+
+    /* Now for each j>i, add A_ji*Ai to Aj */
+    for (j = i+1; j != rows; j++) {
+      if ((mat[j] & (1 << i)) != 0) {
+        mat[j] ^= mat[i];
+        inv[j] ^= inv[i];
+      }
+    }
+  }
+
+  /* Now the matrix is upper triangular.  Start at the top and multiply down */
+
+  for (i = rows-1; i >= 0; i--) {
+    for (j = 0; j < i; j++) {
+      if (mat[j] & (1 << i)) {
+        /*  mat[j] ^= mat[i]; */
+        inv[j] ^= inv[i];
+      }
+    }
+  }
+}
+
+uint32_t gf_bitmatrix_inverse(uint32_t y, int w, uint32_t pp) 
+{
+  uint32_t mat[32], inv[32], mask;
+  int i;
+
+  mask = (w == 32) ? 0xffffffff : (1 << w) - 1;
+  for (i = 0; i < w; i++) {
+    mat[i] = y;
+
+    if (y & (1 << (w-1))) {
+      y = y << 1;
+      y = ((y ^ pp) & mask);
+    } else {
+      y = y << 1;
+    }
+  }
+
+  gf_invert_binary_matrix(mat, inv, w);
+  return inv[0];
+}
+
+void gf_two_byte_region_table_multiply(gf_region_data *rd, uint16_t *base)
+{
+  uint64_t a, prod;
+  int xor;
+  uint64_t *s64, *d64, *top;
+
+  s64 = rd->s_start;
+  d64 = rd->d_start;
+  top = rd->d_top;
+  xor = rd->xor;
+  
+  if (xor) {
+    while (d64 != top) {
+      a = *s64;
+      prod = base[a >> 48];
+      a <<= 16;
+      prod <<= 16;
+      prod ^= base[a >> 48];
+      a <<= 16;
+      prod <<= 16;
+      prod ^= base[a >> 48];
+      a <<= 16;
+      prod <<= 16;
+      prod ^= base[a >> 48];
+      prod ^= *d64;
+      *d64 = prod;
+      s64++;
+      d64++;
+    }
+  } else {
+    while (d64 != top) {
+      a = *s64;
+      prod = base[a >> 48];
+      a <<= 16;
+      prod <<= 16;
+      prod ^= base[a >> 48];
+      a <<= 16;
+      prod <<= 16;
+      prod ^= base[a >> 48];
+      a <<= 16;
+      prod <<= 16;
+      prod ^= base[a >> 48];
+      *d64 = prod;
+      s64++;
+      d64++;
+    }
+  }
+}
+
+static void gf_slow_multiply_region(gf_region_data *rd, void *src, void *dest, void *s_top)
+{
+  uint8_t *s8, *d8;
+  uint16_t *s16, *d16;
+  uint32_t *s32, *d32;
+  uint64_t *s64, *d64;
+  gf_internal_t *h;
+  int wb;
+  uint32_t p, a;
+
+  h = rd->gf->scratch;
+  wb = (h->w)/8;
+  if (wb == 0) wb = 1;
+  
+  while (src < s_top) {
+    switch (h->w) {
+    case 8:
+      s8 = (uint8_t *) src;
+      d8 = (uint8_t *) dest;
+      *d8 = (rd->xor) ? (*d8 ^ rd->gf->multiply.w32(rd->gf, rd->val, *s8)) : 
+                      rd->gf->multiply.w32(rd->gf, rd->val, *s8);
+      break;
+    case 4:
+      s8 = (uint8_t *) src;
+      d8 = (uint8_t *) dest;
+      a = *s8;
+      p = rd->gf->multiply.w32(rd->gf, rd->val, a&0xf);
+      p |= (rd->gf->multiply.w32(rd->gf, rd->val, a >> 4) << 4);
+      if (rd->xor) p ^= *d8;
+      *d8 = p;
+      break;
+    case 16:
+      s16 = (uint16_t *) src;
+      d16 = (uint16_t *) dest;
+      *d16 = (rd->xor) ? (*d16 ^ rd->gf->multiply.w32(rd->gf, rd->val, *s16)) : 
+                      rd->gf->multiply.w32(rd->gf, rd->val, *s16);
+      break;
+    case 32:
+      s32 = (uint32_t *) src;
+      d32 = (uint32_t *) dest;
+      *d32 = (rd->xor) ? (*d32 ^ rd->gf->multiply.w32(rd->gf, rd->val, *s32)) : 
+                      rd->gf->multiply.w32(rd->gf, rd->val, *s32);
+      break;
+    case 64:
+      s64 = (uint64_t *) src;
+      d64 = (uint64_t *) dest;
+      *d64 = (rd->xor) ? (*d64 ^ rd->gf->multiply.w64(rd->gf, rd->val, *s64)) : 
+                      rd->gf->multiply.w64(rd->gf, rd->val, *s64);
+      break;
+    default:
+      fprintf(stderr, "Error: gf_slow_multiply_region: w=%d not implemented.\n", h->w);
+      exit(1);
+    }
+    src = (char*)src + wb;
+    dest = (char*)dest + wb;
+  }
+}
+
+/* JSP - The purpose of this procedure is to error check alignment,
+   and to set up the region operation so that it can best leverage
+   large words.
+
+   It stores its information in rd.
+
+   Assuming you're not doing Cauchy coding, (see below for that),
+   then w will be 4, 8, 16, 32 or 64. It can't be 128 (probably
+   should change that).
+
+   src and dest must then be aligned on ceil(w/8)-byte boundaries.
+   Moreover, bytes must be a multiple of ceil(w/8).  If the variable
+   align is equal to ceil(w/8), then we will set s_start = src,
+   d_start = dest, s_top to (src+bytes) and d_top to (dest+bytes).
+   And we return -- the implementation will go ahead and do the
+   multiplication on individual words (e.g. using discrete logs).
+
+   If align is greater than ceil(w/8), then the implementation needs
+   to work on groups of "align" bytes.  For example, suppose you are
+   implementing BYTWO, without SSE. Then you will be doing the region
+   multiplication in units of 8 bytes, so align = 8. Or, suppose you
+   are doing a Quad table in GF(2^4). You will be doing the region
+   multiplication in units of 2 bytes, so align = 2. Or, suppose you
+   are doing split multiplication with SSE operations in GF(2^8).
+   Then align = 16. Worse yet, suppose you are doing split
+   multiplication with SSE operations in GF(2^16), with or without
+   ALTMAP. Then, you will be doing the multiplication on 256 bits at
+   a time.  So align = 32.
+
+   When align does not equal ceil(w/8), we split the region
+   multiplication into three parts.  We are going to make s_start be
+   the first address greater than or equal to src that is a multiple
+   of align.  s_top is going to be the largest address >= src+bytes
+   such that (s_top - s_start) is a multiple of align.  We do the
+   same with d_start and d_top.  When we say that "src and dest must
+   be aligned with respect to each other, we mean that s_start-src
+   must equal d_start-dest.
+
+   Now, the region multiplication is done in three parts -- the part
+   between src and s_start must be done using single words.
+   Similarly, the part between s_top and src+bytes must also be done
+   using single words.  The part between s_start and s_top will be
+   done in chunks of "align" bytes.
+
+   One final thing -- if align > 16, then s_start and d_start will be
+   aligned on a 16 byte boundary.  Perhaps we should have two
+   variables: align and chunksize.  Then we'd have s_start & d_start
+   aligned to "align", and have s_top-s_start be a multiple of
+   chunksize.  That may be less confusing, but it would be a big
+   change.
+
+   Finally, if align = -1, then we are doing Cauchy multiplication,
+   using only XOR's.  In this case, we're not going to care about
+   alignment because we are just doing XOR's.  Instead, the only
+   thing we care about is that bytes must be a multiple of w.
+
+   This is not to say that alignment doesn't matter in performance
+   with XOR's.  See that discussion in gf_multby_one().
+
+   After you call gf_set_region_data(), the procedure
+   gf_do_initial_region_alignment() calls gf->multiply.w32() on
+   everything between src and s_start.  The procedure
+   gf_do_final_region_alignment() calls gf->multiply.w32() on
+   everything between s_top and src+bytes.
+   */
+
+void gf_set_region_data(gf_region_data *rd,
+  gf_t *gf,
+  void *src,
+  void *dest,
+  int bytes,
+  uint64_t val,
+  int xor,
+  int align)
+{
+  gf_internal_t *h = NULL;
+  int wb;
+  uint32_t a;
+  unsigned long uls, uld;
+
+  if (gf == NULL) {  /* JSP - Can be NULL if you're just doing XOR's */
+    wb = 1;
+  } else {
+    h = gf->scratch;
+    wb = (h->w)/8;
+    if (wb == 0) wb = 1;
+  }
+  
+  rd->gf = gf;
+  rd->src = src;
+  rd->dest = dest;
+  rd->bytes = bytes;
+  rd->val = val;
+  rd->xor = xor;
+  rd->align = align;
+
+  uls = (unsigned long) src;
+  uld = (unsigned long) dest;
+
+  a = (align <= 16) ? align : 16;
+
+  if (align == -1) { /* JSP: This is cauchy.  Error check bytes, then set up the pointers
+                        so that there are no alignment regions. */
+    if (h != NULL && bytes % h->w != 0) {
+      fprintf(stderr, "Error in region multiply operation.\n");
+      fprintf(stderr, "The size must be a multiple of %d bytes.\n", h->w);
+      exit(1);
+    }
+  
+    rd->s_start = src;
+    rd->d_start = dest;
+    rd->s_top = (char*)src + bytes;
+    rd->d_top = (char*)src + bytes;
+    return;
+  }
+
+  if (uls % a != uld % a) {
+    fprintf(stderr, "Error in region multiply operation.\n");
+    fprintf(stderr, "The source & destination pointers must be aligned with respect\n");
+    fprintf(stderr, "to each other along a %d byte boundary.\n", a);
+    fprintf(stderr, "Src = 0x%lx.  Dest = 0x%lx\n", (unsigned long) src,
+            (unsigned long) dest);
+    exit(1);
+  }
+
+  if (uls % wb != 0) {
+    fprintf(stderr, "Error in region multiply operation.\n");
+    fprintf(stderr, "The pointers must be aligned along a %d byte boundary.\n", wb);
+    fprintf(stderr, "Src = 0x%lx.  Dest = 0x%lx\n", (unsigned long) src,
+            (unsigned long) dest);
+    exit(1);
+  }
+
+  if (bytes % wb != 0) {
+    fprintf(stderr, "Error in region multiply operation.\n");
+    fprintf(stderr, "The size must be a multiple of %d bytes.\n", wb);
+    exit(1);
+  }
+
+  uls %= a;
+  if (uls != 0) uls = (a-uls);
+  rd->s_start = (char*)rd->src + uls;
+  rd->d_start = (char*)rd->dest + uls;
+  bytes -= uls;
+  bytes -= (bytes % align);
+  rd->s_top = (char*)rd->s_start + bytes;
+  rd->d_top = (char*)rd->d_start + bytes;
+
+}
+
+void gf_do_initial_region_alignment(gf_region_data *rd)
+{
+  gf_slow_multiply_region(rd, rd->src, rd->dest, rd->s_start);
+}
+
+void gf_do_final_region_alignment(gf_region_data *rd)
+{
+  gf_slow_multiply_region(rd, rd->s_top, rd->d_top, (char*)rd->src+rd->bytes);
+}
+
+void gf_multby_zero(void *dest, int bytes, int xor) 
+{
+  if (xor) return;
+  bzero(dest, bytes);
+  return;
+}
+
+/* JSP - gf_multby_one tries to do this in the most efficient way
+   possible.  If xor = 0, then simply call memcpy() since that
+   should be optimized by the system.  Otherwise, try to do the xor
+   in the following order:
+
+   If src and dest are aligned with respect to each other on 16-byte
+   boundaries and you have SSE instructions, then use aligned SSE
+   instructions.
+
+   If they aren't but you still have SSE instructions, use unaligned
+   SSE instructions.
+
+   If there are no SSE instructions, but they are aligned with
+   respect to each other on 8-byte boundaries, then do them with
+   uint64_t's.
+
+   Otherwise, call gf_unaligned_xor(), which does the following:
+   align a destination pointer along an 8-byte boundary, and then
+   memcpy 32 bytes at a time from the src pointer to an array of
+   doubles.  I'm not sure if that's the best -- probably needs
+   testing, but this seems like it could be a black hole.
+ */
+
+static void gf_unaligned_xor(void *src, void *dest, int bytes);
+
+void gf_multby_one(void *src, void *dest, int bytes, int xor) 
+{
+#ifdef   INTEL_SSE2
+  __m128i ms, md;
+#endif
+  unsigned long uls, uld;
+  uint8_t *s8, *d8;
+  uint64_t *s64, *d64, *dtop64;
+  gf_region_data rd;
+
+  if (!xor) {
+    memcpy(dest, src, bytes);
+    return;
+  }
+  uls = (unsigned long) src;
+  uld = (unsigned long) dest;
+
+#ifdef   INTEL_SSE2
+  int abytes;
+  s8 = (uint8_t *) src;
+  d8 = (uint8_t *) dest;
+  if (uls % 16 == uld % 16) {
+    gf_set_region_data(&rd, NULL, src, dest, bytes, 1, xor, 16);
+    while (s8 != rd.s_start) {
+      *d8 ^= *s8;
+      d8++;
+      s8++;
+    }
+    while (s8 < (uint8_t *) rd.s_top) {
+      ms = _mm_load_si128 ((__m128i *)(s8));
+      md = _mm_load_si128 ((__m128i *)(d8));
+      md = _mm_xor_si128(md, ms);
+      _mm_store_si128((__m128i *)(d8), md);
+      s8 += 16;
+      d8 += 16;
+    }
+    while (s8 != (uint8_t *) src + bytes) {
+      *d8 ^= *s8;
+      d8++;
+      s8++;
+    }
+    return;
+  }
+
+  abytes = (bytes & 0xfffffff0);
+
+  while (d8 < (uint8_t *) dest + abytes) {
+    ms = _mm_loadu_si128 ((__m128i *)(s8));
+    md = _mm_loadu_si128 ((__m128i *)(d8));
+    md = _mm_xor_si128(md, ms);
+    _mm_storeu_si128((__m128i *)(d8), md);
+    s8 += 16;
+    d8 += 16;
+  }
+  while (d8 != (uint8_t *) dest+bytes) {
+    *d8 ^= *s8;
+    d8++;
+    s8++;
+  }
+  return;
+#endif
+
+  if (uls % 8 != uld % 8) {
+    gf_unaligned_xor(src, dest, bytes);
+    return;
+  }
+  
+  gf_set_region_data(&rd, NULL, src, dest, bytes, 1, xor, 8);
+  s8 = (uint8_t *) src;
+  d8 = (uint8_t *) dest;
+  while (d8 != rd.d_start) {
+    *d8 ^= *s8;
+    d8++;
+    s8++;
+  }
+  dtop64 = (uint64_t *) rd.d_top;
+
+  d64 = (uint64_t *) rd.d_start;
+  s64 = (uint64_t *) rd.s_start;
+
+  while (d64 < dtop64) {
+    *d64 ^= *s64;
+    d64++;
+    s64++;
+  }
+
+  s8 = (uint8_t *) rd.s_top;
+  d8 = (uint8_t *) rd.d_top;
+
+  while (d8 != (uint8_t *) dest+bytes) {
+    *d8 ^= *s8;
+    d8++;
+    s8++;
+  }
+  return;
+}
+
+#define UNALIGNED_BUFSIZE (8)
+
+static void gf_unaligned_xor(void *src, void *dest, int bytes)
+{
+  uint64_t scopy[UNALIGNED_BUFSIZE], *d64;
+  int i;
+  gf_region_data rd;
+  uint8_t *s8, *d8;
+
+  /* JSP - call gf_set_region_data(), but use dest in both places.  This is
+     because I only want to set up dest.  If I used src, gf_set_region_data()
+     would fail because src and dest are not aligned to each other wrt 
+     8-byte pointers.  I know this will actually align d_start to 16 bytes.
+     If I change gf_set_region_data() to split alignment & chunksize, then 
+     I could do this correctly. */
+
+  gf_set_region_data(&rd, NULL, dest, dest, bytes, 1, 1, 8*UNALIGNED_BUFSIZE);
+  s8 = (uint8_t *) src;
+  d8 = (uint8_t *) dest;
+
+  while (d8 < (uint8_t *) rd.d_start) {
+    *d8 ^= *s8;
+    d8++;
+    s8++;
+  }
+  
+  d64 = (uint64_t *) d8;
+  while (d64 < (uint64_t *) rd.d_top) {
+    memcpy(scopy, s8, 8*UNALIGNED_BUFSIZE);
+    s8 += 8*UNALIGNED_BUFSIZE;
+    for (i = 0; i < UNALIGNED_BUFSIZE; i++) {
+      *d64 ^= scopy[i];
+      d64++;
+    }
+  }
+  
+  d8 = (uint8_t *) d64;
+  while (d8 < (uint8_t *) ((char*)dest+bytes)) {
+    *d8 ^= *s8;
+    d8++;
+    s8++;
+  }
+}
diff --git a/src/erasure-code/jerasure/gf-complete/src/gf_general.c b/src/erasure-code/jerasure/gf-complete/src/gf_general.c
new file mode 100644
index 0000000..c410598
--- /dev/null
+++ b/src/erasure-code/jerasure/gf-complete/src/gf_general.c
@@ -0,0 +1,538 @@
+/*
+ * GF-Complete: A Comprehensive Open Source Library for Galois Field Arithmetic
+ * James S. Plank, Ethan L. Miller, Kevin M. Greenan,
+ * Benjamin A. Arnold, John A. Burnum, Adam W. Disney, Allen C. McBride.
+ *
+ * gf_general.c
+ *
+ * This file has helper routines for doing basic GF operations with any
+ * legal value of w.  The problem is that w <= 32, w=64 and w=128 all have
+ * different data types, which is a pain.  The procedures in this file try
+ * to alleviate that pain.  They are used in gf_unit and gf_time.
+ */
+
+#include <stdio.h>
+#include <getopt.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "gf_complete.h"
+#include "gf_int.h"
+#include "gf_method.h"
+#include "gf_rand.h"
+#include "gf_general.h"
+
+void gf_general_set_zero(gf_general_t *v, int w)
+{
+  if (w <= 32) {
+    v->w32 = 0;
+  } else if (w <= 64) {
+    v->w64 = 0;
+  } else {
+    v->w128[0] = 0;
+    v->w128[1] = 0;
+  }
+}
+
+void gf_general_set_one(gf_general_t *v, int w)
+{
+  if (w <= 32) {
+    v->w32 = 1;
+  } else if (w <= 64) {
+    v->w64 = 1;
+  } else {
+    v->w128[0] = 0;
+    v->w128[1] = 1;
+  }
+}
+
+void gf_general_set_two(gf_general_t *v, int w)
+{
+  if (w <= 32) {
+    v->w32 = 2;
+  } else if (w <= 64) {
+    v->w64 = 2;
+  } else {
+    v->w128[0] = 0;
+    v->w128[1] = 2;
+  }
+}
+
+int gf_general_is_zero(gf_general_t *v, int w) 
+{
+  if (w <= 32) {
+    return (v->w32 == 0);
+  } else if (w <= 64) {
+    return (v->w64 == 0);
+  } else {
+    return (v->w128[0] == 0 && v->w128[1] == 0);
+  }
+}
+
+int gf_general_is_one(gf_general_t *v, int w) 
+{
+  if (w <= 32) {
+    return (v->w32 == 1);
+  } else if (w <= 64) {
+    return (v->w64 == 1);
+  } else {
+    return (v->w128[0] == 0 && v->w128[1] == 1);
+  }
+}
+
+void gf_general_set_random(gf_general_t *v, int w, int zero_ok) 
+{
+  if (w <= 32) {
+      v->w32 = MOA_Random_W(w, zero_ok);
+  } else if (w <= 64) {
+    while (1) {
+      v->w64 = MOA_Random_64();
+      if (v->w64 != 0 || zero_ok) return;
+    }
+  } else {
+    while (1) {
+      MOA_Random_128(v->w128);
+      if (v->w128[0] != 0 || v->w128[1] != 0 || zero_ok) return;
+    }
+  }
+}
+
+void gf_general_val_to_s(gf_general_t *v, int w, char *s, int hex)
+{
+  if (w <= 32) {
+    if (hex) {
+      sprintf(s, "%x", v->w32);
+    } else {
+      sprintf(s, "%u", v->w32);
+    }
+  } else if (w <= 64) {
+    if (hex) {
+      sprintf(s, "%llx", (long long unsigned int) v->w64);
+    } else {
+      sprintf(s, "%lld", (long long unsigned int) v->w64);
+    }
+  } else {
+    if (v->w128[0] == 0) {
+      sprintf(s, "%llx", (long long unsigned int) v->w128[1]);
+    } else {
+      sprintf(s, "%llx%016llx", (long long unsigned int) v->w128[0], 
+                                (long long unsigned int) v->w128[1]);
+    }
+  }
+}
+
+int gf_general_s_to_val(gf_general_t *v, int w, char *s, int hex)
+{
+  int l;
+  int save;
+
+  if (w <= 32) {
+    if (hex) {
+      if (sscanf(s, "%x", &(v->w32)) == 0) return 0;
+    } else {
+      if (sscanf(s, "%u", &(v->w32)) == 0) return 0;
+    }
+    if (w == 32) return 1;
+    if (w == 31) {
+      if (v->w32 & (1 << 31)) return 0;
+      return 1;
+    } 
+    if (v->w32 & ~((1 << w)-1)) return 0;
+    return 1;
+  } else if (w <= 64) {
+    if (hex) return (sscanf(s, "%llx", (long long unsigned int *) (&(v->w64))) == 1);
+    return (sscanf(s, "%lld", (long long int *) (&(v->w64))) == 1);
+  } else {
+    if (!hex) return 0;
+    l = strlen(s);
+    if (l <= 16) {
+      v->w128[0] = 0;
+      return (sscanf(s, "%llx", (long long unsigned int *) (&(v->w128[1]))) == 1);
+    } else {
+      if (l > 32) return 0;
+      save = s[l-16];
+      s[l-16] = '\0';
+      if (sscanf(s, "%llx", (long long unsigned int *) (&(v->w128[0]))) == 0) {
+        s[l-16] = save;
+        return 0;
+      }
+      return (sscanf(s+(l-16), "%llx", (long long unsigned int *) (&(v->w128[1]))) == 1);
+    }
+  }
+}
+    
+void gf_general_add(gf_t *gf, gf_general_t *a, gf_general_t *b, gf_general_t *c)
+{
+  gf_internal_t *h;
+  int w;
+
+  h = (gf_internal_t *) gf->scratch;
+  w = h->w;
+
+  if (w <= 32) {
+    c->w32 = a->w32 ^ b->w32;
+  } else if (w <= 64) {
+    c->w64 = a->w64 ^ b->w64;
+  } else {
+    c->w128[0] = a->w128[0] ^ b->w128[0];
+    c->w128[1] = a->w128[1] ^ b->w128[1];
+  }
+}
+  
+void gf_general_multiply(gf_t *gf, gf_general_t *a, gf_general_t *b, gf_general_t *c)
+{
+  gf_internal_t *h;
+  int w;
+
+  h = (gf_internal_t *) gf->scratch;
+  w = h->w;
+
+  if (w <= 32) {
+    c->w32 = gf->multiply.w32(gf, a->w32, b->w32);
+  } else if (w <= 64) {
+    c->w64 = gf->multiply.w64(gf, a->w64, b->w64);
+  } else {
+    gf->multiply.w128(gf, a->w128, b->w128, c->w128);
+  }
+}
+  
+void gf_general_divide(gf_t *gf, gf_general_t *a, gf_general_t *b, gf_general_t *c)
+{
+  gf_internal_t *h;
+  int w;
+
+  h = (gf_internal_t *) gf->scratch;
+  w = h->w;
+
+  if (w <= 32) {
+    c->w32 = gf->divide.w32(gf, a->w32, b->w32);
+  } else if (w <= 64) {
+    c->w64 = gf->divide.w64(gf, a->w64, b->w64);
+  } else {
+    gf->divide.w128(gf, a->w128, b->w128, c->w128);
+  }
+}
+  
+void gf_general_inverse(gf_t *gf, gf_general_t *a, gf_general_t *b)
+{
+  gf_internal_t *h;
+  int w;
+
+  h = (gf_internal_t *) gf->scratch;
+  w = h->w;
+
+  if (w <= 32) {
+    b->w32 = gf->inverse.w32(gf, a->w32);
+  } else if (w <= 64) {
+    b->w64 = gf->inverse.w64(gf, a->w64);
+  } else {
+    gf->inverse.w128(gf, a->w128, b->w128);
+  }
+}
+  
+int gf_general_are_equal(gf_general_t *v1, gf_general_t *v2, int w)
+{
+  if (w <= 32) {
+    return (v1->w32 == v2->w32);
+  } else if (w <= 64) {
+    return (v1->w64 == v2->w64);
+  } else {
+    return (v1->w128[0] == v2->w128[0] &&
+            v1->w128[0] == v2->w128[0]);
+  }
+}
+
+void gf_general_do_region_multiply(gf_t *gf, gf_general_t *a, void *ra, void *rb, int bytes, int xor)
+{
+  gf_internal_t *h;
+  int w;
+
+  h = (gf_internal_t *) gf->scratch;
+  w = h->w;
+
+  if (w <= 32) {
+    gf->multiply_region.w32(gf, ra, rb, a->w32, bytes, xor);
+  } else if (w <= 64) {
+    gf->multiply_region.w64(gf, ra, rb, a->w64, bytes, xor);
+  } else {
+    gf->multiply_region.w128(gf, ra, rb, a->w128, bytes, xor);
+  }
+}
+
+void gf_general_do_region_check(gf_t *gf, gf_general_t *a, void *orig_a, void *orig_target, void *final_target, int bytes, int xor)
+{
+  gf_internal_t *h;
+  int w, words, i;
+  gf_general_t oa, ot, ft, sb;
+  char sa[50], soa[50], sot[50], sft[50], ssb[50];
+
+  h = (gf_internal_t *) gf->scratch;
+  w = h->w;
+
+  words = (bytes * 8) / w;
+  for (i = 0; i < words; i++) {
+    if (w <= 32) {
+      oa.w32 = gf->extract_word.w32(gf, orig_a, bytes, i);
+      ot.w32 = gf->extract_word.w32(gf, orig_target, bytes, i);
+      ft.w32 = gf->extract_word.w32(gf, final_target, bytes, i);
+      sb.w32 = gf->multiply.w32(gf, a->w32, oa.w32);
+      if (xor) sb.w32 ^= ot.w32;
+    } else if (w <= 64) {
+      oa.w64 = gf->extract_word.w64(gf, orig_a, bytes, i);
+      ot.w64 = gf->extract_word.w64(gf, orig_target, bytes, i);
+      ft.w64 = gf->extract_word.w64(gf, final_target, bytes, i);
+      sb.w64 = gf->multiply.w64(gf, a->w64, oa.w64);
+      if (xor) sb.w64 ^= ot.w64;
+    } else {
+      gf->extract_word.w128(gf, orig_a, bytes, i, oa.w128);
+      gf->extract_word.w128(gf, orig_target, bytes, i, ot.w128);
+      gf->extract_word.w128(gf, final_target, bytes, i, ft.w128);
+      gf->multiply.w128(gf, a->w128, oa.w128, sb.w128);
+      if (xor) {
+        sb.w128[0] ^= ot.w128[0];
+        sb.w128[1] ^= ot.w128[1];
+      }
+    }
+
+    if (!gf_general_are_equal(&ft, &sb, w)) {
+      
+      fprintf(stderr,"Problem with region multiply (all values in hex):\n");
+      fprintf(stderr,"   Target address base: 0x%lx.  Word 0x%x of 0x%x.  Xor: %d\n", 
+                 (unsigned long) final_target, i, words, xor);
+      gf_general_val_to_s(a, w, sa, 1);
+      gf_general_val_to_s(&oa, w, soa, 1);
+      gf_general_val_to_s(&ot, w, sot, 1);
+      gf_general_val_to_s(&ft, w, sft, 1);
+      gf_general_val_to_s(&sb, w, ssb, 1);
+      fprintf(stderr,"   Value: %s\n", sa);
+      fprintf(stderr,"   Original source word: %s\n", soa);
+      if (xor) fprintf(stderr,"   XOR with target word: %s\n", sot);
+      fprintf(stderr,"   Product word: %s\n", sft);
+      fprintf(stderr,"   It should be: %s\n", ssb);
+      exit(0);
+    }
+  }
+}
+
+void gf_general_set_up_single_timing_test(int w, void *ra, void *rb, int size)
+{
+  void *top;
+  gf_general_t g;
+  uint8_t *r8, *r8a;
+  uint16_t *r16;
+  uint32_t *r32;
+  uint64_t *r64;
+  int i;
+
+  top = (char*)rb+size;
+
+  /* If w is 8, 16, 32, 64 or 128, fill the regions with random bytes.
+     However, don't allow for zeros in rb, because that will screw up
+     division.
+     
+     When w is 4, you fill the regions with random 4-bit words in each byte.
+
+     Otherwise, treat every four bytes as an uint32_t
+     and fill it with a random value mod (1 << w).
+   */
+
+  if (w == 8 || w == 16 || w == 32 || w == 64 || w == 128) {
+    MOA_Fill_Random_Region (ra, size);
+    while (rb < top) {
+      gf_general_set_random(&g, w, 0);
+      switch (w) {
+        case 8: 
+          r8 = (uint8_t *) rb;
+          *r8 = g.w32;
+          break;
+        case 16: 
+          r16 = (uint16_t *) rb;
+          *r16 = g.w32;
+          break;
+        case 32: 
+          r32 = (uint32_t *) rb;
+          *r32 = g.w32;
+          break;
+        case 64:
+          r64 = (uint64_t *) rb;
+          *r64 = g.w64;
+          break;
+        case 128: 
+          r64 = (uint64_t *) rb;
+          r64[0] = g.w128[0];
+          r64[1] = g.w128[1];
+          break;
+      }
+      rb = (char*)rb + (w/8);
+    }
+  } else if (w == 4) {
+    r8a = (uint8_t *) ra;
+    r8 = (uint8_t *) rb;
+    while (r8 < (uint8_t *) top) {
+      gf_general_set_random(&g, w, 1);
+      *r8a = g.w32;
+      gf_general_set_random(&g, w, 0);
+      *r8 = g.w32;
+      r8a++;
+      r8++;
+    }
+  } else {
+    r32 = (uint32_t *) ra;
+    for (i = 0; i < size/4; i++) r32[i] = MOA_Random_W(w, 1);
+    r32 = (uint32_t *) rb;
+    for (i = 0; i < size/4; i++) r32[i] = MOA_Random_W(w, 0);
+  }
+}
+
+/* This sucks, but in order to time, you really need to avoid putting ifs in 
+   the inner loops.  So, I'm doing a separate timing test for each w: 
+   (4 & 8), 16, 32, 64, 128 and everything else.  Fortunately, the "everything else"
+   tests can be equivalent to w=32.
+
+   I'm also putting the results back into ra, because otherwise, the optimizer might
+   figure out that we're not really doing anything in the inner loops and it 
+   will chuck that. */
+
+int gf_general_do_single_timing_test(gf_t *gf, void *ra, void *rb, int size, char test)
+{
+  gf_internal_t *h;
+  void *top;
+  uint8_t *r8a, *r8b, *top8;
+  uint16_t *r16a, *r16b, *top16;
+  uint32_t *r32a, *r32b, *top32;
+  uint64_t *r64a, *r64b, *top64, *r64c;
+  int w, rv;
+
+  h = (gf_internal_t *) gf->scratch;
+  w = h->w;
+  top = (char*)ra + size;
+
+  if (w == 8 || w == 4) {
+    r8a = (uint8_t *) ra; 
+    r8b = (uint8_t *) rb; 
+    top8 = (uint8_t *) top;
+    if (test == 'M') {
+      while (r8a < top8) {
+        *r8a = gf->multiply.w32(gf, *r8a, *r8b);
+        r8a++;
+        r8b++;
+      }
+    } else if (test == 'D') {
+      while (r8a < top8) {
+        *r8a = gf->divide.w32(gf, *r8a, *r8b);
+        r8a++;
+        r8b++;
+      }
+    } else if (test == 'I') {
+      while (r8a < top8) {
+        *r8a = gf->inverse.w32(gf, *r8a);
+        r8a++;
+      }
+    }
+    return (top8 - (uint8_t *) ra);
+  }
+
+  if (w == 16) {
+    r16a = (uint16_t *) ra; 
+    r16b = (uint16_t *) rb; 
+    top16 = (uint16_t *) top;
+    if (test == 'M') {
+      while (r16a < top16) {
+        *r16a = gf->multiply.w32(gf, *r16a, *r16b);
+        r16a++;
+        r16b++;
+      }
+    } else if (test == 'D') {
+      while (r16a < top16) {
+        *r16a = gf->divide.w32(gf, *r16a, *r16b);
+        r16a++;
+        r16b++;
+      }
+    } else if (test == 'I') {
+      while (r16a < top16) {
+        *r16a = gf->inverse.w32(gf, *r16a);
+        r16a++;
+      }
+    }
+    return (top16 - (uint16_t *) ra);
+  }
+  if (w <= 32) {
+    r32a = (uint32_t *) ra; 
+    r32b = (uint32_t *) rb; 
+    top32 = (uint32_t *) ra + (size/4); /* This is for the "everything elses" */
+    
+    if (test == 'M') {
+      while (r32a < top32) {
+        *r32a = gf->multiply.w32(gf, *r32a, *r32b);
+        r32a++;
+        r32b++;
+      }
+    } else if (test == 'D') {
+      while (r32a < top32) {
+        *r32a = gf->divide.w32(gf, *r32a, *r32b);
+        r32a++;
+        r32b++;
+      }
+    } else if (test == 'I') {
+      while (r32a < top32) {
+        *r32a = gf->inverse.w32(gf, *r32a);
+        r32a++;
+      }
+    }
+    return (top32 - (uint32_t *) ra);
+  }
+  if (w == 64) {
+    r64a = (uint64_t *) ra; 
+    r64b = (uint64_t *) rb; 
+    top64 = (uint64_t *) top;
+    if (test == 'M') {
+      while (r64a < top64) {
+        *r64a = gf->multiply.w64(gf, *r64a, *r64b);
+        r64a++;
+        r64b++;
+      }
+    } else if (test == 'D') {
+      while (r64a < top64) {
+        *r64a = gf->divide.w64(gf, *r64a, *r64b);
+        r64a++;
+        r64b++;
+      }
+    } else if (test == 'I') {
+      while (r64a < top64) {
+        *r64a = gf->inverse.w64(gf, *r64a);
+        r64a++;
+      }
+    }
+    return (top64 - (uint64_t *) ra);
+  }
+  if (w == 128) {
+    r64a = (uint64_t *) ra; 
+    r64c = r64a;
+    r64a += 2;
+    r64b = (uint64_t *) rb; 
+    top64 = (uint64_t *) top;
+    rv = (top64 - r64a)/2;
+    if (test == 'M') {
+      while (r64a < top64) {
+        gf->multiply.w128(gf, r64a, r64b, r64c);
+        r64a += 2;
+        r64b += 2;
+      }
+    } else if (test == 'D') {
+      while (r64a < top64) {
+        gf->divide.w128(gf, r64a, r64b, r64c);
+        r64a += 2;
+        r64b += 2;
+      }
+    } else if (test == 'I') {
+      while (r64a < top64) {
+        gf->inverse.w128(gf, r64a, r64c);
+        r64a += 2;
+      }
+    }
+    return rv;
+  }
+  return 0;
+}
diff --git a/src/erasure-code/jerasure/gf-complete/src/gf_method.c b/src/erasure-code/jerasure/gf-complete/src/gf_method.c
new file mode 100644
index 0000000..a7bcacf
--- /dev/null
+++ b/src/erasure-code/jerasure/gf-complete/src/gf_method.c
@@ -0,0 +1,185 @@
+/*
+ * GF-Complete: A Comprehensive Open Source Library for Galois Field Arithmetic
+ * James S. Plank, Ethan L. Miller, Kevin M. Greenan,
+ * Benjamin A. Arnold, John A. Burnum, Adam W. Disney, Allen C. McBride.
+ *
+ * gf_method.c
+ *
+ * Parses argv to figure out the mult_type and arguments.  Returns the gf.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "gf_complete.h"
+#include "gf_int.h"
+#include "gf_method.h"
+
+int create_gf_from_argv(gf_t *gf, int w, int argc, char **argv, int starting)
+{
+  int mult_type, divide_type, region_type;
+  int arg1, arg2;
+  uint64_t prim_poly;
+  gf_t *base;
+
+  mult_type = GF_MULT_DEFAULT;
+  region_type = GF_REGION_DEFAULT;
+  divide_type = GF_DIVIDE_DEFAULT;
+  prim_poly = 0;
+  base = NULL;
+  arg1 = 0;
+  arg2 = 0;
+  while (1) {
+    if (argc > starting) {
+      if (strcmp(argv[starting], "-m") == 0) {
+        starting++;
+        if (mult_type != GF_MULT_DEFAULT) {
+          if (base != NULL) gf_free(base, 1);
+          _gf_errno = GF_E_TWOMULT;
+          return 0;
+        }
+        if (strcmp(argv[starting], "SHIFT") == 0) {
+          mult_type = GF_MULT_SHIFT;
+          starting++;
+        } else if (strcmp(argv[starting], "CARRY_FREE") == 0) {
+          mult_type = GF_MULT_CARRY_FREE;
+          starting++;
+        } else if (strcmp(argv[starting], "GROUP") == 0) {
+          mult_type = GF_MULT_GROUP;
+          if (argc < starting + 3) {
+            _gf_errno = GF_E_GROUPAR;
+            return 0;
+          }
+          if (sscanf(argv[starting+1], "%d", &arg1) == 0 ||
+              sscanf(argv[starting+2], "%d", &arg2) == 0) {
+            _gf_errno = GF_E_GROUPNU;
+            return 0;
+          }
+          starting += 3;
+        } else if (strcmp(argv[starting], "BYTWO_p") == 0) {
+          mult_type = GF_MULT_BYTWO_p;
+          starting++;
+        } else if (strcmp(argv[starting], "BYTWO_b") == 0) {
+          mult_type = GF_MULT_BYTWO_b;
+          starting++;
+        } else if (strcmp(argv[starting], "TABLE") == 0) {
+          mult_type = GF_MULT_TABLE;
+          starting++;
+        } else if (strcmp(argv[starting], "LOG") == 0) {
+          mult_type = GF_MULT_LOG_TABLE;
+          starting++;
+        } else if (strcmp(argv[starting], "LOG_ZERO") == 0) {
+          mult_type = GF_MULT_LOG_ZERO;
+          starting++;
+        } else if (strcmp(argv[starting], "LOG_ZERO_EXT") == 0) {
+          mult_type = GF_MULT_LOG_ZERO_EXT;
+          starting++;
+        } else if (strcmp(argv[starting], "SPLIT") == 0) {
+          mult_type = GF_MULT_SPLIT_TABLE;
+          if (argc < starting + 3) {
+            _gf_errno = GF_E_SPLITAR;
+            return 0;
+          }
+          if (sscanf(argv[starting+1], "%d", &arg1) == 0 ||
+              sscanf(argv[starting+2], "%d", &arg2) == 0) {
+            _gf_errno = GF_E_SPLITNU;
+            return 0;
+          }
+          starting += 3;
+        } else if (strcmp(argv[starting], "COMPOSITE") == 0) {
+          mult_type = GF_MULT_COMPOSITE;
+          if (argc < starting + 2) { _gf_errno = GF_E_FEWARGS; return 0; }
+          if (sscanf(argv[starting+1], "%d", &arg1) == 0) {
+            _gf_errno = GF_E_COMP_A2;
+            return 0;
+          }
+          starting += 2;
+          base = (gf_t *) malloc(sizeof(gf_t));
+          starting = create_gf_from_argv(base, w/arg1, argc, argv, starting);
+          if (starting == 0) {
+            free(base);
+            return 0;
+          }
+        } else {
+          if (base != NULL) gf_free(base, 1);
+          _gf_errno = GF_E_UNKNOWN;
+          return 0;
+        }
+      } else if (strcmp(argv[starting], "-r") == 0) {
+        starting++;
+        if (strcmp(argv[starting], "DOUBLE") == 0) {
+          region_type |= GF_REGION_DOUBLE_TABLE;
+          starting++;
+        } else if (strcmp(argv[starting], "QUAD") == 0) {
+          region_type |= GF_REGION_QUAD_TABLE;
+          starting++;
+        } else if (strcmp(argv[starting], "LAZY") == 0) {
+          region_type |= GF_REGION_LAZY;
+          starting++;
+        } else if (strcmp(argv[starting], "SSE") == 0) {
+          region_type |= GF_REGION_SSE;
+          starting++;
+        } else if (strcmp(argv[starting], "NOSSE") == 0) {
+          region_type |= GF_REGION_NOSSE;
+          starting++;
+        } else if (strcmp(argv[starting], "CAUCHY") == 0) {
+          region_type |= GF_REGION_CAUCHY;
+          starting++;
+        } else if (strcmp(argv[starting], "ALTMAP") == 0) {
+          region_type |= GF_REGION_ALTMAP;
+          starting++;
+        } else {
+          if (base != NULL) gf_free(base, 1);
+          _gf_errno = GF_E_UNK_REG;
+          return 0;
+        }
+      } else if (strcmp(argv[starting], "-p") == 0) {
+        starting++;
+        if (sscanf(argv[starting], "%llx", (long long unsigned int *)(&prim_poly)) == 0) {
+          if (base != NULL) gf_free(base, 1);
+          _gf_errno = GF_E_POLYSPC;
+          return 0;
+        }
+        starting++;
+      } else if (strcmp(argv[starting], "-d") == 0) {
+        starting++;
+        if (divide_type != GF_DIVIDE_DEFAULT) {
+          if (base != NULL) gf_free(base, 1);
+          _gf_errno = GF_E_TWO_DIV;
+          return 0;
+        } else if (strcmp(argv[starting], "EUCLID") == 0) {
+          divide_type = GF_DIVIDE_EUCLID;
+          starting++;
+        } else if (strcmp(argv[starting], "MATRIX") == 0) {
+          divide_type = GF_DIVIDE_MATRIX;
+          starting++;
+        } else {
+          _gf_errno = GF_E_UNK_DIV;
+          return 0;
+        }
+      } else if (strcmp(argv[starting], "-") == 0) {
+         /*
+         printf("Scratch size: %d\n", gf_scratch_size(w, 
+                                      mult_type, region_type, divide_type, arg1, arg2));
+         */
+        if (gf_init_hard(gf, w, mult_type, region_type, divide_type, 
+                         prim_poly, arg1, arg2, base, NULL) == 0) {
+          if (base != NULL) gf_free(base, 1);
+          return 0;
+        } else
+          return starting + 1;
+      } else {
+        if (base != NULL) gf_free(base, 1);
+        _gf_errno = GF_E_UNKFLAG;
+        return 0;
+      }
+    } else {
+      if (base != NULL) gf_free(base, 1);
+      _gf_errno = GF_E_FEWARGS;
+      return 0;
+    }
+  }
+}
diff --git a/src/erasure-code/jerasure/gf-complete/src/gf_rand.c b/src/erasure-code/jerasure/gf-complete/src/gf_rand.c
new file mode 100644
index 0000000..a9aa7ad
--- /dev/null
+++ b/src/erasure-code/jerasure/gf-complete/src/gf_rand.c
@@ -0,0 +1,80 @@
+/*
+ * GF-Complete: A Comprehensive Open Source Library for Galois Field Arithmetic
+ * James S. Plank, Ethan L. Miller, Kevin M. Greenan,
+ * Benjamin A. Arnold, John A. Burnum, Adam W. Disney, Allen C. McBride.
+ *
+ * gf_rand.c -- Random number generator.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "gf_rand.h"
+
+/* Lifted the "Mother of All" random number generator from http://www.agner.org/random/ */
+
+static uint32_t MOA_X[5];
+
+uint32_t MOA_Random_32() {
+  uint64_t sum;
+  sum = (uint64_t)2111111111UL * (uint64_t)MOA_X[3] +
+     (uint64_t)1492 * (uint64_t)(MOA_X[2]) +
+     (uint64_t)1776 * (uint64_t)(MOA_X[1]) +
+     (uint64_t)5115 * (uint64_t)(MOA_X[0]) +
+     (uint64_t)MOA_X[4];
+  MOA_X[3] = MOA_X[2];  MOA_X[2] = MOA_X[1];  MOA_X[1] = MOA_X[0];
+  MOA_X[4] = (uint32_t)(sum >> 32);
+  MOA_X[0] = (uint32_t)sum;
+  return MOA_X[0];
+}
+
+uint64_t MOA_Random_64() {
+  uint64_t sum;
+
+  sum = MOA_Random_32();
+  sum <<= 32;
+  sum |= MOA_Random_32();
+  return sum;
+}
+
+void MOA_Random_128(uint64_t *x) {
+  x[0] = MOA_Random_64();
+  x[1] = MOA_Random_64();
+  return;
+}
+
+uint32_t MOA_Random_W(int w, int zero_ok)
+{
+  uint32_t b;
+
+  do {
+    b = MOA_Random_32();
+    if (w == 31) b &= 0x7fffffff;
+    if (w < 31)  b %= (1 << w);
+  } while (!zero_ok && b == 0);
+  return b;
+}
+
+void MOA_Seed(uint32_t seed) {
+  int i;
+  uint32_t s = seed;
+  for (i = 0; i < 5; i++) {
+    s = s * 29943829 - 1;
+    MOA_X[i] = s;
+  }
+  for (i=0; i<19; i++) MOA_Random_32();
+}
+
+
+void MOA_Fill_Random_Region (void *reg, int size)
+{
+  uint32_t *r32;
+  uint8_t *r8;
+  int i;
+
+  r32 = (uint32_t *) reg;
+  r8 = (uint8_t *) reg;
+  for (i = 0; i < size/4; i++) r32[i] = MOA_Random_32();
+  for (i *= 4; i < size; i++) r8[i] = MOA_Random_W(8, 1);
+}
+
diff --git a/src/erasure-code/jerasure/gf-complete/src/gf_w128.c b/src/erasure-code/jerasure/gf-complete/src/gf_w128.c
new file mode 100644
index 0000000..e54cff2
--- /dev/null
+++ b/src/erasure-code/jerasure/gf-complete/src/gf_w128.c
@@ -0,0 +1,1758 @@
+/*
+ * GF-Complete: A Comprehensive Open Source Library for Galois Field Arithmetic
+ * James S. Plank, Ethan L. Miller, Kevin M. Greenan,
+ * Benjamin A. Arnold, John A. Burnum, Adam W. Disney, Allen C. McBride.
+ *
+ * gf_w128.c
+ *
+ * Routines for 128-bit Galois fields
+ */
+
+#include "gf_int.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+#define GF_FIELD_WIDTH (128)
+
+#define two_x(a) {\
+  a[0] <<= 1; \
+  if (a[1] & 1ULL << 63) a[0] ^= 1; \
+  a[1] <<= 1; }
+  
+#define a_get_b(a, i, b, j) {\
+  a[i] = b[j]; \
+  a[i + 1] = b[j + 1];}
+
+#define set_zero(a, i) {\
+  a[i] = 0; \
+  a[i + 1] = 0;}
+
+struct gf_w128_split_4_128_data {
+  uint64_t last_value[2];
+  uint64_t tables[2][32][16];
+};
+
+struct gf_w128_split_8_128_data {
+  uint64_t last_value[2];
+  uint64_t tables[2][16][256];
+};
+
+typedef struct gf_group_tables_s {
+  gf_val_128_t m_table;
+  gf_val_128_t r_table;
+} gf_group_tables_t;
+
+#define MM_PRINT8(s, r) { uint8_t blah[16], ii; printf("%-12s", s); _mm_storeu_si128((__m128i *)blah, r); for (ii = 0; ii < 16; ii += 1) printf("%s%02x", (ii%4==0) ? "   " : " ", blah[15-ii]); printf("\n"); }
+
+static
+void
+gf_w128_multiply_region_from_single(gf_t *gf, void *src, void *dest, gf_val_128_t val, int bytes,
+int xor)
+{
+    int i;
+    gf_val_128_t s128;
+    gf_val_128_t d128;
+    uint64_t c128[2];
+    gf_region_data rd;
+
+    /* We only do this to check on alignment. */
+    gf_set_region_data(&rd, gf, src, dest, bytes, 0, xor, 8);
+
+    if (val[0] == 0) {
+      if (val[1] == 0) { gf_multby_zero(dest, bytes, xor); return; }
+      if (val[1] == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+    }
+
+    set_zero(c128, 0);
+
+    s128 = (gf_val_128_t) src;
+    d128 = (gf_val_128_t) dest;
+
+    if (xor) {
+      for (i = 0; i < bytes/sizeof(gf_val_64_t); i += 2) {
+        gf->multiply.w128(gf, &s128[i], val, c128);
+        d128[i] ^= c128[0];
+        d128[i+1] ^= c128[1];
+      }
+    } else {
+      for (i = 0; i < bytes/sizeof(gf_val_64_t); i += 2) {
+        gf->multiply.w128(gf, &s128[i], val, &d128[i]);
+      }
+    }
+}
+
+#if defined(INTEL_SSE4_PCLMUL)
+static
+void
+gf_w128_clm_multiply_region_from_single(gf_t *gf, void *src, void *dest, gf_val_128_t val, int bytes,
+int xor)
+{
+    int i;
+    gf_val_128_t s128;
+    gf_val_128_t d128;
+    gf_region_data rd;
+    __m128i     a,b;
+    __m128i     result0,result1;
+    __m128i     prim_poly;
+    __m128i     c,d,e,f;
+    gf_internal_t * h = gf->scratch;
+    prim_poly = _mm_set_epi32(0, 0, 0, (uint32_t)h->prim_poly);
+    /* We only do this to check on alignment. */
+    gf_set_region_data(&rd, gf, src, dest, bytes, 0, xor, 8);
+
+    if (val[0] == 0) {
+      if (val[1] == 0) { gf_multby_zero(dest, bytes, xor); return; }
+      if (val[1] == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+    }
+
+    s128 = (gf_val_128_t) src;
+    d128 = (gf_val_128_t) dest;
+
+    if (xor) {
+      for (i = 0; i < bytes/sizeof(gf_val_64_t); i += 2) {
+        a = _mm_insert_epi64 (_mm_setzero_si128(), s128[i+1], 0);
+        b = _mm_insert_epi64 (a, val[1], 0);
+        a = _mm_insert_epi64 (a, s128[i], 1);
+        b = _mm_insert_epi64 (b, val[0], 1);
+    
+        c = _mm_clmulepi64_si128 (a, b, 0x00); /*low-low*/
+        f = _mm_clmulepi64_si128 (a, b, 0x01); /*high-low*/
+        e = _mm_clmulepi64_si128 (a, b, 0x10); /*low-high*/
+        d = _mm_clmulepi64_si128 (a, b, 0x11); /*high-high*/
+
+        /* now reusing a and b as temporary variables*/
+        result0 = _mm_setzero_si128();
+        result1 = result0;
+
+        result0 = _mm_xor_si128 (result0, _mm_insert_epi64 (d, 0, 0));
+        a = _mm_xor_si128 (_mm_srli_si128 (e, 8), _mm_insert_epi64 (d, 0, 1));
+        result0 = _mm_xor_si128 (result0, _mm_xor_si128 (_mm_srli_si128 (f, 8), a));
+
+        a = _mm_xor_si128 (_mm_slli_si128 (e, 8), _mm_insert_epi64 (c, 0, 0));
+        result1 = _mm_xor_si128 (result1, _mm_xor_si128 (_mm_slli_si128 (f, 8), a));
+        result1 = _mm_xor_si128 (result1, _mm_insert_epi64 (c, 0, 1));
+        /* now we have constructed our 'result' with result0 being the carry bits, and we have to reduce. */
+
+        a = _mm_srli_si128 (result0, 8);
+        b = _mm_clmulepi64_si128 (a, prim_poly, 0x00);
+        result0 = _mm_xor_si128 (result0, _mm_srli_si128 (b, 8));
+        result1 = _mm_xor_si128 (result1, _mm_slli_si128 (b, 8));
+
+        a = _mm_insert_epi64 (result0, 0, 1);
+        b = _mm_clmulepi64_si128 (a, prim_poly, 0x00);
+        result1 = _mm_xor_si128 (result1, b); 
+        d128[i] ^= (uint64_t)_mm_extract_epi64(result1,1);
+        d128[i+1] ^= (uint64_t)_mm_extract_epi64(result1,0);
+      }
+    } else {
+      for (i = 0; i < bytes/sizeof(gf_val_64_t); i += 2) {
+        a = _mm_insert_epi64 (_mm_setzero_si128(), s128[i+1], 0);
+        b = _mm_insert_epi64 (a, val[1], 0);
+        a = _mm_insert_epi64 (a, s128[i], 1);
+        b = _mm_insert_epi64 (b, val[0], 1);
+
+        c = _mm_clmulepi64_si128 (a, b, 0x00); /*low-low*/
+        f = _mm_clmulepi64_si128 (a, b, 0x01); /*high-low*/
+        e = _mm_clmulepi64_si128 (a, b, 0x10); /*low-high*/ 
+        d = _mm_clmulepi64_si128 (a, b, 0x11); /*high-high*/ 
+
+        /* now reusing a and b as temporary variables*/
+        result0 = _mm_setzero_si128();
+        result1 = result0;
+
+        result0 = _mm_xor_si128 (result0, _mm_insert_epi64 (d, 0, 0));
+        a = _mm_xor_si128 (_mm_srli_si128 (e, 8), _mm_insert_epi64 (d, 0, 1));
+        result0 = _mm_xor_si128 (result0, _mm_xor_si128 (_mm_srli_si128 (f, 8), a));
+
+        a = _mm_xor_si128 (_mm_slli_si128 (e, 8), _mm_insert_epi64 (c, 0, 0));
+        result1 = _mm_xor_si128 (result1, _mm_xor_si128 (_mm_slli_si128 (f, 8), a));
+        result1 = _mm_xor_si128 (result1, _mm_insert_epi64 (c, 0, 1));
+        /* now we have constructed our 'result' with result0 being the carry bits, and we have to reduce.*/
+
+        a = _mm_srli_si128 (result0, 8);
+        b = _mm_clmulepi64_si128 (a, prim_poly, 0x00);
+        result0 = _mm_xor_si128 (result0, _mm_srli_si128 (b, 8));
+        result1 = _mm_xor_si128 (result1, _mm_slli_si128 (b, 8));
+
+        a = _mm_insert_epi64 (result0, 0, 1);
+        b = _mm_clmulepi64_si128 (a, prim_poly, 0x00);
+        result1 = _mm_xor_si128 (result1, b);
+        d128[i] = (uint64_t)_mm_extract_epi64(result1,1);
+        d128[i+1] = (uint64_t)_mm_extract_epi64(result1,0);
+      }
+    }
+}
+#endif
+
+/*
+ * Some w128 notes:
+ * --Big Endian
+ * --return values allocated beforehand
+ */
+
+#define GF_W128_IS_ZERO(val) (val[0] == 0 && val[1] == 0)
+
+void
+gf_w128_shift_multiply(gf_t *gf, gf_val_128_t a128, gf_val_128_t b128, gf_val_128_t c128)
+{
+  /* ordered highest bit to lowest l[0] l[1] r[0] r[1] */
+  uint64_t pl[2], pr[2], ppl[2], ppr[2], i, a[2], bl[2], br[2], one, lbit;
+  gf_internal_t *h;
+
+  h = (gf_internal_t *) gf->scratch;
+
+  if (GF_W128_IS_ZERO(a128) || GF_W128_IS_ZERO(b128)) {
+    set_zero(c128, 0);
+    return;
+  }
+
+  a_get_b(a, 0, a128, 0);
+  a_get_b(br, 0, b128, 0);
+  set_zero(bl, 0);
+
+  one = 1;
+  lbit = (one << 63);
+
+  set_zero(pl, 0);
+  set_zero(pr, 0);
+
+  /* Allen: a*b for right half of a */
+  for (i = 0; i < GF_FIELD_WIDTH/2; i++) {
+    if (a[1] & (one << i)) {
+      pl[1] ^= bl[1];
+      pr[0] ^= br[0];
+      pr[1] ^= br[1];
+    }
+    bl[1] <<= 1;
+    if (br[0] & lbit) bl[1] ^= 1;
+    br[0] <<= 1;
+    if (br[1] & lbit) br[0] ^= 1;
+    br[1] <<= 1;
+  }
+
+  /* Allen: a*b for left half of a */
+  for (i = 0; i < GF_FIELD_WIDTH/2; i++) {
+    if (a[0] & (one << i)) {
+      pl[0] ^= bl[0];
+      pl[1] ^= bl[1];
+      pr[0] ^= br[0];
+    }
+    bl[0] <<= 1;
+    if (bl[1] & lbit) bl[0] ^= 1;
+    bl[1] <<= 1;
+    if (br[0] & lbit) bl[1] ^= 1;
+    br[0] <<= 1;
+  }
+
+  /* Allen: do first half of reduction (based on left quarter of initial product) */
+  one = lbit >> 1;
+  ppl[0] = one; /* Allen: introduce leading one of primitive polynomial */
+  ppl[1] = h->prim_poly >> 2;
+  ppr[0] = h->prim_poly << (GF_FIELD_WIDTH/2-2);
+  ppr[1] = 0;
+  while (one != 0) {
+    if (pl[0] & one) {
+      pl[0] ^= ppl[0];
+      pl[1] ^= ppl[1];
+      pr[0] ^= ppr[0];
+      pr[1] ^= ppr[1];
+    }
+    one >>= 1;
+    ppr[1] >>= 1;
+    if (ppr[0] & 1) ppr[1] ^= lbit;
+    ppr[0] >>= 1;
+    if (ppl[1] & 1) ppr[0] ^= lbit;
+    ppl[1] >>= 1;
+    if (ppl[0] & 1) ppl[1] ^= lbit;
+    ppl[0] >>= 1;
+  }
+
+  /* Allen: final half of reduction */
+  one = lbit;
+  while (one != 0) {
+    if (pl[1] & one) {
+      pl[1] ^= ppl[1];
+      pr[0] ^= ppr[0];
+      pr[1] ^= ppr[1];
+    }
+    one >>= 1;
+    ppr[1] >>= 1;
+    if (ppr[0] & 1) ppr[1] ^= lbit;
+    ppr[0] >>= 1;
+    if (ppl[1] & 1) ppr[0] ^= lbit;
+    ppl[1] >>= 1;
+  }
+
+  /* Allen: if we really want to optimize this we can just be using c128 instead of pr all along */
+  c128[0] = pr[0];
+  c128[1] = pr[1];
+
+  return;
+}
+
+void
+gf_w128_clm_multiply(gf_t *gf, gf_val_128_t a128, gf_val_128_t b128, gf_val_128_t c128)
+{
+#if defined(INTEL_SSE4_PCLMUL)
+
+    __m128i     a,b;
+    __m128i     result0,result1;
+    __m128i     prim_poly;
+    __m128i     c,d,e,f;
+    gf_internal_t * h = gf->scratch;
+    
+    a = _mm_insert_epi64 (_mm_setzero_si128(), a128[1], 0);
+    b = _mm_insert_epi64 (a, b128[1], 0);
+    a = _mm_insert_epi64 (a, a128[0], 1);
+    b = _mm_insert_epi64 (b, b128[0], 1);
+
+    prim_poly = _mm_set_epi32(0, 0, 0, (uint32_t)h->prim_poly);
+
+    /* we need to test algorithm 2 later*/
+    c = _mm_clmulepi64_si128 (a, b, 0x00); /*low-low*/
+    f = _mm_clmulepi64_si128 (a, b, 0x01); /*high-low*/
+    e = _mm_clmulepi64_si128 (a, b, 0x10); /*low-high*/
+    d = _mm_clmulepi64_si128 (a, b, 0x11); /*high-high*/
+    
+    /* now reusing a and b as temporary variables*/
+    result0 = _mm_setzero_si128();
+    result1 = result0;
+
+    result0 = _mm_xor_si128 (result0, _mm_insert_epi64 (d, 0, 0));
+    a = _mm_xor_si128 (_mm_srli_si128 (e, 8), _mm_insert_epi64 (d, 0, 1));
+    result0 = _mm_xor_si128 (result0, _mm_xor_si128 (_mm_srli_si128 (f, 8), a));
+
+    a = _mm_xor_si128 (_mm_slli_si128 (e, 8), _mm_insert_epi64 (c, 0, 0));
+    result1 = _mm_xor_si128 (result1, _mm_xor_si128 (_mm_slli_si128 (f, 8), a));
+    result1 = _mm_xor_si128 (result1, _mm_insert_epi64 (c, 0, 1));
+    /* now we have constructed our 'result' with result0 being the carry bits, and we have to reduce.*/
+    
+    a = _mm_srli_si128 (result0, 8);
+    b = _mm_clmulepi64_si128 (a, prim_poly, 0x00);
+    result0 = _mm_xor_si128 (result0, _mm_srli_si128 (b, 8));
+    result1 = _mm_xor_si128 (result1, _mm_slli_si128 (b, 8));
+    
+    a = _mm_insert_epi64 (result0, 0, 1);
+    b = _mm_clmulepi64_si128 (a, prim_poly, 0x00);
+    result1 = _mm_xor_si128 (result1, b);
+
+    c128[0] = (uint64_t)_mm_extract_epi64(result1,1);
+    c128[1] = (uint64_t)_mm_extract_epi64(result1,0);
+#endif
+return;
+}
+
+void
+gf_w128_bytwo_p_multiply(gf_t *gf, gf_val_128_t a128, gf_val_128_t b128, gf_val_128_t c128)
+{
+  uint64_t amask[2], pmask, pp, prod[2]; /*John: pmask is always the highest bit set, and the rest zeros. amask changes, it's a countdown.*/
+  uint64_t topbit; /* this is used as a boolean value */
+  gf_internal_t *h;
+
+  h = (gf_internal_t *) gf->scratch;
+  pp = h->prim_poly;
+  prod[0] = 0;
+  prod[1] = 0;
+  pmask = 0x8000000000000000ULL;
+  amask[0] = 0x8000000000000000ULL;
+  amask[1] = 0;
+
+  while (amask[1] != 0 || amask[0] != 0) {
+    topbit = (prod[0] & pmask);
+    prod[0] <<= 1;
+    if (prod[1] & pmask) prod[0] ^= 1;
+    prod[1] <<= 1;
+    if (topbit) prod[1] ^= pp;
+    if ((a128[0] & amask[0]) || (a128[1] & amask[1])) {
+      prod[0] ^= b128[0];
+      prod[1] ^= b128[1];
+    }
+    amask[1] >>= 1;
+    if (amask[0] & 1) amask[1] ^= pmask;
+    amask[0] >>= 1;
+  }
+  c128[0] = prod [0];
+  c128[1] = prod [1];
+  return;
+}
+
+void
+gf_w128_sse_bytwo_p_multiply(gf_t *gf, gf_val_128_t a128, gf_val_128_t b128, gf_val_128_t c128)
+{
+#if defined(INTEL_SSE4)
+  int i;
+  __m128i a, b, pp, prod, amask, u_middle_one; 
+  /*John: pmask is always the highest bit set, and the rest zeros. amask changes, it's a countdown.*/
+  uint32_t topbit, middlebit, pmask; /* this is used as a boolean value */
+  gf_internal_t *h;
+
+
+  h = (gf_internal_t *) gf->scratch;
+  pp = _mm_set_epi32(0, 0, 0, (uint32_t)h->prim_poly);
+  prod = _mm_setzero_si128();
+  a = _mm_insert_epi64(prod, a128[1], 0x0);
+  a = _mm_insert_epi64(a, a128[0], 0x1);
+  b = _mm_insert_epi64(prod, b128[1], 0x0);
+  b = _mm_insert_epi64(b, b128[0], 0x1);
+  pmask = 0x80000000;
+  amask = _mm_insert_epi32(prod, 0x80000000, 0x3);
+  u_middle_one = _mm_insert_epi32(prod, 1, 0x2);
+  
+  for (i = 0; i < 64; i++) {
+    topbit = (_mm_extract_epi32(prod, 0x3) & pmask);
+    middlebit = (_mm_extract_epi32(prod, 0x1) & pmask);
+    prod = _mm_slli_epi64(prod, 1); /* this instruction loses the middle bit */
+    if (middlebit) {
+      prod = _mm_xor_si128(prod, u_middle_one);
+    }
+    if (topbit) {
+      prod = _mm_xor_si128(prod, pp);
+    }
+    if (((uint64_t)_mm_extract_epi64(_mm_and_si128(a, amask), 1))) {
+      prod = _mm_xor_si128(prod, b);
+    }
+    amask = _mm_srli_epi64(amask, 1); /*so does this one, but we can just replace after loop*/
+  }
+  amask = _mm_insert_epi32(amask, 1 << 31, 0x1);
+  for (i = 64; i < 128; i++) {
+    topbit = (_mm_extract_epi32(prod, 0x3) & pmask);
+    middlebit = (_mm_extract_epi32(prod, 0x1) & pmask);
+    prod = _mm_slli_epi64(prod, 1);
+    if (middlebit) prod = _mm_xor_si128(prod, u_middle_one);
+    if (topbit) prod = _mm_xor_si128(prod, pp);
+    if (((uint64_t)_mm_extract_epi64(_mm_and_si128(a, amask), 0))) {
+      prod = _mm_xor_si128(prod, b);
+    }
+    amask = _mm_srli_epi64(amask, 1);
+  }
+  c128[0] = (uint64_t)_mm_extract_epi64(prod, 1);
+  c128[1] = (uint64_t)_mm_extract_epi64(prod, 0);
+#endif
+  return;
+}
+
+
+/* Ben: This slow function implements sse instrutions for bytwo_b because why not */
+void
+gf_w128_sse_bytwo_b_multiply(gf_t *gf, gf_val_128_t a128, gf_val_128_t b128, gf_val_128_t c128)
+{
+#if defined(INTEL_SSE4)
+  __m128i a, b, lmask, hmask, pp, c, middle_one;
+  gf_internal_t *h;
+  uint64_t topbit, middlebit;
+
+  h = (gf_internal_t *) gf->scratch;
+  
+  c = _mm_setzero_si128();
+  lmask = _mm_insert_epi64(c, 1ULL << 63, 0);
+  hmask = _mm_insert_epi64(c, 1ULL << 63, 1);
+  b = _mm_insert_epi64(c, a128[0], 1);
+  b = _mm_insert_epi64(b, a128[1], 0);
+  a = _mm_insert_epi64(c, b128[0], 1);
+  a = _mm_insert_epi64(a, b128[1], 0);
+  pp = _mm_insert_epi64(c, h->prim_poly, 0);
+  middle_one = _mm_insert_epi64(c, 1, 0x1);
+
+  while (1) {
+    if (_mm_extract_epi32(a, 0x0) & 1) {
+      c = _mm_xor_si128(c, b);
+    }
+    middlebit = (_mm_extract_epi32(a, 0x2) & 1);
+    a = _mm_srli_epi64(a, 1);
+    if (middlebit) a = _mm_xor_si128(a, lmask);
+    if ((_mm_extract_epi64(a, 0x1) == 0ULL) && (_mm_extract_epi64(a, 0x0) == 0ULL)){
+      c128[0] = _mm_extract_epi64(c, 0x1);
+      c128[1] = _mm_extract_epi64(c, 0x0);
+      return;
+    }
+    topbit = (_mm_extract_epi64(_mm_and_si128(b, hmask), 1));
+    middlebit = (_mm_extract_epi64(_mm_and_si128(b, lmask), 0));
+    b = _mm_slli_epi64(b, 1);
+    if (middlebit) b = _mm_xor_si128(b, middle_one);
+    if (topbit) b = _mm_xor_si128(b, pp);
+  }
+#endif
+}
+
+void
+gf_w128_bytwo_b_multiply(gf_t *gf, gf_val_128_t a128, gf_val_128_t b128, gf_val_128_t c128)
+{
+  uint64_t bmask, pp;
+  gf_internal_t *h;
+  uint64_t a[2], b[2], c[2];
+
+  h = (gf_internal_t *) gf->scratch;
+
+  bmask = (1ULL << 63);
+  set_zero(c, 0);
+  b[0] = a128[0];
+  b[1] = a128[1];
+  a[0] = b128[0];
+  a[1] = b128[1];
+  
+  while (1) {
+    if (a[1] & 1) {
+      c[0] ^= b[0];
+      c[1] ^= b[1];
+    }
+    a[1] >>= 1;
+    if (a[0] & 1) a[1] ^= bmask;
+    a[0] >>= 1;
+    if (a[1] == 0 && a[0] == 0) {
+      c128[0] = c[0];
+      c128[1] = c[1];
+      return;
+    }
+    pp = (b[0] & bmask);
+    b[0] <<= 1;
+    if (b[1] & bmask) b[0] ^= 1;
+    b[1] <<= 1;
+    if (pp) b[1] ^= h->prim_poly;
+  }
+}
+
+static
+void
+gf_w128_split_4_128_multiply_region(gf_t *gf, void *src, void *dest, gf_val_128_t val, int bytes, int xor)
+{
+  int i, j, k;
+  uint64_t pp;
+  gf_internal_t *h;
+  uint64_t *s64, *d64, *top;
+  gf_region_data rd;
+  uint64_t v[2], s;
+  struct gf_w128_split_4_128_data *ld;
+
+  /* We only do this to check on alignment. */
+  gf_set_region_data(&rd, gf, src, dest, bytes, 0, xor, 8);
+
+  if (val[0] == 0) {
+    if (val[1] == 0) { gf_multby_zero(dest, bytes, xor); return; }
+    if (val[1] == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+  }
+    
+  h = (gf_internal_t *) gf->scratch;
+  ld = (struct gf_w128_split_4_128_data *) h->private;
+
+  s64 = (uint64_t *) rd.s_start;
+  d64 = (uint64_t *) rd.d_start;
+  top = (uint64_t *) rd.d_top;
+
+  if (val[0] != ld->last_value[0] || val[1] != ld->last_value[1]) {
+    v[0] = val[0];
+    v[1] = val[1];
+    for (i = 0; i < 32; i++) {
+      ld->tables[0][i][0] = 0;
+      ld->tables[1][i][0] = 0;
+      for (j = 1; j < 16; j <<= 1) {
+        for (k = 0; k < j; k++) {
+          ld->tables[0][i][k^j] = (v[0] ^ ld->tables[0][i][k]);
+          ld->tables[1][i][k^j] = (v[1] ^ ld->tables[1][i][k]);
+        }
+        pp = (v[0] & (1ULL << 63));
+        v[0] <<= 1;
+        if (v[1] & (1ULL << 63)) v[0] ^= 1;
+        v[1] <<= 1;
+        if (pp) v[1] ^= h->prim_poly;
+      }
+    }
+  }
+  ld->last_value[0] = val[0];
+  ld->last_value[1] = val[1];
+
+/*
+  for (i = 0; i < 32; i++) {
+    for (j = 0; j < 16; j++) {
+      printf("%2d %2d %016llx %016llx\n", i, j, ld->tables[0][i][j], ld->tables[1][i][j]);
+    }
+    printf("\n");
+  }
+ */
+  i = 0;
+  while (d64 < top) {
+    v[0] = (xor) ? d64[0] : 0;
+    v[1] = (xor) ? d64[1] : 0;
+    s = s64[1];
+    i = 0;
+    while (s != 0) {
+      v[0] ^= ld->tables[0][i][s&0xf];
+      v[1] ^= ld->tables[1][i][s&0xf];
+      s >>= 4;
+      i++;
+    }
+    s = s64[0];
+    i = 16;
+    while (s != 0) {
+      v[0] ^= ld->tables[0][i][s&0xf];
+      v[1] ^= ld->tables[1][i][s&0xf];
+      s >>= 4;
+      i++;
+    }
+    d64[0] = v[0];
+    d64[1] = v[1];
+    s64 += 2;
+    d64 += 2;
+  }
+}
+
+#if defined(INTEL_SSSE3) && defined(INTEL_SSE4)
+static
+void
+gf_w128_split_4_128_sse_multiply_region(gf_t *gf, void *src, void *dest, gf_val_128_t val, int bytes, int xor)
+{
+  gf_internal_t *h;
+  int i, j, k;
+  uint64_t pp, v[2], s, *s64, *d64, *top;
+  __m128i p, tables[32][16];
+  struct gf_w128_split_4_128_data *ld;
+  gf_region_data rd;
+
+  if (val[0] == 0) {
+    if (val[1] == 0) { gf_multby_zero(dest, bytes, xor); return; }
+    if (val[1] == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+  }
+
+  h = (gf_internal_t *) gf->scratch;
+  pp = h->prim_poly;
+  
+  /* We only do this to check on alignment. */
+  gf_set_region_data(&rd, gf, src, dest, bytes, 0, xor, 16);
+
+  /* Doing this instead of gf_do_initial_region_alignment() because that doesn't hold 128-bit vals */
+
+  gf_w128_multiply_region_from_single(gf, src, dest, val, ((char*)rd.s_start-(char*)src), xor);
+
+  s64 = (uint64_t *) rd.s_start;
+  d64 = (uint64_t *) rd.d_start;
+  top = (uint64_t *) rd.d_top;
+ 
+  ld = (struct gf_w128_split_4_128_data *) h->private;
+
+  if (val[0] != ld->last_value[0] || val[1] != ld->last_value[1]) {
+    v[0] = val[0];
+    v[1] = val[1];
+    for (i = 0; i < 32; i++) {
+      ld->tables[0][i][0] = 0;
+      ld->tables[1][i][0] = 0;
+      for (j = 1; j < 16; j <<= 1) {
+        for (k = 0; k < j; k++) {
+          ld->tables[0][i][k^j] = (v[0] ^ ld->tables[0][i][k]);
+          ld->tables[1][i][k^j] = (v[1] ^ ld->tables[1][i][k]);
+        }
+        pp = (v[0] & (1ULL << 63));
+        v[0] <<= 1;
+        if (v[1] & (1ULL << 63)) v[0] ^= 1;
+        v[1] <<= 1;
+        if (pp) v[1] ^= h->prim_poly;
+      }
+    }
+  }
+
+  ld->last_value[0] = val[0];
+  ld->last_value[1] = val[1];
+
+  for (i = 0; i < 32; i++) {
+    for (j = 0; j < 16; j++) {
+      v[0] = ld->tables[0][i][j];
+      v[1] = ld->tables[1][i][j];
+      tables[i][j] = _mm_loadu_si128((__m128i *) v);
+
+/*
+      printf("%2d %2d: ", i, j);
+      MM_PRINT8("", tables[i][j]); */
+    }
+  }
+
+  while (d64 != top) {
+
+    if (xor) {
+      p = _mm_load_si128 ((__m128i *) d64);
+    } else {
+      p = _mm_setzero_si128();
+    }
+    s = *s64;
+    s64++;
+    for (i = 0; i < 16; i++) {
+      j = (s&0xf);
+      s >>= 4;
+      p = _mm_xor_si128(p, tables[16+i][j]);
+    }
+    s = *s64;
+    s64++;
+    for (i = 0; i < 16; i++) {
+      j = (s&0xf);
+      s >>= 4;
+      p = _mm_xor_si128(p, tables[i][j]);
+    }
+    _mm_store_si128((__m128i *) d64, p);
+    d64 += 2;
+  }
+
+  /* Doing this instead of gf_do_final_region_alignment() because that doesn't hold 128-bit vals */
+
+  gf_w128_multiply_region_from_single(gf, rd.s_top, rd.d_top, val, ((char*)src+bytes)-(char*)rd.s_top, xor);
+}
+#endif
+
+#if defined(INTEL_SSSE3) && defined(INTEL_SSE4)
+static
+void
+gf_w128_split_4_128_sse_altmap_multiply_region(gf_t *gf, void *src, void *dest, gf_val_128_t val, int bytes, int xor)
+{
+  gf_internal_t *h;
+  int i, j, k;
+  uint64_t pp, v[2], *s64, *d64, *top;
+  __m128i si, tables[32][16], p[16], v0, mask1;
+  struct gf_w128_split_4_128_data *ld;
+  uint8_t btable[16];
+  gf_region_data rd;
+
+  if (val[0] == 0) {
+    if (val[1] == 0) { gf_multby_zero(dest, bytes, xor); return; }
+    if (val[1] == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+  }
+
+  h = (gf_internal_t *) gf->scratch;
+  pp = h->prim_poly;
+  
+  /* We only do this to check on alignment. */
+  gf_set_region_data(&rd, gf, src, dest, bytes, 0, xor, 256);
+
+  /* Doing this instead of gf_do_initial_region_alignment() because that doesn't hold 128-bit vals */
+
+  gf_w128_multiply_region_from_single(gf, src, dest, val, ((char*)rd.s_start-(char*)src), xor);
+
+  s64 = (uint64_t *) rd.s_start;
+  d64 = (uint64_t *) rd.d_start;
+  top = (uint64_t *) rd.d_top;
+ 
+  ld = (struct gf_w128_split_4_128_data *) h->private;
+
+  if (val[0] != ld->last_value[0] || val[1] != ld->last_value[1]) {
+    v[0] = val[0];
+    v[1] = val[1];
+    for (i = 0; i < 32; i++) {
+      ld->tables[0][i][0] = 0;
+      ld->tables[1][i][0] = 0;
+      for (j = 1; j < 16; j <<= 1) {
+        for (k = 0; k < j; k++) {
+          ld->tables[0][i][k^j] = (v[0] ^ ld->tables[0][i][k]);
+          ld->tables[1][i][k^j] = (v[1] ^ ld->tables[1][i][k]);
+        }
+        pp = (v[0] & (1ULL << 63));
+        v[0] <<= 1;
+        if (v[1] & (1ULL << 63)) v[0] ^= 1;
+        v[1] <<= 1;
+        if (pp) v[1] ^= h->prim_poly;
+      }
+    }
+  }
+
+  ld->last_value[0] = val[0];
+  ld->last_value[1] = val[1];
+
+  for (i = 0; i < 32; i++) {
+    for (j = 0; j < 16; j++) {
+      for (k = 0; k < 16; k++) {
+        btable[k] = (uint8_t) ld->tables[1-(j/8)][i][k];
+        ld->tables[1-(j/8)][i][k] >>= 8;
+      }
+      tables[i][j] = _mm_loadu_si128((__m128i *) btable);
+/*
+      printf("%2d %2d: ", i, j);
+      MM_PRINT8("", tables[i][j]);
+ */
+    }
+  }
+
+
+  mask1 = _mm_set1_epi8(0xf);
+
+  while (d64 != top) {
+
+    if (xor) {
+      for (i = 0; i < 16; i++) p[i] = _mm_load_si128 ((__m128i *) (d64+i*2));
+    } else {
+      for (i = 0; i < 16; i++) p[i] = _mm_setzero_si128();
+    }
+    i = 0;
+    for (k = 0; k < 16; k++) {
+      v0 = _mm_load_si128((__m128i *) s64); 
+      s64 += 2;
+      
+      si = _mm_and_si128(v0, mask1);
+  
+      for (j = 0; j < 16; j++) {
+        p[j] = _mm_xor_si128(p[j], _mm_shuffle_epi8(tables[i][j], si));
+      }
+      i++;
+      v0 = _mm_srli_epi32(v0, 4);
+      si = _mm_and_si128(v0, mask1);
+      for (j = 0; j < 16; j++) {
+        p[j] = _mm_xor_si128(p[j], _mm_shuffle_epi8(tables[i][j], si));
+      }
+      i++;
+    }
+    for (i = 0; i < 16; i++) {
+      _mm_store_si128((__m128i *) d64, p[i]);
+      d64 += 2;
+    }
+  }
+  /* Doing this instead of gf_do_final_region_alignment() because that doesn't hold 128-bit vals */
+
+  gf_w128_multiply_region_from_single(gf, rd.s_top, rd.d_top, val, ((char*)src+bytes)-(char*)rd.s_top, xor);
+}
+#endif
+
+static
+void
+gf_w128_split_8_128_multiply_region(gf_t *gf, void *src, void *dest, gf_val_128_t val, int bytes, int xor)
+{
+  int i, j, k;
+  uint64_t pp;
+  gf_internal_t *h;
+  uint64_t *s64, *d64, *top;
+  gf_region_data rd;
+  uint64_t v[2], s;
+  struct gf_w128_split_8_128_data *ld;
+
+  /* Check on alignment. Ignore it otherwise. */
+  gf_set_region_data(&rd, gf, src, dest, bytes, 0, xor, 8);
+
+  if (val[0] == 0) {
+    if (val[1] == 0) { gf_multby_zero(dest, bytes, xor); return; }
+    if (val[1] == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+  }
+    
+  h = (gf_internal_t *) gf->scratch;
+  ld = (struct gf_w128_split_8_128_data *) h->private;
+
+  s64 = (uint64_t *) rd.s_start;
+  d64 = (uint64_t *) rd.d_start;
+  top = (uint64_t *) rd.d_top;
+
+  if (val[0] != ld->last_value[0] || val[1] != ld->last_value[1]) {
+    v[0] = val[0];
+    v[1] = val[1];
+    for (i = 0; i < 16; i++) {
+      ld->tables[0][i][0] = 0;
+      ld->tables[1][i][0] = 0;
+      for (j = 1; j < (1 << 8); j <<= 1) {
+        for (k = 0; k < j; k++) {
+          ld->tables[0][i][k^j] = (v[0] ^ ld->tables[0][i][k]);
+          ld->tables[1][i][k^j] = (v[1] ^ ld->tables[1][i][k]);
+        }
+        pp = (v[0] & (1ULL << 63));
+        v[0] <<= 1;
+        if (v[1] & (1ULL << 63)) v[0] ^= 1;
+        v[1] <<= 1;
+        if (pp) v[1] ^= h->prim_poly;
+      }
+    }
+  }
+  ld->last_value[0] = val[0];
+  ld->last_value[1] = val[1];
+
+  while (d64 < top) {
+    v[0] = (xor) ? d64[0] : 0;
+    v[1] = (xor) ? d64[1] : 0;
+    s = s64[1];
+    i = 0;
+    while (s != 0) {
+      v[0] ^= ld->tables[0][i][s&0xff];
+      v[1] ^= ld->tables[1][i][s&0xff];
+      s >>= 8;
+      i++;
+    }
+    s = s64[0];
+    i = 8;
+    while (s != 0) {
+      v[0] ^= ld->tables[0][i][s&0xff];
+      v[1] ^= ld->tables[1][i][s&0xff];
+      s >>= 8;
+      i++;
+    }
+    d64[0] = v[0];
+    d64[1] = v[1];
+    s64 += 2;
+    d64 += 2;
+  }
+}
+
+void
+gf_w128_bytwo_b_multiply_region(gf_t *gf, void *src, void *dest, gf_val_128_t val, int bytes, int xor)
+{
+  uint64_t bmask, pp;
+  gf_internal_t *h;
+  uint64_t a[2], c[2], b[2], *s64, *d64, *top;
+  gf_region_data rd;
+
+  /* We only do this to check on alignment. */
+  gf_set_region_data(&rd, gf, src, dest, bytes, 0, xor, 8);
+
+  if (val[0] == 0) {
+    if (val[1] == 0) { gf_multby_zero(dest, bytes, xor); return; }
+    if (val[1] == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+  }
+    
+  h = (gf_internal_t *) gf->scratch;
+  s64 = (uint64_t *) rd.s_start;
+  d64 = (uint64_t *) rd.d_start;
+  top = (uint64_t *) rd.d_top;
+  bmask = (1ULL << 63);
+
+  while (d64 < top) {
+    set_zero(c, 0);
+    b[0] = s64[0];
+    b[1] = s64[1];
+    a[0] = val[0];
+    a[1] = val[1];
+
+    while (a[0] != 0) {
+      if (a[1] & 1) {
+        c[0] ^= b[0];
+        c[1] ^= b[1];
+      }
+      a[1] >>= 1;
+      if (a[0] & 1) a[1] ^= bmask;
+      a[0] >>= 1;
+      pp = (b[0] & bmask);
+      b[0] <<= 1;
+      if (b[1] & bmask) b[0] ^= 1;    
+      b[1] <<= 1;
+      if (pp) b[1] ^= h->prim_poly;
+    }
+    while (1) {
+      if (a[1] & 1) {
+        c[0] ^= b[0];
+        c[1] ^= b[1];
+      }
+      a[1] >>= 1;
+      if (a[1] == 0) break;
+      pp = (b[0] & bmask);
+      b[0] <<= 1;
+      if (b[1] & bmask) b[0] ^= 1;    
+      b[1] <<= 1;
+      if (pp) b[1] ^= h->prim_poly;
+    }
+    if (xor) {
+      d64[0] ^= c[0];
+      d64[1] ^= c[1];
+    } else {
+      d64[0] = c[0];
+      d64[1] = c[1];
+    }
+    s64 += 2;
+    d64 += 2;
+  }
+}
+
+static
+void gf_w128_group_m_init(gf_t *gf, gf_val_128_t b128)
+{
+  int i, j;
+  int g_m;
+  uint64_t prim_poly, lbit;
+  gf_internal_t *scratch;
+  gf_group_tables_t *gt;
+  uint64_t a128[2];
+  scratch = (gf_internal_t *) gf->scratch;
+  gt = scratch->private;
+  g_m = scratch->arg1;
+  prim_poly = scratch->prim_poly;
+
+
+  set_zero(gt->m_table, 0);
+  a_get_b(gt->m_table, 2, b128, 0);
+  lbit = 1;
+  lbit <<= 63;
+
+  for (i = 2; i < (1 << g_m); i <<= 1) {
+    a_get_b(a128, 0, gt->m_table, 2 * (i >> 1));
+    two_x(a128);
+    a_get_b(gt->m_table, 2 * i, a128, 0);
+    if (gt->m_table[2 * (i >> 1)] & lbit) gt->m_table[(2 * i) + 1] ^= prim_poly;
+    for (j = 0; j < i; j++) {
+      gt->m_table[(2 * i) + (2 * j)] = gt->m_table[(2 * i)] ^ gt->m_table[(2 * j)];
+      gt->m_table[(2 * i) + (2 * j) + 1] = gt->m_table[(2 * i) + 1] ^ gt->m_table[(2 * j) + 1];
+    }
+  }
+  return;
+}
+
+void
+gf_w128_group_multiply(GFP gf, gf_val_128_t a128, gf_val_128_t b128, gf_val_128_t c128)
+{
+  int i;
+  /* index_r, index_m, total_m (if g_r > g_m) */
+  int i_r, i_m, t_m;
+  int mask_m, mask_r;
+  int g_m, g_r;
+  uint64_t p_i[2], a[2];
+  gf_internal_t *scratch;
+  gf_group_tables_t *gt;
+
+  scratch = (gf_internal_t *) gf->scratch;
+  gt = scratch->private;
+  g_m = scratch->arg1;
+  g_r = scratch->arg2;
+
+  mask_m = (1 << g_m) - 1;
+  mask_r = (1 << g_r) - 1;
+
+  if (b128[0] != gt->m_table[2] || b128[1] != gt->m_table[3]) {
+    gf_w128_group_m_init(gf, b128);
+  }
+  
+  p_i[0] = 0;
+  p_i[1] = 0;
+  a[0] = a128[0];
+  a[1] = a128[1];
+
+  t_m = 0;
+  i_r = 0;
+
+  /* Top 64 bits */
+  for (i = ((GF_FIELD_WIDTH / 2) / g_m) - 1; i >= 0; i--) {
+    i_m = (a[0] >> (i * g_m)) & mask_m;
+    i_r ^= (p_i[0] >> (64 - g_m)) & mask_r;
+    p_i[0] <<= g_m;
+    p_i[0] ^= (p_i[1] >> (64-g_m));
+    p_i[1] <<= g_m;
+    p_i[0] ^= gt->m_table[2 * i_m];
+    p_i[1] ^= gt->m_table[(2 * i_m) + 1];
+    t_m += g_m;
+    if (t_m == g_r) {
+      p_i[1] ^= gt->r_table[i_r];
+      t_m = 0;
+      i_r = 0;
+    } else {
+      i_r <<= g_m;
+    }
+  }
+
+  for (i = ((GF_FIELD_WIDTH / 2) / g_m) - 1; i >= 0; i--) {
+    i_m = (a[1] >> (i * g_m)) & mask_m;
+    i_r ^= (p_i[0] >> (64 - g_m)) & mask_r;
+    p_i[0] <<= g_m;
+    p_i[0] ^= (p_i[1] >> (64-g_m));
+    p_i[1] <<= g_m;
+    p_i[0] ^= gt->m_table[2 * i_m];
+    p_i[1] ^= gt->m_table[(2 * i_m) + 1];
+    t_m += g_m;
+    if (t_m == g_r) {
+      p_i[1] ^= gt->r_table[i_r];
+      t_m = 0;
+      i_r = 0;
+    } else {
+      i_r <<= g_m;
+    }
+  }
+  c128[0] = p_i[0];
+  c128[1] = p_i[1];
+}
+
+static
+void
+gf_w128_group_multiply_region(gf_t *gf, void *src, void *dest, gf_val_128_t val, int bytes, int xor)
+{
+  int i;
+  int i_r, i_m, t_m;
+  int mask_m, mask_r;
+  int g_m, g_r;
+  uint64_t p_i[2], a[2];
+  gf_internal_t *scratch;
+  gf_group_tables_t *gt;
+  gf_region_data rd;
+  uint64_t *a128, *c128, *top;
+
+  /* We only do this to check on alignment. */
+  gf_set_region_data(&rd, gf, src, dest, bytes, 0, xor, 8);
+      
+  if (val[0] == 0) {
+    if (val[1] == 0) { gf_multby_zero(dest, bytes, xor); return; }
+    if (val[1] == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+  }
+    
+  scratch = (gf_internal_t *) gf->scratch;
+  gt = scratch->private;
+  g_m = scratch->arg1;
+  g_r = scratch->arg2;
+
+  mask_m = (1 << g_m) - 1;
+  mask_r = (1 << g_r) - 1;
+
+  if (val[0] != gt->m_table[2] || val[1] != gt->m_table[3]) {
+    gf_w128_group_m_init(gf, val);
+  }
+
+  a128 = (uint64_t *) src;
+  c128 = (uint64_t *) dest;
+  top = (uint64_t *) rd.d_top;
+
+  while (c128 < top) {
+    p_i[0] = 0;
+    p_i[1] = 0;
+    a[0] = a128[0];
+    a[1] = a128[1];
+  
+    t_m = 0;
+    i_r = 0;
+  
+    /* Top 64 bits */
+    for (i = ((GF_FIELD_WIDTH / 2) / g_m) - 1; i >= 0; i--) {
+      i_m = (a[0] >> (i * g_m)) & mask_m;
+      i_r ^= (p_i[0] >> (64 - g_m)) & mask_r;
+      p_i[0] <<= g_m;
+      p_i[0] ^= (p_i[1] >> (64-g_m));
+      p_i[1] <<= g_m;
+      
+      p_i[0] ^= gt->m_table[2 * i_m];
+      p_i[1] ^= gt->m_table[(2 * i_m) + 1];
+      t_m += g_m;
+      if (t_m == g_r) {
+        p_i[1] ^= gt->r_table[i_r];
+        t_m = 0;
+        i_r = 0;
+      } else {
+        i_r <<= g_m;
+      }
+    }
+    for (i = ((GF_FIELD_WIDTH / 2) / g_m) - 1; i >= 0; i--) {
+      i_m = (a[1] >> (i * g_m)) & mask_m;
+      i_r ^= (p_i[0] >> (64 - g_m)) & mask_r;
+      p_i[0] <<= g_m;
+      p_i[0] ^= (p_i[1] >> (64-g_m));
+      p_i[1] <<= g_m;
+      p_i[0] ^= gt->m_table[2 * i_m];
+      p_i[1] ^= gt->m_table[(2 * i_m) + 1];
+      t_m += g_m;
+      if (t_m == g_r) {
+        p_i[1] ^= gt->r_table[i_r];
+        t_m = 0;
+        i_r = 0;
+      } else {
+        i_r <<= g_m;
+      }
+    }
+  
+    if (xor) {
+      c128[0] ^= p_i[0];
+      c128[1] ^= p_i[1];
+    } else {
+      c128[0] = p_i[0];
+      c128[1] = p_i[1];
+    }
+    a128 += 2;
+    c128 += 2;
+  }
+}
+
+/* a^-1 -> b */
+  void
+gf_w128_euclid(GFP gf, gf_val_128_t a128, gf_val_128_t b128)
+{
+  uint64_t e_i[2], e_im1[2], e_ip1[2];
+  uint64_t d_i, d_im1, d_ip1;
+  uint64_t y_i[2], y_im1[2], y_ip1[2];
+  uint64_t c_i[2];
+  uint64_t *b;
+  uint64_t one = 1;
+
+  /* This needs to return some sort of error (in b128?) */
+  if (a128[0] == 0 && a128[1] == 0) return;
+
+  b = (uint64_t *) b128;
+
+  e_im1[0] = 0;
+  e_im1[1] = ((gf_internal_t *) (gf->scratch))->prim_poly;
+  e_i[0] = a128[0];
+  e_i[1] = a128[1];
+  d_im1 = 128;
+
+  //Allen: I think d_i starts at 63 here, and checks each bit of a, starting at MSB, looking for the first nonzero bit
+  //so d_i should be 0 if this half of a is all 0s, otherwise it should be the position from right of the first-from-left zero bit of this half of a.
+  //BUT if d_i is 0 at end we won't know yet if the rightmost bit of this half is 1 or not
+
+  for (d_i = (d_im1-1) % 64; ((one << d_i) & e_i[0]) == 0 && d_i > 0; d_i--) ;
+
+  //Allen: this is testing just the first half of the stop condition above, so if it holds we know we did not find a nonzero bit yet
+
+  if (!((one << d_i) & e_i[0])) {
+
+    //Allen: this is doing the same thing on the other half of a. In other words, we're still searching for a nonzero bit of a.
+    // but not bothering to test if d_i hits zero, which is fine because we've already tested for a=0.
+
+    for (d_i = (d_im1-1) % 64; ((one << d_i) & e_i[1]) == 0; d_i--) ;
+
+  } else {
+
+    //Allen: if a 1 was found in more-significant half of a, make d_i the ACTUAL index of the first nonzero bit in the entire a.
+
+    d_i += 64;
+  }
+  y_i[0] = 0;
+  y_i[1] = 1;
+  y_im1[0] = 0;
+  y_im1[1] = 0;
+
+  while (!(e_i[0] == 0 && e_i[1] == 1)) {
+
+    e_ip1[0] = e_im1[0];
+    e_ip1[1] = e_im1[1];
+    d_ip1 = d_im1;
+    c_i[0] = 0;
+    c_i[1] = 0;
+
+    while (d_ip1 >= d_i) {
+      if ((d_ip1 - d_i) >= 64) {
+        c_i[0] ^= (one << ((d_ip1 - d_i) - 64));
+        e_ip1[0] ^= (e_i[1] << ((d_ip1 - d_i) - 64));
+      } else {
+        c_i[1] ^= (one << (d_ip1 - d_i));
+        e_ip1[0] ^= (e_i[0] << (d_ip1 - d_i));
+        if (d_ip1 - d_i > 0) e_ip1[0] ^= (e_i[1] >> (64 - (d_ip1 - d_i)));
+        e_ip1[1] ^= (e_i[1] << (d_ip1 - d_i));
+      }
+      d_ip1--;
+      if (e_ip1[0] == 0 && e_ip1[1] == 0) { b[0] = 0; b[1] = 0; return; }
+      while (d_ip1 >= 64 && (e_ip1[0] & (one << (d_ip1 - 64))) == 0) d_ip1--;
+      while (d_ip1 <  64 && (e_ip1[1] & (one << d_ip1)) == 0) d_ip1--;
+    }
+    gf->multiply.w128(gf, c_i, y_i, y_ip1);
+    y_ip1[0] ^= y_im1[0];
+    y_ip1[1] ^= y_im1[1];
+
+    y_im1[0] = y_i[0];
+    y_im1[1] = y_i[1];
+
+    y_i[0] = y_ip1[0];
+    y_i[1] = y_ip1[1];
+
+    e_im1[0] = e_i[0];
+    e_im1[1] = e_i[1];
+    d_im1 = d_i;
+    e_i[0] = e_ip1[0];
+    e_i[1] = e_ip1[1];
+    d_i = d_ip1;
+  }
+
+  b[0] = y_i[0];
+  b[1] = y_i[1];
+  return;
+}
+
+  void
+gf_w128_divide_from_inverse(GFP gf, gf_val_128_t a128, gf_val_128_t b128, gf_val_128_t c128)
+{
+  uint64_t d[2];
+  gf->inverse.w128(gf, b128, d);
+  gf->multiply.w128(gf, a128, d, c128);
+  return;
+}
+
+  void
+gf_w128_inverse_from_divide(GFP gf, gf_val_128_t a128, gf_val_128_t b128)
+{
+  uint64_t one128[2];
+  one128[0] = 0;
+  one128[1] = 1;
+  gf->divide.w128(gf, one128, a128, b128);
+  return;
+}
+
+
+static
+  void
+gf_w128_composite_inverse(gf_t *gf, gf_val_128_t a, gf_val_128_t inv)
+{
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  gf_t *base_gf = h->base_gf;
+  uint64_t a0 = a[1];
+  uint64_t a1 = a[0];
+  uint64_t c0, c1, d, tmp;
+  uint64_t a0inv, a1inv;
+
+  if (a0 == 0) {
+    a1inv = base_gf->inverse.w64(base_gf, a1);
+    c0 = base_gf->multiply.w64(base_gf, a1inv, h->prim_poly);
+    c1 = a1inv;
+  } else if (a1 == 0) {
+    c0 = base_gf->inverse.w64(base_gf, a0);
+    c1 = 0;
+  } else {
+    a1inv = base_gf->inverse.w64(base_gf, a1);
+    a0inv = base_gf->inverse.w64(base_gf, a0);
+
+    d = base_gf->multiply.w64(base_gf, a1, a0inv);
+
+    tmp = (base_gf->multiply.w64(base_gf, a1, a0inv) ^ base_gf->multiply.w64(base_gf, a0, a1inv) ^ h->prim_poly);
+    tmp = base_gf->inverse.w64(base_gf, tmp);
+
+    d = base_gf->multiply.w64(base_gf, d, tmp);
+
+    c0 = base_gf->multiply.w64(base_gf, (d^1), a0inv);
+    c1 = base_gf->multiply.w64(base_gf, d, a1inv);
+  }
+  inv[0] = c1;
+  inv[1] = c0;
+}
+
+static
+  void
+gf_w128_composite_multiply(gf_t *gf, gf_val_128_t a, gf_val_128_t b, gf_val_128_t rv)
+{
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  gf_t *base_gf = h->base_gf;
+  uint64_t b0 = b[1];
+  uint64_t b1 = b[0];
+  uint64_t a0 = a[1];
+  uint64_t a1 = a[0];
+  uint64_t a1b1;
+
+  a1b1 = base_gf->multiply.w64(base_gf, a1, b1);
+
+  rv[1] = (base_gf->multiply.w64(base_gf, a0, b0) ^ a1b1);
+  rv[0] = base_gf->multiply.w64(base_gf, a1, b0) ^ 
+    base_gf->multiply.w64(base_gf, a0, b1) ^ 
+    base_gf->multiply.w64(base_gf, a1b1, h->prim_poly);
+}
+
+static
+  void
+gf_w128_composite_multiply_region(gf_t *gf, void *src, void *dest, gf_val_128_t val, int bytes, int xor)
+{
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  gf_t *base_gf = h->base_gf;
+  uint64_t b0 = val[1];
+  uint64_t b1 = val[0];
+  uint64_t *s64, *d64;
+  uint64_t *top;
+  uint64_t a0, a1, a1b1;
+  gf_region_data rd;
+
+  if (val[0] == 0 && val[1] == 0) { gf_multby_zero(dest, bytes, xor); return; }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, 0, xor, 8);
+
+  s64 = rd.s_start;
+  d64 = rd.d_start;
+  top = rd.d_top;
+
+  if (xor) {
+    while (d64 < top) {
+      a1 = s64[0];
+      a0 = s64[1];
+      a1b1 = base_gf->multiply.w64(base_gf, a1, b1);
+
+      d64[1] ^= (base_gf->multiply.w64(base_gf, a0, b0) ^ a1b1);
+      d64[0] ^= (base_gf->multiply.w64(base_gf, a1, b0) ^ 
+          base_gf->multiply.w64(base_gf, a0, b1) ^ 
+          base_gf->multiply.w64(base_gf, a1b1, h->prim_poly));
+      s64 += 2;
+      d64 += 2;
+    }
+  } else {
+    while (d64 < top) {
+      a1 = s64[0];
+      a0 = s64[1];
+      a1b1 = base_gf->multiply.w64(base_gf, a1, b1);
+
+      d64[1] = (base_gf->multiply.w64(base_gf, a0, b0) ^ a1b1);
+      d64[0] = (base_gf->multiply.w64(base_gf, a1, b0) ^ 
+          base_gf->multiply.w64(base_gf, a0, b1) ^ 
+          base_gf->multiply.w64(base_gf, a1b1, h->prim_poly));
+      s64 += 2;
+      d64 += 2;
+    }
+  }
+}
+
+static
+void
+gf_w128_composite_multiply_region_alt(gf_t *gf, void *src, void *dest, gf_val_128_t val, int bytes, int 
+    xor)
+{
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;  gf_t *base_gf = h->base_gf;
+  gf_val_64_t val0 = val[1];
+  gf_val_64_t val1 = val[0];
+  uint8_t *slow, *shigh;
+  uint8_t *dlow, *dhigh, *top;
+  int sub_reg_size;
+  gf_region_data rd;
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, 0, xor, 64);
+  gf_w128_multiply_region_from_single(gf, src, dest, val, ((char*)rd.s_start-(char*)src), xor);
+
+  slow = (uint8_t *) rd.s_start;
+  dlow = (uint8_t *) rd.d_start;
+  top = (uint8_t*) rd.d_top;
+  sub_reg_size = (top - dlow)/2;
+  shigh = slow + sub_reg_size;
+  dhigh = dlow + sub_reg_size;
+
+  base_gf->multiply_region.w64(base_gf, slow, dlow, val0, sub_reg_size, xor);
+  base_gf->multiply_region.w64(base_gf, shigh, dlow, val1, sub_reg_size, 1);
+  base_gf->multiply_region.w64(base_gf, slow, dhigh, val1, sub_reg_size, xor);
+  base_gf->multiply_region.w64(base_gf, shigh, dhigh, val0, sub_reg_size, 1);
+  base_gf->multiply_region.w64(base_gf, shigh, dhigh, base_gf->multiply.w64(base_gf, h->prim_poly, val1
+        ), sub_reg_size, 1);
+
+  gf_w128_multiply_region_from_single(gf, rd.s_top, rd.d_top, val, ((char*)src+bytes)-(char*)rd.s_top, xor);
+}
+
+
+  static
+int gf_w128_composite_init(gf_t *gf)
+{
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+
+  if (h->region_type & GF_REGION_ALTMAP) {
+    gf->multiply_region.w128 = gf_w128_composite_multiply_region_alt;   
+  } else {
+    gf->multiply_region.w128 = gf_w128_composite_multiply_region;
+  }
+
+  gf->multiply.w128 = gf_w128_composite_multiply;
+  gf->divide.w128 = gf_w128_divide_from_inverse;
+  gf->inverse.w128 = gf_w128_composite_inverse;
+
+  return 1;
+}
+
+static
+int gf_w128_cfm_init(gf_t *gf)
+{
+#if defined(INTEL_SSE4_PCLMUL)
+  gf->inverse.w128 = gf_w128_euclid;
+  gf->multiply.w128 = gf_w128_clm_multiply;
+  gf->multiply_region.w128 = gf_w128_clm_multiply_region_from_single;
+  return 1;
+#endif
+
+  return 0;
+}
+
+static
+int gf_w128_shift_init(gf_t *gf)
+{
+  gf->multiply.w128 = gf_w128_shift_multiply;
+  gf->inverse.w128 = gf_w128_euclid;
+  gf->multiply_region.w128 = gf_w128_multiply_region_from_single;
+  return 1;
+}
+
+  static
+int gf_w128_bytwo_init(gf_t *gf)
+{
+  gf_internal_t *h;
+  h = (gf_internal_t *) gf->scratch;
+
+  if (h->mult_type == GF_MULT_BYTWO_p) {
+    gf->multiply.w128 = gf_w128_bytwo_p_multiply;
+    /*gf->multiply.w128 = gf_w128_sse_bytwo_p_multiply;*/
+    /* John: the sse function is slower.*/
+  } else {
+    gf->multiply.w128 = gf_w128_bytwo_b_multiply;
+    /*gf->multiply.w128 = gf_w128_sse_bytwo_b_multiply;
+Ben: This sse function is also slower. */
+  }
+  gf->inverse.w128 = gf_w128_euclid;
+  gf->multiply_region.w128 = gf_w128_bytwo_b_multiply_region;
+  return 1;
+}
+
+/*
+ * Because the prim poly is only 8 bits and we are limiting g_r to 16, I do not need the high 64
+ * bits in all of these numbers.
+ */
+  static
+void gf_w128_group_r_init(gf_t *gf)
+{
+  int i, j;
+  int g_r;
+  uint64_t pp;
+  gf_internal_t *scratch;
+  gf_group_tables_t *gt;
+  scratch = (gf_internal_t *) gf->scratch;
+  gt = scratch->private;
+  g_r = scratch->arg2;
+  pp = scratch->prim_poly;
+
+  gt->r_table[0] = 0;
+  for (i = 1; i < (1 << g_r); i++) {
+    gt->r_table[i] = 0;
+    for (j = 0; j < g_r; j++) {
+      if (i & (1 << j)) {
+        gt->r_table[i] ^= (pp << j);
+      }
+    }
+  }
+  return;
+}
+
+  static 
+int gf_w128_split_init(gf_t *gf)
+{
+  struct gf_w128_split_4_128_data *sd4;
+  struct gf_w128_split_8_128_data *sd8;
+  gf_internal_t *h;
+
+  h = (gf_internal_t *) gf->scratch;
+
+  gf->multiply.w128 = gf_w128_bytwo_p_multiply;
+#if defined(INTEL_SSE4_PCLMUL)
+  if (!(h->region_type & GF_REGION_NOSSE)){
+    gf->multiply.w128 = gf_w128_clm_multiply;
+  }
+#endif
+
+  gf->inverse.w128 = gf_w128_euclid;
+
+  if ((h->arg1 != 4 && h->arg2 != 4) || h->mult_type == GF_MULT_DEFAULT) {
+    sd8 = (struct gf_w128_split_8_128_data *) h->private;
+    sd8->last_value[0] = 0;
+    sd8->last_value[1] = 0;
+    gf->multiply_region.w128 = gf_w128_split_8_128_multiply_region;
+  } else {
+    sd4 = (struct gf_w128_split_4_128_data *) h->private;
+    sd4->last_value[0] = 0;
+    sd4->last_value[1] = 0;
+    if((h->region_type & GF_REGION_ALTMAP))
+    {
+      #ifdef INTEL_SSE4
+        if(!(h->region_type & GF_REGION_NOSSE))
+          gf->multiply_region.w128 = gf_w128_split_4_128_sse_altmap_multiply_region;
+        else
+          return 0;
+      #else
+        return 0;
+      #endif
+    }
+    else {
+      #ifdef INTEL_SSE4
+        if(!(h->region_type & GF_REGION_NOSSE))
+          gf->multiply_region.w128 = gf_w128_split_4_128_sse_multiply_region;
+        else
+          gf->multiply_region.w128 = gf_w128_split_4_128_multiply_region;
+      #else
+      gf->multiply_region.w128 = gf_w128_split_4_128_multiply_region;
+      #endif
+    }
+  }
+  return 1;
+}
+
+
+static
+int gf_w128_group_init(gf_t *gf)
+{
+  gf_internal_t *scratch;
+  gf_group_tables_t *gt;
+  int g_r, size_r;
+
+  scratch = (gf_internal_t *) gf->scratch;
+  gt = scratch->private;
+  g_r = scratch->arg2;
+  size_r = (1 << g_r);
+
+  gt->r_table = (gf_val_128_t)((char*)scratch->private + (2 * sizeof(uint64_t *)));
+  gt->m_table = gt->r_table + size_r;
+  gt->m_table[2] = 0;
+  gt->m_table[3] = 0;
+
+  gf->multiply.w128 = gf_w128_group_multiply;
+  gf->inverse.w128 = gf_w128_euclid;
+  gf->multiply_region.w128 = gf_w128_group_multiply_region;
+
+  gf_w128_group_r_init(gf);
+
+  return 1;
+}
+
+void gf_w128_extract_word(gf_t *gf, void *start, int bytes, int index, gf_val_128_t rv)
+{
+  gf_val_128_t s;
+
+  s = (gf_val_128_t) start;
+  s += (index * 2); 
+  memcpy(rv, s, 16);
+}
+
+static void gf_w128_split_extract_word(gf_t *gf, void *start, int bytes, int index, gf_val_128_t rv)
+{
+  int i, blocks;
+  uint64_t *r64, tmp;
+  uint8_t *r8;
+  gf_region_data rd;
+
+  gf_set_region_data(&rd, gf, start, start, bytes, 0, 0, 256);
+  r64 = (uint64_t *) start;
+  if ((r64 + index*2 < (uint64_t *) rd.d_start) ||
+      (r64 + index*2 >= (uint64_t *) rd.d_top)) {
+    memcpy(rv, r64+(index*2), 16);
+    return;
+  }
+
+  index -= (((uint64_t *) rd.d_start) - r64)/2;
+  r64 = (uint64_t *) rd.d_start;
+
+  blocks = index/16;
+  r64 += (blocks*32);
+  index %= 16;
+  r8 = (uint8_t *) r64;
+  r8 += index;
+  rv[0] = 0;
+  rv[1] = 0;
+
+  for (i = 0; i < 8; i++) {
+    tmp = *r8;
+    rv[1] |= (tmp << (i*8));
+    r8 += 16;
+  }
+
+  for (i = 0; i < 8; i++) {
+    tmp = *r8;
+    rv[0] |= (tmp << (i*8));
+    r8 += 16;
+  }
+  return;
+}
+
+  static
+void gf_w128_composite_extract_word(gf_t *gf, void *start, int bytes, int index, gf_val_128_t rv)
+{
+  int sub_size;
+  gf_internal_t *h;
+  uint8_t *r8, *top;
+  uint64_t *r64;
+  gf_region_data rd;
+
+  h = (gf_internal_t *) gf->scratch;
+  gf_set_region_data(&rd, gf, start, start, bytes, 0, 0, 64);
+  r64 = (uint64_t *) start;
+  if ((r64 + index*2 < (uint64_t *) rd.d_start) ||
+      (r64 + index*2 >= (uint64_t *) rd.d_top)) {
+    memcpy(rv, r64+(index*2), 16);
+    return;
+  }
+  index -= (((uint64_t *) rd.d_start) - r64)/2;
+  r8 = (uint8_t *) rd.d_start;
+  top = (uint8_t *) rd.d_top;
+  sub_size = (top-r8)/2;
+
+  rv[1] = h->base_gf->extract_word.w64(h->base_gf, r8, sub_size, index);
+  rv[0] = h->base_gf->extract_word.w64(h->base_gf, r8+sub_size, sub_size, index);
+  
+  return;
+}
+
+int gf_w128_scratch_size(int mult_type, int region_type, int divide_type, int arg1, int arg2)
+{
+  int size_m, size_r;
+  if (divide_type==GF_DIVIDE_MATRIX) return 0;
+
+  switch(mult_type)
+  {
+    case GF_MULT_CARRY_FREE:
+      return sizeof(gf_internal_t);
+      break;
+    case GF_MULT_SHIFT:
+      return sizeof(gf_internal_t);
+      break;
+    case GF_MULT_BYTWO_p:
+    case GF_MULT_BYTWO_b:
+      return sizeof(gf_internal_t);
+      break;
+    case GF_MULT_DEFAULT: 
+    case GF_MULT_SPLIT_TABLE:
+      if ((arg1 == 4 && arg2 == 128) || (arg1 == 128 && arg2 == 4)) {
+        return sizeof(gf_internal_t) + sizeof(struct gf_w128_split_4_128_data) + 64;
+      } else if ((arg1 == 8 && arg2 == 128) || (arg1 == 128 && arg2 == 8) || mult_type == GF_MULT_DEFAULT) {
+        return sizeof(gf_internal_t) + sizeof(struct gf_w128_split_8_128_data) + 64;
+      }
+      return 0;
+      break;
+    case GF_MULT_GROUP:
+      /* JSP We've already error checked the arguments. */
+      size_m = (1 << arg1) * 2 * sizeof(uint64_t);
+      size_r = (1 << arg2) * 2 * sizeof(uint64_t);
+      /* 
+       * two pointers prepend the table data for structure
+       * because the tables are of dynamic size
+       */
+      return sizeof(gf_internal_t) + size_m + size_r + 4 * sizeof(uint64_t *);
+      break;
+    case GF_MULT_COMPOSITE:
+      if (arg1 == 2) {
+        return sizeof(gf_internal_t) + 4;
+      } else {
+        return 0;
+      }
+      break;
+
+    default:
+      return 0;
+   }
+}
+
+int gf_w128_init(gf_t *gf)
+{
+  gf_internal_t *h;
+  int no_default_flag = 0;
+
+  h = (gf_internal_t *) gf->scratch;
+  
+  /* Allen: set default primitive polynomial / irreducible polynomial if needed */
+
+  if (h->prim_poly == 0) {
+    if (h->mult_type == GF_MULT_COMPOSITE) {
+      h->prim_poly = gf_composite_get_default_poly(h->base_gf);
+      if (h->prim_poly == 0) return 0; /* This shouldn't happen */
+    } else {
+      h->prim_poly = 0x87; /* Omitting the leftmost 1 as in w=32 */
+    }
+    if (no_default_flag == 1) {
+      fprintf(stderr,"Code contains no default irreducible polynomial for given base field\n");
+      return 0;
+    }
+  }
+
+  gf->multiply.w128 = NULL;
+  gf->divide.w128 = NULL;
+  gf->inverse.w128 = NULL;
+  gf->multiply_region.w128 = NULL;
+  switch(h->mult_type) {
+    case GF_MULT_BYTWO_p:
+    case GF_MULT_BYTWO_b:      if (gf_w128_bytwo_init(gf) == 0) return 0; break;
+    case GF_MULT_CARRY_FREE:   if (gf_w128_cfm_init(gf) == 0) return 0; break;
+    case GF_MULT_SHIFT:        if (gf_w128_shift_init(gf) == 0) return 0; break;
+    case GF_MULT_GROUP:        if (gf_w128_group_init(gf) == 0) return 0; break;
+    case GF_MULT_DEFAULT: 
+    case GF_MULT_SPLIT_TABLE:  if (gf_w128_split_init(gf) == 0) return 0; break;
+    case GF_MULT_COMPOSITE:    if (gf_w128_composite_init(gf) == 0) return 0; break;
+    default: return 0;
+  }
+
+  /* Ben: Used to be h->region_type == GF_REGION_ALTMAP, but failed since there
+     are multiple flags in h->region_type */
+  if (h->mult_type == GF_MULT_SPLIT_TABLE && (h->region_type & GF_REGION_ALTMAP)) {
+    gf->extract_word.w128 = gf_w128_split_extract_word;
+  } else if (h->mult_type == GF_MULT_COMPOSITE && h->region_type == GF_REGION_ALTMAP) {
+    gf->extract_word.w128 = gf_w128_composite_extract_word;
+  } else {
+    gf->extract_word.w128 = gf_w128_extract_word;
+  }
+
+  if (h->divide_type == GF_DIVIDE_EUCLID) {
+    gf->divide.w128 = gf_w128_divide_from_inverse;
+  } 
+
+  if (gf->inverse.w128 != NULL && gf->divide.w128 == NULL) {
+    gf->divide.w128 = gf_w128_divide_from_inverse;
+  }
+  if (gf->inverse.w128 == NULL && gf->divide.w128 != NULL) {
+    gf->inverse.w128 = gf_w128_inverse_from_divide;
+  }
+  return 1;
+}
diff --git a/src/erasure-code/jerasure/gf-complete/src/gf_w16.c b/src/erasure-code/jerasure/gf-complete/src/gf_w16.c
new file mode 100644
index 0000000..f1fb650
--- /dev/null
+++ b/src/erasure-code/jerasure/gf-complete/src/gf_w16.c
@@ -0,0 +1,2489 @@
+/*
+ * GF-Complete: A Comprehensive Open Source Library for Galois Field Arithmetic
+ * James S. Plank, Ethan L. Miller, Kevin M. Greenan,
+ * Benjamin A. Arnold, John A. Burnum, Adam W. Disney, Allen C. McBride.
+ *
+ * gf_w16.c
+ *
+ * Routines for 16-bit Galois fields
+ */
+
+#include "gf_int.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+#define GF_FIELD_WIDTH (16)
+#define GF_FIELD_SIZE (1 << GF_FIELD_WIDTH)
+#define GF_MULT_GROUP_SIZE GF_FIELD_SIZE-1
+
+#define GF_BASE_FIELD_WIDTH (8)
+#define GF_BASE_FIELD_SIZE       (1 << GF_BASE_FIELD_WIDTH)
+
+struct gf_w16_logtable_data {
+    uint16_t      log_tbl[GF_FIELD_SIZE];
+    uint16_t      antilog_tbl[GF_FIELD_SIZE * 2];
+    uint16_t      inv_tbl[GF_FIELD_SIZE];
+    uint16_t      *d_antilog;
+};
+
+struct gf_w16_zero_logtable_data {
+    int           log_tbl[GF_FIELD_SIZE];
+    uint16_t      _antilog_tbl[GF_FIELD_SIZE * 4];
+    uint16_t      *antilog_tbl;
+    uint16_t      inv_tbl[GF_FIELD_SIZE];
+};
+
+struct gf_w16_lazytable_data {
+    uint16_t      log_tbl[GF_FIELD_SIZE];
+    uint16_t      antilog_tbl[GF_FIELD_SIZE * 2];
+    uint16_t      inv_tbl[GF_FIELD_SIZE];
+    uint16_t      *d_antilog;
+    uint16_t      lazytable[GF_FIELD_SIZE];
+};
+
+struct gf_w16_bytwo_data {
+    uint64_t prim_poly;
+    uint64_t mask1;
+    uint64_t mask2;
+};
+
+struct gf_w16_split_8_8_data {
+    uint16_t      tables[3][256][256];
+};
+
+struct gf_w16_group_4_4_data {
+    uint16_t reduce[16];
+    uint16_t shift[16];
+};
+
+struct gf_w16_composite_data {
+  uint8_t *mult_table;
+};
+
+#define AB2(ip, am1 ,am2, b, t1, t2) {\
+  t1 = (b << 1) & am1;\
+  t2 = b & am2; \
+  t2 = ((t2 << 1) - (t2 >> (GF_FIELD_WIDTH-1))); \
+  b = (t1 ^ (t2 & ip));}
+
+#define SSE_AB2(pp, m1 ,m2, va, t1, t2) {\
+          t1 = _mm_and_si128(_mm_slli_epi64(va, 1), m1); \
+          t2 = _mm_and_si128(va, m2); \
+          t2 = _mm_sub_epi64 (_mm_slli_epi64(t2, 1), _mm_srli_epi64(t2, (GF_FIELD_WIDTH-1))); \
+          va = _mm_xor_si128(t1, _mm_and_si128(t2, pp)); }
+
+#define MM_PRINT(s, r) { uint8_t blah[16], ii; printf("%-12s", s); _mm_storeu_si128((__m128i *)blah, r); for (ii = 0; ii < 16; ii += 2) printf("  %02x %02x", blah[15-ii], blah[14-ii]); printf("\n"); }
+
+#define GF_FIRST_BIT (1 << 15)
+#define GF_MULTBY_TWO(p) (((p) & GF_FIRST_BIT) ? (((p) << 1) ^ h->prim_poly) : (p) << 1)
+
+static
+inline
+gf_val_32_t gf_w16_inverse_from_divide (gf_t *gf, gf_val_32_t a)
+{
+  return gf->divide.w32(gf, 1, a);
+}
+
+static
+inline
+gf_val_32_t gf_w16_divide_from_inverse (gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  b = gf->inverse.w32(gf, b);
+  return gf->multiply.w32(gf, a, b);
+}
+
+static
+void
+gf_w16_multiply_region_from_single(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  gf_region_data rd;
+  uint16_t *s16;
+  uint16_t *d16;
+  
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 2);
+  gf_do_initial_region_alignment(&rd);
+
+  s16 = (uint16_t *) rd.s_start;
+  d16 = (uint16_t *) rd.d_start;
+
+  if (xor) {
+    while (d16 < ((uint16_t *) rd.d_top)) {
+      *d16 ^= gf->multiply.w32(gf, val, *s16);
+      d16++;
+      s16++;
+    } 
+  } else {
+    while (d16 < ((uint16_t *) rd.d_top)) {
+      *d16 = gf->multiply.w32(gf, val, *s16);
+      d16++;
+      s16++;
+    } 
+  }
+  gf_do_final_region_alignment(&rd);
+}
+
+#if defined(INTEL_SSE4_PCLMUL)
+static
+void
+gf_w16_clm_multiply_region_from_single_2(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  gf_region_data rd;
+  uint16_t *s16;
+  uint16_t *d16;
+  __m128i         a, b;
+  __m128i         result;
+  __m128i         prim_poly;
+  __m128i         w;
+  gf_internal_t * h = gf->scratch;
+  prim_poly = _mm_set_epi32(0, 0, 0, (uint32_t)(h->prim_poly & 0x1ffffULL));
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 2);
+  gf_do_initial_region_alignment(&rd);
+
+  a = _mm_insert_epi32 (_mm_setzero_si128(), val, 0);
+  
+  s16 = (uint16_t *) rd.s_start;
+  d16 = (uint16_t *) rd.d_start;
+
+  if (xor) {
+    while (d16 < ((uint16_t *) rd.d_top)) {
+
+      /* see gf_w16_clm_multiply() to see explanation of method */
+      
+      b = _mm_insert_epi32 (a, (gf_val_32_t)(*s16), 0);
+      result = _mm_clmulepi64_si128 (a, b, 0);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 2), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 2), 0);
+      result = _mm_xor_si128 (result, w);
+
+      *d16 ^= ((gf_val_32_t)_mm_extract_epi32(result, 0));
+      d16++;
+      s16++;
+    } 
+  } else {
+    while (d16 < ((uint16_t *) rd.d_top)) {
+      
+      /* see gf_w16_clm_multiply() to see explanation of method */
+      
+      b = _mm_insert_epi32 (a, (gf_val_32_t)(*s16), 0);
+      result = _mm_clmulepi64_si128 (a, b, 0);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 2), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 2), 0);
+      result = _mm_xor_si128 (result, w);
+      
+      *d16 = ((gf_val_32_t)_mm_extract_epi32(result, 0));
+      d16++;
+      s16++;
+    } 
+  }
+  gf_do_final_region_alignment(&rd);
+}
+#endif
+
+#if defined(INTEL_SSE4_PCLMUL)
+static
+void
+gf_w16_clm_multiply_region_from_single_3(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  gf_region_data rd;
+  uint16_t *s16;
+  uint16_t *d16;
+
+  __m128i         a, b;
+  __m128i         result;
+  __m128i         prim_poly;
+  __m128i         w;
+  gf_internal_t * h = gf->scratch;
+  prim_poly = _mm_set_epi32(0, 0, 0, (uint32_t)(h->prim_poly & 0x1ffffULL));
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  a = _mm_insert_epi32 (_mm_setzero_si128(), val, 0);
+  
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 2);
+  gf_do_initial_region_alignment(&rd);
+
+  s16 = (uint16_t *) rd.s_start;
+  d16 = (uint16_t *) rd.d_start;
+
+  if (xor) {
+    while (d16 < ((uint16_t *) rd.d_top)) {
+      
+      /* see gf_w16_clm_multiply() to see explanation of method */
+      
+      b = _mm_insert_epi32 (a, (gf_val_32_t)(*s16), 0);
+      result = _mm_clmulepi64_si128 (a, b, 0);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 2), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 2), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 2), 0);
+      result = _mm_xor_si128 (result, w);
+
+      *d16 ^= ((gf_val_32_t)_mm_extract_epi32(result, 0));
+      d16++;
+      s16++;
+    } 
+  } else {
+    while (d16 < ((uint16_t *) rd.d_top)) {
+      
+      /* see gf_w16_clm_multiply() to see explanation of method */
+      
+      b = _mm_insert_epi32 (a, (gf_val_32_t)(*s16), 0);
+      result = _mm_clmulepi64_si128 (a, b, 0);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 2), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 2), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 2), 0);
+      result = _mm_xor_si128 (result, w);
+      
+      *d16 = ((gf_val_32_t)_mm_extract_epi32(result, 0));
+      d16++;
+      s16++;
+    } 
+  }
+  gf_do_final_region_alignment(&rd);
+}
+#endif
+
+#if defined(INTEL_SSE4_PCLMUL)
+static
+void
+gf_w16_clm_multiply_region_from_single_4(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  gf_region_data rd;
+  uint16_t *s16;
+  uint16_t *d16;
+
+  __m128i         a, b;
+  __m128i         result;
+  __m128i         prim_poly;
+  __m128i         w;
+  gf_internal_t * h = gf->scratch;
+  prim_poly = _mm_set_epi32(0, 0, 0, (uint32_t)(h->prim_poly & 0x1ffffULL));
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 2);
+  gf_do_initial_region_alignment(&rd);
+
+  a = _mm_insert_epi32 (_mm_setzero_si128(), val, 0);
+  
+  s16 = (uint16_t *) rd.s_start;
+  d16 = (uint16_t *) rd.d_start;
+
+  if (xor) {
+    while (d16 < ((uint16_t *) rd.d_top)) {
+      
+      /* see gf_w16_clm_multiply() to see explanation of method */
+      
+      b = _mm_insert_epi32 (a, (gf_val_32_t)(*s16), 0);
+      result = _mm_clmulepi64_si128 (a, b, 0);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 2), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 2), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 2), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 2), 0);
+      result = _mm_xor_si128 (result, w);
+
+      *d16 ^= ((gf_val_32_t)_mm_extract_epi32(result, 0));
+      d16++;
+      s16++;
+    } 
+  } else {
+    while (d16 < ((uint16_t *) rd.d_top)) {
+      
+      /* see gf_w16_clm_multiply() to see explanation of method */
+      
+      b = _mm_insert_epi32 (a, (gf_val_32_t)(*s16), 0);
+      result = _mm_clmulepi64_si128 (a, b, 0);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 2), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 2), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 2), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 2), 0);
+      result = _mm_xor_si128 (result, w);
+      
+      *d16 = ((gf_val_32_t)_mm_extract_epi32(result, 0));
+      d16++;
+      s16++;
+    } 
+  }
+  gf_do_final_region_alignment(&rd);
+}
+#endif
+
+static
+inline
+gf_val_32_t gf_w16_euclid (gf_t *gf, gf_val_32_t b)
+{
+  gf_val_32_t e_i, e_im1, e_ip1;
+  gf_val_32_t d_i, d_im1, d_ip1;
+  gf_val_32_t y_i, y_im1, y_ip1;
+  gf_val_32_t c_i;
+
+  if (b == 0) return -1;
+  e_im1 = ((gf_internal_t *) (gf->scratch))->prim_poly;
+  e_i = b;
+  d_im1 = 16;
+  for (d_i = d_im1; ((1 << d_i) & e_i) == 0; d_i--) ;
+  y_i = 1;
+  y_im1 = 0;
+
+  while (e_i != 1) {
+
+    e_ip1 = e_im1;
+    d_ip1 = d_im1;
+    c_i = 0;
+
+    while (d_ip1 >= d_i) {
+      c_i ^= (1 << (d_ip1 - d_i));
+      e_ip1 ^= (e_i << (d_ip1 - d_i));
+      if (e_ip1 == 0) return 0;
+      while ((e_ip1 & (1 << d_ip1)) == 0) d_ip1--;
+    }
+
+    y_ip1 = y_im1 ^ gf->multiply.w32(gf, c_i, y_i);
+    y_im1 = y_i;
+    y_i = y_ip1;
+
+    e_im1 = e_i;
+    d_im1 = d_i;
+    e_i = e_ip1;
+    d_i = d_ip1;
+  }
+
+  return y_i;
+}
+
+static
+gf_val_32_t gf_w16_extract_word(gf_t *gf, void *start, int bytes, int index)
+{
+  uint16_t *r16, rv;
+
+  r16 = (uint16_t *) start;
+  rv = r16[index];
+  return rv;
+}
+
+static
+gf_val_32_t gf_w16_composite_extract_word(gf_t *gf, void *start, int bytes, int index)
+{
+  int sub_size;
+  gf_internal_t *h;
+  uint8_t *r8, *top;
+  uint16_t a, b, *r16;
+  gf_region_data rd;
+
+  h = (gf_internal_t *) gf->scratch;
+  gf_set_region_data(&rd, gf, start, start, bytes, 0, 0, 32);
+  r16 = (uint16_t *) start;
+  if (r16 + index < (uint16_t *) rd.d_start) return r16[index];
+  if (r16 + index >= (uint16_t *) rd.d_top) return r16[index];
+  index -= (((uint16_t *) rd.d_start) - r16);
+  r8 = (uint8_t *) rd.d_start;
+  top = (uint8_t *) rd.d_top;
+  sub_size = (top-r8)/2;
+
+  a = h->base_gf->extract_word.w32(h->base_gf, r8, sub_size, index);
+  b = h->base_gf->extract_word.w32(h->base_gf, r8+sub_size, sub_size, index);
+  return (a | (b << 8));
+}
+
+static
+gf_val_32_t gf_w16_split_extract_word(gf_t *gf, void *start, int bytes, int index)
+{
+  uint16_t *r16, rv;
+  uint8_t *r8;
+  gf_region_data rd;
+
+  gf_set_region_data(&rd, gf, start, start, bytes, 0, 0, 32);
+  r16 = (uint16_t *) start;
+  if (r16 + index < (uint16_t *) rd.d_start) return r16[index];
+  if (r16 + index >= (uint16_t *) rd.d_top) return r16[index];
+  index -= (((uint16_t *) rd.d_start) - r16);
+  r8 = (uint8_t *) rd.d_start;
+  r8 += ((index & 0xfffffff0)*2);
+  r8 += (index & 0xf);
+  rv = (*r8 << 8);
+  r8 += 16;
+  rv |= *r8;
+  return rv;
+}
+
+static
+inline
+gf_val_32_t gf_w16_matrix (gf_t *gf, gf_val_32_t b)
+{
+  return gf_bitmatrix_inverse(b, 16, ((gf_internal_t *) (gf->scratch))->prim_poly);
+}
+
+/* JSP: GF_MULT_SHIFT: The world's dumbest multiplication algorithm.  I only
+   include it for completeness.  It does have the feature that it requires no
+   extra memory.  
+ */
+
+static
+inline
+gf_val_32_t
+gf_w16_clm_multiply_2 (gf_t *gf, gf_val_32_t a16, gf_val_32_t b16)
+{
+  gf_val_32_t rv = 0;
+
+#if defined(INTEL_SSE4_PCLMUL)
+
+  __m128i         a, b;
+  __m128i         result;
+  __m128i         prim_poly;
+  __m128i         w;
+  gf_internal_t * h = gf->scratch;
+
+  a = _mm_insert_epi32 (_mm_setzero_si128(), a16, 0);
+  b = _mm_insert_epi32 (a, b16, 0);
+
+  prim_poly = _mm_set_epi32(0, 0, 0, (uint32_t)(h->prim_poly & 0x1ffffULL));
+
+  /* Do the initial multiply */
+  
+  result = _mm_clmulepi64_si128 (a, b, 0);
+
+  /* Ben: Do prim_poly reduction twice. We are guaranteed that we will only
+     have to do the reduction at most twice, because (w-2)/z == 2. Where
+     z is equal to the number of zeros after the leading 1
+
+     _mm_clmulepi64_si128 is the carryless multiply operation. Here
+     _mm_srli_si128 shifts the result to the right by 2 bytes. This allows
+     us to multiply the prim_poly by the leading bits of the result. We
+     then xor the result of that operation back with the result.*/
+
+  w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 2), 0);
+  result = _mm_xor_si128 (result, w);
+  w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 2), 0);
+  result = _mm_xor_si128 (result, w);
+
+  /* Extracts 32 bit value from result. */
+  
+  rv = ((gf_val_32_t)_mm_extract_epi32(result, 0));
+
+
+#endif
+  return rv;
+}
+
+static
+inline
+gf_val_32_t
+gf_w16_clm_multiply_3 (gf_t *gf, gf_val_32_t a16, gf_val_32_t b16)
+{
+  gf_val_32_t rv = 0;
+
+#if defined(INTEL_SSE4_PCLMUL)
+
+  __m128i         a, b;
+  __m128i         result;
+  __m128i         prim_poly;
+  __m128i         w;
+  gf_internal_t * h = gf->scratch;
+
+  a = _mm_insert_epi32 (_mm_setzero_si128(), a16, 0);
+  b = _mm_insert_epi32 (a, b16, 0);
+
+  prim_poly = _mm_set_epi32(0, 0, 0, (uint32_t)(h->prim_poly & 0x1ffffULL));
+
+  /* Do the initial multiply */
+  
+  result = _mm_clmulepi64_si128 (a, b, 0);
+
+  w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 2), 0);
+  result = _mm_xor_si128 (result, w);
+  w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 2), 0);
+  result = _mm_xor_si128 (result, w);
+  w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 2), 0);
+  result = _mm_xor_si128 (result, w);
+
+  /* Extracts 32 bit value from result. */
+  
+  rv = ((gf_val_32_t)_mm_extract_epi32(result, 0));
+
+
+#endif
+  return rv;
+}
+
+static
+inline
+gf_val_32_t
+gf_w16_clm_multiply_4 (gf_t *gf, gf_val_32_t a16, gf_val_32_t b16)
+{
+  gf_val_32_t rv = 0;
+
+#if defined(INTEL_SSE4_PCLMUL)
+
+  __m128i         a, b;
+  __m128i         result;
+  __m128i         prim_poly;
+  __m128i         w;
+  gf_internal_t * h = gf->scratch;
+
+  a = _mm_insert_epi32 (_mm_setzero_si128(), a16, 0);
+  b = _mm_insert_epi32 (a, b16, 0);
+
+  prim_poly = _mm_set_epi32(0, 0, 0, (uint32_t)(h->prim_poly & 0x1ffffULL));
+
+  /* Do the initial multiply */
+  
+  result = _mm_clmulepi64_si128 (a, b, 0);
+
+  w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 2), 0);
+  result = _mm_xor_si128 (result, w);
+  w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 2), 0);
+  result = _mm_xor_si128 (result, w);
+  w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 2), 0);
+  result = _mm_xor_si128 (result, w);
+  w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 2), 0);
+  result = _mm_xor_si128 (result, w);
+
+  /* Extracts 32 bit value from result. */
+  
+  rv = ((gf_val_32_t)_mm_extract_epi32(result, 0));
+
+
+#endif
+  return rv;
+}
+
+
+static
+inline
+ gf_val_32_t
+gf_w16_shift_multiply (gf_t *gf, gf_val_32_t a16, gf_val_32_t b16)
+{
+  gf_val_32_t product, i, pp, a, b;
+  gf_internal_t *h;
+
+  a = a16;
+  b = b16;
+  h = (gf_internal_t *) gf->scratch;
+  pp = h->prim_poly;
+
+  product = 0;
+
+  for (i = 0; i < GF_FIELD_WIDTH; i++) { 
+    if (a & (1 << i)) product ^= (b << i);
+  }
+  for (i = (GF_FIELD_WIDTH*2-2); i >= GF_FIELD_WIDTH; i--) {
+    if (product & (1 << i)) product ^= (pp << (i-GF_FIELD_WIDTH)); 
+  }
+  return product;
+}
+
+static 
+int gf_w16_shift_init(gf_t *gf)
+{
+  gf->multiply.w32 = gf_w16_shift_multiply;
+  return 1;
+}
+
+static 
+int gf_w16_cfm_init(gf_t *gf)
+{
+#if defined(INTEL_SSE4_PCLMUL)
+  gf_internal_t *h;
+
+  h = (gf_internal_t *) gf->scratch;
+  
+  /*Ben: Determining how many reductions to do */
+  
+  if ((0xfe00 & h->prim_poly) == 0) {
+    gf->multiply.w32 = gf_w16_clm_multiply_2;
+    gf->multiply_region.w32 = gf_w16_clm_multiply_region_from_single_2;
+  } else if((0xf000 & h->prim_poly) == 0) {
+    gf->multiply.w32 = gf_w16_clm_multiply_3;
+    gf->multiply_region.w32 = gf_w16_clm_multiply_region_from_single_3;
+  } else if ((0xe000 & h->prim_poly) == 0) {
+    gf->multiply.w32 = gf_w16_clm_multiply_4;
+    gf->multiply_region.w32 = gf_w16_clm_multiply_region_from_single_4;
+  } else {
+    return 0;
+  } 
+  return 1;
+#endif
+
+  return 0;
+}
+
+/* KMG: GF_MULT_LOGTABLE: */
+
+static
+void
+gf_w16_log_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  uint16_t *s16, *d16;
+  int lv;
+  struct gf_w16_logtable_data *ltd;
+  gf_region_data rd;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 2);
+  gf_do_initial_region_alignment(&rd);
+
+  ltd = (struct gf_w16_logtable_data *) ((gf_internal_t *) gf->scratch)->private;
+  s16 = (uint16_t *) rd.s_start;
+  d16 = (uint16_t *) rd.d_start;
+
+  lv = ltd->log_tbl[val];
+
+  if (xor) {
+    while (d16 < (uint16_t *) rd.d_top) {
+      *d16 ^= (*s16 == 0 ? 0 : ltd->antilog_tbl[lv + ltd->log_tbl[*s16]]);
+      d16++;
+      s16++;
+    }
+  } else {
+    while (d16 < (uint16_t *) rd.d_top) {
+      *d16 = (*s16 == 0 ? 0 : ltd->antilog_tbl[lv + ltd->log_tbl[*s16]]);
+      d16++;
+      s16++;
+    }
+  }
+  gf_do_final_region_alignment(&rd);
+}
+
+static
+inline
+gf_val_32_t
+gf_w16_log_multiply(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  struct gf_w16_logtable_data *ltd;
+
+  ltd = (struct gf_w16_logtable_data *) ((gf_internal_t *) gf->scratch)->private;
+  return (a == 0 || b == 0) ? 0 : ltd->antilog_tbl[(int) ltd->log_tbl[a] + (int) ltd->log_tbl[b]];
+}
+
+static
+inline
+gf_val_32_t
+gf_w16_log_divide(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  int log_sum = 0;
+  struct gf_w16_logtable_data *ltd;
+
+  if (a == 0 || b == 0) return 0;
+  ltd = (struct gf_w16_logtable_data *) ((gf_internal_t *) gf->scratch)->private;
+
+  log_sum = (int) ltd->log_tbl[a] - (int) ltd->log_tbl[b];
+  return (ltd->d_antilog[log_sum]);
+}
+
+static
+gf_val_32_t
+gf_w16_log_inverse(gf_t *gf, gf_val_32_t a)
+{
+  struct gf_w16_logtable_data *ltd;
+
+  ltd = (struct gf_w16_logtable_data *) ((gf_internal_t *) gf->scratch)->private;
+  return (ltd->inv_tbl[a]);
+}
+
+static
+int gf_w16_log_init(gf_t *gf)
+{
+  gf_internal_t *h;
+  struct gf_w16_logtable_data *ltd;
+  int i, b;
+  int check = 0;
+
+  h = (gf_internal_t *) gf->scratch;
+  ltd = h->private;
+  
+  for (i = 0; i < GF_MULT_GROUP_SIZE+1; i++)
+    ltd->log_tbl[i] = 0;
+  ltd->d_antilog = ltd->antilog_tbl + GF_MULT_GROUP_SIZE;
+
+  b = 1;
+  for (i = 0; i < GF_MULT_GROUP_SIZE; i++) {
+      if (ltd->log_tbl[b] != 0) check = 1;
+      ltd->log_tbl[b] = i;
+      ltd->antilog_tbl[i] = b;
+      ltd->antilog_tbl[i+GF_MULT_GROUP_SIZE] = b;
+      b <<= 1;
+      if (b & GF_FIELD_SIZE) {
+          b = b ^ h->prim_poly;
+      }
+  }
+
+  /* If you can't construct the log table, there's a problem.  This code is used for
+     some other implementations (e.g. in SPLIT), so if the log table doesn't work in 
+     that instance, use CARRY_FREE / SHIFT instead. */
+
+  if (check) {
+    if (h->mult_type != GF_MULT_LOG_TABLE) {
+
+#if defined(INTEL_SSE4_PCLMUL)
+      return gf_w16_cfm_init(gf);
+#endif
+      return gf_w16_shift_init(gf);
+    } else {
+      _gf_errno = GF_E_LOGPOLY;
+      return 0;
+    }
+  }
+
+  ltd->inv_tbl[0] = 0;  /* Not really, but we need to fill it with something  */
+  ltd->inv_tbl[1] = 1;
+  for (i = 2; i < GF_FIELD_SIZE; i++) {
+    ltd->inv_tbl[i] = ltd->antilog_tbl[GF_MULT_GROUP_SIZE-ltd->log_tbl[i]];
+  }
+
+  gf->inverse.w32 = gf_w16_log_inverse;
+  gf->divide.w32 = gf_w16_log_divide;
+  gf->multiply.w32 = gf_w16_log_multiply;
+  gf->multiply_region.w32 = gf_w16_log_multiply_region;
+
+  return 1;
+}
+
+/* JSP: GF_MULT_SPLIT_TABLE: Using 8 multiplication tables to leverage SSE instructions.
+*/
+
+
+/* Ben: Does alternate mapping multiplication using a split table in the
+ lazy method without sse instructions*/
+
+static 
+void
+gf_w16_split_4_16_lazy_nosse_altmap_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  uint64_t i, j, c, prod;
+  uint8_t *s8, *d8, *top;
+  uint16_t table[4][16];
+  gf_region_data rd;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 32);
+  gf_do_initial_region_alignment(&rd);    
+
+  /*Ben: Constructs lazy multiplication table*/
+
+  for (j = 0; j < 16; j++) {
+    for (i = 0; i < 4; i++) {
+      c = (j << (i*4));
+      table[i][j] = gf->multiply.w32(gf, c, val);
+    }
+  }
+
+  /*Ben: s8 is the start of source, d8 is the start of dest, top is end of dest region. */
+  
+  s8 = (uint8_t *) rd.s_start;
+  d8 = (uint8_t *) rd.d_start;
+  top = (uint8_t *) rd.d_top;
+
+
+  while (d8 < top) {
+    
+    /*Ben: Multiplies across 16 two byte quantities using alternate mapping 
+       high bits are on the left, low bits are on the right. */
+  
+    for (j=0;j<16;j++) {
+    
+      /*Ben: If the xor flag is set, the product should include what is in dest */
+      prod = (xor) ? ((uint16_t)(*d8)<<8) ^ *(d8+16) : 0;
+
+      /*Ben: xors all 4 table lookups into the product variable*/
+      
+      prod ^= ((table[0][*(s8+16)&0xf]) ^
+          (table[1][(*(s8+16)&0xf0)>>4]) ^
+          (table[2][*(s8)&0xf]) ^
+          (table[3][(*(s8)&0xf0)>>4]));
+
+      /*Ben: Stores product in the destination and moves on*/
+      
+      *d8 = (uint8_t)(prod >> 8);
+      *(d8+16) = (uint8_t)(prod & 0x00ff);
+      s8++;
+      d8++;
+    }
+    s8+=16;
+    d8+=16;
+  }
+  gf_do_final_region_alignment(&rd);
+}
+
+static
+  void
+gf_w16_split_4_16_lazy_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  uint64_t i, j, a, c, prod;
+  uint16_t *s16, *d16, *top;
+  uint16_t table[4][16];
+  gf_region_data rd;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 2);
+  gf_do_initial_region_alignment(&rd);    
+
+  for (j = 0; j < 16; j++) {
+    for (i = 0; i < 4; i++) {
+      c = (j << (i*4));
+      table[i][j] = gf->multiply.w32(gf, c, val);
+    }
+  }
+
+  s16 = (uint16_t *) rd.s_start;
+  d16 = (uint16_t *) rd.d_start;
+  top = (uint16_t *) rd.d_top;
+
+  while (d16 < top) {
+    a = *s16;
+    prod = (xor) ? *d16 : 0;
+    for (i = 0; i < 4; i++) {
+      prod ^= table[i][a&0xf];
+      a >>= 4;
+    }
+    *d16 = prod;
+    s16++;
+    d16++;
+  }
+}
+
+static
+void
+gf_w16_split_8_16_lazy_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  uint64_t j, k, v, a, prod, *s64, *d64, *top64;
+  gf_internal_t *h;
+  uint64_t htable[256], ltable[256];
+  gf_region_data rd;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 8);
+  gf_do_initial_region_alignment(&rd);
+  
+  h = (gf_internal_t *) gf->scratch;
+
+  v = val;
+  ltable[0] = 0;
+  for (j = 1; j < 256; j <<= 1) {
+    for (k = 0; k < j; k++) ltable[k^j] = (v ^ ltable[k]);
+    v = GF_MULTBY_TWO(v);
+  }
+  htable[0] = 0;
+  for (j = 1; j < 256; j <<= 1) {
+    for (k = 0; k < j; k++) htable[k^j] = (v ^ htable[k]);
+    v = GF_MULTBY_TWO(v);
+  }
+
+  s64 = (uint64_t *) rd.s_start;
+  d64 = (uint64_t *) rd.d_start;
+  top64 = (uint64_t *) rd.d_top;
+  
+/* Does Unrolling Matter?  -- Doesn't seem to.
+  while (d64 != top64) {
+    a = *s64;
+
+    prod = htable[a >> 56];
+    a <<= 8;
+    prod ^= ltable[a >> 56];
+    a <<= 8;
+    prod <<= 16;
+
+    prod ^= htable[a >> 56];
+    a <<= 8;
+    prod ^= ltable[a >> 56];
+    a <<= 8;
+    prod <<= 16;
+
+    prod ^= htable[a >> 56];
+    a <<= 8;
+    prod ^= ltable[a >> 56];
+    a <<= 8;
+    prod <<= 16;
+
+    prod ^= htable[a >> 56];
+    a <<= 8;
+    prod ^= ltable[a >> 56];
+    prod ^= ((xor) ? *d64 : 0); 
+    *d64 = prod;
+    s64++;
+    d64++;
+  }
+*/
+  
+  while (d64 != top64) {
+    a = *s64;
+
+    prod = 0;
+    for (j = 0; j < 4; j++) {
+      prod <<= 16;
+      prod ^= htable[a >> 56];
+      a <<= 8;
+      prod ^= ltable[a >> 56];
+      a <<= 8;
+    }
+
+    //JSP: We can move the conditional outside the while loop, but we need to fully test it to understand which is better.
+   
+    prod ^= ((xor) ? *d64 : 0); 
+    *d64 = prod;
+    s64++;
+    d64++;
+  }
+  gf_do_final_region_alignment(&rd);
+}
+
+static void
+gf_w16_table_lazy_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  uint64_t c;
+  gf_internal_t *h;
+  struct gf_w16_lazytable_data *ltd;
+  gf_region_data rd;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 8);
+  gf_do_initial_region_alignment(&rd);
+
+  h = (gf_internal_t *) gf->scratch;
+  ltd = (struct gf_w16_lazytable_data *) h->private;
+
+  ltd->lazytable[0] = 0;
+
+  /*
+  a = val;
+  c = 1;
+  pp = h->prim_poly;
+
+  do {
+    ltd->lazytable[c] = a;
+    c <<= 1;
+    if (c & (1 << GF_FIELD_WIDTH)) c ^= pp;
+    a <<= 1;
+    if (a & (1 << GF_FIELD_WIDTH)) a ^= pp;
+  } while (c != 1);
+  */
+
+  for (c = 1; c < GF_FIELD_SIZE; c++) {
+    ltd->lazytable[c] = gf_w16_shift_multiply(gf, c, val);
+  }
+   
+  gf_two_byte_region_table_multiply(&rd, ltd->lazytable);
+  gf_do_final_region_alignment(&rd);
+}
+
+static
+void
+gf_w16_split_4_16_lazy_sse_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+#ifdef INTEL_SSSE3
+  uint64_t i, j, *s64, *d64, *top64;;
+  uint64_t c, prod;
+  uint8_t low[4][16];
+  uint8_t high[4][16];
+  gf_region_data rd;
+
+  __m128i  mask, ta, tb, ti, tpl, tph, tlow[4], thigh[4], tta, ttb, lmask;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 32);
+  gf_do_initial_region_alignment(&rd);
+
+  for (j = 0; j < 16; j++) {
+    for (i = 0; i < 4; i++) {
+      c = (j << (i*4));
+      prod = gf->multiply.w32(gf, c, val);
+      low[i][j] = (prod & 0xff);
+      high[i][j] = (prod >> 8);
+    }
+  }
+
+  for (i = 0; i < 4; i++) {
+    tlow[i] = _mm_loadu_si128((__m128i *)low[i]);
+    thigh[i] = _mm_loadu_si128((__m128i *)high[i]);
+  }
+
+  s64 = (uint64_t *) rd.s_start;
+  d64 = (uint64_t *) rd.d_start;
+  top64 = (uint64_t *) rd.d_top;
+
+  mask = _mm_set1_epi8 (0x0f);
+  lmask = _mm_set1_epi16 (0xff);
+
+  if (xor) {
+    while (d64 != top64) {
+      
+      ta = _mm_load_si128((__m128i *) s64);
+      tb = _mm_load_si128((__m128i *) (s64+2));
+
+      tta = _mm_srli_epi16(ta, 8);
+      ttb = _mm_srli_epi16(tb, 8);
+      tpl = _mm_and_si128(tb, lmask);
+      tph = _mm_and_si128(ta, lmask);
+
+      tb = _mm_packus_epi16(tpl, tph);
+      ta = _mm_packus_epi16(ttb, tta);
+
+      ti = _mm_and_si128 (mask, tb);
+      tph = _mm_shuffle_epi8 (thigh[0], ti);
+      tpl = _mm_shuffle_epi8 (tlow[0], ti);
+  
+      tb = _mm_srli_epi16(tb, 4);
+      ti = _mm_and_si128 (mask, tb);
+      tpl = _mm_xor_si128(_mm_shuffle_epi8 (tlow[1], ti), tpl);
+      tph = _mm_xor_si128(_mm_shuffle_epi8 (thigh[1], ti), tph);
+
+      ti = _mm_and_si128 (mask, ta);
+      tpl = _mm_xor_si128(_mm_shuffle_epi8 (tlow[2], ti), tpl);
+      tph = _mm_xor_si128(_mm_shuffle_epi8 (thigh[2], ti), tph);
+  
+      ta = _mm_srli_epi16(ta, 4);
+      ti = _mm_and_si128 (mask, ta);
+      tpl = _mm_xor_si128(_mm_shuffle_epi8 (tlow[3], ti), tpl);
+      tph = _mm_xor_si128(_mm_shuffle_epi8 (thigh[3], ti), tph);
+
+      ta = _mm_unpackhi_epi8(tpl, tph);
+      tb = _mm_unpacklo_epi8(tpl, tph);
+
+      tta = _mm_load_si128((__m128i *) d64);
+      ta = _mm_xor_si128(ta, tta);
+      ttb = _mm_load_si128((__m128i *) (d64+2));
+      tb = _mm_xor_si128(tb, ttb); 
+      _mm_store_si128 ((__m128i *)d64, ta);
+      _mm_store_si128 ((__m128i *)(d64+2), tb);
+
+      d64 += 4;
+      s64 += 4;
+      
+    }
+  } else {
+    while (d64 != top64) {
+      
+      ta = _mm_load_si128((__m128i *) s64);
+      tb = _mm_load_si128((__m128i *) (s64+2));
+
+      tta = _mm_srli_epi16(ta, 8);
+      ttb = _mm_srli_epi16(tb, 8);
+      tpl = _mm_and_si128(tb, lmask);
+      tph = _mm_and_si128(ta, lmask);
+
+      tb = _mm_packus_epi16(tpl, tph);
+      ta = _mm_packus_epi16(ttb, tta);
+
+      ti = _mm_and_si128 (mask, tb);
+      tph = _mm_shuffle_epi8 (thigh[0], ti);
+      tpl = _mm_shuffle_epi8 (tlow[0], ti);
+  
+      tb = _mm_srli_epi16(tb, 4);
+      ti = _mm_and_si128 (mask, tb);
+      tpl = _mm_xor_si128(_mm_shuffle_epi8 (tlow[1], ti), tpl);
+      tph = _mm_xor_si128(_mm_shuffle_epi8 (thigh[1], ti), tph);
+
+      ti = _mm_and_si128 (mask, ta);
+      tpl = _mm_xor_si128(_mm_shuffle_epi8 (tlow[2], ti), tpl);
+      tph = _mm_xor_si128(_mm_shuffle_epi8 (thigh[2], ti), tph);
+  
+      ta = _mm_srli_epi16(ta, 4);
+      ti = _mm_and_si128 (mask, ta);
+      tpl = _mm_xor_si128(_mm_shuffle_epi8 (tlow[3], ti), tpl);
+      tph = _mm_xor_si128(_mm_shuffle_epi8 (thigh[3], ti), tph);
+
+      ta = _mm_unpackhi_epi8(tpl, tph);
+      tb = _mm_unpacklo_epi8(tpl, tph);
+
+      _mm_store_si128 ((__m128i *)d64, ta);
+      _mm_store_si128 ((__m128i *)(d64+2), tb);
+
+      d64 += 4;
+      s64 += 4;
+    }
+  }
+
+  gf_do_final_region_alignment(&rd);
+#endif
+}
+
+static
+void
+gf_w16_split_4_16_lazy_sse_altmap_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+#ifdef INTEL_SSSE3
+  uint64_t i, j, *s64, *d64, *top64;;
+  uint64_t c, prod;
+  uint8_t low[4][16];
+  uint8_t high[4][16];
+  gf_region_data rd;
+  __m128i  mask, ta, tb, ti, tpl, tph, tlow[4], thigh[4];
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 32);
+  gf_do_initial_region_alignment(&rd);
+
+  for (j = 0; j < 16; j++) {
+    for (i = 0; i < 4; i++) {
+      c = (j << (i*4));
+      prod = gf->multiply.w32(gf, c, val);
+      low[i][j] = (prod & 0xff);
+      high[i][j] = (prod >> 8);
+    }
+  }
+
+  for (i = 0; i < 4; i++) {
+    tlow[i] = _mm_loadu_si128((__m128i *)low[i]);
+    thigh[i] = _mm_loadu_si128((__m128i *)high[i]);
+  }
+
+  s64 = (uint64_t *) rd.s_start;
+  d64 = (uint64_t *) rd.d_start;
+  top64 = (uint64_t *) rd.d_top;
+
+  mask = _mm_set1_epi8 (0x0f);
+
+  if (xor) {
+    while (d64 != top64) {
+
+      ta = _mm_load_si128((__m128i *) s64);
+      tb = _mm_load_si128((__m128i *) (s64+2));
+
+      ti = _mm_and_si128 (mask, tb);
+      tph = _mm_shuffle_epi8 (thigh[0], ti);
+      tpl = _mm_shuffle_epi8 (tlow[0], ti);
+  
+      tb = _mm_srli_epi16(tb, 4);
+      ti = _mm_and_si128 (mask, tb);
+      tpl = _mm_xor_si128(_mm_shuffle_epi8 (tlow[1], ti), tpl);
+      tph = _mm_xor_si128(_mm_shuffle_epi8 (thigh[1], ti), tph);
+
+      ti = _mm_and_si128 (mask, ta);
+      tpl = _mm_xor_si128(_mm_shuffle_epi8 (tlow[2], ti), tpl);
+      tph = _mm_xor_si128(_mm_shuffle_epi8 (thigh[2], ti), tph);
+  
+      ta = _mm_srli_epi16(ta, 4);
+      ti = _mm_and_si128 (mask, ta);
+      tpl = _mm_xor_si128(_mm_shuffle_epi8 (tlow[3], ti), tpl);
+      tph = _mm_xor_si128(_mm_shuffle_epi8 (thigh[3], ti), tph);
+
+      ta = _mm_load_si128((__m128i *) d64);
+      tph = _mm_xor_si128(tph, ta);
+      _mm_store_si128 ((__m128i *)d64, tph);
+      tb = _mm_load_si128((__m128i *) (d64+2));
+      tpl = _mm_xor_si128(tpl, tb);
+      _mm_store_si128 ((__m128i *)(d64+2), tpl);
+
+      d64 += 4;
+      s64 += 4;
+    }
+  } else {
+    while (d64 != top64) {
+
+      ta = _mm_load_si128((__m128i *) s64);
+      tb = _mm_load_si128((__m128i *) (s64+2));
+
+      ti = _mm_and_si128 (mask, tb);
+      tph = _mm_shuffle_epi8 (thigh[0], ti);
+      tpl = _mm_shuffle_epi8 (tlow[0], ti);
+  
+      tb = _mm_srli_epi16(tb, 4);
+      ti = _mm_and_si128 (mask, tb);
+      tpl = _mm_xor_si128(_mm_shuffle_epi8 (tlow[1], ti), tpl);
+      tph = _mm_xor_si128(_mm_shuffle_epi8 (thigh[1], ti), tph);
+
+      ti = _mm_and_si128 (mask, ta);
+      tpl = _mm_xor_si128(_mm_shuffle_epi8 (tlow[2], ti), tpl);
+      tph = _mm_xor_si128(_mm_shuffle_epi8 (thigh[2], ti), tph);
+  
+      ta = _mm_srli_epi16(ta, 4);
+      ti = _mm_and_si128 (mask, ta);
+      tpl = _mm_xor_si128(_mm_shuffle_epi8 (tlow[3], ti), tpl);
+      tph = _mm_xor_si128(_mm_shuffle_epi8 (thigh[3], ti), tph);
+
+      _mm_store_si128 ((__m128i *)d64, tph);
+      _mm_store_si128 ((__m128i *)(d64+2), tpl);
+
+      d64 += 4;
+      s64 += 4;
+      
+    }
+  }
+  gf_do_final_region_alignment(&rd);
+
+#endif
+}
+
+uint32_t 
+gf_w16_split_8_8_multiply(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  uint32_t alow, blow;
+  struct gf_w16_split_8_8_data *d8;
+  gf_internal_t *h;
+
+  h = (gf_internal_t *) gf->scratch;
+  d8 = (struct gf_w16_split_8_8_data *) h->private;
+
+  alow = a & 0xff;
+  blow = b & 0xff;
+  a >>= 8;
+  b >>= 8;
+
+  return d8->tables[0][alow][blow] ^
+         d8->tables[1][alow][b] ^
+         d8->tables[1][a][blow] ^
+         d8->tables[2][a][b];
+}
+
+static 
+int gf_w16_split_init(gf_t *gf)
+{
+  gf_internal_t *h;
+  struct gf_w16_split_8_8_data *d8;
+  int i, j, exp, issse3;
+  uint32_t p, basep;
+
+  h = (gf_internal_t *) gf->scratch;
+
+issse3 = 0;
+#ifdef INTEL_SSSE3
+  issse3 = 1;
+#endif
+
+  if (h->arg1 == 8 && h->arg2 == 8) {
+    d8 = (struct gf_w16_split_8_8_data *) h->private;
+    basep = 1;
+    for (exp = 0; exp < 3; exp++) {
+      for (j = 0; j < 256; j++) d8->tables[exp][0][j] = 0;
+      for (i = 0; i < 256; i++) d8->tables[exp][i][0] = 0;
+      d8->tables[exp][1][1] = basep;
+      for (i = 2; i < 256; i++) {
+        if (i&1) {
+          p = d8->tables[exp][i^1][1];
+          d8->tables[exp][i][1] = p ^ basep;
+        } else {
+          p = d8->tables[exp][i>>1][1];
+          d8->tables[exp][i][1] = GF_MULTBY_TWO(p);
+        }
+      }
+      for (i = 1; i < 256; i++) {
+        p = d8->tables[exp][i][1];
+        for (j = 1; j < 256; j++) {
+          if (j&1) {
+            d8->tables[exp][i][j] = d8->tables[exp][i][j^1] ^ p;
+          } else {
+            d8->tables[exp][i][j] = GF_MULTBY_TWO(d8->tables[exp][i][j>>1]);
+          }
+        }
+      }
+      for (i = 0; i < 8; i++) basep = GF_MULTBY_TWO(basep);
+    }
+    gf->multiply.w32 = gf_w16_split_8_8_multiply;
+    gf->multiply_region.w32 = gf_w16_split_8_16_lazy_multiply_region;
+    return 1;
+
+  }
+
+  /* We'll be using LOG for multiplication, unless the pp isn't primitive.
+     In that case, we'll be using SHIFT. */
+
+  gf_w16_log_init(gf);
+
+  /* Defaults */
+
+  if (issse3) {
+    gf->multiply_region.w32 = gf_w16_split_4_16_lazy_sse_multiply_region;
+  } else {
+    gf->multiply_region.w32 = gf_w16_split_8_16_lazy_multiply_region;
+  }
+
+
+  if ((h->arg1 == 8 && h->arg2 == 16) || (h->arg2 == 8 && h->arg1 == 16)) {
+    gf->multiply_region.w32 = gf_w16_split_8_16_lazy_multiply_region;
+
+  } else if ((h->arg1 == 4 && h->arg2 == 16) || (h->arg2 == 4 && h->arg1 == 16)) {
+    if (issse3) {
+      if(h->region_type & GF_REGION_ALTMAP && h->region_type & GF_REGION_NOSSE)
+        gf->multiply_region.w32 = gf_w16_split_4_16_lazy_nosse_altmap_multiply_region;
+      else if(h->region_type & GF_REGION_NOSSE)
+        gf->multiply_region.w32 = gf_w16_split_4_16_lazy_multiply_region;
+      else if(h->region_type & GF_REGION_ALTMAP)
+        gf->multiply_region.w32 = gf_w16_split_4_16_lazy_sse_altmap_multiply_region;
+    } else {
+      if(h->region_type & GF_REGION_SSE)
+        return 0;
+      else if(h->region_type & GF_REGION_ALTMAP)
+        gf->multiply_region.w32 = gf_w16_split_4_16_lazy_nosse_altmap_multiply_region;
+      else
+        gf->multiply_region.w32 = gf_w16_split_4_16_lazy_multiply_region;
+    }
+  }
+
+  return 1;
+}
+
+static 
+int gf_w16_table_init(gf_t *gf)
+{
+  gf_w16_log_init(gf);
+
+  gf->multiply_region.w32 = gf_w16_table_lazy_multiply_region; 
+  return 1;
+}
+
+static
+void
+gf_w16_log_zero_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  uint16_t lv;
+  int i;
+  uint16_t *s16, *d16, *top16;
+  struct gf_w16_zero_logtable_data *ltd;
+  gf_region_data rd;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 2);
+  gf_do_initial_region_alignment(&rd);
+
+  ltd = (struct gf_w16_zero_logtable_data*) ((gf_internal_t *) gf->scratch)->private;
+  s16 = (uint16_t *) rd.s_start;
+  d16 = (uint16_t *) rd.d_start;
+  top16 = (uint16_t *) rd.d_top;
+  bytes = top16 - d16;
+
+  lv = ltd->log_tbl[val];
+
+  if (xor) {
+    for (i = 0; i < bytes; i++) {
+      d16[i] ^= (ltd->antilog_tbl[lv + ltd->log_tbl[s16[i]]]);
+    }
+  } else {
+    for (i = 0; i < bytes; i++) {
+      d16[i] = (ltd->antilog_tbl[lv + ltd->log_tbl[s16[i]]]);
+    }
+  }
+
+  /* This isn't necessary. */
+  
+  gf_do_final_region_alignment(&rd);
+}
+
+/* Here -- double-check Kevin */
+
+static
+inline
+gf_val_32_t
+gf_w16_log_zero_multiply (gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  struct gf_w16_zero_logtable_data *ltd;
+
+  ltd = (struct gf_w16_zero_logtable_data *) ((gf_internal_t *) gf->scratch)->private;
+  return ltd->antilog_tbl[ltd->log_tbl[a] + ltd->log_tbl[b]];
+}
+
+static
+inline
+gf_val_32_t
+gf_w16_log_zero_divide (gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  int log_sum = 0;
+  struct gf_w16_zero_logtable_data *ltd;
+
+  if (a == 0 || b == 0) return 0;
+  ltd = (struct gf_w16_zero_logtable_data *) ((gf_internal_t *) gf->scratch)->private;
+
+  log_sum = ltd->log_tbl[a] - ltd->log_tbl[b] + (GF_MULT_GROUP_SIZE);
+  return (ltd->antilog_tbl[log_sum]);
+}
+
+static
+gf_val_32_t
+gf_w16_log_zero_inverse (gf_t *gf, gf_val_32_t a)
+{
+  struct gf_w16_zero_logtable_data *ltd;
+
+  ltd = (struct gf_w16_zero_logtable_data *) ((gf_internal_t *) gf->scratch)->private;
+  return (ltd->inv_tbl[a]);
+}
+
+static
+inline
+gf_val_32_t
+gf_w16_bytwo_p_multiply (gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  uint32_t prod, pp, pmask, amask;
+  gf_internal_t *h;
+  
+  h = (gf_internal_t *) gf->scratch;
+  pp = h->prim_poly;
+
+  
+  prod = 0;
+  pmask = 0x8000;
+  amask = 0x8000;
+
+  while (amask != 0) {
+    if (prod & pmask) {
+      prod = ((prod << 1) ^ pp);
+    } else {
+      prod <<= 1;
+    }
+    if (a & amask) prod ^= b;
+    amask >>= 1;
+  }
+  return prod;
+}
+
+static
+inline
+gf_val_32_t
+gf_w16_bytwo_b_multiply (gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  uint32_t prod, pp, bmask;
+  gf_internal_t *h;
+  
+  h = (gf_internal_t *) gf->scratch;
+  pp = h->prim_poly;
+
+  prod = 0;
+  bmask = 0x8000;
+
+  while (1) {
+    if (a & 1) prod ^= b;
+    a >>= 1;
+    if (a == 0) return prod;
+    if (b & bmask) {
+      b = ((b << 1) ^ pp);
+    } else {
+      b <<= 1;
+    }
+  }
+}
+
+static
+void 
+gf_w16_bytwo_p_nosse_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  uint64_t *s64, *d64, t1, t2, ta, prod, amask;
+  gf_region_data rd;
+  struct gf_w16_bytwo_data *btd;
+    
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  btd = (struct gf_w16_bytwo_data *) ((gf_internal_t *) (gf->scratch))->private;
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 8);
+  gf_do_initial_region_alignment(&rd);
+
+  s64 = (uint64_t *) rd.s_start;
+  d64 = (uint64_t *) rd.d_start;
+
+  if (xor) {
+    while (s64 < (uint64_t *) rd.s_top) {
+      prod = 0;
+      amask = 0x8000;
+      ta = *s64;
+      while (amask != 0) {
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, prod, t1, t2);
+        if (val & amask) prod ^= ta;
+        amask >>= 1;
+      }
+      *d64 ^= prod;
+      d64++;
+      s64++;
+    }
+  } else { 
+    while (s64 < (uint64_t *) rd.s_top) {
+      prod = 0;
+      amask = 0x8000;
+      ta = *s64;
+      while (amask != 0) {
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, prod, t1, t2);
+        if (val & amask) prod ^= ta;
+        amask >>= 1;
+      }
+      *d64 = prod;
+      d64++;
+      s64++;
+    }
+  }
+  gf_do_final_region_alignment(&rd);
+}
+
+#define BYTWO_P_ONESTEP {\
+      SSE_AB2(pp, m1 ,m2, prod, t1, t2); \
+      t1 = _mm_and_si128(v, one); \
+      t1 = _mm_sub_epi16(t1, one); \
+      t1 = _mm_and_si128(t1, ta); \
+      prod = _mm_xor_si128(prod, t1); \
+      v = _mm_srli_epi64(v, 1); }
+
+#ifdef INTEL_SSE2
+static
+void 
+gf_w16_bytwo_p_sse_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  int i;
+  uint8_t *s8, *d8;
+  uint32_t vrev;
+  __m128i pp, m1, m2, ta, prod, t1, t2, tp, one, v;
+  struct gf_w16_bytwo_data *btd;
+  gf_region_data rd;
+    
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  btd = (struct gf_w16_bytwo_data *) ((gf_internal_t *) (gf->scratch))->private;
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 16);
+  gf_do_initial_region_alignment(&rd);
+
+  vrev = 0;
+  for (i = 0; i < 16; i++) {
+    vrev <<= 1;
+    if (!(val & (1 << i))) vrev |= 1;
+  }
+
+  s8 = (uint8_t *) rd.s_start;
+  d8 = (uint8_t *) rd.d_start;
+
+  pp = _mm_set1_epi16(btd->prim_poly&0xffff);
+  m1 = _mm_set1_epi16((btd->mask1)&0xffff);
+  m2 = _mm_set1_epi16((btd->mask2)&0xffff);
+  one = _mm_set1_epi16(1);
+
+  while (d8 < (uint8_t *) rd.d_top) {
+    prod = _mm_setzero_si128();
+    v = _mm_set1_epi16(vrev);
+    ta = _mm_load_si128((__m128i *) s8);
+    tp = (!xor) ? _mm_setzero_si128() : _mm_load_si128((__m128i *) d8);
+    BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP;
+    _mm_store_si128((__m128i *) d8, _mm_xor_si128(prod, tp));
+    d8 += 16;
+    s8 += 16;
+  }
+  gf_do_final_region_alignment(&rd);
+}
+#endif
+
+#ifdef INTEL_SSE2
+static
+void
+gf_w16_bytwo_b_sse_region_2_noxor(gf_region_data *rd, struct gf_w16_bytwo_data *btd)
+{
+  uint8_t *d8, *s8;
+  __m128i pp, m1, m2, t1, t2, va;
+
+  s8 = (uint8_t *) rd->s_start;
+  d8 = (uint8_t *) rd->d_start;
+
+  pp = _mm_set1_epi16(btd->prim_poly&0xffff);
+  m1 = _mm_set1_epi16((btd->mask1)&0xffff);
+  m2 = _mm_set1_epi16((btd->mask2)&0xffff);
+
+  while (d8 < (uint8_t *) rd->d_top) {
+    va = _mm_load_si128 ((__m128i *)(s8));
+    SSE_AB2(pp, m1, m2, va, t1, t2);
+    _mm_store_si128((__m128i *)d8, va);
+    d8 += 16;
+    s8 += 16;
+  }
+}
+#endif
+
+#ifdef INTEL_SSE2
+static
+void
+gf_w16_bytwo_b_sse_region_2_xor(gf_region_data *rd, struct gf_w16_bytwo_data *btd)
+{
+  uint8_t *d8, *s8;
+  __m128i pp, m1, m2, t1, t2, va, vb;
+
+  s8 = (uint8_t *) rd->s_start;
+  d8 = (uint8_t *) rd->d_start;
+
+  pp = _mm_set1_epi16(btd->prim_poly&0xffff);
+  m1 = _mm_set1_epi16((btd->mask1)&0xffff);
+  m2 = _mm_set1_epi16((btd->mask2)&0xffff);
+
+  while (d8 < (uint8_t *) rd->d_top) {
+    va = _mm_load_si128 ((__m128i *)(s8));
+    SSE_AB2(pp, m1, m2, va, t1, t2);
+    vb = _mm_load_si128 ((__m128i *)(d8));
+    vb = _mm_xor_si128(vb, va);
+    _mm_store_si128((__m128i *)d8, vb);
+    d8 += 16;
+    s8 += 16;
+  }
+}
+#endif
+
+
+#ifdef INTEL_SSE2
+static
+void 
+gf_w16_bytwo_b_sse_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  int itb;
+  uint8_t *d8, *s8;
+  __m128i pp, m1, m2, t1, t2, va, vb;
+  struct gf_w16_bytwo_data *btd;
+  gf_region_data rd;
+    
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 16);
+  gf_do_initial_region_alignment(&rd);
+
+  btd = (struct gf_w16_bytwo_data *) ((gf_internal_t *) (gf->scratch))->private;
+
+  if (val == 2) {
+    if (xor) {
+      gf_w16_bytwo_b_sse_region_2_xor(&rd, btd);
+    } else {
+      gf_w16_bytwo_b_sse_region_2_noxor(&rd, btd);
+    }
+    gf_do_final_region_alignment(&rd);
+    return;
+  }
+
+  s8 = (uint8_t *) rd.s_start;
+  d8 = (uint8_t *) rd.d_start;
+
+  pp = _mm_set1_epi16(btd->prim_poly&0xffff);
+  m1 = _mm_set1_epi16((btd->mask1)&0xffff);
+  m2 = _mm_set1_epi16((btd->mask2)&0xffff);
+
+  while (d8 < (uint8_t *) rd.d_top) {
+    va = _mm_load_si128 ((__m128i *)(s8));
+    vb = (!xor) ? _mm_setzero_si128() : _mm_load_si128 ((__m128i *)(d8));
+    itb = val;
+    while (1) {
+      if (itb & 1) vb = _mm_xor_si128(vb, va);
+      itb >>= 1;
+      if (itb == 0) break;
+      SSE_AB2(pp, m1, m2, va, t1, t2);
+    }
+    _mm_store_si128((__m128i *)d8, vb);
+    d8 += 16;
+    s8 += 16;
+  }
+
+  gf_do_final_region_alignment(&rd);
+}
+#endif
+
+static
+void 
+gf_w16_bytwo_b_nosse_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  uint64_t *s64, *d64, t1, t2, ta, tb, prod;
+  struct gf_w16_bytwo_data *btd;
+  gf_region_data rd;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 16);
+  gf_do_initial_region_alignment(&rd);
+
+  btd = (struct gf_w16_bytwo_data *) ((gf_internal_t *) (gf->scratch))->private;
+  s64 = (uint64_t *) rd.s_start;
+  d64 = (uint64_t *) rd.d_start;
+
+  switch (val) {
+  case 2:
+    if (xor) {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 ^= ta;
+        d64++;
+        s64++;
+      }
+    } else {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 = ta;
+        d64++;
+        s64++;
+      }
+    }
+    break; 
+  case 3:
+    if (xor) {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        prod = ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 ^= (ta ^ prod);
+        d64++;
+        s64++;
+      }
+    } else {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        prod = ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 = (ta ^ prod);
+        d64++;
+        s64++;
+      }
+    }
+    break; 
+  case 4:
+    if (xor) {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 ^= ta;
+        d64++;
+        s64++;
+      }
+    } else {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 = ta;
+        d64++;
+        s64++;
+      }
+    }
+    break; 
+  case 5:
+    if (xor) {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        prod = ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 ^= (ta ^ prod);
+        d64++;
+        s64++;
+      }
+    } else {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        prod = ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 = ta ^ prod;
+        d64++;
+        s64++;
+      }
+    }
+  default:
+    if (xor) {
+      while (d64 < (uint64_t *) rd.d_top) {
+        prod = *d64 ;
+        ta = *s64;
+        tb = val;
+        while (1) {
+          if (tb & 1) prod ^= ta;
+          tb >>= 1;
+          if (tb == 0) break;
+          AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        }
+        *d64 = prod;
+        d64++;
+        s64++;
+      }
+    } else {
+      while (d64 < (uint64_t *) rd.d_top) {
+        prod = 0 ;
+        ta = *s64;
+        tb = val;
+        while (1) {
+          if (tb & 1) prod ^= ta;
+          tb >>= 1;
+          if (tb == 0) break;
+          AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        }
+        *d64 = prod;
+        d64++;
+        s64++;
+      }
+    }
+    break;
+  }
+  gf_do_final_region_alignment(&rd);
+}
+
+static
+int gf_w16_bytwo_init(gf_t *gf)
+{
+  gf_internal_t *h;
+  uint64_t ip, m1, m2;
+  struct gf_w16_bytwo_data *btd;
+
+  h = (gf_internal_t *) gf->scratch;
+  btd = (struct gf_w16_bytwo_data *) (h->private);
+  ip = h->prim_poly & 0xffff;
+  m1 = 0xfffe;
+  m2 = 0x8000;
+  btd->prim_poly = 0;
+  btd->mask1 = 0;
+  btd->mask2 = 0;
+
+  while (ip != 0) {
+    btd->prim_poly |= ip;
+    btd->mask1 |= m1;
+    btd->mask2 |= m2;
+    ip <<= GF_FIELD_WIDTH;
+    m1 <<= GF_FIELD_WIDTH;
+    m2 <<= GF_FIELD_WIDTH;
+  }
+
+  if (h->mult_type == GF_MULT_BYTWO_p) {
+    gf->multiply.w32 = gf_w16_bytwo_p_multiply;
+    #ifdef INTEL_SSE2
+      if (h->region_type & GF_REGION_NOSSE)
+        gf->multiply_region.w32 = gf_w16_bytwo_p_nosse_multiply_region;
+      else
+        gf->multiply_region.w32 = gf_w16_bytwo_p_sse_multiply_region;
+    #else
+      gf->multiply_region.w32 = gf_w16_bytwo_p_nosse_multiply_region;
+      if(h->region_type & GF_REGION_SSE)
+        return 0;
+    #endif
+  } else {
+    gf->multiply.w32 = gf_w16_bytwo_b_multiply;
+    #ifdef INTEL_SSE2
+      if (h->region_type & GF_REGION_NOSSE)
+        gf->multiply_region.w32 = gf_w16_bytwo_b_nosse_multiply_region;
+      else
+        gf->multiply_region.w32 = gf_w16_bytwo_b_sse_multiply_region;
+    #else
+      gf->multiply_region.w32 = gf_w16_bytwo_b_nosse_multiply_region;
+      if(h->region_type & GF_REGION_SSE)
+        return 0;
+    #endif
+  }
+
+  return 1;
+}
+
+static
+int gf_w16_log_zero_init(gf_t *gf)
+{
+  gf_internal_t *h;
+  struct gf_w16_zero_logtable_data *ltd;
+  int i, b;
+
+  h = (gf_internal_t *) gf->scratch;
+  ltd = h->private;
+
+  ltd->log_tbl[0] = (-GF_MULT_GROUP_SIZE) + 1;
+
+  bzero(&(ltd->_antilog_tbl[0]), sizeof(ltd->_antilog_tbl));
+
+  ltd->antilog_tbl = &(ltd->_antilog_tbl[GF_FIELD_SIZE * 2]);
+
+  b = 1;
+  for (i = 0; i < GF_MULT_GROUP_SIZE; i++) {
+      ltd->log_tbl[b] = (uint16_t)i;
+      ltd->antilog_tbl[i] = (uint16_t)b;
+      ltd->antilog_tbl[i+GF_MULT_GROUP_SIZE] = (uint16_t)b;
+      b <<= 1;
+      if (b & GF_FIELD_SIZE) {
+          b = b ^ h->prim_poly;
+      }
+  }
+  ltd->inv_tbl[0] = 0;  /* Not really, but we need to fill it with something  */
+  ltd->inv_tbl[1] = 1;
+  for (i = 2; i < GF_FIELD_SIZE; i++) {
+    ltd->inv_tbl[i] = ltd->antilog_tbl[GF_MULT_GROUP_SIZE-ltd->log_tbl[i]];
+  }
+
+  gf->inverse.w32 = gf_w16_log_zero_inverse;
+  gf->divide.w32 = gf_w16_log_zero_divide;
+  gf->multiply.w32 = gf_w16_log_zero_multiply;
+  gf->multiply_region.w32 = gf_w16_log_zero_multiply_region;
+  return 1;
+}
+
+static
+gf_val_32_t
+gf_w16_composite_multiply_recursive(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  gf_t *base_gf = h->base_gf;
+  uint8_t b0 = b & 0x00ff;
+  uint8_t b1 = (b & 0xff00) >> 8;
+  uint8_t a0 = a & 0x00ff;
+  uint8_t a1 = (a & 0xff00) >> 8;
+  uint8_t a1b1;
+  uint16_t rv;
+
+  a1b1 = base_gf->multiply.w32(base_gf, a1, b1);
+
+  rv = ((base_gf->multiply.w32(base_gf, a0, b0) ^ a1b1) | ((base_gf->multiply.w32(base_gf, a1, b0) ^ base_gf->multiply.w32(base_gf, a0, b1) ^ base_gf->multiply.w32(base_gf, a1b1, h->prim_poly)) << 8));
+  return rv;
+}
+
+static
+gf_val_32_t
+gf_w16_composite_multiply_inline(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  uint8_t b0 = b & 0x00ff;
+  uint8_t b1 = (b & 0xff00) >> 8;
+  uint8_t a0 = a & 0x00ff;
+  uint8_t a1 = (a & 0xff00) >> 8;
+  uint8_t a1b1, *mt;
+  uint16_t rv;
+  struct gf_w16_composite_data *cd;
+
+  cd = (struct gf_w16_composite_data *) h->private;
+  mt = cd->mult_table;
+
+  a1b1 = GF_W8_INLINE_MULTDIV(mt, a1, b1);
+
+  rv = ((GF_W8_INLINE_MULTDIV(mt, a0, b0) ^ a1b1) | ((GF_W8_INLINE_MULTDIV(mt, a1, b0) ^ GF_W8_INLINE_MULTDIV(mt, a0, b1) ^ GF_W8_INLINE_MULTDIV(mt, a1b1, h->prim_poly)) << 8));
+  return rv;
+}
+
+/*
+ * Composite field division trick (explained in 2007 tech report)
+ *
+ * Compute a / b = a*b^-1, where p(x) = x^2 + sx + 1
+ *
+ * let c = b^-1
+ *
+ * c*b = (s*b1c1+b1c0+b0c1)x+(b1c1+b0c0)
+ *
+ * want (s*b1c1+b1c0+b0c1) = 0 and (b1c1+b0c0) = 1
+ *
+ * let d = b1c1 and d+1 = b0c0
+ *
+ * solve s*b1c1+b1c0+b0c1 = 0
+ *
+ * solution: d = (b1b0^-1)(b1b0^-1+b0b1^-1+s)^-1
+ *
+ * c0 = (d+1)b0^-1
+ * c1 = d*b1^-1
+ *
+ * a / b = a * c
+ */
+
+static
+gf_val_32_t
+gf_w16_composite_inverse(gf_t *gf, gf_val_32_t a)
+{
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  gf_t *base_gf = h->base_gf;
+  uint8_t a0 = a & 0x00ff;
+  uint8_t a1 = (a & 0xff00) >> 8;
+  uint8_t c0, c1, d, tmp;
+  uint16_t c;
+  uint8_t a0inv, a1inv;
+
+  if (a0 == 0) {
+    a1inv = base_gf->inverse.w32(base_gf, a1);
+    c0 = base_gf->multiply.w32(base_gf, a1inv, h->prim_poly);
+    c1 = a1inv;
+  } else if (a1 == 0) {
+    c0 = base_gf->inverse.w32(base_gf, a0);
+    c1 = 0;
+  } else {
+    a1inv = base_gf->inverse.w32(base_gf, a1);
+    a0inv = base_gf->inverse.w32(base_gf, a0);
+
+    d = base_gf->multiply.w32(base_gf, a1, a0inv);
+
+    tmp = (base_gf->multiply.w32(base_gf, a1, a0inv) ^ base_gf->multiply.w32(base_gf, a0, a1inv) ^ h->prim_poly);
+    tmp = base_gf->inverse.w32(base_gf, tmp);
+
+    d = base_gf->multiply.w32(base_gf, d, tmp);
+
+    c0 = base_gf->multiply.w32(base_gf, (d^1), a0inv);
+    c1 = base_gf->multiply.w32(base_gf, d, a1inv);
+  }
+
+  c = c0 | (c1 << 8);
+
+  return c;
+}
+
+static
+void
+gf_w16_composite_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  gf_t *base_gf = h->base_gf;
+  uint8_t b0 = val & 0x00ff;
+  uint8_t b1 = (val & 0xff00) >> 8;
+  uint16_t *s16, *d16, *top;
+  uint8_t a0, a1, a1b1, *mt;
+  gf_region_data rd;
+  struct gf_w16_composite_data *cd;
+
+  cd = (struct gf_w16_composite_data *) h->private;
+  mt = cd->mult_table;
+  
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 2);
+
+  s16 = rd.s_start;
+  d16 = rd.d_start;
+  top = rd.d_top;
+
+  if (mt == NULL) {
+    if (xor) {
+      while (d16 < top) {
+        a0 = (*s16) & 0x00ff;
+        a1 = ((*s16) & 0xff00) >> 8;
+        a1b1 = base_gf->multiply.w32(base_gf, a1, b1);
+  
+        (*d16) ^= ((base_gf->multiply.w32(base_gf, a0, b0) ^ a1b1) |
+                  ((base_gf->multiply.w32(base_gf, a1, b0) ^ 
+                    base_gf->multiply.w32(base_gf, a0, b1) ^ 
+                    base_gf->multiply.w32(base_gf, a1b1, h->prim_poly)) << 8));
+        s16++;
+        d16++;
+      }
+    } else {
+      while (d16 < top) {
+        a0 = (*s16) & 0x00ff;
+        a1 = ((*s16) & 0xff00) >> 8;
+        a1b1 = base_gf->multiply.w32(base_gf, a1, b1);
+  
+        (*d16) = ((base_gf->multiply.w32(base_gf, a0, b0) ^ a1b1) |
+                  ((base_gf->multiply.w32(base_gf, a1, b0) ^ 
+                    base_gf->multiply.w32(base_gf, a0, b1) ^ 
+                    base_gf->multiply.w32(base_gf, a1b1, h->prim_poly)) << 8));
+        s16++;
+        d16++;
+      }
+    }
+  } else {
+    if (xor) {
+      while (d16 < top) {
+        a0 = (*s16) & 0x00ff;
+        a1 = ((*s16) & 0xff00) >> 8;
+        a1b1 = GF_W8_INLINE_MULTDIV(mt, a1, b1);
+  
+        (*d16) ^= ((GF_W8_INLINE_MULTDIV(mt, a0, b0) ^ a1b1) |
+                  ((GF_W8_INLINE_MULTDIV(mt, a1, b0) ^ 
+                    GF_W8_INLINE_MULTDIV(mt, a0, b1) ^ 
+                    GF_W8_INLINE_MULTDIV(mt, a1b1, h->prim_poly)) << 8));
+        s16++;
+        d16++;
+      }
+    } else {
+      while (d16 < top) {
+        a0 = (*s16) & 0x00ff;
+        a1 = ((*s16) & 0xff00) >> 8;
+        a1b1 = GF_W8_INLINE_MULTDIV(mt, a1, b1);
+  
+        (*d16) = ((GF_W8_INLINE_MULTDIV(mt, a0, b0) ^ a1b1) |
+                  ((GF_W8_INLINE_MULTDIV(mt, a1, b0) ^ 
+                    GF_W8_INLINE_MULTDIV(mt, a0, b1) ^ 
+                    GF_W8_INLINE_MULTDIV(mt, a1b1, h->prim_poly)) << 8));
+        s16++;
+        d16++;
+      }
+    }
+  }
+}
+
+static
+void
+gf_w16_composite_multiply_region_alt(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  gf_t *base_gf = h->base_gf;
+  uint8_t val0 = val & 0x00ff;
+  uint8_t val1 = (val & 0xff00) >> 8;
+  gf_region_data rd;
+  int sub_reg_size;
+  uint8_t *slow, *shigh;
+  uint8_t *dlow, *dhigh, *top;;
+
+  /* JSP: I want the two pointers aligned wrt each other on 16 byte 
+     boundaries.  So I'm going to make sure that the area on 
+     which the two operate is a multiple of 32. Of course, that 
+     junks up the mapping, but so be it -- that's why we have extract_word.... */
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 32);
+  gf_do_initial_region_alignment(&rd);
+
+  slow = (uint8_t *) rd.s_start;
+  dlow = (uint8_t *) rd.d_start;
+  top = (uint8_t *)  rd.d_top;
+  sub_reg_size = (top - dlow)/2;
+  shigh = slow + sub_reg_size;
+  dhigh = dlow + sub_reg_size;
+
+  base_gf->multiply_region.w32(base_gf, slow, dlow, val0, sub_reg_size, xor);
+  base_gf->multiply_region.w32(base_gf, shigh, dlow, val1, sub_reg_size, 1);
+  base_gf->multiply_region.w32(base_gf, slow, dhigh, val1, sub_reg_size, xor);
+  base_gf->multiply_region.w32(base_gf, shigh, dhigh, val0, sub_reg_size, 1);
+  base_gf->multiply_region.w32(base_gf, shigh, dhigh, base_gf->multiply.w32(base_gf, h->prim_poly, val1), sub_reg_size, 1);
+
+  gf_do_final_region_alignment(&rd);
+}
+
+static
+int gf_w16_composite_init(gf_t *gf)
+{
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  struct gf_w16_composite_data *cd;
+
+  if (h->base_gf == NULL) return 0;
+
+  cd = (struct gf_w16_composite_data *) h->private;
+  cd->mult_table = gf_w8_get_mult_table(h->base_gf);
+
+  if (h->region_type & GF_REGION_ALTMAP) {
+    gf->multiply_region.w32 = gf_w16_composite_multiply_region_alt;
+  } else {
+    gf->multiply_region.w32 = gf_w16_composite_multiply_region;
+  }
+
+  if (cd->mult_table == NULL) {
+    gf->multiply.w32 = gf_w16_composite_multiply_recursive;
+  } else {
+    gf->multiply.w32 = gf_w16_composite_multiply_inline;
+  }
+  gf->divide.w32 = NULL;
+  gf->inverse.w32 = gf_w16_composite_inverse;
+
+  return 1;
+}
+
+static
+void
+gf_w16_group_4_set_shift_tables(uint16_t *shift, uint16_t val, gf_internal_t *h)
+{
+  int i, j;
+
+  shift[0] = 0;
+  for (i = 0; i < 16; i += 2) {
+    j = (shift[i>>1] << 1);
+    if (j & (1 << 16)) j ^= h->prim_poly;
+    shift[i] = j;
+    shift[i^1] = j^val;
+  }
+}
+
+static
+inline
+gf_val_32_t
+gf_w16_group_4_4_multiply(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  uint16_t p, l, ind, r, a16;
+
+  struct gf_w16_group_4_4_data *d44;
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+
+  d44 = (struct gf_w16_group_4_4_data *) h->private;
+  gf_w16_group_4_set_shift_tables(d44->shift, b, h);
+
+  a16 = a;
+  ind = a16 >> 12;
+  a16 <<= 4;
+  p = d44->shift[ind];
+  r = p & 0xfff;
+  l = p >> 12;
+  ind = a16 >> 12;
+  a16 <<= 4;
+  p = (d44->shift[ind] ^ d44->reduce[l] ^ (r << 4));
+  r = p & 0xfff;
+  l = p >> 12;
+  ind = a16 >> 12;
+  a16 <<= 4;
+  p = (d44->shift[ind] ^ d44->reduce[l] ^ (r << 4));
+  r = p & 0xfff;
+  l = p >> 12;
+  ind = a16 >> 12;
+  p = (d44->shift[ind] ^ d44->reduce[l] ^ (r << 4));
+  return p;
+}
+
+static
+void gf_w16_group_4_4_region_multiply(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  uint16_t p, l, ind, r, a16, p16;
+  struct gf_w16_group_4_4_data *d44;
+  gf_region_data rd;
+  uint16_t *s16, *d16, *top;
+  
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  d44 = (struct gf_w16_group_4_4_data *) h->private;
+  gf_w16_group_4_set_shift_tables(d44->shift, val, h);
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 2);
+  gf_do_initial_region_alignment(&rd);
+
+  s16 = (uint16_t *) rd.s_start;
+  d16 = (uint16_t *) rd.d_start;
+  top = (uint16_t *) rd.d_top;
+
+  while (d16 < top) {
+    p = 0;
+    a16 = *s16;
+    p16 = (xor) ? *d16 : 0;
+    ind = a16 >> 12;
+    a16 <<= 4;
+    p = d44->shift[ind];
+    r = p & 0xfff;
+    l = p >> 12;
+    ind = a16 >> 12;
+    a16 <<= 4;
+    p = (d44->shift[ind] ^ d44->reduce[l] ^ (r << 4));
+    r = p & 0xfff;
+    l = p >> 12;
+    ind = a16 >> 12;
+    a16 <<= 4;
+    p = (d44->shift[ind] ^ d44->reduce[l] ^ (r << 4));
+    r = p & 0xfff;
+    l = p >> 12;
+    ind = a16 >> 12;
+    p = (d44->shift[ind] ^ d44->reduce[l] ^ (r << 4));
+    p ^= p16;
+    *d16 = p;
+    d16++;
+    s16++;
+  }
+  gf_do_final_region_alignment(&rd);
+}
+
+static
+int gf_w16_group_init(gf_t *gf)
+{
+  int i, j, p;
+  struct gf_w16_group_4_4_data *d44;
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+
+  d44 = (struct gf_w16_group_4_4_data *) h->private;
+  d44->reduce[0] = 0;
+  for (i = 0; i < 16; i++) {
+    p = 0;
+    for (j = 0; j < 4; j++) {
+      if (i & (1 << j)) p ^= (h->prim_poly << j);
+    }
+    d44->reduce[p>>16] = (p&0xffff);
+  }
+
+  gf->multiply.w32 = gf_w16_group_4_4_multiply;
+  gf->divide.w32 = NULL;
+  gf->inverse.w32 = NULL;
+  gf->multiply_region.w32 = gf_w16_group_4_4_region_multiply;
+
+  return 1;
+}
+
+int gf_w16_scratch_size(int mult_type, int region_type, int divide_type, int arg1, int arg2)
+{
+  switch(mult_type)
+  {
+    case GF_MULT_TABLE:
+      return sizeof(gf_internal_t) + sizeof(struct gf_w16_lazytable_data) + 64;
+      break;
+    case GF_MULT_BYTWO_p:
+    case GF_MULT_BYTWO_b:
+      return sizeof(gf_internal_t) + sizeof(struct gf_w16_bytwo_data);
+      break;
+    case GF_MULT_LOG_ZERO:
+      return sizeof(gf_internal_t) + sizeof(struct gf_w16_zero_logtable_data) + 64;
+      break;
+    case GF_MULT_LOG_TABLE:
+      return sizeof(gf_internal_t) + sizeof(struct gf_w16_logtable_data) + 64;
+      break;
+    case GF_MULT_DEFAULT:
+    case GF_MULT_SPLIT_TABLE: 
+      if (arg1 == 8 && arg2 == 8) {
+        return sizeof(gf_internal_t) + sizeof(struct gf_w16_split_8_8_data) + 64;
+      } else if ((arg1 == 8 && arg2 == 16) || (arg2 == 8 && arg1 == 16)) {
+        return sizeof(gf_internal_t) + sizeof(struct gf_w16_logtable_data) + 64;
+      } else if (mult_type == GF_MULT_DEFAULT || 
+                 (arg1 == 4 && arg2 == 16) || (arg2 == 4 && arg1 == 16)) {
+        return sizeof(gf_internal_t) + sizeof(struct gf_w16_logtable_data) + 64;
+      }
+      return 0;
+      break;
+    case GF_MULT_GROUP:     
+      return sizeof(gf_internal_t) + sizeof(struct gf_w16_group_4_4_data) + 64;
+      break;
+    case GF_MULT_CARRY_FREE:
+      return sizeof(gf_internal_t);
+      break;
+    case GF_MULT_SHIFT:
+      return sizeof(gf_internal_t);
+      break;
+    case GF_MULT_COMPOSITE:
+      return sizeof(gf_internal_t) + sizeof(struct gf_w16_composite_data) + 64;
+      break;
+
+    default:
+      return 0;
+   }
+   return 0;
+}
+
+int gf_w16_init(gf_t *gf)
+{
+  gf_internal_t *h;
+
+  h = (gf_internal_t *) gf->scratch;
+
+  /* Allen: set default primitive polynomial / irreducible polynomial if needed */
+
+  if (h->prim_poly == 0) {
+    if (h->mult_type == GF_MULT_COMPOSITE) {
+      h->prim_poly = gf_composite_get_default_poly(h->base_gf);
+      if (h->prim_poly == 0) return 0;
+    } else { 
+
+     /* Allen: use the following primitive polynomial to make 
+               carryless multiply work more efficiently for GF(2^16).
+
+        h->prim_poly = 0x1002d;
+
+        The following is the traditional primitive polynomial for GF(2^16) */
+
+      h->prim_poly = 0x1100b;
+    } 
+  }
+
+  if (h->mult_type != GF_MULT_COMPOSITE) h->prim_poly |= (1 << 16);
+
+  gf->multiply.w32 = NULL;
+  gf->divide.w32 = NULL;
+  gf->inverse.w32 = NULL;
+  gf->multiply_region.w32 = NULL;
+
+  switch(h->mult_type) {
+    case GF_MULT_LOG_ZERO:    if (gf_w16_log_zero_init(gf) == 0) return 0; break;
+    case GF_MULT_LOG_TABLE:   if (gf_w16_log_init(gf) == 0) return 0; break;
+    case GF_MULT_DEFAULT: 
+    case GF_MULT_SPLIT_TABLE: if (gf_w16_split_init(gf) == 0) return 0; break;
+    case GF_MULT_TABLE:       if (gf_w16_table_init(gf) == 0) return 0; break;
+    case GF_MULT_CARRY_FREE:  if (gf_w16_cfm_init(gf) == 0) return 0; break;
+    case GF_MULT_SHIFT:       if (gf_w16_shift_init(gf) == 0) return 0; break;
+    case GF_MULT_COMPOSITE:   if (gf_w16_composite_init(gf) == 0) return 0; break;
+    case GF_MULT_BYTWO_p: 
+    case GF_MULT_BYTWO_b:     if (gf_w16_bytwo_init(gf) == 0) return 0; break;
+    case GF_MULT_GROUP:       if (gf_w16_group_init(gf) == 0) return 0; break;
+    default: return 0;
+  }
+  if (h->divide_type == GF_DIVIDE_EUCLID) {
+    gf->divide.w32 = gf_w16_divide_from_inverse;
+    gf->inverse.w32 = gf_w16_euclid;
+  } else if (h->divide_type == GF_DIVIDE_MATRIX) {
+    gf->divide.w32 = gf_w16_divide_from_inverse;
+    gf->inverse.w32 = gf_w16_matrix;
+  }
+
+  if (gf->divide.w32 == NULL) {
+    gf->divide.w32 = gf_w16_divide_from_inverse;
+    if (gf->inverse.w32 == NULL) gf->inverse.w32 = gf_w16_euclid;
+  }
+
+  if (gf->inverse.w32 == NULL)  gf->inverse.w32 = gf_w16_inverse_from_divide;
+
+  if (h->region_type & GF_REGION_ALTMAP) {
+    if (h->mult_type == GF_MULT_COMPOSITE) {
+      gf->extract_word.w32 = gf_w16_composite_extract_word;
+    } else {
+      gf->extract_word.w32 = gf_w16_split_extract_word;
+    }
+  } else if (h->region_type == GF_REGION_CAUCHY) {
+    gf->multiply_region.w32 = gf_wgen_cauchy_region;
+    gf->extract_word.w32 = gf_wgen_extract_word;
+  } else {
+    gf->extract_word.w32 = gf_w16_extract_word;
+  }
+  if (gf->multiply_region.w32 == NULL) {
+    gf->multiply_region.w32 = gf_w16_multiply_region_from_single;
+  }
+  return 1;
+}
+
+/* Inline setup functions */
+
+uint16_t *gf_w16_get_log_table(gf_t *gf)
+{
+  struct gf_w16_logtable_data *ltd;
+
+  if (gf->multiply.w32 == gf_w16_log_multiply) {
+    ltd = (struct gf_w16_logtable_data *) ((gf_internal_t *) gf->scratch)->private;
+    return (uint16_t *) ltd->log_tbl;
+  }
+  return NULL;
+}
+
+uint16_t *gf_w16_get_mult_alog_table(gf_t *gf)
+{
+  gf_internal_t *h;
+  struct gf_w16_logtable_data *ltd;
+
+  h = (gf_internal_t *) gf->scratch;
+  if (gf->multiply.w32 == gf_w16_log_multiply) {
+    ltd = (struct gf_w16_logtable_data *) h->private;
+    return (uint16_t *) ltd->antilog_tbl;
+  }
+  return NULL;
+}
+
+uint16_t *gf_w16_get_div_alog_table(gf_t *gf)
+{
+  gf_internal_t *h;
+  struct gf_w16_logtable_data *ltd;
+
+  h = (gf_internal_t *) gf->scratch;
+  if (gf->multiply.w32 == gf_w16_log_multiply) {
+    ltd = (struct gf_w16_logtable_data *) h->private;
+    return (uint16_t *) ltd->d_antilog;
+  }
+  return NULL;
+}
diff --git a/src/erasure-code/jerasure/gf-complete/src/gf_w32.c b/src/erasure-code/jerasure/gf-complete/src/gf_w32.c
new file mode 100644
index 0000000..1503c72
--- /dev/null
+++ b/src/erasure-code/jerasure/gf-complete/src/gf_w32.c
@@ -0,0 +1,2741 @@
+/*
+ * GF-Complete: A Comprehensive Open Source Library for Galois Field Arithmetic
+ * James S. Plank, Ethan L. Miller, Kevin M. Greenan,
+ * Benjamin A. Arnold, John A. Burnum, Adam W. Disney, Allen C. McBride.
+ *
+ * gf_w32.c
+ *
+ * Routines for 32-bit Galois fields
+ */
+
+
+#include "gf_int.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+#define GF_FIELD_WIDTH (32)
+#define GF_FIRST_BIT (1 << 31)
+
+#define GF_BASE_FIELD_WIDTH (16)
+#define GF_BASE_FIELD_SIZE       (1 << GF_BASE_FIELD_WIDTH)
+#define GF_BASE_FIELD_GROUP_SIZE  GF_BASE_FIELD_SIZE-1
+#define GF_MULTBY_TWO(p) (((p) & GF_FIRST_BIT) ? (((p) << 1) ^ h->prim_poly) : (p) << 1)
+
+struct gf_split_2_32_lazy_data {
+    uint32_t      tables[16][4];
+    uint32_t      last_value;
+};
+
+struct gf_w32_split_8_8_data {
+    uint32_t      tables[7][256][256];
+    uint32_t      region_tables[4][256];
+    uint32_t      last_value;
+};
+
+struct gf_w32_group_data {
+    uint32_t *reduce;
+    uint32_t *shift;
+    int      tshift;
+    uint64_t rmask;
+    uint32_t *memory;
+};
+
+struct gf_split_16_32_lazy_data {
+    uint32_t      tables[2][(1<<16)];
+    uint32_t      last_value;
+};
+
+struct gf_split_8_32_lazy_data {
+    uint32_t      tables[4][256];
+    uint32_t      last_value;
+};
+
+struct gf_split_4_32_lazy_data {
+    uint32_t      tables[8][16];
+    uint32_t      last_value;
+};
+
+struct gf_w32_bytwo_data {
+    uint64_t prim_poly;
+    uint64_t mask1;
+    uint64_t mask2;
+};
+
+struct gf_w32_composite_data {
+  uint16_t *log;
+  uint16_t *alog;
+};
+
+#define MM_PRINT32(s, r) { uint8_t blah[16], ii; printf("%-12s", s); _mm_storeu_si128((__m128i *)blah, r); for (ii = 0; ii < 16; ii += 4) printf(" %02x%02x%02x%02x", blah[15-ii], blah[14-ii], blah[13-ii], blah[12-ii]); printf("\n"); }
+
+#define MM_PRINT8(s, r) { uint8_t blah[16], ii; printf("%-12s", s); _mm_storeu_si128((__m128i *)blah, r); for (ii = 0; ii < 16; ii += 1) printf("%s%02x", (ii%4==0) ? "   " : " ", blah[15-ii]); printf("\n"); }
+
+#define AB2(ip, am1 ,am2, b, t1, t2) {\
+  t1 = (b << 1) & am1;\
+  t2 = b & am2; \
+  t2 = ((t2 << 1) - (t2 >> (GF_FIELD_WIDTH-1))); \
+  b = (t1 ^ (t2 & ip));}
+
+#define SSE_AB2(pp, m1 ,m2, va, t1, t2) {\
+          t1 = _mm_and_si128(_mm_slli_epi64(va, 1), m1); \
+          t2 = _mm_and_si128(va, m2); \
+          t2 = _mm_sub_epi64 (_mm_slli_epi64(t2, 1), _mm_srli_epi64(t2, (GF_FIELD_WIDTH-1))); \
+          va = _mm_xor_si128(t1, _mm_and_si128(t2, pp)); }
+
+static
+inline
+uint32_t gf_w32_inverse_from_divide (gf_t *gf, uint32_t a)
+{
+  return gf->divide.w32(gf, 1, a);
+}
+
+static
+inline
+uint32_t gf_w32_divide_from_inverse (gf_t *gf, uint32_t a, uint32_t b)
+{
+  b = gf->inverse.w32(gf, b);
+  return gf->multiply.w32(gf, a, b);
+}
+
+static
+void
+gf_w32_multiply_region_from_single(gf_t *gf, void *src, void *dest, uint32_t val, int bytes, int 
+xor)
+{
+  int i;
+  uint32_t *s32;
+  uint32_t *d32;
+   
+  s32 = (uint32_t *) src;
+  d32 = (uint32_t *) dest; 
+ 
+  if (xor) {
+    for (i = 0; i < bytes/sizeof(uint32_t); i++) {
+      d32[i] ^= gf->multiply.w32(gf, val, s32[i]);
+    } 
+  } else {
+    for (i = 0; i < bytes/sizeof(uint32_t); i++) {
+      d32[i] = gf->multiply.w32(gf, val, s32[i]);
+    } 
+  }
+}
+
+#if defined(INTEL_SSE4_PCLMUL)
+
+static 
+void
+gf_w32_clm_multiply_region_from_single_2(gf_t *gf, void *src, void *dest, uint32_t val, int bytes, int xor)
+{
+
+  int i;
+  uint32_t *s32;
+  uint32_t *d32;
+  
+  __m128i         a, b;
+  __m128i         result;
+  __m128i         prim_poly;
+  __m128i         w;
+  gf_internal_t * h = gf->scratch;
+  
+  prim_poly = _mm_set_epi32(0, 0, 1, (uint32_t)(h->prim_poly & 0xffffffffULL));
+   
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  a = _mm_insert_epi32 (_mm_setzero_si128(), val, 0);
+  s32 = (uint32_t *) src;
+  d32 = (uint32_t *) dest; 
+ 
+  if (xor) {
+    for (i = 0; i < bytes/sizeof(uint32_t); i++) {
+      b = _mm_insert_epi32 (a, s32[i], 0);
+      result = _mm_clmulepi64_si128 (a, b, 0);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 4), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 4), 0);
+      result = _mm_xor_si128 (result, w);
+      d32[i] ^= ((gf_val_32_t)_mm_extract_epi32(result, 0));
+    } 
+  } else {
+    for (i = 0; i < bytes/sizeof(uint32_t); i++) {
+      b = _mm_insert_epi32 (a, s32[i], 0);
+      result = _mm_clmulepi64_si128 (a, b, 0);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 4), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 4), 0);
+      result = _mm_xor_si128 (result, w);
+      d32[i] = ((gf_val_32_t)_mm_extract_epi32(result, 0));
+    } 
+  }
+}
+#endif
+
+#if defined(INTEL_SSE4_PCLMUL) 
+
+static 
+void
+gf_w32_clm_multiply_region_from_single_3(gf_t *gf, void *src, void *dest, uint32_t val, int bytes, int xor)
+{
+
+  int i;
+  uint32_t *s32;
+  uint32_t *d32;
+  
+  __m128i         a, b;
+  __m128i         result;
+  __m128i         prim_poly;
+  __m128i         w;
+  gf_internal_t * h = gf->scratch;
+  
+  prim_poly = _mm_set_epi32(0, 0, 1, (uint32_t)(h->prim_poly & 0xffffffffULL));
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+  
+  a = _mm_insert_epi32 (_mm_setzero_si128(), val, 0);
+  
+  s32 = (uint32_t *) src;
+  d32 = (uint32_t *) dest; 
+ 
+  if (xor) {
+    for (i = 0; i < bytes/sizeof(uint32_t); i++) {
+      b = _mm_insert_epi32 (a, s32[i], 0);
+      result = _mm_clmulepi64_si128 (a, b, 0);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 4), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 4), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 4), 0);
+      result = _mm_xor_si128 (result, w);
+      d32[i] ^= ((gf_val_32_t)_mm_extract_epi32(result, 0));
+    } 
+  } else {
+    for (i = 0; i < bytes/sizeof(uint32_t); i++) {
+      b = _mm_insert_epi32 (a, s32[i], 0);
+      result = _mm_clmulepi64_si128 (a, b, 0);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 4), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 4), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 4), 0);
+      result = _mm_xor_si128 (result, w);
+      d32[i] = ((gf_val_32_t)_mm_extract_epi32(result, 0));
+    } 
+  }
+}
+#endif
+
+#if defined(INTEL_SSE4_PCLMUL)
+static 
+void
+gf_w32_clm_multiply_region_from_single_4(gf_t *gf, void *src, void *dest, uint32_t val, int bytes, int xor)
+{
+  int i;
+  uint32_t *s32;
+  uint32_t *d32;
+  
+  __m128i         a, b;
+  __m128i         result;
+  __m128i         prim_poly;
+  __m128i         w;
+  gf_internal_t * h = gf->scratch;
+  
+  prim_poly = _mm_set_epi32(0, 0, 1, (uint32_t)(h->prim_poly & 0xffffffffULL));
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+  
+  a = _mm_insert_epi32 (_mm_setzero_si128(), val, 0);
+  
+  s32 = (uint32_t *) src;
+  d32 = (uint32_t *) dest; 
+ 
+  if (xor) {
+    for (i = 0; i < bytes/sizeof(uint32_t); i++) {
+      b = _mm_insert_epi32 (a, s32[i], 0);
+      result = _mm_clmulepi64_si128 (a, b, 0);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 4), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 4), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 4), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 4), 0);
+      result = _mm_xor_si128 (result, w);
+      d32[i] ^= ((gf_val_32_t)_mm_extract_epi32(result, 0));
+    } 
+  } else {
+    for (i = 0; i < bytes/sizeof(uint32_t); i++) {
+      b = _mm_insert_epi32 (a, s32[i], 0);
+      result = _mm_clmulepi64_si128 (a, b, 0);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 4), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 4), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 4), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 4), 0);
+      result = _mm_xor_si128 (result, w);
+      d32[i] = ((gf_val_32_t)_mm_extract_epi32(result, 0));
+    } 
+  }
+}
+#endif
+
+static
+inline
+uint32_t gf_w32_euclid (gf_t *gf, uint32_t b)
+{
+  uint32_t e_i, e_im1, e_ip1;
+  uint32_t d_i, d_im1, d_ip1;
+  uint32_t y_i, y_im1, y_ip1;
+  uint32_t c_i;
+
+  if (b == 0) return -1;
+  e_im1 = ((gf_internal_t *) (gf->scratch))->prim_poly; 
+  e_i = b;
+  d_im1 = 32;
+  for (d_i = d_im1-1; ((1 << d_i) & e_i) == 0; d_i--) ;
+  y_i = 1;
+  y_im1 = 0;
+
+  while (e_i != 1) {
+
+    e_ip1 = e_im1;
+    d_ip1 = d_im1;
+    c_i = 0;
+
+    while (d_ip1 >= d_i) {
+      c_i ^= (1 << (d_ip1 - d_i));
+      e_ip1 ^= (e_i << (d_ip1 - d_i));
+      d_ip1--;
+      if (e_ip1 == 0) return 0;
+      while ((e_ip1 & (1 << d_ip1)) == 0) d_ip1--;
+    }
+
+    y_ip1 = y_im1 ^ gf->multiply.w32(gf, c_i, y_i);
+    y_im1 = y_i;
+    y_i = y_ip1;
+
+    e_im1 = e_i;
+    d_im1 = d_i;
+    e_i = e_ip1;
+    d_i = d_ip1;
+  }
+
+  return y_i;
+}
+
+static
+gf_val_32_t gf_w32_extract_word(gf_t *gf, void *start, int bytes, int index)
+{
+  uint32_t *r32, rv;
+
+  r32 = (uint32_t *) start;
+  rv = r32[index];
+  return rv;
+}
+
+static
+gf_val_32_t gf_w32_composite_extract_word(gf_t *gf, void *start, int bytes, int index)
+{
+  int sub_size;
+  gf_internal_t *h;
+  uint8_t *r8, *top;
+  uint32_t a, b, *r32;
+  gf_region_data rd;
+
+  h = (gf_internal_t *) gf->scratch;
+  gf_set_region_data(&rd, gf, start, start, bytes, 0, 0, 32);
+  r32 = (uint32_t *) start;
+  if (r32 + index < (uint32_t *) rd.d_start) return r32[index];
+  if (r32 + index >= (uint32_t *) rd.d_top) return r32[index];
+  index -= (((uint32_t *) rd.d_start) - r32);
+  r8 = (uint8_t *) rd.d_start;
+  top = (uint8_t *) rd.d_top;
+  sub_size = (top-r8)/2;
+
+  a = h->base_gf->extract_word.w32(h->base_gf, r8, sub_size, index);
+  b = h->base_gf->extract_word.w32(h->base_gf, r8+sub_size, sub_size, index);
+  return (a | (b << 16));
+}
+
+static
+gf_val_32_t gf_w32_split_extract_word(gf_t *gf, void *start, int bytes, int index)
+{
+  int i;
+  uint32_t *r32, rv;
+  uint8_t *r8;
+  gf_region_data rd;
+
+  gf_set_region_data(&rd, gf, start, start, bytes, 0, 0, 64);
+  r32 = (uint32_t *) start;
+  if (r32 + index < (uint32_t *) rd.d_start) return r32[index];
+  if (r32 + index >= (uint32_t *) rd.d_top) return r32[index];
+  index -= (((uint32_t *) rd.d_start) - r32);
+  r8 = (uint8_t *) rd.d_start;
+  r8 += ((index & 0xfffffff0)*4);
+  r8 += (index & 0xf);
+  r8 += 48;
+  rv =0;
+  for (i = 0; i < 4; i++) {
+    rv <<= 8;
+    rv |= *r8;
+    r8 -= 16;
+  }
+  return rv;
+}
+
+
+static
+inline
+uint32_t gf_w32_matrix (gf_t *gf, uint32_t b)
+{
+  return gf_bitmatrix_inverse(b, 32, ((gf_internal_t *) (gf->scratch))->prim_poly);
+}
+
+/* JSP: GF_MULT_SHIFT: The world's dumbest multiplication algorithm.  I only
+   include it for completeness.  It does have the feature that it requires no
+   extra memory.  
+*/
+
+
+
+
+static
+inline
+gf_val_32_t
+gf_w32_clm_multiply_2 (gf_t *gf, gf_val_32_t a32, gf_val_32_t b32)
+{
+  gf_val_32_t rv = 0;
+
+#if defined(INTEL_SSE4_PCLMUL)
+
+  __m128i         a, b;
+  __m128i         result;
+  __m128i         prim_poly;
+  __m128i         w;
+  gf_internal_t * h = gf->scratch;
+
+
+  a = _mm_insert_epi32 (_mm_setzero_si128(), a32, 0);
+  b = _mm_insert_epi32 (a, b32, 0);
+  
+  prim_poly = _mm_set_epi32(0, 0, 1, (uint32_t)(h->prim_poly & 0xffffffffULL));
+  
+  /* Do the initial multiply */
+
+  result = _mm_clmulepi64_si128 (a, b, 0);
+
+  /* Ben: Do prim_poly reduction twice. We are guaranteed that we will only
+     have to do the reduction at most twice, because (w-2)/z == 2. Where
+     z is equal to the number of zeros after the leading 1 
+
+   _mm_clmulepi64_si128 is the carryless multiply operation. Here
+   _mm_srli_si128 shifts the result to the right by 4 bytes. This allows
+   us to multiply the prim_poly by the leading bits of the result. We
+   then xor the result of that operation back with the result.*/
+
+  w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 4), 0);
+  result = _mm_xor_si128 (result, w);
+  w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 4), 0);
+  result = _mm_xor_si128 (result, w);
+
+  /* Extracts 32 bit value from result. */
+  rv = ((gf_val_32_t)_mm_extract_epi32(result, 0));
+#endif
+  return rv;
+}
+static
+inline
+gf_val_32_t
+gf_w32_clm_multiply_3 (gf_t *gf, gf_val_32_t a32, gf_val_32_t b32)
+{
+  gf_val_32_t rv = 0;
+
+#if defined(INTEL_SSE4_PCLMUL)
+
+  __m128i         a, b;
+  __m128i         result;
+  __m128i         prim_poly;
+  __m128i         w;
+  gf_internal_t * h = gf->scratch;
+
+
+  a = _mm_insert_epi32 (_mm_setzero_si128(), a32, 0);
+  b = _mm_insert_epi32 (a, b32, 0);
+
+  prim_poly = _mm_set_epi32(0, 0, 1, (uint32_t)(h->prim_poly & 0xffffffffULL));
+
+  /* Do the initial multiply */
+  
+  result = _mm_clmulepi64_si128 (a, b, 0);
+
+  w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 4), 0);
+  result = _mm_xor_si128 (result, w);
+  w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 4), 0);
+  result = _mm_xor_si128 (result, w);
+  w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 4), 0);
+  result = _mm_xor_si128 (result, w);
+
+  /* Extracts 32 bit value from result. */
+  
+  rv = ((gf_val_32_t)_mm_extract_epi32(result, 0));
+#endif
+  return rv;
+}
+
+static
+inline
+gf_val_32_t
+gf_w32_clm_multiply_4 (gf_t *gf, gf_val_32_t a32, gf_val_32_t b32)
+{
+  gf_val_32_t rv = 0;
+
+#if defined(INTEL_SSE4_PCLMUL)
+
+  __m128i         a, b;
+  __m128i         result;
+  __m128i         prim_poly;
+  __m128i         w;
+  gf_internal_t * h = gf->scratch;
+
+
+  a = _mm_insert_epi32 (_mm_setzero_si128(), a32, 0);
+  b = _mm_insert_epi32 (a, b32, 0);
+
+  prim_poly = _mm_set_epi32(0, 0, 1, (uint32_t)(h->prim_poly & 0xffffffffULL));
+
+  /* Do the initial multiply */
+  
+  result = _mm_clmulepi64_si128 (a, b, 0);
+
+  w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 4), 0);
+  result = _mm_xor_si128 (result, w);
+  w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 4), 0);
+  result = _mm_xor_si128 (result, w);
+  w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 4), 0);
+  result = _mm_xor_si128 (result, w);
+  w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 4), 0);
+  result = _mm_xor_si128 (result, w);
+
+  /* Extracts 32 bit value from result. */
+  
+  rv = ((gf_val_32_t)_mm_extract_epi32(result, 0));
+#endif
+  return rv;
+}
+
+
+static
+inline
+uint32_t
+gf_w32_shift_multiply (gf_t *gf, uint32_t a32, uint32_t b32)
+{
+  uint64_t product, i, pp, a, b, one;
+  gf_internal_t *h;
+
+  a = a32;
+  b = b32;
+  h = (gf_internal_t *) gf->scratch;
+  one = 1;
+  pp = h->prim_poly | (one << 32);
+
+  product = 0;
+
+  for (i = 0; i < GF_FIELD_WIDTH; i++) { 
+    if (a & (one << i)) product ^= (b << i);
+  }
+  for (i = (GF_FIELD_WIDTH*2-2); i >= GF_FIELD_WIDTH; i--) {
+    if (product & (one << i)) product ^= (pp << (i-GF_FIELD_WIDTH)); 
+  }
+  return product;
+}
+
+  static 
+int gf_w32_cfm_init(gf_t *gf)
+{
+  gf->inverse.w32 = gf_w32_euclid;
+  gf->multiply_region.w32 = gf_w32_multiply_region_from_single;
+  
+  /*Ben: We also check to see if the prim poly will work for pclmul */
+  /*Ben: Check to see how many reduction steps it will take*/
+
+#if defined(INTEL_SSE4_PCLMUL)
+  gf_internal_t *h;
+
+  h = (gf_internal_t *) gf->scratch;
+
+  if ((0xfffe0000 & h->prim_poly) == 0){ 
+    gf->multiply.w32 = gf_w32_clm_multiply_2;
+    gf->multiply_region.w32 = gf_w32_clm_multiply_region_from_single_2;
+  }else if ((0xffc00000 & h->prim_poly) == 0){
+    gf->multiply.w32 = gf_w32_clm_multiply_3;
+    gf->multiply_region.w32 = gf_w32_clm_multiply_region_from_single_3;
+  }else if ((0xfe000000 & h->prim_poly) == 0){
+    gf->multiply.w32 = gf_w32_clm_multiply_4;
+    gf->multiply_region.w32 = gf_w32_clm_multiply_region_from_single_4;
+  } else {
+    return 0;
+  }
+  return 1;
+  #endif
+
+  return 0;
+}
+
+  static 
+int gf_w32_shift_init(gf_t *gf)
+{
+  gf->inverse.w32 = gf_w32_euclid;
+  gf->multiply_region.w32 = gf_w32_multiply_region_from_single;
+  gf->multiply.w32 = gf_w32_shift_multiply;
+  return 1;
+}
+
+static
+  void
+gf_w32_group_set_shift_tables(uint32_t *shift, uint32_t val, gf_internal_t *h)
+{
+  int i;
+  uint32_t j;
+
+  shift[0] = 0;
+
+  for (i = 1; i < (1 << h->arg1); i <<= 1) {
+    for (j = 0; j < i; j++) shift[i|j] = shift[j]^val;
+    if (val & GF_FIRST_BIT) {
+      val <<= 1;
+      val ^= h->prim_poly;
+    } else {
+      val <<= 1;
+    }
+  }
+}
+
+  static
+void gf_w32_group_s_equals_r_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  int leftover, rs;
+  uint32_t p, l, ind, a32;
+  int bits_left;
+  int g_s;
+  gf_region_data rd;
+  uint32_t *s32, *d32, *top;
+  struct gf_w32_group_data *gd;
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gd = (struct gf_w32_group_data *) h->private;
+  g_s = h->arg1;
+  gf_w32_group_set_shift_tables(gd->shift, val, h);
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 4);
+  gf_do_initial_region_alignment(&rd);
+
+  s32 = (uint32_t *) rd.s_start;
+  d32 = (uint32_t *) rd.d_start;
+  top = (uint32_t *) rd.d_top;
+
+  leftover = 32 % g_s;
+  if (leftover == 0) leftover = g_s;
+
+  while (d32 < top) {
+    rs = 32 - leftover;
+    a32 = *s32;
+    ind = a32 >> rs;
+    a32 <<= leftover;
+    p = gd->shift[ind];
+
+    bits_left = rs;
+    rs = 32 - g_s;
+
+    while (bits_left > 0) {
+      bits_left -= g_s;
+      ind = a32 >> rs;
+      a32 <<= g_s;
+      l = p >> rs;
+      p = (gd->shift[ind] ^ gd->reduce[l] ^ (p << g_s));
+    }
+    if (xor) p ^= *d32;
+    *d32 = p;
+    d32++;
+    s32++;
+  }
+  gf_do_final_region_alignment(&rd);
+}
+
+  static
+void gf_w32_group_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  uint32_t *s32, *d32, *top;
+  int i;
+  int leftover;
+  uint64_t p, l, r;
+  uint32_t a32, ind;
+  int g_s, g_r;
+  struct gf_w32_group_data *gd;
+  gf_region_data rd;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  g_s = h->arg1;
+  g_r = h->arg2;
+  gd = (struct gf_w32_group_data *) h->private;
+  gf_w32_group_set_shift_tables(gd->shift, val, h);
+
+  leftover = GF_FIELD_WIDTH % g_s;
+  if (leftover == 0) leftover = g_s;
+
+  gd = (struct gf_w32_group_data *) h->private;
+  gf_w32_group_set_shift_tables(gd->shift, val, h);
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 4);
+  gf_do_initial_region_alignment(&rd);
+
+  s32 = (uint32_t *) rd.s_start;
+  d32 = (uint32_t *) rd.d_start;
+  top = (uint32_t *) rd.d_top;
+
+  while (d32 < top) {
+    a32 = *s32;
+    ind = a32 >> (GF_FIELD_WIDTH - leftover);
+    p = gd->shift[ind];
+    p <<= g_s;
+    a32 <<= leftover;
+  
+    i = (GF_FIELD_WIDTH - leftover);
+    while (i > g_s) {
+      ind = a32 >> (GF_FIELD_WIDTH-g_s);
+      p ^= gd->shift[ind];
+      a32 <<= g_s;
+      p <<= g_s;
+      i -= g_s;
+    }
+  
+    ind = a32 >> (GF_FIELD_WIDTH-g_s);
+    p ^= gd->shift[ind];
+  
+    for (i = gd->tshift ; i >= 0; i -= g_r) {
+      l = p & (gd->rmask << i);
+      r = gd->reduce[l >> (i+32)];
+      r <<= (i);
+      p ^= r;
+    }
+
+    if (xor) p ^= *d32;
+    *d32 = p;
+    d32++;
+    s32++;
+  }
+  gf_do_final_region_alignment(&rd);
+}
+
+static
+inline
+gf_val_32_t
+gf_w32_group_s_equals_r_multiply(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  int leftover, rs;
+  uint32_t p, l, ind, a32;
+  int bits_left;
+  int g_s;
+
+  struct gf_w32_group_data *gd;
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  g_s = h->arg1;
+
+  gd = (struct gf_w32_group_data *) h->private;
+  gf_w32_group_set_shift_tables(gd->shift, b, h);
+
+  leftover = 32 % g_s;
+  if (leftover == 0) leftover = g_s;
+
+  rs = 32 - leftover;
+  a32 = a;
+  ind = a32 >> rs;
+  a32 <<= leftover;
+  p = gd->shift[ind];
+
+  bits_left = rs;
+  rs = 32 - g_s;
+
+  while (bits_left > 0) {
+    bits_left -= g_s;
+    ind = a32 >> rs;
+    a32 <<= g_s;
+    l = p >> rs;
+    p = (gd->shift[ind] ^ gd->reduce[l] ^ (p << g_s));
+  }
+  return p;
+}
+
+static
+inline
+gf_val_32_t
+gf_w32_group_4_4_multiply(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  uint32_t p, l, ind, a32;
+
+  struct gf_w32_group_data *d44;
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+
+  d44 = (struct gf_w32_group_data *) h->private;
+  gf_w32_group_set_shift_tables(d44->shift, b, h);
+
+  p = 0;
+  a32 = a;
+  ind = a32 >> 28;
+  a32 <<= 4;
+  p = d44->shift[ind];
+  ind = a32 >> 28;
+  a32 <<= 4;
+  l = p >> 28;
+  p = (d44->shift[ind] ^ d44->reduce[l] ^ (p << 4));
+  ind = a32 >> 28;
+  a32 <<= 4;
+  l = p >> 28;
+  p = (d44->shift[ind] ^ d44->reduce[l] ^ (p << 4));
+  ind = a32 >> 28;
+  a32 <<= 4;
+  l = p >> 28;
+  p = (d44->shift[ind] ^ d44->reduce[l] ^ (p << 4));
+  ind = a32 >> 28;
+  a32 <<= 4;
+  l = p >> 28;
+  p = (d44->shift[ind] ^ d44->reduce[l] ^ (p << 4));
+  ind = a32 >> 28;
+  a32 <<= 4;
+  l = p >> 28;
+  p = (d44->shift[ind] ^ d44->reduce[l] ^ (p << 4));
+  ind = a32 >> 28;
+  a32 <<= 4;
+  l = p >> 28;
+  p = (d44->shift[ind] ^ d44->reduce[l] ^ (p << 4));
+  ind = a32 >> 28;
+  l = p >> 28;
+  p = (d44->shift[ind] ^ d44->reduce[l] ^ (p << 4));
+  return p;
+}
+
+static
+inline
+gf_val_32_t
+gf_w32_group_multiply(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  int i;
+  int leftover;
+  uint64_t p, l, r;
+  uint32_t a32, ind;
+  int g_s, g_r;
+  struct gf_w32_group_data *gd;
+
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  g_s = h->arg1;
+  g_r = h->arg2;
+  gd = (struct gf_w32_group_data *) h->private;
+  gf_w32_group_set_shift_tables(gd->shift, b, h);
+
+  leftover = GF_FIELD_WIDTH % g_s;
+  if (leftover == 0) leftover = g_s;
+
+  a32 = a;
+  ind = a32 >> (GF_FIELD_WIDTH - leftover);
+  p = gd->shift[ind];
+  p <<= g_s;
+  a32 <<= leftover;
+
+  i = (GF_FIELD_WIDTH - leftover);
+  while (i > g_s) {
+    ind = a32 >> (GF_FIELD_WIDTH-g_s);
+    p ^= gd->shift[ind];
+    a32 <<= g_s;
+    p <<= g_s;
+    i -= g_s;
+  }
+
+  ind = a32 >> (GF_FIELD_WIDTH-g_s);
+  p ^= gd->shift[ind];
+
+  for (i = gd->tshift ; i >= 0; i -= g_r) {
+    l = p & (gd->rmask << i);
+    r = gd->reduce[l >> (i+32)];
+    r <<= (i);
+    p ^= r;
+  }
+  return p;
+}
+
+static
+inline
+gf_val_32_t
+gf_w32_bytwo_b_multiply (gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  uint32_t prod, pp, bmask;
+  gf_internal_t *h;
+
+  h = (gf_internal_t *) gf->scratch;
+  pp = h->prim_poly;
+
+  prod = 0;
+  bmask = 0x80000000;
+
+  while (1) {
+    if (a & 1) prod ^= b;
+    a >>= 1;
+    if (a == 0) return prod;
+    if (b & bmask) {
+      b = ((b << 1) ^ pp);
+    } else {
+      b <<= 1;
+    }
+  }
+}
+
+static
+inline
+gf_val_32_t
+gf_w32_bytwo_p_multiply (gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  uint32_t prod, pp, pmask, amask;
+  gf_internal_t *h;
+
+  h = (gf_internal_t *) gf->scratch;
+  pp = h->prim_poly;
+
+
+  prod = 0;
+  pmask = 0x80000000;
+  amask = 0x80000000;
+
+  while (amask != 0) {
+    if (prod & pmask) {
+      prod = ((prod << 1) ^ pp);
+    } else {
+      prod <<= 1;
+    }
+    if (a & amask) prod ^= b;
+    amask >>= 1;
+  }
+  return prod;
+}
+
+static
+void
+gf_w32_bytwo_p_nosse_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  uint64_t *s64, *d64, t1, t2, ta, prod, amask;
+  gf_region_data rd;
+  struct gf_w32_bytwo_data *btd;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  btd = (struct gf_w32_bytwo_data *) ((gf_internal_t *) (gf->scratch))->private;
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 8);
+  gf_do_initial_region_alignment(&rd);
+
+  s64 = (uint64_t *) rd.s_start;
+  d64 = (uint64_t *) rd.d_start;
+
+  if (xor) {
+    while (s64 < (uint64_t *) rd.s_top) {
+      prod = 0;
+      amask = 0x80000000;
+      ta = *s64;
+      while (amask != 0) {
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, prod, t1, t2);
+        if (val & amask) prod ^= ta;
+        amask >>= 1;
+      }
+      *d64 ^= prod;
+      d64++;
+      s64++;
+    }
+  } else {
+    while (s64 < (uint64_t *) rd.s_top) {
+      prod = 0;
+      amask = 0x80000000;
+      ta = *s64;
+      while (amask != 0) {
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, prod, t1, t2);
+        if (val & amask) prod ^= ta;
+        amask >>= 1;
+      }
+      *d64 = prod;
+      d64++;
+      s64++;
+    }
+  }
+  gf_do_final_region_alignment(&rd);
+}
+
+#define BYTWO_P_ONESTEP {\
+      SSE_AB2(pp, m1 ,m2, prod, t1, t2); \
+      t1 = _mm_and_si128(v, one); \
+      t1 = _mm_sub_epi32(t1, one); \
+      t1 = _mm_and_si128(t1, ta); \
+      prod = _mm_xor_si128(prod, t1); \
+      v = _mm_srli_epi64(v, 1); }
+
+#ifdef INTEL_SSE2
+static
+void
+gf_w32_bytwo_p_sse_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  int i;
+  uint8_t *s8, *d8;
+  uint32_t vrev;
+  __m128i pp, m1, m2, ta, prod, t1, t2, tp, one, v;
+  struct gf_w32_bytwo_data *btd;
+  gf_region_data rd;
+   
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  btd = (struct gf_w32_bytwo_data *) ((gf_internal_t *) (gf->scratch))->private;
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 16);
+  gf_do_initial_region_alignment(&rd);
+
+  vrev = 0;
+  for (i = 0; i < 32; i++) {
+    vrev <<= 1;
+    if (!(val & (1 << i))) vrev |= 1;
+  }
+
+  s8 = (uint8_t *) rd.s_start;
+  d8 = (uint8_t *) rd.d_start;
+
+  pp = _mm_set1_epi32(btd->prim_poly&0xffffffff);
+  m1 = _mm_set1_epi32((btd->mask1)&0xffffffff);
+  m2 = _mm_set1_epi32((btd->mask2)&0xffffffff);
+  one = _mm_set1_epi32(1);
+
+  while (d8 < (uint8_t *) rd.d_top) {
+    prod = _mm_setzero_si128();
+    v = _mm_set1_epi32(vrev);
+    ta = _mm_load_si128((__m128i *) s8);
+    tp = (!xor) ? _mm_setzero_si128() : _mm_load_si128((__m128i *) d8);
+    BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP;
+    _mm_store_si128((__m128i *) d8, _mm_xor_si128(prod, tp));
+    d8 += 16;
+    s8 += 16;
+  }
+  gf_do_final_region_alignment(&rd);
+}
+#endif
+
+static
+void
+gf_w32_bytwo_b_nosse_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  uint64_t *s64, *d64, t1, t2, ta, tb, prod;
+  struct gf_w32_bytwo_data *btd;
+  gf_region_data rd;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 32);
+  gf_do_initial_region_alignment(&rd);
+
+  btd = (struct gf_w32_bytwo_data *) ((gf_internal_t *) (gf->scratch))->private;
+  s64 = (uint64_t *) rd.s_start;
+  d64 = (uint64_t *) rd.d_start;
+
+  switch (val) {
+  case 2:
+    if (xor) {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 ^= ta;
+        d64++;
+        s64++;
+      }
+    } else {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 = ta;
+        d64++;
+        s64++;
+      }
+    }
+    break;
+  case 3:
+    if (xor) {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        prod = ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 ^= (ta ^ prod);
+        d64++;
+        s64++;
+      }
+    } else {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        prod = ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 = (ta ^ prod);
+        d64++;
+        s64++;
+      }
+    }
+  case 4:
+    if (xor) {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 ^= ta;
+        d64++;
+        s64++;
+      }
+    } else {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 = ta;
+        d64++;
+        s64++;
+      }
+    }
+    break;
+  case 5:
+    if (xor) {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        prod = ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 ^= (ta ^ prod);
+        d64++;
+        s64++;
+      }
+    } else {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        prod = ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 = ta ^ prod;
+        d64++;
+        s64++;
+      }
+    }
+  default:
+    if (xor) {
+      while (d64 < (uint64_t *) rd.d_top) {
+        prod = *d64 ;
+        ta = *s64;
+        tb = val;
+        while (1) {
+          if (tb & 1) prod ^= ta;
+          tb >>= 1;
+          if (tb == 0) break;
+          AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        }
+        *d64 = prod;
+        d64++;
+        s64++;
+      }
+    } else {
+      while (d64 < (uint64_t *) rd.d_top) {
+        prod = 0 ;
+        ta = *s64;
+        tb = val;
+        while (1) {
+          if (tb & 1) prod ^= ta;
+          tb >>= 1;
+          if (tb == 0) break;
+          AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        }
+        *d64 = prod;
+        d64++;
+        s64++;
+      }
+    }
+    break;
+  }
+  gf_do_final_region_alignment(&rd);
+}
+
+#ifdef INTEL_SSE2
+static
+void
+gf_w32_bytwo_b_sse_region_2_noxor(gf_region_data *rd, struct gf_w32_bytwo_data *btd)
+{
+  uint8_t *d8, *s8;
+  __m128i pp, m1, m2, t1, t2, va;
+
+  s8 = (uint8_t *) rd->s_start;
+  d8 = (uint8_t *) rd->d_start;
+
+  pp = _mm_set1_epi32(btd->prim_poly&0xffffffff);
+  m1 = _mm_set1_epi32((btd->mask1)&0xffffffff);
+  m2 = _mm_set1_epi32((btd->mask2)&0xffffffff);
+
+  while (d8 < (uint8_t *) rd->d_top) {
+    va = _mm_load_si128 ((__m128i *)(s8));
+    SSE_AB2(pp, m1, m2, va, t1, t2);
+    _mm_store_si128((__m128i *)d8, va);
+    d8 += 16;
+    s8 += 16;
+  }
+}
+#endif
+
+#ifdef INTEL_SSE2
+static
+void
+gf_w32_bytwo_b_sse_region_2_xor(gf_region_data *rd, struct gf_w32_bytwo_data *btd)
+{
+  uint8_t *d8, *s8;
+  __m128i pp, m1, m2, t1, t2, va, vb;
+
+  s8 = (uint8_t *) rd->s_start;
+  d8 = (uint8_t *) rd->d_start;
+
+  pp = _mm_set1_epi32(btd->prim_poly&0xffffffff);
+  m1 = _mm_set1_epi32((btd->mask1)&0xffffffff);
+  m2 = _mm_set1_epi32((btd->mask2)&0xffffffff);
+
+  while (d8 < (uint8_t *) rd->d_top) {
+    va = _mm_load_si128 ((__m128i *)(s8));
+    SSE_AB2(pp, m1, m2, va, t1, t2);
+    vb = _mm_load_si128 ((__m128i *)(d8));
+    vb = _mm_xor_si128(vb, va);
+    _mm_store_si128((__m128i *)d8, vb);
+    d8 += 16;
+    s8 += 16;
+  }
+}
+#endif
+
+
+#ifdef INTEL_SSE2
+static
+void 
+gf_w32_bytwo_b_sse_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  uint32_t itb;
+  uint8_t *d8, *s8;
+  __m128i pp, m1, m2, t1, t2, va, vb;
+  struct gf_w32_bytwo_data *btd;
+  gf_region_data rd;
+    
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 16);
+  gf_do_initial_region_alignment(&rd);
+
+  btd = (struct gf_w32_bytwo_data *) ((gf_internal_t *) (gf->scratch))->private;
+
+  if (val == 2) {
+    if (xor) {
+      gf_w32_bytwo_b_sse_region_2_xor(&rd, btd);
+    } else {
+      gf_w32_bytwo_b_sse_region_2_noxor(&rd, btd);
+    }
+    gf_do_final_region_alignment(&rd);
+    return;
+  }
+
+  s8 = (uint8_t *) rd.s_start;
+  d8 = (uint8_t *) rd.d_start;
+
+  pp = _mm_set1_epi32(btd->prim_poly&0xffffffff);
+  m1 = _mm_set1_epi32((btd->mask1)&0xffffffff);
+  m2 = _mm_set1_epi32((btd->mask2)&0xffffffff);
+
+  while (d8 < (uint8_t *) rd.d_top) {
+    va = _mm_load_si128 ((__m128i *)(s8));
+    vb = (!xor) ? _mm_setzero_si128() : _mm_load_si128 ((__m128i *)(d8));
+    itb = val;
+    while (1) {
+      if (itb & 1) vb = _mm_xor_si128(vb, va);
+      itb >>= 1;
+      if (itb == 0) break;
+      SSE_AB2(pp, m1, m2, va, t1, t2);
+    }
+    _mm_store_si128((__m128i *)d8, vb);
+    d8 += 16;
+    s8 += 16;
+  }
+
+  gf_do_final_region_alignment(&rd);
+}
+#endif
+
+static
+int gf_w32_bytwo_init(gf_t *gf)
+{
+  gf_internal_t *h;
+  uint64_t ip, m1, m2;
+  struct gf_w32_bytwo_data *btd;
+
+  h = (gf_internal_t *) gf->scratch;
+  btd = (struct gf_w32_bytwo_data *) (h->private);
+  ip = h->prim_poly & 0xffffffff;
+  m1 = 0xfffffffe;
+  m2 = 0x80000000;
+  btd->prim_poly = 0;
+  btd->mask1 = 0;
+  btd->mask2 = 0;
+
+  while (ip != 0) {
+    btd->prim_poly |= ip;
+    btd->mask1 |= m1;
+    btd->mask2 |= m2;
+    ip <<= GF_FIELD_WIDTH;
+    m1 <<= GF_FIELD_WIDTH;
+    m2 <<= GF_FIELD_WIDTH;
+  }
+
+  if (h->mult_type == GF_MULT_BYTWO_p) {
+    gf->multiply.w32 = gf_w32_bytwo_p_multiply;
+    #ifdef INTEL_SSE2
+      if (h->region_type & GF_REGION_NOSSE)
+        gf->multiply_region.w32 = gf_w32_bytwo_p_nosse_multiply_region; 
+      else
+        gf->multiply_region.w32 = gf_w32_bytwo_p_sse_multiply_region; 
+    #else
+      gf->multiply_region.w32 = gf_w32_bytwo_p_nosse_multiply_region; 
+      if(h->region_type & GF_REGION_SSE)
+        return 0;
+    #endif
+  } else {
+    gf->multiply.w32 = gf_w32_bytwo_b_multiply; 
+    #ifdef INTEL_SSE2
+      if (h->region_type & GF_REGION_NOSSE)
+        gf->multiply_region.w32 = gf_w32_bytwo_b_nosse_multiply_region; 
+      else
+        gf->multiply_region.w32 = gf_w32_bytwo_b_sse_multiply_region; 
+    #else
+      gf->multiply_region.w32 = gf_w32_bytwo_b_nosse_multiply_region; 
+      if(h->region_type & GF_REGION_SSE)
+        return 0;
+    #endif
+  }
+
+  gf->inverse.w32 = gf_w32_euclid;
+  return 1;
+}
+
+static
+inline
+uint32_t
+gf_w32_split_8_8_multiply (gf_t *gf, uint32_t a32, uint32_t b32)
+{
+  uint32_t product, i, j, mask, tb;
+  gf_internal_t *h;
+  struct gf_w32_split_8_8_data *d8;
+  
+  h = (gf_internal_t *) gf->scratch;
+  d8 = (struct gf_w32_split_8_8_data *) h->private;
+  product = 0;
+  mask = 0xff;
+
+  for (i = 0; i < 4; i++) {
+    tb = b32;
+    for (j = 0; j < 4; j++) {
+      product ^= d8->tables[i+j][a32&mask][tb&mask];
+      tb >>= 8;
+    }
+    a32 >>= 8;
+  }
+  return product;
+}
+
+static
+inline
+void
+gf_w32_split_8_32_lazy_multiply_region(gf_t *gf, void *src, void *dest, uint32_t val, int bytes, int xor)
+{
+  gf_internal_t *h;
+  uint32_t *s32, *d32, *top, p, a, v;
+  struct gf_split_8_32_lazy_data *d8;
+  struct gf_w32_split_8_8_data *d88;
+  uint32_t *t[4];
+  int i, j, k, change;
+  uint32_t pp;
+  gf_region_data rd;
+  
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  h = (gf_internal_t *) gf->scratch;
+  if (h->arg1 == 32 || h->arg2 == 32 || h->mult_type == GF_MULT_DEFAULT) {
+    d8 = (struct gf_split_8_32_lazy_data *) h->private;
+    for (i = 0; i < 4; i++) t[i] = d8->tables[i];
+    change = (val != d8->last_value);
+    if (change) d8->last_value = val;
+  } else {
+    d88 = (struct gf_w32_split_8_8_data *) h->private;
+    for (i = 0; i < 4; i++) t[i] = d88->region_tables[i];
+    change = (val != d88->last_value);
+    if (change) d88->last_value = val;
+  }
+  pp = h->prim_poly;
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 4);
+  gf_do_initial_region_alignment(&rd);
+
+  s32 = (uint32_t *) rd.s_start;
+  d32 = (uint32_t *) rd.d_start;
+  top = (uint32_t *) rd.d_top;
+  
+  if (change) {
+    v = val;
+    for (i = 0; i < 4; i++) {
+      t[i][0] = 0;
+      for (j = 1; j < 256; j <<= 1) {
+        for (k = 0; k < j; k++) {
+          t[i][k^j] = (v ^ t[i][k]);
+        }
+        v = (v & GF_FIRST_BIT) ? ((v << 1) ^ pp) : (v << 1);
+      }
+    }
+  } 
+
+  while (d32 < top) {
+    p = (xor) ? *d32 : 0;
+    a = *s32;
+    i = 0;
+    while (a != 0) {
+      v = (a & 0xff);
+      p ^= t[i][v];
+      a >>= 8;
+      i++;
+    }
+    *d32 = p;
+    d32++;
+    s32++;
+  }
+  gf_do_final_region_alignment(&rd);
+}
+
+static
+inline
+void
+gf_w32_split_16_32_lazy_multiply_region(gf_t *gf, void *src, void *dest, uint32_t val, int bytes, int xor)
+{
+  gf_internal_t *h;
+  uint32_t *s32, *d32, *top, p, a, v;
+  struct gf_split_16_32_lazy_data *d16;
+  uint32_t *t[2];
+  int i, j, k, change;
+  uint32_t pp;
+  gf_region_data rd;
+  
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  h = (gf_internal_t *) gf->scratch;
+  d16 = (struct gf_split_16_32_lazy_data *) h->private;
+  for (i = 0; i < 2; i++) t[i] = d16->tables[i];
+  change = (val != d16->last_value);
+  if (change) d16->last_value = val;
+
+  pp = h->prim_poly;
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 4);
+  gf_do_initial_region_alignment(&rd);
+
+  s32 = (uint32_t *) rd.s_start;
+  d32 = (uint32_t *) rd.d_start;
+  top = (uint32_t *) rd.d_top;
+  
+  if (change) {
+    v = val;
+    for (i = 0; i < 2; i++) {
+      t[i][0] = 0;
+      for (j = 1; j < (1 << 16); j <<= 1) {
+        for (k = 0; k < j; k++) {
+          t[i][k^j] = (v ^ t[i][k]);
+        }
+        v = (v & GF_FIRST_BIT) ? ((v << 1) ^ pp) : (v << 1);
+      }
+    }
+  } 
+
+  while (d32 < top) {
+    p = (xor) ? *d32 : 0;
+    a = *s32;
+    i = 0;
+    while (a != 0) {
+      v = (a & 0xffff);
+      p ^= t[i][v];
+      a >>= 16;
+      i++;
+    }
+    *d32 = p;
+    d32++;
+    s32++;
+  }
+  gf_do_final_region_alignment(&rd);
+}
+
+static
+void
+gf_w32_split_2_32_lazy_multiply_region(gf_t *gf, void *src, void *dest, uint32_t val, int bytes, int xor)
+{
+  gf_internal_t *h;
+  struct gf_split_2_32_lazy_data *ld;
+  int i;
+  uint32_t pp, v, v2, s, *s32, *d32, *top;
+  gf_region_data rd;
+ 
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 4);
+  gf_do_initial_region_alignment(&rd);
+
+  h = (gf_internal_t *) gf->scratch;
+  pp = h->prim_poly;
+
+  ld = (struct gf_split_2_32_lazy_data *) h->private;
+  
+  if (ld->last_value != val) {
+    v = val;
+    for (i = 0; i < 16; i++) {
+      v2 = (v << 1);
+      if (v & GF_FIRST_BIT) v2 ^= pp;
+      ld->tables[i][0] = 0;
+      ld->tables[i][1] = v;
+      ld->tables[i][2] = v2;
+      ld->tables[i][3] = (v2 ^ v);
+      v = (v2 << 1);
+      if (v2 & GF_FIRST_BIT) v ^= pp;
+    }
+  }
+  ld->last_value = val;
+
+  s32 = (uint32_t *) rd.s_start;
+  d32 = (uint32_t *) rd.d_start;
+  top = (uint32_t *) rd.d_top;
+
+  while (d32 != top) {
+    v = (xor) ? *d32 : 0;
+    s = *s32;
+    i = 0;
+    while (s != 0) {
+      v ^= ld->tables[i][s&3];
+      s >>= 2;
+      i++;
+    }
+    *d32 = v;
+    d32++;
+    s32++;
+  }
+  gf_do_final_region_alignment(&rd);
+}
+
+#ifdef INTEL_SSSE3
+static
+void
+gf_w32_split_2_32_lazy_sse_multiply_region(gf_t *gf, void *src, void *dest, uint32_t val, int bytes, int xor)
+{
+  gf_internal_t *h;
+  int i, tindex;
+  uint32_t pp, v, v2, *s32, *d32, *top;
+  __m128i vi, si, pi, shuffler, tables[16], adder, xi, mask1, mask2;
+  gf_region_data rd;
+ 
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 32);
+  gf_do_initial_region_alignment(&rd);
+
+  h = (gf_internal_t *) gf->scratch;
+  pp = h->prim_poly;
+  
+  s32 = (uint32_t *) rd.s_start;
+  d32 = (uint32_t *) rd.d_start;
+  top = (uint32_t *) rd.d_top;
+  
+  v = val;
+  for (i = 0; i < 16; i++) {
+    v2 = (v << 1);
+    if (v & GF_FIRST_BIT) v2 ^= pp;
+    tables[i] = _mm_set_epi32(v2 ^ v, v2, v, 0);
+    v = (v2 << 1);
+    if (v2 & GF_FIRST_BIT) v ^= pp;
+  }
+
+  shuffler = _mm_set_epi8(0xc, 0xc, 0xc, 0xc, 8, 8, 8, 8, 4, 4, 4, 4, 0, 0, 0, 0);
+  adder = _mm_set_epi8(3, 2, 1, 0, 3, 2, 1, 0, 3, 2, 1, 0, 3, 2, 1, 0);
+  mask1 = _mm_set1_epi8(0x3);
+  mask2 = _mm_set1_epi8(0xc);
+
+  while (d32 != top) {
+    pi = (xor) ? _mm_load_si128 ((__m128i *) d32) : _mm_setzero_si128();
+    vi = _mm_load_si128((__m128i *) s32);
+ 
+    tindex = 0;
+    for (i = 0; i < 4; i++) {
+      si = _mm_shuffle_epi8(vi, shuffler);
+
+      xi = _mm_and_si128(si, mask1);
+      xi = _mm_slli_epi16(xi, 2);
+      xi = _mm_xor_si128(xi, adder);
+      pi = _mm_xor_si128(pi, _mm_shuffle_epi8(tables[tindex], xi));
+      tindex++;
+
+      xi = _mm_and_si128(si, mask2);
+      xi = _mm_xor_si128(xi, adder);
+      pi = _mm_xor_si128(pi, _mm_shuffle_epi8(tables[tindex], xi));
+      si = _mm_srli_epi16(si, 2);
+      tindex++;
+
+      xi = _mm_and_si128(si, mask2);
+      xi = _mm_xor_si128(xi, adder);
+      pi = _mm_xor_si128(pi, _mm_shuffle_epi8(tables[tindex], xi));
+      si = _mm_srli_epi16(si, 2);
+      tindex++;
+
+      xi = _mm_and_si128(si, mask2);
+      xi = _mm_xor_si128(xi, adder);
+      pi = _mm_xor_si128(pi, _mm_shuffle_epi8(tables[tindex], xi));
+      si = _mm_srli_epi16(si, 2);
+      tindex++;
+      
+      vi = _mm_srli_epi32(vi, 8);
+    }
+    _mm_store_si128((__m128i *) d32, pi);
+    d32 += 4;
+    s32 += 4;
+  }
+
+  gf_do_final_region_alignment(&rd);
+
+}
+#endif
+
+static
+void
+gf_w32_split_4_32_lazy_multiply_region(gf_t *gf, void *src, void *dest, uint32_t val, int bytes, int xor)
+{
+  gf_internal_t *h;
+  struct gf_split_4_32_lazy_data *ld;
+  int i, j, k;
+  uint32_t pp, v, s, *s32, *d32, *top;
+  gf_region_data rd;
+ 
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  h = (gf_internal_t *) gf->scratch;
+  pp = h->prim_poly;
+
+  ld = (struct gf_split_4_32_lazy_data *) h->private;
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 4);
+  gf_do_initial_region_alignment(&rd);
+  
+  if (ld->last_value != val) {
+    v = val;
+    for (i = 0; i < 8; i++) {
+      ld->tables[i][0] = 0;
+      for (j = 1; j < 16; j <<= 1) {
+        for (k = 0; k < j; k++) {
+          ld->tables[i][k^j] = (v ^ ld->tables[i][k]);
+        }
+        v = (v & GF_FIRST_BIT) ? ((v << 1) ^ pp) : (v << 1);
+      }
+    }
+  }
+  ld->last_value = val;
+
+  s32 = (uint32_t *) rd.s_start;
+  d32 = (uint32_t *) rd.d_start;
+  top = (uint32_t *) rd.d_top;
+
+  while (d32 != top) {
+    v = (xor) ? *d32 : 0;
+    s = *s32;
+    i = 0;
+    while (s != 0) {
+      v ^= ld->tables[i][s&0xf];
+      s >>= 4;
+      i++;
+    }
+    *d32 = v;
+    d32++;
+    s32++;
+  }
+  gf_do_final_region_alignment(&rd);
+}
+
+static
+void
+gf_w32_split_4_32_lazy_sse_altmap_multiply_region(gf_t *gf, void *src, void *dest, uint32_t val, int bytes, int xor)
+{
+#ifdef INTEL_SSSE3
+  gf_internal_t *h;
+  int i, j, k;
+  uint32_t pp, v, *s32, *d32, *top;
+  __m128i si, tables[8][4], p0, p1, p2, p3, mask1, v0, v1, v2, v3;
+  struct gf_split_4_32_lazy_data *ld;
+  uint8_t btable[16];
+  gf_region_data rd;
+ 
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  h = (gf_internal_t *) gf->scratch;
+  pp = h->prim_poly;
+  
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 64);
+  gf_do_initial_region_alignment(&rd);
+
+  s32 = (uint32_t *) rd.s_start;
+  d32 = (uint32_t *) rd.d_start;
+  top = (uint32_t *) rd.d_top;
+  
+  ld = (struct gf_split_4_32_lazy_data *) h->private;
+ 
+  v = val;
+  for (i = 0; i < 8; i++) {
+    ld->tables[i][0] = 0;
+    for (j = 1; j < 16; j <<= 1) {
+      for (k = 0; k < j; k++) {
+        ld->tables[i][k^j] = (v ^ ld->tables[i][k]);
+      }
+      v = (v & GF_FIRST_BIT) ? ((v << 1) ^ pp) : (v << 1);
+    }
+    for (j = 0; j < 4; j++) {
+      for (k = 0; k < 16; k++) {
+        btable[k] = (uint8_t) ld->tables[i][k];
+        ld->tables[i][k] >>= 8;
+      }
+      tables[i][j] = _mm_loadu_si128((__m128i *) btable);
+    }
+  }
+
+  mask1 = _mm_set1_epi8(0xf);
+
+  if (xor) {
+    while (d32 != top) {
+      p0 = _mm_load_si128 ((__m128i *) d32);
+      p1 = _mm_load_si128 ((__m128i *) (d32+4));
+      p2 = _mm_load_si128 ((__m128i *) (d32+8));
+      p3 = _mm_load_si128 ((__m128i *) (d32+12));
+  
+      v0 = _mm_load_si128((__m128i *) s32); s32 += 4;
+      v1 = _mm_load_si128((__m128i *) s32); s32 += 4;
+      v2 = _mm_load_si128((__m128i *) s32); s32 += 4;
+      v3 = _mm_load_si128((__m128i *) s32); s32 += 4;
+  
+      si = _mm_and_si128(v0, mask1);
+      p0 = _mm_xor_si128(p0, _mm_shuffle_epi8(tables[0][0], si));
+      p1 = _mm_xor_si128(p1, _mm_shuffle_epi8(tables[0][1], si));
+      p2 = _mm_xor_si128(p2, _mm_shuffle_epi8(tables[0][2], si));
+      p3 = _mm_xor_si128(p3, _mm_shuffle_epi8(tables[0][3], si));
+      
+      v0 = _mm_srli_epi32(v0, 4);
+      si = _mm_and_si128(v0, mask1);
+      p0 = _mm_xor_si128(p0, _mm_shuffle_epi8(tables[1][0], si));
+      p1 = _mm_xor_si128(p1, _mm_shuffle_epi8(tables[1][1], si));
+      p2 = _mm_xor_si128(p2, _mm_shuffle_epi8(tables[1][2], si));
+      p3 = _mm_xor_si128(p3, _mm_shuffle_epi8(tables[1][3], si));
+  
+      si = _mm_and_si128(v1, mask1);
+      p0 = _mm_xor_si128(p0, _mm_shuffle_epi8(tables[2][0], si));
+      p1 = _mm_xor_si128(p1, _mm_shuffle_epi8(tables[2][1], si));
+      p2 = _mm_xor_si128(p2, _mm_shuffle_epi8(tables[2][2], si));
+      p3 = _mm_xor_si128(p3, _mm_shuffle_epi8(tables[2][3], si));
+      
+      v1 = _mm_srli_epi32(v1, 4);
+      si = _mm_and_si128(v1, mask1);
+      p0 = _mm_xor_si128(p0, _mm_shuffle_epi8(tables[3][0], si));
+      p1 = _mm_xor_si128(p1, _mm_shuffle_epi8(tables[3][1], si));
+      p2 = _mm_xor_si128(p2, _mm_shuffle_epi8(tables[3][2], si));
+      p3 = _mm_xor_si128(p3, _mm_shuffle_epi8(tables[3][3], si));
+  
+      si = _mm_and_si128(v2, mask1);
+      p0 = _mm_xor_si128(p0, _mm_shuffle_epi8(tables[4][0], si));
+      p1 = _mm_xor_si128(p1, _mm_shuffle_epi8(tables[4][1], si));
+      p2 = _mm_xor_si128(p2, _mm_shuffle_epi8(tables[4][2], si));
+      p3 = _mm_xor_si128(p3, _mm_shuffle_epi8(tables[4][3], si));
+      
+      v2 = _mm_srli_epi32(v2, 4);
+      si = _mm_and_si128(v2, mask1);
+      p0 = _mm_xor_si128(p0, _mm_shuffle_epi8(tables[5][0], si));
+      p1 = _mm_xor_si128(p1, _mm_shuffle_epi8(tables[5][1], si));
+      p2 = _mm_xor_si128(p2, _mm_shuffle_epi8(tables[5][2], si));
+      p3 = _mm_xor_si128(p3, _mm_shuffle_epi8(tables[5][3], si));
+  
+      si = _mm_and_si128(v3, mask1);
+      p0 = _mm_xor_si128(p0, _mm_shuffle_epi8(tables[6][0], si));
+      p1 = _mm_xor_si128(p1, _mm_shuffle_epi8(tables[6][1], si));
+      p2 = _mm_xor_si128(p2, _mm_shuffle_epi8(tables[6][2], si));
+      p3 = _mm_xor_si128(p3, _mm_shuffle_epi8(tables[6][3], si));
+      
+      v3 = _mm_srli_epi32(v3, 4);
+      si = _mm_and_si128(v3, mask1);
+      p0 = _mm_xor_si128(p0, _mm_shuffle_epi8(tables[7][0], si));
+      p1 = _mm_xor_si128(p1, _mm_shuffle_epi8(tables[7][1], si));
+      p2 = _mm_xor_si128(p2, _mm_shuffle_epi8(tables[7][2], si));
+      p3 = _mm_xor_si128(p3, _mm_shuffle_epi8(tables[7][3], si));
+  
+      _mm_store_si128((__m128i *) d32, p0);
+      _mm_store_si128((__m128i *) (d32+4), p1);
+      _mm_store_si128((__m128i *) (d32+8), p2);
+      _mm_store_si128((__m128i *) (d32+12), p3);
+      d32 += 16;
+    } 
+  } else {
+    while (d32 != top) {
+  
+      v0 = _mm_load_si128((__m128i *) s32); s32 += 4;
+      v1 = _mm_load_si128((__m128i *) s32); s32 += 4;
+      v2 = _mm_load_si128((__m128i *) s32); s32 += 4;
+      v3 = _mm_load_si128((__m128i *) s32); s32 += 4;
+
+      si = _mm_and_si128(v0, mask1);
+      p0 = _mm_shuffle_epi8(tables[0][0], si);
+      p1 = _mm_shuffle_epi8(tables[0][1], si);
+      p2 = _mm_shuffle_epi8(tables[0][2], si);
+      p3 = _mm_shuffle_epi8(tables[0][3], si);
+      
+      v0 = _mm_srli_epi32(v0, 4);
+      si = _mm_and_si128(v0, mask1);
+      p0 = _mm_xor_si128(p0, _mm_shuffle_epi8(tables[1][0], si));
+      p1 = _mm_xor_si128(p1, _mm_shuffle_epi8(tables[1][1], si));
+      p2 = _mm_xor_si128(p2, _mm_shuffle_epi8(tables[1][2], si));
+      p3 = _mm_xor_si128(p3, _mm_shuffle_epi8(tables[1][3], si));
+  
+      si = _mm_and_si128(v1, mask1);
+      p0 = _mm_xor_si128(p0, _mm_shuffle_epi8(tables[2][0], si));
+      p1 = _mm_xor_si128(p1, _mm_shuffle_epi8(tables[2][1], si));
+      p2 = _mm_xor_si128(p2, _mm_shuffle_epi8(tables[2][2], si));
+      p3 = _mm_xor_si128(p3, _mm_shuffle_epi8(tables[2][3], si));
+      
+      v1 = _mm_srli_epi32(v1, 4);
+      si = _mm_and_si128(v1, mask1);
+      p0 = _mm_xor_si128(p0, _mm_shuffle_epi8(tables[3][0], si));
+      p1 = _mm_xor_si128(p1, _mm_shuffle_epi8(tables[3][1], si));
+      p2 = _mm_xor_si128(p2, _mm_shuffle_epi8(tables[3][2], si));
+      p3 = _mm_xor_si128(p3, _mm_shuffle_epi8(tables[3][3], si));
+  
+      si = _mm_and_si128(v2, mask1);
+      p0 = _mm_xor_si128(p0, _mm_shuffle_epi8(tables[4][0], si));
+      p1 = _mm_xor_si128(p1, _mm_shuffle_epi8(tables[4][1], si));
+      p2 = _mm_xor_si128(p2, _mm_shuffle_epi8(tables[4][2], si));
+      p3 = _mm_xor_si128(p3, _mm_shuffle_epi8(tables[4][3], si));
+      
+      v2 = _mm_srli_epi32(v2, 4);
+      si = _mm_and_si128(v2, mask1);
+      p0 = _mm_xor_si128(p0, _mm_shuffle_epi8(tables[5][0], si));
+      p1 = _mm_xor_si128(p1, _mm_shuffle_epi8(tables[5][1], si));
+      p2 = _mm_xor_si128(p2, _mm_shuffle_epi8(tables[5][2], si));
+      p3 = _mm_xor_si128(p3, _mm_shuffle_epi8(tables[5][3], si));
+  
+      si = _mm_and_si128(v3, mask1);
+      p0 = _mm_xor_si128(p0, _mm_shuffle_epi8(tables[6][0], si));
+      p1 = _mm_xor_si128(p1, _mm_shuffle_epi8(tables[6][1], si));
+      p2 = _mm_xor_si128(p2, _mm_shuffle_epi8(tables[6][2], si));
+      p3 = _mm_xor_si128(p3, _mm_shuffle_epi8(tables[6][3], si));
+      
+      v3 = _mm_srli_epi32(v3, 4);
+      si = _mm_and_si128(v3, mask1);
+      p0 = _mm_xor_si128(p0, _mm_shuffle_epi8(tables[7][0], si));
+      p1 = _mm_xor_si128(p1, _mm_shuffle_epi8(tables[7][1], si));
+      p2 = _mm_xor_si128(p2, _mm_shuffle_epi8(tables[7][2], si));
+      p3 = _mm_xor_si128(p3, _mm_shuffle_epi8(tables[7][3], si));
+  
+      _mm_store_si128((__m128i *) d32, p0);
+      _mm_store_si128((__m128i *) (d32+4), p1);
+      _mm_store_si128((__m128i *) (d32+8), p2);
+      _mm_store_si128((__m128i *) (d32+12), p3);
+      d32 += 16;
+    } 
+  }
+
+  gf_do_final_region_alignment(&rd);
+
+#endif
+}
+
+
+static
+void
+gf_w32_split_4_32_lazy_sse_multiply_region(gf_t *gf, void *src, void *dest, uint32_t val, int bytes, int xor)
+{
+#ifdef INTEL_SSSE3
+  gf_internal_t *h;
+  int i, j, k;
+  uint32_t pp, v, *s32, *d32, *top, tmp_table[16];
+  __m128i si, tables[8][4], p0, p1, p2, p3, mask1, v0, v1, v2, v3, mask8;
+  __m128i tv1, tv2, tv3, tv0;
+  uint8_t btable[16];
+  gf_region_data rd;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  h = (gf_internal_t *) gf->scratch;
+  pp = h->prim_poly;
+  
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 64);
+  gf_do_initial_region_alignment(&rd);
+
+  s32 = (uint32_t *) rd.s_start;
+  d32 = (uint32_t *) rd.d_start;
+  top = (uint32_t *) rd.d_top;
+
+  v = val;
+  for (i = 0; i < 8; i++) {
+    tmp_table[0] = 0;
+    for (j = 1; j < 16; j <<= 1) {
+      for (k = 0; k < j; k++) {
+        tmp_table[k^j] = (v ^ tmp_table[k]);
+      }
+      v = (v & GF_FIRST_BIT) ? ((v << 1) ^ pp) : (v << 1);
+    }
+    for (j = 0; j < 4; j++) {
+      for (k = 0; k < 16; k++) {
+        btable[k] = (uint8_t) tmp_table[k];
+        tmp_table[k] >>= 8;
+      }
+      tables[i][j] = _mm_loadu_si128((__m128i *) btable);
+    }
+  }
+
+  mask1 = _mm_set1_epi8(0xf);
+  mask8 = _mm_set1_epi16(0xff);
+
+  if (xor) {
+    while (d32 != top) {
+      v0 = _mm_load_si128((__m128i *) s32); s32 += 4;
+      v1 = _mm_load_si128((__m128i *) s32); s32 += 4;
+      v2 = _mm_load_si128((__m128i *) s32); s32 += 4;
+      v3 = _mm_load_si128((__m128i *) s32); s32 += 4;
+  
+      p0 = _mm_srli_epi16(v0, 8);
+      p1 = _mm_srli_epi16(v1, 8);
+      p2 = _mm_srli_epi16(v2, 8);
+      p3 = _mm_srli_epi16(v3, 8);
+
+      tv0 = _mm_and_si128(v0, mask8);
+      tv1 = _mm_and_si128(v1, mask8);
+      tv2 = _mm_and_si128(v2, mask8);
+      tv3 = _mm_and_si128(v3, mask8);
+
+      v0 = _mm_packus_epi16(p1, p0);
+      v1 = _mm_packus_epi16(tv1, tv0);
+      v2 = _mm_packus_epi16(p3, p2);
+      v3 = _mm_packus_epi16(tv3, tv2);
+
+      p0 = _mm_srli_epi16(v0, 8);
+      p1 = _mm_srli_epi16(v1, 8);
+      p2 = _mm_srli_epi16(v2, 8);
+      p3 = _mm_srli_epi16(v3, 8);
+
+      tv0 = _mm_and_si128(v0, mask8);
+      tv1 = _mm_and_si128(v1, mask8);
+      tv2 = _mm_and_si128(v2, mask8);
+      tv3 = _mm_and_si128(v3, mask8);
+
+      v0 = _mm_packus_epi16(p2, p0);
+      v1 = _mm_packus_epi16(p3, p1);
+      v2 = _mm_packus_epi16(tv2, tv0);
+      v3 = _mm_packus_epi16(tv3, tv1);
+
+      si = _mm_and_si128(v0, mask1);
+      p0 = _mm_shuffle_epi8(tables[6][0], si);
+      p1 = _mm_shuffle_epi8(tables[6][1], si);
+      p2 = _mm_shuffle_epi8(tables[6][2], si);
+      p3 = _mm_shuffle_epi8(tables[6][3], si);
+      
+      v0 = _mm_srli_epi32(v0, 4);
+      si = _mm_and_si128(v0, mask1);
+      p0 = _mm_xor_si128(p0, _mm_shuffle_epi8(tables[7][0], si));
+      p1 = _mm_xor_si128(p1, _mm_shuffle_epi8(tables[7][1], si));
+      p2 = _mm_xor_si128(p2, _mm_shuffle_epi8(tables[7][2], si));
+      p3 = _mm_xor_si128(p3, _mm_shuffle_epi8(tables[7][3], si));
+  
+      si = _mm_and_si128(v1, mask1);
+      p0 = _mm_xor_si128(p0, _mm_shuffle_epi8(tables[4][0], si));
+      p1 = _mm_xor_si128(p1, _mm_shuffle_epi8(tables[4][1], si));
+      p2 = _mm_xor_si128(p2, _mm_shuffle_epi8(tables[4][2], si));
+      p3 = _mm_xor_si128(p3, _mm_shuffle_epi8(tables[4][3], si));
+      
+      v1 = _mm_srli_epi32(v1, 4);
+      si = _mm_and_si128(v1, mask1);
+      p0 = _mm_xor_si128(p0, _mm_shuffle_epi8(tables[5][0], si));
+      p1 = _mm_xor_si128(p1, _mm_shuffle_epi8(tables[5][1], si));
+      p2 = _mm_xor_si128(p2, _mm_shuffle_epi8(tables[5][2], si));
+      p3 = _mm_xor_si128(p3, _mm_shuffle_epi8(tables[5][3], si));
+  
+      si = _mm_and_si128(v2, mask1);
+      p0 = _mm_xor_si128(p0, _mm_shuffle_epi8(tables[2][0], si));
+      p1 = _mm_xor_si128(p1, _mm_shuffle_epi8(tables[2][1], si));
+      p2 = _mm_xor_si128(p2, _mm_shuffle_epi8(tables[2][2], si));
+      p3 = _mm_xor_si128(p3, _mm_shuffle_epi8(tables[2][3], si));
+      
+      v2 = _mm_srli_epi32(v2, 4);
+      si = _mm_and_si128(v2, mask1);
+      p0 = _mm_xor_si128(p0, _mm_shuffle_epi8(tables[3][0], si));
+      p1 = _mm_xor_si128(p1, _mm_shuffle_epi8(tables[3][1], si));
+      p2 = _mm_xor_si128(p2, _mm_shuffle_epi8(tables[3][2], si));
+      p3 = _mm_xor_si128(p3, _mm_shuffle_epi8(tables[3][3], si));
+  
+      si = _mm_and_si128(v3, mask1);
+      p0 = _mm_xor_si128(p0, _mm_shuffle_epi8(tables[0][0], si));
+      p1 = _mm_xor_si128(p1, _mm_shuffle_epi8(tables[0][1], si));
+      p2 = _mm_xor_si128(p2, _mm_shuffle_epi8(tables[0][2], si));
+      p3 = _mm_xor_si128(p3, _mm_shuffle_epi8(tables[0][3], si));
+      
+      v3 = _mm_srli_epi32(v3, 4);
+      si = _mm_and_si128(v3, mask1);
+      p0 = _mm_xor_si128(p0, _mm_shuffle_epi8(tables[1][0], si));
+      p1 = _mm_xor_si128(p1, _mm_shuffle_epi8(tables[1][1], si));
+      p2 = _mm_xor_si128(p2, _mm_shuffle_epi8(tables[1][2], si));
+      p3 = _mm_xor_si128(p3, _mm_shuffle_epi8(tables[1][3], si));
+  
+      tv0 = _mm_unpackhi_epi8(p1, p3);
+      tv1 = _mm_unpackhi_epi8(p0, p2);
+      tv2 = _mm_unpacklo_epi8(p1, p3);
+      tv3 = _mm_unpacklo_epi8(p0, p2);
+
+      p0 = _mm_unpackhi_epi8(tv1, tv0);
+      p1 = _mm_unpacklo_epi8(tv1, tv0);
+      p2 = _mm_unpackhi_epi8(tv3, tv2);
+      p3 = _mm_unpacklo_epi8(tv3, tv2);
+
+      v0 = _mm_load_si128 ((__m128i *) d32);
+      v1 = _mm_load_si128 ((__m128i *) (d32+4));
+      v2 = _mm_load_si128 ((__m128i *) (d32+8));
+      v3 = _mm_load_si128 ((__m128i *) (d32+12));
+  
+      p0 = _mm_xor_si128(p0, v0);
+      p1 = _mm_xor_si128(p1, v1);
+      p2 = _mm_xor_si128(p2, v2);
+      p3 = _mm_xor_si128(p3, v3);
+
+      _mm_store_si128((__m128i *) d32, p0);
+      _mm_store_si128((__m128i *) (d32+4), p1);
+      _mm_store_si128((__m128i *) (d32+8), p2);
+      _mm_store_si128((__m128i *) (d32+12), p3);
+      d32 += 16;
+    } 
+  } else {
+    while (d32 != top) {
+      v0 = _mm_load_si128((__m128i *) s32); s32 += 4;
+      v1 = _mm_load_si128((__m128i *) s32); s32 += 4;
+      v2 = _mm_load_si128((__m128i *) s32); s32 += 4;
+      v3 = _mm_load_si128((__m128i *) s32); s32 += 4;
+ 
+      p0 = _mm_srli_epi16(v0, 8);
+      p1 = _mm_srli_epi16(v1, 8);
+      p2 = _mm_srli_epi16(v2, 8);
+      p3 = _mm_srli_epi16(v3, 8);
+      
+      tv0 = _mm_and_si128(v0, mask8);
+      tv1 = _mm_and_si128(v1, mask8);
+      tv2 = _mm_and_si128(v2, mask8);
+      tv3 = _mm_and_si128(v3, mask8);
+      
+      v0 = _mm_packus_epi16(p1, p0);
+      v1 = _mm_packus_epi16(tv1, tv0);
+      v2 = _mm_packus_epi16(p3, p2);
+      v3 = _mm_packus_epi16(tv3, tv2);
+      
+      p0 = _mm_srli_epi16(v0, 8);
+      p1 = _mm_srli_epi16(v1, 8);
+      p2 = _mm_srli_epi16(v2, 8);
+      p3 = _mm_srli_epi16(v3, 8);
+     
+      tv0 = _mm_and_si128(v0, mask8);
+      tv1 = _mm_and_si128(v1, mask8);
+      tv2 = _mm_and_si128(v2, mask8);
+      tv3 = _mm_and_si128(v3, mask8);
+      
+      v0 = _mm_packus_epi16(p2, p0);
+      v1 = _mm_packus_epi16(p3, p1);
+      v2 = _mm_packus_epi16(tv2, tv0);
+      v3 = _mm_packus_epi16(tv3, tv1);
+      
+      p0 = v0;
+      p1 = v1;
+      p2 = v2;
+      p3 = v3;
+
+      si = _mm_and_si128(v0, mask1);
+      p0 = _mm_shuffle_epi8(tables[6][0], si);
+      p1 = _mm_shuffle_epi8(tables[6][1], si);
+      p2 = _mm_shuffle_epi8(tables[6][2], si);
+      p3 = _mm_shuffle_epi8(tables[6][3], si);
+      
+      v0 = _mm_srli_epi32(v0, 4);
+      si = _mm_and_si128(v0, mask1);
+      p0 = _mm_xor_si128(p0, _mm_shuffle_epi8(tables[7][0], si));
+      p1 = _mm_xor_si128(p1, _mm_shuffle_epi8(tables[7][1], si));
+      p2 = _mm_xor_si128(p2, _mm_shuffle_epi8(tables[7][2], si));
+      p3 = _mm_xor_si128(p3, _mm_shuffle_epi8(tables[7][3], si));
+  
+      si = _mm_and_si128(v1, mask1);
+      p0 = _mm_xor_si128(p0, _mm_shuffle_epi8(tables[4][0], si));
+      p1 = _mm_xor_si128(p1, _mm_shuffle_epi8(tables[4][1], si));
+      p2 = _mm_xor_si128(p2, _mm_shuffle_epi8(tables[4][2], si));
+      p3 = _mm_xor_si128(p3, _mm_shuffle_epi8(tables[4][3], si));
+      
+      v1 = _mm_srli_epi32(v1, 4);
+      si = _mm_and_si128(v1, mask1);
+      p0 = _mm_xor_si128(p0, _mm_shuffle_epi8(tables[5][0], si));
+      p1 = _mm_xor_si128(p1, _mm_shuffle_epi8(tables[5][1], si));
+      p2 = _mm_xor_si128(p2, _mm_shuffle_epi8(tables[5][2], si));
+      p3 = _mm_xor_si128(p3, _mm_shuffle_epi8(tables[5][3], si));
+  
+      si = _mm_and_si128(v2, mask1);
+      p0 = _mm_xor_si128(p0, _mm_shuffle_epi8(tables[2][0], si));
+      p1 = _mm_xor_si128(p1, _mm_shuffle_epi8(tables[2][1], si));
+      p2 = _mm_xor_si128(p2, _mm_shuffle_epi8(tables[2][2], si));
+      p3 = _mm_xor_si128(p3, _mm_shuffle_epi8(tables[2][3], si));
+      
+      v2 = _mm_srli_epi32(v2, 4);
+      si = _mm_and_si128(v2, mask1);
+      p0 = _mm_xor_si128(p0, _mm_shuffle_epi8(tables[3][0], si));
+      p1 = _mm_xor_si128(p1, _mm_shuffle_epi8(tables[3][1], si));
+      p2 = _mm_xor_si128(p2, _mm_shuffle_epi8(tables[3][2], si));
+      p3 = _mm_xor_si128(p3, _mm_shuffle_epi8(tables[3][3], si));
+  
+      si = _mm_and_si128(v3, mask1);
+      p0 = _mm_xor_si128(p0, _mm_shuffle_epi8(tables[0][0], si));
+      p1 = _mm_xor_si128(p1, _mm_shuffle_epi8(tables[0][1], si));
+      p2 = _mm_xor_si128(p2, _mm_shuffle_epi8(tables[0][2], si));
+      p3 = _mm_xor_si128(p3, _mm_shuffle_epi8(tables[0][3], si));
+      
+      v3 = _mm_srli_epi32(v3, 4);
+      si = _mm_and_si128(v3, mask1);
+      p0 = _mm_xor_si128(p0, _mm_shuffle_epi8(tables[1][0], si));
+      p1 = _mm_xor_si128(p1, _mm_shuffle_epi8(tables[1][1], si));
+      p2 = _mm_xor_si128(p2, _mm_shuffle_epi8(tables[1][2], si));
+      p3 = _mm_xor_si128(p3, _mm_shuffle_epi8(tables[1][3], si)); 
+  
+      tv0 = _mm_unpackhi_epi8(p1, p3);
+      tv1 = _mm_unpackhi_epi8(p0, p2);
+      tv2 = _mm_unpacklo_epi8(p1, p3);
+      tv3 = _mm_unpacklo_epi8(p0, p2);
+      
+      p0 = _mm_unpackhi_epi8(tv1, tv0);
+      p1 = _mm_unpacklo_epi8(tv1, tv0);
+      p2 = _mm_unpackhi_epi8(tv3, tv2);
+      p3 = _mm_unpacklo_epi8(tv3, tv2);
+      
+      _mm_store_si128((__m128i *) d32, p0);
+      _mm_store_si128((__m128i *) (d32+4), p1);
+      _mm_store_si128((__m128i *) (d32+8), p2);
+      _mm_store_si128((__m128i *) (d32+12), p3);
+      d32 += 16;
+    } 
+  }
+  gf_do_final_region_alignment(&rd);
+
+#endif
+}
+
+static 
+int gf_w32_split_init(gf_t *gf)
+{
+  gf_internal_t *h;
+  struct gf_split_2_32_lazy_data *ld2;
+  struct gf_split_4_32_lazy_data *ld4;
+  struct gf_w32_split_8_8_data *d8;
+  struct gf_split_8_32_lazy_data *d32;
+  struct gf_split_16_32_lazy_data *d16;
+  uint32_t p, basep;
+  int i, j, exp, ispclmul, issse3;
+
+  ispclmul = 0;
+#if defined(INTEL_SSE4_PCLMUL)
+  ispclmul = 1;
+#endif
+
+  issse3 = 0;
+#ifdef INTEL_SSSE3
+  issse3 = 1;
+#endif
+
+  h = (gf_internal_t *) gf->scratch;
+
+  /* Defaults */
+  
+  gf->inverse.w32 = gf_w32_euclid;
+
+  /* JSP: First handle single multiplication:  
+     If args == 8, then we're doing split 8 8.  
+     Otherwise, if PCLMUL, we use that.
+     Otherwise, we use bytwo_p.
+   */
+
+  if (h->arg1 == 8 && h->arg2 == 8) {
+    gf->multiply.w32 = gf_w32_split_8_8_multiply;
+  } else if (ispclmul) {
+    if ((0xfffe0000 & h->prim_poly) == 0){
+      gf->multiply.w32 = gf_w32_clm_multiply_2;
+    } else if ((0xffc00000 & h->prim_poly) == 0){
+      gf->multiply.w32 = gf_w32_clm_multiply_3;
+    } else if ((0xfe000000 & h->prim_poly) == 0){
+     gf->multiply.w32 = gf_w32_clm_multiply_4;
+    }
+  } else {
+    gf->multiply.w32 = gf_w32_bytwo_p_multiply;
+  }
+
+  /* Easy cases: 16/32 and 2/32 */
+
+  if ((h->arg1 == 16 && h->arg2 == 32) || (h->arg1 == 32 && h->arg2 == 16)) {
+    d16 = (struct gf_split_16_32_lazy_data *) h->private;
+    d16->last_value = 0;
+    gf->multiply_region.w32 = gf_w32_split_16_32_lazy_multiply_region;
+    return 1;
+  }
+
+  if ((h->arg1 == 2 && h->arg2 == 32) || (h->arg1 == 32 && h->arg2 == 2)) {
+    ld2 = (struct gf_split_2_32_lazy_data *) h->private;
+    ld2->last_value = 0;
+    #ifdef INTEL_SSSE3
+      if (!(h->region_type & GF_REGION_NOSSE))
+        gf->multiply_region.w32 = gf_w32_split_2_32_lazy_sse_multiply_region;
+      else
+        gf->multiply_region.w32 = gf_w32_split_2_32_lazy_multiply_region;
+    #else
+      gf->multiply_region.w32 = gf_w32_split_2_32_lazy_multiply_region;
+      if(h->region_type & GF_REGION_SSE) return 0;
+    #endif
+    return 1;
+  } 
+
+  /* 4/32 or Default + SSE - There is no ALTMAP/NOSSE. */
+
+  if ((h->arg1 == 4 && h->arg2 == 32) || (h->arg1 == 32 && h->arg2 == 4) ||
+      (issse3 && h->mult_type == GF_REGION_DEFAULT)) {
+    ld4 = (struct gf_split_4_32_lazy_data *) h->private;
+    ld4->last_value = 0;
+    if ((h->region_type & GF_REGION_NOSSE) || !issse3) {
+      gf->multiply_region.w32 = gf_w32_split_4_32_lazy_multiply_region;
+    } else if (h->region_type & GF_REGION_ALTMAP) {
+      gf->multiply_region.w32 = gf_w32_split_4_32_lazy_sse_altmap_multiply_region;
+    } else {
+      gf->multiply_region.w32 = gf_w32_split_4_32_lazy_sse_multiply_region;
+    }
+    return 1;
+  } 
+
+  /* 8/32 or Default + no SSE */
+
+  if ((h->arg1 == 8 && h->arg2 == 32) || (h->arg1 == 32 && h->arg2 == 8) || 
+       h->mult_type == GF_MULT_DEFAULT) {
+    d32 = (struct gf_split_8_32_lazy_data *) h->private;
+    d32->last_value = 0;
+    gf->multiply_region.w32 = gf_w32_split_8_32_lazy_multiply_region;
+    return 1;
+  }
+
+  /* Finally, if args == 8, then we have to set up the tables here. */
+
+  if (h->arg1 == 8 && h->arg2 == 8) {
+    d8 = (struct gf_w32_split_8_8_data *) h->private;
+    d8->last_value = 0;
+    gf->multiply.w32 = gf_w32_split_8_8_multiply;
+    gf->multiply_region.w32 = gf_w32_split_8_32_lazy_multiply_region;
+    basep = 1;
+    for (exp = 0; exp < 7; exp++) {
+      for (j = 0; j < 256; j++) d8->tables[exp][0][j] = 0;
+      for (i = 0; i < 256; i++) d8->tables[exp][i][0] = 0;
+      d8->tables[exp][1][1] = basep;
+      for (i = 2; i < 256; i++) {
+        if (i&1) {
+          p = d8->tables[exp][i^1][1];
+          d8->tables[exp][i][1] = p ^ basep;
+        } else {
+          p = d8->tables[exp][i>>1][1];
+          d8->tables[exp][i][1] = GF_MULTBY_TWO(p);
+        }
+      }
+      for (i = 1; i < 256; i++) {
+        p = d8->tables[exp][i][1];
+        for (j = 1; j < 256; j++) {
+          if (j&1) {
+            d8->tables[exp][i][j] = d8->tables[exp][i][j^1] ^ p;
+          } else {
+            d8->tables[exp][i][j] = GF_MULTBY_TWO(d8->tables[exp][i][j>>1]);
+          }
+        }
+      }
+      for (i = 0; i < 8; i++) basep = GF_MULTBY_TWO(basep);
+    }
+    return 1;
+  }
+
+  /* If we get here, then the arguments were bad. */
+
+  return 0;
+}
+
+static
+int gf_w32_group_init(gf_t *gf)
+{
+  uint32_t i, j, p, index;
+  struct gf_w32_group_data *gd;
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  int g_r, g_s;
+
+  g_s = h->arg1;
+  g_r = h->arg2;
+
+  gd = (struct gf_w32_group_data *) h->private;
+  gd->shift = (uint32_t *) (&(gd->memory));
+  gd->reduce = gd->shift + (1 << g_s);
+
+  gd->rmask = (1 << g_r) - 1;
+  gd->rmask <<= 32;
+
+  gd->tshift = 32 % g_s;
+  if (gd->tshift == 0) gd->tshift = g_s;
+  gd->tshift = (32 - gd->tshift);
+  gd->tshift = ((gd->tshift-1)/g_r) * g_r;
+
+  gd->reduce[0] = 0;
+  for (i = 0; i < (1 << g_r); i++) {
+    p = 0;
+    index = 0;
+    for (j = 0; j < g_r; j++) {
+      if (i & (1 << j)) {
+        p ^= (h->prim_poly << j);
+        index ^= (1 << j);
+        index ^= (h->prim_poly >> (32-j));
+      }
+    }
+    gd->reduce[index] = p;
+  }
+
+  if (g_s == g_r) {
+    gf->multiply.w32 = gf_w32_group_s_equals_r_multiply;
+    gf->multiply_region.w32 = gf_w32_group_s_equals_r_multiply_region; 
+  } else {
+    gf->multiply.w32 = gf_w32_group_multiply;
+    gf->multiply_region.w32 = gf_w32_group_multiply_region;
+  }
+  gf->divide.w32 = NULL;
+  gf->inverse.w32 = gf_w32_euclid;
+
+  return 1;
+}
+
+
+static
+uint32_t
+gf_w32_composite_multiply_recursive(gf_t *gf, uint32_t a, uint32_t b)
+{
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  gf_t *base_gf = h->base_gf;
+  uint32_t b0 = b & 0x0000ffff;
+  uint32_t b1 = (b & 0xffff0000) >> 16;
+  uint32_t a0 = a & 0x0000ffff;
+  uint32_t a1 = (a & 0xffff0000) >> 16;
+  uint32_t a1b1;
+  uint32_t rv;
+  a1b1 = base_gf->multiply.w32(base_gf, a1, b1);
+
+  rv = ((base_gf->multiply.w32(base_gf, a1, b0) ^ base_gf->multiply.w32(base_gf, a0, b1) ^ base_gf->multiply.w32(base_gf, a1b1, h->prim_poly)) << 16) | (base_gf->multiply.w32(base_gf, a0, b0) ^ a1b1);
+  return rv;
+}
+
+/* JSP: This could be made faster. Someday, when I'm bored. */
+
+static
+uint32_t
+gf_w32_composite_multiply_inline(gf_t *gf, uint32_t a, uint32_t b)
+{
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  uint32_t b0 = b & 0x0000ffff;
+  uint32_t b1 = b >> 16;
+  uint32_t a0 = a & 0x0000ffff;
+  uint32_t a1 = a >> 16;
+  uint32_t a1b1, prod;
+  uint16_t *log, *alog;
+  struct gf_w32_composite_data *cd;
+
+  cd = (struct gf_w32_composite_data *) h->private;
+  log = cd->log;
+  alog = cd->alog;
+
+  a1b1 = GF_W16_INLINE_MULT(log, alog, a1, b1);
+  prod = GF_W16_INLINE_MULT(log, alog, a1, b0);
+  prod ^= GF_W16_INLINE_MULT(log, alog, a0, b1);
+  prod ^= GF_W16_INLINE_MULT(log, alog, a1b1, h->prim_poly);
+  prod <<= 16;
+  prod ^= GF_W16_INLINE_MULT(log, alog, a0, b0);
+  prod ^= a1b1;
+  return prod;
+}
+
+/*
+ * Composite field division trick (explained in 2007 tech report)
+ *
+ * Compute a / b = a*b^-1, where p(x) = x^2 + sx + 1
+ *
+ * let c = b^-1
+ *
+ * c*b = (s*b1c1+b1c0+b0c1)x+(b1c1+b0c0)
+ *
+ * want (s*b1c1+b1c0+b0c1) = 0 and (b1c1+b0c0) = 1
+ *
+ * let d = b1c1 and d+1 = b0c0
+ *
+ * solve s*b1c1+b1c0+b0c1 = 0
+ *
+ * solution: d = (b1b0^-1)(b1b0^-1+b0b1^-1+s)^-1
+ *
+ * c0 = (d+1)b0^-1
+ * c1 = d*b1^-1
+ *
+ * a / b = a * c
+ */
+
+static
+uint32_t
+gf_w32_composite_inverse(gf_t *gf, uint32_t a)
+{
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  gf_t *base_gf = h->base_gf;
+  uint16_t a0 = a & 0x0000ffff;
+  uint16_t a1 = (a & 0xffff0000) >> 16;
+  uint16_t c0, c1, d, tmp;
+  uint32_t c;
+  uint16_t a0inv, a1inv;
+
+  if (a0 == 0) {
+    a1inv = base_gf->inverse.w32(base_gf, a1);
+    c0 = base_gf->multiply.w32(base_gf, a1inv, h->prim_poly);
+    c1 = a1inv;
+  } else if (a1 == 0) {
+    c0 = base_gf->inverse.w32(base_gf, a0);
+    c1 = 0;
+  } else {
+    a1inv = base_gf->inverse.w32(base_gf, a1);
+    a0inv = base_gf->inverse.w32(base_gf, a0);
+
+    d = base_gf->multiply.w32(base_gf, a1, a0inv);
+
+    tmp = (base_gf->multiply.w32(base_gf, a1, a0inv) ^ base_gf->multiply.w32(base_gf, a0, a1inv) ^ h->prim_poly);
+    tmp = base_gf->inverse.w32(base_gf, tmp);
+
+    d = base_gf->multiply.w32(base_gf, d, tmp);
+
+    c0 = base_gf->multiply.w32(base_gf, (d^1), a0inv);
+    c1 = base_gf->multiply.w32(base_gf, d, a1inv);
+  }
+
+  c = c0 | (c1 << 16);
+
+  return c;
+}
+
+static
+void
+gf_w32_composite_multiply_region(gf_t *gf, void *src, void *dest, uint32_t val, int bytes, int xor)
+{
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  gf_t *base_gf = h->base_gf;
+  uint32_t b0 = val & 0x0000ffff;
+  uint32_t b1 = (val & 0xffff0000) >> 16;
+  uint32_t *s32, *d32, *top;
+  uint16_t a0, a1, a1b1, *log, *alog;
+  uint32_t prod;
+  gf_region_data rd;
+  struct gf_w32_composite_data *cd;
+
+  cd = (struct gf_w32_composite_data *) h->private;
+  log = cd->log;
+  alog = cd->alog;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 4);
+  
+  s32 = rd.s_start;
+  d32 = rd.d_start;
+  top = rd.d_top;
+
+  if (log == NULL) {
+    if (xor) {
+      while (d32 < top) {
+        a0 = *s32 & 0x0000ffff;
+        a1 = (*s32 & 0xffff0000) >> 16;
+        a1b1 = base_gf->multiply.w32(base_gf, a1, b1);
+  
+        *d32 ^= ((base_gf->multiply.w32(base_gf, a0, b0) ^ a1b1) |
+                  ((base_gf->multiply.w32(base_gf, a1, b0) ^ base_gf->multiply.w32(base_gf, a0, b1) ^ base_gf->multiply.w32(base_gf, a1b1, h->prim_poly)) << 16)); 
+        s32++;
+        d32++;
+      }
+    } else {
+      while (d32 < top) {
+        a0 = *s32 & 0x0000ffff;
+        a1 = (*s32 & 0xffff0000) >> 16;
+        a1b1 = base_gf->multiply.w32(base_gf, a1, b1);
+  
+        *d32 = ((base_gf->multiply.w32(base_gf, a0, b0) ^ a1b1) |
+                  ((base_gf->multiply.w32(base_gf, a1, b0) ^ base_gf->multiply.w32(base_gf, a0, b1) ^ base_gf->multiply.w32(base_gf, a1b1, h->prim_poly)) << 16)); 
+        s32++;
+        d32++;
+      }
+    }
+  } else {
+    if (xor) {
+      while (d32 < top) {
+        a0 = *s32 & 0x0000ffff;
+        a1 = (*s32 & 0xffff0000) >> 16;
+        a1b1 = GF_W16_INLINE_MULT(log, alog, a1, b1);
+
+        prod = GF_W16_INLINE_MULT(log, alog, a1, b0);
+        prod ^= GF_W16_INLINE_MULT(log, alog, a0, b1);
+        prod ^= GF_W16_INLINE_MULT(log, alog, a1b1, h->prim_poly);
+        prod <<= 16;
+        prod ^= GF_W16_INLINE_MULT(log, alog, a0, b0);
+        prod ^= a1b1;
+        *d32 ^= prod;
+        s32++;
+        d32++;
+      }
+    } else {
+      while (d32 < top) {
+        a0 = *s32 & 0x0000ffff;
+        a1 = (*s32 & 0xffff0000) >> 16;
+        a1b1 = GF_W16_INLINE_MULT(log, alog, a1, b1);
+  
+        prod = GF_W16_INLINE_MULT(log, alog, a1, b0);
+        prod ^= GF_W16_INLINE_MULT(log, alog, a0, b1);
+        prod ^= GF_W16_INLINE_MULT(log, alog, a1b1, h->prim_poly);
+        prod <<= 16;
+        prod ^= GF_W16_INLINE_MULT(log, alog, a0, b0);
+        prod ^= a1b1;
+        
+        *d32 = prod;
+        s32++;
+        d32++;
+      }
+    }
+  }
+}
+
+static
+void
+gf_w32_composite_multiply_region_alt(gf_t *gf, void *src, void *dest, uint32_t val, int bytes, int xor)
+{
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  gf_t *base_gf = h->base_gf;
+  uint16_t    val0 = val & 0x0000ffff;
+  uint16_t    val1 = (val & 0xffff0000) >> 16;
+  gf_region_data rd;
+  int sub_reg_size;
+  uint8_t *slow, *shigh;
+  uint8_t *dlow, *dhigh, *top;
+
+  /* JSP: I want the two pointers aligned wrt each other on 16 byte
+     boundaries.  So I'm going to make sure that the area on
+     which the two operate is a multiple of 32. Of course, that
+     junks up the mapping, but so be it -- that's why we have extract_word.... */
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 32);
+  gf_do_initial_region_alignment(&rd);
+
+  slow = (uint8_t *) rd.s_start;
+  dlow = (uint8_t *) rd.d_start;
+  top = (uint8_t *)  rd.d_top;
+  sub_reg_size = (top - dlow)/2;
+  shigh = slow + sub_reg_size;
+  dhigh = dlow + sub_reg_size;
+  
+  base_gf->multiply_region.w32(base_gf, slow, dlow, val0, sub_reg_size, xor);
+  base_gf->multiply_region.w32(base_gf, shigh, dlow, val1, sub_reg_size, 1);
+  base_gf->multiply_region.w32(base_gf, slow, dhigh, val1, sub_reg_size, xor);
+  base_gf->multiply_region.w32(base_gf, shigh, dhigh, val0, sub_reg_size, 1);
+  base_gf->multiply_region.w32(base_gf, shigh, dhigh, base_gf->multiply.w32(base_gf, h->prim_poly, val1), sub_reg_size, 1);
+
+  gf_do_final_region_alignment(&rd);
+}
+
+static
+int gf_w32_composite_init(gf_t *gf)
+{
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  struct gf_w32_composite_data *cd;
+
+  if (h->base_gf == NULL) return 0;
+
+  cd = (struct gf_w32_composite_data *) h->private;
+  cd->log = gf_w16_get_log_table(h->base_gf);
+  cd->alog = gf_w16_get_mult_alog_table(h->base_gf);
+
+  if (h->region_type & GF_REGION_ALTMAP) {
+    gf->multiply_region.w32 = gf_w32_composite_multiply_region_alt;
+  } else {
+    gf->multiply_region.w32 = gf_w32_composite_multiply_region;
+  }
+
+  if (cd->log == NULL) {
+    gf->multiply.w32 = gf_w32_composite_multiply_recursive;
+  } else {
+    gf->multiply.w32 = gf_w32_composite_multiply_inline; 
+  }
+  gf->divide.w32 = NULL;
+  gf->inverse.w32 = gf_w32_composite_inverse;
+
+  return 1;
+}
+
+
+
+int gf_w32_scratch_size(int mult_type, int region_type, int divide_type, int arg1, int arg2)
+{
+  int issse3 = 0;
+
+#ifdef INTEL_SSSE3
+  issse3 = 1;
+#endif
+
+  switch(mult_type)
+  {
+    case GF_MULT_BYTWO_p:
+    case GF_MULT_BYTWO_b:
+      return sizeof(gf_internal_t) + sizeof(struct gf_w32_bytwo_data) + 64;
+      break;
+    case GF_MULT_GROUP: 
+      return sizeof(gf_internal_t) + sizeof(struct gf_w32_group_data) +
+               sizeof(uint32_t) * (1 << arg1) +
+               sizeof(uint32_t) * (1 << arg2) + 64;
+      break;
+    case GF_MULT_DEFAULT:
+
+    case GF_MULT_SPLIT_TABLE: 
+        if (arg1 == 8 && arg2 == 8){
+          return sizeof(gf_internal_t) + sizeof(struct gf_w32_split_8_8_data) + 64;
+        }
+        if ((arg1 == 16 && arg2 == 32) || (arg2 == 16 && arg1 == 32)) {
+          return sizeof(gf_internal_t) + sizeof(struct gf_split_16_32_lazy_data) + 64;
+        }
+        if ((arg1 == 2 && arg2 == 32) || (arg2 == 2 && arg1 == 32)) {
+          return sizeof(gf_internal_t) + sizeof(struct gf_split_2_32_lazy_data) + 64;
+        }
+        if ((arg1 == 8 && arg2 == 32) || (arg2 == 8 && arg1 == 32) || 
+             (mult_type == GF_MULT_DEFAULT && !issse3)) {
+          return sizeof(gf_internal_t) + sizeof(struct gf_split_8_32_lazy_data) + 64;
+        }
+        if ((arg1 == 4 && arg2 == 32) || 
+            (arg2 == 4 && arg1 == 32) ||
+            mult_type == GF_MULT_DEFAULT) {
+          return sizeof(gf_internal_t) + sizeof(struct gf_split_4_32_lazy_data) + 64;
+        }
+        return 0;
+    case GF_MULT_CARRY_FREE:
+      return sizeof(gf_internal_t);
+      break;
+    case GF_MULT_SHIFT:
+      return sizeof(gf_internal_t);
+      break;
+    case GF_MULT_COMPOSITE:
+      return sizeof(gf_internal_t) + sizeof(struct gf_w32_composite_data) + 64;
+      break;
+
+    default:
+      return 0;
+   }
+   return 0;
+}
+
+int gf_w32_init(gf_t *gf)
+{
+  gf_internal_t *h;
+
+  h = (gf_internal_t *) gf->scratch;
+  
+  /* Allen: set default primitive polynomial / irreducible polynomial if needed */
+
+  if (h->prim_poly == 0) {
+    if (h->mult_type == GF_MULT_COMPOSITE) { 
+      h->prim_poly = gf_composite_get_default_poly(h->base_gf);
+      if (h->prim_poly == 0) return 0; /* This shouldn't happen */
+    } else { 
+
+      /* Allen: use the following primitive polynomial to make carryless multiply work more efficiently for GF(2^32).*/
+
+      /* h->prim_poly = 0xc5; */
+
+      /* Allen: The following is the traditional primitive polynomial for GF(2^32) */
+
+      h->prim_poly = 0x400007;
+    } 
+  }
+
+  /* No leading one */
+
+  if(h->mult_type != GF_MULT_COMPOSITE) h->prim_poly &= 0xffffffff;
+    
+  gf->multiply.w32 = NULL;
+  gf->divide.w32 = NULL;
+  gf->inverse.w32 = NULL;
+  gf->multiply_region.w32 = NULL;
+
+  switch(h->mult_type) {
+    case GF_MULT_CARRY_FREE:  if (gf_w32_cfm_init(gf) == 0) return 0; break;
+    case GF_MULT_SHIFT:       if (gf_w32_shift_init(gf) == 0) return 0; break;
+    case GF_MULT_COMPOSITE:   if (gf_w32_composite_init(gf) == 0) return 0; break;
+    case GF_MULT_DEFAULT: 
+    case GF_MULT_SPLIT_TABLE: if (gf_w32_split_init(gf) == 0) return 0; break;
+    case GF_MULT_GROUP:       if (gf_w32_group_init(gf) == 0) return 0; break;
+    case GF_MULT_BYTWO_p:   
+    case GF_MULT_BYTWO_b:     if (gf_w32_bytwo_init(gf) == 0) return 0; break;
+    default: return 0;
+  }
+  if (h->divide_type == GF_DIVIDE_EUCLID) {
+    gf->divide.w32 = gf_w32_divide_from_inverse;
+    gf->inverse.w32 = gf_w32_euclid;
+  } else if (h->divide_type == GF_DIVIDE_MATRIX) {
+    gf->divide.w32 = gf_w32_divide_from_inverse;
+    gf->inverse.w32 = gf_w32_matrix;
+  }
+
+  if (gf->inverse.w32 != NULL && gf->divide.w32 == NULL) {
+    gf->divide.w32 = gf_w32_divide_from_inverse;
+  }
+  if (gf->inverse.w32 == NULL && gf->divide.w32 != NULL) {
+    gf->inverse.w32 = gf_w32_inverse_from_divide;
+  }
+  if (h->region_type == GF_REGION_CAUCHY) {
+    gf->extract_word.w32 = gf_wgen_extract_word;
+    gf->multiply_region.w32 = gf_wgen_cauchy_region;
+  } else if (h->region_type & GF_REGION_ALTMAP) {
+    if (h->mult_type == GF_MULT_COMPOSITE) {
+      gf->extract_word.w32 = gf_w32_composite_extract_word;
+    } else {
+      gf->extract_word.w32 = gf_w32_split_extract_word;
+    }
+  } else {
+    gf->extract_word.w32 = gf_w32_extract_word;
+  }
+  return 1;
+}
diff --git a/src/erasure-code/jerasure/gf-complete/src/gf_w4.c b/src/erasure-code/jerasure/gf-complete/src/gf_w4.c
new file mode 100644
index 0000000..65cbf23
--- /dev/null
+++ b/src/erasure-code/jerasure/gf-complete/src/gf_w4.c
@@ -0,0 +1,2081 @@
+/*
+ * GF-Complete: A Comprehensive Open Source Library for Galois Field Arithmetic
+ * James S. Plank, Ethan L. Miller, Kevin M. Greenan,
+ * Benjamin A. Arnold, John A. Burnum, Adam W. Disney, Allen C. McBride.
+ *
+ * gf_w4.c
+ *
+ * Routines for 4-bit Galois fields
+ */
+
+#include "gf_int.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+#define GF_FIELD_WIDTH      4
+#define GF_DOUBLE_WIDTH     (GF_FIELD_WIDTH*2)
+#define GF_FIELD_SIZE       (1 << GF_FIELD_WIDTH)
+#define GF_MULT_GROUP_SIZE       (GF_FIELD_SIZE-1)
+
+/* ------------------------------------------------------------
+   JSP: Each implementation has its own data, which is allocated
+   at one time as part of the handle. For that reason, it 
+   shouldn't be hierarchical -- i.e. one should be able to 
+   allocate it with one call to malloc. */
+
+struct gf_logtable_data {
+    uint8_t      log_tbl[GF_FIELD_SIZE];
+    uint8_t      antilog_tbl[GF_FIELD_SIZE * 2];
+    uint8_t      *antilog_tbl_div;
+};
+
+struct gf_single_table_data {
+    uint8_t      mult[GF_FIELD_SIZE][GF_FIELD_SIZE];
+    uint8_t      div[GF_FIELD_SIZE][GF_FIELD_SIZE];
+};
+
+struct gf_double_table_data {
+    uint8_t      div[GF_FIELD_SIZE][GF_FIELD_SIZE];
+    uint8_t      mult[GF_FIELD_SIZE][GF_FIELD_SIZE*GF_FIELD_SIZE];
+};
+struct gf_quad_table_data {
+    uint8_t      div[GF_FIELD_SIZE][GF_FIELD_SIZE];
+    uint16_t     mult[GF_FIELD_SIZE][(1<<16)];
+};
+
+struct gf_quad_table_lazy_data {
+    uint8_t      div[GF_FIELD_SIZE][GF_FIELD_SIZE];
+    uint8_t      smult[GF_FIELD_SIZE][GF_FIELD_SIZE];
+    uint16_t     mult[(1 << 16)];
+};
+
+struct gf_bytwo_data {
+    uint64_t prim_poly;
+    uint64_t mask1;
+    uint64_t mask2;
+};
+
+#define AB2(ip, am1 ,am2, b, t1, t2) {\
+  t1 = (b << 1) & am1;\
+  t2 = b & am2; \
+  t2 = ((t2 << 1) - (t2 >> (GF_FIELD_WIDTH-1))); \
+  b = (t1 ^ (t2 & ip));}
+
+#define SSE_AB2(pp, m1, va, t1, t2) {\
+          t1 = _mm_and_si128(_mm_slli_epi64(va, 1), m1); \
+          t2 = _mm_and_si128(va, _mm_set1_epi8(0x88)); \
+          t2 = _mm_sub_epi64 (_mm_slli_epi64(t2, 1), _mm_srli_epi64(t2, (GF_FIELD_WIDTH-1))); \
+          va = _mm_xor_si128(t1, _mm_and_si128(t2, pp)); }
+
+/* ------------------------------------------------------------
+   JSP: These are basic and work from multiple implementations.
+ */
+
+static
+inline
+gf_val_32_t gf_w4_inverse_from_divide (gf_t *gf, gf_val_32_t a)
+{
+  return gf->divide.w32(gf, 1, a);
+}
+
+static
+inline
+gf_val_32_t gf_w4_divide_from_inverse (gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  b = gf->inverse.w32(gf, b);
+  return gf->multiply.w32(gf, a, b);
+}
+
+static
+inline
+gf_val_32_t gf_w4_euclid (gf_t *gf, gf_val_32_t b)
+{
+  gf_val_32_t e_i, e_im1, e_ip1;
+  gf_val_32_t d_i, d_im1, d_ip1;
+  gf_val_32_t y_i, y_im1, y_ip1;
+  gf_val_32_t c_i;
+
+  if (b == 0) return -1;
+  e_im1 = ((gf_internal_t *) (gf->scratch))->prim_poly;
+  e_i = b;
+  d_im1 = 4;
+  for (d_i = d_im1; ((1 << d_i) & e_i) == 0; d_i--) ;
+  y_i = 1;
+  y_im1 = 0;
+
+  while (e_i != 1) {
+    e_ip1 = e_im1;
+    d_ip1 = d_im1;
+    c_i = 0;
+
+    while (d_ip1 >= d_i) {
+      c_i ^= (1 << (d_ip1 - d_i));
+      e_ip1 ^= (e_i << (d_ip1 - d_i));
+      if (e_ip1 == 0) return 0;
+      while ((e_ip1 & (1 << d_ip1)) == 0) d_ip1--;
+    }
+
+    y_ip1 = y_im1 ^ gf->multiply.w32(gf, c_i, y_i);
+    y_im1 = y_i;
+    y_i = y_ip1;
+
+    e_im1 = e_i;
+    d_im1 = d_i;
+    e_i = e_ip1;
+    d_i = d_ip1;
+  }
+
+  return y_i;
+}
+
+static 
+gf_val_32_t gf_w4_extract_word(gf_t *gf, void *start, int bytes, int index)
+{
+  uint8_t *r8, v;
+
+  r8 = (uint8_t *) start;
+  v = r8[index/2];
+  if (index%2) {
+    return v >> 4;
+  } else {
+    return v&0xf;
+  }
+}
+
+
+static
+inline
+gf_val_32_t gf_w4_matrix (gf_t *gf, gf_val_32_t b)
+{
+  return gf_bitmatrix_inverse(b, 4, ((gf_internal_t *) (gf->scratch))->prim_poly);
+}
+
+
+static
+inline
+gf_val_32_t
+gf_w4_shift_multiply (gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  uint8_t product, i, pp;
+  gf_internal_t *h;
+  
+  h = (gf_internal_t *) gf->scratch;
+  pp = h->prim_poly;
+
+  product = 0;
+
+  for (i = 0; i < GF_FIELD_WIDTH; i++) { 
+    if (a & (1 << i)) product ^= (b << i);
+  }
+  for (i = (GF_FIELD_WIDTH*2-2); i >= GF_FIELD_WIDTH; i--) {
+    if (product & (1 << i)) product ^= (pp << (i-GF_FIELD_WIDTH)); 
+  }
+  return product;
+}
+
+/* Ben: This function works, but it is 33% slower than the normal shift mult */
+
+static
+inline
+gf_val_32_t
+gf_w4_clm_multiply (gf_t *gf, gf_val_32_t a4, gf_val_32_t b4)
+{
+  gf_val_32_t rv = 0;
+
+#if defined(INTEL_SSE4_PCLMUL)
+
+  __m128i         a, b;
+  __m128i         result;
+  __m128i         prim_poly;
+  __m128i         w;
+  gf_internal_t * h = gf->scratch;
+
+  a = _mm_insert_epi32 (_mm_setzero_si128(), a4, 0);
+  b = _mm_insert_epi32 (a, b4, 0);
+
+  prim_poly = _mm_set_epi32(0, 0, 0, (uint32_t)(h->prim_poly & 0x1fULL));
+
+  /* Do the initial multiply */
+
+  result = _mm_clmulepi64_si128 (a, b, 0);
+
+  /* Ben/JSP: Do prim_poly reduction once. We are guaranteed that we will only
+     have to do the reduction only once, because (w-2)/z == 1. Where
+     z is equal to the number of zeros after the leading 1.
+
+     _mm_clmulepi64_si128 is the carryless multiply operation. Here
+     _mm_srli_epi64 shifts the result to the right by 4 bits. This allows
+     us to multiply the prim_poly by the leading bits of the result. We
+     then xor the result of that operation back with the result. */
+
+  w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_epi64 (result, 4), 0);
+  result = _mm_xor_si128 (result, w);
+
+  /* Extracts 32 bit value from result. */
+
+  rv = ((gf_val_32_t)_mm_extract_epi32(result, 0));
+#endif
+  return rv;
+}
+
+static
+void
+gf_w4_multiply_region_from_single(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int 
+    xor)
+{
+  gf_region_data rd;
+  uint8_t *s8;
+  uint8_t *d8;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 1);
+  gf_do_initial_region_alignment(&rd);
+
+  s8 = (uint8_t *) rd.s_start;
+  d8 = (uint8_t *) rd.d_start;
+
+  if (xor) {
+    while (d8 < ((uint8_t *) rd.d_top)) {
+      *d8 ^= (gf->multiply.w32(gf, val, (*s8 & 0xf)) | 
+             ((gf->multiply.w32(gf, val, (*s8 >> 4))) << 4));
+      d8++;
+      s8++;
+    }
+  } else {
+    while (d8 < ((uint8_t *) rd.d_top)) {
+      *d8 = (gf->multiply.w32(gf, val, (*s8 & 0xf)) | 
+             ((gf->multiply.w32(gf, val, (*s8 >> 4))) << 4));
+      d8++;
+      s8++;
+    }
+  }
+  gf_do_final_region_alignment(&rd);
+}
+
+/* ------------------------------------------------------------
+  IMPLEMENTATION: LOG_TABLE: 
+
+  JSP: This is a basic log-antilog implementation.  
+       I'm not going to spend any time optimizing it because the
+       other techniques are faster for both single and region
+       operations. 
+ */
+
+static
+inline
+gf_val_32_t
+gf_w4_log_multiply (gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  struct gf_logtable_data *ltd;
+    
+  ltd = (struct gf_logtable_data *) ((gf_internal_t *) (gf->scratch))->private;
+  return (a == 0 || b == 0) ? 0 : ltd->antilog_tbl[(unsigned)(ltd->log_tbl[a] + ltd->log_tbl[b])];
+}
+
+static
+inline
+gf_val_32_t
+gf_w4_log_divide (gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  int log_sum = 0;
+  struct gf_logtable_data *ltd;
+    
+  if (a == 0 || b == 0) return 0;
+  ltd = (struct gf_logtable_data *) ((gf_internal_t *) (gf->scratch))->private;
+
+  log_sum = ltd->log_tbl[a] - ltd->log_tbl[b];
+  return (ltd->antilog_tbl_div[log_sum]);
+}
+
+static
+void 
+gf_w4_log_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  int i;
+  uint8_t lv, b, c;
+  uint8_t *s8, *d8;
+  
+  struct gf_logtable_data *ltd;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  ltd = (struct gf_logtable_data *) ((gf_internal_t *) (gf->scratch))->private;
+  s8 = (uint8_t *) src;
+  d8 = (uint8_t *) dest;
+
+  lv = ltd->log_tbl[val];
+
+  for (i = 0; i < bytes; i++) {
+    c = (xor) ? d8[i] : 0;
+    b = (s8[i] >> GF_FIELD_WIDTH);
+    c ^= (b == 0) ? 0 : (ltd->antilog_tbl[lv + ltd->log_tbl[b]] << GF_FIELD_WIDTH);
+    b = (s8[i] & 0xf);
+    c ^= (b == 0) ? 0 : ltd->antilog_tbl[lv + ltd->log_tbl[b]];
+    d8[i] = c;
+  }
+}
+
+static 
+int gf_w4_log_init(gf_t *gf)
+{
+  gf_internal_t *h;
+  struct gf_logtable_data *ltd;
+  int i, b;
+
+  h = (gf_internal_t *) gf->scratch;
+  ltd = h->private;
+
+  for (i = 0; i < GF_FIELD_SIZE; i++)
+    ltd->log_tbl[i]=0;
+
+  ltd->antilog_tbl_div = ltd->antilog_tbl + (GF_FIELD_SIZE-1);
+  b = 1;
+  i = 0;
+  do {
+    if (ltd->log_tbl[b] != 0 && i != 0) {
+      fprintf(stderr, "Cannot construct log table: Polynomial is not primitive.\n\n");
+      return 0;
+    }
+    ltd->log_tbl[b] = i;
+    ltd->antilog_tbl[i] = b;
+    ltd->antilog_tbl[i+GF_FIELD_SIZE-1] = b;
+    b <<= 1;
+    i++;
+    if (b & GF_FIELD_SIZE) b = b ^ h->prim_poly;
+  } while (b != 1);
+
+  if (i != GF_FIELD_SIZE - 1) {
+    _gf_errno = GF_E_LOGPOLY;
+    return 0;
+  }
+    
+  gf->inverse.w32 = gf_w4_inverse_from_divide;
+  gf->divide.w32 = gf_w4_log_divide;
+  gf->multiply.w32 = gf_w4_log_multiply;
+  gf->multiply_region.w32 = gf_w4_log_multiply_region;
+  return 1;
+}
+
+/* ------------------------------------------------------------
+  IMPLEMENTATION: SINGLE TABLE: JSP. 
+ */
+
+static
+inline
+gf_val_32_t
+gf_w4_single_table_multiply (gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  struct gf_single_table_data *std;
+    
+  std = (struct gf_single_table_data *) ((gf_internal_t *) (gf->scratch))->private;
+  return std->mult[a][b];
+}
+
+static
+inline
+gf_val_32_t
+gf_w4_single_table_divide (gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  struct gf_single_table_data *std;
+    
+  std = (struct gf_single_table_data *) ((gf_internal_t *) (gf->scratch))->private;
+  return std->div[a][b];
+}
+
+static
+void 
+gf_w4_single_table_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  int i;
+  uint8_t b, c;
+  uint8_t *s8, *d8;
+  
+  struct gf_single_table_data *std;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  std = (struct gf_single_table_data *) ((gf_internal_t *) (gf->scratch))->private;
+  s8 = (uint8_t *) src;
+  d8 = (uint8_t *) dest;
+
+  for (i = 0; i < bytes; i++) {
+    c = (xor) ? d8[i] : 0;
+    b = (s8[i] >> GF_FIELD_WIDTH);
+    c ^= (std->mult[val][b] << GF_FIELD_WIDTH);
+    b = (s8[i] & 0xf);
+    c ^= (std->mult[val][b]);
+    d8[i] = c;
+  }
+}
+
+#define MM_PRINT(s, r) { uint8_t blah[16]; printf("%-12s", s); _mm_storeu_si128((__m128i *)blah, r); for (i = 0; i < 16; i++) printf(" %02x", blah[i]); printf("\n"); }
+
+#ifdef INTEL_SSSE3
+static
+void 
+gf_w4_single_table_sse_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  gf_region_data rd;
+  uint8_t *base, *sptr, *dptr, *top;
+  __m128i  tl, loset, r, va, th;
+  
+  struct gf_single_table_data *std;
+    
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 16);
+
+  std = (struct gf_single_table_data *) ((gf_internal_t *) (gf->scratch))->private;
+  base = (uint8_t *) std->mult;
+  base += (val << GF_FIELD_WIDTH);
+
+  gf_do_initial_region_alignment(&rd);
+
+  tl = _mm_loadu_si128((__m128i *)base);
+  th = _mm_slli_epi64(tl, 4);
+  loset = _mm_set1_epi8 (0x0f);
+
+  sptr = rd.s_start;
+  dptr = rd.d_start;
+  top = rd.s_top;
+
+  while (sptr < (uint8_t *) top) {
+    va = _mm_load_si128 ((__m128i *)(sptr));
+    r = _mm_and_si128 (loset, va);
+    r = _mm_shuffle_epi8 (tl, r);
+    va = _mm_srli_epi64 (va, 4);
+    va = _mm_and_si128 (loset, va);
+    va = _mm_shuffle_epi8 (th, va);
+    r = _mm_xor_si128 (r, va);
+    va = (xor) ? _mm_load_si128 ((__m128i *)(dptr)) : _mm_setzero_si128(); 
+    r = _mm_xor_si128 (r, va);
+    _mm_store_si128 ((__m128i *)(dptr), r);
+    dptr += 16;
+    sptr += 16;
+  }
+  gf_do_final_region_alignment(&rd);
+
+}
+#endif
+
+static 
+int gf_w4_single_table_init(gf_t *gf)
+{
+  gf_internal_t *h;
+  struct gf_single_table_data *std;
+  int a, b, prod;
+
+
+  h = (gf_internal_t *) gf->scratch;
+  std = (struct gf_single_table_data *)h->private;
+
+  bzero(std->mult, sizeof(uint8_t) * GF_FIELD_SIZE * GF_FIELD_SIZE);
+  bzero(std->div, sizeof(uint8_t) * GF_FIELD_SIZE * GF_FIELD_SIZE);
+
+  for (a = 1; a < GF_FIELD_SIZE; a++) {
+    for (b = 1; b < GF_FIELD_SIZE; b++) {
+      prod = gf_w4_shift_multiply(gf, a, b);
+      std->mult[a][b] = prod;
+      std->div[prod][b] = a;
+    }
+  }
+
+  gf->inverse.w32 = NULL;
+  gf->divide.w32 = gf_w4_single_table_divide;
+  gf->multiply.w32 = gf_w4_single_table_multiply;
+  #ifdef INTEL_SSSE3
+    if(h->region_type & (GF_REGION_NOSSE | GF_REGION_CAUCHY))
+      gf->multiply_region.w32 = gf_w4_single_table_multiply_region;
+    else
+      gf->multiply_region.w32 = gf_w4_single_table_sse_multiply_region;
+  #else
+    gf->multiply_region.w32 = gf_w4_single_table_multiply_region;
+    if (h->region_type & GF_REGION_SSE) return 0;
+  #endif
+
+  return 1;
+}
+
+/* ------------------------------------------------------------
+  IMPLEMENTATION: DOUBLE TABLE: JSP. 
+ */
+
+static
+inline
+gf_val_32_t
+gf_w4_double_table_multiply (gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  struct gf_double_table_data *std;
+    
+  std = (struct gf_double_table_data *) ((gf_internal_t *) (gf->scratch))->private;
+  return std->mult[a][b];
+}
+
+static
+inline
+gf_val_32_t
+gf_w4_double_table_divide (gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  struct gf_double_table_data *std;
+    
+  std = (struct gf_double_table_data *) ((gf_internal_t *) (gf->scratch))->private;
+  return std->div[a][b];
+}
+
+static
+void 
+gf_w4_double_table_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  int i;
+  uint8_t *s8, *d8, *base;
+  gf_region_data rd;
+  struct gf_double_table_data *std;
+    
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 8);
+
+  std = (struct gf_double_table_data *) ((gf_internal_t *) (gf->scratch))->private;
+  s8 = (uint8_t *) src;
+  d8 = (uint8_t *) dest;
+  base = (uint8_t *) std->mult;
+  base += (val << GF_DOUBLE_WIDTH);
+
+  if (xor) {
+    for (i = 0; i < bytes; i++) d8[i] ^= base[s8[i]];
+  } else {
+    for (i = 0; i < bytes; i++) d8[i] = base[s8[i]];
+  }
+}
+
+static 
+int gf_w4_double_table_init(gf_t *gf)
+{
+  gf_internal_t *h;
+  struct gf_double_table_data *std;
+  int a, b, c, prod, ab;
+  uint8_t mult[GF_FIELD_SIZE][GF_FIELD_SIZE];
+
+  h = (gf_internal_t *) gf->scratch;
+  std = (struct gf_double_table_data *)h->private;
+
+  bzero(mult, sizeof(uint8_t) * GF_FIELD_SIZE * GF_FIELD_SIZE);
+  bzero(std->div, sizeof(uint8_t) * GF_FIELD_SIZE * GF_FIELD_SIZE);
+
+  for (a = 1; a < GF_FIELD_SIZE; a++) {
+    for (b = 1; b < GF_FIELD_SIZE; b++) {
+      prod = gf_w4_shift_multiply(gf, a, b);
+      mult[a][b] = prod;
+      std->div[prod][b] = a;
+    }
+  }
+  bzero(std->mult, sizeof(uint8_t) * GF_FIELD_SIZE * GF_FIELD_SIZE * GF_FIELD_SIZE);
+  for (a = 0; a < GF_FIELD_SIZE; a++) {
+    for (b = 0; b < GF_FIELD_SIZE; b++) {
+      ab = mult[a][b];
+      for (c = 0; c < GF_FIELD_SIZE; c++) {
+        std->mult[a][(b << 4) | c] = ((ab << 4) | mult[a][c]);
+      }
+    }
+  }
+
+  gf->inverse.w32 = NULL;
+  gf->divide.w32 = gf_w4_double_table_divide;
+  gf->multiply.w32 = gf_w4_double_table_multiply;
+  gf->multiply_region.w32 = gf_w4_double_table_multiply_region;
+  return 1;
+}
+
+
+static
+inline
+gf_val_32_t
+gf_w4_quad_table_lazy_divide (gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  struct gf_quad_table_lazy_data *std;
+    
+  std = (struct gf_quad_table_lazy_data *) ((gf_internal_t *) (gf->scratch))->private;
+  return std->div[a][b];
+}
+
+static
+inline
+gf_val_32_t
+gf_w4_quad_table_lazy_multiply (gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  struct gf_quad_table_lazy_data *std;
+    
+  std = (struct gf_quad_table_lazy_data *) ((gf_internal_t *) (gf->scratch))->private;
+  return std->smult[a][b];
+}
+
+static
+inline
+gf_val_32_t
+gf_w4_quad_table_divide (gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  struct gf_quad_table_data *std;
+    
+  std = (struct gf_quad_table_data *) ((gf_internal_t *) (gf->scratch))->private;
+  return std->div[a][b];
+}
+
+static
+inline
+gf_val_32_t
+gf_w4_quad_table_multiply (gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  struct gf_quad_table_data *std;
+  uint16_t v;
+    
+  std = (struct gf_quad_table_data *) ((gf_internal_t *) (gf->scratch))->private;
+  v = std->mult[a][b];
+  return v;
+}
+
+static
+void 
+gf_w4_quad_table_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  uint16_t *base;
+  gf_region_data rd;
+  struct gf_quad_table_data *std;
+  struct gf_quad_table_lazy_data *ltd;
+  gf_internal_t *h;
+  int a, b, c, d, va, vb, vc, vd;
+    
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  h = (gf_internal_t *) (gf->scratch);
+  if (h->region_type & GF_REGION_LAZY) {
+    ltd = (struct gf_quad_table_lazy_data *) ((gf_internal_t *) (gf->scratch))->private;
+    base = ltd->mult;
+    for (a = 0; a < 16; a++) {
+      va = (ltd->smult[val][a] << 12);
+      for (b = 0; b < 16; b++) {
+        vb = (ltd->smult[val][b] << 8);
+        for (c = 0; c < 16; c++) {
+          vc = (ltd->smult[val][c] << 4);
+          for (d = 0; d < 16; d++) {
+            vd = ltd->smult[val][d];
+            base[(a << 12) | (b << 8) | (c << 4) | d ] = (va | vb | vc | vd);
+          }
+        }
+      }
+    }
+  } else {
+    std = (struct gf_quad_table_data *) ((gf_internal_t *) (gf->scratch))->private;
+    base = &(std->mult[val][0]);
+  }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 8);
+  gf_do_initial_region_alignment(&rd);
+  gf_two_byte_region_table_multiply(&rd, base);
+  gf_do_final_region_alignment(&rd);
+}
+
+static 
+int gf_w4_quad_table_init(gf_t *gf)
+{
+  gf_internal_t *h;
+  struct gf_quad_table_data *std;
+  int prod, val, a, b, c, d, va, vb, vc, vd;
+  uint8_t mult[GF_FIELD_SIZE][GF_FIELD_SIZE];
+
+  h = (gf_internal_t *) gf->scratch;
+  std = (struct gf_quad_table_data *)h->private;
+
+  bzero(mult, sizeof(uint8_t) * GF_FIELD_SIZE * GF_FIELD_SIZE);
+  bzero(std->div, sizeof(uint8_t) * GF_FIELD_SIZE * GF_FIELD_SIZE);
+
+  for (a = 1; a < GF_FIELD_SIZE; a++) {
+    for (b = 1; b < GF_FIELD_SIZE; b++) {
+      prod = gf_w4_shift_multiply(gf, a, b);
+      mult[a][b] = prod;
+      std->div[prod][b] = a;
+    }
+  }
+
+  for (val = 0; val < 16; val++) {
+    for (a = 0; a < 16; a++) {
+      va = (mult[val][a] << 12);
+      for (b = 0; b < 16; b++) {
+        vb = (mult[val][b] << 8);
+        for (c = 0; c < 16; c++) {
+          vc = (mult[val][c] << 4);
+          for (d = 0; d < 16; d++) {
+            vd = mult[val][d];
+            std->mult[val][(a << 12) | (b << 8) | (c << 4) | d ] = (va | vb | vc | vd);
+          }
+        }
+      }
+    }
+  }
+
+  gf->inverse.w32 = NULL;
+  gf->divide.w32 = gf_w4_quad_table_divide;
+  gf->multiply.w32 = gf_w4_quad_table_multiply;
+  gf->multiply_region.w32 = gf_w4_quad_table_multiply_region;
+  return 1;
+}
+static 
+int gf_w4_quad_table_lazy_init(gf_t *gf)
+{
+  gf_internal_t *h;
+  struct gf_quad_table_lazy_data *std;
+  int a, b, prod, loga, logb;
+  uint8_t log_tbl[GF_FIELD_SIZE];
+  uint8_t antilog_tbl[GF_FIELD_SIZE*2];
+
+  h = (gf_internal_t *) gf->scratch;
+  std = (struct gf_quad_table_lazy_data *)h->private;
+
+  b = 1;
+  for (a = 0; a < GF_MULT_GROUP_SIZE; a++) {
+      log_tbl[b] = a;
+      antilog_tbl[a] = b;
+      antilog_tbl[a+GF_MULT_GROUP_SIZE] = b;
+      b <<= 1;
+      if (b & GF_FIELD_SIZE) {
+          b = b ^ h->prim_poly;
+      }
+  }
+
+  bzero(std->smult, sizeof(uint8_t) * GF_FIELD_SIZE * GF_FIELD_SIZE);
+  bzero(std->div, sizeof(uint8_t) * GF_FIELD_SIZE * GF_FIELD_SIZE);
+
+  for (a = 1; a < GF_FIELD_SIZE; a++) {
+    loga = log_tbl[a];
+    for (b = 1; b < GF_FIELD_SIZE; b++) {
+      logb = log_tbl[b];
+      prod = antilog_tbl[loga+logb];
+      std->smult[a][b] = prod;
+      std->div[prod][b] = a;
+    }
+  }
+
+  gf->inverse.w32 = NULL;
+  gf->divide.w32 = gf_w4_quad_table_lazy_divide;
+  gf->multiply.w32 = gf_w4_quad_table_lazy_multiply;
+  gf->multiply_region.w32 = gf_w4_quad_table_multiply_region;
+  return 1;
+}
+
+static 
+int gf_w4_table_init(gf_t *gf)
+{
+  int rt;
+  gf_internal_t *h;
+  int issse3 = 0;
+
+#ifdef INTEL_SSSE3
+  issse3 = 1;
+#endif
+
+  h = (gf_internal_t *) gf->scratch;
+  rt = (h->region_type);
+
+  if (h->mult_type == GF_MULT_DEFAULT && !issse3) rt |= GF_REGION_DOUBLE_TABLE;
+
+  if (rt & GF_REGION_DOUBLE_TABLE) {
+    return gf_w4_double_table_init(gf);
+  } else if (rt & GF_REGION_QUAD_TABLE) {
+    if (rt & GF_REGION_LAZY) {
+      return gf_w4_quad_table_lazy_init(gf);
+    } else {
+      return gf_w4_quad_table_init(gf);
+    }
+    return gf_w4_double_table_init(gf);
+  } else {
+    return gf_w4_single_table_init(gf);
+  }
+  return 0;
+}
+
+/* ------------------------------------------------------------
+   JSP: GF_MULT_BYTWO_p and _b: See the paper.
+*/
+
+static
+inline
+gf_val_32_t
+gf_w4_bytwo_p_multiply (gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  uint32_t prod, pp, pmask, amask;
+  gf_internal_t *h;
+  
+  h = (gf_internal_t *) gf->scratch;
+  pp = h->prim_poly;
+
+  
+  prod = 0;
+  pmask = 0x8;
+  amask = 0x8;
+
+  while (amask != 0) {
+    if (prod & pmask) {
+      prod = ((prod << 1) ^ pp);
+    } else {
+      prod <<= 1;
+    }
+    if (a & amask) prod ^= b;
+    amask >>= 1;
+  }
+  return prod;
+}
+
+static
+inline
+gf_val_32_t
+gf_w4_bytwo_b_multiply (gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  uint32_t prod, pp, bmask;
+  gf_internal_t *h;
+  
+  h = (gf_internal_t *) gf->scratch;
+  pp = h->prim_poly;
+
+  prod = 0;
+  bmask = 0x8;
+
+  while (1) {
+    if (a & 1) prod ^= b;
+    a >>= 1;
+    if (a == 0) return prod;
+    if (b & bmask) {
+      b = ((b << 1) ^ pp);
+    } else {
+      b <<= 1;
+    }
+  }
+}
+
+static
+void 
+gf_w4_bytwo_p_nosse_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  uint64_t *s64, *d64, t1, t2, ta, prod, amask;
+  gf_region_data rd;
+  struct gf_bytwo_data *btd;
+    
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  btd = (struct gf_bytwo_data *) ((gf_internal_t *) (gf->scratch))->private;
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 8);
+  gf_do_initial_region_alignment(&rd);
+
+  s64 = (uint64_t *) rd.s_start;
+  d64 = (uint64_t *) rd.d_start;
+
+  if (xor) {
+    while (s64 < (uint64_t *) rd.s_top) {
+      prod = 0;
+      amask = 0x8;
+      ta = *s64;
+      while (amask != 0) {
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, prod, t1, t2);
+        if (val & amask) prod ^= ta;
+        amask >>= 1;
+      }
+      *d64 ^= prod;
+      d64++;
+      s64++;
+    }
+  } else { 
+    while (s64 < (uint64_t *) rd.s_top) {
+      prod = 0;
+      amask = 0x8;
+      ta = *s64;
+      while (amask != 0) {
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, prod, t1, t2);
+        if (val & amask) prod ^= ta;
+        amask >>= 1;
+      }
+      *d64 = prod;
+      d64++;
+      s64++;
+    }
+  }
+  gf_do_final_region_alignment(&rd);
+}
+
+#define BYTWO_P_ONESTEP {\
+      SSE_AB2(pp, m1, prod, t1, t2); \
+      t1 = _mm_and_si128(v, one); \
+      t1 = _mm_sub_epi8(t1, one); \
+      t1 = _mm_and_si128(t1, ta); \
+      prod = _mm_xor_si128(prod, t1); \
+      v = _mm_srli_epi64(v, 1); }
+
+#ifdef INTEL_SSE2
+static
+void
+gf_w4_bytwo_p_sse_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  int i;
+  uint8_t *s8, *d8;
+  uint8_t vrev;
+  __m128i pp, m1, ta, prod, t1, t2, tp, one, v;
+  struct gf_bytwo_data *btd;
+  gf_region_data rd;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  btd = (struct gf_bytwo_data *) ((gf_internal_t *) (gf->scratch))->private;
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 16);
+  gf_do_initial_region_alignment(&rd);
+
+  vrev = 0;
+  for (i = 0; i < 4; i++) {
+    vrev <<= 1;
+    if (!(val & (1 << i))) vrev |= 1;
+  }
+
+  s8 = (uint8_t *) rd.s_start;
+  d8 = (uint8_t *) rd.d_start;
+
+  pp = _mm_set1_epi8(btd->prim_poly&0xff);
+  m1 = _mm_set1_epi8((btd->mask1)&0xff);
+  one = _mm_set1_epi8(1);
+
+  while (d8 < (uint8_t *) rd.d_top) {
+    prod = _mm_setzero_si128();
+    v = _mm_set1_epi8(vrev);
+    ta = _mm_load_si128((__m128i *) s8);
+    tp = (!xor) ? _mm_setzero_si128() : _mm_load_si128((__m128i *) d8);
+    BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP;
+    _mm_store_si128((__m128i *) d8, _mm_xor_si128(prod, tp));
+    d8 += 16;
+    s8 += 16;
+  }
+  gf_do_final_region_alignment(&rd);
+}
+#endif
+
+/*
+static
+void 
+gf_w4_bytwo_b_sse_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+#ifdef INTEL_SSE2
+  uint8_t *d8, *s8, tb;
+  __m128i pp, m1, m2, t1, t2, va, vb;
+  struct gf_bytwo_data *btd;
+  gf_region_data rd;
+    
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 16);
+  gf_do_initial_region_alignment(&rd);
+
+  s8 = (uint8_t *) rd.s_start;
+  d8 = (uint8_t *) rd.d_start;
+
+  btd = (struct gf_bytwo_data *) ((gf_internal_t *) (gf->scratch))->private;
+
+  pp = _mm_set1_epi8(btd->prim_poly&0xff);
+  m1 = _mm_set1_epi8((btd->mask1)&0xff);
+  m2 = _mm_set1_epi8((btd->mask2)&0xff);
+
+  if (xor) {
+    while (d8 < (uint8_t *) rd.d_top) {
+      va = _mm_load_si128 ((__m128i *)(s8));
+      vb = _mm_load_si128 ((__m128i *)(d8));
+      tb = val;
+      while (1) {
+        if (tb & 1) vb = _mm_xor_si128(vb, va);
+        tb >>= 1;
+        if (tb == 0) break;
+        SSE_AB2(pp, m1, m2, va, t1, t2);
+      }
+      _mm_store_si128((__m128i *)d8, vb);
+      d8 += 16;
+      s8 += 16;
+    }
+  } else {
+    while (d8 < (uint8_t *) rd.d_top) {
+      va = _mm_load_si128 ((__m128i *)(s8));
+      vb = _mm_setzero_si128 ();
+      tb = val;
+      while (1) {
+        if (tb & 1) vb = _mm_xor_si128(vb, va);
+        tb >>= 1;
+        if (tb == 0) break;
+        t1 = _mm_and_si128(_mm_slli_epi64(va, 1), m1);
+        t2 = _mm_and_si128(va, m2);
+        t2 = _mm_sub_epi64 (
+          _mm_slli_epi64(t2, 1), _mm_srli_epi64(t2, (GF_FIELD_WIDTH-1)));
+        va = _mm_xor_si128(t1, _mm_and_si128(t2, pp));
+      }
+      _mm_store_si128((__m128i *)d8, vb);
+      d8 += 16;
+      s8 += 16;
+    }
+  }
+  gf_do_final_region_alignment(&rd);
+#endif
+}
+*/
+
+#ifdef INTEL_SSE2
+static 
+void
+gf_w4_bytwo_b_sse_region_2_noxor(gf_region_data *rd, struct gf_bytwo_data *btd)
+{
+  uint8_t *d8, *s8;
+  __m128i pp, m1, t1, t2, va;
+
+  s8 = (uint8_t *) rd->s_start;
+  d8 = (uint8_t *) rd->d_start;
+
+  pp = _mm_set1_epi8(btd->prim_poly&0xff);
+  m1 = _mm_set1_epi8((btd->mask1)&0xff);
+
+  while (d8 < (uint8_t *) rd->d_top) {
+    va = _mm_load_si128 ((__m128i *)(s8));
+    SSE_AB2(pp, m1, va, t1, t2);
+    _mm_store_si128((__m128i *)d8, va);
+    d8 += 16;
+    s8 += 16;
+  }
+}
+#endif
+
+#ifdef INTEL_SSE2
+static 
+void
+gf_w4_bytwo_b_sse_region_2_xor(gf_region_data *rd, struct gf_bytwo_data *btd)
+{
+  uint8_t *d8, *s8;
+  __m128i pp, m1, t1, t2, va, vb;
+
+  s8 = (uint8_t *) rd->s_start;
+  d8 = (uint8_t *) rd->d_start;
+
+  pp = _mm_set1_epi8(btd->prim_poly&0xff);
+  m1 = _mm_set1_epi8((btd->mask1)&0xff);
+
+  while (d8 < (uint8_t *) rd->d_top) {
+    va = _mm_load_si128 ((__m128i *)(s8));
+    SSE_AB2(pp, m1, va, t1, t2);
+    vb = _mm_load_si128 ((__m128i *)(d8));
+    vb = _mm_xor_si128(vb, va);
+    _mm_store_si128((__m128i *)d8, vb);
+    d8 += 16;
+    s8 += 16;
+  }
+}
+#endif
+
+#ifdef INTEL_SSE2
+static 
+void
+gf_w4_bytwo_b_sse_region_4_noxor(gf_region_data *rd, struct gf_bytwo_data *btd)
+{
+  uint8_t *d8, *s8;
+  __m128i pp, m1, t1, t2, va;
+
+  s8 = (uint8_t *) rd->s_start;
+  d8 = (uint8_t *) rd->d_start;
+
+  pp = _mm_set1_epi8(btd->prim_poly&0xff);
+  m1 = _mm_set1_epi8((btd->mask1)&0xff);
+
+  while (d8 < (uint8_t *) rd->d_top) {
+    va = _mm_load_si128 ((__m128i *)(s8));
+    SSE_AB2(pp, m1, va, t1, t2);
+    SSE_AB2(pp, m1, va, t1, t2);
+    _mm_store_si128((__m128i *)d8, va);
+    d8 += 16;
+    s8 += 16;
+  }
+}
+#endif
+
+#ifdef INTEL_SSE2
+static 
+void
+gf_w4_bytwo_b_sse_region_4_xor(gf_region_data *rd, struct gf_bytwo_data *btd)
+{
+  uint8_t *d8, *s8;
+  __m128i pp, m1, t1, t2, va, vb;
+
+  s8 = (uint8_t *) rd->s_start;
+  d8 = (uint8_t *) rd->d_start;
+
+  pp = _mm_set1_epi8(btd->prim_poly&0xff);
+  m1 = _mm_set1_epi8((btd->mask1)&0xff);
+
+  while (d8 < (uint8_t *) rd->d_top) {
+    va = _mm_load_si128 ((__m128i *)(s8));
+    SSE_AB2(pp, m1, va, t1, t2);
+    SSE_AB2(pp, m1, va, t1, t2);
+    vb = _mm_load_si128 ((__m128i *)(d8));
+    vb = _mm_xor_si128(vb, va);
+    _mm_store_si128((__m128i *)d8, vb);
+    d8 += 16;
+    s8 += 16;
+  }
+}
+#endif
+
+
+#ifdef INTEL_SSE2
+static 
+void
+gf_w4_bytwo_b_sse_region_3_noxor(gf_region_data *rd, struct gf_bytwo_data *btd)
+{
+  uint8_t *d8, *s8;
+  __m128i pp, m1, t1, t2, va, vb;
+
+  s8 = (uint8_t *) rd->s_start;
+  d8 = (uint8_t *) rd->d_start;
+
+  pp = _mm_set1_epi8(btd->prim_poly&0xff);
+  m1 = _mm_set1_epi8((btd->mask1)&0xff);
+
+  while (d8 < (uint8_t *) rd->d_top) {
+    va = _mm_load_si128 ((__m128i *)(s8));
+    vb = va;
+    SSE_AB2(pp, m1, va, t1, t2);
+    va = _mm_xor_si128(va, vb);
+    _mm_store_si128((__m128i *)d8, va);
+    d8 += 16;
+    s8 += 16;
+  }
+}
+#endif
+
+#ifdef INTEL_SSE2
+static 
+void
+gf_w4_bytwo_b_sse_region_3_xor(gf_region_data *rd, struct gf_bytwo_data *btd)
+{
+  uint8_t *d8, *s8;
+  __m128i pp, m1, t1, t2, va, vb;
+
+  s8 = (uint8_t *) rd->s_start;
+  d8 = (uint8_t *) rd->d_start;
+
+  pp = _mm_set1_epi8(btd->prim_poly&0xff);
+  m1 = _mm_set1_epi8((btd->mask1)&0xff);
+
+  while (d8 < (uint8_t *) rd->d_top) {
+    va = _mm_load_si128 ((__m128i *)(s8));
+    vb = _mm_xor_si128(_mm_load_si128 ((__m128i *)(d8)), va);
+    SSE_AB2(pp, m1, va, t1, t2);
+    vb = _mm_xor_si128(vb, va);
+    _mm_store_si128((__m128i *)d8, vb);
+    d8 += 16;
+    s8 += 16;
+  }
+}
+#endif
+
+#ifdef INTEL_SSE2
+static 
+void
+gf_w4_bytwo_b_sse_region_5_noxor(gf_region_data *rd, struct gf_bytwo_data *btd)
+{
+  uint8_t *d8, *s8;
+  __m128i pp, m1, t1, t2, va, vb;
+
+  s8 = (uint8_t *) rd->s_start;
+  d8 = (uint8_t *) rd->d_start;
+
+  pp = _mm_set1_epi8(btd->prim_poly&0xff);
+  m1 = _mm_set1_epi8((btd->mask1)&0xff);
+
+  while (d8 < (uint8_t *) rd->d_top) {
+    va = _mm_load_si128 ((__m128i *)(s8));
+    vb = va;
+    SSE_AB2(pp, m1, va, t1, t2);
+    SSE_AB2(pp, m1, va, t1, t2);
+    va = _mm_xor_si128(va, vb);
+    _mm_store_si128((__m128i *)d8, va);
+    d8 += 16;
+    s8 += 16;
+  }
+}
+#endif
+
+#ifdef INTEL_SSE2
+static 
+void
+gf_w4_bytwo_b_sse_region_5_xor(gf_region_data *rd, struct gf_bytwo_data *btd)
+{
+  uint8_t *d8, *s8;
+  __m128i pp, m1, t1, t2, va, vb;
+
+  s8 = (uint8_t *) rd->s_start;
+  d8 = (uint8_t *) rd->d_start;
+
+  pp = _mm_set1_epi8(btd->prim_poly&0xff);
+  m1 = _mm_set1_epi8((btd->mask1)&0xff);
+
+  while (d8 < (uint8_t *) rd->d_top) {
+    va = _mm_load_si128 ((__m128i *)(s8));
+    vb = _mm_xor_si128(_mm_load_si128 ((__m128i *)(d8)), va);
+    SSE_AB2(pp, m1, va, t1, t2);
+    SSE_AB2(pp, m1, va, t1, t2);
+    vb = _mm_xor_si128(vb, va);
+    _mm_store_si128((__m128i *)d8, vb);
+    d8 += 16;
+    s8 += 16;
+  }
+}
+#endif
+
+#ifdef INTEL_SSE2
+static 
+void
+gf_w4_bytwo_b_sse_region_7_noxor(gf_region_data *rd, struct gf_bytwo_data *btd)
+{
+  uint8_t *d8, *s8;
+  __m128i pp, m1, t1, t2, va, vb;
+
+  s8 = (uint8_t *) rd->s_start;
+  d8 = (uint8_t *) rd->d_start;
+
+  pp = _mm_set1_epi8(btd->prim_poly&0xff);
+  m1 = _mm_set1_epi8((btd->mask1)&0xff);
+
+  while (d8 < (uint8_t *) rd->d_top) {
+    va = _mm_load_si128 ((__m128i *)(s8));
+    vb = va;
+    SSE_AB2(pp, m1, va, t1, t2);
+    vb = _mm_xor_si128(va, vb);
+    SSE_AB2(pp, m1, va, t1, t2);
+    va = _mm_xor_si128(va, vb);
+    _mm_store_si128((__m128i *)d8, va);
+    d8 += 16;
+    s8 += 16;
+  }
+}
+#endif
+
+#ifdef INTEL_SSE2
+static 
+void
+gf_w4_bytwo_b_sse_region_7_xor(gf_region_data *rd, struct gf_bytwo_data *btd)
+{
+  uint8_t *d8, *s8;
+  __m128i pp, m1, t1, t2, va, vb;
+
+  s8 = (uint8_t *) rd->s_start;
+  d8 = (uint8_t *) rd->d_start;
+
+  pp = _mm_set1_epi8(btd->prim_poly&0xff);
+  m1 = _mm_set1_epi8((btd->mask1)&0xff);
+
+  while (d8 < (uint8_t *) rd->d_top) {
+    va = _mm_load_si128 ((__m128i *)(s8));
+    vb = _mm_xor_si128(_mm_load_si128 ((__m128i *)(d8)), va);
+    SSE_AB2(pp, m1, va, t1, t2);
+    vb = _mm_xor_si128(vb, va);
+    SSE_AB2(pp, m1, va, t1, t2);
+    vb = _mm_xor_si128(vb, va);
+    _mm_store_si128((__m128i *)d8, vb);
+    d8 += 16;
+    s8 += 16;
+  }
+}
+#endif
+
+#ifdef INTEL_SSE2
+static 
+void
+gf_w4_bytwo_b_sse_region_6_noxor(gf_region_data *rd, struct gf_bytwo_data *btd)
+{
+  uint8_t *d8, *s8;
+  __m128i pp, m1, t1, t2, va, vb;
+
+  s8 = (uint8_t *) rd->s_start;
+  d8 = (uint8_t *) rd->d_start;
+
+  pp = _mm_set1_epi8(btd->prim_poly&0xff);
+  m1 = _mm_set1_epi8((btd->mask1)&0xff);
+
+  while (d8 < (uint8_t *) rd->d_top) {
+    va = _mm_load_si128 ((__m128i *)(s8));
+    SSE_AB2(pp, m1, va, t1, t2);
+    vb = va;
+    SSE_AB2(pp, m1, va, t1, t2);
+    va = _mm_xor_si128(va, vb);
+    _mm_store_si128((__m128i *)d8, va);
+    d8 += 16;
+    s8 += 16;
+  }
+}
+#endif
+
+#ifdef INTEL_SSE2
+static 
+void
+gf_w4_bytwo_b_sse_region_6_xor(gf_region_data *rd, struct gf_bytwo_data *btd)
+{
+  uint8_t *d8, *s8;
+  __m128i pp, m1, t1, t2, va, vb;
+
+  s8 = (uint8_t *) rd->s_start;
+  d8 = (uint8_t *) rd->d_start;
+
+  pp = _mm_set1_epi8(btd->prim_poly&0xff);
+  m1 = _mm_set1_epi8((btd->mask1)&0xff);
+
+  while (d8 < (uint8_t *) rd->d_top) {
+    va = _mm_load_si128 ((__m128i *)(s8));
+    SSE_AB2(pp, m1, va, t1, t2);
+    vb = _mm_xor_si128(_mm_load_si128 ((__m128i *)(d8)), va);
+    SSE_AB2(pp, m1, va, t1, t2);
+    vb = _mm_xor_si128(vb, va);
+    _mm_store_si128((__m128i *)d8, vb);
+    d8 += 16;
+    s8 += 16;
+  }
+}
+#endif
+
+#ifdef INTEL_SSE2
+static
+void 
+gf_w4_bytwo_b_sse_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  uint8_t *d8, *s8, tb;
+  __m128i pp, m1, m2, t1, t2, va, vb;
+  struct gf_bytwo_data *btd;
+  gf_region_data rd;
+    
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 16);
+  gf_do_initial_region_alignment(&rd);
+
+  s8 = (uint8_t *) rd.s_start;
+  d8 = (uint8_t *) rd.d_start;
+
+  btd = (struct gf_bytwo_data *) ((gf_internal_t *) (gf->scratch))->private;
+
+  switch (val) {
+    case 2:
+      if (!xor) {
+        gf_w4_bytwo_b_sse_region_2_noxor(&rd, btd);
+      } else {
+        gf_w4_bytwo_b_sse_region_2_xor(&rd, btd);
+      }
+      gf_do_final_region_alignment(&rd);
+      return;
+    case 3:
+      if (!xor) {
+        gf_w4_bytwo_b_sse_region_3_noxor(&rd, btd);
+      } else {
+        gf_w4_bytwo_b_sse_region_3_xor(&rd, btd);
+      }
+      gf_do_final_region_alignment(&rd);
+      return;
+    case 4:
+      if (!xor) {
+        gf_w4_bytwo_b_sse_region_4_noxor(&rd, btd);
+      } else {
+        gf_w4_bytwo_b_sse_region_4_xor(&rd, btd);
+      }
+      gf_do_final_region_alignment(&rd);
+      return;
+    case 5:
+      if (!xor) {
+        gf_w4_bytwo_b_sse_region_5_noxor(&rd, btd);
+      } else {
+        gf_w4_bytwo_b_sse_region_5_xor(&rd, btd);
+      }
+      gf_do_final_region_alignment(&rd);
+      return;
+    case 6:
+      if (!xor) {
+        gf_w4_bytwo_b_sse_region_6_noxor(&rd, btd);
+      } else {
+        gf_w4_bytwo_b_sse_region_6_xor(&rd, btd);
+      }
+      gf_do_final_region_alignment(&rd);
+      return;
+    case 7:
+      if (!xor) {
+        gf_w4_bytwo_b_sse_region_7_noxor(&rd, btd);
+      } else {
+        gf_w4_bytwo_b_sse_region_7_xor(&rd, btd);
+      }
+      gf_do_final_region_alignment(&rd);
+      return;
+  }
+
+  pp = _mm_set1_epi8(btd->prim_poly&0xff);
+  m1 = _mm_set1_epi8((btd->mask1)&0xff);
+  m2 = _mm_set1_epi8((btd->mask2)&0xff);
+
+  if (xor) {
+    while (d8 < (uint8_t *) rd.d_top) {
+      va = _mm_load_si128 ((__m128i *)(s8));
+      vb = _mm_load_si128 ((__m128i *)(d8));
+      tb = val;
+      while (1) {
+        if (tb & 1) vb = _mm_xor_si128(vb, va);
+        tb >>= 1;
+        if (tb == 0) break;
+        SSE_AB2(pp, m1, va, t1, t2);
+      }
+      _mm_store_si128((__m128i *)d8, vb);
+      d8 += 16;
+      s8 += 16;
+    }
+  } else {
+    while (d8 < (uint8_t *) rd.d_top) {
+      va = _mm_load_si128 ((__m128i *)(s8));
+      vb = _mm_setzero_si128 ();
+      tb = val;
+      while (1) {
+        if (tb & 1) vb = _mm_xor_si128(vb, va);
+        tb >>= 1;
+        if (tb == 0) break;
+        t1 = _mm_and_si128(_mm_slli_epi64(va, 1), m1);
+        t2 = _mm_and_si128(va, m2);
+        t2 = _mm_sub_epi64 (
+          _mm_slli_epi64(t2, 1), _mm_srli_epi64(t2, (GF_FIELD_WIDTH-1)));
+        va = _mm_xor_si128(t1, _mm_and_si128(t2, pp));
+      }
+      _mm_store_si128((__m128i *)d8, vb);
+      d8 += 16;
+      s8 += 16;
+    }
+  }
+  gf_do_final_region_alignment(&rd);
+}
+#endif
+
+static
+void 
+gf_w4_bytwo_b_nosse_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  uint64_t *s64, *d64, t1, t2, ta, tb, prod;
+  struct gf_bytwo_data *btd;
+  gf_region_data rd;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 16);
+  gf_do_initial_region_alignment(&rd);
+
+  btd = (struct gf_bytwo_data *) ((gf_internal_t *) (gf->scratch))->private;
+  s64 = (uint64_t *) rd.s_start;
+  d64 = (uint64_t *) rd.d_start;
+
+  switch (val) {
+  case 1:
+    if (xor) {
+      while (d64 < (uint64_t *) rd.d_top) {
+        *d64 ^= *s64;
+        d64++;
+        s64++;
+      }
+    } else {
+      while (d64 < (uint64_t *) rd.d_top) {
+        *d64 = *s64;
+        d64++;
+        s64++;
+      }
+    }
+    break;
+  case 2:
+    if (xor) {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 ^= ta;
+        d64++;
+        s64++;
+      }
+    } else {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 = ta;
+        d64++;
+        s64++;
+      }
+    }
+    break; 
+  case 3:
+    if (xor) {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        prod = ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 ^= (ta ^ prod);
+        d64++;
+        s64++;
+      }
+    } else {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        prod = ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 = (ta ^ prod);
+        d64++;
+        s64++;
+      }
+    }
+    break; 
+  case 4:
+    if (xor) {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 ^= ta;
+        d64++;
+        s64++;
+      }
+    } else {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 = ta;
+        d64++;
+        s64++;
+      }
+    }
+    break; 
+  case 5:
+    if (xor) {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        prod = ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 ^= (ta ^ prod);
+        d64++;
+        s64++;
+      }
+    } else {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        prod = ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 = ta ^ prod;
+        d64++;
+        s64++;
+      }
+    }
+  case 6:
+    if (xor) {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        prod = ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 ^= (ta ^ prod);
+        d64++;
+        s64++;
+      }
+    } else {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        prod = ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 = ta ^ prod;
+        d64++;
+        s64++;
+      }
+    }
+  case 7:
+    if (xor) {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        prod = ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        prod ^= ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 ^= (ta ^ prod);
+        d64++;
+        s64++;
+      }
+    } else {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        prod = ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        prod ^= ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 = ta ^ prod;
+        d64++;
+        s64++;
+      }
+    }
+    break; 
+  case 8:
+    if (xor) {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 ^= ta;
+        d64++;
+        s64++;
+      }
+    } else {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 = ta;
+        d64++;
+        s64++;
+      }
+    }
+    break; 
+  case 9:
+    if (xor) {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        prod = ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 ^= (ta ^ prod);
+        d64++;
+        s64++;
+      }
+    } else {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        prod = ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 = (ta ^ prod);
+        d64++;
+        s64++;
+      }
+    }
+    break; 
+  case 10:
+    if (xor) {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        prod = ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 ^= (ta ^ prod);
+        d64++;
+        s64++;
+      }
+    } else {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        prod = ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 = (ta ^ prod);
+        d64++;
+        s64++;
+      }
+    }
+    break; 
+  case 11:
+    if (xor) {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        prod = ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        prod ^= ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 ^= (ta ^ prod);
+        d64++;
+        s64++;
+      }
+    } else {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        prod = ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        prod ^= ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 = (ta ^ prod);
+        d64++;
+        s64++;
+      }
+    }
+    break; 
+  case 12:
+    if (xor) {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        prod = ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 ^= (ta ^ prod);
+        d64++;
+        s64++;
+      }
+    } else {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        prod = ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 = (ta ^ prod);
+        d64++;
+        s64++;
+      }
+    }
+    break; 
+  case 13:
+    if (xor) {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        prod = ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        prod ^= ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 ^= (ta ^ prod);
+        d64++;
+        s64++;
+      }
+    } else {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        prod = ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        prod ^= ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 = (ta ^ prod);
+        d64++;
+        s64++;
+      }
+    }
+    break; 
+  case 14:
+    if (xor) {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        prod = ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        prod ^= ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 ^= (ta ^ prod);
+        d64++;
+        s64++;
+      }
+    } else {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        prod = ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        prod ^= ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 = (ta ^ prod);
+        d64++;
+        s64++;
+      }
+    }
+    break; 
+  case 15:
+    if (xor) {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        prod = ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        prod ^= ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        prod ^= ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 ^= (ta ^ prod);
+        d64++;
+        s64++;
+      }
+    } else {
+      while (d64 < (uint64_t *) rd.d_top) {
+        ta = *s64;
+        prod = ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        prod ^= ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        prod ^= ta;
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        *d64 = (ta ^ prod);
+        d64++;
+        s64++;
+      }
+    }
+    break; 
+  default:
+    if (xor) {
+      while (d64 < (uint64_t *) rd.d_top) {
+        prod = *d64 ;
+        ta = *s64;
+        tb = val;
+        while (1) {
+          if (tb & 1) prod ^= ta;
+          tb >>= 1;
+          if (tb == 0) break;
+          AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        }
+        *d64 = prod;
+        d64++;
+        s64++;
+      }
+    } else {
+      while (d64 < (uint64_t *) rd.d_top) {
+        prod = 0 ;
+        ta = *s64;
+        tb = val;
+        while (1) {
+          if (tb & 1) prod ^= ta;
+          tb >>= 1;
+          if (tb == 0) break;
+          AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        }
+        *d64 = prod;
+        d64++;
+        s64++;
+      }
+    }
+    break;
+  }
+  gf_do_final_region_alignment(&rd);
+}
+
+static 
+int gf_w4_bytwo_init(gf_t *gf)
+{
+  gf_internal_t *h;
+  uint64_t ip, m1, m2;
+  struct gf_bytwo_data *btd;
+
+  h = (gf_internal_t *) gf->scratch;
+  btd = (struct gf_bytwo_data *) (h->private);
+  ip = h->prim_poly & 0xf;
+  m1 = 0xe;
+  m2 = 0x8;
+  btd->prim_poly = 0;
+  btd->mask1 = 0;
+  btd->mask2 = 0;
+
+  while (ip != 0) {
+    btd->prim_poly |= ip;
+    btd->mask1 |= m1;
+    btd->mask2 |= m2;
+    ip <<= GF_FIELD_WIDTH;
+    m1 <<= GF_FIELD_WIDTH;
+    m2 <<= GF_FIELD_WIDTH;
+  }
+
+  if (h->mult_type == GF_MULT_BYTWO_p) {
+    gf->multiply.w32 = gf_w4_bytwo_p_multiply;
+    #ifdef INTEL_SSE2
+      if (h->region_type & GF_REGION_NOSSE)
+        gf->multiply_region.w32 = gf_w4_bytwo_p_nosse_multiply_region;
+      else
+        gf->multiply_region.w32 = gf_w4_bytwo_p_sse_multiply_region;
+    #else
+      gf->multiply_region.w32 = gf_w4_bytwo_p_nosse_multiply_region;
+      if (h->region_type & GF_REGION_SSE)
+        return 0;
+    #endif
+  } else {
+    gf->multiply.w32 = gf_w4_bytwo_b_multiply;
+    #ifdef INTEL_SSE2
+      if (h->region_type & GF_REGION_NOSSE)
+        gf->multiply_region.w32 = gf_w4_bytwo_b_nosse_multiply_region;
+      else
+        gf->multiply_region.w32 = gf_w4_bytwo_b_sse_multiply_region;
+    #else
+      gf->multiply_region.w32 = gf_w4_bytwo_b_nosse_multiply_region;
+      if (h->region_type & GF_REGION_SSE)
+        return 0;
+    #endif
+  }
+  return 1;
+}
+
+
+static 
+int gf_w4_cfm_init(gf_t *gf)
+{
+#if defined(INTEL_SSE4_PCLMUL)
+  gf->multiply.w32 = gf_w4_clm_multiply;
+  return 1;
+#endif
+  return 0;
+}
+
+static 
+int gf_w4_shift_init(gf_t *gf)
+{
+  gf->multiply.w32 = gf_w4_shift_multiply;
+  return 1;
+}
+
+/* JSP: I'm putting all error-checking into gf_error_check(), so you don't 
+   have to do error checking in scratch_size or in init */
+
+int gf_w4_scratch_size(int mult_type, int region_type, int divide_type, int arg1, int arg2)
+{
+  int issse3 = 0;
+
+#ifdef INTEL_SSSE3
+  issse3 = 1;
+#endif
+
+  switch(mult_type)
+  {
+    case GF_MULT_BYTWO_p:
+    case GF_MULT_BYTWO_b:
+      return sizeof(gf_internal_t) + sizeof(struct gf_bytwo_data);
+      break;
+    case GF_MULT_DEFAULT:
+    case GF_MULT_TABLE:
+      if (region_type == GF_REGION_CAUCHY) {
+        return sizeof(gf_internal_t) + sizeof(struct gf_single_table_data) + 64;
+      }
+
+      if (mult_type == GF_MULT_DEFAULT && !issse3) region_type = GF_REGION_DOUBLE_TABLE;
+
+      if (region_type & GF_REGION_DOUBLE_TABLE) {
+        return sizeof(gf_internal_t) + sizeof(struct gf_double_table_data) + 64;
+      } else if (region_type & GF_REGION_QUAD_TABLE) {
+        if ((region_type & GF_REGION_LAZY) == 0) {
+          return sizeof(gf_internal_t) + sizeof(struct gf_quad_table_data) + 64;
+        } else {
+          return sizeof(gf_internal_t) + sizeof(struct gf_quad_table_lazy_data) + 64;
+        }
+      } else {
+        return sizeof(gf_internal_t) + sizeof(struct gf_single_table_data) + 64;
+      }
+      break;
+
+    case GF_MULT_LOG_TABLE:
+      return sizeof(gf_internal_t) + sizeof(struct gf_logtable_data) + 64;
+      break;
+    case GF_MULT_CARRY_FREE:
+      return sizeof(gf_internal_t);
+      break;
+    case GF_MULT_SHIFT:
+      return sizeof(gf_internal_t);
+      break;
+    default:
+      return 0;
+   }
+  return 0;
+}
+
+int
+gf_w4_init (gf_t *gf)
+{
+  gf_internal_t *h;
+
+  h = (gf_internal_t *) gf->scratch;
+  if (h->prim_poly == 0) h->prim_poly = 0x13;
+  h->prim_poly |= 0x10;
+  gf->multiply.w32 = NULL;
+  gf->divide.w32 = NULL;
+  gf->inverse.w32 = NULL;
+  gf->multiply_region.w32 = NULL;
+  gf->extract_word.w32 = gf_w4_extract_word;
+
+  switch(h->mult_type) {
+    case GF_MULT_CARRY_FREE: if (gf_w4_cfm_init(gf) == 0) return 0; break;
+    case GF_MULT_SHIFT:      if (gf_w4_shift_init(gf) == 0) return 0; break;
+    case GF_MULT_BYTWO_p:   
+    case GF_MULT_BYTWO_b:    if (gf_w4_bytwo_init(gf) == 0) return 0; break;
+    case GF_MULT_LOG_TABLE:  if (gf_w4_log_init(gf) == 0) return 0; break;
+    case GF_MULT_DEFAULT:   
+    case GF_MULT_TABLE:      if (gf_w4_table_init(gf) == 0) return 0; break;
+    default: return 0;
+  }
+
+  if (h->divide_type == GF_DIVIDE_EUCLID) {
+    gf->divide.w32 = gf_w4_divide_from_inverse;
+    gf->inverse.w32 = gf_w4_euclid;
+  } else if (h->divide_type == GF_DIVIDE_MATRIX) {
+    gf->divide.w32 = gf_w4_divide_from_inverse;
+    gf->inverse.w32 = gf_w4_matrix;
+  }
+
+  if (gf->divide.w32 == NULL) {
+    gf->divide.w32 = gf_w4_divide_from_inverse;
+    if (gf->inverse.w32 == NULL) gf->inverse.w32 = gf_w4_euclid;
+  }
+
+  if (gf->inverse.w32 == NULL)  gf->inverse.w32 = gf_w4_inverse_from_divide;
+
+  if (h->region_type == GF_REGION_CAUCHY) {
+    gf->multiply_region.w32 = gf_wgen_cauchy_region;
+    gf->extract_word.w32 = gf_wgen_extract_word;
+  }
+
+  if (gf->multiply_region.w32 == NULL) {
+    gf->multiply_region.w32 = gf_w4_multiply_region_from_single;
+  }
+
+  return 1;
+}
+
+/* Inline setup functions */
+
+uint8_t *gf_w4_get_mult_table(gf_t *gf)
+{
+  gf_internal_t *h;
+  struct gf_single_table_data *std;
+  
+  h = (gf_internal_t *) gf->scratch;
+  if (gf->multiply.w32 == gf_w4_single_table_multiply) {
+    std = (struct gf_single_table_data *) h->private;
+    return (uint8_t *) std->mult;
+  } 
+  return NULL;
+}
+    
+uint8_t *gf_w4_get_div_table(gf_t *gf)
+{
+  gf_internal_t *h;
+  struct gf_single_table_data *std;
+  
+  h = (gf_internal_t *) gf->scratch;
+  if (gf->multiply.w32 == gf_w4_single_table_multiply) {
+    std = (struct gf_single_table_data *) h->private;
+    return (uint8_t *) std->div;
+  } 
+  return NULL;
+}
+
diff --git a/src/erasure-code/jerasure/gf-complete/src/gf_w64.c b/src/erasure-code/jerasure/gf-complete/src/gf_w64.c
new file mode 100644
index 0000000..f04daf0
--- /dev/null
+++ b/src/erasure-code/jerasure/gf-complete/src/gf_w64.c
@@ -0,0 +1,2244 @@
+/*
+ * GF-Complete: A Comprehensive Open Source Library for Galois Field Arithmetic
+ * James S. Plank, Ethan L. Miller, Kevin M. Greenan,
+ * Benjamin A. Arnold, John A. Burnum, Adam W. Disney, Allen C. McBride.
+ *
+ * gf_w64.c
+ *
+ * Routines for 64-bit Galois fields
+ */
+
+#include "gf_int.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+#define GF_FIELD_WIDTH (64)
+#define GF_FIRST_BIT (1ULL << 63)
+
+#define GF_BASE_FIELD_WIDTH (32)
+#define GF_BASE_FIELD_SIZE       (1ULL << GF_BASE_FIELD_WIDTH)
+#define GF_BASE_FIELD_GROUP_SIZE  GF_BASE_FIELD_SIZE-1
+
+struct gf_w64_group_data {
+    uint64_t *reduce;
+    uint64_t *shift;
+    uint64_t *memory;
+};
+
+struct gf_split_4_64_lazy_data {
+    uint64_t      tables[16][16];
+    uint64_t      last_value;
+};
+
+struct gf_split_8_64_lazy_data {
+    uint64_t      tables[8][(1<<8)];
+    uint64_t      last_value;
+};
+
+struct gf_split_16_64_lazy_data {
+    uint64_t      tables[4][(1<<16)];
+    uint64_t      last_value;
+};
+
+struct gf_split_8_8_data {
+    uint64_t      tables[15][256][256];
+};
+
+static
+inline
+gf_val_64_t gf_w64_inverse_from_divide (gf_t *gf, gf_val_64_t a)
+{
+  return gf->divide.w64(gf, 1, a);
+}
+
+#define MM_PRINT8(s, r) { uint8_t blah[16], ii; printf("%-12s", s); _mm_storeu_si128((__m128i *)blah, r); for (ii = 0; ii < 16; ii += 1) printf("%s%02x", (ii%4==0) ? "   " : " ", blah[15-ii]); printf("\n"); }
+
+static
+inline
+gf_val_64_t gf_w64_divide_from_inverse (gf_t *gf, gf_val_64_t a, gf_val_64_t b)
+{
+  b = gf->inverse.w64(gf, b);
+  return gf->multiply.w64(gf, a, b);
+}
+
+static
+void
+gf_w64_multiply_region_from_single(gf_t *gf, void *src, void *dest, gf_val_64_t val, int bytes, int
+xor)
+{
+  int i;
+  gf_val_64_t *s64;
+  gf_val_64_t *d64;
+
+  s64 = (gf_val_64_t *) src;
+  d64 = (gf_val_64_t *) dest;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  if (xor) {
+    for (i = 0; i < bytes/sizeof(gf_val_64_t); i++) {
+      d64[i] ^= gf->multiply.w64(gf, val, s64[i]);
+    }
+  } else {
+    for (i = 0; i < bytes/sizeof(gf_val_64_t); i++) {
+      d64[i] = gf->multiply.w64(gf, val, s64[i]);
+    }
+  }
+}
+
+#if defined(INTEL_SSE4_PCLMUL) 
+static
+void
+gf_w64_clm_multiply_region_from_single_2(gf_t *gf, void *src, void *dest, gf_val_64_t val, int bytes, int
+xor)
+{
+  gf_val_64_t *s64, *d64, *top;
+  gf_region_data rd;
+
+  __m128i         a, b;
+  __m128i         result, r1;
+  __m128i         prim_poly;
+  __m128i         w;
+  __m128i         m1, m2, m3, m4;
+  gf_internal_t * h = gf->scratch;
+  
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+  
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 16);
+  gf_do_initial_region_alignment(&rd);
+
+  prim_poly = _mm_set_epi32(0, 0, 0, (uint32_t)(h->prim_poly & 0xffffffffULL));
+  b = _mm_insert_epi64 (_mm_setzero_si128(), val, 0);
+  m1 = _mm_set_epi32(0, 0, 0, (uint32_t)0xffffffff);
+  m2 = _mm_slli_si128(m1, 4);
+  m2 = _mm_or_si128(m1, m2);
+  m3 = _mm_slli_si128(m1, 8);
+  m4 = _mm_slli_si128(m3, 4);
+
+  s64 = (gf_val_64_t *) rd.s_start;
+  d64 = (gf_val_64_t *) rd.d_start;
+  top = (gf_val_64_t *) rd.d_top;
+
+  if (xor) {
+    while (d64 != top) {
+      a = _mm_load_si128((__m128i *) s64);  
+      result = _mm_clmulepi64_si128 (a, b, 1);
+
+      w = _mm_clmulepi64_si128 (_mm_and_si128(result, m4), prim_poly, 1);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (_mm_and_si128(result, m3), prim_poly, 1);
+      r1 = _mm_xor_si128 (result, w);
+
+      result = _mm_clmulepi64_si128 (a, b, 0);
+
+      w = _mm_clmulepi64_si128 (_mm_and_si128(result, m4), prim_poly, 1);
+      result = _mm_xor_si128 (result, w);
+
+      w = _mm_clmulepi64_si128 (_mm_and_si128(result, m3), prim_poly, 1);
+      result = _mm_xor_si128 (result, w);
+
+      result = _mm_unpacklo_epi64(result, r1);
+      
+      r1 = _mm_load_si128((__m128i *) d64);
+      result = _mm_xor_si128(r1, result);
+      _mm_store_si128((__m128i *) d64, result);
+      d64 += 2;
+      s64 += 2;
+    }
+  } else {
+    while (d64 != top) {
+      
+      a = _mm_load_si128((__m128i *) s64);  
+      result = _mm_clmulepi64_si128 (a, b, 1);
+
+      w = _mm_clmulepi64_si128 (_mm_and_si128(result, m4), prim_poly, 1);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (_mm_and_si128(result, m3), prim_poly, 1);
+      r1 = _mm_xor_si128 (result, w);
+
+      result = _mm_clmulepi64_si128 (a, b, 0);
+
+      w = _mm_clmulepi64_si128 (_mm_and_si128(result, m4), prim_poly, 1);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (_mm_and_si128(result, m3), prim_poly, 1);
+      result = _mm_xor_si128 (result, w);
+      
+      result = _mm_unpacklo_epi64(result, r1);
+
+      _mm_store_si128((__m128i *) d64, result);
+      d64 += 2;
+      s64 += 2;
+    }
+  }
+  gf_do_final_region_alignment(&rd);
+}
+#endif
+
+#if defined(INTEL_SSE4_PCLMUL)
+static
+void
+gf_w64_clm_multiply_region_from_single_4(gf_t *gf, void *src, void *dest, gf_val_64_t val, int bytes, int
+xor)
+{
+  gf_val_64_t *s64, *d64, *top;
+  gf_region_data rd;
+
+  __m128i         a, b;
+  __m128i         result, r1;
+  __m128i         prim_poly;
+  __m128i         w;
+  __m128i         m1, m3, m4;
+  gf_internal_t * h = gf->scratch;
+  
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+  
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 16);
+  gf_do_initial_region_alignment(&rd);
+  
+  prim_poly = _mm_set_epi32(0, 0, 0, (uint32_t)(h->prim_poly & 0xffffffffULL));
+  b = _mm_insert_epi64 (_mm_setzero_si128(), val, 0);
+  m1 = _mm_set_epi32(0, 0, 0, (uint32_t)0xffffffff);
+  m3 = _mm_slli_si128(m1, 8);
+  m4 = _mm_slli_si128(m3, 4);
+
+  s64 = (gf_val_64_t *) rd.s_start;
+  d64 = (gf_val_64_t *) rd.d_start;
+  top = (gf_val_64_t *) rd.d_top;
+
+  if (xor) {
+    while (d64 != top) {
+      a = _mm_load_si128((__m128i *) s64);
+      result = _mm_clmulepi64_si128 (a, b, 1);
+
+      w = _mm_clmulepi64_si128 (_mm_and_si128(result, m4), prim_poly, 1);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (_mm_and_si128(result, m3), prim_poly, 1);
+      r1 = _mm_xor_si128 (result, w);
+
+      result = _mm_clmulepi64_si128 (a, b, 0);
+
+      w = _mm_clmulepi64_si128 (_mm_and_si128(result, m4), prim_poly, 1);
+      result = _mm_xor_si128 (result, w);
+
+      w = _mm_clmulepi64_si128 (_mm_and_si128(result, m3), prim_poly, 1);
+      result = _mm_xor_si128 (result, w);
+
+      result = _mm_unpacklo_epi64(result, r1);
+
+      r1 = _mm_load_si128((__m128i *) d64);
+      result = _mm_xor_si128(r1, result);
+      _mm_store_si128((__m128i *) d64, result);
+      d64 += 2;
+      s64 += 2;
+    }
+  } else {
+    while (d64 != top) {
+      a = _mm_load_si128((__m128i *) s64);
+      result = _mm_clmulepi64_si128 (a, b, 1);
+
+      w = _mm_clmulepi64_si128 (_mm_and_si128(result, m4), prim_poly, 1);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (_mm_and_si128(result, m3), prim_poly, 1);
+      r1 = _mm_xor_si128 (result, w);
+
+      result = _mm_clmulepi64_si128 (a, b, 0);
+
+      w = _mm_clmulepi64_si128 (_mm_and_si128(result, m4), prim_poly, 1);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (_mm_and_si128(result, m3), prim_poly, 1);
+      result = _mm_xor_si128 (result, w);
+
+      result = _mm_unpacklo_epi64(result, r1);
+
+      _mm_store_si128((__m128i *) d64, result);
+      d64 += 2;
+      s64 += 2; 
+    }
+  }
+  gf_do_final_region_alignment(&rd);
+}
+#endif
+
+static
+  inline
+gf_val_64_t gf_w64_euclid (gf_t *gf, gf_val_64_t b)
+{
+  gf_val_64_t e_i, e_im1, e_ip1;
+  gf_val_64_t d_i, d_im1, d_ip1;
+  gf_val_64_t y_i, y_im1, y_ip1;
+  gf_val_64_t c_i;
+  gf_val_64_t one = 1;
+
+  if (b == 0) return -1;
+  e_im1 = ((gf_internal_t *) (gf->scratch))->prim_poly;
+  e_i = b;
+  d_im1 = 64;
+  for (d_i = d_im1-1; ((one << d_i) & e_i) == 0; d_i--) ;
+  y_i = 1;
+  y_im1 = 0;
+
+  while (e_i != 1) {
+
+    e_ip1 = e_im1;
+    d_ip1 = d_im1;
+    c_i = 0;
+
+    while (d_ip1 >= d_i) {
+      c_i ^= (one << (d_ip1 - d_i));
+      e_ip1 ^= (e_i << (d_ip1 - d_i));
+      d_ip1--;
+      if (e_ip1 == 0) return 0;
+      while ((e_ip1 & (one << d_ip1)) == 0) d_ip1--;
+    }
+
+    y_ip1 = y_im1 ^ gf->multiply.w64(gf, c_i, y_i);
+    y_im1 = y_i;
+    y_i = y_ip1;
+
+    e_im1 = e_i;
+    d_im1 = d_i;
+    e_i = e_ip1;
+    d_i = d_ip1;
+  }
+
+  return y_i;
+}
+
+/* JSP: GF_MULT_SHIFT: The world's dumbest multiplication algorithm.  I only
+   include it for completeness.  It does have the feature that it requires no
+   extra memory.  
+*/
+
+static
+inline
+gf_val_64_t
+gf_w64_shift_multiply (gf_t *gf, gf_val_64_t a64, gf_val_64_t b64)
+{
+  uint64_t pl, pr, ppl, ppr, i, a, bl, br, one, lbit;
+  gf_internal_t *h;
+
+  h = (gf_internal_t *) gf->scratch;
+  ppr = h->prim_poly;
+  
+  /* Allen: set leading one of primitive polynomial */
+  
+  ppl = 1;
+ 
+  a = a64;
+  bl = 0;
+  br = b64;
+  one = 1;
+  lbit = (one << 63);
+
+  pl = 0; /* Allen: left side of product */
+  pr = 0; /* Allen: right side of product */
+
+  /* Allen: unlike the corresponding functions for smaller word sizes,
+   * this loop carries out the initial carryless multiply by
+   * shifting b itself rather than simply looking at successively
+   * higher shifts of b */
+  
+  for (i = 0; i < GF_FIELD_WIDTH; i++) {
+    if (a & (one << i)) {
+      pl ^= bl;
+      pr ^= br;
+    }
+
+    bl <<= 1;
+    if (br & lbit) bl ^= 1;
+    br <<= 1;
+  }
+
+  /* Allen: the name of the variable "one" is no longer descriptive at this point */
+  
+  one = lbit >> 1;
+  ppl = (h->prim_poly >> 2) | one;
+  ppr = (h->prim_poly << (GF_FIELD_WIDTH-2));
+  while (one != 0) {
+    if (pl & one) {
+      pl ^= ppl;
+      pr ^= ppr;
+    }
+    one >>= 1;
+    ppr >>= 1;
+    if (ppl & 1) ppr ^= lbit;
+    ppl >>= 1;
+  }
+  return pr;
+}
+
+/*
+ * ELM: Use the Intel carryless multiply instruction to do very fast 64x64 multiply.
+ */
+
+static
+inline
+gf_val_64_t
+gf_w64_clm_multiply_2 (gf_t *gf, gf_val_64_t a64, gf_val_64_t b64)
+{
+       gf_val_64_t rv = 0;
+
+#if defined(INTEL_SSE4_PCLMUL) 
+
+        __m128i         a, b;
+        __m128i         result;
+        __m128i         prim_poly;
+        __m128i         v, w;
+        gf_internal_t * h = gf->scratch;
+
+        a = _mm_insert_epi64 (_mm_setzero_si128(), a64, 0);
+        b = _mm_insert_epi64 (a, b64, 0); 
+        prim_poly = _mm_set_epi32(0, 0, 0, (uint32_t)(h->prim_poly & 0xffffffffULL));
+        /* Do the initial multiply */
+   
+        result = _mm_clmulepi64_si128 (a, b, 0);
+        
+        /* Mask off the high order 32 bits using subtraction of the polynomial.
+         * NOTE: this part requires that the polynomial have at least 32 leading 0 bits.
+         */
+
+        /* Adam: We cant include the leading one in the 64 bit pclmul,
+         so we need to split up the high 8 bytes of the result into two 
+         parts before we multiply them with the prim_poly.*/
+
+        v = _mm_insert_epi32 (_mm_srli_si128 (result, 8), 0, 0);
+        w = _mm_clmulepi64_si128 (prim_poly, v, 0);
+        result = _mm_xor_si128 (result, w);
+        v = _mm_insert_epi32 (_mm_srli_si128 (result, 8), 0, 1);
+        w = _mm_clmulepi64_si128 (prim_poly, v, 0);
+        result = _mm_xor_si128 (result, w);
+
+        rv = ((gf_val_64_t)_mm_extract_epi64(result, 0));
+#endif
+        return rv;
+}
+ 
+static
+inline
+gf_val_64_t
+gf_w64_clm_multiply_4 (gf_t *gf, gf_val_64_t a64, gf_val_64_t b64)
+{
+  gf_val_64_t rv = 0;
+
+#if defined(INTEL_SSE4_PCLMUL) 
+
+  __m128i         a, b;
+  __m128i         result;
+  __m128i         prim_poly;
+  __m128i         v, w;
+  gf_internal_t * h = gf->scratch;
+
+  a = _mm_insert_epi64 (_mm_setzero_si128(), a64, 0);
+  b = _mm_insert_epi64 (a, b64, 0);
+  prim_poly = _mm_set_epi32(0, 0, 0, (uint32_t)(h->prim_poly & 0xffffffffULL));
+ 
+  /* Do the initial multiply */
+  
+  result = _mm_clmulepi64_si128 (a, b, 0);
+
+  v = _mm_insert_epi32 (_mm_srli_si128 (result, 8), 0, 0);
+  w = _mm_clmulepi64_si128 (prim_poly, v, 0);
+  result = _mm_xor_si128 (result, w);
+  v = _mm_insert_epi32 (_mm_srli_si128 (result, 8), 0, 1);
+  w = _mm_clmulepi64_si128 (prim_poly, v, 0);
+  result = _mm_xor_si128 (result, w);
+  
+  v = _mm_insert_epi32 (_mm_srli_si128 (result, 8), 0, 0);
+  w = _mm_clmulepi64_si128 (prim_poly, v, 0);
+  result = _mm_xor_si128 (result, w);
+  v = _mm_insert_epi32 (_mm_srli_si128 (result, 8), 0, 1);
+  w = _mm_clmulepi64_si128 (prim_poly, v, 0);
+  result = _mm_xor_si128 (result, w);
+
+  rv = ((gf_val_64_t)_mm_extract_epi64(result, 0));
+#endif
+  return rv;
+}
+
+
+  void
+gf_w64_clm_multiply_region(gf_t *gf, void *src, void *dest, uint64_t val, int bytes, int xor)
+{
+#if defined(INTEL_SSE4_PCLMUL) 
+  gf_internal_t *h;
+  uint8_t *s8, *d8, *dtop;
+  gf_region_data rd;
+  __m128i  v, b, m, prim_poly, c, fr, w, result;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  h = (gf_internal_t *) gf->scratch;
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 16);
+  gf_do_initial_region_alignment(&rd);
+
+  s8 = (uint8_t *) rd.s_start;
+  d8 = (uint8_t *) rd.d_start;
+  dtop = (uint8_t *) rd.d_top;
+
+  v = _mm_insert_epi64(_mm_setzero_si128(), val, 0);
+  m = _mm_set_epi32(0, 0, 0xffffffff, 0xffffffff);
+  prim_poly = _mm_set_epi32(0, 0, 0, (uint32_t)(h->prim_poly & 0xffffffffULL));
+
+  if (xor) {
+    while (d8 != dtop) {
+      b = _mm_load_si128((__m128i *) s8);
+      result = _mm_clmulepi64_si128 (b, v, 0);
+      c = _mm_insert_epi32 (_mm_srli_si128 (result, 8), 0, 0);
+      w = _mm_clmulepi64_si128 (prim_poly, c, 0);
+      result = _mm_xor_si128 (result, w);
+      c = _mm_insert_epi32 (_mm_srli_si128 (result, 8), 0, 1);
+      w = _mm_clmulepi64_si128 (prim_poly, c, 0);
+      fr = _mm_xor_si128 (result, w);
+      fr = _mm_and_si128 (fr, m);
+
+      result = _mm_clmulepi64_si128 (b, v, 1);
+      c = _mm_insert_epi32 (_mm_srli_si128 (result, 8), 0, 0);
+      w = _mm_clmulepi64_si128 (prim_poly, c, 0);
+      result = _mm_xor_si128 (result, w);
+      c = _mm_insert_epi32 (_mm_srli_si128 (result, 8), 0, 1);
+      w = _mm_clmulepi64_si128 (prim_poly, c, 0);
+      result = _mm_xor_si128 (result, w);
+      result = _mm_slli_si128 (result, 8);
+      fr = _mm_xor_si128 (result, fr);
+      result = _mm_load_si128((__m128i *) d8);
+      fr = _mm_xor_si128 (result, fr);
+
+      _mm_store_si128((__m128i *) d8, fr);
+      d8 += 16;
+      s8 += 16;
+    }
+  } else {
+    while (d8 < dtop) {
+      b = _mm_load_si128((__m128i *) s8);
+      result = _mm_clmulepi64_si128 (b, v, 0);
+      c = _mm_insert_epi32 (_mm_srli_si128 (result, 8), 0, 0);
+      w = _mm_clmulepi64_si128 (prim_poly, c, 0);
+      result = _mm_xor_si128 (result, w);
+      c = _mm_insert_epi32 (_mm_srli_si128 (result, 8), 0, 1);
+      w = _mm_clmulepi64_si128 (prim_poly, c, 0);
+      fr = _mm_xor_si128 (result, w);
+      fr = _mm_and_si128 (fr, m);
+  
+      result = _mm_clmulepi64_si128 (b, v, 1);
+      c = _mm_insert_epi32 (_mm_srli_si128 (result, 8), 0, 0);
+      w = _mm_clmulepi64_si128 (prim_poly, c, 0);
+      result = _mm_xor_si128 (result, w);
+      c = _mm_insert_epi32 (_mm_srli_si128 (result, 8), 0, 1);
+      w = _mm_clmulepi64_si128 (prim_poly, c, 0);
+      result = _mm_xor_si128 (result, w);
+      result = _mm_slli_si128 (result, 8);
+      fr = _mm_xor_si128 (result, fr);
+  
+      _mm_store_si128((__m128i *) d8, fr);
+      d8 += 16;
+      s8 += 16;
+    }
+  }
+  gf_do_final_region_alignment(&rd);
+#endif
+}
+
+void
+gf_w64_split_4_64_lazy_multiply_region(gf_t *gf, void *src, void *dest, uint64_t val, int bytes, int xor)
+{
+  gf_internal_t *h;
+  struct gf_split_4_64_lazy_data *ld;
+  int i, j, k;
+  uint64_t pp, v, s, *s64, *d64, *top;
+  gf_region_data rd;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  h = (gf_internal_t *) gf->scratch;
+  pp = h->prim_poly;
+
+  ld = (struct gf_split_4_64_lazy_data *) h->private;
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 8);
+  gf_do_initial_region_alignment(&rd);
+
+  if (ld->last_value != val) {
+    v = val;
+    for (i = 0; i < 16; i++) {
+      ld->tables[i][0] = 0;
+      for (j = 1; j < 16; j <<= 1) {
+        for (k = 0; k < j; k++) {
+          ld->tables[i][k^j] = (v ^ ld->tables[i][k]);
+        }
+        v = (v & GF_FIRST_BIT) ? ((v << 1) ^ pp) : (v << 1);
+      }
+    }
+  }
+  ld->last_value = val;
+
+  s64 = (uint64_t *) rd.s_start;
+  d64 = (uint64_t *) rd.d_start;
+  top = (uint64_t *) rd.d_top;
+
+  while (d64 != top) {
+    v = (xor) ? *d64 : 0;
+    s = *s64;
+    i = 0;
+    while (s != 0) {
+      v ^= ld->tables[i][s&0xf];
+      s >>= 4;
+      i++;
+    }
+    *d64 = v;
+    d64++;
+    s64++;
+  }
+  gf_do_final_region_alignment(&rd);
+}
+
+static
+inline
+uint64_t
+gf_w64_split_8_8_multiply (gf_t *gf, uint64_t a64, uint64_t b64)
+{
+  uint64_t product, i, j, mask, tb;
+  gf_internal_t *h;
+  struct gf_split_8_8_data *d8;
+ 
+  h = (gf_internal_t *) gf->scratch;
+  d8 = (struct gf_split_8_8_data *) h->private;
+  product = 0;
+  mask = 0xff;
+
+  for (i = 0; a64 != 0; i++) {
+    tb = b64;
+    for (j = 0; tb != 0; j++) {
+      product ^= d8->tables[i+j][a64&mask][tb&mask];
+      tb >>= 8;
+    }
+    a64 >>= 8;
+  }
+  return product;
+}
+
+void
+gf_w64_split_8_64_lazy_multiply_region(gf_t *gf, void *src, void *dest, uint64_t val, int bytes, int xor)
+{
+  gf_internal_t *h;
+  struct gf_split_8_64_lazy_data *ld;
+  int i, j, k;
+  uint64_t pp, v, s, *s64, *d64, *top;
+  gf_region_data rd;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  h = (gf_internal_t *) gf->scratch;
+  pp = h->prim_poly;
+
+  ld = (struct gf_split_8_64_lazy_data *) h->private;
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 4);
+  gf_do_initial_region_alignment(&rd);
+
+  if (ld->last_value != val) {
+    v = val;
+    for (i = 0; i < 8; i++) {
+      ld->tables[i][0] = 0;
+      for (j = 1; j < 256; j <<= 1) {
+        for (k = 0; k < j; k++) {
+          ld->tables[i][k^j] = (v ^ ld->tables[i][k]);
+        }
+        v = (v & GF_FIRST_BIT) ? ((v << 1) ^ pp) : (v << 1);
+      }
+    }
+  }
+  ld->last_value = val;
+
+  s64 = (uint64_t *) rd.s_start;
+  d64 = (uint64_t *) rd.d_start;
+  top = (uint64_t *) rd.d_top;
+
+  while (d64 != top) {
+    v = (xor) ? *d64 : 0;
+    s = *s64;
+    i = 0;
+    while (s != 0) {
+      v ^= ld->tables[i][s&0xff];
+      s >>= 8;
+      i++;
+    }
+    *d64 = v;
+    d64++;
+    s64++;
+  }
+  gf_do_final_region_alignment(&rd);
+}
+
+void
+gf_w64_split_16_64_lazy_multiply_region(gf_t *gf, void *src, void *dest, uint64_t val, int bytes, int xor)
+{
+  gf_internal_t *h;
+  struct gf_split_16_64_lazy_data *ld;
+  int i, j, k;
+  uint64_t pp, v, s, *s64, *d64, *top;
+  gf_region_data rd;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  h = (gf_internal_t *) gf->scratch;
+  pp = h->prim_poly;
+
+  ld = (struct gf_split_16_64_lazy_data *) h->private;
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 4);
+  gf_do_initial_region_alignment(&rd);
+
+  if (ld->last_value != val) {
+    v = val;
+    for (i = 0; i < 4; i++) {
+      ld->tables[i][0] = 0;
+      for (j = 1; j < (1<<16); j <<= 1) {
+        for (k = 0; k < j; k++) {
+          ld->tables[i][k^j] = (v ^ ld->tables[i][k]);
+        }
+        v = (v & GF_FIRST_BIT) ? ((v << 1) ^ pp) : (v << 1);
+      }
+    }
+  }
+  ld->last_value = val;
+
+  s64 = (uint64_t *) rd.s_start;
+  d64 = (uint64_t *) rd.d_start;
+  top = (uint64_t *) rd.d_top;
+
+  while (d64 != top) {
+    v = (xor) ? *d64 : 0;
+    s = *s64;
+    i = 0;
+    while (s != 0) {
+      v ^= ld->tables[i][s&0xffff];
+      s >>= 16;
+      i++;
+    }
+    *d64 = v;
+    d64++;
+    s64++;
+  }
+  gf_do_final_region_alignment(&rd);
+}
+
+static 
+int gf_w64_shift_init(gf_t *gf)
+{
+  gf->multiply.w64 = gf_w64_shift_multiply;
+  gf->inverse.w64 = gf_w64_euclid;
+  gf->multiply_region.w64 = gf_w64_multiply_region_from_single;
+  return 1;
+}
+
+static 
+int gf_w64_cfm_init(gf_t *gf)
+{
+  gf->inverse.w64 = gf_w64_euclid;
+  gf->multiply_region.w64 = gf_w64_multiply_region_from_single;
+
+#if defined(INTEL_SSE4_PCLMUL) 
+  gf_internal_t *h;
+
+  h = (gf_internal_t *) gf->scratch;
+
+  if ((0xfffffffe00000000ULL & h->prim_poly) == 0){ 
+    gf->multiply.w64 = gf_w64_clm_multiply_2;
+    gf->multiply_region.w64 = gf_w64_clm_multiply_region_from_single_2; 
+  }else if((0xfffe000000000000ULL & h->prim_poly) == 0){
+    gf->multiply.w64 = gf_w64_clm_multiply_4;
+    gf->multiply_region.w64 = gf_w64_clm_multiply_region_from_single_4;
+  } else {
+    return 0;
+  }
+  return 1;
+#endif
+
+  return 0;
+}
+
+static
+void
+gf_w64_group_set_shift_tables(uint64_t *shift, uint64_t val, gf_internal_t *h)
+{
+  int i;
+  uint64_t j;
+  uint64_t one = 1;
+  int g_s;
+
+  g_s = h->arg1;
+  shift[0] = 0;
+ 
+  for (i = 1; i < (1 << g_s); i <<= 1) {
+    for (j = 0; j < i; j++) shift[i|j] = shift[j]^val;
+    if (val & (one << 63)) {
+      val <<= 1;
+      val ^= h->prim_poly;
+    } else {
+      val <<= 1;
+    }
+  }
+}
+
+static
+inline
+gf_val_64_t
+gf_w64_group_multiply(gf_t *gf, gf_val_64_t a, gf_val_64_t b)
+{
+  uint64_t top, bot, mask, tp;
+  int g_s, g_r, lshift, rshift;
+  struct gf_w64_group_data *gd;
+
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  g_s = h->arg1;
+  g_r = h->arg2;
+  gd = (struct gf_w64_group_data *) h->private;
+  gf_w64_group_set_shift_tables(gd->shift, b, h);
+
+  mask = ((1 << g_s) - 1);
+  top = 0;
+  bot = gd->shift[a&mask];
+  a >>= g_s; 
+
+  if (a == 0) return bot;
+  lshift = 0;
+  rshift = 64;
+
+  do {              /* Shifting out is straightfoward */
+    lshift += g_s;
+    rshift -= g_s;
+    tp = gd->shift[a&mask];
+    top ^= (tp >> rshift);
+    bot ^= (tp << lshift);
+    a >>= g_s; 
+  } while (a != 0);
+
+  /* Reducing is a bit gross, because I don't zero out the index bits of top.
+     The reason is that we throw top away.  Even better, that last (tp >> rshift)
+     is going to be ignored, so it doesn't matter how (tp >> 64) is implemented. */
+     
+  lshift = ((lshift-1) / g_r) * g_r;
+  rshift = 64 - lshift;
+  mask = (1 << g_r) - 1;
+  while (lshift >= 0) {
+    tp = gd->reduce[(top >> lshift) & mask];
+    top ^= (tp >> rshift);
+    bot ^= (tp << lshift);
+    lshift -= g_r;
+    rshift += g_r;
+  }
+    
+  return bot;
+}
+
+static
+void gf_w64_group_multiply_region(gf_t *gf, void *src, void *dest, gf_val_64_t val, int bytes, int xor)
+{
+  int i, fzb;
+  uint64_t a64, smask, rmask, top, bot, tp;
+  int lshift, rshift, g_s, g_r;
+  gf_region_data rd;
+  uint64_t *s64, *d64, *dtop;
+  struct gf_w64_group_data *gd;
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gd = (struct gf_w64_group_data *) h->private;
+  g_s = h->arg1;
+  g_r = h->arg2;
+  gf_w64_group_set_shift_tables(gd->shift, val, h);
+
+  for (i = 63; !(val & (1ULL << i)); i--) ;
+  i += g_s;
+  
+  /* i is the bit position of the first zero bit in any element of
+                           gd->shift[] */
+  
+  if (i > 64) i = 64;   
+  
+  fzb = i;
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 4);
+  
+  gf_do_initial_region_alignment(&rd);
+
+  s64 = (uint64_t *) rd.s_start;
+  d64 = (uint64_t *) rd.d_start;
+  dtop = (uint64_t *) rd.d_top;
+
+  smask = (1 << g_s) - 1;
+  rmask = (1 << g_r) - 1;
+
+  while (d64 < dtop) {
+    a64 = *s64;
+    
+    top = 0;
+    bot = gd->shift[a64&smask];
+    a64 >>= g_s;
+    i = fzb;
+
+    if (a64 != 0) {
+      lshift = 0;
+      rshift = 64;
+  
+      do {  
+        lshift += g_s;
+        rshift -= g_s;
+        tp = gd->shift[a64&smask];
+        top ^= (tp >> rshift);
+        bot ^= (tp << lshift);
+        a64 >>= g_s;
+      } while (a64 != 0);
+      i += lshift;
+  
+      lshift = ((i-64-1) / g_r) * g_r;
+      rshift = 64 - lshift;
+      while (lshift >= 0) {
+        tp = gd->reduce[(top >> lshift) & rmask];
+        top ^= (tp >> rshift);    
+        bot ^= (tp << lshift);
+        lshift -= g_r;
+        rshift += g_r;
+      }
+    }
+
+    if (xor) bot ^= *d64;
+    *d64 = bot;
+    d64++;
+    s64++;
+  }
+  gf_do_final_region_alignment(&rd);
+}
+
+static
+inline
+gf_val_64_t
+gf_w64_group_s_equals_r_multiply(gf_t *gf, gf_val_64_t a, gf_val_64_t b)
+{
+  int leftover, rs;
+  uint64_t p, l, ind, a64;
+  int bits_left;
+  int g_s;
+
+  struct gf_w64_group_data *gd;
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  g_s = h->arg1;
+
+  gd = (struct gf_w64_group_data *) h->private;
+  gf_w64_group_set_shift_tables(gd->shift, b, h);
+
+  leftover = 64 % g_s;
+  if (leftover == 0) leftover = g_s;
+
+  rs = 64 - leftover;
+  a64 = a;
+  ind = a64 >> rs;
+  a64 <<= leftover;
+  p = gd->shift[ind];
+
+  bits_left = rs;
+  rs = 64 - g_s;
+
+  while (bits_left > 0) {
+    bits_left -= g_s;
+    ind = a64 >> rs;
+    a64 <<= g_s;
+    l = p >> rs;
+    p = (gd->shift[ind] ^ gd->reduce[l] ^ (p << g_s));
+  }
+  return p;
+}
+
+static
+void gf_w64_group_s_equals_r_multiply_region(gf_t *gf, void *src, void *dest, gf_val_64_t val, int bytes, int xor)
+{
+  int leftover, rs;
+  uint64_t p, l, ind, a64;
+  int bits_left;
+  int g_s;
+  gf_region_data rd;
+  uint64_t *s64, *d64, *top;
+  struct gf_w64_group_data *gd;
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gd = (struct gf_w64_group_data *) h->private;
+  g_s = h->arg1;
+  gf_w64_group_set_shift_tables(gd->shift, val, h);
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 4);
+  gf_do_initial_region_alignment(&rd);
+
+  s64 = (uint64_t *) rd.s_start;
+  d64 = (uint64_t *) rd.d_start;
+  top = (uint64_t *) rd.d_top;
+
+  leftover = 64 % g_s;
+  if (leftover == 0) leftover = g_s;
+
+  while (d64 < top) {
+    rs = 64 - leftover;
+    a64 = *s64;
+    ind = a64 >> rs;
+    a64 <<= leftover;
+    p = gd->shift[ind];
+
+    bits_left = rs;
+    rs = 64 - g_s;
+
+    while (bits_left > 0) {
+      bits_left -= g_s;
+      ind = a64 >> rs;
+      a64 <<= g_s;
+      l = p >> rs;
+      p = (gd->shift[ind] ^ gd->reduce[l] ^ (p << g_s));
+    }
+    if (xor) p ^= *d64;
+    *d64 = p;
+    d64++;
+    s64++;
+  }
+  gf_do_final_region_alignment(&rd);
+}
+
+
+static
+int gf_w64_group_init(gf_t *gf)
+{
+  uint64_t i, j, p, index;
+  struct gf_w64_group_data *gd;
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  int g_r, g_s;
+
+  g_s = h->arg1;
+  g_r = h->arg2;
+
+  gd = (struct gf_w64_group_data *) h->private;
+  gd->shift = (uint64_t *) (&(gd->memory));
+  gd->reduce = gd->shift + (1 << g_s);
+
+  gd->reduce[0] = 0;
+  for (i = 0; i < (1 << g_r); i++) {
+    p = 0;
+    index = 0;
+    for (j = 0; j < g_r; j++) {
+      if (i & (1 << j)) {
+        p ^= (h->prim_poly << j);
+        index ^= (1 << j);
+        if (j > 0) index ^= (h->prim_poly >> (64-j)); 
+      }
+    }
+    gd->reduce[index] = p;
+  }
+
+  if (g_s == g_r) {
+    gf->multiply.w64 = gf_w64_group_s_equals_r_multiply;
+    gf->multiply_region.w64 = gf_w64_group_s_equals_r_multiply_region; 
+  } else {
+    gf->multiply.w64 = gf_w64_group_multiply;
+    gf->multiply_region.w64 = gf_w64_group_multiply_region; 
+  }
+  gf->divide.w64 = NULL;
+  gf->inverse.w64 = gf_w64_euclid;
+
+  return 1;
+}
+
+static
+gf_val_64_t gf_w64_extract_word(gf_t *gf, void *start, int bytes, int index)
+{
+  uint64_t *r64, rv;
+
+  r64 = (uint64_t *) start;
+  rv = r64[index];
+  return rv;
+}
+
+static
+gf_val_64_t gf_w64_composite_extract_word(gf_t *gf, void *start, int bytes, int index)
+{
+  int sub_size;
+  gf_internal_t *h;
+  uint8_t *r8, *top;
+  uint64_t a, b, *r64;
+  gf_region_data rd;
+
+  h = (gf_internal_t *) gf->scratch;
+  gf_set_region_data(&rd, gf, start, start, bytes, 0, 0, 32);
+  r64 = (uint64_t *) start;
+  if (r64 + index < (uint64_t *) rd.d_start) return r64[index];
+  if (r64 + index >= (uint64_t *) rd.d_top) return r64[index];
+  index -= (((uint64_t *) rd.d_start) - r64);
+  r8 = (uint8_t *) rd.d_start;
+  top = (uint8_t *) rd.d_top;
+  sub_size = (top-r8)/2;
+
+  a = h->base_gf->extract_word.w32(h->base_gf, r8, sub_size, index);
+  b = h->base_gf->extract_word.w32(h->base_gf, r8+sub_size, sub_size, index);
+  return (a | ((uint64_t)b << 32));
+}
+
+static
+gf_val_64_t gf_w64_split_extract_word(gf_t *gf, void *start, int bytes, int index)
+{
+  int i;
+  uint64_t *r64, rv;
+  uint8_t *r8;
+  gf_region_data rd;
+
+  gf_set_region_data(&rd, gf, start, start, bytes, 0, 0, 128);
+  r64 = (uint64_t *) start;
+  if (r64 + index < (uint64_t *) rd.d_start) return r64[index];
+  if (r64 + index >= (uint64_t *) rd.d_top) return r64[index];
+  index -= (((uint64_t *) rd.d_start) - r64);
+  r8 = (uint8_t *) rd.d_start;
+  r8 += ((index & 0xfffffff0)*8);
+  r8 += (index & 0xf);
+  r8 += 112;
+  rv =0;
+  for (i = 0; i < 8; i++) {
+    rv <<= 8;
+    rv |= *r8;
+    r8 -= 16;
+  }
+  return rv;
+}
+
+static
+inline
+gf_val_64_t
+gf_w64_bytwo_b_multiply (gf_t *gf, gf_val_64_t a, gf_val_64_t b)
+{
+  uint64_t prod, pp, bmask;
+  gf_internal_t *h;
+
+  h = (gf_internal_t *) gf->scratch;
+  pp = h->prim_poly;
+
+  prod = 0;
+  bmask = 0x8000000000000000ULL;
+
+  while (1) {
+    if (a & 1) prod ^= b;
+    a >>= 1;
+    if (a == 0) return prod;
+    if (b & bmask) {
+      b = ((b << 1) ^ pp);
+    } else {
+      b <<= 1;
+    }
+  }
+}
+
+static
+inline
+gf_val_64_t
+gf_w64_bytwo_p_multiply (gf_t *gf, gf_val_64_t a, gf_val_64_t b)
+{
+  uint64_t prod, pp, pmask, amask;
+  gf_internal_t *h;
+
+  h = (gf_internal_t *) gf->scratch;
+  pp = h->prim_poly;
+
+  prod = 0;
+  
+  /* changed from declare then shift to just declare.*/
+  
+  pmask = 0x8000000000000000ULL;
+  amask = 0x8000000000000000ULL;
+
+  while (amask != 0) {
+    if (prod & pmask) {
+      prod = ((prod << 1) ^ pp);
+    } else {
+      prod <<= 1;
+    }
+    if (a & amask) prod ^= b;
+    amask >>= 1;
+  }
+  return prod;
+}
+
+static
+void
+gf_w64_bytwo_p_nosse_multiply_region(gf_t *gf, void *src, void *dest, gf_val_64_t val, int bytes, int xor)
+{
+  uint64_t *s64, *d64, ta, prod, amask, pmask, pp;
+  gf_region_data rd;
+  gf_internal_t *h;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 8);
+  gf_do_initial_region_alignment(&rd);
+
+  h = (gf_internal_t *) gf->scratch;
+
+  s64 = (uint64_t *) rd.s_start;
+  d64 = (uint64_t *) rd.d_start;
+  pmask = 0x80000000;
+  pmask <<= 32;
+  pp = h->prim_poly;
+
+  if (xor) {
+    while (s64 < (uint64_t *) rd.s_top) {
+      prod = 0;
+      amask = pmask;
+      ta = *s64;
+      while (amask != 0) {
+        prod = (prod & pmask) ? ((prod << 1) ^ pp) : (prod << 1);
+        if (val & amask) prod ^= ta;
+        amask >>= 1;
+      }
+      *d64 ^= prod;
+      d64++;
+      s64++;
+    }
+  } else {
+    while (s64 < (uint64_t *) rd.s_top) {
+      prod = 0;
+      amask = pmask;
+      ta = *s64;
+      while (amask != 0) {
+        prod = (prod & pmask) ? ((prod << 1) ^ pp) : (prod << 1);
+        if (val & amask) prod ^= ta;
+        amask >>= 1;
+      }
+      *d64 = prod;
+      d64++;
+      s64++;
+    }
+  }
+  gf_do_final_region_alignment(&rd);
+}
+
+static
+void
+gf_w64_bytwo_b_nosse_multiply_region(gf_t *gf, void *src, void *dest, gf_val_64_t val, int bytes, int xor)
+{
+  uint64_t *s64, *d64, ta, tb, prod, bmask, pp;
+  gf_region_data rd;
+  gf_internal_t *h;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 8);
+  gf_do_initial_region_alignment(&rd);
+
+  h = (gf_internal_t *) gf->scratch;
+
+  s64 = (uint64_t *) rd.s_start;
+  d64 = (uint64_t *) rd.d_start;
+  bmask = 0x80000000;
+  bmask <<= 32;
+  pp = h->prim_poly;
+
+  if (xor) {
+    while (s64 < (uint64_t *) rd.s_top) {
+      prod = 0;
+      tb = val;
+      ta = *s64;
+      while (1) {
+        if (tb & 1) prod ^= ta;
+        tb >>= 1;
+        if (tb == 0) break;
+        ta = (ta & bmask) ? ((ta << 1) ^ pp) : (ta << 1);
+      }
+      *d64 ^= prod;
+      d64++;
+      s64++;
+    }
+  } else {
+    while (s64 < (uint64_t *) rd.s_top) {
+      prod = 0;
+      tb = val;
+      ta = *s64;
+      while (1) {
+        if (tb & 1) prod ^= ta;
+        tb >>= 1;
+        if (tb == 0) break;
+        ta = (ta & bmask) ? ((ta << 1) ^ pp) : (ta << 1);
+      }
+      *d64 = prod;
+      d64++;
+      s64++;
+    }
+  }
+  gf_do_final_region_alignment(&rd);
+}
+
+#define SSE_AB2(pp, m1 ,m2, va, t1, t2) {\
+          t1 = _mm_and_si128(_mm_slli_epi64(va, 1), m1); \
+          t2 = _mm_and_si128(va, m2); \
+          t2 = _mm_sub_epi64 (_mm_slli_epi64(t2, 1), _mm_srli_epi64(t2, (GF_FIELD_WIDTH-1))); \
+          va = _mm_xor_si128(t1, _mm_and_si128(t2, pp)); }
+
+#define BYTWO_P_ONESTEP {\
+      SSE_AB2(pp, m1 ,m2, prod, t1, t2); \
+      t1 = _mm_and_si128(v, one); \
+      t1 = _mm_sub_epi64(t1, one); \
+      t1 = _mm_and_si128(t1, ta); \
+      prod = _mm_xor_si128(prod, t1); \
+      v = _mm_srli_epi64(v, 1); }
+
+
+void gf_w64_bytwo_p_sse_multiply_region(gf_t *gf, void *src, void *dest, gf_val_64_t val, int bytes, int xor)
+{
+#ifdef INTEL_SSE2
+  int i;
+  uint8_t *s8, *d8;
+  uint64_t vrev, one64;
+  uint64_t amask;
+  __m128i pp, m1, m2, ta, prod, t1, t2, tp, one, v;
+  gf_region_data rd;
+  gf_internal_t *h;
+  
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 16);
+  gf_do_initial_region_alignment(&rd);
+
+  h = (gf_internal_t *) gf->scratch;
+  one64 = 1;
+  vrev = 0;
+  for (i = 0; i < 64; i++) {
+    vrev <<= 1;
+    if (!(val & (one64 << i))) vrev |= 1;
+  }
+
+  s8 = (uint8_t *) rd.s_start;
+  d8 = (uint8_t *) rd.d_start;
+
+  amask = -1;
+  amask ^= 1;
+  pp = _mm_set1_epi64x(h->prim_poly);
+  m1 = _mm_set1_epi64x(amask);
+  m2 = _mm_set1_epi64x(one64 << 63);
+  one = _mm_set1_epi64x(1);
+
+  while (d8 < (uint8_t *) rd.d_top) {
+    prod = _mm_setzero_si128();
+    v = _mm_set1_epi64x(vrev);
+    ta = _mm_load_si128((__m128i *) s8);
+    tp = (!xor) ? _mm_setzero_si128() : _mm_load_si128((__m128i *) d8);
+    BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP; BYTWO_P_ONESTEP;
+    _mm_store_si128((__m128i *) d8, _mm_xor_si128(prod, tp));
+    d8 += 16;
+    s8 += 16;
+  }
+  gf_do_final_region_alignment(&rd);
+#endif
+}
+
+#ifdef INTEL_SSE2
+static
+void
+gf_w64_bytwo_b_sse_region_2_xor(gf_region_data *rd)
+{
+  uint64_t one64, amask;
+  uint8_t *d8, *s8;
+  __m128i pp, m1, m2, t1, t2, va, vb;
+  gf_internal_t *h;
+
+  s8 = (uint8_t *) rd->s_start;
+  d8 = (uint8_t *) rd->d_start;
+
+  h = (gf_internal_t *) rd->gf->scratch;
+  one64 = 1;
+  amask = -1;
+  amask ^= 1;
+  pp = _mm_set1_epi64x(h->prim_poly);
+  m1 = _mm_set1_epi64x(amask);
+  m2 = _mm_set1_epi64x(one64 << 63);
+
+  while (d8 < (uint8_t *) rd->d_top) {
+    va = _mm_load_si128 ((__m128i *)(s8));
+    SSE_AB2(pp, m1, m2, va, t1, t2);
+    vb = _mm_load_si128 ((__m128i *)(d8));
+    vb = _mm_xor_si128(vb, va);
+    _mm_store_si128((__m128i *)d8, vb);
+    d8 += 16;
+    s8 += 16;
+  }
+}
+#endif
+
+#ifdef INTEL_SSE2
+static
+void
+gf_w64_bytwo_b_sse_region_2_noxor(gf_region_data *rd)
+{
+  uint64_t one64, amask;
+  uint8_t *d8, *s8;
+  __m128i pp, m1, m2, t1, t2, va;
+  gf_internal_t *h;
+
+  s8 = (uint8_t *) rd->s_start;
+  d8 = (uint8_t *) rd->d_start;
+
+  h = (gf_internal_t *) rd->gf->scratch;
+  one64 = 1;
+  amask = -1;
+  amask ^= 1;
+  pp = _mm_set1_epi64x(h->prim_poly);
+  m1 = _mm_set1_epi64x(amask);
+  m2 = _mm_set1_epi64x(one64 << 63);
+
+  while (d8 < (uint8_t *) rd->d_top) {
+    va = _mm_load_si128 ((__m128i *)(s8));
+    SSE_AB2(pp, m1, m2, va, t1, t2);
+    _mm_store_si128((__m128i *)d8, va);
+    d8 += 16;
+    s8 += 16;
+  }
+}
+#endif
+
+#ifdef INTEL_SSE2
+static
+void
+gf_w64_bytwo_b_sse_multiply_region(gf_t *gf, void *src, void *dest, gf_val_64_t val, int bytes, int xor)
+{
+  uint64_t itb, amask, one64;
+  uint8_t *d8, *s8;
+  __m128i pp, m1, m2, t1, t2, va, vb;
+  gf_region_data rd;
+  gf_internal_t *h;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 16);
+  gf_do_initial_region_alignment(&rd);
+
+  if (val == 2) {
+    if (xor) {
+      gf_w64_bytwo_b_sse_region_2_xor(&rd);
+    } else {
+      gf_w64_bytwo_b_sse_region_2_noxor(&rd);
+    }
+    gf_do_final_region_alignment(&rd);
+    return;
+  }
+
+  s8 = (uint8_t *) rd.s_start;
+  d8 = (uint8_t *) rd.d_start;
+  h = (gf_internal_t *) gf->scratch;
+
+  one64 = 1;
+  amask = -1;
+  amask ^= 1;
+  pp = _mm_set1_epi64x(h->prim_poly);
+  m1 = _mm_set1_epi64x(amask);
+  m2 = _mm_set1_epi64x(one64 << 63);
+
+  while (d8 < (uint8_t *) rd.d_top) {
+    va = _mm_load_si128 ((__m128i *)(s8));
+    vb = (!xor) ? _mm_setzero_si128() : _mm_load_si128 ((__m128i *)(d8));
+    itb = val;
+    while (1) {
+      if (itb & 1) vb = _mm_xor_si128(vb, va);
+      itb >>= 1;
+      if (itb == 0) break;
+      SSE_AB2(pp, m1, m2, va, t1, t2);
+    }
+    _mm_store_si128((__m128i *)d8, vb);
+    d8 += 16;
+    s8 += 16;
+  }
+
+  gf_do_final_region_alignment(&rd);
+}
+#endif
+
+
+static
+int gf_w64_bytwo_init(gf_t *gf)
+{
+  gf_internal_t *h;
+
+  h = (gf_internal_t *) gf->scratch;
+
+  if (h->mult_type == GF_MULT_BYTWO_p) {
+    gf->multiply.w64 = gf_w64_bytwo_p_multiply;
+    #ifdef INTEL_SSE2 
+      if (h->region_type & GF_REGION_NOSSE)
+        gf->multiply_region.w64 = gf_w64_bytwo_p_nosse_multiply_region; 
+      else
+        gf->multiply_region.w64 = gf_w64_bytwo_p_sse_multiply_region; 
+    #else
+      gf->multiply_region.w64 = gf_w64_bytwo_p_nosse_multiply_region; 
+      if(h->region_type & GF_REGION_SSE)
+        return 0;
+    #endif
+  } else {
+    gf->multiply.w64 = gf_w64_bytwo_b_multiply;
+    #ifdef INTEL_SSE2 
+      if (h->region_type & GF_REGION_NOSSE)
+        gf->multiply_region.w64 = gf_w64_bytwo_b_nosse_multiply_region; 
+      else
+        gf->multiply_region.w64 = gf_w64_bytwo_b_sse_multiply_region; 
+    #else
+      gf->multiply_region.w64 = gf_w64_bytwo_b_nosse_multiply_region; 
+      if(h->region_type & GF_REGION_SSE)
+        return 0;
+    #endif
+  }
+  gf->inverse.w64 = gf_w64_euclid;
+  return 1;
+}
+
+
+static
+gf_val_64_t
+gf_w64_composite_multiply(gf_t *gf, gf_val_64_t a, gf_val_64_t b)
+{
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  gf_t *base_gf = h->base_gf;
+  uint32_t b0 = b & 0x00000000ffffffff;
+  uint32_t b1 = (b & 0xffffffff00000000) >> 32;
+  uint32_t a0 = a & 0x00000000ffffffff;
+  uint32_t a1 = (a & 0xffffffff00000000) >> 32;
+  uint32_t a1b1;
+
+  a1b1 = base_gf->multiply.w32(base_gf, a1, b1);
+
+  return ((uint64_t)(base_gf->multiply.w32(base_gf, a0, b0) ^ a1b1) | 
+         ((uint64_t)(base_gf->multiply.w32(base_gf, a1, b0) ^ base_gf->multiply.w32(base_gf, a0, b1) ^ base_gf->multiply.w32(base_gf, a1b1, h->prim_poly)) << 32));
+}
+
+/*
+ * Composite field division trick (explained in 2007 tech report)
+ *
+ * Compute a / b = a*b^-1, where p(x) = x^2 + sx + 1
+ *
+ * let c = b^-1
+ *
+ * c*b = (s*b1c1+b1c0+b0c1)x+(b1c1+b0c0)
+ *
+ * want (s*b1c1+b1c0+b0c1) = 0 and (b1c1+b0c0) = 1
+ *
+ * let d = b1c1 and d+1 = b0c0
+ *
+ * solve s*b1c1+b1c0+b0c1 = 0
+ *
+ * solution: d = (b1b0^-1)(b1b0^-1+b0b1^-1+s)^-1
+ *
+ * c0 = (d+1)b0^-1
+ * c1 = d*b1^-1
+ *
+ * a / b = a * c
+ */
+
+static
+gf_val_64_t
+gf_w64_composite_inverse(gf_t *gf, gf_val_64_t a)
+{
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  gf_t *base_gf = h->base_gf;
+  uint32_t a0 = a & 0x00000000ffffffff;
+  uint32_t a1 = (a & 0xffffffff00000000) >> 32;
+  uint32_t c0, c1, d, tmp;
+  uint64_t c;
+  uint32_t a0inv, a1inv;
+
+  if (a0 == 0) {
+    a1inv = base_gf->inverse.w32(base_gf, a1);
+    c0 = base_gf->multiply.w32(base_gf, a1inv, h->prim_poly);
+    c1 = a1inv;
+  } else if (a1 == 0) {
+    c0 = base_gf->inverse.w32(base_gf, a0);
+    c1 = 0;
+  } else {
+    a1inv = base_gf->inverse.w32(base_gf, a1);
+    a0inv = base_gf->inverse.w32(base_gf, a0);
+
+    d = base_gf->multiply.w32(base_gf, a1, a0inv);
+
+    tmp = (base_gf->multiply.w32(base_gf, a1, a0inv) ^ base_gf->multiply.w32(base_gf, a0, a1inv) ^ h->prim_poly);
+    tmp = base_gf->inverse.w32(base_gf, tmp);
+
+    d = base_gf->multiply.w32(base_gf, d, tmp);
+
+    c0 = base_gf->multiply.w32(base_gf, (d^1), a0inv);
+    c1 = base_gf->multiply.w32(base_gf, d, a1inv);
+  }
+
+  c = c0 | ((uint64_t)c1 << 32);
+
+  return c;
+}
+
+static
+void
+gf_w64_composite_multiply_region(gf_t *gf, void *src, void *dest, gf_val_64_t val, int bytes, int xor)
+{
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  gf_t *base_gf = h->base_gf;
+  uint32_t b0 = val & 0x00000000ffffffff;
+  uint32_t b1 = (val & 0xffffffff00000000) >> 32;
+  uint64_t *s64, *d64;
+  uint64_t *top;
+  uint64_t a0, a1, a1b1;
+  gf_region_data rd;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 8);
+
+  s64 = rd.s_start;
+  d64 = rd.d_start;
+  top = rd.d_top;
+  
+  if (xor) {
+    while (d64 < top) {
+      a0 = *s64 & 0x00000000ffffffff;
+      a1 = (*s64 & 0xffffffff00000000) >> 32;
+      a1b1 = base_gf->multiply.w32(base_gf, a1, b1);
+
+      *d64 ^= ((uint64_t)(base_gf->multiply.w32(base_gf, a0, b0) ^ a1b1) |
+                ((uint64_t)(base_gf->multiply.w32(base_gf, a1, b0) ^ base_gf->multiply.w32(base_gf, a0, b1) ^ base_gf->multiply.w32(base_gf, a1b1, h->prim_poly)) << 32));
+      s64++;
+      d64++;
+    }
+  } else {
+    while (d64 < top) {
+      a0 = *s64 & 0x00000000ffffffff;
+      a1 = (*s64 & 0xffffffff00000000) >> 32;
+      a1b1 = base_gf->multiply.w32(base_gf, a1, b1);
+
+      *d64 = ((base_gf->multiply.w32(base_gf, a0, b0) ^ a1b1) |
+                ((uint64_t)(base_gf->multiply.w32(base_gf, a1, b0) ^ base_gf->multiply.w32(base_gf, a0, b1) ^ base_gf->multiply.w32(base_gf, a1b1, h->prim_poly)) << 32));
+      s64++;
+      d64++;
+    }
+  }
+}
+
+static
+void
+gf_w64_composite_multiply_region_alt(gf_t *gf, void *src, void *dest, gf_val_64_t val, int bytes, int xor)
+{
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  gf_t *base_gf = h->base_gf;
+  gf_val_32_t val0 = val & 0x00000000ffffffff;
+  gf_val_32_t val1 = (val & 0xffffffff00000000) >> 32;
+  uint8_t *slow, *shigh;
+  uint8_t *dlow, *dhigh, *top;
+  int sub_reg_size;
+  gf_region_data rd;
+
+  if (!xor) {
+    memset(dest, 0, bytes);
+  }
+  
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 32);
+  gf_do_initial_region_alignment(&rd);
+
+  slow = (uint8_t *) rd.s_start;
+  dlow = (uint8_t *) rd.d_start;
+  top = (uint8_t*) rd.d_top;
+  sub_reg_size = (top - dlow)/2;
+  shigh = slow + sub_reg_size;
+  dhigh = dlow + sub_reg_size;
+
+  base_gf->multiply_region.w32(base_gf, slow, dlow, val0, sub_reg_size, xor);
+  base_gf->multiply_region.w32(base_gf, shigh, dlow, val1, sub_reg_size, 1);
+  base_gf->multiply_region.w32(base_gf, slow, dhigh, val1, sub_reg_size, xor);
+  base_gf->multiply_region.w32(base_gf, shigh, dhigh, val0, sub_reg_size, 1);
+  base_gf->multiply_region.w32(base_gf, shigh, dhigh, base_gf->multiply.w32(base_gf, h->prim_poly, val1), sub_reg_size, 1);
+
+  gf_do_final_region_alignment(&rd);
+}
+
+
+
+static
+int gf_w64_composite_init(gf_t *gf)
+{
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+
+  if (h->region_type & GF_REGION_ALTMAP) {
+    gf->multiply_region.w64 = gf_w64_composite_multiply_region_alt;
+  } else {
+    gf->multiply_region.w64 = gf_w64_composite_multiply_region;
+  }
+
+  gf->multiply.w64 = gf_w64_composite_multiply;
+  gf->divide.w64 = NULL;
+  gf->inverse.w64 = gf_w64_composite_inverse;
+
+  return 1;
+}
+
+#ifdef INTEL_SSSE3
+static
+  void
+gf_w64_split_4_64_lazy_sse_altmap_multiply_region(gf_t *gf, void *src, void *dest, uint64_t val, int bytes, int xor)
+{
+  gf_internal_t *h;
+  int i, j, k;
+  uint64_t pp, v, *s64, *d64, *top;
+  __m128i si, tables[16][8], p[8], v0, mask1;
+  struct gf_split_4_64_lazy_data *ld;
+  uint8_t btable[16];
+  gf_region_data rd;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  h = (gf_internal_t *) gf->scratch;
+  pp = h->prim_poly;
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 128);
+  gf_do_initial_region_alignment(&rd);
+
+  s64 = (uint64_t *) rd.s_start;
+  d64 = (uint64_t *) rd.d_start;
+  top = (uint64_t *) rd.d_top;
+ 
+  ld = (struct gf_split_4_64_lazy_data *) h->private;
+
+  v = val;
+  for (i = 0; i < 16; i++) {
+    ld->tables[i][0] = 0;
+    for (j = 1; j < 16; j <<= 1) {
+      for (k = 0; k < j; k++) {
+        ld->tables[i][k^j] = (v ^ ld->tables[i][k]);
+      }
+      v = (v & GF_FIRST_BIT) ? ((v << 1) ^ pp) : (v << 1);
+    }
+    for (j = 0; j < 8; j++) {
+      for (k = 0; k < 16; k++) {
+        btable[k] = (uint8_t) ld->tables[i][k];
+        ld->tables[i][k] >>= 8;
+      }
+      tables[i][j] = _mm_loadu_si128((__m128i *) btable);
+    }
+  }
+
+  mask1 = _mm_set1_epi8(0xf);
+
+  while (d64 != top) {
+
+    if (xor) {
+      for (i = 0; i < 8; i++) p[i] = _mm_load_si128 ((__m128i *) (d64+i*2));
+    } else {
+      for (i = 0; i < 8; i++) p[i] = _mm_setzero_si128();
+    }
+    i = 0;
+    for (k = 0; k < 8; k++) {
+      v0 = _mm_load_si128((__m128i *) s64); 
+      /* MM_PRINT8("v", v0); */
+      s64 += 2;
+      
+      si = _mm_and_si128(v0, mask1);
+  
+      for (j = 0; j < 8; j++) {
+        p[j] = _mm_xor_si128(p[j], _mm_shuffle_epi8(tables[i][j], si));
+      }
+      i++;
+      v0 = _mm_srli_epi32(v0, 4);
+      si = _mm_and_si128(v0, mask1);
+      for (j = 0; j < 8; j++) {
+        p[j] = _mm_xor_si128(p[j], _mm_shuffle_epi8(tables[i][j], si));
+      }
+      i++;
+    }
+    for (i = 0; i < 8; i++) {
+      /* MM_PRINT8("v", p[i]); */
+      _mm_store_si128((__m128i *) d64, p[i]);
+      d64 += 2;
+    }
+  }
+  gf_do_final_region_alignment(&rd);
+}
+#endif
+
+#ifdef INTEL_SSE4
+static
+  void
+gf_w64_split_4_64_lazy_sse_multiply_region(gf_t *gf, void *src, void *dest, uint64_t val, int bytes, int xor)
+{
+  gf_internal_t *h;
+  int i, j, k;
+  uint64_t pp, v, *s64, *d64, *top;
+  __m128i si, tables[16][8], p[8], st[8], mask1, mask8, mask16, t1;
+  struct gf_split_4_64_lazy_data *ld;
+  uint8_t btable[16];
+  gf_region_data rd;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  h = (gf_internal_t *) gf->scratch;
+  pp = h->prim_poly;
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 128);
+  gf_do_initial_region_alignment(&rd);
+
+  s64 = (uint64_t *) rd.s_start;
+  d64 = (uint64_t *) rd.d_start;
+  top = (uint64_t *) rd.d_top;
+ 
+  ld = (struct gf_split_4_64_lazy_data *) h->private;
+
+  v = val;
+  for (i = 0; i < 16; i++) {
+    ld->tables[i][0] = 0;
+    for (j = 1; j < 16; j <<= 1) {
+      for (k = 0; k < j; k++) {
+        ld->tables[i][k^j] = (v ^ ld->tables[i][k]);
+      }
+      v = (v & GF_FIRST_BIT) ? ((v << 1) ^ pp) : (v << 1);
+    }
+    for (j = 0; j < 8; j++) {
+      for (k = 0; k < 16; k++) {
+        btable[k] = (uint8_t) ld->tables[i][k];
+        ld->tables[i][k] >>= 8;
+      }
+      tables[i][j] = _mm_loadu_si128((__m128i *) btable);
+    }
+  }
+
+  mask1 = _mm_set1_epi8(0xf);
+  mask8 = _mm_set1_epi16(0xff);
+  mask16 = _mm_set1_epi32(0xffff);
+
+  while (d64 != top) {
+
+    for (i = 0; i < 8; i++) p[i] = _mm_setzero_si128();
+
+    for (k = 0; k < 8; k++) {
+      st[k]  = _mm_load_si128((__m128i *) s64); 
+      s64 += 2;
+    }
+
+    for (k = 0; k < 4; k ++) {
+      st[k] = _mm_shuffle_epi32(st[k], _MM_SHUFFLE(3,1,2,0));
+      st[k+4] = _mm_shuffle_epi32(st[k+4], _MM_SHUFFLE(2,0,3,1));
+      t1 = _mm_blend_epi16(st[k], st[k+4], 0xf0);
+      st[k] = _mm_srli_si128(st[k], 8);
+      st[k+4] = _mm_slli_si128(st[k+4], 8);
+      st[k+4] = _mm_blend_epi16(st[k], st[k+4], 0xf0);
+      st[k] = t1;
+    }
+
+/*
+    printf("After pack pass 1\n");
+    for (k = 0; k < 8; k++) {
+      MM_PRINT8("v", st[k]);
+    }
+    printf("\n");
+ */
+    
+    t1 = _mm_packus_epi32(_mm_and_si128(st[0], mask16), _mm_and_si128(st[2], mask16));
+    st[2] = _mm_packus_epi32(_mm_srli_epi32(st[0], 16), _mm_srli_epi32(st[2], 16));
+    st[0] = t1;
+    t1 = _mm_packus_epi32(_mm_and_si128(st[1], mask16), _mm_and_si128(st[3], mask16));
+    st[3] = _mm_packus_epi32(_mm_srli_epi32(st[1], 16), _mm_srli_epi32(st[3], 16));
+    st[1] = t1;
+    t1 = _mm_packus_epi32(_mm_and_si128(st[4], mask16), _mm_and_si128(st[6], mask16));
+    st[6] = _mm_packus_epi32(_mm_srli_epi32(st[4], 16), _mm_srli_epi32(st[6], 16));
+    st[4] = t1;
+    t1 = _mm_packus_epi32(_mm_and_si128(st[5], mask16), _mm_and_si128(st[7], mask16));
+    st[7] = _mm_packus_epi32(_mm_srli_epi32(st[5], 16), _mm_srli_epi32(st[7], 16));
+    st[5] = t1;
+
+/*
+    printf("After pack pass 2\n");
+    for (k = 0; k < 8; k++) {
+      MM_PRINT8("v", st[k]);
+    }
+    printf("\n");
+ */
+    t1 = _mm_packus_epi16(_mm_and_si128(st[0], mask8), _mm_and_si128(st[1], mask8));
+    st[1] = _mm_packus_epi16(_mm_srli_epi16(st[0], 8), _mm_srli_epi16(st[1], 8));
+    st[0] = t1;
+    t1 = _mm_packus_epi16(_mm_and_si128(st[2], mask8), _mm_and_si128(st[3], mask8));
+    st[3] = _mm_packus_epi16(_mm_srli_epi16(st[2], 8), _mm_srli_epi16(st[3], 8));
+    st[2] = t1;
+    t1 = _mm_packus_epi16(_mm_and_si128(st[4], mask8), _mm_and_si128(st[5], mask8));
+    st[5] = _mm_packus_epi16(_mm_srli_epi16(st[4], 8), _mm_srli_epi16(st[5], 8));
+    st[4] = t1;
+    t1 = _mm_packus_epi16(_mm_and_si128(st[6], mask8), _mm_and_si128(st[7], mask8));
+    st[7] = _mm_packus_epi16(_mm_srli_epi16(st[6], 8), _mm_srli_epi16(st[7], 8));
+    st[6] = t1;
+
+/*
+    printf("After final pack pass 2\n");
+    for (k = 0; k < 8; k++) {
+      MM_PRINT8("v", st[k]);
+    }
+ */
+    i = 0;
+    for (k = 0; k < 8; k++) {
+      si = _mm_and_si128(st[k], mask1);
+  
+      for (j = 0; j < 8; j++) {
+        p[j] = _mm_xor_si128(p[j], _mm_shuffle_epi8(tables[i][j], si));
+      }
+      i++;
+      st[k] = _mm_srli_epi32(st[k], 4);
+      si = _mm_and_si128(st[k], mask1);
+      for (j = 0; j < 8; j++) {
+        p[j] = _mm_xor_si128(p[j], _mm_shuffle_epi8(tables[i][j], si));
+      }
+      i++;
+    }
+
+    t1 = _mm_unpacklo_epi8(p[0], p[1]);
+    p[1] = _mm_unpackhi_epi8(p[0], p[1]);
+    p[0] = t1;
+    t1 = _mm_unpacklo_epi8(p[2], p[3]);
+    p[3] = _mm_unpackhi_epi8(p[2], p[3]);
+    p[2] = t1;
+    t1 = _mm_unpacklo_epi8(p[4], p[5]);
+    p[5] = _mm_unpackhi_epi8(p[4], p[5]);
+    p[4] = t1;
+    t1 = _mm_unpacklo_epi8(p[6], p[7]);
+    p[7] = _mm_unpackhi_epi8(p[6], p[7]);
+    p[6] = t1;
+
+/*
+    printf("After unpack pass 1:\n");
+    for (i = 0; i < 8; i++) {
+      MM_PRINT8("v", p[i]);
+    }
+ */
+
+    t1 = _mm_unpacklo_epi16(p[0], p[2]);
+    p[2] = _mm_unpackhi_epi16(p[0], p[2]);
+    p[0] = t1;
+    t1 = _mm_unpacklo_epi16(p[1], p[3]);
+    p[3] = _mm_unpackhi_epi16(p[1], p[3]);
+    p[1] = t1;
+    t1 = _mm_unpacklo_epi16(p[4], p[6]);
+    p[6] = _mm_unpackhi_epi16(p[4], p[6]);
+    p[4] = t1;
+    t1 = _mm_unpacklo_epi16(p[5], p[7]);
+    p[7] = _mm_unpackhi_epi16(p[5], p[7]);
+    p[5] = t1;
+
+/*
+    printf("After unpack pass 2:\n");
+    for (i = 0; i < 8; i++) {
+      MM_PRINT8("v", p[i]);
+    }
+ */
+
+    t1 = _mm_unpacklo_epi32(p[0], p[4]);
+    p[4] = _mm_unpackhi_epi32(p[0], p[4]);
+    p[0] = t1;
+    t1 = _mm_unpacklo_epi32(p[1], p[5]);
+    p[5] = _mm_unpackhi_epi32(p[1], p[5]);
+    p[1] = t1;
+    t1 = _mm_unpacklo_epi32(p[2], p[6]);
+    p[6] = _mm_unpackhi_epi32(p[2], p[6]);
+    p[2] = t1;
+    t1 = _mm_unpacklo_epi32(p[3], p[7]);
+    p[7] = _mm_unpackhi_epi32(p[3], p[7]);
+    p[3] = t1;
+
+    if (xor) {
+      for (i = 0; i < 8; i++) {
+        t1 = _mm_load_si128((__m128i *) d64);
+        _mm_store_si128((__m128i *) d64, _mm_xor_si128(p[i], t1));
+        d64 += 2;
+      }
+    } else {
+      for (i = 0; i < 8; i++) {
+        _mm_store_si128((__m128i *) d64, p[i]);
+        d64 += 2;
+      }
+    }
+
+  }
+
+  gf_do_final_region_alignment(&rd);
+}
+#endif
+
+#define GF_MULTBY_TWO(p) (((p) & GF_FIRST_BIT) ? (((p) << 1) ^ h->prim_poly) : (p) << 1);
+
+static
+int gf_w64_split_init(gf_t *gf)
+{
+  gf_internal_t *h;
+  struct gf_split_4_64_lazy_data *d4;
+  struct gf_split_8_64_lazy_data *d8;
+  struct gf_split_8_8_data *d88;
+  struct gf_split_16_64_lazy_data *d16;
+  uint64_t p, basep;
+  int exp, i, j;
+
+  h = (gf_internal_t *) gf->scratch;
+
+  /* Defaults */
+
+  gf->multiply_region.w64 = gf_w64_multiply_region_from_single;
+
+  gf->multiply.w64 = gf_w64_bytwo_p_multiply; 
+
+#if defined(INTEL_SSE4_PCLMUL) 
+  if ((!(h->region_type & GF_REGION_NOSSE) &&
+     (h->arg1 == 64 || h->arg2 == 64)) ||
+     h->mult_type == GF_MULT_DEFAULT){
+   
+    if ((0xfffffffe00000000ULL & h->prim_poly) == 0){ 
+      gf->multiply.w64 = gf_w64_clm_multiply_2;
+      gf->multiply_region.w64 = gf_w64_clm_multiply_region_from_single_2; 
+    }else if((0xfffe000000000000ULL & h->prim_poly) == 0){
+      gf->multiply.w64 = gf_w64_clm_multiply_4;
+      gf->multiply_region.w64 = gf_w64_clm_multiply_region_from_single_4; 
+    }else{
+      return 0;
+    }
+  }
+#endif
+
+  gf->inverse.w64 = gf_w64_euclid;
+
+  /* Allen: set region pointers for default mult type. Single pointers are
+   * taken care of above (explicitly for sse, implicitly for no sse). */
+
+#ifdef INTEL_SSE4
+  if (h->mult_type == GF_MULT_DEFAULT) {
+    d4 = (struct gf_split_4_64_lazy_data *) h->private;
+    d4->last_value = 0;
+    gf->multiply_region.w64 = gf_w64_split_4_64_lazy_sse_multiply_region; 
+  }
+#else
+  if (h->mult_type == GF_MULT_DEFAULT) {
+    d8 = (struct gf_split_8_64_lazy_data *) h->private;
+    d8->last_value = 0;
+    gf->multiply_region.w64 = gf_w64_split_8_64_lazy_multiply_region;
+  }
+#endif
+
+  if ((h->arg1 == 4 && h->arg2 == 64) || (h->arg1 == 64 && h->arg2 == 4)) {
+    d4 = (struct gf_split_4_64_lazy_data *) h->private;
+    d4->last_value = 0;
+
+    if((h->region_type & GF_REGION_ALTMAP) && (h->region_type & GF_REGION_NOSSE)) return 0;
+    if(h->region_type & GF_REGION_ALTMAP)
+    {
+      #ifdef INTEL_SSSE3
+        gf->multiply_region.w64 = gf_w64_split_4_64_lazy_sse_altmap_multiply_region; 
+      #else
+        return 0;
+      #endif
+    }
+    else //no altmap
+    {
+      #ifdef INTEL_SSE4
+        if(h->region_type & GF_REGION_NOSSE)
+          gf->multiply_region.w64 = gf_w64_split_4_64_lazy_multiply_region;
+        else
+          gf->multiply_region.w64 = gf_w64_split_4_64_lazy_sse_multiply_region; 
+      #else
+        gf->multiply_region.w64 = gf_w64_split_4_64_lazy_multiply_region;
+        if(h->region_type & GF_REGION_SSE)
+          return 0;
+      #endif
+    }
+  }
+  if ((h->arg1 == 8 && h->arg2 == 64) || (h->arg1 == 64 && h->arg2 == 8)) {
+    d8 = (struct gf_split_8_64_lazy_data *) h->private;
+    d8->last_value = 0;
+    gf->multiply_region.w64 = gf_w64_split_8_64_lazy_multiply_region;
+  }
+  if ((h->arg1 == 16 && h->arg2 == 64) || (h->arg1 == 64 && h->arg2 == 16)) {
+    d16 = (struct gf_split_16_64_lazy_data *) h->private;
+    d16->last_value = 0;
+    gf->multiply_region.w64 = gf_w64_split_16_64_lazy_multiply_region;
+  }
+  if ((h->arg1 == 8 && h->arg2 == 8)) {
+    d88 = (struct gf_split_8_8_data *) h->private;
+    gf->multiply.w64 = gf_w64_split_8_8_multiply;
+
+    /* The performance of this guy sucks, so don't bother with a region op */
+    
+    basep = 1;
+    for (exp = 0; exp < 15; exp++) {
+      for (j = 0; j < 256; j++) d88->tables[exp][0][j] = 0;
+      for (i = 0; i < 256; i++) d88->tables[exp][i][0] = 0;
+      d88->tables[exp][1][1] = basep;
+      for (i = 2; i < 256; i++) {
+        if (i&1) {
+          p = d88->tables[exp][i^1][1];
+          d88->tables[exp][i][1] = p ^ basep;
+        } else {
+          p = d88->tables[exp][i>>1][1];
+          d88->tables[exp][i][1] = GF_MULTBY_TWO(p);
+        }
+      }
+      for (i = 1; i < 256; i++) {
+        p = d88->tables[exp][i][1];
+        for (j = 1; j < 256; j++) {
+          if (j&1) {
+            d88->tables[exp][i][j] = d88->tables[exp][i][j^1] ^ p;
+          } else {
+            d88->tables[exp][i][j] = GF_MULTBY_TWO(d88->tables[exp][i][j>>1]);
+          }
+        }
+      }
+      for (i = 0; i < 8; i++) basep = GF_MULTBY_TWO(basep);
+    }
+  }
+  return 1;
+}
+
+int gf_w64_scratch_size(int mult_type, int region_type, int divide_type, int arg1, int arg2)
+{
+  switch(mult_type)
+  {
+    case GF_MULT_SHIFT:
+      return sizeof(gf_internal_t);
+      break;
+    case GF_MULT_CARRY_FREE:
+      return sizeof(gf_internal_t);
+      break;
+    case GF_MULT_BYTWO_p:
+    case GF_MULT_BYTWO_b:
+      return sizeof(gf_internal_t);
+      break;
+
+    case GF_MULT_DEFAULT:
+
+      /* Allen: set the *local* arg1 and arg2, just for scratch size purposes,
+       * then fall through to split table scratch size code. */
+
+#ifdef INTEL_SSE4
+      arg1 = 64;
+      arg2 = 4;
+#else
+      arg1 = 64;
+      arg2 = 8;
+#endif
+
+    case GF_MULT_SPLIT_TABLE:
+        if (arg1 == 8 && arg2 == 8) {
+          return sizeof(gf_internal_t) + sizeof(struct gf_split_8_8_data) + 64;
+        }
+        if ((arg1 == 16 && arg2 == 64) || (arg2 == 16 && arg1 == 64)) {
+          return sizeof(gf_internal_t) + sizeof(struct gf_split_16_64_lazy_data) + 64;
+        }
+        if ((arg1 == 8 && arg2 == 64) || (arg2 == 8 && arg1 == 64)) {
+          return sizeof(gf_internal_t) + sizeof(struct gf_split_8_64_lazy_data) + 64;
+        }
+
+        if ((arg1 == 64 && arg2 == 4) || (arg1 == 4 && arg2 == 64)) {
+          return sizeof(gf_internal_t) + sizeof(struct gf_split_4_64_lazy_data) + 64;
+        }
+        return 0;
+    case GF_MULT_GROUP:
+      return sizeof(gf_internal_t) + sizeof(struct gf_w64_group_data) +
+               sizeof(uint64_t) * (1 << arg1) +
+               sizeof(uint64_t) * (1 << arg2) + 64;
+      break;
+    case GF_MULT_COMPOSITE:
+      if (arg1 == 2) return sizeof(gf_internal_t) + 64;
+      return 0;
+      break;
+    default:
+      return 0;
+   }
+}
+
+int gf_w64_init(gf_t *gf)
+{
+  gf_internal_t *h;
+  int no_default_flag = 0;
+
+  h = (gf_internal_t *) gf->scratch;
+  
+  /* Allen: set default primitive polynomial / irreducible polynomial if needed */
+
+  /* Omitting the leftmost 1 as in w=32 */
+
+  if (h->prim_poly == 0) {
+    if (h->mult_type == GF_MULT_COMPOSITE) {
+      h->prim_poly = gf_composite_get_default_poly(h->base_gf);
+      if (h->prim_poly == 0) return 0; /* This shouldn't happen */
+    } else {
+      h->prim_poly = 0x1b;
+    } 
+    if (no_default_flag == 1) { 
+      fprintf(stderr,"Code contains no default irreducible polynomial for given base field\n"); 
+      return 0; 
+    } 
+  }
+
+  gf->multiply.w64 = NULL;
+  gf->divide.w64 = NULL;
+  gf->inverse.w64 = NULL;
+  gf->multiply_region.w64 = NULL;
+
+  switch(h->mult_type) {
+    case GF_MULT_CARRY_FREE:  if (gf_w64_cfm_init(gf) == 0) return 0; break;
+    case GF_MULT_SHIFT:       if (gf_w64_shift_init(gf) == 0) return 0; break;
+    case GF_MULT_COMPOSITE:   if (gf_w64_composite_init(gf) == 0) return 0; break;
+    case GF_MULT_DEFAULT:
+    case GF_MULT_SPLIT_TABLE: if (gf_w64_split_init(gf) == 0) return 0; break; 
+    case GF_MULT_GROUP:       if (gf_w64_group_init(gf) == 0) return 0; break; 
+    case GF_MULT_BYTWO_p:
+    case GF_MULT_BYTWO_b:     if (gf_w64_bytwo_init(gf) == 0) return 0; break;
+    default: return 0;
+  }
+  if (h->divide_type == GF_DIVIDE_EUCLID) {
+    gf->divide.w64 = gf_w64_divide_from_inverse;
+    gf->inverse.w64 = gf_w64_euclid;
+  } 
+
+  if (gf->inverse.w64 != NULL && gf->divide.w64 == NULL) {
+    gf->divide.w64 = gf_w64_divide_from_inverse;
+  }
+  if (gf->inverse.w64 == NULL && gf->divide.w64 != NULL) {
+    gf->inverse.w64 = gf_w64_inverse_from_divide;
+  }
+
+  if (h->region_type == GF_REGION_CAUCHY) return 0;
+
+  if (h->region_type & GF_REGION_ALTMAP) {
+    if (h->mult_type == GF_MULT_COMPOSITE) {
+      gf->extract_word.w64 = gf_w64_composite_extract_word;
+    } else if (h->mult_type == GF_MULT_SPLIT_TABLE) {
+      gf->extract_word.w64 = gf_w64_split_extract_word;
+    }
+  } else {
+    gf->extract_word.w64 = gf_w64_extract_word;
+  }
+
+  return 1;
+}
diff --git a/src/erasure-code/jerasure/gf-complete/src/gf_w8.c b/src/erasure-code/jerasure/gf-complete/src/gf_w8.c
new file mode 100644
index 0000000..89ef6a2
--- /dev/null
+++ b/src/erasure-code/jerasure/gf-complete/src/gf_w8.c
@@ -0,0 +1,2456 @@
+/*
+ * GF-Complete: A Comprehensive Open Source Library for Galois Field Arithmetic
+ * James S. Plank, Ethan L. Miller, Kevin M. Greenan,
+ * Benjamin A. Arnold, John A. Burnum, Adam W. Disney, Allen C. McBride.
+ *
+ * gf_w8.c
+ *
+ * Routines for 8-bit Galois fields
+ */
+
+#include "gf_int.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+#define GF_FIELD_WIDTH (8)
+#define GF_FIELD_SIZE       (1 << GF_FIELD_WIDTH)
+#define GF_HALF_SIZE       (1 << (GF_FIELD_WIDTH/2))
+#define GF_MULT_GROUP_SIZE       GF_FIELD_SIZE-1
+
+#define GF_BASE_FIELD_WIDTH (4)
+#define GF_BASE_FIELD_SIZE       (1 << GF_BASE_FIELD_WIDTH)
+
+struct gf_w8_logtable_data {
+    uint8_t         log_tbl[GF_FIELD_SIZE];
+    uint8_t         antilog_tbl[GF_FIELD_SIZE * 2];
+    uint8_t         inv_tbl[GF_FIELD_SIZE];
+};
+
+struct gf_w8_logzero_table_data {
+    short           log_tbl[GF_FIELD_SIZE];  /* Make this signed, so that we can divide easily */
+    uint8_t         antilog_tbl[512+512+1];
+    uint8_t         *div_tbl;
+    uint8_t         *inv_tbl;
+};
+
+struct gf_w8_logzero_small_table_data {
+    short           log_tbl[GF_FIELD_SIZE];  /* Make this signed, so that we can divide easily */
+    uint8_t         antilog_tbl[255*3];
+    uint8_t         inv_tbl[GF_FIELD_SIZE];
+    uint8_t         *div_tbl;
+};
+
+struct gf_w8_composite_data {
+  uint8_t *mult_table;
+};
+
+/* Don't change the order of these relative to gf_w8_half_table_data */
+
+struct gf_w8_default_data {
+  uint8_t     high[GF_FIELD_SIZE][GF_HALF_SIZE];
+  uint8_t     low[GF_FIELD_SIZE][GF_HALF_SIZE];
+  uint8_t     divtable[GF_FIELD_SIZE][GF_FIELD_SIZE];
+  uint8_t     multtable[GF_FIELD_SIZE][GF_FIELD_SIZE];
+};
+
+struct gf_w8_half_table_data {
+  uint8_t     high[GF_FIELD_SIZE][GF_HALF_SIZE];
+  uint8_t     low[GF_FIELD_SIZE][GF_HALF_SIZE];
+};
+
+struct gf_w8_single_table_data {
+  uint8_t     divtable[GF_FIELD_SIZE][GF_FIELD_SIZE];
+  uint8_t     multtable[GF_FIELD_SIZE][GF_FIELD_SIZE];
+};
+
+struct gf_w8_double_table_data {
+    uint8_t         div[GF_FIELD_SIZE][GF_FIELD_SIZE];
+    uint16_t        mult[GF_FIELD_SIZE][GF_FIELD_SIZE*GF_FIELD_SIZE];
+};
+
+struct gf_w8_double_table_lazy_data {
+    uint8_t         div[GF_FIELD_SIZE][GF_FIELD_SIZE];
+    uint8_t         smult[GF_FIELD_SIZE][GF_FIELD_SIZE];
+    uint16_t        mult[GF_FIELD_SIZE*GF_FIELD_SIZE];
+};
+
+struct gf_w4_logtable_data {
+    uint8_t         log_tbl[GF_BASE_FIELD_SIZE];
+    uint8_t         antilog_tbl[GF_BASE_FIELD_SIZE * 2];
+    uint8_t         *antilog_tbl_div;
+};
+
+struct gf_w4_single_table_data {
+    uint8_t         div[GF_BASE_FIELD_SIZE][GF_BASE_FIELD_SIZE];
+    uint8_t         mult[GF_BASE_FIELD_SIZE][GF_BASE_FIELD_SIZE];
+};
+
+struct gf_w8_bytwo_data {
+    uint64_t prim_poly;
+    uint64_t mask1;
+    uint64_t mask2;
+};
+
+#define AB2(ip, am1 ,am2, b, t1, t2) {\
+  t1 = (b << 1) & am1;\
+  t2 = b & am2; \
+  t2 = ((t2 << 1) - (t2 >> (GF_FIELD_WIDTH-1))); \
+  b = (t1 ^ (t2 & ip));}
+
+#define SSE_AB2(pp, m1 ,m2, va, t1, t2) {\
+          t1 = _mm_and_si128(_mm_slli_epi64(va, 1), m1); \
+          t2 = _mm_and_si128(va, m2); \
+          t2 = _mm_sub_epi64 (_mm_slli_epi64(t2, 1), _mm_srli_epi64(t2, (GF_FIELD_WIDTH-1))); \
+          va = _mm_xor_si128(t1, _mm_and_si128(t2, pp)); }
+
+#define MM_PRINT(s, r) { uint8_t blah[16], ii; printf("%-12s", s); _mm_storeu_si128((__m128i *)blah, r); for (ii = 0; ii < 16; ii += 2) printf("  %02x %02x", blah[15-ii], blah[14-ii]); printf("\n"); }
+
+static
+inline
+uint32_t gf_w8_inverse_from_divide (gf_t *gf, uint32_t a)
+{
+  return gf->divide.w32(gf, 1, a);
+}
+
+static
+inline
+uint32_t gf_w8_divide_from_inverse (gf_t *gf, uint32_t a, uint32_t b)
+{
+  b = gf->inverse.w32(gf, b);
+  return gf->multiply.w32(gf, a, b);
+}
+
+static
+inline
+uint32_t gf_w8_euclid (gf_t *gf, uint32_t b)
+{
+  uint32_t e_i, e_im1, e_ip1;
+  uint32_t d_i, d_im1, d_ip1;
+  uint32_t y_i, y_im1, y_ip1;
+  uint32_t c_i;
+
+  if (b == 0) return -1;
+  e_im1 = ((gf_internal_t *) (gf->scratch))->prim_poly;
+  e_i = b;
+  d_im1 = 8;
+  for (d_i = d_im1; ((1 << d_i) & e_i) == 0; d_i--) ;
+  y_i = 1;
+  y_im1 = 0;
+
+  while (e_i != 1) {
+
+    e_ip1 = e_im1;
+    d_ip1 = d_im1;
+    c_i = 0;
+
+    while (d_ip1 >= d_i) {
+      c_i ^= (1 << (d_ip1 - d_i));
+      e_ip1 ^= (e_i << (d_ip1 - d_i));
+      if (e_ip1 == 0) return 0;
+      while ((e_ip1 & (1 << d_ip1)) == 0) d_ip1--;
+    }
+
+    y_ip1 = y_im1 ^ gf->multiply.w32(gf, c_i, y_i);
+    y_im1 = y_i;
+    y_i = y_ip1;
+
+    e_im1 = e_i;
+    d_im1 = d_i;
+    e_i = e_ip1;
+    d_i = d_ip1;
+  }
+
+  return y_i;
+}
+
+static
+gf_val_32_t gf_w8_extract_word(gf_t *gf, void *start, int bytes, int index)
+{
+  uint8_t *r8;
+
+  r8 = (uint8_t *) start;
+  return r8[index];
+}
+
+static
+gf_val_32_t gf_w8_composite_extract_word(gf_t *gf, void *start, int bytes, int index)
+{
+  int sub_size;
+  gf_internal_t *h;
+  uint8_t *r8, *top;
+  uint8_t a, b;
+  gf_region_data rd;
+
+  h = (gf_internal_t *) gf->scratch;
+  gf_set_region_data(&rd, gf, start, start, bytes, 0, 0, 32);
+  r8 = (uint8_t *) start;
+  if (r8 + index < (uint8_t *) rd.d_start) return r8[index];
+  if (r8 + index >= (uint8_t *) rd.d_top) return r8[index];
+  index -= (((uint8_t *) rd.d_start) - r8);
+  r8 = (uint8_t *) rd.d_start;
+  top = (uint8_t *) rd.d_top;
+  sub_size = (top-r8)/2;
+
+  a = h->base_gf->extract_word.w32(h->base_gf, r8, sub_size, index);
+  b = h->base_gf->extract_word.w32(h->base_gf, r8+sub_size, sub_size, index);
+  return (a | (b << 4));
+}
+
+static
+inline
+uint32_t gf_w8_matrix (gf_t *gf, uint32_t b)
+{
+  return gf_bitmatrix_inverse(b, 8, ((gf_internal_t *) (gf->scratch))->prim_poly);
+}
+
+
+static
+inline
+gf_val_32_t
+gf_w8_clm_multiply_2 (gf_t *gf, gf_val_32_t a8, gf_val_32_t b8)
+{
+  gf_val_32_t rv = 0;
+
+#if defined(INTEL_SSE4_PCLMUL)
+
+  __m128i         a, b;
+  __m128i         result;
+  __m128i         prim_poly;
+  __m128i         w;
+  gf_internal_t * h = gf->scratch;
+
+  a = _mm_insert_epi32 (_mm_setzero_si128(), a8, 0);
+  b = _mm_insert_epi32 (a, b8, 0);
+
+  prim_poly = _mm_set_epi32(0, 0, 0, (uint32_t)(h->prim_poly & 0x1ffULL));
+
+  /* Do the initial multiply */
+
+  result = _mm_clmulepi64_si128 (a, b, 0);
+
+  /* Ben: Do prim_poly reduction twice. We are guaranteed that we will only
+     have to do the reduction at most twice, because (w-2)/z == 2. Where
+     z is equal to the number of zeros after the leading 1
+
+     _mm_clmulepi64_si128 is the carryless multiply operation. Here
+     _mm_srli_si128 shifts the result to the right by 1 byte. This allows
+     us to multiply the prim_poly by the leading bits of the result. We
+     then xor the result of that operation back with the result.*/
+
+  w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 1), 0);
+  result = _mm_xor_si128 (result, w);
+  w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 1), 0);
+  result = _mm_xor_si128 (result, w);
+
+  /* Extracts 32 bit value from result. */
+  
+  rv = ((gf_val_32_t)_mm_extract_epi32(result, 0));
+
+#endif
+  return rv;
+}
+
+static
+inline
+gf_val_32_t
+gf_w8_clm_multiply_3 (gf_t *gf, gf_val_32_t a8, gf_val_32_t b8)
+{
+  gf_val_32_t rv = 0;
+
+#if defined(INTEL_SSE4_PCLMUL)
+
+  __m128i         a, b;
+  __m128i         result;
+  __m128i         prim_poly;
+  __m128i         w;
+  gf_internal_t * h = gf->scratch;
+
+  a = _mm_insert_epi32 (_mm_setzero_si128(), a8, 0);
+  b = _mm_insert_epi32 (a, b8, 0);
+
+  prim_poly = _mm_set_epi32(0, 0, 0, (uint32_t)(h->prim_poly & 0x1ffULL));
+
+  /* Do the initial multiply */
+  
+  result = _mm_clmulepi64_si128 (a, b, 0);
+
+  w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 1), 0);
+  result = _mm_xor_si128 (result, w);
+  w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 1), 0);
+  result = _mm_xor_si128 (result, w);
+  w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 1), 0);
+  result = _mm_xor_si128 (result, w);
+
+  /* Extracts 32 bit value from result. */
+  
+  rv = ((gf_val_32_t)_mm_extract_epi32(result, 0));
+
+#endif
+  return rv;
+}
+
+static
+inline
+gf_val_32_t
+gf_w8_clm_multiply_4 (gf_t *gf, gf_val_32_t a8, gf_val_32_t b8)
+{
+  gf_val_32_t rv = 0;
+
+#if defined(INTEL_SSE4_PCLMUL)
+
+  __m128i         a, b;
+  __m128i         result;
+  __m128i         prim_poly;
+  __m128i         w;
+  gf_internal_t * h = gf->scratch;
+
+  a = _mm_insert_epi32 (_mm_setzero_si128(), a8, 0);
+  b = _mm_insert_epi32 (a, b8, 0);
+
+  prim_poly = _mm_set_epi32(0, 0, 0, (uint32_t)(h->prim_poly & 0x1ffULL));
+
+  /* Do the initial multiply */
+  
+  result = _mm_clmulepi64_si128 (a, b, 0);
+
+  w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 1), 0);
+  result = _mm_xor_si128 (result, w);
+  w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 1), 0);
+  result = _mm_xor_si128 (result, w);
+  w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 1), 0);
+  result = _mm_xor_si128 (result, w);
+  w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 1), 0);
+  result = _mm_xor_si128 (result, w);
+
+  /* Extracts 32 bit value from result. */
+  rv = ((gf_val_32_t)_mm_extract_epi32(result, 0));
+
+#endif
+  return rv;
+}
+
+
+static
+void
+gf_w8_multiply_region_from_single(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int
+    xor)
+{
+  gf_region_data rd;
+  uint8_t *s8;
+  uint8_t *d8;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 1);
+  gf_do_initial_region_alignment(&rd);
+
+  s8 = (uint8_t *) rd.s_start;
+  d8 = (uint8_t *) rd.d_start;
+
+  if (xor) {
+    while (d8 < ((uint8_t *) rd.d_top)) {
+      *d8 ^= gf->multiply.w32(gf, val, *s8);
+      d8++;
+      s8++;
+    }
+  } else {
+    while (d8 < ((uint8_t *) rd.d_top)) {
+      *d8 = gf->multiply.w32(gf, val, *s8);
+      d8++;
+      s8++;
+    }
+  }
+  gf_do_final_region_alignment(&rd);
+}
+
+#if defined(INTEL_SSE4_PCLMUL)
+static
+void
+gf_w8_clm_multiply_region_from_single_2(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int
+    xor)
+{
+  gf_region_data rd;
+  uint8_t *s8;
+  uint8_t *d8;
+
+  __m128i         a, b;
+  __m128i         result;
+  __m128i         prim_poly;
+  __m128i         w;
+  gf_internal_t * h = gf->scratch;
+
+  prim_poly = _mm_set_epi32(0, 0, 0, (uint32_t)(h->prim_poly & 0x1ffULL));
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  a = _mm_insert_epi32 (_mm_setzero_si128(), val, 0);
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 1);
+  gf_do_initial_region_alignment(&rd);
+
+  s8 = (uint8_t *) rd.s_start;
+  d8 = (uint8_t *) rd.d_start;
+
+  if (xor) {
+    while (d8 < ((uint8_t *) rd.d_top)) {
+      b = _mm_insert_epi32 (a, (gf_val_32_t)(*s8), 0);
+      result = _mm_clmulepi64_si128 (a, b, 0);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 1), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 1), 0);
+      result = _mm_xor_si128 (result, w);
+      *d8 ^= ((gf_val_32_t)_mm_extract_epi32(result, 0));
+      d8++;
+      s8++;
+    }
+  } else {
+    while (d8 < ((uint8_t *) rd.d_top)) {
+      b = _mm_insert_epi32 (a, (gf_val_32_t)(*s8), 0);
+      result = _mm_clmulepi64_si128 (a, b, 0);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 1), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 1), 0);
+      result = _mm_xor_si128 (result, w);
+      *d8 = ((gf_val_32_t)_mm_extract_epi32(result, 0));
+      d8++;
+      s8++;
+    }
+  }
+  gf_do_final_region_alignment(&rd);
+}
+#endif
+
+#if defined(INTEL_SSE4_PCLMUL)
+static
+void
+gf_w8_clm_multiply_region_from_single_3(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int
+    xor)
+{
+  gf_region_data rd;
+  uint8_t *s8;
+  uint8_t *d8;
+
+  __m128i         a, b;
+  __m128i         result;
+  __m128i         prim_poly;
+  __m128i         w;
+  gf_internal_t * h = gf->scratch;
+
+  prim_poly = _mm_set_epi32(0, 0, 0, (uint32_t)(h->prim_poly & 0x1ffULL));
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  a = _mm_insert_epi32 (_mm_setzero_si128(), val, 0);
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 1);
+  gf_do_initial_region_alignment(&rd);
+
+  s8 = (uint8_t *) rd.s_start;
+  d8 = (uint8_t *) rd.d_start;
+
+  if (xor) {
+    while (d8 < ((uint8_t *) rd.d_top)) {
+      b = _mm_insert_epi32 (a, (gf_val_32_t)(*s8), 0);
+      result = _mm_clmulepi64_si128 (a, b, 0);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 1), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 1), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 1), 0);
+      result = _mm_xor_si128 (result, w);
+      *d8 ^= ((gf_val_32_t)_mm_extract_epi32(result, 0));
+      d8++;
+      s8++;
+    }
+  } else {
+    while (d8 < ((uint8_t *) rd.d_top)) {
+      b = _mm_insert_epi32 (a, (gf_val_32_t)(*s8), 0);
+      result = _mm_clmulepi64_si128 (a, b, 0);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 1), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 1), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 1), 0);
+      result = _mm_xor_si128 (result, w);
+      *d8 = ((gf_val_32_t)_mm_extract_epi32(result, 0));
+      d8++;
+      s8++;
+    }
+  }
+  gf_do_final_region_alignment(&rd);
+}
+#endif
+
+#if defined(INTEL_SSE4_PCLMUL)
+static
+void
+gf_w8_clm_multiply_region_from_single_4(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int
+    xor)
+{
+  gf_region_data rd;
+  uint8_t *s8;
+  uint8_t *d8;
+
+  __m128i         a, b;
+  __m128i         result;
+  __m128i         prim_poly;
+  __m128i         w;
+  gf_internal_t * h = gf->scratch;
+
+  prim_poly = _mm_set_epi32(0, 0, 0, (uint32_t)(h->prim_poly & 0x1ffULL));
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  a = _mm_insert_epi32 (_mm_setzero_si128(), val, 0);
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 1);
+  gf_do_initial_region_alignment(&rd);
+
+  s8 = (uint8_t *) rd.s_start;
+  d8 = (uint8_t *) rd.d_start;
+
+  if (xor) {
+    while (d8 < ((uint8_t *) rd.d_top)) {
+      b = _mm_insert_epi32 (a, (gf_val_32_t)(*s8), 0);
+      result = _mm_clmulepi64_si128 (a, b, 0);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 1), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 1), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 1), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 1), 0);
+      result = _mm_xor_si128 (result, w);
+      *d8 ^= ((gf_val_32_t)_mm_extract_epi32(result, 0));
+      d8++;
+      s8++;
+    }
+  } else {
+    while (d8 < ((uint8_t *) rd.d_top)) {
+      b = _mm_insert_epi32 (a, (gf_val_32_t)(*s8), 0);
+      result = _mm_clmulepi64_si128 (a, b, 0);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 1), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 1), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 1), 0);
+      result = _mm_xor_si128 (result, w);
+      w = _mm_clmulepi64_si128 (prim_poly, _mm_srli_si128 (result, 1), 0);
+      result = _mm_xor_si128 (result, w);
+      *d8 = ((gf_val_32_t)_mm_extract_epi32(result, 0));
+      d8++;
+      s8++;
+    }
+  }
+  gf_do_final_region_alignment(&rd);
+}
+#endif
+
+/* ------------------------------------------------------------
+IMPLEMENTATION: SHIFT:
+
+JSP: The world's dumbest multiplication algorithm.  I only
+include it for completeness.  It does have the feature that it requires no
+extra memory.  
+ */
+
+static
+inline
+  uint32_t
+gf_w8_shift_multiply (gf_t *gf, uint32_t a8, uint32_t b8)
+{
+  uint16_t product, i, pp, a, b;
+  gf_internal_t *h;
+
+  a = a8;
+  b = b8;
+  h = (gf_internal_t *) gf->scratch;
+  pp = h->prim_poly;
+
+  product = 0;
+
+  for (i = 0; i < GF_FIELD_WIDTH; i++) { 
+    if (a & (1 << i)) product ^= (b << i);
+  }
+  for (i = (GF_FIELD_WIDTH*2-2); i >= GF_FIELD_WIDTH; i--) {
+    if (product & (1 << i)) product ^= (pp << (i-GF_FIELD_WIDTH)); 
+  }
+  return product;
+}
+
+static 
+int gf_w8_cfm_init(gf_t *gf)
+{ 
+#if defined(INTEL_SSE4_PCLMUL)
+  gf_internal_t *h;
+
+  h = (gf_internal_t *) gf->scratch;
+
+    if ((0xe0 & h->prim_poly) == 0){
+      gf->multiply.w32 = gf_w8_clm_multiply_2;
+      gf->multiply_region.w32 = gf_w8_clm_multiply_region_from_single_2;
+    }else if ((0xc0 & h->prim_poly) == 0){
+      gf->multiply.w32 = gf_w8_clm_multiply_3;
+      gf->multiply_region.w32 = gf_w8_clm_multiply_region_from_single_3;
+    }else if ((0x80 & h->prim_poly) == 0){ 
+      gf->multiply.w32 = gf_w8_clm_multiply_4;
+      gf->multiply_region.w32 = gf_w8_clm_multiply_region_from_single_4;
+    }else{
+      return 0;
+    }
+  return 1;
+#endif
+
+  return 0;
+
+}
+
+static 
+int gf_w8_shift_init(gf_t *gf)
+{ 
+  gf->multiply.w32 = gf_w8_shift_multiply;  /* The others will be set automatically */
+  return 1;
+}
+
+/* ------------------------------------------------------------
+IMPLEMENTATION: LOG_TABLE:
+
+JSP: Kevin wrote this, and I'm converting it to my structure.
+*/
+
+static
+inline
+  uint32_t
+gf_w8_logzero_multiply (gf_t *gf, uint32_t a, uint32_t b)
+{
+  struct gf_w8_logzero_table_data *ltd;
+
+  ltd = (struct gf_w8_logzero_table_data *) ((gf_internal_t *) gf->scratch)->private;
+  return ltd->antilog_tbl[ltd->log_tbl[a] + ltd->log_tbl[b]];
+}
+
+static
+inline
+  uint32_t
+gf_w8_logzero_divide (gf_t *gf, uint32_t a, uint32_t b)
+{
+  struct gf_w8_logzero_table_data *ltd;
+
+  ltd = (struct gf_w8_logzero_table_data *) ((gf_internal_t *) gf->scratch)->private;
+  return ltd->div_tbl[ltd->log_tbl[a] - ltd->log_tbl[b]];
+}
+
+static
+inline
+  uint32_t
+gf_w8_logzero_small_multiply (gf_t *gf, uint32_t a, uint32_t b)
+{
+  struct gf_w8_logzero_small_table_data *std;
+
+  std = (struct gf_w8_logzero_small_table_data *) ((gf_internal_t *) gf->scratch)->private;
+  if (b == 0) return 0;
+  return std->antilog_tbl[std->log_tbl[a] + std->log_tbl[b]];
+}
+
+static
+inline
+  uint32_t
+gf_w8_logzero_small_divide (gf_t *gf, uint32_t a, uint32_t b)
+{
+  struct gf_w8_logzero_small_table_data *std;
+
+  std = (struct gf_w8_logzero_small_table_data *) ((gf_internal_t *) gf->scratch)->private;
+  return std->div_tbl[std->log_tbl[a] - std->log_tbl[b]];
+}
+
+static
+inline
+  uint32_t
+gf_w8_log_multiply (gf_t *gf, uint32_t a, uint32_t b)
+{
+  struct gf_w8_logtable_data *ltd;
+
+  ltd = (struct gf_w8_logtable_data *) ((gf_internal_t *) gf->scratch)->private;
+  return (a == 0 || b == 0) ? 0 : ltd->antilog_tbl[(unsigned)(ltd->log_tbl[a] + ltd->log_tbl[b])];
+}
+
+static
+inline
+  uint32_t
+gf_w8_log_divide (gf_t *gf, uint32_t a, uint32_t b)
+{
+  int log_sum = 0;
+  struct gf_w8_logtable_data *ltd;
+
+  if (a == 0 || b == 0) return 0;
+  ltd = (struct gf_w8_logtable_data *) ((gf_internal_t *) gf->scratch)->private;
+
+  log_sum = ltd->log_tbl[a] - ltd->log_tbl[b] + (GF_MULT_GROUP_SIZE);
+  return (ltd->antilog_tbl[log_sum]);
+}
+
+static
+  uint32_t
+gf_w8_log_inverse (gf_t *gf, uint32_t a)
+{
+  struct gf_w8_logtable_data *ltd;
+
+  ltd = (struct gf_w8_logtable_data *) ((gf_internal_t *) gf->scratch)->private;
+  return (ltd->inv_tbl[a]);
+}
+
+static
+  uint32_t
+gf_w8_logzero_inverse (gf_t *gf, uint32_t a)
+{
+  struct gf_w8_logzero_table_data *ltd;
+
+  ltd = (struct gf_w8_logzero_table_data *) ((gf_internal_t *) gf->scratch)->private;
+  return (ltd->inv_tbl[a]);
+}
+
+static
+  uint32_t
+gf_w8_logzero_small_inverse (gf_t *gf, uint32_t a)
+{
+  struct gf_w8_logzero_small_table_data *std;
+
+  std = (struct gf_w8_logzero_small_table_data *) ((gf_internal_t *) gf->scratch)->private;
+  return (std->inv_tbl[a]);
+}
+
+static
+  void
+gf_w8_log_multiply_region(gf_t *gf, void *src, void *dest, uint32_t val, int bytes, int xor)
+{
+  int i;
+  uint8_t lv;
+  uint8_t *s8, *d8;
+  struct gf_w8_logtable_data *ltd;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  ltd = (struct gf_w8_logtable_data *) ((gf_internal_t *) gf->scratch)->private;
+  s8 = (uint8_t *) src;
+  d8 = (uint8_t *) dest;
+
+  lv = ltd->log_tbl[val];
+
+  if (xor) {
+    for (i = 0; i < bytes; i++) {
+      d8[i] ^= (s8[i] == 0 ? 0 : ltd->antilog_tbl[lv + ltd->log_tbl[s8[i]]]);
+    }
+  } else {
+    for (i = 0; i < bytes; i++) {
+      d8[i] = (s8[i] == 0 ? 0 : ltd->antilog_tbl[lv + ltd->log_tbl[s8[i]]]);
+    }
+  }
+}
+
+static
+  void
+gf_w8_logzero_multiply_region(gf_t *gf, void *src, void *dest, uint32_t val, int bytes, int xor)
+{
+  int i;
+  uint8_t lv;
+  uint8_t *s8, *d8;
+  struct gf_w8_logzero_table_data *ltd;
+  struct gf_w8_logzero_small_table_data *std;
+  short *log;
+  uint8_t *alt;
+  gf_internal_t *h;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  h = (gf_internal_t *) gf->scratch;
+
+  if (h->arg1 == 1) {
+    std = (struct gf_w8_logzero_small_table_data *) h->private;
+    log = std->log_tbl;
+    alt = std->antilog_tbl;
+  } else {
+    ltd = (struct gf_w8_logzero_table_data *) h->private;
+    log = ltd->log_tbl;
+    alt = ltd->antilog_tbl;
+  }
+  s8 = (uint8_t *) src;
+  d8 = (uint8_t *) dest;
+
+  lv = log[val];
+
+  if (xor) {
+    for (i = 0; i < bytes; i++) {
+      d8[i] ^= (alt[lv + log[s8[i]]]);
+    }
+  } else {
+    for (i = 0; i < bytes; i++) {
+      d8[i] = (alt[lv + log[s8[i]]]);
+    }
+  }
+}
+
+  static
+int gf_w8_log_init(gf_t *gf)
+{
+  gf_internal_t *h;
+  struct gf_w8_logtable_data *ltd = NULL;
+  struct gf_w8_logzero_table_data *ztd = NULL;
+  struct gf_w8_logzero_small_table_data *std = NULL;
+  uint8_t *alt;
+  uint8_t *inv;
+  int i, b;
+  int check = 0;
+
+  h = (gf_internal_t *) gf->scratch;
+  if (h->mult_type == GF_MULT_LOG_TABLE) {
+    ltd = h->private;
+    alt = ltd->antilog_tbl;
+    inv = ltd->inv_tbl;
+  } else if (h->mult_type == GF_MULT_LOG_ZERO) {
+    std = h->private;
+    alt = std->antilog_tbl;
+    std->div_tbl = (alt + 255);
+    inv = std->inv_tbl;
+  } else {
+    ztd = h->private;
+    alt = ztd->antilog_tbl;
+    ztd->inv_tbl = (alt + 512 + 256);
+    ztd->div_tbl = (alt + 255);
+    inv = ztd->inv_tbl;
+  }
+
+  for (i = 0; i < GF_MULT_GROUP_SIZE+1; i++) {
+    if (h->mult_type == GF_MULT_LOG_TABLE)
+      ltd->log_tbl[i] = 0;
+    else if (h->mult_type == GF_MULT_LOG_ZERO)
+      std->log_tbl[i] = 0;
+    else
+      ztd->log_tbl[i] = 0;
+  }
+
+  if (h->mult_type == GF_MULT_LOG_TABLE) {
+    ltd->log_tbl[0] = 0;
+  } else if (h->mult_type == GF_MULT_LOG_ZERO) {
+    std->log_tbl[0] = 510;
+  } else {
+    ztd->log_tbl[0] = 512;
+  }
+
+  b = 1;
+  for (i = 0; i < GF_MULT_GROUP_SIZE; i++) {
+    if (h->mult_type == GF_MULT_LOG_TABLE) {
+      if (ltd->log_tbl[b] != 0) check = 1;
+      ltd->log_tbl[b] = i;
+    } else if (h->mult_type == GF_MULT_LOG_ZERO) {
+      if (std->log_tbl[b] != 0) check = 1;
+      std->log_tbl[b] = i;
+    } else {
+      if (ztd->log_tbl[b] != 0) check = 1;
+      ztd->log_tbl[b] = i;
+    }
+    alt[i] = b;
+    alt[i+GF_MULT_GROUP_SIZE] = b;
+    b <<= 1;
+    if (b & GF_FIELD_SIZE) {
+      b = b ^ h->prim_poly;
+    }
+  }
+  if (check) {
+    _gf_errno = GF_E_LOGPOLY;
+    return 0;
+  }
+
+  if (h->mult_type == GF_MULT_LOG_ZERO) bzero(alt+510, 255);
+
+  if (h->mult_type == GF_MULT_LOG_ZERO_EXT) {
+    bzero(alt+512, 255);
+    alt[512+512] = 0;
+  }
+
+  inv[0] = 0;  /* Not really, but we need to fill it with something  */
+  i = 1;
+  b = GF_MULT_GROUP_SIZE;
+  do {
+    inv[i] = alt[b];
+    i <<= 1;
+    if (i & (1 << 8)) i ^= h->prim_poly;
+    b--;
+  } while (i != 1);
+
+  if (h->mult_type == GF_MULT_LOG_TABLE) {
+    gf->inverse.w32 = gf_w8_log_inverse;
+    gf->divide.w32 = gf_w8_log_divide;
+    gf->multiply.w32 = gf_w8_log_multiply;
+    gf->multiply_region.w32 = gf_w8_log_multiply_region;
+  } else if (h->mult_type == GF_MULT_LOG_ZERO) {
+    gf->inverse.w32 = gf_w8_logzero_small_inverse;
+    gf->divide.w32 = gf_w8_logzero_small_divide;
+    gf->multiply.w32 = gf_w8_logzero_small_multiply;
+    gf->multiply_region.w32 = gf_w8_logzero_multiply_region;
+  } else {
+    gf->inverse.w32 = gf_w8_logzero_inverse;
+    gf->divide.w32 = gf_w8_logzero_divide;
+    gf->multiply.w32 = gf_w8_logzero_multiply;
+    gf->multiply_region.w32 = gf_w8_logzero_multiply_region;
+  }
+  return 1;
+}
+
+/* ------------------------------------------------------------
+IMPLEMENTATION: FULL_TABLE:
+
+JSP: Kevin wrote this, and I'm converting it to my structure.
+ */
+
+static
+  gf_val_32_t
+gf_w8_table_multiply(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  struct gf_w8_single_table_data *ftd;
+
+  ftd = (struct gf_w8_single_table_data *) ((gf_internal_t *) gf->scratch)->private;
+  return (ftd->multtable[a][b]);
+}
+
+static
+  gf_val_32_t
+gf_w8_table_divide(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  struct gf_w8_single_table_data *ftd;
+
+  ftd = (struct gf_w8_single_table_data *) ((gf_internal_t *) gf->scratch)->private;
+  return (ftd->divtable[a][b]);
+}
+
+static
+  gf_val_32_t
+gf_w8_default_multiply(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  struct gf_w8_default_data *ftd;
+
+  ftd = (struct gf_w8_default_data *) ((gf_internal_t *) gf->scratch)->private;
+  return (ftd->multtable[a][b]);
+}
+
+#ifdef INTEL_SSSE3
+static
+  gf_val_32_t
+gf_w8_default_divide(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  struct gf_w8_default_data *ftd;
+
+  ftd = (struct gf_w8_default_data *) ((gf_internal_t *) gf->scratch)->private;
+  return (ftd->divtable[a][b]);
+}
+#endif
+
+static
+  gf_val_32_t
+gf_w8_double_table_multiply(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  struct gf_w8_double_table_data *ftd;
+
+  ftd = (struct gf_w8_double_table_data *) ((gf_internal_t *) gf->scratch)->private;
+  return (ftd->mult[a][b]);
+}
+
+static
+  gf_val_32_t
+gf_w8_double_table_divide(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  struct gf_w8_double_table_data *ftd;
+
+  ftd = (struct gf_w8_double_table_data *) ((gf_internal_t *) gf->scratch)->private;
+  return (ftd->div[a][b]);
+}
+
+static
+  void
+gf_w8_double_table_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  uint16_t *base;
+  uint32_t b, c, vc, vb;
+  gf_internal_t *h;
+  struct gf_w8_double_table_data  *dtd;
+  struct gf_w8_double_table_lazy_data  *ltd;
+  gf_region_data rd;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  h = (gf_internal_t *) (gf->scratch);
+  if (h->region_type & GF_REGION_LAZY) {
+    ltd = (struct gf_w8_double_table_lazy_data *) h->private;
+    base = ltd->mult;
+    for (b = 0; b < GF_FIELD_SIZE; b++) {
+      vb = (ltd->smult[val][b] << 8);
+      for (c = 0; c < GF_FIELD_SIZE; c++) {
+        vc = ltd->smult[val][c];
+        base[(b << 8)| c] = (vb | vc);
+      }
+    }
+
+  } else {
+    dtd = (struct gf_w8_double_table_data *) h->private;
+    base = &(dtd->mult[val][0]);
+  }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 8);
+  gf_do_initial_region_alignment(&rd);
+  gf_two_byte_region_table_multiply(&rd, base);
+  gf_do_final_region_alignment(&rd);
+}
+
+static
+  gf_val_32_t
+gf_w8_double_table_lazy_multiply(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  struct gf_w8_double_table_lazy_data *ftd;
+
+  ftd = (struct gf_w8_double_table_lazy_data *) ((gf_internal_t *) gf->scratch)->private;
+  return (ftd->smult[a][b]);
+}
+
+static
+  gf_val_32_t
+gf_w8_double_table_lazy_divide(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  struct gf_w8_double_table_lazy_data *ftd;
+
+  ftd = (struct gf_w8_double_table_lazy_data *) ((gf_internal_t *) gf->scratch)->private;
+  return (ftd->div[a][b]);
+}
+
+static
+  void
+gf_w8_table_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  int i;
+  uint8_t *s8, *d8;
+  struct gf_w8_single_table_data *ftd;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  ftd = (struct gf_w8_single_table_data *) ((gf_internal_t *) gf->scratch)->private;
+  s8 = (uint8_t *) src;
+  d8 = (uint8_t *) dest;
+
+  if (xor) {
+    for (i = 0; i < bytes; i++) {
+      d8[i] ^= ftd->multtable[s8[i]][val];
+    }
+  } else {
+    for (i = 0; i < bytes; i++) {
+      d8[i] = ftd->multtable[s8[i]][val];
+    }
+  }
+}
+
+#ifdef INTEL_SSSE3
+static
+  void
+gf_w8_split_multiply_region_sse(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  uint8_t *bh, *bl, *sptr, *dptr;
+  __m128i  loset, t1, r, va, mth, mtl;
+  struct gf_w8_half_table_data *htd;
+  gf_region_data rd;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  htd = (struct gf_w8_half_table_data *) ((gf_internal_t *) (gf->scratch))->private;
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 16);
+  gf_do_initial_region_alignment(&rd);
+
+  bh = (uint8_t *) htd->high;
+  bh += (val << 4);
+  bl = (uint8_t *) htd->low;
+  bl += (val << 4);
+
+  sptr = rd.s_start;
+  dptr = rd.d_start;
+
+  mth = _mm_loadu_si128 ((__m128i *)(bh));
+  mtl = _mm_loadu_si128 ((__m128i *)(bl));
+  loset = _mm_set1_epi8 (0x0f);
+
+  if (xor) {
+    while (sptr < (uint8_t *) rd.s_top) {
+      va = _mm_load_si128 ((__m128i *)(sptr));
+      t1 = _mm_and_si128 (loset, va);
+      r = _mm_shuffle_epi8 (mtl, t1);
+      va = _mm_srli_epi64 (va, 4);
+      t1 = _mm_and_si128 (loset, va);
+      r = _mm_xor_si128 (r, _mm_shuffle_epi8 (mth, t1));
+      va = _mm_load_si128 ((__m128i *)(dptr));
+      r = _mm_xor_si128 (r, va);
+      _mm_store_si128 ((__m128i *)(dptr), r);
+      dptr += 16;
+      sptr += 16;
+    }
+  } else {
+    while (sptr < (uint8_t *) rd.s_top) {
+      va = _mm_load_si128 ((__m128i *)(sptr));
+      t1 = _mm_and_si128 (loset, va);
+      r = _mm_shuffle_epi8 (mtl, t1);
+      va = _mm_srli_epi64 (va, 4);
+      t1 = _mm_and_si128 (loset, va);
+      r = _mm_xor_si128 (r, _mm_shuffle_epi8 (mth, t1));
+      _mm_store_si128 ((__m128i *)(dptr), r);
+      dptr += 16;
+      sptr += 16;
+    }
+  }
+
+  gf_do_final_region_alignment(&rd);
+}
+#endif
+
+
+/* ------------------------------------------------------------
+IMPLEMENTATION: FULL_TABLE:
+ */
+
+static
+  gf_val_32_t
+gf_w8_split_multiply(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  struct gf_w8_half_table_data *htd;
+  htd = (struct gf_w8_half_table_data *) ((gf_internal_t *) gf->scratch)->private;
+
+  return htd->high[b][a>>4] ^ htd->low[b][a&0xf];
+}
+
+static
+  void
+gf_w8_split_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  int i;
+  uint8_t *s8, *d8;
+  struct gf_w8_half_table_data *htd;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  htd = (struct gf_w8_half_table_data *) ((gf_internal_t *) gf->scratch)->private;
+  s8 = (uint8_t *) src;
+  d8 = (uint8_t *) dest;
+
+  if (xor) {
+    for (i = 0; i < bytes; i++) {
+      d8[i] ^= (htd->high[val][s8[i]>>4] ^ htd->low[val][s8[i]&0xf]);
+    }
+  } else {
+    for (i = 0; i < bytes; i++) {
+      d8[i] = (htd->high[val][s8[i]>>4] ^ htd->low[val][s8[i]&0xf]);
+    }
+  }
+}
+
+
+  static
+int gf_w8_split_init(gf_t *gf)
+{
+  gf_internal_t *h;
+  struct gf_w8_half_table_data *htd;
+  int a, b;
+
+  h = (gf_internal_t *) gf->scratch;
+  htd = (struct gf_w8_half_table_data *)h->private;
+
+  bzero(htd->high, sizeof(uint8_t)*GF_FIELD_SIZE*GF_HALF_SIZE);
+  bzero(htd->low, sizeof(uint8_t)*GF_FIELD_SIZE*GF_HALF_SIZE);
+
+  for (a = 1; a < GF_FIELD_SIZE; a++) {
+    for (b = 1; b < GF_HALF_SIZE; b++) {
+      htd->low[a][b] = gf_w8_shift_multiply(gf,a,b);
+      htd->high[a][b] = gf_w8_shift_multiply(gf,a,b<<4);
+    }
+  }
+
+  gf->multiply.w32 = gf_w8_split_multiply;
+  
+  #ifdef INTEL_SSSE3
+    if (h->region_type & GF_REGION_NOSSE)
+      gf->multiply_region.w32 = gf_w8_split_multiply_region;
+    else
+      gf->multiply_region.w32 = gf_w8_split_multiply_region_sse;
+  #else
+    gf->multiply_region.w32 = gf_w8_split_multiply_region;
+    if(h->region_type & GF_REGION_SSE)
+      return 0;
+  #endif
+
+  return 1;
+}
+
+/* JSP: This is disgusting, but it is what it is.  If there is no SSE,
+   then the default is equivalent to single table.  If there is SSE, then
+   we use the "gf_w8_default_data" which is a hybrid of SPLIT & TABLE. */
+   
+static
+int gf_w8_table_init(gf_t *gf)
+{
+  gf_internal_t *h;
+  struct gf_w8_single_table_data *ftd = NULL;
+  struct gf_w8_double_table_data *dtd = NULL;
+  struct gf_w8_double_table_lazy_data *ltd = NULL;
+  struct gf_w8_default_data *dd = NULL;
+  int a, b, c, prod, scase, issse;
+
+  h = (gf_internal_t *) gf->scratch;
+
+  issse = 0;
+#ifdef INTEL_SSSE3
+  issse = 1;
+#endif
+
+  if (h->mult_type == GF_MULT_DEFAULT && issse) {
+    dd = (struct gf_w8_default_data *)h->private;
+    scase = 3;
+    bzero(dd->high, sizeof(uint8_t) * GF_FIELD_SIZE * GF_HALF_SIZE);
+    bzero(dd->low, sizeof(uint8_t) * GF_FIELD_SIZE * GF_HALF_SIZE);
+    bzero(dd->divtable, sizeof(uint8_t) * GF_FIELD_SIZE * GF_FIELD_SIZE);
+    bzero(dd->multtable, sizeof(uint8_t) * GF_FIELD_SIZE * GF_FIELD_SIZE);
+  } else if (h->mult_type == GF_MULT_DEFAULT || 
+             h->region_type == 0 || (h->region_type & GF_REGION_CAUCHY)) {
+    ftd = (struct gf_w8_single_table_data *)h->private;
+    bzero(ftd->divtable, sizeof(uint8_t) * GF_FIELD_SIZE * GF_FIELD_SIZE);
+    bzero(ftd->multtable, sizeof(uint8_t) * GF_FIELD_SIZE * GF_FIELD_SIZE);
+    scase = 0;
+  } else if (h->region_type == GF_REGION_DOUBLE_TABLE) {
+    dtd = (struct gf_w8_double_table_data *)h->private;
+    bzero(dtd->div, sizeof(uint8_t) * GF_FIELD_SIZE * GF_FIELD_SIZE);
+    bzero(dtd->mult, sizeof(uint16_t) * GF_FIELD_SIZE * GF_FIELD_SIZE * GF_FIELD_SIZE);
+    scase = 1;
+  } else if (h->region_type == (GF_REGION_DOUBLE_TABLE | GF_REGION_LAZY)) {
+    ltd = (struct gf_w8_double_table_lazy_data *)h->private;
+    bzero(ltd->div, sizeof(uint8_t) * GF_FIELD_SIZE * GF_FIELD_SIZE);
+    bzero(ltd->smult, sizeof(uint8_t) * GF_FIELD_SIZE * GF_FIELD_SIZE);
+    scase = 2;
+  } else {
+    fprintf(stderr, "Internal error in gf_w8_table_init\n");
+    exit(0);
+  }
+
+  for (a = 1; a < GF_FIELD_SIZE; a++) {
+    for (b = 1; b < GF_FIELD_SIZE; b++) {
+      prod = gf_w8_shift_multiply(gf,a,b);
+      switch (scase) {
+        case 0: 
+          ftd->multtable[a][b] = prod;
+          ftd->divtable[prod][b] = a;
+          break;
+        case 1:
+          dtd->div[prod][b] = a;
+          for (c = 0; c < GF_FIELD_SIZE; c++) {
+            dtd->mult[a][(c<<8)|b] |= prod;
+            dtd->mult[a][(b<<8)|c] |= (prod<<8);
+          }
+          break;
+        case 2:
+          ltd->div[prod][b] = a;
+          ltd->smult[a][b] = prod;
+          break;
+        case 3:
+          dd->multtable[a][b] = prod;
+          dd->divtable[prod][b] = a;
+          if ((b & 0xf) == b) { dd->low[a][b] = prod; }
+          if ((b & 0xf0) == b) { dd->high[a][b>>4] = prod; }
+          break;
+      }
+    }
+  }
+
+  gf->inverse.w32 = NULL; /* Will set from divide */
+  switch (scase) {
+    case 0: 
+      gf->divide.w32 = gf_w8_table_divide;
+      gf->multiply.w32 = gf_w8_table_multiply;
+      gf->multiply_region.w32 = gf_w8_table_multiply_region;
+      break;
+    case 1:
+      gf->divide.w32 = gf_w8_double_table_divide;
+      gf->multiply.w32 = gf_w8_double_table_multiply;
+      gf->multiply_region.w32 = gf_w8_double_table_multiply_region;
+      break;
+    case 2:
+      gf->divide.w32 = gf_w8_double_table_lazy_divide;
+      gf->multiply.w32 = gf_w8_double_table_lazy_multiply;
+      gf->multiply_region.w32 = gf_w8_double_table_multiply_region;
+      break;
+    case 3:
+#ifdef INTEL_SSSE3
+      gf->divide.w32 = gf_w8_default_divide;
+      gf->multiply.w32 = gf_w8_default_multiply;
+      gf->multiply_region.w32 = gf_w8_split_multiply_region_sse;
+#endif
+      break;
+  }
+  return 1;
+}
+
+static
+  void
+gf_w8_composite_multiply_region_alt(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  gf_t *base_gf = h->base_gf;
+  uint8_t val0 = val & 0x0f;
+  uint8_t val1 = (val & 0xf0) >> 4;
+  gf_region_data rd;
+  int sub_reg_size;
+
+  if (val == 0) {
+    if (xor) return;
+    bzero(dest, bytes);
+    return;
+  }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 32);
+  gf_do_initial_region_alignment(&rd);
+
+  sub_reg_size = ((char*)rd.d_top - (char*)rd.d_start) / 2;
+
+  base_gf->multiply_region.w32(base_gf, rd.s_start, rd.d_start, val0, sub_reg_size, xor);
+  base_gf->multiply_region.w32(base_gf, (char*)rd.s_start+sub_reg_size, rd.d_start, val1, sub_reg_size, 1);
+  base_gf->multiply_region.w32(base_gf, rd.s_start, (char*)rd.d_start+sub_reg_size, val1, sub_reg_size, xor);
+  base_gf->multiply_region.w32(base_gf, (char*)rd.s_start+sub_reg_size, (char*)rd.d_start+sub_reg_size, val0, sub_reg_size, 1);
+  base_gf->multiply_region.w32(base_gf, (char*)rd.s_start+sub_reg_size, (char*)rd.d_start+sub_reg_size, base_gf->multiply.w32(base_gf, h->prim_poly, val1), sub_reg_size, 1);
+
+   gf_do_final_region_alignment(&rd);
+}
+
+static
+gf_val_32_t
+gf_w8_composite_multiply_recursive(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  gf_t *base_gf = h->base_gf;
+  uint8_t b0 = b & 0x0f; 
+  uint8_t b1 = (b & 0xf0) >> 4; 
+  uint8_t a0 = a & 0x0f; 
+  uint8_t a1 = (a & 0xf0) >> 4; 
+  uint8_t a1b1;
+
+  a1b1 = base_gf->multiply.w32(base_gf, a1, b1);
+
+  return ((base_gf->multiply.w32(base_gf, a0, b0) ^ a1b1) | 
+          ((base_gf->multiply.w32(base_gf, a1, b0) ^ 
+           base_gf->multiply.w32(base_gf, a0, b1) ^ 
+           base_gf->multiply.w32(base_gf, a1b1, h->prim_poly)) << 4));
+}
+
+static
+gf_val_32_t
+gf_w8_composite_multiply_inline(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  uint8_t b0 = b & 0x0f; 
+  uint8_t b1 = (b & 0xf0) >> 4; 
+  uint8_t a0 = a & 0x0f; 
+  uint8_t a1 = (a & 0xf0) >> 4; 
+  uint8_t a1b1, *mt;
+  struct gf_w8_composite_data *cd;
+
+  cd = (struct gf_w8_composite_data *) h->private;
+  mt = cd->mult_table;
+
+  a1b1 = GF_W4_INLINE_MULTDIV(mt, a1, b1);
+
+  return ((GF_W4_INLINE_MULTDIV(mt, a0, b0) ^ a1b1) | 
+          ((GF_W4_INLINE_MULTDIV(mt, a1, b0) ^ 
+           GF_W4_INLINE_MULTDIV(mt, a0, b1) ^ 
+           GF_W4_INLINE_MULTDIV(mt, a1b1, h->prim_poly)) << 4));
+}
+
+/*
+ * Composite field division trick (explained in 2007 tech report) 
+ *
+ * Compute a / b = a*b^-1, where p(x) = x^2 + sx + 1 
+ * 
+ * let c = b^-1
+ *
+ * c*b = (s*b1c1+b1c0+b0c1)x+(b1c1+b0c0)
+ * 
+ * want (s*b1c1+b1c0+b0c1) = 0 and (b1c1+b0c0) = 1 
+ *
+ * let d = b1c1 and d+1 = b0c0
+ *
+ * solve s*b1c1+b1c0+b0c1 = 0
+ *
+ * solution: d = (b1b0^-1)(b1b0^-1+b0b1^-1+s)^-1
+ *
+ * c0 = (d+1)b0^-1
+ * c1 = d*b1^-1
+ * 
+ * a / b = a * c
+ */
+
+static
+gf_val_32_t
+gf_w8_composite_inverse(gf_t *gf, gf_val_32_t a)
+{
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  gf_t *base_gf = h->base_gf;
+  uint8_t a0 = a & 0x0f; 
+  uint8_t a1 = (a & 0xf0) >> 4; 
+  uint8_t c0, c1, c, d, tmp;
+  uint8_t a0inv, a1inv; 
+
+  if (a0 == 0) {
+    a1inv = base_gf->inverse.w32(base_gf, a1) & 0xf;
+    c0 = base_gf->multiply.w32(base_gf, a1inv, h->prim_poly);
+    c1 = a1inv;
+  } else if (a1 == 0) {
+    c0 = base_gf->inverse.w32(base_gf, a0);
+    c1 = 0;
+  } else {
+    a1inv = base_gf->inverse.w32(base_gf, a1) & 0xf;
+    a0inv = base_gf->inverse.w32(base_gf, a0) & 0xf;
+
+    d = base_gf->multiply.w32(base_gf, a1, a0inv) & 0xf;
+
+    tmp = (base_gf->multiply.w32(base_gf, a1, a0inv) ^ base_gf->multiply.w32(base_gf, a0, a1inv) ^ h->prim_poly) & 0xf;
+    tmp = base_gf->inverse.w32(base_gf, tmp) & 0xf;
+
+    d = base_gf->multiply.w32(base_gf, d, tmp) & 0xf;
+
+    c0 = base_gf->multiply.w32(base_gf, (d^1), a0inv) & 0xf; 
+    c1 = base_gf->multiply.w32(base_gf, d, a1inv) & 0xf; 
+  }
+
+  c = c0 | (c1 << 4);
+
+  return c;
+}
+
+static
+void
+gf_w8_composite_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  gf_region_data rd;
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  gf_t *base_gf = h->base_gf;
+  uint8_t b0 = val & 0x0f; 
+  uint8_t b1 = (val & 0xf0) >> 4; 
+  uint8_t *s8;
+  uint8_t *d8; 
+  uint8_t *mt;
+  uint8_t a0, a1, a1b1;
+  struct gf_w8_composite_data *cd;
+
+  cd = (struct gf_w8_composite_data *) h->private;
+
+  if (val == 0) {
+    if (xor) return;
+    bzero(dest, bytes);
+    return;
+  }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 1);
+  gf_do_initial_region_alignment(&rd);
+  
+  
+  s8 = (uint8_t *) rd.s_start;
+  d8 = (uint8_t *) rd.d_start;
+
+  mt = cd->mult_table;
+  if (mt == NULL) {
+    if (xor) {
+      while (d8 < (uint8_t *) rd.d_top) {
+        a0 = *s8 & 0x0f; 
+        a1 = (*s8 & 0xf0) >> 4; 
+        a1b1 = base_gf->multiply.w32(base_gf, a1, b1);
+  
+        *d8 ^= ((base_gf->multiply.w32(base_gf, a0, b0) ^ a1b1) | 
+               ((base_gf->multiply.w32(base_gf, a1, b0) ^ 
+                 base_gf->multiply.w32(base_gf, a0, b1) ^ 
+                 base_gf->multiply.w32(base_gf, a1b1, h->prim_poly)) << 4));
+        s8++;
+        d8++;
+      }
+    } else {
+      while (d8 < (uint8_t *) rd.d_top) {
+        a0 = *s8 & 0x0f; 
+        a1 = (*s8 & 0xf0) >> 4; 
+        a1b1 = base_gf->multiply.w32(base_gf, a1, b1);
+  
+        *d8 = ((base_gf->multiply.w32(base_gf, a0, b0) ^ a1b1) | 
+              ((base_gf->multiply.w32(base_gf, a1, b0) ^ 
+                base_gf->multiply.w32(base_gf, a0, b1) ^ 
+                base_gf->multiply.w32(base_gf, a1b1, h->prim_poly)) << 4));
+        s8++;
+        d8++;
+      }
+    }
+  } else {
+    if (xor) {
+      while (d8 < (uint8_t *) rd.d_top) {
+        a0 = *s8 & 0x0f; 
+        a1 = (*s8 & 0xf0) >> 4; 
+        a1b1 = GF_W4_INLINE_MULTDIV(mt, a1, b1);
+  
+        *d8 ^= ((GF_W4_INLINE_MULTDIV(mt, a0, b0) ^ a1b1) | 
+               ((GF_W4_INLINE_MULTDIV(mt, a1, b0) ^ 
+                 GF_W4_INLINE_MULTDIV(mt, a0, b1) ^ 
+                 GF_W4_INLINE_MULTDIV(mt, a1b1, h->prim_poly)) << 4));
+        s8++;
+        d8++;
+      }
+    } else {
+      while (d8 < (uint8_t *) rd.d_top) {
+        a0 = *s8 & 0x0f; 
+        a1 = (*s8 & 0xf0) >> 4; 
+        a1b1 = GF_W4_INLINE_MULTDIV(mt, a1, b1);
+  
+        *d8 = ((GF_W4_INLINE_MULTDIV(mt, a0, b0) ^ a1b1) | 
+              ((GF_W4_INLINE_MULTDIV(mt, a1, b0) ^ 
+                GF_W4_INLINE_MULTDIV(mt, a0, b1) ^ 
+                GF_W4_INLINE_MULTDIV(mt, a1b1, h->prim_poly)) << 4));
+        s8++;
+        d8++;
+      }
+    }
+  }
+  gf_do_final_region_alignment(&rd);
+  return;
+}
+
+static
+int gf_w8_composite_init(gf_t *gf)
+{
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  struct gf_w8_composite_data *cd;
+
+  if (h->base_gf == NULL) return 0;
+
+  cd = (struct gf_w8_composite_data *) h->private;
+  cd->mult_table = gf_w4_get_mult_table(h->base_gf);
+
+  if (h->region_type & GF_REGION_ALTMAP) {
+    gf->multiply_region.w32 = gf_w8_composite_multiply_region_alt;
+  } else {
+    gf->multiply_region.w32 = gf_w8_composite_multiply_region;
+  }
+
+  if (cd->mult_table == NULL) {
+    gf->multiply.w32 = gf_w8_composite_multiply_recursive;
+  } else {
+    gf->multiply.w32 = gf_w8_composite_multiply_inline;
+  }
+  gf->divide.w32 = NULL;
+  gf->inverse.w32 = gf_w8_composite_inverse;
+
+  return 1;
+}
+
+static
+inline
+  gf_val_32_t
+gf_w8_bytwo_p_multiply (gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  uint32_t prod, pp, pmask, amask;
+  gf_internal_t *h;
+
+  h = (gf_internal_t *) gf->scratch;
+  pp = h->prim_poly;
+
+
+  prod = 0;
+  pmask = 0x80;
+  amask = 0x80;
+
+  while (amask != 0) {
+    if (prod & pmask) {
+      prod = ((prod << 1) ^ pp);
+    } else {
+      prod <<= 1;
+    }
+    if (a & amask) prod ^= b;
+    amask >>= 1;
+  }
+  return prod;
+}
+
+static
+inline
+  gf_val_32_t
+gf_w8_bytwo_b_multiply (gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  uint32_t prod, pp, bmask;
+  gf_internal_t *h;
+
+  h = (gf_internal_t *) gf->scratch;
+  pp = h->prim_poly;
+
+  prod = 0;
+  bmask = 0x80;
+
+  while (1) {
+    if (a & 1) prod ^= b;
+    a >>= 1;
+    if (a == 0) return prod;
+    if (b & bmask) {
+      b = ((b << 1) ^ pp);
+    } else {
+      b <<= 1;
+    }
+  }
+}
+
+static
+  void 
+gf_w8_bytwo_p_nosse_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  uint64_t *s64, *d64, t1, t2, ta, prod, amask;
+  gf_region_data rd;
+  struct gf_w8_bytwo_data *btd;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  btd = (struct gf_w8_bytwo_data *) ((gf_internal_t *) (gf->scratch))->private;
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 8);
+  gf_do_initial_region_alignment(&rd);
+
+  s64 = (uint64_t *) rd.s_start;
+  d64 = (uint64_t *) rd.d_start;
+
+  if (xor) {
+    while (s64 < (uint64_t *) rd.s_top) {
+      prod = 0;
+      amask = 0x80;
+      ta = *s64;
+      while (amask != 0) {
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, prod, t1, t2);
+        if (val & amask) prod ^= ta;
+        amask >>= 1;
+      }
+      *d64 ^= prod;
+      d64++;
+      s64++;
+    }
+  } else { 
+    while (s64 < (uint64_t *) rd.s_top) {
+      prod = 0;
+      amask = 0x80;
+      ta = *s64;
+      while (amask != 0) {
+        AB2(btd->prim_poly, btd->mask1, btd->mask2, prod, t1, t2);
+        if (val & amask) prod ^= ta;
+        amask >>= 1;
+      }
+      *d64 = prod;
+      d64++;
+      s64++;
+    }
+  }
+  gf_do_final_region_alignment(&rd);
+}
+
+#define BYTWO_P_ONESTEP {\
+  SSE_AB2(pp, m1 ,m2, prod, t1, t2); \
+  t1 = _mm_and_si128(v, one); \
+  t1 = _mm_sub_epi8(t1, one); \
+  t1 = _mm_and_si128(t1, ta); \
+  prod = _mm_xor_si128(prod, t1); \
+  v = _mm_srli_epi64(v, 1); }
+
+#ifdef INTEL_SSE2
+static
+  void 
+gf_w8_bytwo_p_sse_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  int i;
+  uint8_t *s8, *d8;
+  uint8_t vrev;
+  __m128i pp, m1, m2, ta, prod, t1, t2, tp, one, v;
+  struct gf_w8_bytwo_data *btd;
+  gf_region_data rd;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  btd = (struct gf_w8_bytwo_data *) ((gf_internal_t *) (gf->scratch))->private;
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 16);
+  gf_do_initial_region_alignment(&rd);
+
+  vrev = 0;
+  for (i = 0; i < 8; i++) {
+    vrev <<= 1;
+    if (!(val & (1 << i))) vrev |= 1;
+  }
+
+  s8 = (uint8_t *) rd.s_start;
+  d8 = (uint8_t *) rd.d_start;
+
+  pp = _mm_set1_epi8(btd->prim_poly&0xff);
+  m1 = _mm_set1_epi8((btd->mask1)&0xff);
+  m2 = _mm_set1_epi8((btd->mask2)&0xff);
+  one = _mm_set1_epi8(1);
+
+  while (d8 < (uint8_t *) rd.d_top) {
+    prod = _mm_setzero_si128();
+    v = _mm_set1_epi8(vrev);
+    ta = _mm_load_si128((__m128i *) s8);
+    tp = (!xor) ? _mm_setzero_si128() : _mm_load_si128((__m128i *) d8);
+    BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP;
+    BYTWO_P_ONESTEP;
+    _mm_store_si128((__m128i *) d8, _mm_xor_si128(prod, tp));
+    d8 += 16;
+    s8 += 16;
+  }
+  gf_do_final_region_alignment(&rd);
+}
+#endif
+
+#ifdef INTEL_SSE2
+static
+  void
+gf_w8_bytwo_b_sse_region_2_noxor(gf_region_data *rd, struct gf_w8_bytwo_data *btd)
+{
+  uint8_t *d8, *s8;
+  __m128i pp, m1, m2, t1, t2, va;
+
+  s8 = (uint8_t *) rd->s_start;
+  d8 = (uint8_t *) rd->d_start;
+
+  pp = _mm_set1_epi8(btd->prim_poly&0xff);
+  m1 = _mm_set1_epi8((btd->mask1)&0xff);
+  m2 = _mm_set1_epi8((btd->mask2)&0xff);
+
+  while (d8 < (uint8_t *) rd->d_top) {
+    va = _mm_load_si128 ((__m128i *)(s8));
+    SSE_AB2(pp, m1, m2, va, t1, t2);
+    _mm_store_si128((__m128i *)d8, va);
+    d8 += 16;
+    s8 += 16;
+  }
+}
+#endif
+
+#ifdef INTEL_SSE2
+static
+  void
+gf_w8_bytwo_b_sse_region_2_xor(gf_region_data *rd, struct gf_w8_bytwo_data *btd)
+{
+  uint8_t *d8, *s8;
+  __m128i pp, m1, m2, t1, t2, va, vb;
+
+  s8 = (uint8_t *) rd->s_start;
+  d8 = (uint8_t *) rd->d_start;
+
+  pp = _mm_set1_epi8(btd->prim_poly&0xff);
+  m1 = _mm_set1_epi8((btd->mask1)&0xff);
+  m2 = _mm_set1_epi8((btd->mask2)&0xff);
+
+  while (d8 < (uint8_t *) rd->d_top) {
+    va = _mm_load_si128 ((__m128i *)(s8));
+    SSE_AB2(pp, m1, m2, va, t1, t2);
+    vb = _mm_load_si128 ((__m128i *)(d8));
+    vb = _mm_xor_si128(vb, va);
+    _mm_store_si128((__m128i *)d8, vb);
+    d8 += 16;
+    s8 += 16;
+  }
+}
+#endif
+
+
+#ifdef INTEL_SSE2
+static
+  void 
+gf_w8_bytwo_b_sse_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  int itb;
+  uint8_t *d8, *s8;
+  __m128i pp, m1, m2, t1, t2, va, vb;
+  struct gf_w8_bytwo_data *btd;
+  gf_region_data rd;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 16);
+  gf_do_initial_region_alignment(&rd);
+
+  btd = (struct gf_w8_bytwo_data *) ((gf_internal_t *) (gf->scratch))->private;
+
+  if (val == 2) {
+    if (xor) {
+      gf_w8_bytwo_b_sse_region_2_xor(&rd, btd);
+    } else {
+      gf_w8_bytwo_b_sse_region_2_noxor(&rd, btd);
+    }
+    gf_do_final_region_alignment(&rd);
+    return;
+  }
+
+  s8 = (uint8_t *) rd.s_start;
+  d8 = (uint8_t *) rd.d_start;
+
+  pp = _mm_set1_epi8(btd->prim_poly&0xff);
+  m1 = _mm_set1_epi8((btd->mask1)&0xff);
+  m2 = _mm_set1_epi8((btd->mask2)&0xff);
+
+  while (d8 < (uint8_t *) rd.d_top) {
+    va = _mm_load_si128 ((__m128i *)(s8));
+    vb = (!xor) ? _mm_setzero_si128() : _mm_load_si128 ((__m128i *)(d8));
+    itb = val;
+    while (1) {
+      if (itb & 1) vb = _mm_xor_si128(vb, va);
+      itb >>= 1;
+      if (itb == 0) break;
+      SSE_AB2(pp, m1, m2, va, t1, t2);
+    }
+    _mm_store_si128((__m128i *)d8, vb);
+    d8 += 16;
+    s8 += 16;
+  }
+
+  gf_do_final_region_alignment(&rd);
+}
+#endif
+
+static
+  void 
+gf_w8_bytwo_b_nosse_multiply_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  uint64_t *s64, *d64, t1, t2, ta, tb, prod;
+  struct gf_w8_bytwo_data *btd;
+  gf_region_data rd;
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, 16);
+  gf_do_initial_region_alignment(&rd);
+
+  btd = (struct gf_w8_bytwo_data *) ((gf_internal_t *) (gf->scratch))->private;
+  s64 = (uint64_t *) rd.s_start;
+  d64 = (uint64_t *) rd.d_start;
+
+  switch (val) {
+    case 2:
+      if (xor) {
+        while (d64 < (uint64_t *) rd.d_top) {
+          ta = *s64;
+          AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+          *d64 ^= ta;
+          d64++;
+          s64++;
+        }
+      } else {
+        while (d64 < (uint64_t *) rd.d_top) {
+          ta = *s64;
+          AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+          *d64 = ta;
+          d64++;
+          s64++;
+        }
+      }
+      break; 
+    case 3:
+      if (xor) {
+        while (d64 < (uint64_t *) rd.d_top) {
+          ta = *s64;
+          prod = ta;
+          AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+          *d64 ^= (ta ^ prod);
+          d64++;
+          s64++;
+        }
+      } else {
+        while (d64 < (uint64_t *) rd.d_top) {
+          ta = *s64;
+          prod = ta;
+          AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+          *d64 = (ta ^ prod);
+          d64++;
+          s64++;
+        }
+      }
+      break; 
+    case 4:
+      if (xor) {
+        while (d64 < (uint64_t *) rd.d_top) {
+          ta = *s64;
+          AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+          AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+          *d64 ^= ta;
+          d64++;
+          s64++;
+        }
+      } else {
+        while (d64 < (uint64_t *) rd.d_top) {
+          ta = *s64;
+          AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+          AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+          *d64 = ta;
+          d64++;
+          s64++;
+        }
+      }
+      break; 
+    case 5:
+      if (xor) {
+        while (d64 < (uint64_t *) rd.d_top) {
+          ta = *s64;
+          prod = ta;
+          AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+          AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+          *d64 ^= (ta ^ prod);
+          d64++;
+          s64++;
+        }
+      } else {
+        while (d64 < (uint64_t *) rd.d_top) {
+          ta = *s64;
+          prod = ta;
+          AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+          AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+          *d64 = ta ^ prod;
+          d64++;
+          s64++;
+        }
+      }
+    case 6:
+      if (xor) {
+        while (d64 < (uint64_t *) rd.d_top) {
+          ta = *s64;
+          AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+          prod = ta;
+          AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+          *d64 ^= (ta ^ prod);
+          d64++;
+          s64++;
+        }
+      } else {
+        while (d64 < (uint64_t *) rd.d_top) {
+          ta = *s64;
+          AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+          prod = ta;
+          AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+          *d64 = ta ^ prod;
+          d64++;
+          s64++;
+        }
+      }
+      /*
+         case 7:
+         if (xor) {
+         while (d64 < (uint64_t *) rd.d_top) {
+         ta = *s64;
+         prod = ta;
+         AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+         prod ^= ta;
+         AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+       *d64 ^= (ta ^ prod);
+       d64++;
+       s64++;
+       }
+       } else {
+       while (d64 < (uint64_t *) rd.d_top) {
+       ta = *s64;
+       prod = ta;
+       AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+       prod ^= ta;
+       AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+       *d64 = ta ^ prod;
+       d64++;
+       s64++;
+       }
+       }
+       break; 
+       */
+    case 8:
+      if (xor) {
+        while (d64 < (uint64_t *) rd.d_top) {
+          ta = *s64;
+          AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+          AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+          AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+          *d64 ^= ta;
+          d64++;
+          s64++;
+        }
+      } else {
+        while (d64 < (uint64_t *) rd.d_top) {
+          ta = *s64;
+          AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+          AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+          AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+          *d64 = ta;
+          d64++;
+          s64++;
+        }
+      }
+      break; 
+      /*
+         case 9:
+         if (xor) {
+         while (d64 < (uint64_t *) rd.d_top) {
+         ta = *s64;
+         prod = ta;
+         AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+         AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+         AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+       *d64 ^= (ta ^ prod);
+       d64++;
+       s64++;
+       }
+       } else {
+       while (d64 < (uint64_t *) rd.d_top) {
+       ta = *s64;
+       prod = ta;
+       AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+       AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+       AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+       *d64 = (ta ^ prod);
+       d64++;
+       s64++;
+       }
+       }
+       break; 
+       case 10:
+       if (xor) {
+       while (d64 < (uint64_t *) rd.d_top) {
+       ta = *s64;
+       AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+       prod = ta;
+       AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+       AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+       *d64 ^= (ta ^ prod);
+       d64++;
+       s64++;
+       }
+       } else {
+       while (d64 < (uint64_t *) rd.d_top) {
+       ta = *s64;
+       AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+       prod = ta;
+       AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+       AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+       *d64 = (ta ^ prod);
+       d64++;
+       s64++;
+       }
+       }
+       break; 
+       case 11:
+       if (xor) {
+       while (d64 < (uint64_t *) rd.d_top) {
+       ta = *s64;
+       prod = ta;
+       AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+       prod ^= ta;
+       AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+       AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+       *d64 ^= (ta ^ prod);
+       d64++;
+       s64++;
+       }
+       } else {
+       while (d64 < (uint64_t *) rd.d_top) {
+       ta = *s64;
+       prod = ta;
+       AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+       prod ^= ta;
+       AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+      AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+      *d64 = (ta ^ prod);
+      d64++;
+      s64++;
+      }
+  }
+  break; 
+    case 12:
+  if (xor) {
+    while (d64 < (uint64_t *) rd.d_top) {
+      ta = *s64;
+      AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+      AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+      prod = ta;
+      AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+      *d64 ^= (ta ^ prod);
+      d64++;
+      s64++;
+    }
+  } else {
+    while (d64 < (uint64_t *) rd.d_top) {
+      ta = *s64;
+      AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+      AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+      prod = ta;
+      AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+      *d64 = (ta ^ prod);
+      d64++;
+      s64++;
+    }
+  }
+  break; 
+    case 13:
+  if (xor) {
+    while (d64 < (uint64_t *) rd.d_top) {
+      ta = *s64;
+      prod = ta;
+      AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+      AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+      prod ^= ta;
+      AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+      *d64 ^= (ta ^ prod);
+      d64++;
+      s64++;
+    }
+  } else {
+    while (d64 < (uint64_t *) rd.d_top) {
+      ta = *s64;
+      prod = ta;
+      AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+      AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+      prod ^= ta;
+      AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+      *d64 = (ta ^ prod);
+      d64++;
+      s64++;
+    }
+  }
+  break; 
+    case 14:
+  if (xor) {
+    while (d64 < (uint64_t *) rd.d_top) {
+      ta = *s64;
+      AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+      prod = ta;
+      AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+      prod ^= ta;
+      AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+      *d64 ^= (ta ^ prod);
+      d64++;
+      s64++;
+    }
+  } else {
+    while (d64 < (uint64_t *) rd.d_top) {
+      ta = *s64;
+      AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+      prod = ta;
+      AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+      prod ^= ta;
+      AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+      *d64 = (ta ^ prod);
+      d64++;
+      s64++;
+    }
+  }
+  break; 
+    case 15:
+  if (xor) {
+    while (d64 < (uint64_t *) rd.d_top) {
+      ta = *s64;
+      prod = ta;
+      AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+      prod ^= ta;
+      AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+      prod ^= ta;
+      AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+      *d64 ^= (ta ^ prod);
+      d64++;
+      s64++;
+    }
+  } else {
+    while (d64 < (uint64_t *) rd.d_top) {
+      ta = *s64;
+      prod = ta;
+      AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+      prod ^= ta;
+      AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+      prod ^= ta;
+      AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+      *d64 = (ta ^ prod);
+      d64++;
+      s64++;
+    }
+  }
+  break; 
+  */
+    default:
+    if (xor) {
+      while (d64 < (uint64_t *) rd.d_top) {
+        prod = *d64 ;
+        ta = *s64;
+        tb = val;
+        while (1) {
+          if (tb & 1) prod ^= ta;
+          tb >>= 1;
+          if (tb == 0) break;
+          AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        }
+        *d64 = prod;
+        d64++;
+        s64++;
+      }
+    } else {
+      while (d64 < (uint64_t *) rd.d_top) {
+        prod = 0 ;
+        ta = *s64;
+        tb = val;
+        while (1) {
+          if (tb & 1) prod ^= ta;
+          tb >>= 1;
+          if (tb == 0) break;
+          AB2(btd->prim_poly, btd->mask1, btd->mask2, ta, t1, t2);
+        }
+        *d64 = prod;
+        d64++;
+        s64++;
+      }
+    }
+    break;
+  }
+  gf_do_final_region_alignment(&rd);
+}
+
+  static
+int gf_w8_bytwo_init(gf_t *gf)
+{
+  gf_internal_t *h;
+  uint64_t ip, m1, m2;
+  struct gf_w8_bytwo_data *btd;
+
+  h = (gf_internal_t *) gf->scratch;
+  btd = (struct gf_w8_bytwo_data *) (h->private);
+  ip = h->prim_poly & 0xff;
+  m1 = 0xfe;
+  m2 = 0x80;
+  btd->prim_poly = 0;
+  btd->mask1 = 0;
+  btd->mask2 = 0;
+
+  while (ip != 0) {
+    btd->prim_poly |= ip;
+    btd->mask1 |= m1;
+    btd->mask2 |= m2;
+    ip <<= GF_FIELD_WIDTH;
+    m1 <<= GF_FIELD_WIDTH;
+    m2 <<= GF_FIELD_WIDTH;
+  }
+
+  if (h->mult_type == GF_MULT_BYTWO_p) {
+    gf->multiply.w32 = gf_w8_bytwo_p_multiply;
+#ifdef INTEL_SSE2
+    if (h->region_type & GF_REGION_NOSSE)
+      gf->multiply_region.w32 = gf_w8_bytwo_p_nosse_multiply_region;
+    else
+      gf->multiply_region.w32 = gf_w8_bytwo_p_sse_multiply_region;
+#else
+    gf->multiply_region.w32 = gf_w8_bytwo_p_nosse_multiply_region;
+    if(h->region_type & GF_REGION_SSE)
+      return 0;
+#endif
+  } else {
+    gf->multiply.w32 = gf_w8_bytwo_b_multiply;
+#ifdef INTEL_SSE2
+    if (h->region_type & GF_REGION_NOSSE)
+      gf->multiply_region.w32 = gf_w8_bytwo_b_nosse_multiply_region;
+    else
+      gf->multiply_region.w32 = gf_w8_bytwo_b_sse_multiply_region;
+#else
+    gf->multiply_region.w32 = gf_w8_bytwo_b_nosse_multiply_region;
+    if(h->region_type & GF_REGION_SSE)
+      return 0;
+#endif
+  }
+  return 1;
+}
+
+
+/* ------------------------------------------------------------
+   General procedures.
+   You don't need to error check here on in init, because it's done
+   for you in gf_error_check().
+ */
+
+int gf_w8_scratch_size(int mult_type, int region_type, int divide_type, int arg1, int arg2)
+{
+  switch(mult_type)
+  {
+    case GF_MULT_DEFAULT:
+#ifdef INTEL_SSSE3
+      return sizeof(gf_internal_t) + sizeof(struct gf_w8_default_data) + 64;
+#endif
+      return sizeof(gf_internal_t) + sizeof(struct gf_w8_single_table_data) + 64;
+    case GF_MULT_TABLE:
+      if (region_type == GF_REGION_CAUCHY) {
+        return sizeof(gf_internal_t) + sizeof(struct gf_w8_single_table_data) + 64;
+      }
+
+      if (region_type == GF_REGION_DEFAULT) {
+        return sizeof(gf_internal_t) + sizeof(struct gf_w8_single_table_data) + 64;
+      } 
+      if (region_type & GF_REGION_DOUBLE_TABLE) {
+        if (region_type == GF_REGION_DOUBLE_TABLE) {
+          return sizeof(gf_internal_t) + sizeof(struct gf_w8_double_table_data) + 64;
+        } else if (region_type == (GF_REGION_DOUBLE_TABLE | GF_REGION_LAZY)) {
+          return sizeof(gf_internal_t) + sizeof(struct gf_w8_double_table_lazy_data) + 64;
+        } else {
+          return 0;
+        }
+      }
+      return 0;
+      break;
+    case GF_MULT_BYTWO_p:
+    case GF_MULT_BYTWO_b:
+      return sizeof(gf_internal_t) + sizeof(struct gf_w8_bytwo_data);
+      break;
+    case GF_MULT_SPLIT_TABLE:
+      if ((arg1 == 4 && arg2 == 8) || (arg1 == 8 && arg2 == 4)) {
+        return sizeof(gf_internal_t) + sizeof(struct gf_w8_half_table_data) + 64;
+      }
+      break;
+    case GF_MULT_LOG_TABLE:
+      return sizeof(gf_internal_t) + sizeof(struct gf_w8_logtable_data) + 64;
+      break;
+    case GF_MULT_LOG_ZERO:
+      return sizeof(gf_internal_t) + sizeof(struct gf_w8_logzero_small_table_data) + 64;
+      break;
+    case GF_MULT_LOG_ZERO_EXT:
+      return sizeof(gf_internal_t) + sizeof(struct gf_w8_logzero_table_data) + 64;
+      break;
+    case GF_MULT_CARRY_FREE:
+      return sizeof(gf_internal_t);
+      break;
+    case GF_MULT_SHIFT:
+      return sizeof(gf_internal_t);
+      break;
+    case GF_MULT_COMPOSITE:
+      return sizeof(gf_internal_t) + sizeof(struct gf_w8_composite_data) + 64;
+    default:
+      return 0;
+  }
+  return 0;
+}
+
+int gf_w8_init(gf_t *gf)
+{
+  gf_internal_t *h;
+
+  h = (gf_internal_t *) gf->scratch;
+
+  /* Allen: set default primitive polynomial / irreducible polynomial if needed */
+
+  if (h->prim_poly == 0) {
+    if (h->mult_type == GF_MULT_COMPOSITE) { 
+      h->prim_poly = gf_composite_get_default_poly(h->base_gf);
+      if (h->prim_poly == 0) return 0;   /* JSP: This shouldn't happen, but just in case. */
+    } else {             
+      h->prim_poly = 0x11d;
+    } 
+  }
+  if (h->mult_type != GF_MULT_COMPOSITE) { 
+    h->prim_poly |= 0x100;
+  }
+
+  gf->multiply.w32 = NULL;
+  gf->divide.w32 = NULL;
+  gf->inverse.w32 = NULL;
+  gf->multiply_region.w32 = NULL;
+  gf->extract_word.w32 = gf_w8_extract_word;
+
+  switch(h->mult_type) {
+    case GF_MULT_DEFAULT:      
+    case GF_MULT_TABLE:        if (gf_w8_table_init(gf) == 0) return 0; break;
+    case GF_MULT_BYTWO_p:
+    case GF_MULT_BYTWO_b:      if (gf_w8_bytwo_init(gf) == 0) return 0; break;
+    case GF_MULT_LOG_ZERO:
+    case GF_MULT_LOG_ZERO_EXT:
+    case GF_MULT_LOG_TABLE:    if (gf_w8_log_init(gf) == 0) return 0; break;
+    case GF_MULT_CARRY_FREE:   if (gf_w8_cfm_init(gf) == 0) return 0; break;
+    case GF_MULT_SHIFT:        if (gf_w8_shift_init(gf) == 0) return 0; break;
+    case GF_MULT_SPLIT_TABLE:  if (gf_w8_split_init(gf) == 0) return 0; break;
+    case GF_MULT_COMPOSITE:    if (gf_w8_composite_init(gf) == 0) return 0; break;
+    default: return 0;
+  }
+
+  if (h->divide_type == GF_DIVIDE_EUCLID) {
+    gf->divide.w32 = gf_w8_divide_from_inverse;
+    gf->inverse.w32 = gf_w8_euclid;
+  } else if (h->divide_type == GF_DIVIDE_MATRIX) {
+    gf->divide.w32 = gf_w8_divide_from_inverse;
+    gf->inverse.w32 = gf_w8_matrix;
+  }
+
+  if (gf->divide.w32 == NULL) {
+    gf->divide.w32 = gf_w8_divide_from_inverse;
+    if (gf->inverse.w32 == NULL) gf->inverse.w32 = gf_w8_euclid;
+  }
+
+  if (gf->inverse.w32 == NULL)  gf->inverse.w32 = gf_w8_inverse_from_divide;
+
+  if (h->mult_type == GF_MULT_COMPOSITE && (h->region_type & GF_REGION_ALTMAP)) {
+    gf->extract_word.w32 = gf_w8_composite_extract_word;
+  }
+
+  if (h->region_type == GF_REGION_CAUCHY) {
+    gf->multiply_region.w32 = gf_wgen_cauchy_region;
+    gf->extract_word.w32 = gf_wgen_extract_word;
+  }
+
+  if (gf->multiply_region.w32 == NULL) {
+    gf->multiply_region.w32 = gf_w8_multiply_region_from_single;
+  }
+
+  return 1;
+}
+
+
+/* Inline setup functions */
+
+uint8_t *gf_w8_get_mult_table(gf_t *gf)
+{
+  gf_internal_t *h;
+  struct gf_w8_default_data *ftd;
+  struct gf_w8_single_table_data *std;
+
+  h = (gf_internal_t *) gf->scratch;
+  if (gf->multiply.w32 == gf_w8_default_multiply) {
+    ftd = (struct gf_w8_default_data *) h->private;
+    return (uint8_t *) ftd->multtable;
+  } else if (gf->multiply.w32 == gf_w8_table_multiply) {
+    std = (struct gf_w8_single_table_data *) h->private;
+    return (uint8_t *) std->multtable;
+  }
+  return NULL;
+}
+
+uint8_t *gf_w8_get_div_table(gf_t *gf)
+{
+  struct gf_w8_default_data *ftd;
+  struct gf_w8_single_table_data *std;
+
+  if (gf->multiply.w32 == gf_w8_default_multiply) {
+    ftd = (struct gf_w8_default_data *) ((gf_internal_t *) gf->scratch)->private;
+    return (uint8_t *) ftd->divtable;
+  } else if (gf->multiply.w32 == gf_w8_table_multiply) {
+    std = (struct gf_w8_single_table_data *) ((gf_internal_t *) gf->scratch)->private;
+    return (uint8_t *) std->divtable;
+  }
+  return NULL;
+}
diff --git a/src/erasure-code/jerasure/gf-complete/src/gf_wgen.c b/src/erasure-code/jerasure/gf-complete/src/gf_wgen.c
new file mode 100644
index 0000000..68c6bb0
--- /dev/null
+++ b/src/erasure-code/jerasure/gf-complete/src/gf_wgen.c
@@ -0,0 +1,1019 @@
+/*
+ * GF-Complete: A Comprehensive Open Source Library for Galois Field Arithmetic
+ * James S. Plank, Ethan L. Miller, Kevin M. Greenan,
+ * Benjamin A. Arnold, John A. Burnum, Adam W. Disney, Allen C. McBride.
+ *
+ * gf_wgen.c
+ *
+ * Routines for Galois fields for general w < 32.  For specific w, 
+   like 4, 8, 16, 32, 64 and 128, see the other files.
+ */
+
+#include "gf_int.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+struct gf_wgen_table_w8_data {
+  uint8_t *mult;
+  uint8_t *div;
+  uint8_t base;
+};
+
+struct gf_wgen_table_w16_data {
+  uint16_t *mult;
+  uint16_t *div;
+  uint16_t base;
+};
+
+struct gf_wgen_log_w8_data {
+  uint8_t *log;
+  uint8_t *anti;
+  uint8_t *danti;
+  uint8_t base;
+};
+
+struct gf_wgen_log_w16_data {
+  uint16_t *log;
+  uint16_t *anti;
+  uint16_t *danti;
+  uint16_t base;
+};
+
+struct gf_wgen_log_w32_data {
+  uint32_t *log;
+  uint32_t *anti;
+  uint32_t *danti;
+  uint32_t base;
+};
+
+struct gf_wgen_group_data {
+    uint32_t *reduce;
+    uint32_t *shift;
+    uint32_t mask;
+    uint64_t rmask;
+    int tshift;
+    uint32_t memory;
+};
+
+static
+inline
+gf_val_32_t gf_wgen_inverse_from_divide (gf_t *gf, gf_val_32_t a)
+{
+  return gf->divide.w32(gf, 1, a);
+}
+
+static
+inline
+gf_val_32_t gf_wgen_divide_from_inverse (gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  b = gf->inverse.w32(gf, b);
+  return gf->multiply.w32(gf, a, b);
+}
+
+static
+inline
+gf_val_32_t gf_wgen_euclid (gf_t *gf, gf_val_32_t b)
+{
+  
+  gf_val_32_t e_i, e_im1, e_ip1;
+  gf_val_32_t d_i, d_im1, d_ip1;
+  gf_val_32_t y_i, y_im1, y_ip1;
+  gf_val_32_t c_i;
+
+  if (b == 0) return -1;
+  e_im1 = ((gf_internal_t *) (gf->scratch))->prim_poly;
+  e_i = b;
+  d_im1 = ((gf_internal_t *) (gf->scratch))->w;
+  for (d_i = d_im1; ((1 << d_i) & e_i) == 0; d_i--) ;
+  y_i = 1;
+  y_im1 = 0;
+
+  while (e_i != 1) {
+
+    e_ip1 = e_im1;
+    d_ip1 = d_im1;
+    c_i = 0;
+
+    while (d_ip1 >= d_i) {
+      c_i ^= (1 << (d_ip1 - d_i));
+      e_ip1 ^= (e_i << (d_ip1 - d_i));
+      if (e_ip1 == 0) return 0;
+      while ((e_ip1 & (1 << d_ip1)) == 0) d_ip1--;
+    }
+
+    y_ip1 = y_im1 ^ gf->multiply.w32(gf, c_i, y_i);
+    y_im1 = y_i;
+    y_i = y_ip1;
+
+    e_im1 = e_i;
+    d_im1 = d_i;
+    e_i = e_ip1;
+    d_i = d_ip1;
+  }
+
+  return y_i;
+}
+
+gf_val_32_t gf_wgen_extract_word(gf_t *gf, void *start, int bytes, int index)
+{
+  uint8_t *ptr;
+  uint32_t rv;
+  int rs;
+  int byte, bit, i;
+  gf_internal_t *h;
+
+  h = (gf_internal_t *) gf->scratch;
+  rs = bytes / h->w;
+  byte = index/8;
+  bit = index%8;
+
+  ptr = (uint8_t *) start;
+  ptr += bytes;
+  ptr -= rs;
+  ptr += byte;
+
+  rv = 0;
+  for (i = 0; i < h->w; i++) {
+    rv <<= 1;
+    if ((*ptr) & (1 << bit)) rv |= 1;
+    ptr -= rs;
+  }
+  
+  return rv;
+}
+
+static
+inline
+gf_val_32_t gf_wgen_matrix (gf_t *gf, gf_val_32_t b)
+{
+  return gf_bitmatrix_inverse(b, ((gf_internal_t *) (gf->scratch))->w, 
+              ((gf_internal_t *) (gf->scratch))->prim_poly);
+}
+
+static
+inline
+uint32_t
+gf_wgen_shift_multiply (gf_t *gf, uint32_t a32, uint32_t b32)
+{
+  uint64_t product, i, pp, a, b, one;
+  gf_internal_t *h;
+ 
+  a = a32;
+  b = b32;
+  h = (gf_internal_t *) gf->scratch;
+  one = 1;
+  pp = h->prim_poly | (one << h->w);
+
+  product = 0;
+
+  for (i = 0; i < h->w; i++) {
+    if (a & (one << i)) product ^= (b << i);
+  }
+  for (i = h->w*2-1; i >= h->w; i--) {
+    if (product & (one << i)) product ^= (pp << (i-h->w));
+  }
+  return product;
+}
+
+static 
+int gf_wgen_shift_init(gf_t *gf)
+{
+  gf->multiply.w32 = gf_wgen_shift_multiply;
+  gf->inverse.w32 = gf_wgen_euclid;
+  return 1;
+}
+
+static
+gf_val_32_t
+gf_wgen_bytwo_b_multiply (gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  uint32_t prod, pp, bmask;
+  gf_internal_t *h;
+
+  h = (gf_internal_t *) gf->scratch;
+  pp = h->prim_poly;
+
+  prod = 0;
+  bmask = (1 << (h->w-1));
+
+  while (1) {
+    if (a & 1) prod ^= b;
+    a >>= 1;
+    if (a == 0) return prod;
+    if (b & bmask) {
+      b = ((b << 1) ^ pp);
+    } else {
+      b <<= 1;
+    }
+  }
+}
+
+static 
+int gf_wgen_bytwo_b_init(gf_t *gf)
+{
+  gf->multiply.w32 = gf_wgen_bytwo_b_multiply;
+  gf->inverse.w32 = gf_wgen_euclid;
+  return 1;
+}
+
+static
+inline
+gf_val_32_t
+gf_wgen_bytwo_p_multiply (gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  uint32_t prod, pp, pmask, amask;
+  gf_internal_t *h;
+
+  h = (gf_internal_t *) gf->scratch;
+  pp = h->prim_poly;
+
+  prod = 0;
+  pmask = (1 << ((h->w)-1)); /*Ben: Had an operator precedence warning here*/
+  amask = pmask;
+
+  while (amask != 0) {
+    if (prod & pmask) {
+      prod = ((prod << 1) ^ pp);
+    } else {
+      prod <<= 1;
+    }
+    if (a & amask) prod ^= b;
+    amask >>= 1;
+  }
+  return prod;
+}
+
+
+static 
+int gf_wgen_bytwo_p_init(gf_t *gf)
+{
+  gf->multiply.w32 = gf_wgen_bytwo_p_multiply;
+  gf->inverse.w32 = gf_wgen_euclid;
+  return 1;
+}
+
+static
+void
+gf_wgen_group_set_shift_tables(uint32_t *shift, uint32_t val, gf_internal_t *h)
+{
+  int i;
+  uint32_t j;
+  int g_s;
+
+  if (h->mult_type == GF_MULT_DEFAULT) {
+    g_s = 2;
+  } else {
+    g_s = h->arg1;
+  }
+
+  shift[0] = 0;
+
+  for (i = 1; i < (1 << g_s); i <<= 1) {
+    for (j = 0; j < i; j++) shift[i|j] = shift[j]^val;
+    if (val & (1 << (h->w-1))) {
+      val <<= 1;
+      val ^= h->prim_poly;
+    } else {
+      val <<= 1;
+    }
+  }
+}
+
+static
+inline
+gf_val_32_t
+gf_wgen_group_s_equals_r_multiply(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  int leftover, rs;
+  uint32_t p, l, ind, a32;
+  int bits_left;
+  int g_s;
+  int w;
+
+  struct gf_wgen_group_data *gd;
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  g_s = h->arg1;
+  w = h->w;
+
+  gd = (struct gf_wgen_group_data *) h->private;
+  gf_wgen_group_set_shift_tables(gd->shift, b, h);
+
+  leftover = w % g_s;
+  if (leftover == 0) leftover = g_s;
+
+  rs = w - leftover;
+  a32 = a;
+  ind = a32 >> rs;
+  a32 <<= leftover;
+  a32 &= gd->mask;
+  p = gd->shift[ind];
+
+  bits_left = rs;
+  rs = w - g_s;
+
+  while (bits_left > 0) {
+    bits_left -= g_s;
+    ind = a32 >> rs;
+    a32 <<= g_s;
+    a32 &= gd->mask;
+    l = p >> rs;
+    p = (gd->shift[ind] ^ gd->reduce[l] ^ (p << g_s)) & gd->mask;
+  }
+  return p;
+}
+
+char *bits(uint32_t v)
+{
+  char *rv;
+  int i, j;
+
+  rv = malloc(30);
+  j = 0;
+  for (i = 27; i >= 0; i--) {
+    rv[j] = '0' + ((v & (1 << i)) ? 1 : 0);
+    j++;
+  }
+  rv[j] = '\0';
+  return rv;
+}
+char *bits_56(uint64_t v)
+{
+  char *rv;
+  int i, j;
+  uint64_t one;
+
+  one = 1;
+
+  rv = malloc(60);
+  j = 0;
+  for (i = 55; i >= 0; i--) {
+    rv[j] = '0' + ((v & (one << i)) ? 1 : 0);
+    j++;
+  }
+  rv[j] = '\0';
+  return rv;
+}
+
+static
+inline
+gf_val_32_t
+gf_wgen_group_multiply(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  int i;
+  int leftover;
+  uint64_t p, l, r;
+  uint32_t a32, ind;
+  int g_s, g_r;
+  struct gf_wgen_group_data *gd;
+  int w;
+
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  if (h->mult_type == GF_MULT_DEFAULT) {
+    g_s = 2;
+    g_r = 8;
+  } else {
+    g_s = h->arg1;
+    g_r = h->arg2;
+  }
+  w = h->w;
+  gd = (struct gf_wgen_group_data *) h->private;
+  gf_wgen_group_set_shift_tables(gd->shift, b, h);
+
+  leftover = w % g_s;
+  if (leftover == 0) leftover = g_s;
+
+  a32 = a;
+  ind = a32 >> (w - leftover);
+  p = gd->shift[ind];
+  p <<= g_s;
+  a32 <<= leftover;
+  a32 &= gd->mask;
+
+  i = (w - leftover);
+  while (i > g_s) {
+    ind = a32 >> (w-g_s);
+    p ^= gd->shift[ind];
+    a32 <<= g_s;
+    a32 &= gd->mask;
+    p <<= g_s;
+    i -= g_s;
+  }
+
+  ind = a32 >> (h->w-g_s);
+  p ^= gd->shift[ind];
+
+  for (i = gd->tshift ; i >= 0; i -= g_r) {
+    l = p & (gd->rmask << i);
+    r = gd->reduce[l >> (i+w)];
+    r <<= (i);
+    p ^= r;
+  }
+  return p & gd->mask;
+}
+
+static
+int gf_wgen_group_init(gf_t *gf)
+{
+  uint32_t i, j, p, index;
+  struct gf_wgen_group_data *gd;
+  gf_internal_t *h = (gf_internal_t *) gf->scratch;
+  int g_s, g_r;
+
+  if (h->mult_type == GF_MULT_DEFAULT) {
+    g_s = 2;
+    g_r = 8;
+  } else {
+    g_s = h->arg1;
+    g_r = h->arg2;
+  }
+  gd = (struct gf_wgen_group_data *) h->private;
+  gd->shift = &(gd->memory);
+  gd->reduce = gd->shift + (1 << g_s);
+  gd->mask = (h->w != 31) ? ((1 << h->w)-1) : 0x7fffffff;
+
+  gd->rmask = (1 << g_r) - 1;
+  gd->rmask <<= h->w;
+
+  gd->tshift = h->w % g_s;
+  if (gd->tshift == 0) gd->tshift = g_s;
+  gd->tshift = (h->w - gd->tshift);
+  gd->tshift = ((gd->tshift-1)/g_r) * g_r;
+
+  gd->reduce[0] = 0;
+  for (i = 0; i < (1 << g_r); i++) {
+    p = 0;
+    index = 0;
+    for (j = 0; j < g_r; j++) {
+      if (i & (1 << j)) {
+        p ^= (h->prim_poly << j);
+        index ^= (h->prim_poly >> (h->w-j));
+      }
+    }
+    gd->reduce[index] = (p & gd->mask);
+  }
+
+  if (g_s == g_r) {
+    gf->multiply.w32 = gf_wgen_group_s_equals_r_multiply;
+  } else {
+    gf->multiply.w32 = gf_wgen_group_multiply; 
+  }
+  gf->divide.w32 = NULL;
+  gf->divide.w32 = NULL;
+  return 1;
+}
+
+
+static
+gf_val_32_t
+gf_wgen_table_8_multiply(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  gf_internal_t *h;
+  struct gf_wgen_table_w8_data *std;
+  
+  h = (gf_internal_t *) gf->scratch;
+  std = (struct gf_wgen_table_w8_data *) h->private;
+
+  return (std->mult[(a<<h->w)+b]);
+}
+
+static
+gf_val_32_t
+gf_wgen_table_8_divide(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  gf_internal_t *h;
+  struct gf_wgen_table_w8_data *std;
+  
+  h = (gf_internal_t *) gf->scratch;
+  std = (struct gf_wgen_table_w8_data *) h->private;
+
+  return (std->div[(a<<h->w)+b]);
+}
+
+static 
+int gf_wgen_table_8_init(gf_t *gf)
+{
+  gf_internal_t *h;
+  int w;
+  struct gf_wgen_table_w8_data *std;
+  uint32_t a, b, p;
+  
+  h = (gf_internal_t *) gf->scratch;
+  w = h->w;
+  std = (struct gf_wgen_table_w8_data *) h->private;
+  
+  std->mult = &(std->base);
+  std->div = std->mult + ((1<<h->w)*(1<<h->w));
+  
+  for (a = 0; a < (1 << w); a++) {
+    std->mult[a] = 0;
+    std->mult[a<<w] = 0;
+    std->div[a] = 0;
+    std->div[a<<w] = 0;
+  }
+    
+  for (a = 1; a < (1 << w); a++) {
+    for (b = 1; b < (1 << w); b++) {
+      p = gf_wgen_shift_multiply(gf, a, b);
+      std->mult[(a<<w)|b] = p;
+      std->div[(p<<w)|a] = b;
+    }
+  }
+
+  gf->multiply.w32 = gf_wgen_table_8_multiply;
+  gf->divide.w32 = gf_wgen_table_8_divide;
+  return 1;
+}
+
+static
+gf_val_32_t
+gf_wgen_table_16_multiply(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  gf_internal_t *h;
+  struct gf_wgen_table_w16_data *std;
+  
+  h = (gf_internal_t *) gf->scratch;
+  std = (struct gf_wgen_table_w16_data *) h->private;
+
+  return (std->mult[(a<<h->w)+b]);
+}
+
+static
+gf_val_32_t
+gf_wgen_table_16_divide(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  gf_internal_t *h;
+  struct gf_wgen_table_w16_data *std;
+  
+  h = (gf_internal_t *) gf->scratch;
+  std = (struct gf_wgen_table_w16_data *) h->private;
+
+  return (std->div[(a<<h->w)+b]);
+}
+
+static 
+int gf_wgen_table_16_init(gf_t *gf)
+{
+  gf_internal_t *h;
+  int w;
+  struct gf_wgen_table_w16_data *std;
+  uint32_t a, b, p;
+  
+  h = (gf_internal_t *) gf->scratch;
+  w = h->w;
+  std = (struct gf_wgen_table_w16_data *) h->private;
+  
+  std->mult = &(std->base);
+  std->div = std->mult + ((1<<h->w)*(1<<h->w));
+  
+  for (a = 0; a < (1 << w); a++) {
+    std->mult[a] = 0;
+    std->mult[a<<w] = 0;
+    std->div[a] = 0;
+    std->div[a<<w] = 0;
+  }
+  
+  for (a = 1; a < (1 << w); a++) {
+    for (b = 1; b < (1 << w); b++) {
+      p = gf_wgen_shift_multiply(gf, a, b);
+      std->mult[(a<<w)|b] = p;
+      std->div[(p<<w)|a] = b;
+    }
+  }
+
+  gf->multiply.w32 = gf_wgen_table_16_multiply;
+  gf->divide.w32 = gf_wgen_table_16_divide;
+  return 1;
+}
+
+static 
+int gf_wgen_table_init(gf_t *gf)
+{
+  gf_internal_t *h;
+  
+  h = (gf_internal_t *) gf->scratch;
+  if (h->w <= 8) return gf_wgen_table_8_init(gf);
+  if (h->w <= 14) return gf_wgen_table_16_init(gf);
+
+  /* Returning zero to make the compiler happy, but this won't get 
+     executed, because it is tested in _scratch_space. */
+
+  return 0;
+}
+
+static
+gf_val_32_t
+gf_wgen_log_8_multiply(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  gf_internal_t *h;
+  struct gf_wgen_log_w8_data *std;
+  
+  h = (gf_internal_t *) gf->scratch;
+  std = (struct gf_wgen_log_w8_data *) h->private;
+
+  if (a == 0 || b == 0) return 0;
+  return (std->anti[std->log[a]+std->log[b]]);
+}
+
+static
+gf_val_32_t
+gf_wgen_log_8_divide(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  gf_internal_t *h;
+  struct gf_wgen_log_w8_data *std;
+  int index;
+  
+  h = (gf_internal_t *) gf->scratch;
+  std = (struct gf_wgen_log_w8_data *) h->private;
+
+  if (a == 0 || b == 0) return 0;
+  index = std->log[a];
+  index -= std->log[b];
+
+  return (std->danti[index]);
+}
+
+static 
+int gf_wgen_log_8_init(gf_t *gf)
+{
+  gf_internal_t *h;
+  struct gf_wgen_log_w8_data *std;
+  int w;
+  uint32_t a, i;
+  int check = 0;
+  
+  h = (gf_internal_t *) gf->scratch;
+  w = h->w;
+  std = (struct gf_wgen_log_w8_data *) h->private;
+  
+  std->log = &(std->base);
+  std->anti = std->log + (1<<h->w);
+  std->danti = std->anti + (1<<h->w)-1;
+  
+  for (i = 0; i < (1 << w); i++)
+    std->log[i] = 0;
+
+  a = 1;
+  for(i=0; i < (1<<w)-1; i++)
+  {
+    if (std->log[a] != 0) check = 1;
+    std->log[a] = i;
+    std->anti[i] = a;
+    std->danti[i] = a;
+    a <<= 1;
+    if(a & (1<<w))
+      a ^= h->prim_poly;
+    //a &= ((1 << w)-1);
+  }
+
+  if (check != 0) {
+    _gf_errno = GF_E_LOGPOLY;
+    return 0;
+  }
+
+  gf->multiply.w32 = gf_wgen_log_8_multiply;
+  gf->divide.w32 = gf_wgen_log_8_divide;
+  return 1;
+}
+
+static
+gf_val_32_t
+gf_wgen_log_16_multiply(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  gf_internal_t *h;
+  struct gf_wgen_log_w16_data *std;
+  
+  h = (gf_internal_t *) gf->scratch;
+  std = (struct gf_wgen_log_w16_data *) h->private;
+
+  if (a == 0 || b == 0) return 0;
+  return (std->anti[std->log[a]+std->log[b]]);
+}
+
+static
+gf_val_32_t
+gf_wgen_log_16_divide(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  gf_internal_t *h;
+  struct gf_wgen_log_w16_data *std;
+  int index;
+  
+  h = (gf_internal_t *) gf->scratch;
+  std = (struct gf_wgen_log_w16_data *) h->private;
+
+  if (a == 0 || b == 0) return 0;
+  index = std->log[a];
+  index -= std->log[b];
+
+  return (std->danti[index]);
+}
+
+static 
+int gf_wgen_log_16_init(gf_t *gf)
+{
+  gf_internal_t *h;
+  struct gf_wgen_log_w16_data *std;
+  int w;
+  uint32_t a, i;
+  int check = 0;
+  
+  h = (gf_internal_t *) gf->scratch;
+  w = h->w;
+  std = (struct gf_wgen_log_w16_data *) h->private;
+  
+  std->log = &(std->base);
+  std->anti = std->log + (1<<h->w);
+  std->danti = std->anti + (1<<h->w)-1;
+ 
+  for (i = 0; i < (1 << w); i++)
+    std->log[i] = 0;
+
+  a = 1;
+  for(i=0; i < (1<<w)-1; i++)
+  {
+    if (std->log[a] != 0) check = 1;
+    std->log[a] = i;
+    std->anti[i] = a;
+    std->danti[i] = a;
+    a <<= 1;
+    if(a & (1<<w))
+      a ^= h->prim_poly;
+    //a &= ((1 << w)-1);
+  }
+
+  if (check) {
+    if (h->mult_type != GF_MULT_LOG_TABLE) return gf_wgen_shift_init(gf);
+    _gf_errno = GF_E_LOGPOLY;
+    return 0;
+  }
+  
+  gf->multiply.w32 = gf_wgen_log_16_multiply;
+  gf->divide.w32 = gf_wgen_log_16_divide;
+  return 1;
+}
+
+static
+gf_val_32_t
+gf_wgen_log_32_multiply(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  gf_internal_t *h;
+  struct gf_wgen_log_w32_data *std;
+  
+  h = (gf_internal_t *) gf->scratch;
+  std = (struct gf_wgen_log_w32_data *) h->private;
+
+  if (a == 0 || b == 0) return 0;
+  return (std->anti[std->log[a]+std->log[b]]);
+}
+
+static
+gf_val_32_t
+gf_wgen_log_32_divide(gf_t *gf, gf_val_32_t a, gf_val_32_t b)
+{
+  gf_internal_t *h;
+  struct gf_wgen_log_w32_data *std;
+  int index;
+  
+  h = (gf_internal_t *) gf->scratch;
+  std = (struct gf_wgen_log_w32_data *) h->private;
+
+  if (a == 0 || b == 0) return 0;
+  index = std->log[a];
+  index -= std->log[b];
+
+  return (std->danti[index]);
+}
+
+static 
+int gf_wgen_log_32_init(gf_t *gf)
+{
+  gf_internal_t *h;
+  struct gf_wgen_log_w32_data *std;
+  int w;
+  uint32_t a, i;
+  int check = 0;
+
+  h = (gf_internal_t *) gf->scratch;
+  w = h->w;
+  std = (struct gf_wgen_log_w32_data *) h->private;
+  
+  std->log = &(std->base);
+  std->anti = std->log + (1<<h->w);
+  std->danti = std->anti + (1<<h->w)-1;
+  
+  for (i = 0; i < (1 << w); i++)
+    std->log[i] = 0;
+
+  a = 1;
+  for(i=0; i < (1<<w)-1; i++)
+  {
+    if (std->log[a] != 0) check = 1;
+    std->log[a] = i;
+    std->anti[i] = a;
+    std->danti[i] = a;
+    a <<= 1;
+    if(a & (1<<w))
+      a ^= h->prim_poly;
+    //a &= ((1 << w)-1);
+  }
+
+  if (check != 0) {
+    _gf_errno = GF_E_LOGPOLY;
+    return 0;
+  }
+
+  gf->multiply.w32 = gf_wgen_log_32_multiply;
+  gf->divide.w32 = gf_wgen_log_32_divide;
+  return 1;
+}
+
+static 
+int gf_wgen_log_init(gf_t *gf)
+{
+  gf_internal_t *h;
+  
+  h = (gf_internal_t *) gf->scratch;
+  if (h->w <= 8) return gf_wgen_log_8_init(gf);
+  if (h->w <= 16) return gf_wgen_log_16_init(gf);
+  if (h->w <= 32) return gf_wgen_log_32_init(gf); 
+
+  /* Returning zero to make the compiler happy, but this won't get 
+     executed, because it is tested in _scratch_space. */
+
+  return 0;
+}
+
+int gf_wgen_scratch_size(int w, int mult_type, int region_type, int divide_type, int arg1, int arg2)
+{
+
+  switch(mult_type)
+  {
+    case GF_MULT_DEFAULT: 
+      if (w <= 8) {
+          return sizeof(gf_internal_t) + sizeof(struct gf_wgen_table_w8_data) +
+               sizeof(uint8_t)*(1 << w)*(1<<w)*2 + 64;
+      } else if (w <= 16) {
+        return sizeof(gf_internal_t) + sizeof(struct gf_wgen_log_w16_data) +
+               sizeof(uint16_t)*(1 << w)*3;
+      } else {
+        return sizeof(gf_internal_t) + sizeof(struct gf_wgen_group_data) +
+               sizeof(uint32_t) * (1 << 2) +
+               sizeof(uint32_t) * (1 << 8) + 64;
+      }
+    case GF_MULT_SHIFT:
+    case GF_MULT_BYTWO_b:
+    case GF_MULT_BYTWO_p:
+      return sizeof(gf_internal_t);
+      break;
+    case GF_MULT_GROUP:
+      return sizeof(gf_internal_t) + sizeof(struct gf_wgen_group_data) +
+               sizeof(uint32_t) * (1 << arg1) +
+               sizeof(uint32_t) * (1 << arg2) + 64;
+      break;
+
+    case GF_MULT_TABLE: 
+      if (w <= 8) {
+        return sizeof(gf_internal_t) + sizeof(struct gf_wgen_table_w8_data) +
+               sizeof(uint8_t)*(1 << w)*(1<<w)*2 + 64;
+      } else if (w < 15) {
+        return sizeof(gf_internal_t) + sizeof(struct gf_wgen_table_w16_data) +
+               sizeof(uint16_t)*(1 << w)*(1<<w)*2 + 64;
+      } 
+      return 0;
+    case GF_MULT_LOG_TABLE: 
+      if (w <= 8) {
+        return sizeof(gf_internal_t) + sizeof(struct gf_wgen_log_w8_data) +
+               sizeof(uint8_t)*(1 << w)*3;
+      } else if (w <= 16) {
+        return sizeof(gf_internal_t) + sizeof(struct gf_wgen_log_w16_data) +
+               sizeof(uint16_t)*(1 << w)*3;
+      } else if (w <= 27) {
+        return sizeof(gf_internal_t) + sizeof(struct gf_wgen_log_w32_data) +
+               sizeof(uint32_t)*(1 << w)*3;
+      } else 
+      return 0;
+    default:
+      return 0;
+   }
+}
+
+void
+gf_wgen_cauchy_region(gf_t *gf, void *src, void *dest, gf_val_32_t val, int bytes, int xor)
+{
+  gf_internal_t *h;
+  gf_region_data rd;
+  int written;    
+  int rs, i, j;
+
+  gf_set_region_data(&rd, gf, src, dest, bytes, val, xor, -1);
+
+  if (val == 0) { gf_multby_zero(dest, bytes, xor); return; }
+  if (val == 1) { gf_multby_one(src, dest, bytes, xor); return; }
+
+  h = (gf_internal_t *) gf->scratch;
+  rs = bytes / (h->w);
+  
+  written = (xor) ? 0xffffffff : 0;
+  for (i = 0; i < h->w; i++) {
+    for (j = 0; j < h->w; j++) {
+      if (val & (1 << j)) {
+        gf_multby_one(src, ((char*)dest) + j*rs, rs, (written & (1 << j)));
+        written |= (1 << j);
+      }
+    }
+    src = (char*)src + rs;
+    val = gf->multiply.w32(gf, val, 2);
+  }
+}
+
+int gf_wgen_init(gf_t *gf)
+{
+  gf_internal_t *h;
+
+  h = (gf_internal_t *) gf->scratch;
+  if (h->prim_poly == 0) {
+    switch (h->w) {
+      case 1: h->prim_poly = 1; break;
+      case 2: h->prim_poly = 7; break;
+      case 3: h->prim_poly = 013; break;
+      case 4: h->prim_poly = 023; break;
+      case 5: h->prim_poly = 045; break;
+      case 6: h->prim_poly = 0103; break;
+      case 7: h->prim_poly = 0211; break;
+      case 8: h->prim_poly = 0435; break;
+      case 9: h->prim_poly = 01021; break;
+      case 10: h->prim_poly = 02011; break;
+      case 11: h->prim_poly = 04005; break;
+      case 12: h->prim_poly = 010123; break;
+      case 13: h->prim_poly = 020033; break;
+      case 14: h->prim_poly = 042103; break;
+      case 15: h->prim_poly = 0100003; break;
+      case 16: h->prim_poly = 0210013; break;
+      case 17: h->prim_poly = 0400011; break;
+      case 18: h->prim_poly = 01000201; break;
+      case 19: h->prim_poly = 02000047; break;
+      case 20: h->prim_poly = 04000011; break;
+      case 21: h->prim_poly = 010000005; break;
+      case 22: h->prim_poly = 020000003; break;
+      case 23: h->prim_poly = 040000041; break;
+      case 24: h->prim_poly = 0100000207; break;
+      case 25: h->prim_poly = 0200000011; break;
+      case 26: h->prim_poly = 0400000107; break;
+      case 27: h->prim_poly = 01000000047; break;
+      case 28: h->prim_poly = 02000000011; break;
+      case 29: h->prim_poly = 04000000005; break;
+      case 30: h->prim_poly = 010040000007; break;
+      case 31: h->prim_poly = 020000000011; break;
+      case 32: h->prim_poly = 00020000007; break;
+      default: fprintf(stderr, "gf_wgen_init: w not defined yet\n"); exit(1);
+    }
+  } else {
+    if (h->w == 32) {
+      h->prim_poly &= 0xffffffff;
+    } else {
+      h->prim_poly |= (1 << h->w);
+      if (h->prim_poly & ~((1ULL<<(h->w+1))-1)) return 0;
+    }
+  }
+
+  gf->multiply.w32 = NULL;
+  gf->divide.w32 = NULL;
+  gf->inverse.w32 = NULL;
+  gf->multiply_region.w32 = gf_wgen_cauchy_region;
+  gf->extract_word.w32 = gf_wgen_extract_word;
+
+  switch(h->mult_type) {
+    case GF_MULT_DEFAULT:
+      if (h->w <= 8) {
+        if (gf_wgen_table_init(gf) == 0) return 0; 
+      } else if (h->w <= 16) {
+        if (gf_wgen_log_init(gf) == 0) return 0; 
+      } else {
+        if (gf_wgen_bytwo_p_init(gf) == 0) return 0; 
+      }
+      break;
+    case GF_MULT_SHIFT:     if (gf_wgen_shift_init(gf) == 0) return 0; break;
+    case GF_MULT_BYTWO_b:     if (gf_wgen_bytwo_b_init(gf) == 0) return 0; break;
+    case GF_MULT_BYTWO_p:     if (gf_wgen_bytwo_p_init(gf) == 0) return 0; break;
+    case GF_MULT_GROUP:     if (gf_wgen_group_init(gf) == 0) return 0; break;
+    case GF_MULT_TABLE:     if (gf_wgen_table_init(gf) == 0) return 0; break;
+    case GF_MULT_LOG_TABLE: if (gf_wgen_log_init(gf) == 0) return 0; break;
+    default: return 0;
+  }
+  if (h->divide_type == GF_DIVIDE_EUCLID) {
+    gf->divide.w32 = gf_wgen_divide_from_inverse;
+    gf->inverse.w32 = gf_wgen_euclid;
+  } else if (h->divide_type == GF_DIVIDE_MATRIX) {
+    gf->divide.w32 = gf_wgen_divide_from_inverse;
+    gf->inverse.w32 = gf_wgen_matrix;
+  }
+
+  if (gf->inverse.w32== NULL && gf->divide.w32 == NULL) gf->inverse.w32 = gf_wgen_euclid;
+
+  if (gf->inverse.w32 != NULL && gf->divide.w32 == NULL) {
+    gf->divide.w32 = gf_wgen_divide_from_inverse;
+  }
+  if (gf->inverse.w32 == NULL && gf->divide.w32 != NULL) {
+    gf->inverse.w32 = gf_wgen_inverse_from_divide;
+  }
+  return 1;
+}
diff --git a/src/erasure-code/jerasure/jerasure/include/cauchy.h b/src/erasure-code/jerasure/jerasure/include/cauchy.h
new file mode 100644
index 0000000..a4fad6b
--- /dev/null
+++ b/src/erasure-code/jerasure/jerasure/include/cauchy.h
@@ -0,0 +1,45 @@
+/* *
+ * Copyright (c) 2013, James S. Plank and Kevin Greenan
+ * All rights reserved.
+ *
+ * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure
+ * Coding Techniques
+ *
+ * Revision 2.0: Galois Field backend now links to GF-Complete
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  - Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ *  - Neither the name of the University of Tennessee nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+extern int *cauchy_original_coding_matrix(int k, int m, int w);
+extern int *cauchy_xy_coding_matrix(int k, int m, int w, int *x, int *y);
+extern void cauchy_improve_coding_matrix(int k, int m, int w, int *matrix);
+extern int *cauchy_good_general_coding_matrix(int k, int m, int w);
+extern int cauchy_n_ones(int n, int w);
diff --git a/src/erasure-code/jerasure/jerasure/include/galois.h b/src/erasure-code/jerasure/jerasure/include/galois.h
new file mode 100644
index 0000000..d75be6a
--- /dev/null
+++ b/src/erasure-code/jerasure/jerasure/include/galois.h
@@ -0,0 +1,99 @@
+/* *
+ * Copyright (c) 2013, James S. Plank and Kevin Greenan
+ * All rights reserved.
+ *
+ * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure
+ * Coding Techniques
+ *
+ * Revision 2.0: Galois Field backend now links to GF-Complete
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  - Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ *  - Neither the name of the University of Tennessee nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef _GALOIS_H
+#define _GALOIS_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <gf_complete.h>
+
+extern void galois_change_technique(gf_t *gf, int w);
+
+extern int galois_single_multiply(int a, int b, int w);
+extern int galois_single_divide(int a, int b, int w);
+extern int galois_inverse(int x, int w);
+
+void galois_region_xor(           char *src,         /* Source Region */
+                                  char *dest,        /* Dest Region (holds result) */
+                                  int nbytes);      /* Number of bytes in region */
+
+/* These multiply regions in w=8, w=16 and w=32.  They are much faster
+   than calling galois_single_multiply.  The regions must be long word aligned. */
+
+void galois_w08_region_multiply(char *region,       /* Region to multiply */
+                                  int multby,       /* Number to multiply by */
+                                  int nbytes,       /* Number of bytes in region */
+                                  char *r2,         /* If r2 != NULL, products go here.  
+                                                       Otherwise region is overwritten */
+                                  int add);         /* If (r2 != NULL && add) the produce is XOR'd with r2 */
+
+void galois_w16_region_multiply(char *region,       /* Region to multiply */
+                                  int multby,       /* Number to multiply by */
+                                  int nbytes,       /* Number of bytes in region */
+                                  char *r2,         /* If r2 != NULL, products go here.  
+                                                       Otherwise region is overwritten */
+                                  int add);         /* If (r2 != NULL && add) the produce is XOR'd with r2 */
+
+void galois_w32_region_multiply(char *region,       /* Region to multiply */
+                                  int multby,       /* Number to multiply by */
+                                  int nbytes,       /* Number of bytes in region */
+                                  char *r2,         /* If r2 != NULL, products go here.  
+                                                       Otherwise region is overwritten */
+                                  int add);         /* If (r2 != NULL && add) the produce is XOR'd with r2 */
+
+gf_t* galois_init_field(int w,
+                             int mult_type,
+                             int region_type,
+                             int divide_type,
+                             uint64_t prim_poly,
+                             int arg1,
+                             int arg2);
+
+gf_t* galois_init_composite_field(int w,
+                                int region_type,
+                                int divide_type,
+                                int degree,
+                                gf_t* base_gf);
+
+gf_t * galois_get_field_ptr(int w);
+
+
+#endif
diff --git a/src/erasure-code/jerasure/jerasure.h b/src/erasure-code/jerasure/jerasure/include/jerasure.h
similarity index 85%
rename from src/erasure-code/jerasure/jerasure.h
rename to src/erasure-code/jerasure/jerasure/include/jerasure.h
index 8cc25ca..0836780 100644
--- a/src/erasure-code/jerasure/jerasure.h
+++ b/src/erasure-code/jerasure/jerasure/include/jerasure.h
@@ -1,51 +1,43 @@
-/* jerasure.h - header of kernel procedures
- * James S. Plank
-
-Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure Coding Techniques
-
-Revision 1.2A
-May 24, 2011
-
-James S. Plank
-Department of Electrical Engineering and Computer Science
-University of Tennessee
-Knoxville, TN 37996
-plank at cs.utk.edu
-
-Copyright (c) 2011, James S. Plank
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
- - Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
- - Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in
-   the documentation and/or other materials provided with the
-   distribution.
-
- - Neither the name of the University of Tennessee nor the names of its
-   contributors may be used to endorse or promote products derived
-   from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
-WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-
+/* *
+ * Copyright (c) 2013, James S. Plank and Kevin Greenan
+ * All rights reserved.
+ *
+ * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure
+ * Coding Techniques
+ *
+ * Revision 2.0: Galois Field backend now links to GF-Complete
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  - Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ *  - Neither the name of the University of Tennessee nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
  */
 
+
 #ifndef _JERASURE_H
 #define _JERASURE_H
 
@@ -297,4 +289,6 @@ int *jerasure_matrix_multiply(int *m1, int *m2, int r1, int c1, int r2, int c2,
 
 void jerasure_get_stats(double *fill_in);
 
+int jerasure_autoconf_test();
+
 #endif
diff --git a/src/erasure-code/jerasure/jerasure/include/liberation.h b/src/erasure-code/jerasure/jerasure/include/liberation.h
new file mode 100644
index 0000000..f2fb723
--- /dev/null
+++ b/src/erasure-code/jerasure/jerasure/include/liberation.h
@@ -0,0 +1,47 @@
+/* *
+ * Copyright (c) 2013, James S. Plank and Kevin Greenan
+ * All rights reserved.
+ *
+ * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure
+ * Coding Techniques
+ *
+ * Revision 2.0: Galois Field backend now links to GF-Complete
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  - Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ *  - Neither the name of the University of Tennessee nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef _LIBERATION
+
+extern int *liberation_coding_bitmatrix(int k, int w);
+extern int *liber8tion_coding_bitmatrix(int k);
+extern int *blaum_roth_coding_bitmatrix(int k, int w);
+
+#endif
diff --git a/src/erasure-code/jerasure/jerasure/include/reed_sol.h b/src/erasure-code/jerasure/jerasure/include/reed_sol.h
new file mode 100644
index 0000000..d2d8fe8
--- /dev/null
+++ b/src/erasure-code/jerasure/jerasure/include/reed_sol.h
@@ -0,0 +1,50 @@
+/* *
+ * Copyright (c) 2013, James S. Plank and Kevin Greenan
+ * All rights reserved.
+ *
+ * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure
+ * Coding Techniques
+ *
+ * Revision 2.0: Galois Field backend now links to GF-Complete
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  - Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ *  - Neither the name of the University of Tennessee nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+extern int *reed_sol_vandermonde_coding_matrix(int k, int m, int w);
+extern int *reed_sol_extended_vandermonde_matrix(int rows, int cols, int w);
+extern int *reed_sol_big_vandermonde_distribution_matrix(int rows, int cols, int w);
+
+extern int reed_sol_r6_encode(int k, int w, char **data_ptrs, char **coding_ptrs, int size);
+extern int *reed_sol_r6_coding_matrix(int k, int w);
+
+extern void reed_sol_galois_w08_region_multby_2(char *region, int nbytes);
+extern void reed_sol_galois_w16_region_multby_2(char *region, int nbytes);
+extern void reed_sol_galois_w32_region_multby_2(char *region, int nbytes);
diff --git a/src/erasure-code/jerasure/cauchy.c b/src/erasure-code/jerasure/jerasure/src/cauchy.c
similarity index 91%
rename from src/erasure-code/jerasure/cauchy.c
rename to src/erasure-code/jerasure/jerasure/src/cauchy.c
index c6bb3c0..f63dfb7 100644
--- a/src/erasure-code/jerasure/cauchy.c
+++ b/src/erasure-code/jerasure/jerasure/src/cauchy.c
@@ -1,50 +1,47 @@
-/* cauchy.c
- * James S. Plank
-
-Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure Coding Techniques
-
-Revision 1.2A
-May 24, 2011
-
-James S. Plank
-Department of Electrical Engineering and Computer Science
-University of Tennessee
-Knoxville, TN 37996
-plank at cs.utk.edu
-
-Copyright (c) 2011, James S. Plank
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
- - Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
- - Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in
-   the documentation and/or other materials provided with the
-   distribution.
-
- - Neither the name of the University of Tennessee nor the names of its
-   contributors may be used to endorse or promote products derived
-   from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
-WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
+/* *
+ * Copyright (c) 2014, James S. Plank and Kevin Greenan
+ * All rights reserved.
+ *
+ * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure
+ * Coding Techniques
+ *
+ * Revision 2.0: Galois Field backend now links to GF-Complete
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  - Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ *  - Neither the name of the University of Tennessee nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
 
+/* Jerasure's authors:
 
+   Revision 2.x - 2014: James S. Plank and Kevin M. Greenan
+   Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman.
+   Revision 1.0 - 2007: James S. Plank
  */
 
 #include <stdio.h>
diff --git a/src/erasure-code/jerasure/jerasure/src/galois.c b/src/erasure-code/jerasure/jerasure/src/galois.c
new file mode 100644
index 0000000..398a649
--- /dev/null
+++ b/src/erasure-code/jerasure/jerasure/src/galois.c
@@ -0,0 +1,353 @@
+/* *
+ * Copyright (c) 2014, James S. Plank and Kevin Greenan
+ * All rights reserved.
+ *
+ * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure
+ * Coding Techniques
+ *
+ * Revision 2.0: Galois Field backend now links to GF-Complete
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  - Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ *  - Neither the name of the University of Tennessee nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Jerasure's authors:
+
+   Revision 2.x - 2014: James S. Plank and Kevin M. Greenan
+   Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman.
+   Revision 1.0 - 2007: James S. Plank
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "galois.h"
+
+#define MAX_GF_INSTANCES 64
+gf_t *gfp_array[MAX_GF_INSTANCES] = { 0 };
+int  gfp_is_composite[MAX_GF_INSTANCES] = { 0 };
+
+gf_t *galois_get_field_ptr(int w)
+{
+  if (gfp_array[w] != NULL) {
+    return gfp_array[w];
+  }
+
+  return NULL;
+}
+
+gf_t* galois_init_field(int w,
+                        int mult_type,
+                        int region_type,
+                        int divide_type,
+                        uint64_t prim_poly,
+                        int arg1,
+                        int arg2)
+{
+  int scratch_size;
+  void *scratch_memory;
+  gf_t *gfp;
+
+  if (w <= 0 || w > 32) {
+    fprintf(stderr, "ERROR -- cannot init default Galois field for w=%d\n", w);
+    exit(1);
+  }
+
+  gfp = (gf_t *) malloc(sizeof(gf_t));
+  if (!gfp) {
+    fprintf(stderr, "ERROR -- cannot allocate memory for Galois field w=%d\n", w);
+    exit(1);
+  }
+
+  scratch_size = gf_scratch_size(w, mult_type, region_type, divide_type, arg1, arg2);
+  if (!scratch_size) {
+    fprintf(stderr, "ERROR -- cannot get scratch size for base field w=%d\n", w);
+    exit(1);
+  }
+
+  scratch_memory = malloc(scratch_size);
+  if (!scratch_memory) {
+    fprintf(stderr, "ERROR -- cannot get scratch memory for base field w=%d\n", w);
+    exit(1);
+  }
+
+  if(!gf_init_hard(gfp,
+                   w, 
+                   mult_type, 
+                   region_type, 
+                   divide_type, 
+                   prim_poly, 
+                   arg1, 
+                   arg2, 
+                   NULL, 
+                   scratch_memory))
+  {
+    fprintf(stderr, "ERROR -- cannot init default Galois field for w=%d\n", w);
+    exit(1);
+  }
+
+  gfp_is_composite[w] = 0;
+  return gfp;
+}
+
+gf_t* galois_init_composite_field(int w,
+                                int region_type,
+                                int divide_type,
+                                int degree,
+                                gf_t* base_gf)
+{
+  int scratch_size;
+  void *scratch_memory;
+  gf_t *gfp;
+  
+  if (w <= 0 || w > 32) {
+    fprintf(stderr, "ERROR -- cannot init composite field for w=%d\n", w);
+    exit(1);
+  }
+  
+  gfp = (gf_t *) malloc(sizeof(gf_t));
+  if (!gfp) {
+    fprintf(stderr, "ERROR -- cannot allocate memory for Galois field w=%d\n", w);
+    exit(1);
+  }
+
+  scratch_size = gf_scratch_size(w, GF_MULT_COMPOSITE, region_type, divide_type, degree, 0);
+  if (!scratch_size) {
+    fprintf(stderr, "ERROR -- cannot get scratch size for composite field w=%d\n", w);
+    exit(1);
+  }
+
+  scratch_memory = malloc(scratch_size);
+  if (!scratch_memory) {
+    fprintf(stderr, "ERROR -- cannot get scratch memory for composite field w=%d\n", w);
+    exit(1);
+  }
+
+  if(!gf_init_hard(gfp,
+                   w,
+                   GF_MULT_COMPOSITE,
+                   region_type,
+                   divide_type,
+                   0, 
+                   degree, 
+                   0, 
+                   base_gf,
+                   scratch_memory))
+  {
+    fprintf(stderr, "ERROR -- cannot init default composite field for w=%d\n", w);
+    exit(1);
+  }
+  gfp_is_composite[w] = 1;
+  return gfp;
+}
+
+static void galois_init_default_field(int w)
+{
+  if (w <= 0 || w > 32) {
+    fprintf(stderr, "ERROR -- cannot init default Galois field for w=%d\n", w);
+    exit(1);
+  }
+
+  if (gfp_array[w] == NULL) {
+    gfp_array[w] = (gf_t*)malloc(sizeof(gf_t));
+    if (gfp_array[w] == NULL) {
+      fprintf(stderr, "ERROR -- cannot allocate memory for Galois field w=%d\n", w);
+      exit(1);
+    }
+  }
+
+  if (!gf_init_easy(gfp_array[w], w)) {
+    fprintf(stderr, "ERROR -- cannot init default Galois field for w=%d\n", w);
+    exit(1);
+  }
+}
+
+
+static int is_valid_gf(gf_t *gf, int w)
+{
+  // TODO: I assume we may eventually
+  // want to do w=64 and 128, so w
+  // will be needed to perform this check
+  (void)w;
+
+  if (gf == NULL) {
+    return 0;
+  }
+  if (gf->multiply.w32 == NULL) {
+    return 0;
+  }
+  if (gf->multiply_region.w32 == NULL) {
+    return 0;
+  }
+  if (gf->divide.w32 == NULL) {
+    return 0;
+  }
+  if (gf->inverse.w32 == NULL) {
+    return 0;
+  }
+  if (gf->extract_word.w32 == NULL) {
+    return 0;
+  }
+
+  return 1;
+}
+
+void galois_change_technique(gf_t *gf, int w)
+{
+  if (w <= 0 || w > 32) {
+    fprintf(stderr, "ERROR -- cannot support Galois field for w=%d\n", w);
+    exit(1);
+  }
+
+  if (!is_valid_gf(gf, w)) {
+    fprintf(stderr, "ERROR -- overriding with invalid Galois field for w=%d\n", w);
+    exit(1);
+  }
+
+  if (gfp_array[w] != NULL) {
+    gf_free(gfp_array[w], gfp_is_composite[w]);
+  }
+
+  gfp_array[w] = gf;
+}
+
+int galois_single_multiply(int x, int y, int w)
+{
+  if (x == 0 || y == 0) return 0;
+  
+  if (gfp_array[w] == NULL) {
+    galois_init_default_field(w);
+  }
+
+  if (w <= 32) {
+    return gfp_array[w]->multiply.w32(gfp_array[w], x, y);
+  } else {
+    fprintf(stderr, "ERROR -- Galois field not implemented for w=%d\n", w);
+    return 0;
+  }
+}
+
+int galois_single_divide(int x, int y, int w)
+{
+  if (x == 0) return 0;
+  if (y == 0) return -1;
+
+  if (gfp_array[w] == NULL) {
+    galois_init_default_field(w);
+  }
+
+  if (w <= 32) {
+    return gfp_array[w]->divide.w32(gfp_array[w], x, y);
+  } else {
+    fprintf(stderr, "ERROR -- Galois field not implemented for w=%d\n", w);
+    return 0;
+  }
+}
+
+void galois_w08_region_multiply(char *region,      /* Region to multiply */
+                                  int multby,       /* Number to multiply by */
+                                  int nbytes,        /* Number of bytes in region */
+                                  char *r2,          /* If r2 != NULL, products go here */
+                                  int add)
+{
+  if (gfp_array[8] == NULL) {
+    galois_init_default_field(8);
+  }
+  gfp_array[8]->multiply_region.w32(gfp_array[8], region, r2, multby, nbytes, add);
+}
+
+void galois_w16_region_multiply(char *region,      /* Region to multiply */
+                                  int multby,       /* Number to multiply by */
+                                  int nbytes,        /* Number of bytes in region */
+                                  char *r2,          /* If r2 != NULL, products go here */
+                                  int add)
+{
+  if (gfp_array[16] == NULL) {
+    galois_init_default_field(16);
+  }
+  gfp_array[16]->multiply_region.w32(gfp_array[16], region, r2, multby, nbytes, add);
+}
+
+
+void galois_w32_region_multiply(char *region,      /* Region to multiply */
+                                  int multby,       /* Number to multiply by */
+                                  int nbytes,        /* Number of bytes in region */
+                                  char *r2,          /* If r2 != NULL, products go here */
+                                  int add)
+{
+  if (gfp_array[32] == NULL) {
+    galois_init_default_field(32);
+  }
+  gfp_array[32]->multiply_region.w32(gfp_array[32], region, r2, multby, nbytes, add);
+}
+
+void galois_w8_region_xor(void *src, void *dest, int nbytes)
+{
+  if (gfp_array[8] == NULL) {
+    galois_init_default_field(8);
+  }
+  gfp_array[8]->multiply_region.w32(gfp_array[32], src, dest, 1, nbytes, 1);
+}
+
+void galois_w16_region_xor(void *src, void *dest, int nbytes)
+{
+  if (gfp_array[16] == NULL) {
+    galois_init_default_field(16);
+  }
+  gfp_array[16]->multiply_region.w32(gfp_array[16], src, dest, 1, nbytes, 1);
+}
+
+void galois_w32_region_xor(void *src, void *dest, int nbytes)
+{
+  if (gfp_array[32] == NULL) {
+    galois_init_default_field(32);
+  }
+  gfp_array[32]->multiply_region.w32(gfp_array[32], src, dest, 1, nbytes, 1);
+}
+
+void galois_region_xor(char *src, char *dest, int nbytes)
+{
+  if (nbytes >= 16) {
+    galois_w32_region_xor(src, dest, nbytes);
+  } else {
+    int i = 0;
+    for (i = 0; i < nbytes; i++) {
+      *dest ^= *src;
+      dest++;
+      src++;
+    } 
+  }
+}
+
+int galois_inverse(int y, int w)
+{
+  if (y == 0) return -1;
+  return galois_single_divide(1, y, w);
+}
diff --git a/src/erasure-code/jerasure/jerasure.c b/src/erasure-code/jerasure/jerasure/src/jerasure.c
similarity index 93%
rename from src/erasure-code/jerasure/jerasure.c
rename to src/erasure-code/jerasure/jerasure/src/jerasure.c
index e5df475..bb577af 100644
--- a/src/erasure-code/jerasure/jerasure.c
+++ b/src/erasure-code/jerasure/jerasure/src/jerasure.c
@@ -1,49 +1,47 @@
-/* jerasure.c
- * James S. Plank
-
-Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure Coding Techniques
-
-Revision 1.2A
-May 24, 2011
-
-James S. Plank
-Department of Electrical Engineering and Computer Science
-University of Tennessee
-Knoxville, TN 37996
-plank at cs.utk.edu
-
-Copyright (c) 2011, James S. Plank
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
- - Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
- - Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in
-   the documentation and/or other materials provided with the
-   distribution.
-
- - Neither the name of the University of Tennessee nor the names of its
-   contributors may be used to endorse or promote products derived
-   from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
-WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
+/* *
+ * Copyright (c) 2014, James S. Plank and Kevin Greenan
+ * All rights reserved.
+ *
+ * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure
+ * Coding Techniques
+ *
+ * Revision 2.0: Galois Field backend now links to GF-Complete
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  - Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ *  - Neither the name of the University of Tennessee nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Jerasure's authors:
 
+   Revision 2.x - 2014: James S. Plank and Kevin M. Greenan
+   Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman.
+   Revision 1.0 - 2007: James S. Plank
  */
 
 #include <stdio.h>
@@ -276,7 +274,7 @@ int *jerasure_matrix_to_bitmatrix(int k, int m, int w, int *matrix)
   int rowelts, rowindex, colindex, elt, i, j, l, x;
 
   bitmatrix = talloc(int, k*m*w*w);
-  if (bitmatrix == NULL) { return NULL; }
+  if (matrix == NULL) { return NULL; }
 
   rowelts = k * w;
   rowindex = 0;
@@ -348,7 +346,7 @@ void jerasure_bitmatrix_dotprod(int k, int w, int *bitmatrix_row,
               jerasure_total_memcpy_bytes += packetsize;
               pstarted = 1;
             } else {
-              galois_region_xor(pptr, dptr, pptr, packetsize);
+              galois_region_xor(dptr, pptr, packetsize);
               jerasure_total_xor_bytes += packetsize;
             }
           }
@@ -367,7 +365,7 @@ void jerasure_do_parity(int k, char **data_ptrs, char *parity_ptr, int size)
   jerasure_total_memcpy_bytes += size;
   
   for (i = 1; i < k; i++) {
-    galois_region_xor(data_ptrs[i], parity_ptr, parity_ptr, size);
+    galois_region_xor(data_ptrs[i], parity_ptr, size);
     jerasure_total_xor_bytes += size;
   }
 }
@@ -606,7 +604,7 @@ void jerasure_matrix_dotprod(int k, int w, int *matrix_row,
         jerasure_total_memcpy_bytes += size;
         init = 1;
       } else {
-        galois_region_xor(sptr, dptr, dptr, size);
+        galois_region_xor(sptr, dptr, size);
         jerasure_total_xor_bytes += size;
       }
     }
@@ -839,11 +837,7 @@ static int **jerasure_generate_decoding_schedule(int k, int m, int w, int *bitma
   row_ids = talloc(int, k+m);
   ind_to_row = talloc(int, k+m);
 
-  if (set_up_ids_for_scheduled_decoding(k, m, erasures, row_ids, ind_to_row) < 0) {
-    free(row_ids);
-    free(ind_to_row);
-    return NULL;
-  }
+  if (set_up_ids_for_scheduled_decoding(k, m, erasures, row_ids, ind_to_row) < 0) return NULL;
 
   /* Now, we're going to create one decoding matrix which is going to 
      decode everything with one call.  The hope is that the scheduler
@@ -1180,7 +1174,7 @@ void jerasure_do_scheduled_operations(char **ptrs, int **operations, int packets
       operations[op][2], 
       operations[op][3]); 
       printf("xor(0x%x, 0x%x -> 0x%x, %d)\n", sptr, dptr, dptr, packetsize); */
-      galois_region_xor(sptr, dptr, dptr, packetsize);
+      galois_region_xor(sptr, dptr, packetsize);
       jerasure_total_xor_bytes += packetsize;
     } else {
 /*      printf("memcpy(0x%x <- 0x%x)\n", dptr, sptr); */
@@ -1378,3 +1372,16 @@ void jerasure_bitmatrix_encode(int k, int m, int w, int *bitmatrix,
   }
 }
 
+/*
+ * Exported function for use by autoconf to perform quick 
+ * spot-check.
+ */
+int jerasure_autoconf_test()
+{
+  int x = galois_single_multiply(1, 2, 8);
+  if (x != 2) {
+    return -1;
+  }
+  return 0;
+}
+
diff --git a/src/erasure-code/jerasure/liberation.c b/src/erasure-code/jerasure/jerasure/src/liberation.c
similarity index 71%
rename from src/erasure-code/jerasure/liberation.c
rename to src/erasure-code/jerasure/jerasure/src/liberation.c
index beca10d..11a1c4f 100644
--- a/src/erasure-code/jerasure/liberation.c
+++ b/src/erasure-code/jerasure/jerasure/src/liberation.c
@@ -1,50 +1,47 @@
-/* liberation.c
- * James S. Plank
-
-Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure Coding Techniques
-
-Revision 1.2A
-May 24, 2011
-
-James S. Plank
-Department of Electrical Engineering and Computer Science
-University of Tennessee
-Knoxville, TN 37996
-plank at cs.utk.edu
-
-Copyright (c) 2011, James S. Plank
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
- - Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
- - Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in
-   the documentation and/or other materials provided with the
-   distribution.
-
- - Neither the name of the University of Tennessee nor the names of its
-   contributors may be used to endorse or promote products derived
-   from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
-WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
+/* *
+ * Copyright (c) 2014, James S. Plank and Kevin Greenan
+ * All rights reserved.
+ *
+ * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure
+ * Coding Techniques
+ *
+ * Revision 2.0: Galois Field backend now links to GF-Complete
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  - Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ *  - Neither the name of the University of Tennessee nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
 
+/* Jerasure's authors:
 
+   Revision 2.x - 2014: James S. Plank and Kevin M. Greenan
+   Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman.
+   Revision 1.0 - 2007: James S. Plank
  */
 
 #include <stdio.h>
diff --git a/src/erasure-code/jerasure/reed_sol.c b/src/erasure-code/jerasure/jerasure/src/reed_sol.c
similarity index 58%
rename from src/erasure-code/jerasure/reed_sol.c
rename to src/erasure-code/jerasure/jerasure/src/reed_sol.c
index 003eb41..c0dfe83 100644
--- a/src/erasure-code/jerasure/reed_sol.c
+++ b/src/erasure-code/jerasure/jerasure/src/reed_sol.c
@@ -1,55 +1,54 @@
-/* reed_sol.c
- * James S. Plank
-
-Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure Coding Techniques
-
-Revision 1.2A
-May 24, 2011
-
-James S. Plank
-Department of Electrical Engineering and Computer Science
-University of Tennessee
-Knoxville, TN 37996
-plank at cs.utk.edu
-
-Copyright (c) 2011, James S. Plank
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
- - Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
- - Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in
-   the documentation and/or other materials provided with the
-   distribution.
-
- - Neither the name of the University of Tennessee nor the names of its
-   contributors may be used to endorse or promote products derived
-   from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
-WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
+/* *
+ * Copyright (c) 2014, James S. Plank and Kevin Greenan
+ * All rights reserved.
+ *
+ * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure
+ * Coding Techniques
+ *
+ * Revision 2.0: Galois Field backend now links to GF-Complete
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  - Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ *  - Neither the name of the University of Tennessee nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+ * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Jerasure's authors:
 
+   Revision 2.x - 2014: James S. Plank and Kevin M. Greenan
+   Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman.
+   Revision 1.0 - 2007: James S. Plank
  */
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
+#include <gf_complete.h>
 #include "galois.h"
 #include "jerasure.h"
 #include "reed_sol.h"
@@ -98,118 +97,52 @@ int *reed_sol_vandermonde_coding_matrix(int k, int m, int w)
   return dist;
 }
 
-static int prim32 = -1;
-
-#define rgw32_mask(v) ((v) & 0x80000000)
-
-void reed_sol_galois_w32_region_multby_2(char *region, int nbytes) 
-{
-  int *l1;
-  int *ltop;
-  char *ctop;
-
-  if (prim32 == -1) prim32 = galois_single_multiply((1 << 31), 2, 32);
-
-  ctop = region + nbytes;
-  ltop = (int *) ctop;
-  l1 = (int *) region;
-
-  while (l1 < ltop) {
-    *l1 = ((*l1) << 1) ^ ((*l1 & 0x80000000) ? prim32 : 0);
-    l1++;
-  }
-}
-
 static int prim08 = -1;
-static int mask08_1 = -1;
-static int mask08_2 = -1;
+static gf_t GF08;
 
 void reed_sol_galois_w08_region_multby_2(char *region, int nbytes)
 {
-  unsigned int *l1;
-  unsigned int *ltop;
-  char *ctop;
-  unsigned int tmp, tmp2;
-  
-
   if (prim08 == -1) {
-    tmp = galois_single_multiply((1 << 7), 2, 8);
-    prim08 = 0;
-    while (tmp != 0) {
-      prim08 |= tmp;
-      tmp = (tmp << 8);
-    }
-    tmp = (1 << 8) - 2;
-    mask08_1 = 0;
-    while (tmp != 0) {
-      mask08_1 |= tmp;
-      tmp = (tmp << 8);
-    }
-    tmp = (1 << 7);
-    mask08_2 = 0;
-    while (tmp != 0) {
-      mask08_2 |= tmp;
-      tmp = (tmp << 8);
+    prim08 = galois_single_multiply((1 << 7), 2, 8);
+    if (!gf_init_hard(&GF08, 8, GF_MULT_BYTWO_b, GF_REGION_DEFAULT, GF_DIVIDE_DEFAULT,
+                      prim08, 0, 0, NULL, NULL)) {
+      fprintf(stderr, "Error: Can't initialize the GF for reed_sol_galois_w08_region_multby_2\n");
+      exit(1);
     }
   }
-
-  ctop = region + nbytes;
-  ltop = (unsigned int *) ctop;
-  l1 = (unsigned int *) region;
-
-  while (l1 < ltop) {
-    tmp = ((*l1) << 1) & mask08_1;
-    tmp2 = (*l1) & mask08_2;
-    tmp2 = ((tmp2 << 1) - (tmp2 >> 7));
-    *l1 = (tmp ^ (tmp2 & prim08));
-    l1++;
-  }
+  GF08.multiply_region.w32(&GF08, region, region, 2, nbytes, 0);
 }
 
 static int prim16 = -1;
-static int mask16_1 = -1;
-static int mask16_2 = -1;
+static gf_t GF16;
 
 void reed_sol_galois_w16_region_multby_2(char *region, int nbytes)
 {
-  unsigned int *l1;
-  unsigned int *ltop;
-  char *ctop;
-  unsigned int tmp, tmp2;
-  
-
   if (prim16 == -1) {
-    tmp = galois_single_multiply((1 << 15), 2, 16);
-    prim16 = 0;
-    while (tmp != 0) {
-      prim16 |= tmp;
-      tmp = (tmp << 16);
-    }
-    tmp = (1 << 16) - 2;
-    mask16_1 = 0;
-    while (tmp != 0) {
-      mask16_1 |= tmp;
-      tmp = (tmp << 16);
-    }
-    tmp = (1 << 15);
-    mask16_2 = 0;
-    while (tmp != 0) {
-      mask16_2 |= tmp;
-      tmp = (tmp << 16);
+    prim16 = galois_single_multiply((1 << 15), 2, 16);
+    if (!gf_init_hard(&GF16, 16, GF_MULT_BYTWO_b, GF_REGION_DEFAULT, GF_DIVIDE_DEFAULT,
+                      prim16, 0, 0, NULL, NULL)) {
+      fprintf(stderr, "Error: Can't initialize the GF for reed_sol_galois_w16_region_multby_2\n");
+      exit(1);
     }
   }
+  GF16.multiply_region.w32(&GF16, region, region, 2, nbytes, 0);
+}
 
-  ctop = region + nbytes;
-  ltop = (unsigned int *) ctop;
-  l1 = (unsigned int *) region;
+static int prim32 = -1;
+static gf_t GF32;
 
-  while (l1 < ltop) {
-    tmp = ((*l1) << 1) & mask16_1;
-    tmp2 = (*l1) & mask16_2;
-    tmp2 = ((tmp2 << 1) - (tmp2 >> 15));
-    *l1 = (tmp ^ (tmp2 & prim16));
-    l1++;
+void reed_sol_galois_w32_region_multby_2(char *region, int nbytes)
+{
+  if (prim32 == -1) {
+    prim32 = galois_single_multiply((1 << 31), 2, 32);
+    if (!gf_init_hard(&GF32, 32, GF_MULT_BYTWO_b, GF_REGION_DEFAULT, GF_DIVIDE_DEFAULT,
+                      prim32, 0, 0, NULL, NULL)) {
+      fprintf(stderr, "Error: Can't initialize the GF for reed_sol_galois_w32_region_multby_2\n");
+      exit(1);
+    }
   }
+  GF32.multiply_region.w32(&GF32, region, region, 2, nbytes, 0);
 }
 
 int reed_sol_r6_encode(int k, int w, char **data_ptrs, char **coding_ptrs, int size)
@@ -220,7 +153,7 @@ int reed_sol_r6_encode(int k, int w, char **data_ptrs, char **coding_ptrs, int s
 
   memcpy(coding_ptrs[0], data_ptrs[0], size);
 
-  for (i = 1; i < k; i++) galois_region_xor(coding_ptrs[0], data_ptrs[i], coding_ptrs[0], size);
+  for (i = 1; i < k; i++) galois_region_xor(data_ptrs[i], coding_ptrs[0], size);
 
   /* Next, put the sum of (2^j)*Dj into coding region 1 */
 
@@ -234,7 +167,7 @@ int reed_sol_r6_encode(int k, int w, char **data_ptrs, char **coding_ptrs, int s
       default: return 0;
     }
 
-    galois_region_xor(coding_ptrs[1], data_ptrs[i], coding_ptrs[1], size);
+    galois_region_xor(data_ptrs[i], coding_ptrs[1], size);
   }
   return 1;
 }
diff --git a/src/erasure-code/jerasure/liberation.h b/src/erasure-code/jerasure/liberation.h
deleted file mode 100644
index ee176e8..0000000
--- a/src/erasure-code/jerasure/liberation.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* liberation.h
- * James S. Plank
-
-Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure Coding Techniques
-
-Revision 1.2A
-May 24, 2011
-
-James S. Plank
-Department of Electrical Engineering and Computer Science
-University of Tennessee
-Knoxville, TN 37996
-plank at cs.utk.edu
-
-Copyright (c) 2011, James S. Plank
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
- - Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
- - Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in
-   the documentation and/or other materials provided with the
-   distribution.
-
- - Neither the name of the University of Tennessee nor the names of its
-   contributors may be used to endorse or promote products derived
-   from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
-WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-
-
- */
-
-#ifndef _LIBERATION
-
-extern int *liberation_coding_bitmatrix(int k, int w);
-extern int *liber8tion_coding_bitmatrix(int k);
-extern int *blaum_roth_coding_bitmatrix(int k, int w);
-
-#endif
diff --git a/src/erasure-code/jerasure/reed_sol.h b/src/erasure-code/jerasure/reed_sol.h
deleted file mode 100644
index 741c317..0000000
--- a/src/erasure-code/jerasure/reed_sol.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* reed_sol.h
- * James S. Plank
-
-Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure Coding Techniques
-
-Revision 1.2A
-May 24, 2011
-
-James S. Plank
-Department of Electrical Engineering and Computer Science
-University of Tennessee
-Knoxville, TN 37996
-plank at cs.utk.edu
-
-Copyright (c) 2011, James S. Plank
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
- - Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
- - Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in
-   the documentation and/or other materials provided with the
-   distribution.
-
- - Neither the name of the University of Tennessee nor the names of its
-   contributors may be used to endorse or promote products derived
-   from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
-WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-
-
- */
-
-extern int *reed_sol_vandermonde_coding_matrix(int k, int m, int w);
-extern int *reed_sol_extended_vandermonde_matrix(int rows, int cols, int w);
-extern int *reed_sol_big_vandermonde_distribution_matrix(int rows, int cols, int w);
-
-extern int reed_sol_r6_encode(int k, int w, char **data_ptrs, char **coding_ptrs, int size);
-extern int *reed_sol_r6_coding_matrix(int k, int w);
-
-extern void reed_sol_galois_w08_region_multby_2(char *region, int nbytes);
-extern void reed_sol_galois_w16_region_multby_2(char *region, int nbytes);
-extern void reed_sol_galois_w32_region_multby_2(char *region, int nbytes);
diff --git a/src/erasure-code/jerasure/vectorop.h b/src/erasure-code/jerasure/vectorop.h
deleted file mode 100644
index 5135f82..0000000
--- a/src/erasure-code/jerasure/vectorop.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// -*- 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) 2014 CERN/Switzerland
- *               
- *
- * Authors: Andreas-Joachim Peters <andreas.joachim.peters at cern.ch> 
- *          
- *
- *  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.
- * 
- */
-
-#ifndef CEPH_VECTOROP_H
-#define	CEPH_VECTOROP_H
-
-// -------------------------------------------------------------------------
-// constant used in the block alignment function to allow for vector ops
-// -------------------------------------------------------------------------
-#define LARGEST_VECTOR_WORDSIZE 16
-
-// -------------------------------------------------------------------------
-// switch to 128-bit XOR operations if possible 
-// -------------------------------------------------------------------------
-#if __GNUC__ > 4 || \
-  (__GNUC__ == 4 && (__GNUC_MINOR__ >= 4) ) || \
-  (__clang__ == 1 )
-
-#ifdef VECTOROP_DEBUG
-#pragma message "* using 128-bit vector operations in " __FILE__ 
-#endif
-// -------------------------------------------------------------------------
-// use 128-bit pointer
-// -------------------------------------------------------------------------
-typedef long vector_op_t __attribute__ ((vector_size (16)));
-#define VECTOR_WORDSIZE 16
-#else
-// -------------------------------------------------------------------------
-// use 64-bit pointer
-// -------------------------------------------------------------------------
-typedef unsigned long long vector_op_t;
-#define VECTOR_WORDSIZE 8
-#endif
-
-#endif	/* CEPH_VECTOROP_H */
-
diff --git a/src/global/global_init.cc b/src/global/global_init.cc
index 5e56e8f..7b20343 100644
--- a/src/global/global_init.cc
+++ b/src/global/global_init.cc
@@ -56,8 +56,10 @@ static const char* c_str_or_null(const std::string &str)
   return str.c_str();
 }
 
-void global_init(std::vector < const char * > *alt_def_args, std::vector < const char* >& args,
-	       uint32_t module_type, code_environment_t code_env, int flags)
+void global_pre_init(std::vector < const char * > *alt_def_args,
+		     std::vector < const char* >& args,
+		     uint32_t module_type, code_environment_t code_env,
+		     int flags)
 {
   // You can only call global_init once.
   assert(!g_ceph_context);
@@ -104,10 +106,17 @@ void global_init(std::vector < const char * > *alt_def_args, std::vector < const
   // Expand metavariables. Invoke configuration observers.
   conf->apply_changes(NULL);
 
-  g_lockdep = cct->_conf->lockdep;
-
   // Now we're ready to complain about config file parse errors
   complain_about_parse_errors(cct, &parse_errors);
+}
+
+void global_init(std::vector < const char * > *alt_def_args,
+		 std::vector < const char* >& args,
+		 uint32_t module_type, code_environment_t code_env, int flags)
+{
+  global_pre_init(alt_def_args, args, module_type, code_env, flags);
+
+  g_lockdep = g_ceph_context->_conf->lockdep;
 
   // signal stuff
   int siglist[] = { SIGPIPE, 0 };
@@ -130,14 +139,13 @@ void global_init(std::vector < const char * > *alt_def_args, std::vector < const
   }
 
   if (g_lockdep) {
-    dout(1) << "lockdep is enabled" << dendl;
-    lockdep_register_ceph_context(cct);
+    lockdep_register_ceph_context(g_ceph_context);
   }
-  register_assert_context(cct);
+  register_assert_context(g_ceph_context);
 
   // call all observers now.  this has the side-effect of configuring
   // and opening the log file immediately.
-  conf->call_all_observers();
+  g_conf->call_all_observers();
 
   if (code_env == CODE_ENVIRONMENT_DAEMON && !(flags & CINIT_FLAG_NO_DAEMON_ACTIONS))
     output_ceph_version();
@@ -202,14 +210,14 @@ void global_init_postfork_start(CephContext *cct)
    * guarantee that nobody ever writes to stdout, even though they're not
    * supposed to.
    */
-  TEMP_FAILURE_RETRY(close(STDIN_FILENO));
+  VOID_TEMP_FAILURE_RETRY(close(STDIN_FILENO));
   if (open("/dev/null", O_RDONLY) < 0) {
     int err = errno;
     derr << "global_init_daemonize: open(/dev/null) failed: error "
 	 << err << dendl;
     exit(1);
   }
-  TEMP_FAILURE_RETRY(close(STDOUT_FILENO));
+  VOID_TEMP_FAILURE_RETRY(close(STDOUT_FILENO));
   if (open("/dev/null", O_RDONLY) < 0) {
     int err = errno;
     derr << "global_init_daemonize: open(/dev/null) failed: error "
@@ -256,7 +264,7 @@ void global_init_chdir(const CephContext *cct)
  */
 int global_init_shutdown_stderr(CephContext *cct)
 {
-  TEMP_FAILURE_RETRY(close(STDERR_FILENO));
+  VOID_TEMP_FAILURE_RETRY(close(STDERR_FILENO));
   if (open("/dev/null", O_RDONLY) < 0) {
     int err = errno;
     derr << "global_init_shutdown_stderr: open(/dev/null) failed: error "
diff --git a/src/global/global_init.h b/src/global/global_init.h
index 67586e4..54c8d3d 100644
--- a/src/global/global_init.h
+++ b/src/global/global_init.h
@@ -30,8 +30,16 @@ class CephContext;
  * daemons and utility programs need to call. It takes care of a lot of
  * initialization, including setting up g_ceph_context.
  */
-void global_init(std::vector < const char * > *alt_def_args, std::vector < const char* >& args,
-	       uint32_t module_type, code_environment_t code_env, int flags);
+void global_init(std::vector < const char * > *alt_def_args,
+		 std::vector < const char* >& args,
+		 uint32_t module_type, code_environment_t code_env, int flags);
+
+// just the first half; enough to get config parsed but doesn't start up the
+// cct or log.
+void global_pre_init(std::vector < const char * > *alt_def_args,
+		     std::vector < const char* >& args,
+		     uint32_t module_type, code_environment_t code_env,
+		     int flags);
 
 /*
  * perform all of the steps that global_init_daemonize performs just prior
diff --git a/src/global/pidfile.cc b/src/global/pidfile.cc
index 0de51d6..3b8962a 100644
--- a/src/global/pidfile.cc
+++ b/src/global/pidfile.cc
@@ -57,7 +57,7 @@ int pidfile_write(const md_config_t *conf)
   if (ret < 0) {
     derr << "write_pid_file: failed to write to pid file '"
 	 << pid_file << "': " << cpp_strerror(ret) << dendl;
-    TEMP_FAILURE_RETRY(::close(fd));
+    VOID_TEMP_FAILURE_RETRY(::close(fd));
     return ret;
   }
   if (TEMP_FAILURE_RETRY(::close(fd))) {
@@ -82,7 +82,7 @@ int pidfile_remove(void)
   char buf[32];
   memset(buf, 0, sizeof(buf));
   ssize_t res = safe_read(fd, buf, sizeof(buf));
-  TEMP_FAILURE_RETRY(::close(fd));
+  VOID_TEMP_FAILURE_RETRY(::close(fd));
   if (res < 0)
     return res;
   int a = atoi(buf);
diff --git a/src/include/ceph_features.h b/src/include/ceph_features.h
index f2b8a85..d6c7d6f 100644
--- a/src/include/ceph_features.h
+++ b/src/include/ceph_features.h
@@ -50,6 +50,7 @@
 #define CEPH_FEATURE_MDS_INLINE_DATA     (1ULL<<40)
 #define CEPH_FEATURE_CRUSH_TUNABLES3     (1ULL<<41)
 #define CEPH_FEATURE_OSD_PRIMARY_AFFINITY (1ULL<<41)  /* overlap w/ tunables3 */
+#define CEPH_FEATURE_MSGR_KEEPALIVE2   (1ULL<<42)
 
 /*
  * The introduction of CEPH_FEATURE_OSD_SNAPMAPPER caused the feature
@@ -120,6 +121,7 @@ static inline unsigned long long ceph_sanitize_features(unsigned long long f) {
 	 CEPH_FEATURE_MDS_INLINE_DATA |	    \
 	 CEPH_FEATURE_CRUSH_TUNABLES3 |	    \
 	 CEPH_FEATURE_OSD_PRIMARY_AFFINITY |	\
+	 CEPH_FEATURE_MSGR_KEEPALIVE2 |	\
 	 0ULL)
 
 #define CEPH_FEATURES_SUPPORTED_DEFAULT  CEPH_FEATURES_ALL
diff --git a/src/include/cephfs/libcephfs.h b/src/include/cephfs/libcephfs.h
index e600605..282f41b 100644
--- a/src/include/cephfs/libcephfs.h
+++ b/src/include/cephfs/libcephfs.h
@@ -86,6 +86,7 @@ typedef struct Fh Fh;
 
 #endif /* ! __cplusplus */
 
+struct inodeno_t;
 struct Inode;
 typedef struct Inode Inode;
 
@@ -1208,6 +1209,11 @@ int ceph_debug_get_file_caps(struct ceph_mount_info *cmount, const char *path);
 /* Low Level */
 struct Inode *ceph_ll_get_inode(struct ceph_mount_info *cmount,
 				vinodeno_t vino);
+int ceph_ll_lookup_inode(
+    struct ceph_mount_info *cmount,
+    struct inodeno_t ino,
+    Inode **inode);
+
 /**
  * Get the root inode of FS. Increase counter of references for root Inode. You must call ceph_ll_forget for it!
  *
diff --git a/src/include/compat.h b/src/include/compat.h
index dc15533..25d3d76 100644
--- a/src/include/compat.h
+++ b/src/include/compat.h
@@ -26,6 +26,14 @@
   __result; })
 #endif
 
+#ifdef __cplusplus
+# define VOID_TEMP_FAILURE_RETRY(expression) \
+   static_cast<void>(TEMP_FAILURE_RETRY(expression))
+#else
+# define VOID_TEMP_FAILURE_RETRY(expression) \
+   do { (void)TEMP_FAILURE_RETRY(expression); } while (0)
+#endif
+
 #if defined(__FreeBSD__) || defined(__APPLE__)
 #define lseek64(fd, offset, whence) lseek(fd, offset, whence)
 #endif
diff --git a/src/include/frag.h b/src/include/frag.h
index fbe5b43..f98765a 100644
--- a/src/include/frag.h
+++ b/src/include/frag.h
@@ -295,7 +295,7 @@ public:
       int nb = get_split(t);
       if (nb) 
 	t.split(nb, q);   // queue up children
-      else 
+      else if (x.contains(t))
 	ls.push_back(t);  // not spit, it's a leaf.
     }
   }
diff --git a/src/include/msgr.h b/src/include/msgr.h
index 5854682..a1ad993 100644
--- a/src/include/msgr.h
+++ b/src/include/msgr.h
@@ -90,6 +90,8 @@ struct ceph_entity_inst {
 #define CEPH_MSGR_TAG_BADAUTHORIZER 11 /* bad authorizer */
 #define CEPH_MSGR_TAG_FEATURES      12 /* insufficient features */
 #define CEPH_MSGR_TAG_SEQ           13 /* 64-bit int follows with seen seq number */
+#define CEPH_MSGR_TAG_KEEPALIVE2     14
+#define CEPH_MSGR_TAG_KEEPALIVE2_ACK 15  /* keepalive reply */
 
 
 /*
diff --git a/src/include/rados/librados.h b/src/include/rados/librados.h
index f0d45af..0a3ef2b 100644
--- a/src/include/rados/librados.h
+++ b/src/include/rados/librados.h
@@ -522,6 +522,14 @@ int rados_cluster_stat(rados_t cluster, struct rados_cluster_stat_t *result);
 int rados_cluster_fsid(rados_t cluster, char *buf, size_t len);
 
 /**
+ * Get/wait for the most recent osdmap
+ * 
+ * @param cluster the cluster to shutdown
+ * @returns 0 on sucess, negative error code on failure
+ */
+int rados_wait_for_latest_osdmap(rados_t cluster);
+
+/**
  * @defgroup librados_h_pools Pools
  *
  * RADOS pools are separate namespaces for objects. Pools may have
@@ -734,6 +742,9 @@ int rados_ioctx_pool_set_auid(rados_ioctx_t io, uint64_t auid);
  */
 int rados_ioctx_pool_get_auid(rados_ioctx_t io, uint64_t *auid);
 
+int rados_ioctx_pool_requires_alignment(rados_ioctx_t io);
+uint64_t rados_ioctx_pool_required_alignment(rados_ioctx_t io);
+
 /**
  * Get the pool id of the io context
  *
diff --git a/src/include/types.h b/src/include/types.h
index 974edee..ffb0202 100644
--- a/src/include/types.h
+++ b/src/include/types.h
@@ -235,7 +235,7 @@ WRITE_RAW_ENCODER(ceph_mon_statfs_reply)
 // some basic types
 
 // NOTE: these must match ceph_fs.h typedefs
-typedef uint64_t tid_t;         // transaction id
+typedef uint64_t ceph_tid_t; // transaction id
 typedef uint64_t version_t;
 typedef __u32 epoch_t;       // map epoch  (32bits -> 13 epochs/second for 10 years)
 
diff --git a/src/init-ceph.in b/src/init-ceph.in
index dac00d9..846bd57 100644
--- a/src/init-ceph.in
+++ b/src/init-ceph.in
@@ -12,6 +12,8 @@
 # Description:       Enable Ceph distributed file system services.
 ### END INIT INFO
 
+. /lib/lsb/init-functions
+
 # if we start up as ./mkcephfs, assume everything else is in the
 # current directory too.
 if [ `dirname $0` = "." ] && [ $PWD != "/etc/init.d" ]; then
@@ -323,9 +325,9 @@ for name in $what; do
 		    get_conf osd_location_hook "$BINDIR/ceph-crush-location" "osd crush location hook"
 		    osd_location=`$osd_location_hook --cluster ceph --id $id --type osd`
 		    get_conf osd_weight "" "osd crush initial weight"
-		    defaultweight="$(df -P -k $osd_data/. | tail -1 | awk '{ d=$2/1073741824 ; r = sprintf(\"%.2f\", d); print r }')"
+		    defaultweight="$(df -P -k $osd_data/. | tail -1 | awk '{ print sprintf("%.2f",$2/1073741824) }')"
 		    get_conf osd_keyring "$osd_data/keyring" "keyring"
-		    do_cmd "timeout 10 $BINDIR/ceph -c $conf --name=osd.$id --keyring=$osd_keyring osd crush create-or-move -- $id ${osd_weight:-${defaultweight:-1}} $osd_location"
+		    do_cmd "timeout 30 $BINDIR/ceph -c $conf --name=osd.$id --keyring=$osd_keyring osd crush create-or-move -- $id ${osd_weight:-${defaultweight:-1}} $osd_location"
 		fi
 	    fi
 
diff --git a/src/init-radosgw b/src/init-radosgw
index caa05cb..c38ddad 100644
--- a/src/init-radosgw
+++ b/src/init-radosgw
@@ -6,6 +6,7 @@
 # Default-Start:     2 3 4 5
 # Default-Stop:      0 1 6
 # Short-Description: radosgw RESTful rados gateway
+# Description: radosgw RESTful rados gateway
 ### END INIT INFO
 
 PATH=/sbin:/bin:/usr/bin
diff --git a/src/init-rbdmap b/src/init-rbdmap
index 01fe0fb..a6f47b3 100755
--- a/src/init-rbdmap
+++ b/src/init-rbdmap
@@ -7,8 +7,11 @@
 
 ### BEGIN INIT INFO
 # Provides:          rbdmap
-# Required-Start:    $network
-# Required-Stop:     $network
+# Required-Start:    $network $remote_fs
+# Required-Stop:     $network $remote_fs
+# Should-Start:      ceph
+# Should-Stop:       ceph
+# X-Start-Before:    $x-display-manager
 # Default-Start:     2 3 4 5
 # Default-Stop:      0 1 6
 # Short-Description: Ceph RBD Mapping
@@ -93,6 +96,11 @@ case "$1" in
 	do_unmap
 	;;
 
+  restart|force-reload)
+	$0 stop
+	$0 start
+	;;
+
   reload)
 	do_map
 	;;
@@ -102,7 +110,7 @@ case "$1" in
 	;;
 
   *)
-	log_success_msg "Usage: rbdmap {start|stop|reload|status}"
+	log_success_msg "Usage: rbdmap {start|stop|restart|force-reload|reload|status}"
 	exit 1
 	;;
 esac
diff --git a/src/java/Makefile.in b/src/java/Makefile.in
index 67670b9..0e967f6 100644
--- a/src/java/Makefile.in
+++ b/src/java/Makefile.in
@@ -52,10 +52,10 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_classpath.m4 \
 	$(top_srcdir)/m4/ax_c_var_func.m4 \
 	$(top_srcdir)/m4/ax_check_compile_flag.m4 \
 	$(top_srcdir)/m4/ax_cxx_static_cast.m4 \
-	$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
-	$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
-	$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
-	$(top_srcdir)/configure.ac
+	$(top_srcdir)/m4/ax_intel.m4 $(top_srcdir)/m4/libtool.m4 \
+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+	$(top_srcdir)/m4/pkg.m4 $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
@@ -147,6 +147,14 @@ INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
 INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTEL_FLAGS = @INTEL_FLAGS@
+INTEL_PCLMUL_FLAGS = @INTEL_PCLMUL_FLAGS@
+INTEL_SSE2_FLAGS = @INTEL_SSE2_FLAGS@
+INTEL_SSE3_FLAGS = @INTEL_SSE3_FLAGS@
+INTEL_SSE4_1_FLAGS = @INTEL_SSE4_1_FLAGS@
+INTEL_SSE4_2_FLAGS = @INTEL_SSE4_2_FLAGS@
+INTEL_SSE_FLAGS = @INTEL_SSE_FLAGS@
+INTEL_SSSE3_FLAGS = @INTEL_SSSE3_FLAGS@
 JAR = @JAR@
 JAVAC = @JAVAC@
 JAVAH = @JAVAH@
diff --git a/src/java/test/com/ceph/fs/CephMountTest.java b/src/java/test/com/ceph/fs/CephMountTest.java
index a86b4e5..82c3f1b 100644
--- a/src/java/test/com/ceph/fs/CephMountTest.java
+++ b/src/java/test/com/ceph/fs/CephMountTest.java
@@ -826,8 +826,7 @@ public class CephMountTest {
 
     /* list xattrs */
     String[] xattrs = mount.listxattr(path);
-    /* the ceph.file.layout xattr exists for all files automatically */
-    assertTrue(xattrs.length == 3);
+    assertTrue(xattrs.length == 2);
     int found = 0;
     for (String xattr : xattrs) {
       if (xattr.compareTo("user.attr1") == 0) {
@@ -838,13 +837,9 @@ public class CephMountTest {
         found++;
         continue;
       }
-      if (xattr.compareTo("ceph.file.layout") == 0) {
-        found++;
-        continue;
-      }
       System.out.println("found unwanted xattr: " + xattr);
     }
-    assertTrue(found == 3);
+    assertTrue(found == 2);
 
     /* get first xattr by looking up length */
     long attr1_len = mount.getxattr(path, "user.attr1", null);
diff --git a/src/libcephfs.cc b/src/libcephfs.cc
index 74bd6c3..88e86ba 100644
--- a/src/libcephfs.cc
+++ b/src/libcephfs.cc
@@ -1169,6 +1169,51 @@ extern "C" struct Inode *ceph_ll_get_inode(class ceph_mount_info *cmount,
   return (cmount->get_client())->ll_get_inode(vino);
 }
 
+
+/**
+ * Populates the client cache with the requested inode, and its
+ * parent dentry.
+ */
+extern "C" int ceph_ll_lookup_inode(
+    struct ceph_mount_info *cmount,
+    struct inodeno_t ino,
+    Inode **inode)
+{
+  int r = (cmount->get_client())->lookup_ino(ino, inode);
+  if (r) {
+    return r;
+  }
+  if (inode) {
+    assert(*inode != NULL);
+  }
+
+  // Request the parent inode, so that we can look up the name
+  Inode *parent;
+  r = (cmount->get_client())->lookup_parent(*inode, &parent);
+  if (r && r != -EINVAL) {
+    // Unexpected error
+    (cmount->get_client())->ll_forget(*inode, 1);
+    return r;
+  } else if (r == -EINVAL) {
+    // EINVAL indicates node without parents (root), drop out now
+    // and don't try to look up the non-existent dentry.
+    return 0;
+  }
+  assert(parent != NULL);
+
+  // Finally, get the name (dentry) of the requested inode
+  r = (cmount->get_client())->lookup_name(*inode, parent);
+  if (r) {
+    // Unexpected error
+    (cmount->get_client())->ll_forget(parent, 1);
+    (cmount->get_client())->ll_forget(*inode, 1);
+    return r;
+  }
+
+  (cmount->get_client())->ll_forget(parent, 1);
+  return 0;
+}
+
 extern "C" int ceph_ll_lookup(class ceph_mount_info *cmount,
 			      struct Inode *parent, const char *name,
 			      struct stat *attr, Inode **out,
diff --git a/src/librados/AioCompletionImpl.h b/src/librados/AioCompletionImpl.h
index 48941bb..521f3bc 100644
--- a/src/librados/AioCompletionImpl.h
+++ b/src/librados/AioCompletionImpl.h
@@ -43,7 +43,7 @@ struct librados::AioCompletionImpl {
   unsigned maxlen;
 
   IoCtxImpl *io;
-  tid_t aio_write_seq;
+  ceph_tid_t aio_write_seq;
   xlist<AioCompletionImpl*>::item aio_write_list_item;
 
   AioCompletionImpl() : lock("AioCompletionImpl lock", false, false),
diff --git a/src/librados/IoCtxImpl.cc b/src/librados/IoCtxImpl.cc
index e3e6620..4f5387a 100644
--- a/src/librados/IoCtxImpl.cc
+++ b/src/librados/IoCtxImpl.cc
@@ -26,8 +26,8 @@
 #define dout_prefix *_dout << "librados: "
 
 librados::IoCtxImpl::IoCtxImpl() :
-  ref_cnt(0), client(NULL), poolid(0), assert_ver(0), notify_timeout(30),
-  aio_write_list_lock("librados::IoCtxImpl::aio_write_list_lock"),
+  ref_cnt(0), client(NULL), poolid(0), assert_ver(0), last_objver(0),
+  notify_timeout(30), aio_write_list_lock("librados::IoCtxImpl::aio_write_list_lock"),
   aio_write_seq(0), lock(NULL), objecter(NULL)
 {
 }
@@ -95,7 +95,7 @@ void librados::IoCtxImpl::complete_aio_write(AioCompletionImpl *c)
   assert(c->io == this);
   c->aio_write_list_item.remove_myself();
 
-  map<tid_t, std::list<AioCompletionImpl*> >::iterator waiters = aio_write_waiters.begin();
+  map<ceph_tid_t, std::list<AioCompletionImpl*> >::iterator waiters = aio_write_waiters.begin();
   while (waiters != aio_write_waiters.end()) {
     if (!aio_write_list.empty() &&
 	aio_write_list.front()->aio_write_seq <= waiters->first) {
@@ -123,7 +123,7 @@ void librados::IoCtxImpl::flush_aio_writes_async(AioCompletionImpl *c)
   ldout(client->cct, 20) << "flush_aio_writes_async " << this
 			 << " completion " << c << dendl;
   Mutex::Locker l(aio_write_list_lock);
-  tid_t seq = aio_write_seq;
+  ceph_tid_t seq = aio_write_seq;
   if (aio_write_list.empty()) {
     ldout(client->cct, 20) << "flush_aio_writes_async no writes. (tid "
 			   << seq << ")" << dendl;
@@ -140,7 +140,7 @@ void librados::IoCtxImpl::flush_aio_writes()
 {
   ldout(client->cct, 20) << "flush_aio_writes" << dendl;
   aio_write_list_lock.Lock();
-  tid_t seq = aio_write_seq;
+  ceph_tid_t seq = aio_write_seq;
   while (!aio_write_list.empty() &&
 	 aio_write_list.front()->aio_write_seq <= seq)
     aio_write_cond.Wait(aio_write_list_lock);
diff --git a/src/librados/IoCtxImpl.h b/src/librados/IoCtxImpl.h
index 58e27ed..528022f 100644
--- a/src/librados/IoCtxImpl.h
+++ b/src/librados/IoCtxImpl.h
@@ -42,10 +42,10 @@ struct librados::IoCtxImpl {
   object_locator_t oloc;
 
   Mutex aio_write_list_lock;
-  tid_t aio_write_seq;
+  ceph_tid_t aio_write_seq;
   Cond aio_write_cond;
   xlist<AioCompletionImpl*> aio_write_list;
-  map<tid_t, std::list<AioCompletionImpl*> > aio_write_waiters;
+  map<ceph_tid_t, std::list<AioCompletionImpl*> > aio_write_waiters;
 
   Mutex *lock;
   Objecter *objecter;
diff --git a/src/librados/RadosClient.cc b/src/librados/RadosClient.cc
index b656b5e..249c34f 100644
--- a/src/librados/RadosClient.cc
+++ b/src/librados/RadosClient.cc
@@ -754,7 +754,7 @@ int librados::RadosClient::osd_command(int osd, vector<string>& cmd,
   Cond cond;
   bool done;
   int ret;
-  tid_t tid;
+  ceph_tid_t tid;
 
   if (osd < 0)
     return -EINVAL;
@@ -781,7 +781,7 @@ int librados::RadosClient::pg_command(pg_t pgid, vector<string>& cmd,
   Cond cond;
   bool done;
   int ret;
-  tid_t tid;
+  ceph_tid_t tid;
   lock.Lock();
   int r = objecter->pg_command(pgid, cmd, inbl, &tid, poutbl, prs,
 		        new C_SafeCond(&mylock, &cond, &done, &ret));
diff --git a/src/librados/librados.cc b/src/librados/librados.cc
index 42476b5..80f2c63 100644
--- a/src/librados/librados.cc
+++ b/src/librados/librados.cc
@@ -2021,6 +2021,12 @@ extern "C" int rados_cluster_fsid(rados_t cluster, char *buf,
   return fsid.length();
 }
 
+extern "C" int rados_wait_for_latest_osdmap(rados_t cluster)
+{
+  librados::RadosClient *radosp = (librados::RadosClient *)cluster;
+  return radosp->wait_for_latest_osdmap();
+}
+
 extern "C" int rados_pool_list(rados_t cluster, char *buf, size_t len)
 {
   librados::RadosClient *client = (librados::RadosClient *)cluster;
@@ -2421,6 +2427,18 @@ extern "C" int rados_ioctx_pool_get_auid(rados_ioctx_t io, uint64_t *auid)
   return ctx->client->pool_get_auid(ctx->get_id(), (unsigned long long *)auid);
 }
 
+extern "C" int rados_ioctx_pool_requires_alignment(rados_ioctx_t io)
+{
+  librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
+  return ctx->client->pool_requires_alignment(ctx->get_id());
+}
+
+extern "C" uint64_t rados_ioctx_pool_required_alignment(rados_ioctx_t io)
+{
+  librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
+  return ctx->client->pool_required_alignment(ctx->get_id());
+}
+
 extern "C" void rados_ioctx_locator_set_key(rados_ioctx_t io, const char *key)
 {
   librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
@@ -3162,7 +3180,6 @@ extern "C" void rados_write_op_create(rados_write_op_t write_op,
 {
   ::ObjectOperation *oo = (::ObjectOperation *) write_op;
   if(category) {
-    std::string cpp_category = category;
     oo->create(exclusive, category);
   } else {
     oo->create(!!exclusive);
diff --git a/src/librbd/AioRequest.cc b/src/librbd/AioRequest.cc
index 881f754..5cf9a11 100644
--- a/src/librbd/AioRequest.cc
+++ b/src/librbd/AioRequest.cc
@@ -109,7 +109,8 @@ namespace librbd {
 
   AbstractWrite::AbstractWrite()
     : m_state(LIBRBD_AIO_WRITE_FLAT),
-      m_parent_overlap(0) {}
+      m_parent_overlap(0),
+      m_snap_seq(0) {}
   AbstractWrite::AbstractWrite(ImageCtx *ictx, const std::string &oid,
 			       uint64_t object_no, uint64_t object_off, uint64_t len,
 			       vector<pair<uint64_t,uint64_t> >& objectx,
diff --git a/src/librbd/LibrbdWriteback.cc b/src/librbd/LibrbdWriteback.cc
index ddb882d..854ac9d 100644
--- a/src/librbd/LibrbdWriteback.cc
+++ b/src/librbd/LibrbdWriteback.cc
@@ -131,7 +131,7 @@ namespace librbd {
     return may;
   }
 
-  tid_t LibrbdWriteback::write(const object_t& oid,
+  ceph_tid_t LibrbdWriteback::write(const object_t& oid,
 			       const object_locator_t& oloc,
 			       uint64_t off, uint64_t len,
 			       const SnapContext& snapc,
diff --git a/src/librbd/LibrbdWriteback.h b/src/librbd/LibrbdWriteback.h
index 0967421..a8bd9cb 100644
--- a/src/librbd/LibrbdWriteback.h
+++ b/src/librbd/LibrbdWriteback.h
@@ -32,7 +32,7 @@ namespace librbd {
     virtual bool may_copy_on_write(const object_t& oid, uint64_t read_off, uint64_t read_len, snapid_t snapid);
 
     // Note that oloc, trunc_size, and trunc_seq are ignored
-    virtual tid_t write(const object_t& oid, const object_locator_t& oloc,
+    virtual ceph_tid_t write(const object_t& oid, const object_locator_t& oloc,
 			uint64_t off, uint64_t len, const SnapContext& snapc,
 			const bufferlist &bl, utime_t mtime, uint64_t trunc_size,
 			__u32 trunc_seq, Context *oncommit);
@@ -52,7 +52,7 @@ namespace librbd {
   private:
     void complete_writes(const std::string& oid);
 
-    tid_t m_tid;
+    ceph_tid_t m_tid;
     Mutex& m_lock;
     librbd::ImageCtx *m_ictx;
     ceph::unordered_map<std::string, std::queue<write_result_d*> > m_writes;
diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc
index 61e910b..8056fab 100644
--- a/src/librbd/internal.cc
+++ b/src/librbd/internal.cc
@@ -1955,6 +1955,13 @@ reprotect_and_return_err:
 	return;
       }
       assert(m_bl->length() == (size_t)r);
+
+      if (m_bl->is_zero()) {
+	delete m_bl;
+	m_throttle->end_op(r);
+	return;
+      }
+
       Context *ctx = new C_CopyWrite(m_throttle, m_bl);
       AioCompletion *comp = aio_create_completion_internal(ctx, rbd_ctx_cb);
       r = aio_write(m_dest, m_offset, m_bl->length(), m_bl->c_str(), comp);
diff --git a/src/libs3/debian/changelog b/src/libs3/debian/changelog
new file mode 100644
index 0000000..520b2b9
--- /dev/null
+++ b/src/libs3/debian/changelog
@@ -0,0 +1,5 @@
+libs3 (all) unstable; urgency=low
+
+  * This file is not maintained.  See project source code for changes.
+
+ -- Bryan Ischo <bryan at ischo.com>  Wed, 06 Aug 2008 09:36:43 -0400
diff --git a/src/libs3/debian/changelog.Debian b/src/libs3/debian/changelog.Debian
new file mode 100644
index 0000000..81072be
--- /dev/null
+++ b/src/libs3/debian/changelog.Debian
@@ -0,0 +1,6 @@
+libs3 (all) unstable; urgency=low
+
+      * libs3 Debian maintainer and upstream author are identical.
+        Therefore see normal changelog file for Debian changes.
+
+ -- Bryan Ischo <bryan at ischo.com>  Wed, 06 Aug 2008 09:36:43 -0400
diff --git a/src/libs3/debian/control b/src/libs3/debian/control
new file mode 100644
index 0000000..28ddc6b
--- /dev/null
+++ b/src/libs3/debian/control
@@ -0,0 +1,12 @@
+Package: libs3
+Source: THIS LINE WILL BE REMOVED, dpkg-shlibdepends NEEDS IT
+Version: LIBS3_VERSION
+Architecture: DEBIAN_ARCHITECTURE
+Section: net
+Priority: extra
+Maintainer: Bryan Ischo <bryan at ischo.com>
+Homepage: http://libs3.ischo.com/index.html
+Description: C Library and Tools for Amazon S3 Access
+ This package includes the libs3 shared object library, needed to run
+ applications compiled against libs3, and additionally contains the s3
+ utility for accessing Amazon S3.
diff --git a/src/libs3/debian/control.dev b/src/libs3/debian/control.dev
new file mode 100644
index 0000000..5ee5ae7
--- /dev/null
+++ b/src/libs3/debian/control.dev
@@ -0,0 +1,26 @@
+Package: libs3-dev
+Version: LIBS3_VERSION
+Architecture: DEBIAN_ARCHITECTURE
+Section: libdevel
+Priority: extra
+Depends: libs3 (>= LIBS3_VERSION)
+Maintainer: Bryan Ischo <bryan at ischo.com>
+Homepage: http://libs3.ischo.com/index.html
+Description: C Development Library for Amazon S3 Access
+ This library provides an API for using Amazon's S3 service (see
+ http://s3.amazonaws.com).  Its design goals are:
+ .
+  - To provide a simple and straightforward API for accessing all of S3's
+    functionality
+  - To not require the developer using libs3 to need to know anything about:
+      - HTTP
+      - XML
+      - SSL
+    In other words, this API is meant to stand on its own, without requiring
+    any implicit knowledge of how S3 services are accessed using HTTP
+    protocols.
+  - To be usable from multithreaded code
+  - To be usable by code which wants to process multiple S3 requests
+    simultaneously from a single thread
+  - To be usable in the simple, straightforward way using sequentialized
+    blocking requests
diff --git a/src/libs3/debian/postinst b/src/libs3/debian/postinst
new file mode 100755
index 0000000..2d1871b
--- /dev/null
+++ b/src/libs3/debian/postinst
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+ldconfig
diff --git a/src/log/Log.cc b/src/log/Log.cc
index 0087057..37bb4ef 100644
--- a/src/log/Log.cc
+++ b/src/log/Log.cc
@@ -72,7 +72,7 @@ Log::~Log()
 
   assert(!is_started());
   if (m_fd >= 0)
-    TEMP_FAILURE_RETRY(::close(m_fd));
+    VOID_TEMP_FAILURE_RETRY(::close(m_fd));
 
   pthread_mutex_destroy(&m_queue_mutex);
   pthread_mutex_destroy(&m_flush_mutex);
@@ -113,7 +113,7 @@ void Log::set_log_file(string fn)
 void Log::reopen_log_file()
 {
   if (m_fd >= 0)
-    TEMP_FAILURE_RETRY(::close(m_fd));
+    VOID_TEMP_FAILURE_RETRY(::close(m_fd));
   if (m_log_file.length()) {
     m_fd = ::open(m_log_file.c_str(), O_CREAT|O_WRONLY|O_APPEND, 0644);
   } else {
diff --git a/src/logrotate.conf b/src/logrotate.conf
index 9181b56..9f69646 100644
--- a/src/logrotate.conf
+++ b/src/logrotate.conf
@@ -25,4 +25,5 @@
         fi
     endscript
     missingok
+    notifempty
 }
diff --git a/src/make_version b/src/make_version
index e2fed42..3ed2bac 100755
--- a/src/make_version
+++ b/src/make_version
@@ -1,7 +1,14 @@
 #!/bin/sh
 
-cur=`head -1 $1`
-v=`tail -1 $1 | cut -c 2-`
+echo '$1: '$1
+
+if [ "$1" =  "-n" ] ; then
+   cur="no_version"
+   v="Development"
+else
+   cur=`head -1 $1`
+   v=`tail -1 $1 | cut -c 2-`
+fi
 
 print_all() {
 	echo "#ifndef CEPH_VERSION_H"
diff --git a/src/mds/AnchorServer.h b/src/mds/AnchorServer.h
index fb38051..d6f1d84 100644
--- a/src/mds/AnchorServer.h
+++ b/src/mds/AnchorServer.h
@@ -33,7 +33,7 @@ class AnchorServer : public MDSTableServer {
   map<inodeno_t, list<pair<version_t, Context*> > > pending_ops;
 
   void reset_state();
-  void encode_server_state(bufferlist& bl) {
+  void encode_server_state(bufferlist& bl) const {
     ENCODE_START(2, 2, bl);
     ::encode(anchor_map, bl);
     ::encode(pending_create, bl);
@@ -70,10 +70,11 @@ class AnchorServer : public MDSTableServer {
   // for the dencoder
   AnchorServer() : MDSTableServer(NULL, TABLE_ANCHOR) {}
   void encode(bufferlist& bl) const {
-    AnchorServer *me = const_cast<AnchorServer*>(this);
-    me->encode_server_state(bl);
+    encode_server_state(bl);
+  }
+  void decode(bufferlist::iterator& bl) {
+    decode_server_state(bl);
   }
-  void decode(bufferlist::iterator& bl) { decode_server_state(bl); }
 
   // server bits
   void _prepare(bufferlist &bl, uint64_t reqid, int bymds);
diff --git a/src/mds/CDir.cc b/src/mds/CDir.cc
index e244175..35573b6 100644
--- a/src/mds/CDir.cc
+++ b/src/mds/CDir.cc
@@ -201,11 +201,8 @@ CDir::CDir(CInode *in, frag_t fg, MDCache *mdcache, bool auth) :
   request_pins = 0;
 
   nested_anchors = 0;
-
-  //hack_num_accessed = -1;
   
   dir_rep = REP_NONE;
-  //dir_rep = REP_ALL;      // hack: to wring out some bugs! FIXME FIXME
 }
 
 /**
@@ -215,6 +212,9 @@ CDir::CDir(CInode *in, frag_t fg, MDCache *mdcache, bool auth) :
  */
 bool CDir::check_rstats()
 {
+  if (!g_conf->mds_debug_scatterstat)
+    return true;
+
   dout(25) << "check_rstats on " << this << dendl;
   if (!is_complete() || !is_auth() || is_frozen()) {
     dout(10) << "check_rstats bailing out -- incomplete or non-auth or frozen dir!" << dendl;
@@ -232,9 +232,7 @@ bool CDir::check_rstats()
       //if (i->second->get_linkage()->is_primary())
         dout(1) << *(i->second) << dendl;
     }
-    assert(!g_conf->mds_debug_scatterstat ||
-           (get_num_head_items() ==
-            (fnode.fragstat.nfiles + fnode.fragstat.nsubdirs)));
+    assert(get_num_head_items() == (fnode.fragstat.nfiles + fnode.fragstat.nsubdirs));
   } else {
     dout(20) << "get_num_head_items() = " << get_num_head_items()
              << "; fnode.fragstat.nfiles=" << fnode.fragstat.nfiles
@@ -268,9 +266,9 @@ bool CDir::check_rstats()
     dout(25) << "my rstats:              " << fnode.rstat << dendl;
   }
 
-  assert(!g_conf->mds_debug_scatterstat || sub_info.rbytes == fnode.rstat.rbytes);
-  assert(!g_conf->mds_debug_scatterstat || sub_info.rfiles == fnode.rstat.rfiles);
-  assert(!g_conf->mds_debug_scatterstat || sub_info.rsubdirs == fnode.rstat.rsubdirs);
+  assert(sub_info.rbytes == fnode.rstat.rbytes);
+  assert(sub_info.rfiles == fnode.rstat.rfiles);
+  assert(sub_info.rsubdirs == fnode.rstat.rsubdirs);
   dout(10) << "check_rstats complete on " << this << dendl;
   return true;
 }
@@ -619,7 +617,9 @@ void CDir::add_to_bloom(CDentry *dn)
     /* not create bloom filter for incomplete dir that was added by log replay */
     if (!is_complete())
       return;
-    bloom = new bloom_filter(100, 0.05, 0);
+    unsigned size = get_num_head_items() + get_num_snap_items();
+    if (size < 100) size = 100;
+    bloom = new bloom_filter(size, 1.0 / size, 0);
   }
   /* This size and false positive probability is completely random.*/
   bloom->insert(dn->name.c_str(), dn->name.size());
@@ -1543,10 +1543,10 @@ void CDir::_omap_fetched(bufferlist& hdrbl, map<string, bufferlist>& omap,
 
   bool stray = inode->is_stray();
 
-  unsigned pos = 0;
-  for (map<string, bufferlist>::iterator p = omap.begin();
-       p != omap.end();
-       ++p, ++pos) {
+  unsigned pos = omap.size() - 1;
+  for (map<string, bufferlist>::reverse_iterator p = omap.rbegin();
+       p != omap.rend();
+       ++p, --pos) {
     // dname
     string dname;
     snapid_t first, last;
@@ -1742,7 +1742,6 @@ void CDir::_omap_fetched(bufferlist& hdrbl, map<string, bufferlist>& omap,
   }
 
   //cache->mds->logger->inc("newin", num_new_inodes_loaded);
-  //hack_num_accessed = 0;
 
   if (purged_any)
     log_mark_dirty();
diff --git a/src/mds/CDir.h b/src/mds/CDir.h
index 955a04e..dc1037a 100644
--- a/src/mds/CDir.h
+++ b/src/mds/CDir.h
@@ -151,7 +151,7 @@ public:
 
   static const int WAIT_DNLOCK_OFFSET = 4;
 
-  static const uint64_t WAIT_ANY_MASK  = (0xffffffff);
+  static const uint64_t WAIT_ANY_MASK = (uint64_t)(-1);
   static const uint64_t WAIT_ATFREEZEROOT = (WAIT_UNFREEZE);
   static const uint64_t WAIT_ATSUBTREEROOT = (WAIT_SINGLEAUTH);
 
@@ -219,6 +219,7 @@ public:
   void log_mark_dirty();
   void mark_clean();
 
+  bool is_new() { return item_new.is_on_list(); }
   void mark_new(LogSegment *ls);
 
 public:
@@ -324,6 +325,7 @@ protected:
     return num_dirty;
   }
 
+  int64_t get_frag_size() { return get_projected_fnode()->fragstat.size(); }
 
   // -- dentries and inodes --
  public:
@@ -370,10 +372,10 @@ public:
   void merge(list<CDir*>& subs, list<Context*>& waiters, bool replay);
 
   bool should_split() {
-    return (int)get_num_head_items() > g_conf->mds_bal_split_size;
+    return (int)get_frag_size() > g_conf->mds_bal_split_size;
   }
   bool should_merge() {
-    return (int)get_num_head_items() < g_conf->mds_bal_merge_size;
+    return (int)get_frag_size() < g_conf->mds_bal_merge_size;
   }
 
 private:
diff --git a/src/mds/CInode.cc b/src/mds/CInode.cc
index 02cabd3..e475dfb 100644
--- a/src/mds/CInode.cc
+++ b/src/mds/CInode.cc
@@ -534,11 +534,12 @@ CDir *CInode::get_approx_dirfrag(frag_t fg)
     return ls.front();
 
   // try parents?
-  while (1) {
+  while (fg.bits() > 0) {
     fg = fg.parent();
     dir = get_dirfrag(fg);
     if (dir) return dir;
   }
+  return NULL;
 }	
 
 void CInode::get_dirfrags(list<CDir*>& ls) 
@@ -642,6 +643,16 @@ bool CInode::has_subtree_root_dirfrag(int auth)
   return false;
 }
 
+bool CInode::has_subtree_or_exporting_dirfrag()
+{
+  for (map<frag_t,CDir*>::iterator p = dirfrags.begin();
+       p != dirfrags.end();
+       ++p)
+    if (p->second->is_subtree_root() ||
+	p->second->state_test(CDir::STATE_EXPORTING))
+      return true;
+  return false;
+}
 
 void CInode::get_stickydirs()
 {
@@ -1197,7 +1208,8 @@ void CInode::encode_lock_state(int type, bufferlist& bl)
     if (is_auth()) {
       ::encode(inode.version, bl);
     } else {
-      bool dirty = dirfragtreelock.is_dirty();
+      // treat flushing as dirty when rejoining cache
+      bool dirty = dirfragtreelock.is_dirty_or_flushing();
       ::encode(dirty, bl);
     }
     {
@@ -1231,7 +1243,8 @@ void CInode::encode_lock_state(int type, bufferlist& bl)
 	::encode(inode.inline_version, bl);
       }
     } else {
-      bool dirty = filelock.is_dirty();
+      // treat flushing as dirty when rejoining cache
+      bool dirty = filelock.is_dirty_or_flushing();
       ::encode(dirty, bl);
     }
 
@@ -1266,7 +1279,8 @@ void CInode::encode_lock_state(int type, bufferlist& bl)
     if (is_auth()) {
       ::encode(inode.version, bl);
     } else {
-      bool dirty = nestlock.is_dirty();
+      // treat flushing as dirty when rejoining cache
+      bool dirty = nestlock.is_dirty_or_flushing();
       ::encode(dirty, bl);
     }
     {
@@ -3048,10 +3062,11 @@ int CInode::encode_inodestat(bufferlist& bl, Session *session,
 
 void CInode::encode_cap_message(MClientCaps *m, Capability *cap)
 {
+  assert(cap);
+
   client_t client = cap->get_client();
 
-  bool pfile = filelock.is_xlocked_by_client(client) ||
-    (cap && (cap->issued() & CEPH_CAP_FILE_EXCL));
+  bool pfile = filelock.is_xlocked_by_client(client) || (cap->issued() & CEPH_CAP_FILE_EXCL);
   bool pauth = authlock.is_xlocked_by_client(client);
   bool plink = linklock.is_xlocked_by_client(client);
   bool pxattr = xattrlock.is_xlocked_by_client(client);
@@ -3225,7 +3240,7 @@ void CInode::_decode_locks_rejoin(bufferlist::iterator& p, list<Context*>& waite
 
 void CInode::encode_export(bufferlist& bl)
 {
-  ENCODE_START(4, 4, bl)
+  ENCODE_START(5, 4, bl)
   _encode_base(bl);
 
   ::encode(state, bl);
@@ -3253,8 +3268,12 @@ void CInode::encode_export(bufferlist& bl)
   ::encode(bounding, bl);
 
   _encode_locks_full(bl);
-  get(PIN_TEMPEXPORTING);
+
+  ::encode(fcntl_locks, bl);
+  ::encode(flock_locks, bl);
   ENCODE_FINISH(bl);
+
+  get(PIN_TEMPEXPORTING);
 }
 
 void CInode::finish_export(utime_t now)
@@ -3274,7 +3293,7 @@ void CInode::finish_export(utime_t now)
 void CInode::decode_import(bufferlist::iterator& p,
 			   LogSegment *ls)
 {
-  DECODE_START_LEGACY_COMPAT_LEN(4, 4, 4, p);
+  DECODE_START(5, p);
 
   _decode_base(p);
 
@@ -3296,52 +3315,56 @@ void CInode::decode_import(bufferlist::iterator& p,
   if (!replica_map.empty())
     get(PIN_REPLICATED);
 
-  if (struct_v >= 2) {
-    // decode fragstat info on bounding cdirs
-    bufferlist bounding;
-    ::decode(bounding, p);
-    bufferlist::iterator q = bounding.begin();
-    while (!q.end()) {
-      frag_t fg;
-      ::decode(fg, q);
-      CDir *dir = get_dirfrag(fg);
-      assert(dir);  // we should have all bounds open
-
-      // Only take the remote's fragstat/rstat if we are non-auth for
-      // this dirfrag AND the lock is NOT in a scattered (MIX) state.
-      // We know lock is stable, and MIX is the only state in which
-      // the inode auth (who sent us this data) may not have the best
-      // info.
-
-      // HMM: Are there cases where dir->is_auth() is an insufficient
-      // check because the dirfrag is under migration?  That implies
-      // it is frozen (and in a SYNC or LOCK state).  FIXME.
-
-      if (dir->is_auth() ||
-	  filelock.get_state() == LOCK_MIX) {
-	dout(10) << " skipped fragstat info for " << *dir << dendl;
-	frag_info_t f;
-	::decode(f, q);
-	::decode(f, q);
-      } else {
-	::decode(dir->fnode.fragstat, q);
-	::decode(dir->fnode.accounted_fragstat, q);
-	dout(10) << " took fragstat info for " << *dir << dendl;
-      }
-      if (dir->is_auth() ||
-	  nestlock.get_state() == LOCK_MIX) {
-	dout(10) << " skipped rstat info for " << *dir << dendl;
-	nest_info_t n;
-	::decode(n, q);
-	::decode(n, q);
-      } else {
-	::decode(dir->fnode.rstat, q);
-	::decode(dir->fnode.accounted_rstat, q);
-	dout(10) << " took rstat info for " << *dir << dendl;
-      }
+  // decode fragstat info on bounding cdirs
+  bufferlist bounding;
+  ::decode(bounding, p);
+  bufferlist::iterator q = bounding.begin();
+  while (!q.end()) {
+    frag_t fg;
+    ::decode(fg, q);
+    CDir *dir = get_dirfrag(fg);
+    assert(dir);  // we should have all bounds open
+
+    // Only take the remote's fragstat/rstat if we are non-auth for
+    // this dirfrag AND the lock is NOT in a scattered (MIX) state.
+    // We know lock is stable, and MIX is the only state in which
+    // the inode auth (who sent us this data) may not have the best
+    // info.
+
+    // HMM: Are there cases where dir->is_auth() is an insufficient
+    // check because the dirfrag is under migration?  That implies
+    // it is frozen (and in a SYNC or LOCK state).  FIXME.
+
+    if (dir->is_auth() ||
+        filelock.get_state() == LOCK_MIX) {
+      dout(10) << " skipped fragstat info for " << *dir << dendl;
+      frag_info_t f;
+      ::decode(f, q);
+      ::decode(f, q);
+    } else {
+      ::decode(dir->fnode.fragstat, q);
+      ::decode(dir->fnode.accounted_fragstat, q);
+      dout(10) << " took fragstat info for " << *dir << dendl;
+    }
+    if (dir->is_auth() ||
+        nestlock.get_state() == LOCK_MIX) {
+      dout(10) << " skipped rstat info for " << *dir << dendl;
+      nest_info_t n;
+      ::decode(n, q);
+      ::decode(n, q);
+    } else {
+      ::decode(dir->fnode.rstat, q);
+      ::decode(dir->fnode.accounted_rstat, q);
+      dout(10) << " took rstat info for " << *dir << dendl;
     }
   }
 
   _decode_locks_full(p);
+
+  if (struct_v >= 5) {
+    ::decode(fcntl_locks, p);
+    ::decode(flock_locks, p);
+  }
+
   DECODE_FINISH(p);
 }
diff --git a/src/mds/CInode.h b/src/mds/CInode.h
index 3977859..efc9825 100644
--- a/src/mds/CInode.h
+++ b/src/mds/CInode.h
@@ -355,6 +355,7 @@ public:
   void close_dirfrag(frag_t fg);
   void close_dirfrags();
   bool has_subtree_root_dirfrag(int auth=-1);
+  bool has_subtree_or_exporting_dirfrag();
 
   void force_dirfrags();
   void verify_dirfrags();
@@ -390,6 +391,11 @@ protected:
   ceph_lock_state_t fcntl_locks;
   ceph_lock_state_t flock_locks;
 
+  void clear_file_locks() {
+    fcntl_locks.clear();
+    flock_locks.clear();
+  }
+
   // LogSegment dlists i (may) belong to
 public:
   elist<CInode*>::item item_dirty;
diff --git a/src/mds/Capability.h b/src/mds/Capability.h
index 7e04de0..c105a38 100644
--- a/src/mds/Capability.h
+++ b/src/mds/Capability.h
@@ -311,7 +311,7 @@ public:
 	issue(newpending);
       last_issue_stamp = other.last_issue_stamp;
     } else {
-      inc_last_seq();
+      issue(CEPH_CAP_PIN);
     }
 
     client_follows = other.client_follows;
@@ -330,7 +330,7 @@ public:
       else
 	issue(newpending);
     } else {
-      inc_last_seq();
+      issue(CEPH_CAP_PIN);
     }
 
     // wanted
diff --git a/src/mds/Dumper.cc b/src/mds/Dumper.cc
index cb570a5..f7f18c9 100644
--- a/src/mds/Dumper.cc
+++ b/src/mds/Dumper.cc
@@ -22,79 +22,35 @@
 #include "common/safe_io.h"
 #include "mds/Dumper.h"
 #include "mds/mdstypes.h"
-#include "mon/MonClient.h"
+#include "mds/LogEvent.h"
 #include "osdc/Journaler.h"
 
 #define dout_subsys ceph_subsys_mds
 
-Dumper::~Dumper()
-{
-}
 
-bool Dumper::ms_get_authorizer(int dest_type, AuthAuthorizer **authorizer,
-                         bool force_new)
+int Dumper::init(int rank_)
 {
-  if (dest_type == CEPH_ENTITY_TYPE_MON)
-    return true;
+  rank = rank_;
 
-  if (force_new) {
-    if (monc->wait_auth_rotating(10) < 0)
-      return false;
+  int r = MDSUtility::init();
+  if (r < 0) {
+    return r;
   }
 
-  *authorizer = monc->auth->build_authorizer(dest_type);
-  return *authorizer != NULL;
-}
-
-void Dumper::init(int rank) 
-{
   inodeno_t ino = MDS_INO_LOG_OFFSET + rank;
-  unsigned pg_pool = MDS_METADATA_POOL;
-  osdmap = new OSDMap();
-  objecter = new Objecter(g_ceph_context, messenger, monc, osdmap, lock, timer,
-			  0, 0);
-  journaler = new Journaler(ino, pg_pool, CEPH_FS_ONDISK_MAGIC,
+  journaler = new Journaler(ino, mdsmap->get_metadata_pool(), CEPH_FS_ONDISK_MAGIC,
                                        objecter, 0, 0, &timer);
-
-  objecter->set_client_incarnation(0);
-
-  messenger->add_dispatcher_head(this);
-  messenger->start();
-
-  monc->set_want_keys(CEPH_ENTITY_TYPE_MON|CEPH_ENTITY_TYPE_OSD|CEPH_ENTITY_TYPE_MDS);
-  monc->set_messenger(messenger);
-  monc->init();
-  monc->authenticate();
-
-  client_t whoami = monc->get_global_id();
-  messenger->set_myname(entity_name_t::CLIENT(whoami.v));
-
-  objecter->init_unlocked();
-  lock.Lock();
-  objecter->init_locked();
-  lock.Unlock();
-  objecter->wait_for_osd_map();
-  timer.init();
+  return 0;
 }
 
-void Dumper::shutdown()
-{
-  lock.Lock();
-  timer.shutdown();
-  objecter->shutdown_locked();
-  lock.Unlock();
-  objecter->shutdown_unlocked();
-}
 
-void Dumper::dump(const char *dump_file)
+int Dumper::recover_journal()
 {
   bool done = false;
   Cond cond;
-  int r = 0;
-  int rank = strtol(g_conf->name.get_id().c_str(), 0, 0);
-  inodeno_t ino = MDS_INO_LOG_OFFSET + rank;
+  Mutex localLock("dump:recover_journal");
+  int r;
 
-  Mutex localLock("dump:lock");
   lock.Lock();
   journaler->recover(new C_SafeCond(&localLock, &cond, &done, &r));
   lock.Unlock();
@@ -105,21 +61,35 @@ void Dumper::dump(const char *dump_file)
 
   if (r < 0) { // Error
     derr << "error on recovery: " << cpp_strerror(r) << dendl;
-    messenger->shutdown();
-    // wait for messenger to finish
-    messenger->wait();
-    shutdown();
+    return r;
   } else {
     dout(10) << "completed journal recovery" << dendl;
+    return 0;
   }
+}
+
+
+void Dumper::dump(const char *dump_file)
+{
+  bool done = false;
+  int r = 0;
+  Cond cond;
+  Mutex localLock("dump:lock");
 
+  r = recover_journal();
+  if (r) {
+    return;
+  }
   uint64_t start = journaler->get_read_pos();
   uint64_t end = journaler->get_write_pos();
   uint64_t len = end-start;
+  inodeno_t ino = MDS_INO_LOG_OFFSET + rank;
+
   cout << "journal is " << start << "~" << len << std::endl;
 
   Filer filer(objecter);
   bufferlist bl;
+
   lock.Lock();
   filer.read(ino, &journaler->get_layout(), CEPH_NOSNAP,
              start, len, &bl, 0, new C_SafeCond(&localLock, &cond, &done));
@@ -158,13 +128,6 @@ void Dumper::dump(const char *dump_file)
     int err = errno;
     derr << "unable to open " << dump_file << ": " << cpp_strerror(err) << dendl;
   }
-
-  messenger->shutdown();
-
-  // wait for messenger to finish
-  messenger->wait();
-
-  shutdown();
 }
 
 void Dumper::undump(const char *dump_file)
@@ -184,7 +147,7 @@ void Dumper::undump(const char *dump_file)
   char buf[200];
   int r = safe_read(fd, buf, sizeof(buf));
   if (r < 0) {
-    TEMP_FAILURE_RETRY(::close(fd));
+    VOID_TEMP_FAILURE_RETRY(::close(fd));
     return;
   }
 
@@ -195,7 +158,6 @@ void Dumper::undump(const char *dump_file)
   cout << "start " << start << " len " << len << std::endl;
   
   inodeno_t ino = MDS_INO_LOG_OFFSET + rank;
-  unsigned pg_pool = MDS_METADATA_POOL;
 
   Journaler::Header h;
   h.trimmed_pos = start;
@@ -204,13 +166,13 @@ void Dumper::undump(const char *dump_file)
   h.magic = CEPH_FS_ONDISK_MAGIC;
 
   h.layout = g_default_file_layout;
-  h.layout.fl_pg_pool = pg_pool;
+  h.layout.fl_pg_pool = mdsmap->get_metadata_pool();
   
   bufferlist hbl;
   ::encode(h, hbl);
 
   object_t oid = file_object_t(ino, 0);
-  object_locator_t oloc(pg_pool);
+  object_locator_t oloc(mdsmap->get_metadata_pool());
   SnapContext snapc;
 
   bool done = false;
@@ -247,8 +209,66 @@ void Dumper::undump(const char *dump_file)
     left -= l;
   }
 
-  TEMP_FAILURE_RETRY(::close(fd));
+  VOID_TEMP_FAILURE_RETRY(::close(fd));
   cout << "done." << std::endl;
 }
 
 
+/**
+ * Write JSON-formatted log entries to standard out.
+ */
+void Dumper::dump_entries()
+{
+  Mutex localLock("dump_entries");
+  JSONFormatter jf(true);
+
+  int r = recover_journal();
+  if (r) {
+    return;
+  }
+
+  jf.open_array_section("log");
+  bool got_data = true;
+  lock.Lock();
+  // Until the journal is empty, pop an event or wait for one to
+  // be available.
+  dout(10) << "Journaler read/write/size: "
+      << journaler->get_read_pos() << "/" << journaler->get_write_pos()
+      << "/" << journaler->get_write_pos() - journaler->get_read_pos() << dendl;
+  while (journaler->get_read_pos() != journaler->get_write_pos()) {
+    bufferlist entry_bl;
+    got_data = journaler->try_read_entry(entry_bl);
+    dout(10) << "try_read_entry: " << got_data << dendl;
+    if (got_data) {
+      LogEvent *le = LogEvent::decode(entry_bl);
+      if (!le) {
+	dout(0) << "Error decoding LogEvent" << dendl;
+	break;
+      } else {
+	jf.open_object_section("log_event");
+	jf.dump_unsigned("type", le->get_type());
+	jf.dump_unsigned("start_off", le->get_start_off());
+	jf.dump_unsigned("stamp_sec", le->get_stamp().tv.tv_sec);
+	jf.dump_unsigned("stamp_nsec", le->get_stamp().tv.tv_nsec);
+	le->dump(&jf);
+	jf.close_section();
+	delete le;
+      }
+    } else {
+      bool done = false;
+      Cond cond;
+
+      journaler->wait_for_readable(new C_SafeCond(&localLock, &cond, &done));
+      lock.Unlock();
+      localLock.Lock();
+      while (!done)
+        cond.Wait(localLock);
+      localLock.Unlock();
+      lock.Lock();
+    }
+  }
+  lock.Unlock();
+  jf.close_section();
+  jf.flush(cout);
+  return;
+}
diff --git a/src/mds/Dumper.h b/src/mds/Dumper.h
index 794ae0c..6218ef4 100644
--- a/src/mds/Dumper.h
+++ b/src/mds/Dumper.h
@@ -14,12 +14,9 @@
 #ifndef JOURNAL_DUMPER_H_
 #define JOURNAL_DUMPER_H_
 
-#include "osd/OSDMap.h"
-#include "osdc/Objecter.h"
+
+#include "mds/MDSUtility.h"
 #include "osdc/Journaler.h"
-#include "msg/Dispatcher.h"
-#include "msg/Messenger.h"
-#include "auth/Auth.h"
 
 /**
  * This class lets you dump out an mds journal for troubleshooting or whatever.
@@ -29,60 +26,22 @@
  * of the file to dump to.
  */
 
-class Dumper : public Dispatcher {
-public:
-  Objecter *objecter;
+class Dumper : public MDSUtility {
+private:
   Journaler *journaler;
-  OSDMap *osdmap;
-  Messenger *messenger;
-  MonClient *monc;
-  Mutex lock;
-  SafeTimer timer;
-
   int rank;
 
-  /*
-   * The messenger should be a valid Messenger. You should call bind()
-   * before passing it in, but not do anything else.
-   * The MonClient needs to be valid, and you should have called
-   * build_initial_monmap().
-   */
-  Dumper(Messenger *messenger_, MonClient *monc_) :
-    Dispatcher(messenger_->cct),
-    objecter(NULL),
-    journaler(NULL),
-    osdmap(NULL),
-    messenger(messenger_),
-    monc(monc_),
-    lock("Dumper::lock"),
-    timer(g_ceph_context, lock),
-    rank(-1)
-  { }
+public:
+  Dumper() : journaler(NULL), rank(-1)
+  {}
 
-  virtual ~Dumper();
+  void handle_mds_map(MMDSMap* m);
 
-  bool ms_dispatch(Message *m) {
-    Mutex::Locker locker(lock);
-    switch (m->get_type()) {
-    case CEPH_MSG_OSD_OPREPLY:
-      objecter->handle_osd_op_reply((MOSDOpReply *)m);
-      break;
-    case CEPH_MSG_OSD_MAP:
-      objecter->handle_osd_map((MOSDMap*)m);
-      break;
-    default:
-      return false;
-    }
-    return true;
-  }
-  bool ms_handle_reset(Connection *con) { return false; }
-  void ms_handle_remote_reset(Connection *con) {}
-  bool ms_get_authorizer(int dest_type, AuthAuthorizer **authorizer,
-                         bool force_new);
-  void init(int rank);
-  void shutdown();
+  int init(int rank);
+  int recover_journal();
   void dump(const char *dumpfile);
   void undump(const char *dumpfile);
+  void dump_entries();
 };
 
 #endif /* JOURNAL_DUMPER_H_ */
diff --git a/src/mds/InoTable.cc b/src/mds/InoTable.cc
index 426b915..f0bf3bd 100644
--- a/src/mds/InoTable.cc
+++ b/src/mds/InoTable.cc
@@ -156,3 +156,34 @@ void InoTable::skip_inos(inodeno_t i)
   projected_version = ++version;
   dout(10) << "skip_inos now " << free << dendl;
 }
+
+void InoTable::dump(Formatter *f) const
+{
+  f->open_object_section("inotable");
+
+  f->open_array_section("projected_free");
+  for (interval_set<inodeno_t>::const_iterator i = projected_free.begin(); i != projected_free.end(); ++i) {
+    f->open_object_section("range");
+    f->dump_int("start", (*i).first);
+    f->dump_int("len", (*i).second);
+    f->close_section();
+  }
+  f->close_section();
+
+  f->open_array_section("free");
+  for (interval_set<inodeno_t>::const_iterator i = free.begin(); i != free.end(); ++i) {
+    f->open_object_section("range");
+    f->dump_int("start", (*i).first);
+    f->dump_int("len", (*i).second);
+    f->close_section();
+  }
+  f->close_section();
+
+  f->close_section();
+}
+
+
+void InoTable::generate_test_instances(list<InoTable*>& ls)
+{
+  ls.push_back(new InoTable());
+}
diff --git a/src/mds/InoTable.h b/src/mds/InoTable.h
index 88fd9ec..100db95 100644
--- a/src/mds/InoTable.h
+++ b/src/mds/InoTable.h
@@ -43,7 +43,7 @@ class InoTable : public MDSTable {
   void replay_reset();
 
   void reset_state();
-  void encode_state(bufferlist& bl) {
+  void encode_state(bufferlist& bl) const {
     ENCODE_START(2, 2, bl);
     ::encode(free, bl);
     ENCODE_FINISH(bl);
@@ -55,6 +55,17 @@ class InoTable : public MDSTable {
     DECODE_FINISH(bl);
   }
 
+  // To permit enc/decoding in isolation in dencoder
+  InoTable() : MDSTable(NULL, "inotable", true) {}
+  void encode(bufferlist& bl) const {
+    encode_state(bl);
+  }
+  void decode(bufferlist::iterator& bl) {
+    decode_state(bl);
+  }
+  void dump(Formatter *f) const;
+  static void generate_test_instances(list<InoTable*>& ls);
+
   void skip_inos(inodeno_t i);
 };
 
diff --git a/src/mds/Locker.cc b/src/mds/Locker.cc
index 1906c49..6a274bb 100644
--- a/src/mds/Locker.cc
+++ b/src/mds/Locker.cc
@@ -1298,7 +1298,7 @@ bool Locker::wrlock_start(SimpleLock *lock, MDRequest *mut, bool nowait)
   CInode *in = static_cast<CInode *>(lock->get_parent());
   client_t client = mut->get_client();
   bool want_scatter = !nowait && lock->get_parent()->is_auth() &&
-		      (in->has_subtree_root_dirfrag() ||
+		      (in->has_subtree_or_exporting_dirfrag() ||
 		       static_cast<ScatterLock*>(lock)->get_scatter_wanted());
 
   while (1) {
@@ -1799,8 +1799,10 @@ bool Locker::issue_caps(CInode *in, Capability *only_cap)
     // add in any xlocker-only caps (for locks this client is the xlocker for)
     allowed |= xlocker_allowed & in->get_xlocker_mask(it->first);
 
+    Session *session = mds->get_session(it->first);
     if (in->inode.inline_version != CEPH_INLINE_NONE &&
-        !mds->get_session(it->first)->connection->has_feature(CEPH_FEATURE_MDS_INLINE_DATA))
+	!(session && session->connection &&
+	  session->connection->has_feature(CEPH_FEATURE_MDS_INLINE_DATA)))
       allowed &= ~(CEPH_CAP_FILE_RD | CEPH_CAP_FILE_WR);
 
     int pending = cap->pending();
@@ -3920,7 +3922,7 @@ void Locker::scatter_eval(ScatterLock *lock, bool *need_issue)
   }
 
   CInode *in = static_cast<CInode*>(lock->get_parent());
-  if (!in->has_subtree_root_dirfrag() || in->is_base()) {
+  if (!in->has_subtree_or_exporting_dirfrag() || in->is_base()) {
     // i _should_ be sync.
     if (!lock->is_wrlocked() &&
 	lock->get_state() != LOCK_SYNC) {
@@ -4284,7 +4286,7 @@ void Locker::file_eval(ScatterLock *lock, bool *need_issue)
 	   !lock->is_rdlocked() &&
 	   //!lock->is_waiter_for(SimpleLock::WAIT_WR) &&
 	   ((wanted & (CEPH_CAP_GWR|CEPH_CAP_GBUFFER)) ||
-	    (in->inode.is_dir() && !in->has_subtree_root_dirfrag())) &&
+	    (in->inode.is_dir() && !in->has_subtree_or_exporting_dirfrag())) &&
 	   in->get_target_loner() >= 0) {
     dout(7) << "file_eval stable, bump to loner " << *lock
 	    << " on " << *lock->get_parent() << dendl;
@@ -4308,7 +4310,7 @@ void Locker::file_eval(ScatterLock *lock, bool *need_issue)
 	   !lock->is_waiter_for(SimpleLock::WAIT_WR) &&
 	   !(wanted & (CEPH_CAP_GWR|CEPH_CAP_GBUFFER)) &&
 	   !((lock->get_state() == LOCK_MIX) &&
-	     in->is_dir() && in->has_subtree_root_dirfrag())  // if we are a delegation point, stay where we are
+	     in->is_dir() && in->has_subtree_or_exporting_dirfrag())  // if we are a delegation point, stay where we are
 	   //((wanted & CEPH_CAP_RD) || 
 	   //in->is_replicated() || 
 	   //lock->get_num_client_lease() || 
diff --git a/src/mds/LogEvent.h b/src/mds/LogEvent.h
index fdf145c..e7e8a62 100644
--- a/src/mds/LogEvent.h
+++ b/src/mds/LogEvent.h
@@ -83,6 +83,7 @@ protected:
   virtual void encode(bufferlist& bl) const = 0;
   virtual void decode(bufferlist::iterator &bl) = 0;
   static LogEvent *decode(bufferlist &bl);
+  virtual void dump(Formatter *f) const = 0;
 
   void encode_with_header(bufferlist& bl) {
     ::encode(EVENT_NEW_ENCODING, bl);
diff --git a/src/mds/LogSegment.h b/src/mds/LogSegment.h
index c9fdfd7..2fffe3b 100644
--- a/src/mds/LogSegment.h
+++ b/src/mds/LogSegment.h
@@ -59,7 +59,7 @@ class LogSegment {
   set<dirfrag_t> uncommitted_fragments;
 
   // client request ids
-  map<int, tid_t> last_client_tids;
+  map<int, ceph_tid_t> last_client_tids;
 
   // table version
   version_t inotablev;
diff --git a/src/mds/MDBalancer.cc b/src/mds/MDBalancer.cc
index 06989b5..fbf24c9 100644
--- a/src/mds/MDBalancer.cc
+++ b/src/mds/MDBalancer.cc
@@ -1000,11 +1000,11 @@ void MDBalancer::hit_dir(utime_t now, CDir *dir, int type, int who, double amoun
       dir->is_auth()) {
 
     dout(20) << "hit_dir " << type << " pop is " << v << ", frag " << dir->get_frag()
-	     << " size " << dir->get_num_head_items() << dendl;
+	     << " size " << dir->get_frag_size() << dendl;
 
     // split
     if (g_conf->mds_bal_split_size > 0 &&
-	((dir->get_num_head_items() > (unsigned)g_conf->mds_bal_split_size) ||
+	(dir->should_split() ||
 	 (v > g_conf->mds_bal_split_rd && type == META_POP_IRD) ||
 	 (v > g_conf->mds_bal_split_wr && type == META_POP_IWR)) &&
 	split_queue.count(dir->dirfrag()) == 0) {
@@ -1013,8 +1013,7 @@ void MDBalancer::hit_dir(utime_t now, CDir *dir, int type, int who, double amoun
     }
 
     // merge?
-    if (dir->get_frag() != frag_t() &&
-	(dir->get_num_head_items() < (unsigned)g_conf->mds_bal_merge_size) &&
+    if (dir->get_frag() != frag_t() && dir->should_merge() &&
 	merge_queue.count(dir->dirfrag()) == 0) {
       dout(10) << "hit_dir " << type << " pop is " << v << ", putting in merge_queue: " << *dir << dendl;
       merge_queue.insert(dir->dirfrag());
diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc
index 080fe1b..b75bab0 100644
--- a/src/mds/MDCache.cc
+++ b/src/mds/MDCache.cc
@@ -344,18 +344,6 @@ void MDCache::create_empty_hierarchy(C_Gather *gather)
   adjust_subtree_auth(rootdir, mds->whoami);   
   rootdir->dir_rep = CDir::REP_ALL;   //NONE;
 
-  // create ceph dir
-  CInode *ceph = create_system_inode(MDS_INO_CEPH, S_IFDIR);
-  CDentry *dn = rootdir->add_primary_dentry(".ceph", ceph);
-  dn->_mark_dirty(mds->mdlog->get_current_segment());
-
-  CDir *cephdir = ceph->get_or_open_dirfrag(this, frag_t());
-  cephdir->dir_rep = CDir::REP_ALL;   //NONE;
-
-  ceph->inode.dirstat = cephdir->fnode.fragstat;
-
-  rootdir->fnode.fragstat.nsubdirs = 1;
-  rootdir->fnode.rstat = ceph->inode.rstat;
   rootdir->fnode.accounted_fragstat = rootdir->fnode.fragstat;
   rootdir->fnode.accounted_rstat = rootdir->fnode.rstat;
 
@@ -363,10 +351,6 @@ void MDCache::create_empty_hierarchy(C_Gather *gather)
   root->inode.rstat = rootdir->fnode.rstat;
   root->inode.accounted_rstat = root->inode.rstat;
 
-  cephdir->mark_complete();
-  cephdir->mark_dirty(cephdir->pre_dirty(), mds->mdlog->get_current_segment());
-  cephdir->commit(0, gather->new_sub());
-
   rootdir->mark_complete();
   rootdir->mark_dirty(rootdir->pre_dirty(), mds->mdlog->get_current_segment());
   rootdir->commit(0, gather->new_sub());
@@ -380,7 +364,6 @@ void MDCache::create_mydir_hierarchy(C_Gather *gather)
   char myname[10];
   snprintf(myname, sizeof(myname), "mds%d", mds->whoami);
   CInode *my = create_system_inode(MDS_INO_MDSDIR(mds->whoami), S_IFDIR);
-  //cephdir->add_remote_dentry(myname, MDS_INO_MDSDIR(mds->whoami), S_IFDIR);
 
   CDir *mydir = my->get_or_open_dirfrag(this, frag_t());
   adjust_subtree_auth(mydir, mds->whoami);   
@@ -1086,12 +1069,10 @@ void MDCache::get_force_dirfrag_bound_set(vector<dirfrag_t>& dfs, set<CDir*>& bo
 	    all = false;
 	  }
 	}
-	if (all) {
+	if (all)
 	  fgls.push_back(approx_fg);
-	} else {
+	else
 	  diri->dirfragtree.get_leaves_under(fg, fgls);
-	  assert(!fgls.empty());
-	}
       }
       dout(10) << "  frag " << fg << " contains " << fgls << dendl;
       for (list<frag_t>::iterator r = fgls.begin(); r != fgls.end(); ++r) {
@@ -1103,24 +1084,13 @@ void MDCache::get_force_dirfrag_bound_set(vector<dirfrag_t>& dfs, set<CDir*>& bo
   }
 }
 
-
 void MDCache::adjust_bounded_subtree_auth(CDir *dir, vector<dirfrag_t>& bound_dfs, pair<int,int> auth)
 {
   dout(7) << "adjust_bounded_subtree_auth " << dir->get_dir_auth() << " -> " << auth
-	  << " on " << *dir 
-	  << " bound_dfs " << bound_dfs
-	  << dendl;
-  
-  // make bounds list
+	  << " on " << *dir << " bound_dfs " << bound_dfs << dendl;
+
   set<CDir*> bounds;
-  for (vector<dirfrag_t>::iterator p = bound_dfs.begin();
-       p != bound_dfs.end();
-       ++p) {
-    CDir *bd = get_dirfrag(*p);
-    if (bd) 
-      bounds.insert(bd);
-  }
-  
+  get_force_dirfrag_bound_set(bound_dfs, bounds);
   adjust_bounded_subtree_auth(dir, bounds, auth);
 }
 
@@ -2002,8 +1972,8 @@ void MDCache::predirty_journal_parents(Mutation *mut, EMetaBlob *blob,
     }
 
     bool stop = false;
-    if (!pin->can_auth_pin() || pin->is_ambiguous_auth()) {
-      dout(10) << "predirty_journal_parents can't auth pin or ambig on " << *pin << dendl;
+    if (!pin->is_auth() || (!mut->is_auth_pinned(pin) && !pin->can_auth_pin())) {
+      dout(10) << "predirty_journal_parents !auth or ambig or can't authpin on " << *pin << dendl;
       stop = true;
     }
 
@@ -2077,9 +2047,9 @@ void MDCache::predirty_journal_parents(Mutation *mut, EMetaBlob *blob,
 	pi->mtime = pi->ctime = pi->dirstat.mtime;
       dout(20) << "predirty_journal_parents     gives " << pi->dirstat << " on " << *pin << dendl;
 
-      if (pi->dirstat.size() < 0)
-	assert(!"negative dirstat size" == g_conf->mds_verify_scatter);
       if (parent->get_frag() == frag_t()) { // i.e., we are the only frag
+	if (pi->dirstat.size() < 0)
+	  assert(!"negative dirstat size" == g_conf->mds_verify_scatter);
 	if (pi->dirstat.size() != pf->fragstat.size()) {
 	  mds->clog.error() << "unmatched fragstat size on single dirfrag "
 	     << parent->dirfrag() << ", inode has " << pi->dirstat
@@ -3016,11 +2986,7 @@ void MDCache::handle_resolve(MMDSResolve *m)
     CDir *dir = get_force_dirfrag(pi->first);
     if (!dir)
       continue;
-
-    set<CDir*> bounds;
-    get_force_dirfrag_bound_set(pi->second, bounds);
-
-    adjust_bounded_subtree_auth(dir, bounds, from);
+    adjust_bounded_subtree_auth(dir, pi->second, from);
     try_subtree_merge(dir);
   }
 
@@ -3158,15 +3124,12 @@ void MDCache::handle_resolve_ack(MMDSResolveAck *ack)
       }
     } else {
       MDRequest *mdr = request_get(*p);
-      if (mdr->more()->slave_commit) {
-	Context *fin = mdr->more()->slave_commit;
-	mdr->more()->slave_commit = 0;
-	fin->complete(-1);
+      mdr->aborted = true;
+      if (mdr->slave_request) {
+	if (mdr->more()->slave_commit) // journaling slave prepare ?
+	  add_rollback(*p, from);
       } else {
-	if (mdr->slave_request) 
-	  mdr->aborted = true;
-	else
-	  request_finish(mdr);
+	request_finish(mdr);
       }
     }
   }
@@ -3185,7 +3148,7 @@ void MDCache::add_uncommitted_slave_update(metareqid_t reqid, int master, MDSlav
 {
   assert(uncommitted_slave_updates[master].count(reqid) == 0);
   uncommitted_slave_updates[master][reqid] = su;
-  for(set<CDir*>::iterator p = su->olddirs.begin(); p != su->olddirs.end(); ++p)
+  for(set<CInode*>::iterator p = su->olddirs.begin(); p != su->olddirs.end(); ++p)
     uncommitted_slave_rename_olddir[*p]++;
   for(set<CInode*>::iterator p = su->unlinked.begin(); p != su->unlinked.end(); ++p)
     uncommitted_slave_unlink[*p]++;
@@ -3200,25 +3163,38 @@ void MDCache::finish_uncommitted_slave_update(metareqid_t reqid, int master)
   if (uncommitted_slave_updates[master].empty())
     uncommitted_slave_updates.erase(master);
   // discard the non-auth subtree we renamed out of
-  for(set<CDir*>::iterator p = su->olddirs.begin(); p != su->olddirs.end(); ++p) {
-    CDir *dir = *p;
-    uncommitted_slave_rename_olddir[dir]--;
-    if (uncommitted_slave_rename_olddir[dir] == 0) {
-      uncommitted_slave_rename_olddir.erase(dir);
-      CDir *root = get_subtree_root(dir);
-      if (root->get_dir_auth() == CDIR_AUTH_UNDEF)
-	try_trim_non_auth_subtree(root);
-    }
+  for(set<CInode*>::iterator p = su->olddirs.begin(); p != su->olddirs.end(); ++p) {
+    CInode *diri = *p;
+    map<CInode*, int>::iterator it = uncommitted_slave_rename_olddir.find(diri);
+    assert(it != uncommitted_slave_rename_olddir.end());
+    it->second--;
+    if (it->second == 0) {
+      uncommitted_slave_rename_olddir.erase(it);
+      list<CDir*> ls;
+      diri->get_dirfrags(ls);
+      for (list<CDir*>::iterator q = ls.begin(); q != ls.end(); ++q) {
+	CDir *root = get_subtree_root(*q);
+	if (root->get_dir_auth() == CDIR_AUTH_UNDEF) {
+	  try_trim_non_auth_subtree(root);
+	  if (*q != root)
+	    break;
+	}
+      }
+    } else
+      assert(it->second > 0);
   }
   // removed the inodes that were unlinked by slave update
   for(set<CInode*>::iterator p = su->unlinked.begin(); p != su->unlinked.end(); ++p) {
     CInode *in = *p;
-    uncommitted_slave_unlink[in]--;
-    if (uncommitted_slave_unlink[in] == 0) {
-      uncommitted_slave_unlink.erase(in);
+    map<CInode*, int>::iterator it = uncommitted_slave_unlink.find(in);
+    assert(it != uncommitted_slave_unlink.end());
+    it->second--;
+    if (it->second == 0) {
+      uncommitted_slave_unlink.erase(it);
       if (!in->get_projected_parent_dn())
 	mds->mdcache->remove_inode_recursive(in);
-    }
+    } else
+      assert(it->second > 0);
   }
   delete su;
 }
@@ -3469,9 +3445,14 @@ void MDCache::recalc_auth_bits()
       dfq.pop_front();
 
       // dir
-      if (auth) 
+      if (auth) {
 	dir->state_set(CDir::STATE_AUTH);
-      else {
+      } else {
+	// close empty non-auth dirfrag
+	if (!dir->is_subtree_root() && dir->get_num_any() == 0) {
+	  dir->inode->close_dirfrag(dir->get_frag());
+	  continue;
+	}
 	dir->state_set(CDir::STATE_REJOINING);
 	dir->state_clear(CDir::STATE_AUTH);
 	dir->state_clear(CDir::STATE_COMPLETE);
@@ -3620,6 +3601,8 @@ void MDCache::rejoin_send_rejoins()
 	 ++p) {
       assert(cap_export_targets.count(p->first));
       int target = cap_export_targets[p->first];
+      if (rejoins.count(target) == 0)
+	continue;
       rejoins[target]->cap_exports[p->first] = p->second;
       for (map<client_t,ceph_mds_cap_reconnect>::iterator q = p->second.begin();
 	   q != p->second.end();
@@ -4445,7 +4428,7 @@ void MDCache::handle_cache_rejoin_strong(MMDSCacheRejoin *strong)
       for (list<frag_t>::iterator q = ls.begin(); q != ls.end(); ++q) {
 	CDir *dir = diri->get_dirfrag(*q);
 	if (!dir)
-	  dir = rejoin_invent_dirfrag(p->first);
+	  dir = rejoin_invent_dirfrag(dirfrag_t(diri->ino(), *q));
 	else
 	  dout(10) << " have(approx) " << *dir << dendl;
 	dir->add_replica(from, p->second.nonce);
@@ -4821,8 +4804,6 @@ void MDCache::handle_cache_rejoin_ack(MMDSCacheRejoin *ack)
     assert(in);
     bufferlist::iterator q = basebl.begin();
     in->_decode_base(q);
-    // auth will send a full inode for any inode it got scatterlock state for.
-    in->clear_scatter_dirty();
     dout(10) << " got inode base " << *in << dendl;
   }
 
@@ -6310,6 +6291,11 @@ bool MDCache::trim(int max)
     CDir *dir = p->first;
     ++p;
     if (!dir->is_auth() && !dir->get_inode()->is_auth()) {
+      // don't trim subtree root if its auth MDS is recovering.
+      // This simplify the cache rejoin code.
+      if (dir->is_subtree_root() &&
+	  rejoin_ack_gather.count(dir->get_dir_auth().first))
+	continue;
       if (dir->get_num_ref() == 1)  // subtree pin
 	trim_dirfrag(dir, 0, expiremap);
     }
@@ -6503,8 +6489,11 @@ bool MDCache::trim_inode(CDentry *dn, CInode *in, CDir *con, map<int, MCacheExpi
     // DIR
     list<CDir*> dfls;
     in->get_dirfrags(dfls);
-    for (list<CDir*>::iterator p = dfls.begin(); p != dfls.end(); ++p)
-      trim_dirfrag(*p, con ? con:*p, expiremap);  // if no container (e.g. root dirfrag), use *p
+    for (list<CDir*>::iterator p = dfls.begin(); p != dfls.end(); ++p) {
+      CDir *dir = *p;
+      assert(!dir->is_subtree_root());
+      trim_dirfrag(dir, con ? con:dir, expiremap);  // if no container (e.g. root dirfrag), use *p
+    }
   }
   
   // INODE
@@ -6599,6 +6588,9 @@ void MDCache::trim_non_auth()
       // add back into lru (at the top)
       lru.lru_insert_top(dn);
 
+      if (dnl->is_remote() && dnl->get_inode() && !dnl->get_inode()->is_auth())
+	dn->unlink_remote(dnl);
+
       if (dn->get_dir()->get_inode()->is_stray()) {
 	dn->state_set(CDentry::STATE_STRAY);
 	if (dnl->is_primary() && dnl->get_inode()->inode.nlink == 0)
@@ -6642,6 +6634,9 @@ void MDCache::trim_non_auth()
       dir->remove_dentry(dn);
       // adjust the dir state
       dir->state_clear(CDir::STATE_COMPLETE);  // dir incomplete!
+      // close empty non-auth dirfrag
+      if (!dir->is_subtree_root() && dir->get_num_any() == 0)
+	dir->inode->close_dirfrag(dir->get_frag());
     }
   }
 
@@ -6695,11 +6690,8 @@ bool MDCache::trim_non_auth_subtree(CDir *dir)
 {
   dout(10) << "trim_non_auth_subtree(" << dir << ") " << *dir << dendl;
 
-  if (uncommitted_slave_rename_olddir.count(dir) || // preserve the dir for rollback
-      my_ambiguous_imports.count(dir->dirfrag()))
-    return true;
+  bool keep_dir = !can_trim_non_auth_dirfrag(dir);
 
-  bool keep_dir = false;
   CDir::map_t::iterator j = dir->begin();
   CDir::map_t::iterator i = j;
   while (j != dir->end()) {
@@ -6716,13 +6708,10 @@ bool MDCache::trim_non_auth_subtree(CDir *dir)
         for (list<CDir*>::iterator subdir = subdirs.begin();
             subdir != subdirs.end();
             ++subdir) {
-          if (uncommitted_slave_rename_olddir.count(*subdir) || // preserve the dir for rollback
-	      my_ambiguous_imports.count((*subdir)->dirfrag()) ||
-	      (*subdir)->is_subtree_root()) {
+          if ((*subdir)->is_subtree_root()) {
             keep_inode = true;
-            dout(10) << "trim_non_auth_subtree(" << dir << ") subdir " << *subdir << "is kept!" << dendl;
-          }
-          else {
+            dout(10) << "trim_non_auth_subtree(" << dir << ") keeping " << **subdir << dendl;
+          } else {
             if (trim_non_auth_subtree(*subdir))
               keep_inode = true;
             else {
@@ -6741,8 +6730,9 @@ bool MDCache::trim_non_auth_subtree(CDir *dir)
         dir->remove_dentry(dn);
       } else {
         dout(20) << "trim_non_auth_subtree(" << dir << ") keeping inode " << in << " with dentry " << dn <<dendl;
-        keep_dir = true;
       }
+    } else if (keep_dir && dnl->is_null()) { // keep null dentry for slave rollback
+      dout(20) << "trim_non_auth_subtree(" << dir << ") keeping dentry " << dn <<dendl;
     } else { // just remove it
       dout(20) << "trim_non_auth_subtree(" << dir << ") removing dentry " << dn << dendl;
       if (dnl->is_remote())
@@ -6754,7 +6744,7 @@ bool MDCache::trim_non_auth_subtree(CDir *dir)
    * We've now checked all our children and deleted those that need it.
    * Now return to caller, and tell them if *we're* a keeper.
    */
-  return keep_dir;
+  return keep_dir || dir->get_num_any();
 }
 
 /*
@@ -6773,7 +6763,8 @@ void MDCache::try_trim_non_auth_subtree(CDir *dir)
   for (set<CDir*>::iterator p = bounds.begin(); p != bounds.end(); ++p) {
     CDir *bd = *p;
     if (bd->get_dir_auth().first != mds->whoami &&  // we are not auth
-	bd->get_num_any() == 0) {                   // and empty
+	bd->get_num_any() == 0 && // and empty
+	can_trim_non_auth_dirfrag(bd)) {
       CInode *bi = bd->get_inode();
       dout(10) << " closing empty non-auth child subtree " << *bd << dendl;
       remove_subtree(bd);
@@ -6789,8 +6780,20 @@ void MDCache::try_trim_non_auth_subtree(CDir *dir)
     // can we trim this subtree (and possibly our ancestors) too?
     while (true) {
       CInode *diri = dir->get_inode();
-      if (diri->is_base())
+      if (diri->is_base()) {
+	if (!diri->is_root() && diri->authority().first != mds->whoami) {
+	  dout(10) << " closing empty non-auth subtree " << *dir << dendl;
+	  remove_subtree(dir);
+	  dir->mark_clean();
+	  diri->close_dirfrag(dir->get_frag());
+
+	  dout(10) << " removing " << *diri << dendl;
+	  assert(!diri->get_parent_dn());
+	  assert(diri->get_num_ref() == 0);
+	  remove_inode(diri);
+	}
 	break;
+      }
 
       CDir *psub = get_subtree_root(diri->get_parent_dir());
       dout(10) << " parent subtree is " << *psub << dendl;
@@ -6913,6 +6916,22 @@ void MDCache::handle_cache_expire(MCacheExpire *m)
       if (!dir) {
 	CInode *diri = get_inode(it->first.ino);
 	if (diri) {
+	  if (mds->is_rejoin() &&
+	      rejoin_ack_gather.count(mds->whoami) && // haven't sent rejoin ack yet
+	      !diri->is_replica(from)) {
+	    list<CDir*> ls;
+	    diri->get_nested_dirfrags(ls);
+	    dout(7) << " dir expire on dirfrag " << it->first << " from mds." << from
+		    << " while rejoining, inode isn't replicated" << dendl;
+	    for (list<CDir*>::iterator q = ls.begin(); q != ls.end(); ++q) {
+	      dir = *q;
+	      if (dir->is_replica(from)) {
+		dout(7) << " dir expire on " << *dir << " from mds." << from << dendl;
+		dir->remove_replica(from);
+	      }
+	    }
+	    continue;
+	  }
 	  CDir *other = diri->get_approx_dirfrag(it->first.frag);
 	  if (other) {
 	    dout(7) << " dir expire on dirfrag " << it->first << " from mds." << from
@@ -8684,7 +8703,7 @@ void MDCache::find_ino_peers(inodeno_t ino, Context *c, int hint)
   dout(5) << "find_ino_peers " << ino << " hint " << hint << dendl;
   assert(!have_inode(ino));
   
-  tid_t tid = ++find_ino_peer_last_tid;
+  ceph_tid_t tid = ++find_ino_peer_last_tid;
   find_ino_peer_info_t& fip = find_ino_peer[tid];
   fip.ino = ino;
   fip.tid = tid;
@@ -8698,8 +8717,7 @@ void MDCache::_do_find_ino_peer(find_ino_peer_info_t& fip)
 {
   set<int> all, active;
   mds->mdsmap->get_mds_set(all);
-  mds->mdsmap->get_active_mds_set(active);
-  mds->mdsmap->get_mds_set(active, MDSMap::STATE_STOPPING);
+  mds->mdsmap->get_clientreplay_or_active_or_stopping_mds_set(active);
 
   dout(10) << "_do_find_ino_peer " << fip.tid << " " << fip.ino
 	   << " active " << active << " all " << all
@@ -8748,7 +8766,7 @@ void MDCache::handle_find_ino(MMDSFindIno *m)
 
 void MDCache::handle_find_ino_reply(MMDSFindInoReply *m)
 {
-  map<tid_t, find_ino_peer_info_t>::iterator p = find_ino_peer.find(m->tid);
+  map<ceph_tid_t, find_ino_peer_info_t>::iterator p = find_ino_peer.find(m->tid);
   if (p != find_ino_peer.end()) {
     dout(10) << "handle_find_ino_reply " << *m << dendl;
     find_ino_peer_info_t& fip = p->second;
@@ -8790,7 +8808,7 @@ void MDCache::handle_find_ino_reply(MMDSFindInoReply *m)
 void MDCache::kick_find_ino_peers(int who)
 {
   // find_ino_peers requests we should move on from
-  for (map<tid_t,find_ino_peer_info_t>::iterator p = find_ino_peer.begin();
+  for (map<ceph_tid_t,find_ino_peer_info_t>::iterator p = find_ino_peer.begin();
        p != find_ino_peer.end();
        ++p) {
     find_ino_peer_info_t& fip = p->second;
@@ -8880,7 +8898,7 @@ void MDCache::request_finish(MDRequest *mdr)
   if (mdr->has_more() && mdr->more()->slave_commit) {
     Context *fin = mdr->more()->slave_commit;
     mdr->more()->slave_commit = 0;
-    fin->complete(0);   // this must re-call request_finish.
+    fin->complete(mdr->aborted ? -1 : 0);   // this must re-call request_finish.
     return; 
   }
 
@@ -10070,7 +10088,7 @@ void MDCache::discover_ino(CDir *base,
 
 void MDCache::kick_discovers(int who)
 {
-  for (map<tid_t,discover_info_t>::iterator p = discovers.begin();
+  for (map<ceph_tid_t,discover_info_t>::iterator p = discovers.begin();
        p != discovers.end();
        ++p) {
     if (p->second.mds != who)
@@ -10217,14 +10235,20 @@ void MDCache::handle_discover(MDiscover *dis)
       break;
     }
 
-    // open dir?
-    if (!curdir) 
+    if (!curdir) { // open dir?
+      if (cur->is_frozen()) {
+	if (!reply->is_empty()) {
+	  dout(7) << *cur << " is frozen, non-empty reply, stopping" << dendl;
+	  break;
+	}
+	dout(7) << *cur << " is frozen, empty reply, waiting" << dendl;
+	cur->add_waiter(CInode::WAIT_UNFREEZE, new C_MDS_RetryMessage(mds, dis));
+	reply->put();
+	return;
+      }
       curdir = cur->get_or_open_dirfrag(this, fg);
-    assert(curdir);
-    assert(curdir->is_auth());
-    
-    // is dir frozen?
-    if (curdir->is_frozen()) {
+    } else if (curdir->is_frozen_tree() ||
+	       (curdir->is_frozen_dir() && fragment_are_all_frozen(curdir))) {
       if (dis->wants_base_dir() && dis->get_base_dir_frag() != curdir->get_frag()) {
 	dout(7) << *curdir << " is frozen, dirfrag mismatch, stopping" << dendl;
 	reply->set_flag_error_dir();
@@ -10285,7 +10309,8 @@ void MDCache::handle_discover(MDiscover *dis)
 	dout(7) << "incomplete dir contents for " << *curdir << ", fetching" << dendl;
 	if (reply->is_empty()) {
 	  // fetch and wait
-	  curdir->fetch(new C_MDS_RetryMessage(mds, dis));
+	  curdir->fetch(new C_MDS_RetryMessage(mds, dis),
+			dis->wants_base_dir() && curdir->get_version() == 0);
 	  reply->put();
 	  return;
 	} else {
@@ -10303,23 +10328,7 @@ void MDCache::handle_discover(MDiscover *dis)
 	reply->set_flag_error_ino();
 	break;
       }
-      
-      // is this a new mds dir?
-      /*
-      if (curdir->ino() == MDS_INO_CEPH) {
-	char t[10];
-	snprintf(t, sizeof(t), "mds%d", from);
-	if (t == dis->get_dentry(i)) {
-	  // yes.
-	  _create_mdsdir_dentry(curdir, from, t, new C_MDS_RetryMessage(mds, dis));
-	  //_create_system_file(curdir, t, create_system_inode(MDS_INO_MDSDIR(from), S_IFDIR),
-	  //new C_MDS_RetryMessage(mds, dis));
-	  reply->put();
-	  return;
-	}
-      }	
-      */
-      
+
       // send null dentry
       dout(7) << "dentry " << dis->get_dentry(i) << " dne, returning null in "
 	      << *curdir << dendl;
@@ -10420,7 +10429,7 @@ void MDCache::handle_discover_reply(MDiscoverReply *m)
 
   // decrement discover counters
   if (m->get_tid()) {
-    map<tid_t,discover_info_t>::iterator p = discovers.find(m->get_tid());
+    map<ceph_tid_t,discover_info_t>::iterator p = discovers.find(m->get_tid());
     if (p != discovers.end()) {
       dout(10) << " found tid " << m->get_tid() << dendl;
       discovers.erase(p);
@@ -11298,12 +11307,25 @@ void MDCache::fragment_mark_and_complete(list<CDir*>& dirs)
        ++p) {
     CDir *dir = *p;
 
+    bool ready = true;
     if (!dir->is_complete()) {
       dout(15) << " fetching incomplete " << *dir << dendl;
-      dir->fetch(gather.new_sub(),
-		 true);  // ignore authpinnability
-    } 
-    else if (!dir->state_test(CDir::STATE_DNPINNEDFRAG)) {
+      dir->fetch(gather.new_sub(), true);  // ignore authpinnability
+      ready = false;
+    }
+    if (dir->get_frag() == frag_t() && dir->is_new()) {
+      // The COMPLETE flag gets lost if we fragment a new dirfrag, then rollback
+      // the operation. To avoid CDir::fetch() complaining about missing object,
+      // we commit new dirfrag first.
+      dout(15) << " committing new " << *dir << dendl;
+      assert(dir->is_dirty());
+      dir->commit(0, gather.new_sub(), true);
+      ready = false;
+    }
+    if (!ready)
+      continue;
+
+    if (!dir->state_test(CDir::STATE_DNPINNEDFRAG)) {
       dout(15) << " marking " << *dir << dendl;
       for (CDir::map_t::iterator p = dir->items.begin();
 	   p != dir->items.end();
@@ -11315,8 +11337,7 @@ void MDCache::fragment_mark_and_complete(list<CDir*>& dirs)
       }
       dir->state_set(CDir::STATE_DNPINNEDFRAG);
       dir->auth_unpin(dir);
-    }
-    else {
+    } else {
       dout(15) << " already marked " << *dir << dendl;
     }
   }
@@ -11355,6 +11376,20 @@ void MDCache::fragment_unmark_unfreeze_dirs(list<CDir*>& dirs)
   }
 }
 
+bool MDCache::fragment_are_all_frozen(CDir *dir)
+{
+  assert(dir->is_frozen_dir());
+  map<dirfrag_t,fragment_info_t>::iterator p;
+  for (p = fragments.lower_bound(dirfrag_t(dir->ino(), 0));
+       p != fragments.end() && p->first.ino == dir->ino();
+       ++p) {
+    if (p->first.frag.contains(dir->get_frag()))
+      return p->second.has_frozen;
+  }
+  assert(0);
+  return false;
+}
+
 void MDCache::fragment_freeze_inc_num_waiters(CDir *dir)
 {
   map<dirfrag_t,fragment_info_t>::iterator p;
@@ -11382,7 +11417,7 @@ void MDCache::find_stale_fragment_freeze()
     dirfrag_t df = p->first;
     fragment_info_t& info = p->second;
     ++p;
-    if (info.dirs_frozen)
+    if (info.has_frozen)
       continue;
     CDir *dir;
     int total_auth_pins = 0;
@@ -11445,9 +11480,7 @@ class C_MDC_FragmentCommit : public Context {
   list<CDir*> resultfrags;
 public:
   C_MDC_FragmentCommit(MDCache *m, dirfrag_t df, list<CDir*>& l) :
-    mdcache(m), basedirfrag(df) {
-    resultfrags.swap(l);
-  }
+    mdcache(m), basedirfrag(df), resultfrags(l) {}
   virtual void finish(int r) {
     mdcache->_fragment_committed(basedirfrag, resultfrags);
   }
@@ -11482,7 +11515,7 @@ void MDCache::fragment_frozen(dirfrag_t basedirfrag, int r)
   dout(10) << "fragment_frozen " << basedirfrag.frag << " by " << info.bits
 	   << " on " << info.dirs.front()->get_inode() << dendl;
 
-  info.dirs_frozen = true;
+  info.has_frozen = true;
 
   MDRequest *mdr = request_start_internal(CEPH_MDS_OP_FRAGMENTDIR);
   mdr->more()->fragment_base = basedirfrag;
@@ -11550,10 +11583,10 @@ void MDCache::dispatch_fragment_dir(MDRequest *mdr)
        p != info.resultfrags.end();
        ++p) {
     if (diri->is_auth()) {
-      le->metablob.add_fragmented_dir(*p, false);
+      le->metablob.add_fragmented_dir(*p, false, false);
     } else {
       (*p)->state_set(CDir::STATE_DIRTYDFT);
-      le->metablob.add_fragmented_dir(*p, true);
+      le->metablob.add_fragmented_dir(*p, false, true);
     }
   }
 
@@ -11651,7 +11684,12 @@ void MDCache::_fragment_stored(MDRequest *mdr)
 
     mds->send_message_mds(notify, p->first);
   }
-  
+
+  // journal commit
+  EFragment *le = new EFragment(mds->mdlog, EFragment::OP_COMMIT, basedirfrag, info.bits);
+  mds->mdlog->start_submit_entry(le, new C_MDC_FragmentCommit(this, basedirfrag,
+							      info.resultfrags));
+
   mds->locker->drop_locks(mdr);
 
   // unfreeze resulting frags
@@ -11674,11 +11712,6 @@ void MDCache::_fragment_stored(MDRequest *mdr)
     dir->unfreeze_dir();
   }
 
-  // journal commit
-  EFragment *le = new EFragment(mds->mdlog, EFragment::OP_COMMIT, basedirfrag, info.bits);
-  mds->mdlog->start_submit_entry(le, new C_MDC_FragmentCommit(this, basedirfrag,
-							      info.resultfrags));
-
   fragments.erase(it);
   request_finish(mdr);
 }
@@ -11794,15 +11827,8 @@ void MDCache::add_uncommitted_fragment(dirfrag_t basedirfrag, int bits, list<fra
   uf.bits = bits;
   uf.ls = ls;
   ls->uncommitted_fragments.insert(basedirfrag);
-  if (rollback) {
+  if (rollback)
     uf.rollback.swap(*rollback);
-    // preserve COMPLETE flag for newly created dirfrag
-    if (bits > 0 && basedirfrag.frag == frag_t()) {
-      CDir *dir = get_dirfrag(basedirfrag);
-      if (dir && dir->is_complete())
-	uf.complete = true;
-    }
-  }
 }
 
 void MDCache::finish_uncommitted_fragment(dirfrag_t basedirfrag, int op)
@@ -11866,6 +11892,7 @@ void MDCache::rollback_uncommitted_fragments()
     LogSegment *ls = mds->mdlog->get_current_segment();
     EFragment *le = new EFragment(mds->mdlog, EFragment::OP_ROLLBACK, p->first, uf.bits);
     mds->mdlog->start_entry(le);
+    bool diri_auth = (diri->authority() != CDIR_AUTH_UNDEF);
 
     list<frag_t> old_frags;
     diri->dirfragtree.get_leaves_under(p->first.frag, old_frags);
@@ -11887,29 +11914,40 @@ void MDCache::rollback_uncommitted_fragments()
 	dir->set_version(rollback.fnode.version);
 	dir->fnode = rollback.fnode;
 
-	if (uf.complete)
-	  dir->mark_complete();
 	dir->_mark_dirty(ls);
 
 	if (!(dir->fnode.rstat == dir->fnode.accounted_rstat)) {
 	  dout(10) << "    dirty nestinfo on " << *dir << dendl;
 	  mds->locker->mark_updated_scatterlock(&dir->inode->nestlock);
 	  ls->dirty_dirfrag_nest.push_back(&dir->inode->item_dirty_dirfrag_nest);
-	  dir->get_inode()->nestlock.mark_dirty();
 	}
 	if (!(dir->fnode.fragstat == dir->fnode.accounted_fragstat)) {
 	  dout(10) << "    dirty fragstat on " << *dir << dendl;
 	  mds->locker->mark_updated_scatterlock(&dir->inode->filelock);
 	  ls->dirty_dirfrag_dir.push_back(&dir->inode->item_dirty_dirfrag_dir);
-	  dir->get_inode()->filelock.mark_dirty();
 	}
 
 	le->add_orig_frag(dir->get_frag());
 	le->metablob.add_dir_context(dir);
-	le->metablob.add_dir(dir, true, uf.complete);
+	if (diri_auth) {
+	  le->metablob.add_fragmented_dir(dir, true, false);
+	} else {
+	  dout(10) << "    dirty dirfragtree on " << *dir << dendl;
+	  dir->state_set(CDir::STATE_DIRTYDFT);
+	  le->metablob.add_fragmented_dir(dir, true, true);
+	}
       }
     }
 
+    if (diri_auth) {
+      diri->project_inode()->version = diri->pre_dirty();
+      diri->pop_and_dirty_projected_inode(ls); // hacky
+      le->metablob.add_primary_dentry(diri->get_projected_parent_dn(), diri, true);
+    } else {
+      mds->locker->mark_updated_scatterlock(&diri->dirfragtreelock);
+      ls->dirty_dirfrag_dirfragtree.push_back(&diri->item_dirty_dirfrag_dirfragtree);
+    }
+
     if (g_conf->mds_debug_frag)
       diri->verify_dirfrags();
 
diff --git a/src/mds/MDCache.h b/src/mds/MDCache.h
index b3c5ad5..422b94d 100644
--- a/src/mds/MDCache.h
+++ b/src/mds/MDCache.h
@@ -131,7 +131,7 @@ public:
 
   // -- discover --
   struct discover_info_t {
-    tid_t tid;
+    ceph_tid_t tid;
     int mds;
     inodeno_t ino;
     frag_t frag;
@@ -144,12 +144,12 @@ public:
     discover_info_t() : tid(0), mds(-1), snap(CEPH_NOSNAP), want_base_dir(false), want_xlocked(false) {}
   };
 
-  map<tid_t, discover_info_t> discovers;
-  tid_t discover_last_tid;
+  map<ceph_tid_t, discover_info_t> discovers;
+  ceph_tid_t discover_last_tid;
 
   void _send_discover(discover_info_t& dis);
   discover_info_t& _create_discover(int mds) {
-    tid_t t = ++discover_last_tid;
+    ceph_tid_t t = ++discover_last_tid;
     discover_info_t& d = discovers[t];
     d.tid = t;
     d.mds = mds;
@@ -317,7 +317,7 @@ protected:
   map<int, map<dirfrag_t, vector<dirfrag_t> > > other_ambiguous_imports;  
 
   map<int, map<metareqid_t, MDSlaveUpdate*> > uncommitted_slave_updates;  // slave: for replay.
-  map<CDir*, int> uncommitted_slave_rename_olddir;  // slave: preserve the non-auth dir until seeing commit.
+  map<CInode*, int> uncommitted_slave_rename_olddir;  // slave: preserve the non-auth dir until seeing commit.
   map<CInode*, int> uncommitted_slave_unlink;  // slave: preserve the unlinked inode until seeing commit.
 
   // track master requests whose slaves haven't acknowledged commit
@@ -581,6 +581,10 @@ public:
   void trim_non_auth();      // trim out trimmable non-auth items
   bool trim_non_auth_subtree(CDir *directory);
   void try_trim_non_auth_subtree(CDir *dir);
+  bool can_trim_non_auth_dirfrag(CDir *dir) {
+    return my_ambiguous_imports.count((dir)->dirfrag()) == 0 &&
+	   uncommitted_slave_rename_olddir.count(dir->inode) == 0;
+  }
 
   void trim_client_leases();
   void check_memory_usage();
@@ -617,6 +621,13 @@ public:
       return NULL;
     return in->get_dirfrag(df.frag);
   }
+  CDir* get_dirfrag(inodeno_t ino, const string& dn) {
+    CInode *in = get_inode(ino);
+    if (!in)
+      return NULL;
+    frag_t fg = in->pick_dirfrag(dn);
+    return in->get_dirfrag(fg);
+  }
   CDir* get_force_dirfrag(dirfrag_t df) {
     CInode *diri = get_inode(df.ino);
     if (!diri)
@@ -802,7 +813,7 @@ protected:
     open_ino_info_t() : checking(-1), auth_hint(-1),
       check_peers(true), fetch_backtrace(true), discover(false) {}
   };
-  tid_t open_ino_last_tid;
+  ceph_tid_t open_ino_last_tid;
   map<inodeno_t,open_ino_info_t> opening_inodes;
 
   void _open_ino_backtrace_fetched(inodeno_t ino, bufferlist& bl, int err);
@@ -830,7 +841,7 @@ public:
   // -- find_ino_peer --
   struct find_ino_peer_info_t {
     inodeno_t ino;
-    tid_t tid;
+    ceph_tid_t tid;
     Context *fin;
     int hint;
     int checking;
@@ -839,8 +850,8 @@ public:
     find_ino_peer_info_t() : tid(0), fin(NULL), hint(-1), checking(-1) {}
   };
 
-  map<tid_t, find_ino_peer_info_t> find_ino_peer;
-  tid_t find_ino_peer_last_tid;
+  map<ceph_tid_t, find_ino_peer_info_t> find_ino_peer;
+  ceph_tid_t find_ino_peer_last_tid;
 
   void find_ino_peers(inodeno_t ino, Context *c, int hint=-1);
   void _do_find_ino_peer(find_ino_peer_info_t& fip);
@@ -946,12 +957,11 @@ private:
   struct ufragment {
     int bits;
     bool committed;
-    bool complete;
     LogSegment *ls;
     list<Context*> waiters;
     list<frag_t> old_frags;
     bufferlist rollback;
-    ufragment() : bits(0), committed(false), complete(false), ls(NULL) {}
+    ufragment() : bits(0), committed(false), ls(NULL) {}
   };
   map<dirfrag_t, ufragment> uncommitted_fragments;
 
@@ -961,11 +971,11 @@ private:
     list<CDir*> resultfrags;
     MDRequest *mdr;
     // for deadlock detection
-    bool dirs_frozen;
+    bool has_frozen;
     utime_t last_cum_auth_pins_change;
     int last_cum_auth_pins;
     int num_remote_waiters;	// number of remote authpin waiters
-    fragment_info_t() : last_cum_auth_pins(0), num_remote_waiters(0) {}
+    fragment_info_t() : has_frozen(false), last_cum_auth_pins(0), num_remote_waiters(0) {}
   };
   map<dirfrag_t,fragment_info_t> fragments;
 
@@ -1016,6 +1026,7 @@ public:
 
   void find_stale_fragment_freeze();
   void fragment_freeze_inc_num_waiters(CDir *dir);
+  bool fragment_are_all_frozen(CDir *dir);
   int get_num_fragmenting_dirs() { return fragments.size(); }
 
   // -- updates --
diff --git a/src/mds/MDLog.cc b/src/mds/MDLog.cc
index cacbebf..991eaf5 100644
--- a/src/mds/MDLog.cc
+++ b/src/mds/MDLog.cc
@@ -219,13 +219,18 @@ void MDLog::submit_entry(LogEvent *le, Context *c)
   uint64_t last_seg = get_last_segment_offset();
   uint64_t period = journaler->get_layout_period();
   // start a new segment if there are none or if we reach end of last segment
-  if (journaler->get_write_pos()/period != last_seg/period) {
+  if (le->get_type() == EVENT_SUBTREEMAP ||
+      (le->get_type() == EVENT_IMPORTFINISH && mds->is_resolve())) {
+    // avoid infinite loop when ESubtreeMap is very large.
+    // don not insert ESubtreeMap among EImportFinish events that finish
+    // disambiguate imports. Because the ESubtreeMap reflects the subtree
+    // state when all EImportFinish events are replayed.
+  } else if (journaler->get_write_pos()/period != last_seg/period) {
     dout(10) << "submit_entry also starting new segment: last = " << last_seg
 	     << ", cur pos = " << journaler->get_write_pos() << dendl;
     start_new_segment();
   } else if (g_conf->mds_debug_subtrees &&
-	     le->get_type() != EVENT_SUBTREEMAP_TEST &&
-	     le->get_type() != EVENT_SUBTREEMAP) {
+	     le->get_type() != EVENT_SUBTREEMAP_TEST) {
     // debug: journal this every time to catch subtree replay bugs.
     // use a different event id so it doesn't get interpreted as a
     // LogSegment boundary on replay.
diff --git a/src/mds/MDS.cc b/src/mds/MDS.cc
index c62b75f..2473ff0 100644
--- a/src/mds/MDS.cc
+++ b/src/mds/MDS.cc
@@ -136,6 +136,8 @@ MDS::MDS(const std::string &n, Messenger *m, MonClient *mc) :
   server = new Server(this);
   locker = new Locker(this, mdcache);
 
+  dispatch_depth = 0;
+
   // clients
   last_client_mdsmap_bcast = 0;
   
@@ -494,7 +496,11 @@ int MDS::init(int wanted_state)
     uint64_t osd_features = objecter->osdmap->get_up_osd_features();
     if (osd_features & CEPH_FEATURE_OSD_TMAP2OMAP)
       break;
-    derr << "*** one or more OSDs do not support TMAP2OMAP; upgrade OSDs before starting MDS (or downgrade MDS) ***" << dendl;
+    if (objecter->osdmap->get_num_up_osds() > 0) {
+        derr << "*** one or more OSDs do not support TMAP2OMAP; upgrade OSDs before starting MDS (or downgrade MDS) ***" << dendl;
+    } else {
+        derr << "*** no OSDs are up as of epoch " << objecter->osdmap->get_epoch() << ", waiting" << dendl;
+    }
     sleep(10);
   }
 
@@ -1187,7 +1193,7 @@ void MDS::boot_create()
 
   // write empty sessionmap
   sessionmap.save(fin.new_sub());
-  
+
   // initialize tables
   if (mdsmap->get_tableserver() == whoami) {
     dout(10) << "boot_create creating fresh anchortable" << dendl;
@@ -1201,6 +1207,8 @@ void MDS::boot_create()
     snapserver->handle_mds_recovery(whoami);
   }
 
+  assert(g_conf->mds_kill_create_at != 1);
+
   // ok now journal it
   mdlog->journal_segment_subtree_map();
   mdlog->wait_for_safe(fin.new_sub());
@@ -1711,7 +1719,9 @@ bool MDS::ms_dispatch(Message *m)
     m->put();
     ret = true;
   } else {
+    inc_dispatch_depth();
     ret = _dispatch(m);
+    dec_dispatch_depth();
   }
   mds_lock.Unlock();
   return ret;
@@ -1913,6 +1923,9 @@ bool MDS::_dispatch(Message *m)
     }
   }
 
+  if (dispatch_depth > 1)
+    return true;
+
   // finish any triggered contexts
   while (!finished_queue.empty()) {
     dout(7) << "mds has " << finished_queue.size() << " queued contexts" << dendl;
@@ -2097,6 +2110,7 @@ bool MDS::ms_handle_reset(Connection *con)
       if (session->is_closed()) {
 	dout(3) << "ms_handle_reset closing connection for session " << session->info.inst << dendl;
 	messenger->mark_down(con);
+	con->set_priv(NULL);
 	sessionmap.remove_session(session);
       }
       session->put();
@@ -2125,6 +2139,7 @@ void MDS::ms_handle_remote_reset(Connection *con)
       if (session->is_closed()) {
 	dout(3) << "ms_handle_remote_reset closing connection for session " << session->info.inst << dendl;
 	messenger->mark_down(con);
+	con->set_priv(NULL);
 	sessionmap.remove_session(session);
       }
       session->put();
diff --git a/src/mds/MDS.h b/src/mds/MDS.h
index ac68fea..fc1cfcd 100644
--- a/src/mds/MDS.h
+++ b/src/mds/MDS.h
@@ -204,7 +204,7 @@ class MDS : public Dispatcher {
 
   map<int,version_t> peer_mdsmap_epoch;
 
-  tid_t last_tid;    // for mds-initiated requests (e.g. stray rename)
+  ceph_tid_t last_tid;    // for mds-initiated requests (e.g. stray rename)
 
  public:
   void wait_for_active(Context *c) { 
@@ -251,7 +251,7 @@ class MDS : public Dispatcher {
 
   void request_state(int s);
 
-  tid_t issue_tid() { return ++last_tid; }
+  ceph_tid_t issue_tid() { return ++last_tid; }
     
 
   // -- waiters --
@@ -321,6 +321,7 @@ class MDS : public Dispatcher {
   }
 
  private:
+  int dispatch_depth;
   bool ms_dispatch(Message *m);
   bool ms_get_authorizer(int dest_type, AuthAuthorizer **authorizer, bool force_new);
   bool ms_verify_authorizer(Connection *con, int peer_type,
@@ -409,6 +410,9 @@ class MDS : public Dispatcher {
 
   void request_osdmap(Context *c);
 
+  void inc_dispatch_depth() { ++dispatch_depth; }
+  void dec_dispatch_depth() { --dispatch_depth; }
+
   // messages
   bool _dispatch(Message *m);
 
@@ -436,7 +440,9 @@ public:
     this->mds = mds;
   }
   virtual void finish(int r) {
+    mds->inc_dispatch_depth();
     mds->_dispatch(m);
+    mds->dec_dispatch_depth();
   }
 };
 
diff --git a/src/mds/MDSMap.h b/src/mds/MDSMap.h
index 004a699..8046a7c 100644
--- a/src/mds/MDSMap.h
+++ b/src/mds/MDSMap.h
@@ -477,12 +477,14 @@ public:
     return in.size() >= max_mds;
   }
   bool is_degraded() const {   // degraded = some recovery in process.  fixes active membership and recovery_set.
-    return 
-      get_num_mds(STATE_REPLAY) + 
-      get_num_mds(STATE_RESOLVE) + 
-      get_num_mds(STATE_RECONNECT) + 
-      get_num_mds(STATE_REJOIN) + 
-      failed.size();
+    if (!failed.empty())
+      return true;
+    for (map<uint64_t,mds_info_t>::const_iterator p = mds_info.begin();
+	 p != mds_info.end();
+	 ++p)
+      if (p->second.state >= STATE_REPLAY && p->second.state <= STATE_CLIENTREPLAY)
+	return true;
+    return false;
   }
   bool is_any_failed() {
     return failed.size();
diff --git a/src/mds/MDSTable.cc b/src/mds/MDSTable.cc
index ef0326d..967c9ee 100644
--- a/src/mds/MDSTable.cc
+++ b/src/mds/MDSTable.cc
@@ -27,7 +27,7 @@
 
 #define dout_subsys ceph_subsys_mds
 #undef dout_prefix
-#define dout_prefix *_dout << "mds." << mds->get_nodeid() << "." << table_name << ": "
+#define dout_prefix *_dout << "mds." << (mds ? mds->get_nodeid() : -1) << "." << table_name << ": "
 
 
 class C_MT_Save : public Context {
@@ -148,7 +148,7 @@ void MDSTable::load_2(int r, bufferlist& bl, Context *onfinish)
     return;
   }
   if (r < 0) {
-    dout(10) << "load_2 could not read table: " << r << dendl;
+    derr << "load_2 could not read table: " << r << dendl;
     assert(r >= 0);
   }
 
diff --git a/src/mds/MDSTable.h b/src/mds/MDSTable.h
index f258cf9..edcb203 100644
--- a/src/mds/MDSTable.h
+++ b/src/mds/MDSTable.h
@@ -79,7 +79,7 @@ public:
   // child must overload these
   virtual void reset_state() = 0;
   virtual void decode_state(bufferlist::iterator& p) = 0;
-  virtual void encode_state(bufferlist& bl) = 0;
+  virtual void encode_state(bufferlist& bl) const = 0;
 };
 
 #endif
diff --git a/src/mds/MDSTableServer.h b/src/mds/MDSTableServer.h
index 55827e7..223fc91 100644
--- a/src/mds/MDSTableServer.h
+++ b/src/mds/MDSTableServer.h
@@ -77,10 +77,10 @@ private:
   void handle_request(MMDSTableRequest *m);
   void do_server_update(bufferlist& bl);
 
-  virtual void encode_server_state(bufferlist& bl) = 0;
+  virtual void encode_server_state(bufferlist& bl) const = 0;
   virtual void decode_server_state(bufferlist::iterator& bl) = 0;
 
-  void encode_state(bufferlist& bl) {
+  void encode_state(bufferlist& bl) const {
     encode_server_state(bl);
     ::encode(pending_for_mds, bl);
   }
diff --git a/src/mds/MDSUtility.cc b/src/mds/MDSUtility.cc
new file mode 100644
index 0000000..09be280
--- /dev/null
+++ b/src/mds/MDSUtility.cc
@@ -0,0 +1,160 @@
+// -*- 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) 2014 John Spray <john.spray at inktank.com>
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation.  See file COPYING.
+ */
+
+#include "mds/MDSUtility.h"
+#include "mon/MonClient.h"
+
+#define dout_subsys ceph_subsys_mds
+
+
+MDSUtility::MDSUtility() :
+  Dispatcher(g_ceph_context),
+  objecter(NULL),
+  lock("MDSUtility::lock"),
+  timer(g_ceph_context, lock),
+  waiting_for_mds_map(NULL)
+{
+  monc = new MonClient(g_ceph_context);
+  messenger = Messenger::create(g_ceph_context, entity_name_t::CLIENT(), "mds", getpid());
+  mdsmap = new MDSMap();
+  osdmap = new OSDMap();
+  objecter = new Objecter(g_ceph_context, messenger, monc, osdmap, lock, timer, 0, 0);
+}
+
+
+MDSUtility::~MDSUtility()
+{
+  delete objecter;
+  delete monc;
+  delete messenger;
+  delete osdmap;
+  delete mdsmap;
+  assert(waiting_for_mds_map == NULL);
+}
+
+
+int MDSUtility::init()
+{
+  // Initialize Messenger
+  int r = messenger->bind(g_conf->public_addr);
+  if (r < 0)
+    return r;
+
+  messenger->add_dispatcher_head(this);
+  messenger->start();
+
+  // Initialize MonClient
+  if (monc->build_initial_monmap() < 0)
+    return -1;
+
+  monc->set_want_keys(CEPH_ENTITY_TYPE_MON|CEPH_ENTITY_TYPE_OSD|CEPH_ENTITY_TYPE_MDS);
+  monc->set_messenger(messenger);
+  monc->init();
+  r = monc->authenticate();
+  if (r < 0) {
+    derr << "Authentication failed, did you specify an MDS ID with a valid keyring?" << dendl;
+    return r;
+  }
+
+  client_t whoami = monc->get_global_id();
+  messenger->set_myname(entity_name_t::CLIENT(whoami.v));
+
+  // Initialize Objecter and wait for OSD map
+  objecter->set_client_incarnation(0);
+  objecter->init_unlocked();
+  lock.Lock();
+  objecter->init_locked();
+  lock.Unlock();
+  objecter->wait_for_osd_map();
+  timer.init();
+
+  // Prepare to receive MDS map and request it
+  Mutex init_lock("MDSUtility:init");
+  Cond cond;
+  bool done = false;
+  assert(!mdsmap->get_epoch());
+  lock.Lock();
+  waiting_for_mds_map = new C_SafeCond(&init_lock, &cond, &done, NULL);
+  lock.Unlock();
+  monc->sub_want("mdsmap", 0, CEPH_SUBSCRIBE_ONETIME);
+  monc->renew_subs();
+
+  // Wait for MDS map
+  dout(4) << "waiting for MDS map..." << dendl;
+  init_lock.Lock();
+  while (!done)
+    cond.Wait(init_lock);
+  init_lock.Unlock();
+  dout(4) << "Got MDS map " << mdsmap->get_epoch() << dendl;
+
+  return 0;
+}
+
+
+void MDSUtility::shutdown()
+{
+  lock.Lock();
+  timer.shutdown();
+  objecter->shutdown_locked();
+  lock.Unlock();
+  objecter->shutdown_unlocked();
+  monc->shutdown();
+  messenger->shutdown();
+  messenger->wait();
+}
+
+
+bool MDSUtility::ms_dispatch(Message *m)
+{
+   Mutex::Locker locker(lock);
+   switch (m->get_type()) {
+   case CEPH_MSG_OSD_OPREPLY:
+     objecter->handle_osd_op_reply((MOSDOpReply *)m);
+     break;
+   case CEPH_MSG_OSD_MAP:
+     objecter->handle_osd_map((MOSDMap*)m);
+     break;
+   case CEPH_MSG_MDS_MAP:
+     handle_mds_map((MMDSMap*)m);
+     break;
+   default:
+     return false;
+   }
+   return true;
+}
+
+
+void MDSUtility::handle_mds_map(MMDSMap* m)
+{
+  mdsmap->decode(m->get_encoded());
+  if (waiting_for_mds_map) {
+    waiting_for_mds_map->complete(0);
+    waiting_for_mds_map = NULL;
+  }
+}
+
+
+bool MDSUtility::ms_get_authorizer(int dest_type, AuthAuthorizer **authorizer,
+                         bool force_new)
+{
+  if (dest_type == CEPH_ENTITY_TYPE_MON)
+    return true;
+
+  if (force_new) {
+    if (monc->wait_auth_rotating(10) < 0)
+      return false;
+  }
+
+  *authorizer = monc->auth->build_authorizer(dest_type);
+  return *authorizer != NULL;
+}
diff --git a/src/mds/MDSUtility.h b/src/mds/MDSUtility.h
new file mode 100644
index 0000000..d3f938e
--- /dev/null
+++ b/src/mds/MDSUtility.h
@@ -0,0 +1,58 @@
+// -*- 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) 2014 John Spray <john.spray at inktank.com>
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation.  See file COPYING.
+ */
+
+#ifndef MDS_UTILITY_H_
+#define MDS_UTILITY_H_
+
+#include "osd/OSDMap.h"
+#include "osdc/Objecter.h"
+#include "mds/MDSMap.h"
+#include "messages/MMDSMap.h"
+#include "msg/Dispatcher.h"
+#include "msg/Messenger.h"
+#include "auth/Auth.h"
+
+/// MDS Utility
+/**
+ * This class is the parent for MDS utilities, i.e. classes that
+ * need access the objects belonging to the MDS without actually
+ * acting as an MDS daemon themselves.
+ */
+class MDSUtility : public Dispatcher {
+protected:
+  Objecter *objecter;
+  OSDMap *osdmap;
+  MDSMap *mdsmap;
+  Messenger *messenger;
+  MonClient *monc;
+
+  Mutex lock;
+  SafeTimer timer;
+
+  Context *waiting_for_mds_map;
+
+public:
+  MDSUtility();
+  ~MDSUtility();
+
+  void handle_mds_map(MMDSMap* m);
+  bool ms_dispatch(Message *m);
+  bool ms_handle_reset(Connection *con) { return false; }
+  void ms_handle_remote_reset(Connection *con) {}
+  bool ms_get_authorizer(int dest_type, AuthAuthorizer **authorizer,
+                         bool force_new);
+  int init();
+  void shutdown();
+};
+
+#endif /* MDS_UTILITY_H_ */
diff --git a/src/mds/Makefile.am b/src/mds/Makefile.am
index 05d0e1a..4ee3500 100644
--- a/src/mds/Makefile.am
+++ b/src/mds/Makefile.am
@@ -27,7 +27,8 @@ libmds_la_SOURCES = \
 	mds/SnapServer.cc \
 	mds/snap.cc \
 	mds/SessionMap.cc \
-	mds/MDLog.cc 
+	mds/MDLog.cc \
+	mds/MDSUtility.cc
 libmds_la_LIBADD = $(LIBOSDC)
 noinst_LTLIBRARIES += libmds.la
 
@@ -57,6 +58,7 @@ noinst_HEADERS += \
 	mds/MDSTable.h \
 	mds/MDSTableServer.h \
 	mds/MDSTableClient.h \
+	mds/MDSUtility.h \
 	mds/Mutation.h \
 	mds/Migrator.h \
 	mds/Resetter.h \
diff --git a/src/mds/Migrator.cc b/src/mds/Migrator.cc
index 233a511..08cf06c 100644
--- a/src/mds/Migrator.cc
+++ b/src/mds/Migrator.cc
@@ -1346,6 +1346,8 @@ void Migrator::finish_export_inode(CInode *in, utime_t now, int peer,
 
   in->clear_dirty_parent();
 
+  in->clear_file_locks();
+
   // waiters
   in->take_waiting(CInode::WAIT_ANY_MASK, finished);
 
@@ -2361,6 +2363,8 @@ void Migrator::import_reverse(CDir *dir)
 	in->dirfragtreelock.clear_gather();
 	in->filelock.clear_gather();
 
+	in->clear_file_locks();
+
 	// non-bounding dir?
 	list<CDir*> dfs;
 	in->get_dirfrags(dfs);
@@ -2385,6 +2389,7 @@ void Migrator::import_reverse(CDir *dir)
 	if (cap->is_new())
 	  in->remove_client_cap(q->first);
       }
+      in->put(CInode::PIN_IMPORTINGCAPS);
     }
     for (map<client_t,entity_inst_t>::iterator p = stat.client_map.begin();
 	 p != stat.client_map.end();
@@ -2575,6 +2580,7 @@ void Migrator::import_finish(CDir *dir, bool notify, bool last)
 				    q->second.mseq - 1, it->second.peer, CEPH_CAP_FLAG_AUTH);
       }
       p->second.clear();
+      in->replica_caps_wanted = 0;
     }
     for (map<client_t,entity_inst_t>::iterator p = it->second.client_map.begin();
 	 p != it->second.client_map.end();
@@ -2638,9 +2644,11 @@ void Migrator::import_finish(CDir *dir, bool notify, bool last)
   // re-eval imported caps
   for (map<CInode*, map<client_t,Capability::Export> >::iterator p = peer_exports.begin();
        p != peer_exports.end();
-       ++p)
+       ++p) {
     if (p->first->is_auth())
       mds->locker->eval(p->first, CEPH_CAP_LOCKS, true);
+    p->first->put(CInode::PIN_IMPORTINGCAPS);
+  }
 
   // send pending import_maps?
   mds->mdcache->maybe_send_pending_resolves();
@@ -2771,8 +2779,10 @@ void Migrator::finish_import_inode_caps(CInode *in, int peer, bool auth_cap,
     }
   }
 
-  in->replica_caps_wanted = 0;
-  in->put(CInode::PIN_IMPORTINGCAPS);
+  if (peer >= 0) {
+    in->replica_caps_wanted = 0;
+    in->put(CInode::PIN_IMPORTINGCAPS);
+  }
 }
 
 int Migrator::decode_import_dir(bufferlist::iterator& blp,
@@ -2803,7 +2813,7 @@ int Migrator::decode_import_dir(bufferlist::iterator& blp,
 
   // adjust replica list
   //assert(!dir->is_replica(oldauth));    // not true on failed export
-  dir->add_replica(oldauth);
+  dir->add_replica(oldauth, CDir::EXPORT_NONCE);
   if (dir->is_replica(mds->get_nodeid()))
     dir->remove_replica(mds->get_nodeid());
 
diff --git a/src/mds/Migrator.h b/src/mds/Migrator.h
index 0bf35f0..d3a2129 100644
--- a/src/mds/Migrator.h
+++ b/src/mds/Migrator.h
@@ -96,7 +96,8 @@ protected:
     utime_t last_cum_auth_pins_change;
     int last_cum_auth_pins;
     int num_remote_waiters; // number of remote authpin waiters
-    export_state_t() : mut(NULL), last_cum_auth_pins(0), num_remote_waiters(0) {}
+    export_state_t() : state(0), peer(0), tid(0), mut(NULL), 
+		       last_cum_auth_pins(0), num_remote_waiters(0) {}
   };
 
   map<CDir*, export_state_t>  export_state;
@@ -140,7 +141,7 @@ protected:
     map<client_t,entity_inst_t> client_map;
     map<CInode*, map<client_t,Capability::Export> > peer_exports;
     Mutation *mut;
-    import_state_t() : mut(NULL) {}
+    import_state_t() : state(0), peer(0), tid(0), mut(NULL) {}
   };
 
   map<dirfrag_t, import_state_t>  import_state;
diff --git a/src/mds/Mutation.cc b/src/mds/Mutation.cc
index 3916b2a..0bf5475 100644
--- a/src/mds/Mutation.cc
+++ b/src/mds/Mutation.cc
@@ -226,7 +226,7 @@ bool MDRequest::freeze_auth_pin(CInode *inode)
   return true;
 }
 
-void MDRequest::unfreeze_auth_pin()
+void MDRequest::unfreeze_auth_pin(bool clear_inode)
 {
   assert(more()->is_freeze_authpin);
   CInode *inode = more()->rename_inode;
@@ -235,6 +235,8 @@ void MDRequest::unfreeze_auth_pin()
   else
     inode->unfreeze_inode();
   more()->is_freeze_authpin = false;
+  if (clear_inode)
+    more()->rename_inode = NULL;
 }
 
 void MDRequest::set_remote_frozen_auth_pin(CInode *inode)
@@ -273,7 +275,7 @@ bool MDRequest::can_auth_pin(MDSCacheObject *object)
 void MDRequest::drop_local_auth_pins()
 {
   if (has_more() && more()->is_freeze_authpin)
-    unfreeze_auth_pin();
+    unfreeze_auth_pin(true);
   Mutation::drop_local_auth_pins();
 }
 
diff --git a/src/mds/Mutation.h b/src/mds/Mutation.h
index 10ed53d..206b71a 100644
--- a/src/mds/Mutation.h
+++ b/src/mds/Mutation.h
@@ -246,7 +246,7 @@ struct MDRequest : public Mutation {
       src_reanchor_atid(0), dst_reanchor_atid(0), inode_import_v(0),
       rename_inode(0), is_freeze_authpin(false), is_ambiguous_auth(false),
       is_remote_frozen_authpin(false), is_inode_exporter(false),
-      flock_was_waiting(false), stid(0), slave_commit(0) { }
+      flock_was_waiting(false), stid(0), slave_commit(0), export_dir(NULL)  { }
   } *_more;
 
 
@@ -312,7 +312,7 @@ struct MDRequest : public Mutation {
   bool slave_did_prepare();
   bool did_ino_allocation();
   bool freeze_auth_pin(CInode *inode);
-  void unfreeze_auth_pin();
+  void unfreeze_auth_pin(bool clear_inode=false);
   void set_remote_frozen_auth_pin(CInode *inode);
   bool can_auth_pin(MDSCacheObject *object);
   void drop_local_auth_pins();
@@ -328,7 +328,7 @@ struct MDSlaveUpdate {
   bufferlist rollback;
   elist<MDSlaveUpdate*>::item item;
   Context *waiter;
-  set<CDir*> olddirs;
+  set<CInode*> olddirs;
   set<CInode*> unlinked;
   MDSlaveUpdate(int oo, bufferlist &rbl, elist<MDSlaveUpdate*> &list) :
     origop(oo),
diff --git a/src/mds/Resetter.cc b/src/mds/Resetter.cc
index 74da069..22839ec 100644
--- a/src/mds/Resetter.cc
+++ b/src/mds/Resetter.cc
@@ -18,82 +18,21 @@
 #include "mon/MonClient.h"
 #include "mds/events/EResetJournal.h"
 
-Resetter::~Resetter()
-{
-}
 
-bool Resetter::ms_get_authorizer(int dest_type, AuthAuthorizer **authorizer,
-                         bool force_new)
+int Resetter::init(int rank)
 {
-  if (dest_type == CEPH_ENTITY_TYPE_MON)
-    return true;
-
-  if (force_new) {
-    if (monc->wait_auth_rotating(10) < 0)
-      return false;
+  int r = MDSUtility::init();
+  if (r < 0) {
+    return r;
   }
 
-  *authorizer = monc->auth->build_authorizer(dest_type);
-  return *authorizer != NULL;
-}
-
-bool Resetter::ms_dispatch(Message *m)
-{
-  Mutex::Locker l(lock);
-  switch (m->get_type()) {
-  case CEPH_MSG_OSD_OPREPLY:
-    objecter->handle_osd_op_reply((MOSDOpReply *)m);
-    break;
-  case CEPH_MSG_OSD_MAP:
-    objecter->handle_osd_map((MOSDMap*)m);
-    break;
-  default:
-    return false;
-  }
-  return true;
-}
-
-
-void Resetter::init(int rank) 
-{
   inodeno_t ino = MDS_INO_LOG_OFFSET + rank;
-  unsigned pg_pool = MDS_METADATA_POOL;
-  osdmap = new OSDMap();
-  objecter = new Objecter(g_ceph_context, messenger, monc, osdmap, lock, timer,
-			  0, 0);
-  journaler = new Journaler(ino, pg_pool, CEPH_FS_ONDISK_MAGIC,
-                                       objecter, 0, 0, &timer);
+  journaler = new Journaler(ino,
+      mdsmap->get_metadata_pool(),
+      CEPH_FS_ONDISK_MAGIC,
+      objecter, 0, 0, &timer);
 
-  objecter->set_client_incarnation(0);
-
-  messenger->add_dispatcher_head(this);
-  messenger->start();
-
-  monc->set_want_keys(CEPH_ENTITY_TYPE_MON|CEPH_ENTITY_TYPE_OSD|CEPH_ENTITY_TYPE_MDS);
-  monc->set_messenger(messenger);
-  monc->init();
-  monc->authenticate();
-
-  client_t whoami = monc->get_global_id();
-  messenger->set_myname(entity_name_t::CLIENT(whoami.v));
-
-  objecter->init_unlocked();
-  lock.Lock();
-  objecter->init_locked();
-  lock.Unlock();
-  objecter->wait_for_osd_map();
-  timer.init();
-}
-
-void Resetter::shutdown()
-{
-  lock.Lock();
-  timer.shutdown();
-  objecter->shutdown_locked();
-  lock.Unlock();
-  objecter->shutdown_unlocked();
-  messenger->shutdown();
-  messenger->wait();
+  return 0;
 }
 
 void Resetter::reset()
@@ -172,5 +111,4 @@ void Resetter::reset()
   assert(r == 0);
 
   cout << "done" << std::endl;
-  shutdown();
 }
diff --git a/src/mds/Resetter.h b/src/mds/Resetter.h
index b3bc067..e967b24 100644
--- a/src/mds/Resetter.h
+++ b/src/mds/Resetter.h
@@ -14,54 +14,23 @@
 #ifndef JOURNAL_RESETTER_H_
 #define JOURNAL_RESETTER_H_
 
-#include "osd/OSDMap.h"
-#include "osdc/Objecter.h"
+
 #include "osdc/Journaler.h"
-#include "msg/Dispatcher.h"
-#include "msg/Messenger.h"
-#include "auth/Auth.h"
+#include "mds/MDSUtility.h"
 
 /**
- * This class lets you dump out an mds journal for troubleshooting or whatever.
+ * This class lets you reset an mds journal for troubleshooting or whatever.
  *
- * It was built to work with cmds so some of the design choices are random.
- * To use, create a Resetter, call init(), and then call dump() with the name
+ * To use, create a Resetter, call init(), and then call reset() with the name
  * of the file to dump to.
  */
-
-class Resetter : public Dispatcher {
+class Resetter : public MDSUtility {
 public:
-  Objecter *objecter;
   Journaler *journaler;
-  OSDMap *osdmap;
-  Messenger *messenger;
-  MonClient *monc;
-  Mutex lock;
-  SafeTimer timer;
-
-  /*
-   * The messenger should be a valid Messenger. You should call bind()
-   * before passing it in, but not do anything else.
-   * The MonClient needs to be valid, and you should have called
-   * build_initial_monmap().
-   */
-  Resetter(Messenger *messenger_, MonClient *monc_) :
-    Dispatcher(messenger_->cct),
-    messenger(messenger_),
-    monc(monc_),
-    lock("Resetter::lock"),
-    timer(g_ceph_context, lock)
-  {}
 
-  virtual ~Resetter();
+  Resetter() : journaler(NULL) {}
 
-  bool ms_dispatch(Message *m);
-  bool ms_handle_reset(Connection *con) { return false; }
-  void ms_handle_remote_reset(Connection *con) {}
-  bool ms_get_authorizer(int dest_type, AuthAuthorizer **authorizer,
-                         bool force_new);
-  void init(int rank);
-  void shutdown();
+  int init(int rank);
   void reset();
 };
 
diff --git a/src/mds/Server.cc b/src/mds/Server.cc
index 8a4321e..984ad29 100644
--- a/src/mds/Server.cc
+++ b/src/mds/Server.cc
@@ -271,7 +271,7 @@ void Server::flush_client_sessions(set<client_t>& client_set, C_GatherBuilder& g
   for (set<client_t>::iterator p = client_set.begin(); p != client_set.end(); ++p) {
     Session *session = mds->sessionmap.get_session(entity_name_t::CLIENT(p->v));
     assert(session);
-    if (session->is_stale() ||
+    if (!session->is_open() ||
 	!session->connection.get() ||
 	!session->connection->has_feature(CEPH_FEATURE_EXPORT_PEER))
       continue;
@@ -1679,6 +1679,11 @@ void Server::handle_slave_auth_pin(MDRequest *mdr)
   if (fail) {
     mdr->drop_local_auth_pins();  // just in case
   } else {
+    /* freeze authpin wrong inode */
+    if (mdr->has_more() && mdr->more()->is_freeze_authpin &&
+	mdr->more()->rename_inode != auth_pin_freeze)
+      mdr->unfreeze_auth_pin(true);
+
     /* handle_slave_rename_prep() call freeze_inode() to wait for all other operations
      * on the source inode to complete. This happens after all locks for the rename
      * operation are acquired. But to acquire locks, we need auth pin locks' parent
@@ -2401,6 +2406,10 @@ void Server::handle_client_lookup_ino(MDRequest *mdr, bool want_parent, bool wan
   }
 
   if (want_parent) {
+    if (in->is_base()) {
+      reply_request(mdr, -EINVAL);
+      return;
+    }
     if (!diri || diri->is_stray()) {
       reply_request(mdr, -ESTALE);
       return;
@@ -2838,6 +2847,8 @@ void Server::handle_client_readdir(MDRequest *mdr)
   if (!dir->is_complete()) {
     if (dir->is_frozen()) {
       dout(7) << "dir is frozen " << *dir << dendl;
+      mds->locker->drop_locks(mdr);
+      mdr->drop_local_auth_pins();
       dir->add_waiter(CDir::WAIT_UNFREEZE, new C_MDS_RetryRequest(mdcache, mdr));
       return;
     }
@@ -4484,6 +4495,18 @@ public:
   }
 };
 
+class C_MDS_SlaveLinkCommit : public Context {
+  Server *server;
+  MDRequest *mdr;
+  CInode *targeti;
+public:
+  C_MDS_SlaveLinkCommit(Server *s, MDRequest *r, CInode *t) :
+    server(s), mdr(r), targeti(t) { }
+  void finish(int r) {
+    server->_commit_slave_link(mdr, r, targeti);
+  }
+};
+
 /* This function DOES put the mdr->slave_request before returning*/
 void Server::handle_slave_link_prep(MDRequest *mdr)
 {
@@ -4562,22 +4585,13 @@ void Server::handle_slave_link_prep(MDRequest *mdr)
   mdcache->predirty_journal_parents(mdr, &le->commit, dnl->get_inode(), 0, PREDIRTY_SHALLOW|PREDIRTY_PRIMARY, 0);
   mdcache->journal_dirty_inode(mdr, &le->commit, targeti);
 
+  // set up commit waiter
+  mdr->more()->slave_commit = new C_MDS_SlaveLinkCommit(this, mdr, targeti);
+
   mdlog->submit_entry(le, new C_MDS_SlaveLinkPrep(this, mdr, targeti));
   mdlog->flush();
 }
 
-class C_MDS_SlaveLinkCommit : public Context {
-  Server *server;
-  MDRequest *mdr;
-  CInode *targeti;
-public:
-  C_MDS_SlaveLinkCommit(Server *s, MDRequest *r, CInode *t) :
-    server(s), mdr(r), targeti(t) { }
-  void finish(int r) {
-    server->_commit_slave_link(mdr, r, targeti);
-  }
-};
-
 void Server::_logged_slave_link(MDRequest *mdr, CInode *targeti) 
 {
   dout(10) << "_logged_slave_link " << *mdr
@@ -4592,17 +4606,19 @@ void Server::_logged_slave_link(MDRequest *mdr, CInode *targeti)
   // hit pop
   mds->balancer->hit_inode(mdr->now, targeti, META_POP_IWR);
 
-  // ack
-  MMDSSlaveRequest *reply = new MMDSSlaveRequest(mdr->reqid, mdr->attempt,
-						 MMDSSlaveRequest::OP_LINKPREPACK);
-  mds->send_message_mds(reply, mdr->slave_to_mds);
-  
-  // set up commit waiter
-  mdr->more()->slave_commit = new C_MDS_SlaveLinkCommit(this, mdr, targeti);
-
   // done.
   mdr->slave_request->put();
   mdr->slave_request = 0;
+
+  // ack
+  if (!mdr->aborted) {
+    MMDSSlaveRequest *reply = new MMDSSlaveRequest(mdr->reqid, mdr->attempt,
+						   MMDSSlaveRequest::OP_LINKPREPACK);
+    mds->send_message_mds(reply, mdr->slave_to_mds);
+  } else {
+    dout(10) << " abort flag set, finishing" << dendl;
+    mdcache->request_finish(mdr);
+  }
 }
 
 
@@ -5132,6 +5148,16 @@ struct C_MDS_SlaveRmdirPrep : public Context {
   }
 };
 
+struct C_MDS_SlaveRmdirCommit : public Context {
+  Server *server;
+  MDRequest *mdr;
+  C_MDS_SlaveRmdirCommit(Server *s, MDRequest *r)
+    : server(s), mdr(r) { }
+  void finish(int r) {
+    server->_commit_slave_rmdir(mdr, r);
+  }
+};
+
 void Server::handle_slave_rmdir_prep(MDRequest *mdr)
 {
   dout(10) << "handle_slave_rmdir_prep " << *mdr 
@@ -5181,20 +5207,13 @@ void Server::handle_slave_rmdir_prep(MDRequest *mdr)
 
   mds->mdcache->project_subtree_rename(in, dn->get_dir(), straydn->get_dir());
 
+  // set up commit waiter
+  mdr->more()->slave_commit = new C_MDS_SlaveRmdirCommit(this, mdr);
+
   mdlog->submit_entry(le, new C_MDS_SlaveRmdirPrep(this, mdr, dn, straydn));
   mdlog->flush();
 }
 
-struct C_MDS_SlaveRmdirCommit : public Context {
-  Server *server;
-  MDRequest *mdr;
-  C_MDS_SlaveRmdirCommit(Server *s, MDRequest *r)
-    : server(s), mdr(r) { }
-  void finish(int r) {
-    server->_commit_slave_rmdir(mdr, r);
-  }
-};
-
 void Server::_logged_slave_rmdir(MDRequest *mdr, CDentry *dn, CDentry *straydn)
 {
   dout(10) << "_logged_slave_rmdir " << *mdr << " on " << *dn << dendl;
@@ -5207,17 +5226,19 @@ void Server::_logged_slave_rmdir(MDRequest *mdr, CDentry *dn, CDentry *straydn)
   dn->pop_projected_linkage();
   mdcache->adjust_subtree_after_rename(in, dn->get_dir(), true);
 
-  MMDSSlaveRequest *reply = new MMDSSlaveRequest(mdr->reqid, mdr->attempt,
-						 MMDSSlaveRequest::OP_RMDIRPREPACK);
-  mds->send_message_mds(reply, mdr->slave_to_mds);
-
-  // set up commit waiter
-  mdr->more()->slave_commit = new C_MDS_SlaveRmdirCommit(this, mdr);
-
   // done.
   mdr->slave_request->put();
   mdr->slave_request = 0;
   mdr->straydn = 0;
+
+  if (!mdr->aborted) {
+    MMDSSlaveRequest *reply = new MMDSSlaveRequest(mdr->reqid, mdr->attempt,
+						   MMDSSlaveRequest::OP_RMDIRPREPACK);
+    mds->send_message_mds(reply, mdr->slave_to_mds);
+  } else {
+    dout(10) << " abort flag set, finishing" << dendl;
+    mdcache->request_finish(mdr);
+  }
 }
 
 void Server::handle_slave_rmdir_prep_ack(MDRequest *mdr, MMDSSlaveRequest *ack)
@@ -5288,6 +5309,8 @@ void Server::do_rmdir_rollback(bufferlist &rbl, int master, MDRequest *mdr)
   assert(mdr || mds->is_resolve());
 
   CDir *dir = mds->mdcache->get_dirfrag(rollback.src_dir);
+  if (!dir)
+    dir = mds->mdcache->get_dirfrag(rollback.src_dir.ino, rollback.src_dname);
   assert(dir);
   CDentry *dn = dir->lookup(rollback.src_dname);
   assert(dn);
@@ -5629,6 +5652,8 @@ void Server::handle_client_rename(MDRequest *mdr)
   else
     witnesses.insert(srcdn->authority().first);
   destdn->list_replicas(witnesses);
+  if (destdnl->is_remote() && !oldin->is_auth())
+    witnesses.insert(oldin->authority().first);
   dout(10) << " witnesses " << witnesses << ", have " << mdr->more()->witnessed << dendl;
 
 
@@ -5644,6 +5669,8 @@ void Server::handle_client_rename(MDRequest *mdr)
     dout(10) << " will remote_wrlock srcdir scatterlocks on mds." << srcdirauth << dendl;
     remote_wrlocks[&srcdn->get_dir()->inode->filelock] = srcdirauth;
     remote_wrlocks[&srcdn->get_dir()->inode->nestlock] = srcdirauth;
+    if (srci->is_dir())
+      rdlocks.insert(&srci->dirfragtreelock);
   } else {
     wrlocks.insert(&srcdn->get_dir()->inode->filelock);
     wrlocks.insert(&srcdn->get_dir()->inode->nestlock);
@@ -5675,9 +5702,9 @@ void Server::handle_client_rename(MDRequest *mdr)
     // open_remote_ino() with 'want_locked=true' when the srcdn or destdn
     // is traversed.
     if (srcdnl->is_remote())
-      xlocks.insert(&srci->get_parent_dn()->lock);
+      xlocks.insert(&srci->get_projected_parent_dn()->lock);
     if (destdnl->is_remote())
-      xlocks.insert(&oldin->get_parent_dn()->lock);
+      xlocks.insert(&oldin->get_projected_parent_dn()->lock);
   }
 
   // we need to update srci's ctime.  xlock its least contended lock to do that...
@@ -5878,10 +5905,13 @@ void Server::_rename_finish(MDRequest *mdr, CDentry *srcdn, CDentry *destdn, CDe
   _rename_apply(mdr, srcdn, destdn, straydn);
 
   CDentry::linkage_t *destdnl = destdn->get_linkage();
+  CInode *in = destdnl->get_inode();
+  bool need_eval = mdr->more()->cap_imports.count(in);
+
   // test hack: test slave commit
-  if (!mdr->more()->slaves.empty() && !destdnl->get_inode()->is_dir())
+  if (!mdr->more()->slaves.empty() && !in->is_dir())
     assert(g_conf->mds_kill_rename_at != 5);
-  if (!mdr->more()->slaves.empty() && destdnl->get_inode()->is_dir())
+  if (!mdr->more()->slaves.empty() && in->is_dir())
     assert(g_conf->mds_kill_rename_at != 6);
   
   // commit anchor updates?
@@ -5892,9 +5922,8 @@ void Server::_rename_finish(MDRequest *mdr, CDentry *srcdn, CDentry *destdn, CDe
 
   // bump popularity
   mds->balancer->hit_dir(mdr->now, srcdn->get_dir(), META_POP_IWR);
-  if (destdnl->is_remote() &&
-      destdnl->get_inode()->is_auth())
-    mds->balancer->hit_inode(mdr->now, destdnl->get_inode(), META_POP_IWR);
+  if (destdnl->is_remote() && in->is_auth())
+    mds->balancer->hit_inode(mdr->now, in, META_POP_IWR);
 
   // did we import srci?  if so, explicitly ack that import that, before we unlock and reply.
 
@@ -5903,7 +5932,10 @@ void Server::_rename_finish(MDRequest *mdr, CDentry *srcdn, CDentry *destdn, CDe
   // reply
   MClientReply *reply = new MClientReply(mdr->client_request, 0);
   reply_request(mdr, reply);
-  
+
+  if (need_eval)
+    mds->locker->eval(in, CEPH_CAP_LOCKS, true);
+
   // clean up?
   if (straydn) 
     mdcache->eval_stray(straydn);
@@ -6043,7 +6075,7 @@ void Server::_rename_prepare(MDRequest *mdr,
   }
 
   bool force_journal_stray = false;
-  if (oldin && oldin->is_dir() && !straydn->is_auth())
+  if (oldin && oldin->is_dir() && straydn && !straydn->is_auth())
     force_journal_stray = _need_force_journal(oldin, true);
 
   if (linkmerge)
@@ -6681,9 +6713,10 @@ void Server::_logged_slave_rename(MDRequest *mdr,
   dout(10) << "_logged_slave_rename " << *mdr << dendl;
 
   // prepare ack
-  MMDSSlaveRequest *reply = new MMDSSlaveRequest(mdr->reqid, mdr->attempt,
-						 MMDSSlaveRequest::OP_RENAMEPREPACK);
-  
+  MMDSSlaveRequest *reply = NULL;
+  if (!mdr->aborted)
+    reply= new MMDSSlaveRequest(mdr->reqid, mdr->attempt, MMDSSlaveRequest::OP_RENAMEPREPACK);
+
   CDentry::linkage_t *srcdnl = srcdn->get_linkage();
   CDentry::linkage_t *destdnl = destdn->get_linkage();
   //CDentry::linkage_t *straydnl = straydn ? straydn->get_linkage() : 0;
@@ -6706,9 +6739,11 @@ void Server::_logged_slave_rename(MDRequest *mdr,
     for (list<CDir*>::iterator p = bounds.begin(); p != bounds.end(); ++p)
       (*p)->state_clear(CDir::STATE_EXPORTBOUND);
 
-    ::encode(exported_client_map, reply->inode_export);
-    reply->inode_export.claim_append(inodebl);
-    reply->inode_export_v = srcdnl->get_inode()->inode.version;
+    if (reply) {
+      ::encode(exported_client_map, reply->inode_export);
+      reply->inode_export.claim_append(inodebl);
+      reply->inode_export_v = srcdnl->get_inode()->inode.version;
+    }
 
     // remove mdr auth pin
     mdr->auth_unpin(srcdnl->get_inode());
@@ -6725,8 +6760,6 @@ void Server::_logged_slave_rename(MDRequest *mdr,
   
   destdnl = destdn->get_linkage();
 
-  mds->send_message_mds(reply, mdr->slave_to_mds);
-  
   // bump popularity
   mds->balancer->hit_dir(mdr->now, srcdn->get_dir(), META_POP_IWR);
   if (destdnl->get_inode() && destdnl->get_inode()->is_auth())
@@ -6736,6 +6769,14 @@ void Server::_logged_slave_rename(MDRequest *mdr,
   mdr->slave_request->put();
   mdr->slave_request = 0;
   mdr->straydn = 0;
+
+  if (reply) {
+    mds->send_message_mds(reply, mdr->slave_to_mds);
+  } else {
+    assert(mdr->aborted);
+    dout(10) << " abort flag set, finishing" << dendl;
+    mdcache->request_finish(mdr);
+  }
 }
 
 void Server::_commit_slave_rename(MDRequest *mdr, int r,
@@ -6896,6 +6937,8 @@ void Server::do_rename_rollback(bufferlist &rbl, int master, MDRequest *mdr,
 
   CDentry *srcdn = NULL;
   CDir *srcdir = mds->mdcache->get_dirfrag(rollback.orig_src.dirfrag);
+  if (!srcdir)
+    srcdir = mds->mdcache->get_dirfrag(rollback.orig_src.dirfrag.ino, rollback.orig_src.dname);
   if (srcdir) {
     dout(10) << "  srcdir " << *srcdir << dendl;
     srcdn = srcdir->lookup(rollback.orig_src.dname);
@@ -6909,6 +6952,8 @@ void Server::do_rename_rollback(bufferlist &rbl, int master, MDRequest *mdr,
 
   CDentry *destdn = NULL;
   CDir *destdir = mds->mdcache->get_dirfrag(rollback.orig_dest.dirfrag);
+  if (!destdir)
+    destdir = mds->mdcache->get_dirfrag(rollback.orig_dest.dirfrag.ino, rollback.orig_dest.dname);
   if (destdir) {
     dout(10) << " destdir " << *destdir << dendl;
     destdn = destdir->lookup(rollback.orig_dest.dname);
@@ -7023,7 +7068,14 @@ void Server::do_rename_rollback(bufferlist &rbl, int master, MDRequest *mdr,
       ti = target->get_projected_inode();
     if (ti->ctime == rollback.ctime)
       ti->ctime = rollback.orig_dest.old_ctime;
-    ti->nlink++;
+    if (MDS_INO_IS_STRAY(rollback.orig_src.dirfrag.ino)) {
+      if (MDS_INO_IS_STRAY(rollback.orig_dest.dirfrag.ino))
+	assert(!rollback.orig_dest.ino && !rollback.orig_dest.remote_ino);
+      else
+	assert(rollback.orig_dest.remote_ino &&
+	       rollback.orig_dest.remote_ino == rollback.orig_src.ino);
+    } else
+      ti->nlink++;
   }
 
   if (srcdn)
diff --git a/src/mds/SessionMap.h b/src/mds/SessionMap.h
index 8ddbacc..e06a7b7 100644
--- a/src/mds/SessionMap.h
+++ b/src/mds/SessionMap.h
@@ -181,17 +181,17 @@ private:
 
 
 public:
-  void add_completed_request(tid_t t, inodeno_t created) {
+  void add_completed_request(ceph_tid_t t, inodeno_t created) {
     info.completed_requests[t] = created;
   }
-  void trim_completed_requests(tid_t mintid) {
+  void trim_completed_requests(ceph_tid_t mintid) {
     // trim
     while (!info.completed_requests.empty() && 
 	   (mintid == 0 || info.completed_requests.begin()->first < mintid))
       info.completed_requests.erase(info.completed_requests.begin());
   }
-  bool have_completed_request(tid_t tid, inodeno_t *pcreated) const {
-    map<tid_t,inodeno_t>::const_iterator p = info.completed_requests.find(tid);
+  bool have_completed_request(ceph_tid_t tid, inodeno_t *pcreated) const {
+    map<ceph_tid_t,inodeno_t>::const_iterator p = info.completed_requests.find(tid);
     if (p == info.completed_requests.end())
       return false;
     if (pcreated)
@@ -370,7 +370,7 @@ public:
     Session *session = get_session(rid.name);
     return session && session->have_completed_request(rid.tid, NULL);
   }
-  void trim_completed_requests(entity_name_t c, tid_t tid) {
+  void trim_completed_requests(entity_name_t c, ceph_tid_t tid) {
     Session *session = get_session(c);
     assert(session);
     session->trim_completed_requests(tid);
diff --git a/src/mds/SnapServer.cc b/src/mds/SnapServer.cc
index f8aedb6..3d2b417 100644
--- a/src/mds/SnapServer.cc
+++ b/src/mds/SnapServer.cc
@@ -257,3 +257,84 @@ void SnapServer::check_osd_map(bool force)
 
   last_checked_osdmap = version;
 }
+
+
+void SnapServer::dump(Formatter *f) const
+{
+  f->open_object_section("snapserver");
+
+  f->dump_int("last_snap", last_snap.val);
+
+  f->open_array_section("pending_noop");
+  for(set<version_t>::const_iterator i = pending_noop.begin(); i != pending_noop.end(); ++i) {
+    f->dump_unsigned("version", *i);
+  }
+  f->close_section();
+
+  f->open_array_section("snaps");
+  for (map<snapid_t, SnapInfo>::const_iterator i = snaps.begin(); i != snaps.end(); ++i) {
+    f->open_object_section("snap");
+    i->second.dump(f);
+    f->close_section();
+  }
+  f->close_section();
+
+  f->open_object_section("need_to_purge");
+  for (map<int, set<snapid_t> >::const_iterator i = need_to_purge.begin(); i != need_to_purge.end(); ++i) {
+    stringstream pool_id;
+    pool_id << i->first;
+    f->open_array_section(pool_id.str().c_str());
+    for (set<snapid_t>::const_iterator s = i->second.begin(); s != i->second.end(); ++s) {
+      f->dump_unsigned("snapid", s->val);
+    }
+    f->close_section();
+  }
+  f->close_section();
+
+  f->open_array_section("pending_create");
+  for(map<version_t, SnapInfo>::const_iterator i = pending_create.begin(); i != pending_create.end(); ++i) {
+    f->open_object_section("snap");
+    f->dump_unsigned("version", i->first);
+    f->open_object_section("snapinfo");
+    i->second.dump(f);
+    f->close_section();
+    f->close_section();
+  }
+  f->close_section();
+
+  f->open_array_section("pending_destroy");
+  for(map<version_t, pair<snapid_t, snapid_t> >::const_iterator i = pending_destroy.begin(); i != pending_destroy.end(); ++i) {
+    f->open_object_section("snap");
+    f->dump_unsigned("version", i->first);
+    f->dump_unsigned("removed_snap", i->second.first);
+    f->dump_unsigned("seq", i->second.second);
+    f->close_section();
+  }
+  f->close_section();
+
+  f->close_section();
+}
+
+void SnapServer::generate_test_instances(list<SnapServer*>& ls)
+{
+  list<SnapInfo*> snapinfo_instances;
+  SnapInfo::generate_test_instances(snapinfo_instances);
+  SnapInfo populated_snapinfo = *(snapinfo_instances.back());
+  for (list<SnapInfo*>::iterator i = snapinfo_instances.begin(); i != snapinfo_instances.end(); ++i) {
+    delete *i;
+  }
+
+  SnapServer *blank = new SnapServer();
+  ls.push_back(blank);
+  SnapServer *populated = new SnapServer();
+  populated->last_snap = 123;
+  populated->snaps[456] = populated_snapinfo;
+  populated->need_to_purge[2].insert(012);
+  populated->pending_create[234] = populated_snapinfo;
+  populated->pending_destroy[345].first = 567;
+  populated->pending_destroy[345].second = 768;
+  populated->pending_noop.insert(890);
+
+  ls.push_back(populated);
+
+}
diff --git a/src/mds/SnapServer.h b/src/mds/SnapServer.h
index a3c3bd7..95e1508 100644
--- a/src/mds/SnapServer.h
+++ b/src/mds/SnapServer.h
@@ -39,7 +39,7 @@ public:
 		       last_checked_osdmap(0) { }
     
   void reset_state();
-  void encode_server_state(bufferlist& bl) {
+  void encode_server_state(bufferlist& bl) const {
     ENCODE_START(3, 3, bl);
     ::encode(last_snap, bl);
     ::encode(snaps, bl);
@@ -67,6 +67,17 @@ public:
     DECODE_FINISH(bl);
   }
 
+  // To permit enc/decoding in isolation in dencoder
+  SnapServer() : MDSTableServer(NULL, TABLE_SNAP), last_checked_osdmap(0) {}
+  void encode(bufferlist& bl) const {
+    encode_server_state(bl);
+  }
+  void decode(bufferlist::iterator& bl) {
+    decode_server_state(bl);
+  }
+  void dump(Formatter *f) const;
+  static void generate_test_instances(list<SnapServer*>& ls);
+
   // server bits
   void _prepare(bufferlist &bl, uint64_t reqid, int bymds);
   bool _is_prepared(version_t tid);
diff --git a/src/mds/events/EMetaBlob.h b/src/mds/events/EMetaBlob.h
index 14c640f..fb34697 100644
--- a/src/mds/events/EMetaBlob.h
+++ b/src/mds/events/EMetaBlob.h
@@ -540,9 +540,9 @@ private:
     return add_dir(dir->dirfrag(), dir->get_projected_fnode(), dir->get_projected_version(),
 		   dir->is_dirty(), dir->is_complete(), false, true, dir->is_dirty_dft());
   }
-  dirlump& add_fragmented_dir(CDir *dir, bool dirtydft) {
+  dirlump& add_fragmented_dir(CDir *dir, bool dirty, bool dirtydft) {
     return add_dir(dir->dirfrag(), dir->get_projected_fnode(), dir->get_projected_version(),
-		   false, false, false, false, dirtydft);
+		   dirty, false, false, false, dirtydft);
   }
   dirlump& add_dir(dirfrag_t df, fnode_t *pf, version_t pv, bool dirty,
 		   bool complete=false, bool isnew=false,
diff --git a/src/mds/flock.h b/src/mds/flock.h
index a98446d..4791b85 100644
--- a/src/mds/flock.h
+++ b/src/mds/flock.h
@@ -198,10 +198,20 @@ public:
   void encode(bufferlist& bl) const {
     ::encode(held_locks, bl);
     ::encode(waiting_locks, bl);
+    ::encode(client_held_lock_counts, bl);
+    ::encode(client_waiting_lock_counts, bl);
   }
   void decode(bufferlist::iterator& bl) {
     ::decode(held_locks, bl);
     ::decode(waiting_locks, bl);
+    ::decode(client_held_lock_counts, bl);
+    ::decode(client_waiting_lock_counts, bl);
+  }
+  void clear() {
+    held_locks.clear();
+    waiting_locks.clear();
+    client_held_lock_counts.clear();
+    client_waiting_lock_counts.clear();
   }
 };
 WRITE_CLASS_ENCODER(ceph_lock_state_t)
diff --git a/src/mds/journal.cc b/src/mds/journal.cc
index f818d7c..2bf24c3 100644
--- a/src/mds/journal.cc
+++ b/src/mds/journal.cc
@@ -157,7 +157,7 @@ void LogSegment::try_to_expire(MDS *mds, C_GatherBuilder &gather_bld)
       CInode *in = *p;
       assert(in->last == CEPH_NOSNAP);
       ++p;
-      if (in->is_auth() && in->is_any_caps()) {
+      if (in->is_auth() && !in->is_ambiguous_auth() && in->is_any_caps()) {
 	if (in->is_any_caps_wanted()) {
 	  dout(20) << "try_to_expire requeueing open file " << *in << dendl;
 	  if (!le) {
@@ -533,6 +533,18 @@ void EMetaBlob::fullbit::update_inode(MDS *mds, CInode *in)
 	       << dirfragtree << " on " << *in << dendl;
       in->dirfragtree = dirfragtree;
       in->force_dirfrags();
+      if (in->has_dirfrags() && in->authority() == CDIR_AUTH_UNDEF) {
+	list<CDir*> ls;
+	in->get_nested_dirfrags(ls);
+	for (list<CDir*>::iterator p = ls.begin(); p != ls.end(); ++p) {
+	  CDir *dir = *p;
+	  if (dir->get_num_any() == 0 &&
+	      mds->mdcache->can_trim_non_auth_dirfrag(dir)) {
+	    dout(10) << " closing empty non-auth dirfrag " << *dir << dendl;
+	    in->close_dirfrag(dir->get_frag());
+	  }
+	}
+      }
     }
 
     /*
@@ -603,6 +615,14 @@ void EMetaBlob::remotebit::dump(Formatter *f) const
     type_string = "symlink"; break;
   case S_IFDIR:
     type_string = "directory"; break;
+  case S_IFIFO:
+    type_string = "fifo"; break;
+  case S_IFCHR:
+    type_string = "chr"; break;
+  case S_IFBLK:
+    type_string = "blk"; break;
+  case S_IFSOCK:
+    type_string = "sock"; break;
   default:
     assert (0 == "unknown d_type!");
   }
@@ -1001,8 +1021,6 @@ void EMetaBlob::replay(MDS *mds, LogSegment *logseg, MDSlaveUpdate *slaveup)
 
     if (lump.is_dirty()) {
       dir->_mark_dirty(logseg);
-      dir->get_inode()->filelock.mark_dirty();
-      dir->get_inode()->nestlock.mark_dirty();
 
       if (!(dir->fnode.rstat == dir->fnode.accounted_rstat)) {
 	dout(10) << "EMetaBlob.replay      dirty nestinfo on " << *dir << dendl;
@@ -1202,7 +1220,7 @@ void EMetaBlob::replay(MDS *mds, LogSegment *logseg, MDSlaveUpdate *slaveup)
 	  assert(dir);
 	  // preserve subtree bound until slave commit
 	  if (dir->get_dir_auth() == CDIR_AUTH_UNDEF)
-	    slaveup->olddirs.insert(dir);
+	    slaveup->olddirs.insert(dir->inode);
 	}
       }
 
@@ -1212,7 +1230,7 @@ void EMetaBlob::replay(MDS *mds, LogSegment *logseg, MDSlaveUpdate *slaveup)
       CDir *root = mds->mdcache->get_subtree_root(olddir);
       if (root->get_dir_auth() == CDIR_AUTH_UNDEF) {
 	if (slaveup) // preserve the old dir until slave commit
-	  slaveup->olddirs.insert(olddir);
+	  slaveup->olddirs.insert(olddir->inode);
 	else
 	  mds->mdcache->try_trim_non_auth_subtree(root);
       }
diff --git a/src/mds/mdstypes.cc b/src/mds/mdstypes.cc
index aadf123..113cce6 100644
--- a/src/mds/mdstypes.cc
+++ b/src/mds/mdstypes.cc
@@ -555,7 +555,7 @@ void session_info_t::decode(bufferlist::iterator& p)
   DECODE_START_LEGACY_COMPAT_LEN(3, 2, 2, p);
   ::decode(inst, p);
   if (struct_v <= 2) {
-    set<tid_t> s;
+    set<ceph_tid_t> s;
     ::decode(s, p);
     while (!s.empty()) {
       completed_requests[*s.begin()] = inodeno_t();
@@ -576,7 +576,7 @@ void session_info_t::dump(Formatter *f) const
   f->dump_stream("inst") << inst;
 
   f->open_array_section("completed_requests");
-  for (map<tid_t,inodeno_t>::const_iterator p = completed_requests.begin();
+  for (map<ceph_tid_t,inodeno_t>::const_iterator p = completed_requests.begin();
        p != completed_requests.end();
        ++p) {
     f->open_object_section("request");
diff --git a/src/mds/mdstypes.h b/src/mds/mdstypes.h
index 8e7d9a9..184cf70 100644
--- a/src/mds/mdstypes.h
+++ b/src/mds/mdstypes.h
@@ -45,10 +45,10 @@ using namespace std;
 #define NUM_STRAY                 10
 
 #define MDS_INO_ROOT              1
+
+// No longer created but recognised in existing filesystems
+// so that we don't try to fragment it.
 #define MDS_INO_CEPH              2
-#define MDS_INO_PGTABLE           3
-#define MDS_INO_ANCHORTABLE       4
-#define MDS_INO_SNAPTABLE         5
 
 #define MDS_INO_MDSDIR_OFFSET     (1*MAX_MDS)
 #define MDS_INO_LOG_OFFSET        (2*MAX_MDS)
@@ -513,7 +513,7 @@ inline ostream& operator<<(ostream& out, const old_rstat_t& o) {
 
 struct session_info_t {
   entity_inst_t inst;
-  map<tid_t,inodeno_t> completed_requests;
+  map<ceph_tid_t,inodeno_t> completed_requests;
   interval_set<inodeno_t> prealloc_inos;   // preallocated, ready to use.
   interval_set<inodeno_t> used_inos;       // journaling use
 
@@ -651,7 +651,7 @@ struct metareqid_t {
   entity_name_t name;
   uint64_t tid;
   metareqid_t() : tid(0) {}
-  metareqid_t(entity_name_t n, tid_t t) : name(n), tid(t) {}
+  metareqid_t(entity_name_t n, ceph_tid_t t) : name(n), tid(t) {}
   void encode(bufferlist& bl) const {
     ::encode(name, bl);
     ::encode(tid, bl);
diff --git a/src/messages/MClientRequest.h b/src/messages/MClientRequest.h
index 0c17b16..c436368 100644
--- a/src/messages/MClientRequest.h
+++ b/src/messages/MClientRequest.h
@@ -110,7 +110,7 @@ public:
   }
 
   // normal fields
-  void set_oldest_client_tid(tid_t t) { head.oldest_client_tid = t; }
+  void set_oldest_client_tid(ceph_tid_t t) { head.oldest_client_tid = t; }
   void inc_num_fwd() { head.num_fwd = head.num_fwd + 1; }
   void set_retry_attempt(int a) { head.num_retry = a; }
   void set_filepath(const filepath& fp) { path = fp; }
@@ -125,7 +125,7 @@ public:
     head.flags = head.flags | CEPH_MDS_FLAG_REPLAY;
   }
     
-  tid_t get_oldest_client_tid() const { return head.oldest_client_tid; }
+  ceph_tid_t get_oldest_client_tid() const { return head.oldest_client_tid; }
   int get_num_fwd() const { return head.num_fwd; }
   int get_retry_attempt() const { return head.num_retry; }
   int get_op() const { return head.op; }
diff --git a/src/messages/MClientRequestForward.h b/src/messages/MClientRequestForward.h
index e174d83..976d9dc 100644
--- a/src/messages/MClientRequestForward.h
+++ b/src/messages/MClientRequestForward.h
@@ -25,7 +25,7 @@ class MClientRequestForward : public Message {
   MClientRequestForward()
     : Message(CEPH_MSG_CLIENT_REQUEST_FORWARD),
       dest_mds(-1), num_fwd(-1), client_must_resend(false) {}
-  MClientRequestForward(tid_t t, int dm, int nf, bool cmr) : 
+  MClientRequestForward(ceph_tid_t t, int dm, int nf, bool cmr) :
     Message(CEPH_MSG_CLIENT_REQUEST_FORWARD),
     dest_mds(dm), num_fwd(nf), client_must_resend(cmr) {
     assert(client_must_resend);
diff --git a/src/messages/MDiscoverReply.h b/src/messages/MDiscoverReply.h
index 1623cf3..361a517 100644
--- a/src/messages/MDiscoverReply.h
+++ b/src/messages/MDiscoverReply.h
@@ -127,7 +127,10 @@ class MDiscoverReply : public Message {
     flag_error_dn(false),
     flag_error_ino(false),
     flag_error_dir(false),
-    dir_auth_hint(CDIR_AUTH_UNKNOWN) {
+    unsolicited(false),
+    dir_auth_hint(CDIR_AUTH_UNKNOWN),
+    starts_with(DIR)
+  {
     header.tid = dis->get_tid();
   }
   MDiscoverReply(dirfrag_t df) :
@@ -141,7 +144,10 @@ class MDiscoverReply : public Message {
     flag_error_dn(false),
     flag_error_ino(false),
     flag_error_dir(false),
-    dir_auth_hint(CDIR_AUTH_UNKNOWN) {
+    unsolicited(false),
+    dir_auth_hint(CDIR_AUTH_UNKNOWN),
+    starts_with(DIR)
+  {
     header.tid = 0;
   }
 private:
diff --git a/src/messages/MGetPoolStats.h b/src/messages/MGetPoolStats.h
index acf9637..d004e29 100644
--- a/src/messages/MGetPoolStats.h
+++ b/src/messages/MGetPoolStats.h
@@ -26,7 +26,7 @@ public:
   list<string> pools;
 
   MGetPoolStats() : PaxosServiceMessage(MSG_GETPOOLSTATS, 0) {}
-  MGetPoolStats(const uuid_d& f, tid_t t, list<string>& ls, version_t l) :
+  MGetPoolStats(const uuid_d& f, ceph_tid_t t, list<string>& ls, version_t l) :
     PaxosServiceMessage(MSG_GETPOOLSTATS, l),
     fsid(f), pools(ls) {
     set_tid(t);
diff --git a/src/messages/MGetPoolStatsReply.h b/src/messages/MGetPoolStatsReply.h
index 719d5b8..07b99cf 100644
--- a/src/messages/MGetPoolStatsReply.h
+++ b/src/messages/MGetPoolStatsReply.h
@@ -24,7 +24,7 @@ public:
   map<string,pool_stat_t> pool_stats;
 
   MGetPoolStatsReply() : PaxosServiceMessage(MSG_GETPOOLSTATSREPLY, 0) {}
-  MGetPoolStatsReply(uuid_d& f, tid_t t, version_t v) :
+  MGetPoolStatsReply(uuid_d& f, ceph_tid_t t, version_t v) :
     PaxosServiceMessage(MSG_GETPOOLSTATSREPLY, v),
     fsid(f) {
     set_tid(t);
diff --git a/src/messages/MMDSFindIno.h b/src/messages/MMDSFindIno.h
index d8eddcb..859a7c4 100644
--- a/src/messages/MMDSFindIno.h
+++ b/src/messages/MMDSFindIno.h
@@ -19,11 +19,11 @@
 #include "include/filepath.h"
 
 struct MMDSFindIno : public Message {
-  tid_t tid;
+  ceph_tid_t tid;
   inodeno_t ino;
 
   MMDSFindIno() : Message(MSG_MDS_FINDINO) {}
-  MMDSFindIno(tid_t t, inodeno_t i) : Message(MSG_MDS_FINDINO), tid(t), ino(i) {}
+  MMDSFindIno(ceph_tid_t t, inodeno_t i) : Message(MSG_MDS_FINDINO), tid(t), ino(i) {}
 
   const char *get_type_name() const { return "findino"; }
   void print(ostream &out) const {
diff --git a/src/messages/MMDSFindInoReply.h b/src/messages/MMDSFindInoReply.h
index 3d6ec6c..aaf2a6e 100644
--- a/src/messages/MMDSFindInoReply.h
+++ b/src/messages/MMDSFindInoReply.h
@@ -19,11 +19,11 @@
 #include "include/filepath.h"
 
 struct MMDSFindInoReply : public Message {
-  tid_t tid;
+  ceph_tid_t tid;
   filepath path;
 
   MMDSFindInoReply() : Message(MSG_MDS_FINDINOREPLY) {}
-  MMDSFindInoReply(tid_t t) : Message(MSG_MDS_FINDINOREPLY), tid(t) {}
+  MMDSFindInoReply(ceph_tid_t t) : Message(MSG_MDS_FINDINOREPLY), tid(t) {}
 
   const char *get_type_name() const { return "findinoreply"; }
   void print(ostream &out) const {
diff --git a/src/messages/MMDSOpenIno.h b/src/messages/MMDSOpenIno.h
index 0918e87..a169fd0 100644
--- a/src/messages/MMDSOpenIno.h
+++ b/src/messages/MMDSOpenIno.h
@@ -22,7 +22,7 @@ struct MMDSOpenIno : public Message {
   vector<inode_backpointer_t> ancestors;
 
   MMDSOpenIno() : Message(MSG_MDS_OPENINO) {}
-  MMDSOpenIno(tid_t t, inodeno_t i, vector<inode_backpointer_t>& a) :
+  MMDSOpenIno(ceph_tid_t t, inodeno_t i, vector<inode_backpointer_t>& a) :
     Message(MSG_MDS_OPENINO), ino(i), ancestors(a) {
     header.tid = t;
   }
diff --git a/src/messages/MMDSOpenInoReply.h b/src/messages/MMDSOpenInoReply.h
index 245027f..5204d3c 100644
--- a/src/messages/MMDSOpenInoReply.h
+++ b/src/messages/MMDSOpenInoReply.h
@@ -24,7 +24,7 @@ struct MMDSOpenInoReply : public Message {
   int32_t error;
 
   MMDSOpenInoReply() : Message(MSG_MDS_OPENINOREPLY) {}
-  MMDSOpenInoReply(tid_t t, inodeno_t i, int h=-1, int e=0) :
+  MMDSOpenInoReply(ceph_tid_t t, inodeno_t i, int h=-1, int e=0) :
     Message(MSG_MDS_OPENINOREPLY), ino(i), hint(h), error(e) {
     header.tid = t;
   }
diff --git a/src/messages/MMDSSlaveRequest.h b/src/messages/MMDSSlaveRequest.h
index 67f5c78..15f095b 100644
--- a/src/messages/MMDSSlaveRequest.h
+++ b/src/messages/MMDSSlaveRequest.h
@@ -141,7 +141,8 @@ public:
   MMDSSlaveRequest() : Message(MSG_MDS_SLAVE_REQUEST) { }
   MMDSSlaveRequest(metareqid_t ri, __u32 att, int o) : 
     Message(MSG_MDS_SLAVE_REQUEST),
-    reqid(ri), attempt(att), op(o), flags(0) { }
+    reqid(ri), attempt(att), op(o), flags(0), lock_type(0),
+    inode_export_v(0) { }
 private:
   ~MMDSSlaveRequest() {}
 
diff --git a/src/messages/MMonGetVersion.h b/src/messages/MMonGetVersion.h
index 14c6481..e74daa6 100644
--- a/src/messages/MMonGetVersion.h
+++ b/src/messages/MMonGetVersion.h
@@ -48,7 +48,7 @@ public:
     ::decode(what, p);
   }
 
-  tid_t handle;
+  ceph_tid_t handle;
   string what;
 
 private:
diff --git a/src/messages/MMonGetVersionReply.h b/src/messages/MMonGetVersionReply.h
index 95e384d..b13b2f0 100644
--- a/src/messages/MMonGetVersionReply.h
+++ b/src/messages/MMonGetVersionReply.h
@@ -53,7 +53,7 @@ public:
       ::decode(oldest_version, p);
   }
 
-  tid_t handle;
+  ceph_tid_t handle;
   version_t version;
   version_t oldest_version;
 
diff --git a/src/messages/MOSDOp.h b/src/messages/MOSDOp.h
index 7a27838..ed0a669 100644
--- a/src/messages/MOSDOp.h
+++ b/src/messages/MOSDOp.h
@@ -74,7 +74,7 @@ public:
 		       header.tid);
   }
   int get_client_inc() { return client_inc; }
-  tid_t get_client_tid() { return header.tid; }
+  ceph_tid_t get_client_tid() { return header.tid; }
   
   object_t& get_oid() { return oid; }
 
diff --git a/src/messages/MOSDSubOp.h b/src/messages/MOSDSubOp.h
index 9c405e6..7c9c504 100644
--- a/src/messages/MOSDSubOp.h
+++ b/src/messages/MOSDSubOp.h
@@ -223,7 +223,7 @@ public:
     : Message(MSG_OSD_SUBOP, HEAD_VERSION, COMPAT_VERSION) { }
   MOSDSubOp(osd_reqid_t r, pg_shard_t from,
 	    spg_t p, const hobject_t& po, bool noop_, int aw,
-	    epoch_t mape, tid_t rtid, eversion_t v)
+	    epoch_t mape, ceph_tid_t rtid, eversion_t v)
     : Message(MSG_OSD_SUBOP, HEAD_VERSION, COMPAT_VERSION),
       map_epoch(mape),
       reqid(r),
diff --git a/src/messages/MPoolOp.h b/src/messages/MPoolOp.h
index e6d31ee..d864741 100644
--- a/src/messages/MPoolOp.h
+++ b/src/messages/MPoolOp.h
@@ -34,13 +34,13 @@ public:
 
   MPoolOp()
     : PaxosServiceMessage(CEPH_MSG_POOLOP, 0, HEAD_VERSION, COMPAT_VERSION) { }
-  MPoolOp(const uuid_d& f, tid_t t, int p, string& n, int o, version_t v)
+  MPoolOp(const uuid_d& f, ceph_tid_t t, int p, string& n, int o, version_t v)
     : PaxosServiceMessage(CEPH_MSG_POOLOP, v, HEAD_VERSION, COMPAT_VERSION),
       fsid(f), pool(p), name(n), op(o),
       auid(0), snapid(0), crush_rule(0) {
     set_tid(t);
   }
-  MPoolOp(const uuid_d& f, tid_t t, int p, string& n,
+  MPoolOp(const uuid_d& f, ceph_tid_t t, int p, string& n,
 	  int o, uint64_t uid, version_t v)
     : PaxosServiceMessage(CEPH_MSG_POOLOP, v, HEAD_VERSION, COMPAT_VERSION),
       fsid(f), pool(p), name(n), op(o),
diff --git a/src/messages/MPoolOpReply.h b/src/messages/MPoolOpReply.h
index 702fdf7..d4fa50a 100644
--- a/src/messages/MPoolOpReply.h
+++ b/src/messages/MPoolOpReply.h
@@ -26,14 +26,14 @@ public:
 
   MPoolOpReply() : PaxosServiceMessage(CEPH_MSG_POOLOP_REPLY, 0)
   {}
-  MPoolOpReply( uuid_d& f, tid_t t, int rc, int e, version_t v) :
+  MPoolOpReply( uuid_d& f, ceph_tid_t t, int rc, int e, version_t v) :
     PaxosServiceMessage(CEPH_MSG_POOLOP_REPLY, v),
     fsid(f),
     replyCode(rc),
     epoch(e) {
     set_tid(t);
   }
-  MPoolOpReply( uuid_d& f, tid_t t, int rc, int e, version_t v,
+  MPoolOpReply( uuid_d& f, ceph_tid_t t, int rc, int e, version_t v,
 		bufferlist *blp) :
     PaxosServiceMessage(CEPH_MSG_POOLOP_REPLY, v),
     fsid(f),
diff --git a/src/messages/MStatfs.h b/src/messages/MStatfs.h
index 61370a9..ec19f6e 100644
--- a/src/messages/MStatfs.h
+++ b/src/messages/MStatfs.h
@@ -24,7 +24,7 @@ public:
   uuid_d fsid;
 
   MStatfs() : PaxosServiceMessage(CEPH_MSG_STATFS, 0) {}
-  MStatfs(const uuid_d& f, tid_t t, version_t v) :
+  MStatfs(const uuid_d& f, ceph_tid_t t, version_t v) :
     PaxosServiceMessage(CEPH_MSG_STATFS, v), fsid(f) {
     set_tid(t);
   }
diff --git a/src/messages/MStatfsReply.h b/src/messages/MStatfsReply.h
index 8ceec9c..6bf42d8 100644
--- a/src/messages/MStatfsReply.h
+++ b/src/messages/MStatfsReply.h
@@ -21,7 +21,7 @@ public:
   struct ceph_mon_statfs_reply h;
 
   MStatfsReply() : Message(CEPH_MSG_STATFS_REPLY) {}
-  MStatfsReply(uuid_d &f, tid_t t, epoch_t epoch) : Message(CEPH_MSG_STATFS_REPLY) {
+  MStatfsReply(uuid_d &f, ceph_tid_t t, epoch_t epoch) : Message(CEPH_MSG_STATFS_REPLY) {
     memcpy(&h.fsid, f.uuid, sizeof(h.fsid));
     header.tid = t;
     h.version = epoch;
diff --git a/src/mon/LogMonitor.cc b/src/mon/LogMonitor.cc
index 8ed5ed9..cc98554 100644
--- a/src/mon/LogMonitor.cc
+++ b/src/mon/LogMonitor.cc
@@ -163,7 +163,7 @@ void LogMonitor::update_from_paxos(bool *need_bootstrap)
 	dout(1) << "error writing to " << g_conf->mon_cluster_log_file
 		<< ": " << cpp_strerror(err) << dendl;
       }
-      TEMP_FAILURE_RETRY(::close(fd));
+      VOID_TEMP_FAILURE_RETRY(::close(fd));
     }
   }
 
diff --git a/src/mon/MDSMonitor.cc b/src/mon/MDSMonitor.cc
index d25b0cb..12755b7 100644
--- a/src/mon/MDSMonitor.cc
+++ b/src/mon/MDSMonitor.cc
@@ -721,8 +721,17 @@ void MDSMonitor::fail_mds_gid(uint64_t gid)
   pending_mdsmap.last_failure_osd_epoch = mon->osdmon()->blacklist(info.addr, until);
 
   if (info.rank >= 0) {
+    if (info.state == MDSMap::STATE_CREATING) {
+      // If this gid didn't make it past CREATING, then forget
+      // the rank ever existed so that next time it's handed out
+      // to a gid it'll go back into CREATING.
+      pending_mdsmap.in.erase(info.rank);
+    } else {
+      // Put this rank into the failed list so that the next available STANDBY will
+      // pick it up.
+      pending_mdsmap.failed.insert(info.rank);
+    }
     pending_mdsmap.up.erase(info.rank);
-    pending_mdsmap.failed.insert(info.rank);
   }
 
   pending_mdsmap.mds_info.erase(gid);
@@ -828,8 +837,10 @@ bool MDSMonitor::prepare_command(MMonCommand *m)
     ss << "max_mds = " << pending_mdsmap.max_mds;
   } else if (prefix == "mds set") {
     string var;
-    if (!cmd_getval(g_ceph_context, cmdmap, "var", var) < 0)
+    if (!cmd_getval(g_ceph_context, cmdmap, "var", var) || var.empty()) {
+      ss << "Invalid variable";
       goto out;
+    }
     string val;
     string interr;
     int64_t n = 0;
diff --git a/src/mon/Makefile.am b/src/mon/Makefile.am
index 2e91517..68c6503 100644
--- a/src/mon/Makefile.am
+++ b/src/mon/Makefile.am
@@ -14,7 +14,7 @@ libmon_la_SOURCES = \
 	mon/HealthMonitor.cc \
 	mon/DataHealthService.cc \
 	mon/ConfigKeyService.cc
-libmon_la_LIBADD = $(LIBAUTH) $(LIBCOMMON) $(LIBOS) $(LIBERASURE_CODE)
+libmon_la_LIBADD = $(LIBAUTH) $(LIBCOMMON) $(LIBOS)
 noinst_LTLIBRARIES += libmon.la
 
 noinst_HEADERS += \
diff --git a/src/mon/MonClient.cc b/src/mon/MonClient.cc
index 25dd3cd..fcb622b 100644
--- a/src/mon/MonClient.cc
+++ b/src/mon/MonClient.cc
@@ -628,6 +628,11 @@ void MonClient::_reopen_session(int rank, string name)
   state = MC_STATE_NEGOTIATING;
   hunting = true;
 
+  // send an initial keepalive to ensure our timestamp is valid by the
+  // time we are in an OPENED state (by sequencing this before
+  // authentication).
+  messenger->send_keepalive(cur_con.get());
+
   MAuth *m = new MAuth;
   m->protocol = 0;
   m->monmap_epoch = monmap.get_epoch();
@@ -696,9 +701,20 @@ void MonClient::tick()
       _renew_subs();
 
     messenger->send_keepalive(cur_con.get());
-   
+
     if (state == MC_STATE_HAVE_SESSION) {
       send_log();
+
+      if (cct->_conf->mon_client_ping_timeout > 0 &&
+	  cur_con->has_feature(CEPH_FEATURE_MSGR_KEEPALIVE2)) {
+	utime_t lk = cur_con->get_last_keepalive_ack();
+	utime_t interval = ceph_clock_now(cct) - lk;
+	if (interval > cct->_conf->mon_client_ping_timeout) {
+	  ldout(cct, 1) << "no keepalive since " << lk << " (" << interval
+			<< " seconds), reconnecting" << dendl;
+	  _reopen_session();
+	}
+      }
     }
   }
 
@@ -914,7 +930,7 @@ int MonClient::_cancel_mon_command(uint64_t tid, int r)
 {
   assert(monc_lock.is_locked());
 
-  map<tid_t, MonCommand*>::iterator it = mon_commands.find(tid);
+  map<ceph_tid_t, MonCommand*>::iterator it = mon_commands.find(tid);
   if (it == mon_commands.end()) {
     ldout(cct, 10) << __func__ << " tid " << tid << " dne" << dendl;
     return -ENOENT;
@@ -1018,7 +1034,7 @@ void MonClient::get_version(string map, version_t *newest, version_t *oldest, Co
 void MonClient::handle_get_version_reply(MMonGetVersionReply* m)
 {
   assert(monc_lock.is_locked());
-  map<tid_t, version_req_d*>::iterator iter = version_requests.find(m->handle);
+  map<ceph_tid_t, version_req_d*>::iterator iter = version_requests.find(m->handle);
   if (iter == version_requests.end()) {
     ldout(cct, 0) << __func__ << " version request with handle " << m->handle
 		  << " not found" << dendl;
diff --git a/src/mon/MonClient.h b/src/mon/MonClient.h
index a2998bb..239d91b 100644
--- a/src/mon/MonClient.h
+++ b/src/mon/MonClient.h
@@ -434,8 +434,8 @@ private:
     version_req_d(Context *con, version_t *n, version_t *o) : context(con),newest(n), oldest(o) {}
   };
 
-  map<tid_t, version_req_d*> version_requests;
-  tid_t version_req_id;
+  map<ceph_tid_t, version_req_d*> version_requests;
+  ceph_tid_t version_req_id;
   void handle_get_version_reply(MMonGetVersionReply* m);
 
 
diff --git a/src/mon/MonCommands.h b/src/mon/MonCommands.h
index a6bf5e5..a8e138a 100644
--- a/src/mon/MonCommands.h
+++ b/src/mon/MonCommands.h
@@ -4,6 +4,9 @@
  * Ceph - scalable distributed file system
  *
  * Copyright (C) 2013 Inktank Storage, Inc. 
+ * Copyright (C) 2013,2014 Cloudwatt <libre.licensing at cloudwatt.com>
+ *
+ * Author: Loic Dachary <loic at dachary.org>
  *
  * This is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -149,16 +152,16 @@ COMMAND("pg set_nearfull_ratio name=ratio,type=CephFloat,range=0.0|1.0", \
 
 COMMAND("auth export name=entity,type=CephString,req=false", \
        	"write keyring for requested entity, or master keyring if none given", \
-	"auth", "r", "cli,rest")
+	"auth", "rx", "cli,rest")
 COMMAND("auth get name=entity,type=CephString", \
-	"write keyring file with requested key", "auth", "r", "cli,rest")
+	"write keyring file with requested key", "auth", "rx", "cli,rest")
 COMMAND("auth get-key name=entity,type=CephString", "display requested key", \
-	"auth", "r", "cli,rest")
+	"auth", "rx", "cli,rest")
 COMMAND("auth print-key name=entity,type=CephString", "display requested key", \
-	"auth", "r", "cli,rest")
+	"auth", "rx", "cli,rest")
 COMMAND("auth print_key name=entity,type=CephString", "display requested key", \
-	"auth", "r", "cli,rest")
-COMMAND("auth list", "list authentication state", "auth", "r", "cli,rest")
+	"auth", "rx", "cli,rest")
+COMMAND("auth list", "list authentication state", "auth", "rx", "cli,rest")
 COMMAND("auth import", "auth import: read keyring file from -i <file>", \
 	"auth", "rw", "cli,rest")
 COMMAND("auth add " \
@@ -441,8 +444,8 @@ COMMAND("osd crush rule create-simple " \
 	"osd", "rw", "cli,rest")
 COMMAND("osd crush rule create-erasure " \
 	"name=name,type=CephString,goodchars=[A-Za-z0-9-_.] " \
-	"name=properties,type=CephString,n=N,req=false,goodchars=[A-Za-z0-9-_.=]", \
-	"create crush rule <name> suitable for erasure coded pool created with <properties>", \
+	"name=profile,type=CephString,req=false,goodchars=[A-Za-z0-9-_.=]", \
+	"create crush rule <name> for erasure coded pool created with <profile> (default default)", \
 	"osd", "rw", "cli,rest")
 COMMAND("osd crush rule rm " \
 	"name=name,type=CephString,goodchars=[A-Za-z0-9-_.] ",	\
@@ -452,6 +455,22 @@ COMMAND("osd setmaxosd " \
 	"set new maximum osd value", "osd", "rw", "cli,rest")
 COMMAND("osd pause", "pause osd", "osd", "rw", "cli,rest")
 COMMAND("osd unpause", "unpause osd", "osd", "rw", "cli,rest")
+COMMAND("osd erasure-code-profile set " \
+	"name=name,type=CephString,goodchars=[A-Za-z0-9-_.] " \
+	"name=profile,type=CephString,n=N,req=false,goodchars=[A-Za-z0-9-_.=]", \
+	"create erasure code profile <name> with [<key[=value]> ...] pairs. Add a --force at the end to override an existing profile (VERY DANGEROUS)", \
+	"osd", "rw", "cli,rest")
+COMMAND("osd erasure-code-profile get " \
+	"name=name,type=CephString,goodchars=[A-Za-z0-9-_.]", \
+	"get erasure code profile <name>", \
+	"osd", "r", "cli,rest")
+COMMAND("osd erasure-code-profile rm " \
+	"name=name,type=CephString,goodchars=[A-Za-z0-9-_.]", \
+	"remove erasure code profile <name>", \
+	"osd", "rw", "cli,rest")
+COMMAND("osd erasure-code-profile ls", \
+	"list all erasure code profiles", \
+	"osd", "r", "cli,rest")
 COMMAND("osd set " \
 	"name=key,type=CephChoices,strings=pause|noup|nodown|noout|noin|nobackfill|norecover|noscrub|nodeep-scrub|notieragent", \
 	"set <key>", "osd", "rw", "cli,rest")
@@ -476,6 +495,16 @@ COMMAND("osd reweight " \
 	"name=id,type=CephInt,range=0 " \
 	"type=CephFloat,name=weight,range=0.0|1.0", \
 	"reweight osd to 0.0 < <weight> < 1.0", "osd", "rw", "cli,rest")
+COMMAND("osd pg-temp " \
+	"name=pgid,type=CephPgid " \
+	"name=id,type=CephString,n=N,req=false", \
+	"set pg_temp mapping pgid:[<id> [<id>...]] (developers only)", \
+        "osd", "rw", "cli,rest")
+COMMAND("osd primary-temp " \
+	"name=pgid,type=CephPgid " \
+	"name=id,type=CephString", \
+        "set primary_temp mapping pgid:<id>|-1 (developers only)", \
+        "osd", "rw", "cli,rest")
 COMMAND("osd primary-affinity " \
 	"name=id,type=CephOsdName " \
 	"type=CephFloat,name=weight,range=0.0|1.0", \
@@ -508,7 +537,8 @@ COMMAND("osd pool create " \
 	"name=pg_num,type=CephInt,range=0 " \
 	"name=pgp_num,type=CephInt,range=0,req=false " \
         "name=pool_type,type=CephChoices,strings=replicated|erasure,req=false " \
-	"name=properties,type=CephString,n=N,req=false,goodchars=[A-Za-z0-9-_.=]", \
+	"name=erasure_code_profile,type=CephString,req=false,goodchars=[A-Za-z0-9-_.=] " \
+	"name=ruleset,type=CephString,req=false,goodchars=[A-Za-z0-9-_.=]", \
 	"create pool", "osd", "rw", "cli,rest")
 COMMAND("osd pool delete " \
 	"name=pool,type=CephPoolname " \
@@ -522,11 +552,11 @@ COMMAND("osd pool rename " \
 	"rename <srcpool> to <destpool>", "osd", "rw", "cli,rest")
 COMMAND("osd pool get " \
 	"name=pool,type=CephPoolname " \
-	"name=var,type=CephChoices,strings=size|min_size|crash_replay_interval|pg_num|pgp_num|crush_ruleset", \
+	"name=var,type=CephChoices,strings=size|min_size|crash_replay_interval|pg_num|pgp_num|crush_ruleset|hit_set_type|hit_set_period|hit_set_count|hit_set_fpp", \
 	"get pool parameter <var>", "osd", "r", "cli,rest")
 COMMAND("osd pool set " \
 	"name=pool,type=CephPoolname " \
-	"name=var,type=CephChoices,strings=size|min_size|crash_replay_interval|pg_num|pgp_num|crush_ruleset|hashpspool|hit_set_type|hit_set_period|hit_set_count|hit_set_fpp|debug_fake_ec_pool||target_max_bytes|target_max_objects|cache_target_dirty_ratio|cache_target_full_ratio|cache_min_flush_age|cache_min_evict_age " \
+	"name=var,type=CephChoices,strings=size|min_size|crash_replay_interval|pg_num|pgp_num|crush_ruleset|hashpspool|hit_set_type|hit_set_period|hit_set_count|hit_set_fpp|debug_fake_ec_pool|target_max_bytes|target_max_objects|cache_target_dirty_ratio|cache_target_full_ratio|cache_min_flush_age|cache_min_evict_age " \
 	"name=val,type=CephString", \
 	"set pool parameter <var> to <val>", "osd", "rw", "cli,rest")
 // 'val' is a CephString because it can include a unit.  Perhaps
diff --git a/src/mon/Monitor.cc b/src/mon/Monitor.cc
index dac9c3e..7e29e14 100644
--- a/src/mon/Monitor.cc
+++ b/src/mon/Monitor.cc
@@ -260,7 +260,7 @@ void Monitor::do_admin_command(string command, cmdmap_t& cmdmap, string format,
   boost::scoped_ptr<Formatter> f(new_formatter(format));
 
   if (command == "mon_status") {
-    _mon_status(f.get(), ss);
+    get_mon_status(f.get(), ss);
     if (f)
       f->flush(ss);
   } else if (command == "quorum_status")
@@ -1740,7 +1740,7 @@ void Monitor::_quorum_status(Formatter *f, ostream& ss)
     delete f;
 }
 
-void Monitor::_mon_status(Formatter *f, ostream& ss)
+void Monitor::get_mon_status(Formatter *f, ostream& ss)
 {
   bool free_formatter = false;
 
@@ -1941,7 +1941,7 @@ void Monitor::get_health(string& status, bufferlist *detailbl, Formatter *f)
     f->close_section();
 }
 
-void Monitor::get_status(stringstream &ss, Formatter *f)
+void Monitor::get_cluster_status(stringstream &ss, Formatter *f)
 {
   if (f)
     f->open_object_section("status");
@@ -2283,8 +2283,8 @@ void Monitor::handle_command(MMonCommand *m)
     cmd_getval(g_ceph_context, cmdmap, "detail", detail);
 
     if (prefix == "status") {
-      // get_status handles f == NULL
-      get_status(ds, f.get());
+      // get_cluster_status handles f == NULL
+      get_cluster_status(ds, f.get());
 
       if (f) {
         f->flush(ds);
@@ -2375,7 +2375,7 @@ void Monitor::handle_command(MMonCommand *m)
     rs = "";
     r = 0;
   } else if (prefix == "mon_status") {
-    _mon_status(f.get(), ds);
+    get_mon_status(f.get(), ds);
     if (f)
       f->flush(ds);
     rdata.append(ds);
@@ -3042,7 +3042,7 @@ void Monitor::handle_ping(MPing *m)
   get_health(health_str, NULL, f);
   {
     stringstream ss;
-    _mon_status(f, ss);
+    get_mon_status(f, ss);
   }
 
   f->close_section();
@@ -3493,6 +3493,12 @@ void Monitor::handle_get_version(MMonGetVersion *m)
     return;
   }
 
+  if (!is_leader() && !is_peon()) {
+    dout(10) << " waiting for quorum" << dendl;
+    waitfor_quorum.push_back(new C_RetryMessage(this, m));
+    return;
+  }
+
   MMonGetVersionReply *reply = new MMonGetVersionReply();
   reply->handle = m->handle;
   if (m->what == "mdsmap") {
diff --git a/src/mon/Monitor.h b/src/mon/Monitor.h
index e8828a1..8e04634 100644
--- a/src/mon/Monitor.h
+++ b/src/mon/Monitor.h
@@ -618,7 +618,7 @@ public:
                         const map<string,cmd_vartype>& cmdmap,
                         const map<string,string>& param_str_map,
                         const MonCommand *this_cmd);
-  void _mon_status(Formatter *f, ostream& ss);
+  void get_mon_status(Formatter *f, ostream& ss);
   void _quorum_status(Formatter *f, ostream& ss);
   void _osdmonitor_prepare_command(cmdmap_t& cmdmap, ostream& ss);
   void _add_bootstrap_peer_hint(string cmd, cmdmap_t& cmdmap, ostream& ss);
@@ -632,7 +632,7 @@ public:
    * @param detailbl optional bufferlist* to fill with a detailed report
    */
   void get_health(string& status, bufferlist *detailbl, Formatter *f);
-  void get_status(stringstream &ss, Formatter *f);
+  void get_cluster_status(stringstream &ss, Formatter *f);
 
   void reply_command(MMonCommand *m, int rc, const string &rs, version_t version);
   void reply_command(MMonCommand *m, int rc, const string &rs, bufferlist& rdata, version_t version);
diff --git a/src/mon/OSDMonitor.cc b/src/mon/OSDMonitor.cc
index a3ec269..4de2b42 100644
--- a/src/mon/OSDMonitor.cc
+++ b/src/mon/OSDMonitor.cc
@@ -4,6 +4,9 @@
  * Ceph - scalable distributed file system
  *
  * Copyright (C) 2004-2006 Sage Weil <sage at newdream.net>
+ * Copyright (C) 2013,2014 Cloudwatt <libre.licensing at cloudwatt.com>
+ *
+ * Author: Loic Dachary <loic at dachary.org>
  *
  * This is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -260,7 +263,7 @@ void OSDMonitor::update_from_paxos(bool *need_bootstrap)
 
   /** we don't have any of the feature bit infrastructure in place for
    * supporting primary_temp mappings without breaking old clients/OSDs.*/
-  assert(osdmap.primary_temp->empty());
+  assert(g_conf->mon_osd_allow_primary_temp || osdmap.primary_temp->empty());
 
   if (mon->is_leader()) {
     // kick pgmon, make sure it's seen the latest map
@@ -640,7 +643,7 @@ version_t OSDMonitor::get_trim_to()
 {
   if (mon->pgmon()->is_readable() &&
       mon->pgmon()->pg_map.creating_pgs.empty()) {
-    epoch_t floor = mon->pgmon()->pg_map.calc_min_last_epoch_clean();
+    epoch_t floor = mon->pgmon()->pg_map.get_min_last_epoch_clean();
     dout(10) << " min_last_epoch_clean " << floor << dendl;
     if (g_conf->mon_osd_force_trim_to > 0 &&
 	g_conf->mon_osd_force_trim_to < (int)get_last_committed()) {
@@ -1472,11 +1475,15 @@ bool OSDMonitor::preprocess_pgtemp(MOSDPGTemp *m)
     }
 
     // removal?
-    if (p->second.empty() && osdmap.pg_temp->count(p->first))
+    if (p->second.empty() && (osdmap.pg_temp->count(p->first) ||
+			      osdmap.primary_temp->count(p->first)))
       return false;
     // change?
+    //  NOTE: we assume that this will clear pg_primary, so consider
+    //        an existing pg_primary field to imply a change
     if (p->second.size() && (osdmap.pg_temp->count(p->first) == 0 ||
-			     (*osdmap.pg_temp)[p->first] != p->second))
+			     (*osdmap.pg_temp)[p->first] != p->second ||
+			     osdmap.primary_temp->count(p->first)))
       return false;
   }
 
@@ -1510,6 +1517,13 @@ bool OSDMonitor::prepare_pgtemp(MOSDPGTemp *m)
       continue;
     }
     pending_inc.new_pg_temp[p->first] = p->second;
+
+    // unconditionally clear pg_primary (until this message can encode
+    // a change for that, too.. at which point we need to also fix
+    // preprocess_pg_temp)
+    if (osdmap.primary_temp->count(p->first) ||
+	pending_inc.new_primary_temp.count(p->first))
+      pending_inc.new_primary_temp[p->first] = -1;
   }
   pending_inc.new_up_thru[from] = m->map_epoch;   // set up_thru too, so the osd doesn't have to ask again
   wait_for_finished_proposal(new C_ReplyMap(this, m, m->map_epoch));
@@ -2422,6 +2436,22 @@ bool OSDMonitor::preprocess_command(MMonCommand *m)
         f->dump_int("crash_replay_interval", p->get_crash_replay_interval());
       } else if (var == "crush_ruleset") {
         f->dump_int("crush_ruleset", p->get_crush_ruleset());
+      } else if (var == "hit_set_period") {
+	f->dump_int("hit_set_period", p->hit_set_period);
+      } else if (var == "hit_set_count") {
+	f->dump_int("hit_set_count", p->hit_set_count);
+      } else if (var == "hit_set_type") {
+	f->dump_string("hit_set_type", HitSet::get_type_name(p->hit_set_params.get_type()));
+      } else if (var == "hit_set_fpp") {
+	if (p->hit_set_params.get_type() != HitSet::TYPE_BLOOM) {
+	  f->close_section();
+	  ss << "hit set is no of type Bloom; invalid to get a false positive rate!";
+	  r = -EINVAL;
+	  goto reply;
+	} else {
+	  BloomHitSet::Params *bloomp = static_cast<BloomHitSet::Params*>(p->hit_set_params.impl.get());
+	  f->dump_float("hit_set_fpp", bloomp->get_fpp());
+	}
       }
 
       f->close_section();
@@ -2439,6 +2469,20 @@ bool OSDMonitor::preprocess_command(MMonCommand *m)
         ss << "crash_replay_interval: " << p->get_crash_replay_interval();
       } else if (var == "crush_ruleset") {
         ss << "crush_ruleset: " << p->get_crush_ruleset();
+      } else if (var == "hit_set_period") {
+	ss << "hit_set_period: " << p->hit_set_period;
+      } else if (var == "hit_set_count") {
+	ss << "hit_set_count: " << p->hit_set_count;
+      } else if (var == "hit_set_type") {
+	ss << "hit_set_type: " <<  HitSet::get_type_name(p->hit_set_params.get_type());
+      } else if (var == "hit_set_fpp") {
+	if (p->hit_set_params.get_type() != HitSet::TYPE_BLOOM) {
+	  ss << "hit set is no of type Bloom; invalid to get a false positive rate!";
+	  r = -EINVAL;
+	  goto reply;
+	}
+	BloomHitSet::Params *bloomp = static_cast<BloomHitSet::Params*>(p->hit_set_params.impl.get());
+	ss << "hit_set_fpp: " << bloomp->get_fpp();
       }
       rdata.append(ss);
       ss.str("");
@@ -2613,6 +2657,52 @@ stats_out:
     f->flush(rs);
     rs << "\n";
     rdata.append(rs.str());
+  } else if (prefix == "osd erasure-code-profile ls") {
+    const map<string,map<string,string> > &profiles =
+      osdmap.get_erasure_code_profiles();
+    if (f)
+      f->open_array_section("erasure-code-profiles");
+    for(map<string,map<string,string> >::const_iterator i = profiles.begin();
+	i != profiles.end();
+	i++) {
+      if (f)
+        f->dump_string("profile", i->first.c_str());
+      else
+	rdata.append(i->first + "\n");
+    }
+    if (f) {
+      f->close_section();
+      ostringstream rs;
+      f->flush(rs);
+      rs << "\n";
+      rdata.append(rs.str());
+    }
+  } else if (prefix == "osd erasure-code-profile get") {
+    string name;
+    cmd_getval(g_ceph_context, cmdmap, "name", name);
+    if (!osdmap.has_erasure_code_profile(name)) {
+      ss << "unknown erasure code profile '" << name << "'";
+      r = -ENOENT;
+      goto reply;
+    }
+    const map<string,string> &profile = osdmap.get_erasure_code_profile(name);
+    if (f)
+      f->open_object_section("profile");
+    for (map<string,string>::const_iterator i = profile.begin();
+	 i != profile.end();
+	 i++) {
+      if (f)
+        f->dump_string(i->first.c_str(), i->second.c_str());
+      else
+	rdata.append(i->first + "=" + i->second + "\n");
+    }
+    if (f) {
+      f->close_section();
+      ostringstream rs;
+      f->flush(rs);
+      rs << "\n";
+      rdata.append(rs.str());
+    }
   } else {
     // try prepare update
     return false;
@@ -2777,30 +2867,73 @@ int OSDMonitor::prepare_new_pool(MPoolOp *m)
   MonSession *session = m->get_session();
   if (!session)
     return -EPERM;
-  vector<string> properties;
+  string erasure_code_profile;
   stringstream ss;
+  string ruleset_name;
   if (m->auid)
-    return prepare_new_pool(m->name, m->auid, m->crush_rule, 0, 0,
-                            properties, pg_pool_t::TYPE_REPLICATED, ss);
+    return prepare_new_pool(m->name, m->auid, m->crush_rule, ruleset_name,
+			    0, 0,
+                            erasure_code_profile,
+			    pg_pool_t::TYPE_REPLICATED, ss);
   else
-    return prepare_new_pool(m->name, session->auid, m->crush_rule, 0, 0,
-                            properties, pg_pool_t::TYPE_REPLICATED, ss);
+    return prepare_new_pool(m->name, session->auid, m->crush_rule, ruleset_name,
+			    0, 0,
+                            erasure_code_profile,
+			    pg_pool_t::TYPE_REPLICATED, ss);
+}
+
+int OSDMonitor::crush_ruleset_create_erasure(const string &name,
+					     const string &profile,
+					     int *ruleset,
+					     stringstream &ss)
+{
+  *ruleset = osdmap.crush->get_rule_id(name);
+  if (*ruleset != -ENOENT)
+    return -EEXIST;
+
+  CrushWrapper newcrush;
+  _get_pending_crush(newcrush);
+
+  *ruleset = newcrush.get_rule_id(name);
+  if (*ruleset != -ENOENT) {
+    return -EALREADY;
+  } else {
+    ErasureCodeInterfaceRef erasure_code;
+    int err = get_erasure_code(profile, &erasure_code, ss);
+    if (err) {
+      ss << "failed to load plugin using profile " << profile;
+      return err;
+    }
+
+    err = erasure_code->create_ruleset(name, newcrush, &ss);
+    erasure_code.reset();
+    if (err < 0)
+      return err;
+    *ruleset = err;
+    pending_inc.crush.clear();
+    newcrush.encode(pending_inc.crush);
+    return 0;
+  }
 }
 
-int OSDMonitor::get_erasure_code(const map<string,string> &properties,
+int OSDMonitor::get_erasure_code(const string &erasure_code_profile,
 				 ErasureCodeInterfaceRef *erasure_code,
 				 stringstream &ss)
 {
+  if (pending_inc.has_erasure_code_profile(erasure_code_profile))
+    return -EAGAIN;
+  const map<string,string> &profile =
+    osdmap.get_erasure_code_profile(erasure_code_profile);
   map<string,string>::const_iterator plugin =
-    properties.find("erasure-code-plugin");
-  if (plugin == properties.end()) {
+    profile.find("plugin");
+  if (plugin == profile.end()) {
     ss << "cannot determine the erasure code plugin"
-       << " because erasure-code-plugin is not in the properties "
-       << properties;
+       << " because there is no 'plugin' entry in the erasure_code_profile "
+       << profile;
     return -EINVAL;
   }
   ErasureCodePluginRegistry &instance = ErasureCodePluginRegistry::instance();
-  return instance.factory(plugin->second, properties, erasure_code);
+  return instance.factory(plugin->second, profile, erasure_code, ss);
 }
 
 int OSDMonitor::check_cluster_features(uint64_t features,
@@ -2847,32 +2980,48 @@ int OSDMonitor::check_cluster_features(uint64_t features,
   return 0;
 }
 
-int OSDMonitor::prepare_pool_properties(const unsigned pool_type,
-					const vector<string> &properties,
-					map<string,string> *properties_map,
-					stringstream &ss)
+bool OSDMonitor::erasure_code_profile_in_use(const map<int64_t, pg_pool_t> &pools,
+					     const string &profile,
+					     ostream &ss)
 {
-  if (pool_type == pg_pool_t::TYPE_ERASURE) {
-    int r = get_str_map(g_conf->osd_pool_default_erasure_code_properties,
-			ss,
-			properties_map);
-    if (r)
-      return r;
-    (*properties_map)["erasure-code-directory"] =
-      g_conf->osd_pool_default_erasure_code_directory;
-  }
-
-  for (vector<string>::const_iterator i = properties.begin();
-       i != properties.end();
+  bool found = false;
+  for (map<int64_t, pg_pool_t>::const_iterator p = pools.begin();
+       p != pools.end();
+       ++p) {
+    if (p->second.erasure_code_profile == profile) {
+      ss << osdmap.pool_name[p->first] << " ";
+      found = true;
+    }
+  }
+  if (found) {
+    ss << "pool(s) are using the erasure code profile '" << profile << "'";
+  }
+  return found;
+}
+
+int OSDMonitor::parse_erasure_code_profile(const vector<string> &erasure_code_profile,
+					   map<string,string> *erasure_code_profile_map,
+					   stringstream &ss)
+{
+  int r = get_str_map(g_conf->osd_pool_default_erasure_code_profile,
+		      ss,
+		      erasure_code_profile_map);
+  if (r)
+    return r;
+  (*erasure_code_profile_map)["directory"] =
+    g_conf->osd_pool_default_erasure_code_directory;
+
+  for (vector<string>::const_iterator i = erasure_code_profile.begin();
+       i != erasure_code_profile.end();
        ++i) {
     size_t equal = i->find('=');
     if (equal == string::npos)
-      (*properties_map)[*i] = string();
+      (*erasure_code_profile_map)[*i] = string();
     else {
       const string key = i->substr(0, equal);
       equal++;
       const string value = i->substr(equal);
-      (*properties_map)[key] = value;
+      (*erasure_code_profile_map)[key] = value;
     }
   }
 
@@ -2880,7 +3029,7 @@ int OSDMonitor::prepare_pool_properties(const unsigned pool_type,
 }
 
 int OSDMonitor::prepare_pool_size(const unsigned pool_type,
-				  const map<string,string> &properties,
+				  const string &erasure_code_profile,
 				  unsigned *size,
 				  stringstream &ss)
 {
@@ -2892,7 +3041,7 @@ int OSDMonitor::prepare_pool_size(const unsigned pool_type,
   case pg_pool_t::TYPE_ERASURE:
     {
       ErasureCodeInterfaceRef erasure_code;
-      err = get_erasure_code(properties, &erasure_code, ss);
+      err = get_erasure_code(erasure_code_profile, &erasure_code, ss);
       if (err == 0)
 	*size = erasure_code->get_chunk_count();
     }
@@ -2906,7 +3055,7 @@ int OSDMonitor::prepare_pool_size(const unsigned pool_type,
 }
 
 int OSDMonitor::prepare_pool_stripe_width(const unsigned pool_type,
-					  const map<string,string> &properties,
+					  const string &erasure_code_profile,
 					  uint32_t *stripe_width,
 					  stringstream &ss)
 {
@@ -2918,7 +3067,7 @@ int OSDMonitor::prepare_pool_stripe_width(const unsigned pool_type,
   case pg_pool_t::TYPE_ERASURE:
     {
       ErasureCodeInterfaceRef erasure_code;
-      err = get_erasure_code(properties, &erasure_code, ss);
+      err = get_erasure_code(erasure_code_profile, &erasure_code, ss);
       uint32_t desired_stripe_width = g_conf->osd_pool_erasure_code_stripe_width;
       if (err == 0)
 	*stripe_width = erasure_code->get_data_chunk_count() *
@@ -2935,7 +3084,8 @@ int OSDMonitor::prepare_pool_stripe_width(const unsigned pool_type,
 }
 
 int OSDMonitor::prepare_pool_crush_ruleset(const unsigned pool_type,
-					   const map<string,string> &properties,
+					   const string &erasure_code_profile,
+					   const string &ruleset_name,
 					   int *crush_ruleset,
 					   stringstream &ss)
 {
@@ -2947,30 +3097,22 @@ int OSDMonitor::prepare_pool_crush_ruleset(const unsigned pool_type,
       break;
     case pg_pool_t::TYPE_ERASURE:
       {
-	map<string,string>::const_iterator ruleset =
-	  properties.find("crush_ruleset");
-	if (ruleset == properties.end()) {
-	  ss << "prepare_pool_crush_ruleset: crush_ruleset is missing from "
-	     << properties;
-	  return -EINVAL;
-	}
-
-	*crush_ruleset = osdmap.crush->get_rule_id(ruleset->second);
-	if (*crush_ruleset < 0) {
-	  CrushWrapper newcrush;
-	  _get_pending_crush(newcrush);
-
-	  int rule = newcrush.get_rule_id(ruleset->second);
-	  if (rule < 0) {
-	    ss << "prepare_pool_crush_ruleset: ruleset " << ruleset->second
-	       << " does not exist";
-	    return -EINVAL;
-	  } else {
-	    dout(20) << "prepare_pool_crush_ruleset: ruleset "
-		     << ruleset->second << " try again" << dendl;
-	    return -EAGAIN;
-	  }
-	}
+	int err = crush_ruleset_create_erasure(ruleset_name,
+					       erasure_code_profile,
+					       crush_ruleset, ss);
+	switch (err) {
+	case -EALREADY:
+	  dout(20) << "prepare_pool_crush_ruleset: ruleset "
+		   << ruleset_name << " try again" << dendl;
+	case 0:
+	  // need to wait for the crush rule to be proposed before proceeding
+	  err = -EAGAIN;
+	  break;
+	case -EEXIST:
+	  err = 0;
+	  break;
+ 	}
+	return err;
       }
       break;
     default:
@@ -2986,34 +3128,35 @@ int OSDMonitor::prepare_pool_crush_ruleset(const unsigned pool_type,
 /**
  * @param name The name of the new pool
  * @param auid The auid of the pool owner. Can be -1
- * @param crush_rule The crush rule to use. If <0, will use the system default
+ * @param crush_ruleset The crush rule to use. If <0, will use the system default
+ * @param crush_ruleset_name The crush rule to use, if crush_rulset <0
  * @param pg_num The pg_num to use. If set to 0, will use the system default
  * @param pgp_num The pgp_num to use. If set to 0, will use the system default
- * @param properties An opaque list of key[=value] pairs for pool configuration
+ * @param erasure_code_profile The profile name in OSDMap to be used for erasure code
  * @param pool_type TYPE_ERASURE, TYPE_REP or TYPE_RAID4
  * @param ss human readable error message, if any.
  *
  * @return 0 on success, negative errno on failure.
  */
-int OSDMonitor::prepare_new_pool(string& name, uint64_t auid, int crush_ruleset,
+int OSDMonitor::prepare_new_pool(string& name, uint64_t auid,
+				 int crush_ruleset,
+				 const string &crush_ruleset_name,
                                  unsigned pg_num, unsigned pgp_num,
-				 const vector<string> &properties,
+				 const string &erasure_code_profile,
                                  const unsigned pool_type,
 				 stringstream &ss)
 {
-  map<string,string> properties_map;
-  int r = prepare_pool_properties(pool_type, properties, &properties_map, ss);
-  if (r)
-    return r;
-  r = prepare_pool_crush_ruleset(pool_type, properties_map, &crush_ruleset, ss);
+  int r;
+  r = prepare_pool_crush_ruleset(pool_type, erasure_code_profile,
+				 crush_ruleset_name, &crush_ruleset, ss);
   if (r)
     return r;
   unsigned size;
-  r = prepare_pool_size(pool_type, properties_map, &size, ss);
+  r = prepare_pool_size(pool_type, erasure_code_profile, &size, ss);
   if (r)
     return r;
   uint32_t stripe_width = 0;
-  r = prepare_pool_stripe_width(pool_type, properties_map, &stripe_width, ss);
+  r = prepare_pool_stripe_width(pool_type, erasure_code_profile, &stripe_width, ss);
   if (r)
     return r;
 
@@ -3042,7 +3185,7 @@ int OSDMonitor::prepare_new_pool(string& name, uint64_t auid, int crush_ruleset,
   pi->set_pgp_num(pgp_num ? pgp_num : g_conf->osd_pool_default_pgp_num);
   pi->last_change = pending_inc.epoch;
   pi->auid = auid;
-  pi->properties = properties_map;
+  pi->erasure_code_profile = erasure_code_profile;
   pi->stripe_width = stripe_width;
   pi->cache_target_dirty_ratio_micro =
     g_conf->osd_pool_default_cache_target_dirty_ratio * 1000000;
@@ -3239,17 +3382,22 @@ int OSDMonitor::prepare_command_pool_set(map<string,cmd_vartype> &cmdmap,
   } else if (var == "hit_set_type") {
     if (val == "none")
       p.hit_set_params = HitSet::Params();
-    else if (val == "bloom") {
-      BloomHitSet::Params *bsp = new BloomHitSet::Params;
-      bsp->set_fpp(g_conf->osd_pool_default_hit_set_bloom_fpp);
-      p.hit_set_params = HitSet::Params(bsp);
-    } else if (val == "explicit_hash")
-      p.hit_set_params = HitSet::Params(new ExplicitHashHitSet::Params);
-    else if (val == "explicit_object")
-      p.hit_set_params = HitSet::Params(new ExplicitObjectHitSet::Params);
     else {
-      ss << "unrecognized hit_set type '" << val << "'";
-      return -EINVAL;
+      int err = check_cluster_features(CEPH_FEATURE_OSD_CACHEPOOL, ss);
+      if (err)
+	return err;
+      if (val == "bloom") {
+	BloomHitSet::Params *bsp = new BloomHitSet::Params;
+	bsp->set_fpp(g_conf->osd_pool_default_hit_set_bloom_fpp);
+	p.hit_set_params = HitSet::Params(bsp);
+      } else if (val == "explicit_hash")
+	p.hit_set_params = HitSet::Params(new ExplicitHashHitSet::Params);
+      else if (val == "explicit_object")
+	p.hit_set_params = HitSet::Params(new ExplicitObjectHitSet::Params);
+      else {
+	ss << "unrecognized hit_set type '" << val << "'";
+	return -EINVAL;
+      }
     }
   } else if (var == "hit_set_period") {
     if (interr.length()) {
@@ -3848,52 +3996,111 @@ bool OSDMonitor::prepare_command_impl(MMonCommand *m,
 					      get_last_committed() + 1));
     return true;
 
-  } else if (prefix == "osd crush rule create-erasure") {
-    err = check_cluster_features(CEPH_FEATURE_CRUSH_V2, ss);
-    if (err == -EAGAIN)
+  } else if (prefix == "osd erasure-code-profile rm") {
+    string name;
+    cmd_getval(g_ceph_context, cmdmap, "name", name);
+
+    if (erasure_code_profile_in_use(pending_inc.new_pools, name, ss))
       goto wait;
-    if (err)
+
+    if (erasure_code_profile_in_use(osdmap.pools, name, ss)) {
+      err = -EBUSY;
       goto reply;
-    string name, poolstr;
-    cmd_getval(g_ceph_context, cmdmap, "name", name);
-    vector<string> properties;
-    cmd_getval(g_ceph_context, cmdmap, "properties", properties);
+    }
 
-    if (osdmap.crush->rule_exists(name)) {
-      ss << "rule " << name << " already exists";
+    if (osdmap.has_erasure_code_profile(name) ||
+	pending_inc.new_erasure_code_profiles.count(name)) {
+      if (osdmap.has_erasure_code_profile(name)) {
+	pending_inc.old_erasure_code_profiles.push_back(name);
+      } else {
+	dout(20) << "erasure code profile rm " << name << ": creation canceled" << dendl;
+	pending_inc.new_erasure_code_profiles.erase(name);
+      }
+
+      getline(ss, rs);
+      wait_for_finished_proposal(new Monitor::C_Command(mon, m, 0, rs,
+							get_last_committed() + 1));
+      return true;
+    } else {
+      ss << "erasure-code-profile " << name << " does not exist";
       err = 0;
       goto reply;
     }
 
-    map<string,string> properties_map;
-    err = prepare_pool_properties(pg_pool_t::TYPE_ERASURE,
-				  properties, &properties_map, ss);
+  } else if (prefix == "osd erasure-code-profile set") {
+    string name;
+    cmd_getval(g_ceph_context, cmdmap, "name", name);
+    vector<string> profile;
+    cmd_getval(g_ceph_context, cmdmap, "profile", profile);
+    bool force;
+    if (profile.size() > 0 && profile.back() == "--force") {
+      profile.pop_back();
+      force = true;
+    } else {
+      force = false;
+    }
+    map<string,string> profile_map;
+    err = parse_erasure_code_profile(profile, &profile_map, ss);
     if (err)
       goto reply;
 
-    CrushWrapper newcrush;
-    _get_pending_crush(newcrush);
-
-    if (newcrush.rule_exists(name)) {
-      ss << "rule " << name << " already exists";
-      err = 0;
-    } else {
-      ErasureCodeInterfaceRef erasure_code;
-      err = get_erasure_code(properties_map, &erasure_code, ss);
-      if (err) {
-	ss << "failed to load plugin using properties " << properties_map;
+    if (osdmap.has_erasure_code_profile(name)) {
+      if (osdmap.get_erasure_code_profile(name) == profile_map) {
+	err = 0;
 	goto reply;
       }
+      if (!force) {
+	err = -EPERM;
+	ss << "will not override erasure code profile " << name;
+	goto reply;
+      }
+    }
 
-      int rule = erasure_code->create_ruleset(name, newcrush, &ss);
-      erasure_code.reset();
-      if (rule < 0) {
-	err = rule;
+    if (pending_inc.has_erasure_code_profile(name)) {
+      dout(20) << "erasure code profile " << name << " try again" << dendl;
+      goto wait;
+    } else {
+      dout(20) << "erasure code profile " << name << " set" << dendl;
+      pending_inc.set_erasure_code_profile(name, profile_map);
+    }
+
+    getline(ss, rs);
+    wait_for_finished_proposal(new Monitor::C_Command(mon, m, 0, rs,
+                                                      get_last_committed() + 1));
+    return true;
+
+  } else if (prefix == "osd crush rule create-erasure") {
+    err = check_cluster_features(CEPH_FEATURE_CRUSH_V2, ss);
+    if (err == -EAGAIN)
+      goto wait;
+    if (err)
+      goto reply;
+    string name, poolstr;
+    cmd_getval(g_ceph_context, cmdmap, "name", name);
+    string profile;
+    cmd_getval(g_ceph_context, cmdmap, "profile", profile);
+    if (profile == "")
+      profile = "default";
+
+    int ruleset;
+    err = crush_ruleset_create_erasure(name, profile, &ruleset, ss);
+    if (err < 0) {
+      switch(err) {
+      case -EEXIST: // return immediately
+	ss << "rule " << name << " already exists";
+	err = 0;
 	goto reply;
+	break;
+      case -EALREADY: // wait for pending to be proposed
+	ss << "rule " << name << " already exists";
+	err = 0;
+	break;
+      default: // non recoverable error
+ 	goto reply;
+	break;
       }
-      ss << "created rule " << name << " at " << rule;
-      pending_inc.crush.clear();
-      newcrush.encode(pending_inc.crush);
+    } else {
+      ss << "created ruleset " << name << " at " << ruleset;
     }
 
     getline(ss, rs);
@@ -4102,6 +4309,106 @@ bool OSDMonitor::prepare_command_impl(MMonCommand *m,
 						get_last_committed() + 1));
       return true;
     }
+  } else if (prefix == "osd pg-temp") {
+    string pgidstr;
+    if (!cmd_getval(g_ceph_context, cmdmap, "pgid", pgidstr)) {
+      ss << "unable to parse 'pgid' value '"
+         << cmd_vartype_stringify(cmdmap["pgid"]) << "'";
+      err = -EINVAL;
+      goto reply;
+    }
+    pg_t pgid;
+    if (!pgid.parse(pgidstr.c_str())) {
+      ss << "invalid pgid '" << pgidstr << "'";
+      err = -EINVAL;
+      goto reply;
+    }
+    PGMap& pg_map = mon->pgmon()->pg_map;
+    if (!pg_map.pg_stat.count(pgid)) {
+      ss << "pg " << pgid << " does not exist";
+      err = -ENOENT;
+      goto reply;
+    }
+
+    vector<string> id_vec;
+    vector<int32_t> new_pg_temp;
+    if (!cmd_getval(g_ceph_context, cmdmap, "id", id_vec)) {
+      ss << "unable to parse 'id' value(s) '"
+         << cmd_vartype_stringify(cmdmap["id"]) << "'";
+      err = -EINVAL;
+      goto reply;
+    }
+    for (unsigned i = 0; i < id_vec.size(); i++) {
+      int32_t osd = parse_osd_id(id_vec[i].c_str(), &ss);
+      if (osd < 0) {
+        err = -EINVAL;
+        goto reply;
+      }
+      if (!osdmap.exists(osd)) {
+        ss << "osd." << osd << " does not exist";
+        err = -ENOENT;
+        goto reply;
+      }
+
+      new_pg_temp.push_back(osd);
+    }
+
+    pending_inc.new_pg_temp[pgid] = new_pg_temp;
+    ss << "set " << pgid << " pg_temp mapping to " << new_pg_temp;
+    goto update;
+  } else if (prefix == "osd primary-temp") {
+    string pgidstr;
+    if (!cmd_getval(g_ceph_context, cmdmap, "pgid", pgidstr)) {
+      ss << "unable to parse 'pgid' value '"
+         << cmd_vartype_stringify(cmdmap["pgid"]) << "'";
+      err = -EINVAL;
+      goto reply;
+    }
+    pg_t pgid;
+    if (!pgid.parse(pgidstr.c_str())) {
+      ss << "invalid pgid '" << pgidstr << "'";
+      err = -EINVAL;
+      goto reply;
+    }
+    PGMap& pg_map = mon->pgmon()->pg_map;
+    if (!pg_map.pg_stat.count(pgid)) {
+      ss << "pg " << pgid << " does not exist";
+      err = -ENOENT;
+      goto reply;
+    }
+
+    string id;
+    int32_t osd;
+    if (!cmd_getval(g_ceph_context, cmdmap, "id", id)) {
+      ss << "unable to parse 'id' value '"
+         << cmd_vartype_stringify(cmdmap["id"]) << "'";
+      err = -EINVAL;
+      goto reply;
+    }
+    if (strcmp(id.c_str(), "-1")) {
+      osd = parse_osd_id(id.c_str(), &ss);
+      if (osd < 0) {
+        err = -EINVAL;
+        goto reply;
+      }
+      if (!osdmap.exists(osd)) {
+        ss << "osd." << osd << " does not exist";
+        err = -ENOENT;
+        goto reply;
+      }
+    } else {
+      osd = -1;
+    }
+
+    if (!g_conf->mon_osd_allow_primary_temp) {
+      ss << "you must enable 'mon osd allow primary temp = true' on the mons before you can set primary_temp mappings.  note that this is for developers only: older clients/OSDs will break and there is no feature bit infrastructure in place.";
+      err = -EPERM;
+      goto reply;
+    }
+
+    pending_inc.new_primary_temp[pgid] = osd;
+    ss << "set " << pgid << " primary_temp mapping to " << osd;
+    goto update;
   } else if (prefix == "osd primary-affinity") {
     int64_t id;
     if (!cmd_getval(g_ceph_context, cmdmap, "id", id)) {
@@ -4424,9 +4731,6 @@ done:
       goto reply;
     }
 
-    vector<string> properties;
-    cmd_getval(g_ceph_context, cmdmap, "properties", properties);
-
     int pool_type;
     if (pool_type_str == "replicated") {
       pool_type = pg_pool_t::TYPE_REPLICATED;
@@ -4445,10 +4749,27 @@ done:
       goto reply;
     }
 
+    string ruleset_name;
+    cmd_getval(g_ceph_context, cmdmap, "ruleset", ruleset_name);
+    string erasure_code_profile;
+    cmd_getval(g_ceph_context, cmdmap, "erasure_code_profile", erasure_code_profile);
+    if (erasure_code_profile == "")
+      erasure_code_profile = "default";
+    if (ruleset_name == "") {
+      if (erasure_code_profile == "default") {
+	ruleset_name = "erasure-code";
+      } else {
+	dout(1) << "implicitly use ruleset named after the pool: "
+		<< poolstr << dendl;
+	ruleset_name = poolstr;
+      }
+    }
+
     err = prepare_new_pool(poolstr, 0, // auid=0 for admin created pool
-			   -1,         // default crush rule
+			   -1, // default crush rule
+			   ruleset_name,
 			   pg_num, pgp_num,
-			   properties, pool_type,
+			   erasure_code_profile, pool_type,
 			   ss);
     if (err < 0) {
       switch(err) {
@@ -4542,6 +4863,8 @@ done:
 
   } else if (prefix == "osd pool set") {
     err = prepare_command_pool_set(cmdmap, ss);
+    if (err == -EAGAIN)
+      goto wait;
     if (err < 0)
       goto reply;
 
@@ -4550,6 +4873,11 @@ done:
 						   get_last_committed() + 1));
     return true;
   } else if (prefix == "osd tier add") {
+    err = check_cluster_features(CEPH_FEATURE_OSD_CACHEPOOL, ss);
+    if (err == -EAGAIN)
+      goto wait;
+    if (err)
+      goto reply;
     string poolstr;
     cmd_getval(g_ceph_context, cmdmap, "pool", poolstr);
     int64_t pool_id = osdmap.lookup_pg_pool_name(poolstr);
@@ -4601,6 +4929,7 @@ done:
       return true;
     }
     np->tiers.insert(tierpool_id);
+    np->set_snap_epoch(pending_inc.epoch); // tier will update to our snap info
     ntp->tier_of = pool_id;
     ss << "pool '" << tierpoolstr << "' is now (or already was) a tier of '" << poolstr << "'";
     wait_for_finished_proposal(new Monitor::C_Command(mon, m, 0, ss.str(),
@@ -4658,6 +4987,11 @@ done:
 					      get_last_committed() + 1));
     return true;
   } else if (prefix == "osd tier set-overlay") {
+    err = check_cluster_features(CEPH_FEATURE_OSD_CACHEPOOL, ss);
+    if (err == -EAGAIN)
+      goto wait;
+    if (err)
+      goto reply;
     string poolstr;
     cmd_getval(g_ceph_context, cmdmap, "pool", poolstr);
     int64_t pool_id = osdmap.lookup_pg_pool_name(poolstr);
@@ -4724,6 +5058,11 @@ done:
 					      get_last_committed() + 1));
     return true;
   } else if (prefix == "osd tier cache-mode") {
+    err = check_cluster_features(CEPH_FEATURE_OSD_CACHEPOOL, ss);
+    if (err == -EAGAIN)
+      goto wait;
+    if (err)
+      goto reply;
     string poolstr;
     cmd_getval(g_ceph_context, cmdmap, "pool", poolstr);
     int64_t pool_id = osdmap.lookup_pg_pool_name(poolstr);
@@ -4755,6 +5094,11 @@ done:
 					      get_last_committed() + 1));
     return true;
   } else if (prefix == "osd tier add-cache") {
+    err = check_cluster_features(CEPH_FEATURE_OSD_CACHEPOOL, ss);
+    if (err == -EAGAIN)
+      goto wait;
+    if (err)
+      goto reply;
     string poolstr;
     cmd_getval(g_ceph_context, cmdmap, "pool", poolstr);
     int64_t pool_id = osdmap.lookup_pg_pool_name(poolstr);
@@ -4833,6 +5177,7 @@ done:
       return true;
     }
     np->tiers.insert(tierpool_id);
+    np->set_snap_epoch(pending_inc.epoch); // tier will update to our snap info
     ntp->tier_of = pool_id;
     ntp->cache_mode = mode;
     ntp->hit_set_count = g_conf->osd_tier_default_cache_hit_set_count;
@@ -5070,6 +5415,7 @@ bool OSDMonitor::prepare_pool_op(MPoolOp *m)
         _pool_op_reply(m, -ENOTSUP, osdmap.get_epoch());
         return false;
       }
+      /* fall-thru */
     case POOL_OP_CREATE_UNMANAGED_SNAP:
       // but we will allow creating an unmanaged snapshot on any pool
       // as long as it is not in 'pool' snaps mode.
diff --git a/src/mon/OSDMonitor.h b/src/mon/OSDMonitor.h
index 8a87374..afc08f0 100644
--- a/src/mon/OSDMonitor.h
+++ b/src/mon/OSDMonitor.h
@@ -4,6 +4,9 @@
  * Ceph - scalable distributed file system
  *
  * Copyright (C) 2004-2006 Sage Weil <sage at newdream.net>
+ * Copyright (C) 2013,2014 Cloudwatt <libre.licensing at cloudwatt.com>
+ *
+ * Author: Loic Dachary <loic at dachary.org>
  *
  * This is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -240,28 +243,37 @@ private:
   bool prepare_pool_op (MPoolOp *m);
   bool prepare_pool_op_create (MPoolOp *m);
   bool prepare_pool_op_delete(MPoolOp *m);
-  int get_erasure_code(const map<string,string> &properties,
+  int crush_ruleset_create_erasure(const string &name,
+				   const string &profile,
+				   int *ruleset,
+				   stringstream &ss);
+  int get_erasure_code(const string &erasure_code_profile,
 		       ErasureCodeInterfaceRef *erasure_code,
 		       stringstream &ss);
-  int prepare_pool_properties(const unsigned pool_type,
-			      const vector<string> &properties,
-			      map<string,string> *properties_map,
-			      stringstream &ss);
   int prepare_pool_crush_ruleset(const unsigned pool_type,
-				 const map<string,string> &properties,
+				 const string &erasure_code_profile,
+				 const string &ruleset_name,
 				 int *crush_ruleset,
 				 stringstream &ss);
+  bool erasure_code_profile_in_use(const map<int64_t, pg_pool_t> &pools,
+				   const string &profile,
+				   ostream &ss);
+  int parse_erasure_code_profile(const vector<string> &erasure_code_profile,
+				 map<string,string> *erasure_code_profile_map,
+				 stringstream &ss);
   int prepare_pool_size(const unsigned pool_type,
-			const map<string,string> &properties,
+			const string &erasure_code_profile,
 			unsigned *size,
 			stringstream &ss);
   int prepare_pool_stripe_width(const unsigned pool_type,
-				const map<string,string> &properties,
+				const string &erasure_code_profile,
 				unsigned *stripe_width,
 				stringstream &ss);
-  int prepare_new_pool(string& name, uint64_t auid, int crush_ruleset,
+  int prepare_new_pool(string& name, uint64_t auid,
+		       int crush_ruleset,
+		       const string &crush_ruleset_name,
                        unsigned pg_num, unsigned pgp_num,
-		       const vector<string> &properties,
+		       const string &erasure_code_profile,
                        const unsigned pool_type,
 		       stringstream &ss);
   int prepare_new_pool(MPoolOp *m);
diff --git a/src/mon/PGMap.cc b/src/mon/PGMap.cc
index fbed206..5ec8ee2 100644
--- a/src/mon/PGMap.cc
+++ b/src/mon/PGMap.cc
@@ -207,7 +207,20 @@ void PGMap::apply_incremental(CephContext *cct, const Incremental& inc)
     if (t == pg_stat.end()) {
       ceph::unordered_map<pg_t,pg_stat_t>::value_type v(update_pg, update_stat);
       pg_stat.insert(v);
+      // did we affect the min?
+      if (min_last_epoch_clean &&
+	  update_stat.get_effective_last_epoch_clean() < min_last_epoch_clean)
+	min_last_epoch_clean = 0;
     } else {
+      // did we (or might we) affect the min?
+      epoch_t lec = update_stat.get_effective_last_epoch_clean();
+      if (min_last_epoch_clean &&
+	  (lec < min_last_epoch_clean ||  // we did
+	   (lec > min_last_epoch_clean && // we might
+	    t->second.get_effective_last_epoch_clean() == min_last_epoch_clean)
+	   ))
+	min_last_epoch_clean = 0;
+
       stat_pg_sub(update_pg, t->second);
       t->second = update_stat;
     }
@@ -229,15 +242,29 @@ void PGMap::apply_incremental(CephContext *cct, const Incremental& inc)
       stat_osd_sub(t->second);
       t->second = new_stats;
     }
+    ceph::unordered_map<int32_t,epoch_t>::iterator i = osd_epochs.find(osd);
     map<int32_t,epoch_t>::const_iterator j = inc.get_osd_epochs().find(osd);
     assert(j != inc.get_osd_epochs().end());
-    osd_epochs[j->first] = j->second;
+
+    // will we potentially affect the min?
+    if (min_last_epoch_clean &&
+	(i == osd_epochs.end() ||
+	 j->second < min_last_epoch_clean ||
+	 (j->second > min_last_epoch_clean &&
+	  i->second == min_last_epoch_clean)))
+      min_last_epoch_clean = 0;
+
+    if (i == osd_epochs.end())
+      osd_epochs.insert(*j);
+    else
+      i->second = j->second;
 
     stat_osd_add(new_stats);
 
     // adjust [near]full status
     register_nearfull_status(osd, new_stats);
   }
+  set<int64_t> deleted_pools;
   for (set<pg_t>::const_iterator p = inc.pg_remove.begin();
        p != inc.pg_remove.end();
        ++p) {
@@ -247,6 +274,14 @@ void PGMap::apply_incremental(CephContext *cct, const Incremental& inc)
       stat_pg_sub(removed_pg, s->second);
       pg_stat.erase(s);
     }
+    if (removed_pg.ps() == 0)
+      deleted_pools.insert(removed_pg.pool());
+  }
+  for (set<int64_t>::iterator p = deleted_pools.begin();
+       p != deleted_pools.end();
+       ++p) {
+    dout(20) << " deleted pool " << *p << dendl;
+    deleted_pool(*p);
   }
 
   for (set<int>::iterator p = inc.get_osd_stat_rm().begin();
@@ -282,6 +317,8 @@ void PGMap::apply_incremental(CephContext *cct, const Incremental& inc)
     last_osdmap_epoch = inc.osdmap_epoch;
   if (inc.pg_scan)
     last_pg_scan = inc.pg_scan;
+
+  min_last_epoch_clean = 0;  // invalidate
 }
 
 void PGMap::redo_full_sets()
@@ -334,6 +371,8 @@ void PGMap::calc_stats()
     stat_osd_add(p->second);
 
   redo_full_sets();
+
+  calc_min_last_epoch_clean();
 }
 
 void PGMap::update_pg(pg_t pgid, bufferlist& bl)
diff --git a/src/mon/PGMap.h b/src/mon/PGMap.h
index f4e8df5..99ce521 100644
--- a/src/mon/PGMap.h
+++ b/src/mon/PGMap.h
@@ -105,6 +105,7 @@ public:
   ceph::unordered_map<int,pool_stat_t> pg_pool_sum;
   pool_stat_t pg_sum;
   osd_stat_t osd_sum;
+  mutable epoch_t min_last_epoch_clean;
 
   utime_t stamp;
 
@@ -138,6 +139,13 @@ public:
                           const ceph::unordered_map<uint64_t, pool_stat_t>& pg_pool_sum_old);
   void clear_delta();
 
+  void deleted_pool(int64_t pool) {
+    pg_pool_sum.erase(pool);
+    per_pool_sum_deltas.erase(pool);
+    per_pool_sum_deltas_stamps.erase(pool);
+    per_pool_sum_delta.erase(pool);
+  }
+
  private:
   void update_delta(CephContext *cct,
                     const utime_t ts,
@@ -152,6 +160,9 @@ public:
                              const utime_t ts,
                              const uint64_t pool,
                              const pool_stat_t& old_pool_sum);
+
+  epoch_t calc_min_last_epoch_clean() const;
+
  public:
 
   set<pg_t> creating_pgs;   // lru: front = new additions, back = recently pinged
@@ -169,7 +180,8 @@ public:
       last_osdmap_epoch(0), last_pg_scan(0),
       full_ratio(0), nearfull_ratio(0),
       num_pg(0),
-      num_osd(0)
+      num_osd(0),
+      min_last_epoch_clean(0)
   {}
 
   void set_full_ratios(float full, float nearfull) {
@@ -285,7 +297,11 @@ public:
   void print_summary(Formatter *f, ostream *out) const;
   void print_oneline_summary(ostream *out) const;
 
-  epoch_t calc_min_last_epoch_clean() const;
+  epoch_t get_min_last_epoch_clean() const {
+    if (!min_last_epoch_clean)
+      min_last_epoch_clean = calc_min_last_epoch_clean();
+    return min_last_epoch_clean;
+  }
 
   static void generate_test_instances(list<PGMap*>& o);
 };
diff --git a/src/mon/PGMonitor.cc b/src/mon/PGMonitor.cc
index 5adf535..fdee216 100644
--- a/src/mon/PGMonitor.cc
+++ b/src/mon/PGMonitor.cc
@@ -430,6 +430,7 @@ void PGMonitor::apply_pgmap_delta(bufferlist& bl)
   ceph::unordered_map<uint64_t, pool_stat_t> pg_pool_sum_old;
 
   // pgs
+  set<int64_t> deleted_pools;
   bufferlist::iterator p = dirty_pgs.begin();
   while (!p.end()) {
     pg_t pgid;
@@ -446,6 +447,8 @@ void PGMonitor::apply_pgmap_delta(bufferlist& bl)
       pg_map.update_pg(pgid, bl);
     } else {
       pg_map.remove_pg(pgid);
+      if (pgid.ps() == 0)
+	deleted_pools.insert(pgid.pool());
     }
   }
 
@@ -467,6 +470,14 @@ void PGMonitor::apply_pgmap_delta(bufferlist& bl)
   pg_map.update_global_delta(g_ceph_context, inc_stamp, pg_sum_old);
   pg_map.update_pool_deltas(g_ceph_context, inc_stamp, pg_pool_sum_old);
 
+  // clean up deleted pools after updating the deltas
+  for (set<int64_t>::iterator p = deleted_pools.begin();
+       p != deleted_pools.end();
+       ++p) {
+    dout(20) << " deleted pool " << *p << dendl;
+    pg_map.deleted_pool(*p);
+  }
+
   // ok, we're now on the new version
   pg_map.version = v;
 }
diff --git a/src/mon/Paxos.cc b/src/mon/Paxos.cc
index 495268f..3883a32 100644
--- a/src/mon/Paxos.cc
+++ b/src/mon/Paxos.cc
@@ -691,22 +691,21 @@ void Paxos::handle_accept(MMonPaxos *accept)
 
   assert(g_conf->paxos_kill_at != 6);
 
-  // new majority?
-  if (accepted.size() == (unsigned)mon->monmap->size()/2+1) {
+  // only commit (and expose committed state) when we get *all* quorum
+  // members to accept.  otherwise, they may still be sharing the now
+  // stale state.
+  // FIXME: we can improve this with an additional lease revocation message
+  // that doesn't block for the persist.
+  if (accepted == mon->get_quorum()) {
     // yay, commit!
-    // note: this may happen before the lease is reextended (below)
-    dout(10) << " got majority, committing" << dendl;
+    dout(10) << " got majority, committing, done with update" << dendl;
     commit();
     if (!do_refresh())
       goto out;
     if (is_updating())
       commit_proposal();
     finish_contexts(g_ceph_context, waiting_for_commit);
-  }
 
-  // done?
-  if (accepted == mon->get_quorum()) {
-    dout(10) << " got quorum, done with update" << dendl;
     // cancel timeout event
     mon->timer.cancel_event(accept_timeout_event);
     accept_timeout_event = 0;
diff --git a/src/msg/Accepter.cc b/src/msg/Accepter.cc
index f8ae711..d747ccb 100644
--- a/src/msg/Accepter.cc
+++ b/src/msg/Accepter.cc
@@ -247,7 +247,9 @@ void Accepter::stop()
 
   // wait for thread to stop before closing the socket, to avoid
   // racing against fd re-use.
-  join();
+  if (is_started()) {
+    join();
+  }
 
   if (listen_sd >= 0) {
     ::close(listen_sd);
diff --git a/src/msg/DispatchQueue.cc b/src/msg/DispatchQueue.cc
index 3adc038..8a79ce0 100644
--- a/src/msg/DispatchQueue.cc
+++ b/src/msg/DispatchQueue.cc
@@ -55,6 +55,7 @@ void DispatchQueue::local_delivery(Message *m, int priority)
 {
   Mutex::Locker l(lock);
   m->set_connection(msgr->local_connection.get());
+  m->set_recv_stamp(ceph_clock_now(msgr->cct));
   add_arrival(m);
   if (priority >= CEPH_MSG_PRIO_LOW) {
     mqueue.enqueue_strict(
diff --git a/src/msg/DispatchQueue.h b/src/msg/DispatchQueue.h
index df73130..dffd65c 100644
--- a/src/msg/DispatchQueue.h
+++ b/src/msg/DispatchQueue.h
@@ -168,6 +168,7 @@ class DispatchQueue {
   void entry();
   void wait();
   void shutdown();
+  bool is_started() {return dispatch_thread.is_started();}
 
   DispatchQueue(CephContext *cct, SimpleMessenger *msgr)
     : cct(cct), msgr(msgr),
diff --git a/src/msg/Message.h b/src/msg/Message.h
index 740be7b..a69944f 100644
--- a/src/msg/Message.h
+++ b/src/msg/Message.h
@@ -177,6 +177,7 @@ struct Connection : private RefCountedObject {
   RefCountedObject *priv;
   int peer_type;
   entity_addr_t peer_addr;
+  utime_t last_keepalive_ack;
 private:
   uint64_t features;
 public:
@@ -184,7 +185,7 @@ public:
   bool failed;              /// true if we are a lossy connection that has failed.
 
   int rx_buffers_version;
-  map<tid_t,pair<bufferlist,int> > rx_buffers;
+  map<ceph_tid_t,pair<bufferlist,int> > rx_buffers;
 
   friend class boost::intrusive_ptr<Connection>;
 
@@ -284,15 +285,19 @@ public:
   void set_features(uint64_t f) { features = f; }
   void set_feature(uint64_t f) { features |= f; }
 
-  void post_rx_buffer(tid_t tid, bufferlist& bl) {
+  void post_rx_buffer(ceph_tid_t tid, bufferlist& bl) {
     Mutex::Locker l(lock);
     ++rx_buffers_version;
     rx_buffers[tid] = pair<bufferlist,int>(bl, rx_buffers_version);
   }
-  void revoke_rx_buffer(tid_t tid) {
+  void revoke_rx_buffer(ceph_tid_t tid) {
     Mutex::Locker l(lock);
     rx_buffers.erase(tid);
   }
+
+  utime_t get_last_keepalive_ack() const {
+    return last_keepalive_ack;
+  }
 };
 typedef boost::intrusive_ptr<Connection> ConnectionRef;
 
diff --git a/src/msg/Pipe.cc b/src/msg/Pipe.cc
index 9020888..3d86789 100644
--- a/src/msg/Pipe.cc
+++ b/src/msg/Pipe.cc
@@ -86,7 +86,8 @@ Pipe::Pipe(SimpleMessenger *r, int st, Connection *con)
     reader_running(false), reader_needs_join(false),
     writer_running(false),
     in_q(&(r->dispatch_queue)),
-    keepalive(false),
+    send_keepalive(false),
+    send_keepalive_ack(false),
     close_on_empty(false),
     connect_seq(0), peer_global_seq(0),
     out_seq(0), in_seq(0), in_seq_acked(0) {
@@ -1420,6 +1421,37 @@ void Pipe::reader()
       pipe_lock.Lock();
       continue;
     }
+    if (tag == CEPH_MSGR_TAG_KEEPALIVE2) {
+      ldout(msgr->cct,30) << "reader got KEEPALIVE2 tag ..." << dendl;
+      ceph_timespec t;
+      int rc = tcp_read((char*)&t, sizeof(t));
+      pipe_lock.Lock();
+      if (rc < 0) {
+	ldout(msgr->cct,2) << "reader couldn't read KEEPALIVE2 stamp "
+			   << cpp_strerror(errno) << dendl;
+	fault(true);
+      } else {
+	send_keepalive_ack = true;
+	keepalive_ack_stamp = utime_t(t);
+	ldout(msgr->cct,20) << "reader got KEEPALIVE2 " << keepalive_ack_stamp
+			    << dendl;
+	cond.Signal();
+      }
+      continue;
+    }
+    if (tag == CEPH_MSGR_TAG_KEEPALIVE2_ACK) {
+      ldout(msgr->cct,20) << "reader got KEEPALIVE_ACK" << dendl;
+      struct ceph_timespec t;
+      int rc = tcp_read((char*)&t, sizeof(t));
+      pipe_lock.Lock();
+      if (rc < 0) {
+	ldout(msgr->cct,2) << "reader couldn't read KEEPALIVE2 stamp " << cpp_strerror(errno) << dendl;
+	fault(true);
+      } else {
+	connection_state->last_keepalive_ack = utime_t(t);
+      }
+      continue;
+    }
 
     // open ...
     if (tag == CEPH_MSGR_TAG_ACK) {
@@ -1569,16 +1601,36 @@ void Pipe::writer()
 	(is_queued() || in_seq > in_seq_acked)) {
 
       // keepalive?
-      if (keepalive) {
-	pipe_lock.Unlock();
-	int rc = write_keepalive();
+      if (send_keepalive) {
+	int rc;
+	if (connection_state->has_feature(CEPH_FEATURE_MSGR_KEEPALIVE2)) {
+	  pipe_lock.Unlock();
+	  rc = write_keepalive2(CEPH_MSGR_TAG_KEEPALIVE2,
+				ceph_clock_now(msgr->cct));
+	} else {
+	  pipe_lock.Unlock();
+	  rc = write_keepalive();
+	}
 	pipe_lock.Lock();
 	if (rc < 0) {
-	  ldout(msgr->cct,2) << "writer couldn't write keepalive, " << strerror_r(errno, buf, sizeof(buf)) << dendl;
+	  ldout(msgr->cct,2) << "writer couldn't write keepalive[2], "
+			     << strerror_r(errno, buf, sizeof(buf)) << dendl;
 	  fault();
  	  continue;
 	}
-	keepalive = false;
+	send_keepalive = false;
+      }
+      if (send_keepalive_ack) {
+	utime_t t = keepalive_ack_stamp;
+	pipe_lock.Unlock();
+	int rc = write_keepalive2(CEPH_MSGR_TAG_KEEPALIVE2_ACK, t);
+	pipe_lock.Lock();
+	if (rc < 0) {
+	  ldout(msgr->cct,2) << "writer couldn't write keepalive_ack, " << strerror_r(errno, buf, sizeof(buf)) << dendl;
+	  fault();
+	  continue;
+	}
+	send_keepalive_ack = false;
       }
 
       // send ack?
@@ -1827,7 +1879,7 @@ int Pipe::read_message(Message **pm)
 
       // get a buffer
       connection_state->lock.Lock();
-      map<tid_t,pair<bufferlist,int> >::iterator p = connection_state->rx_buffers.find(header.tid);
+      map<ceph_tid_t,pair<bufferlist,int> >::iterator p = connection_state->rx_buffers.find(header.tid);
       if (p != connection_state->rx_buffers.end()) {
 	if (rxbuf.length() == 0 || p->second.second != rxbuf_version) {
 	  ldout(msgr->cct,10) << "reader seleting rx buffer v " << p->second.second
@@ -2039,6 +2091,26 @@ int Pipe::write_keepalive()
   return 0;
 }
 
+int Pipe::write_keepalive2(char tag, const utime_t& t)
+{
+  ldout(msgr->cct,10) << "write_keepalive2 " << (int)tag << " " << t << dendl;
+  struct ceph_timespec ts;
+  t.encode_timeval(&ts);
+  struct msghdr msg;
+  memset(&msg, 0, sizeof(msg));
+  struct iovec msgvec[2];
+  msgvec[0].iov_base = &tag;
+  msgvec[0].iov_len = 1;
+  msgvec[1].iov_base = &ts;
+  msgvec[1].iov_len = sizeof(ts);
+  msg.msg_iov = msgvec;
+  msg.msg_iovlen = 2;
+
+  if (do_sendmsg(&msg, 1 + sizeof(ts)) < 0)
+    return -1;
+  return 0;
+}
+
 
 int Pipe::write_message(ceph_msg_header& header, ceph_msg_footer& footer, bufferlist& blist)
 {
diff --git a/src/msg/Pipe.h b/src/msg/Pipe.h
index 6c91395..29d7958 100644
--- a/src/msg/Pipe.h
+++ b/src/msg/Pipe.h
@@ -161,7 +161,9 @@ class DispatchQueue;
     DispatchQueue *in_q;
     list<Message*> sent;
     Cond cond;
-    bool keepalive;
+    bool send_keepalive;
+    bool send_keepalive_ack;
+    utime_t keepalive_ack_stamp;
     bool halt_delivery; //if a pipe's queue is destroyed, stop adding to it
     bool close_on_empty;
     
@@ -195,6 +197,7 @@ class DispatchQueue;
     int do_sendmsg(struct msghdr *msg, int len, bool more=false);
     int write_ack(uint64_t s);
     int write_keepalive();
+    int write_keepalive2(char tag, const utime_t &t);
 
     void fault(bool reader=false);
 
@@ -218,7 +221,7 @@ class DispatchQueue;
 
     __u32 get_out_seq() { return out_seq; }
 
-    bool is_queued() { return !out_q.empty() || keepalive; }
+    bool is_queued() { return !out_q.empty() || send_keepalive || send_keepalive_ack; }
 
     entity_addr_t& get_peer_addr() { return peer_addr; }
 
@@ -244,7 +247,7 @@ class DispatchQueue;
     }
     void _send_keepalive() {
       assert(pipe_lock.is_locked());
-      keepalive = true;
+      send_keepalive = true;
       cond.Signal();
     }
     Message *_get_next_outgoing() {
diff --git a/src/msg/SimpleMessenger.cc b/src/msg/SimpleMessenger.cc
index 78e0e69..2070fe5 100644
--- a/src/msg/SimpleMessenger.cc
+++ b/src/msg/SimpleMessenger.cc
@@ -399,6 +399,19 @@ ConnectionRef SimpleMessenger::get_loopback_connection()
 void SimpleMessenger::submit_message(Message *m, Connection *con,
 				     const entity_addr_t& dest_addr, int dest_type, bool lazy)
 {
+
+  if (cct->_conf->ms_dump_on_send) {
+    m->encode(-1, true);
+    ldout(cct, 0) << "submit_message " << *m << "\n";
+    m->get_payload().hexdump(*_dout);
+    if (m->get_data().length() > 0) {
+      *_dout << " data:\n";
+      m->get_data().hexdump(*_dout);
+    }
+    *_dout << dendl;
+    m->clear_payload();
+  }
+
   // existing connection?
   if (con) {
     Pipe *pipe = NULL;
@@ -509,10 +522,12 @@ void SimpleMessenger::wait()
   }
   lock.Unlock();
 
-  ldout(cct,10) << "wait: waiting for dispatch queue" << dendl;
-  dispatch_queue.wait();
-  ldout(cct,10) << "wait: dispatch queue is stopped" << dendl;
-  
+  if(dispatch_queue.is_started()) {
+    ldout(cct,10) << "wait: waiting for dispatch queue" << dendl;
+    dispatch_queue.wait();
+    ldout(cct,10) << "wait: dispatch queue is stopped" << dendl;
+  }
+
   // done!  clean up.
   if (did_bind) {
     ldout(cct,20) << "wait: stopping accepter thread" << dendl;
diff --git a/src/ocf/Makefile.in b/src/ocf/Makefile.in
index 5362dae..4f243be 100644
--- a/src/ocf/Makefile.in
+++ b/src/ocf/Makefile.in
@@ -49,10 +49,10 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_classpath.m4 \
 	$(top_srcdir)/m4/ax_c_var_func.m4 \
 	$(top_srcdir)/m4/ax_check_compile_flag.m4 \
 	$(top_srcdir)/m4/ax_cxx_static_cast.m4 \
-	$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
-	$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
-	$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
-	$(top_srcdir)/configure.ac
+	$(top_srcdir)/m4/ax_intel.m4 $(top_srcdir)/m4/libtool.m4 \
+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+	$(top_srcdir)/m4/pkg.m4 $(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
@@ -144,6 +144,14 @@ INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
 INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTEL_FLAGS = @INTEL_FLAGS@
+INTEL_PCLMUL_FLAGS = @INTEL_PCLMUL_FLAGS@
+INTEL_SSE2_FLAGS = @INTEL_SSE2_FLAGS@
+INTEL_SSE3_FLAGS = @INTEL_SSE3_FLAGS@
+INTEL_SSE4_1_FLAGS = @INTEL_SSE4_1_FLAGS@
+INTEL_SSE4_2_FLAGS = @INTEL_SSE4_2_FLAGS@
+INTEL_SSE_FLAGS = @INTEL_SSE_FLAGS@
+INTEL_SSSE3_FLAGS = @INTEL_SSSE3_FLAGS@
 JAR = @JAR@
 JAVAC = @JAVAC@
 JAVAH = @JAVAH@
diff --git a/src/os/FDCache.h b/src/os/FDCache.h
index 13d7445..ba11e12 100644
--- a/src/os/FDCache.h
+++ b/src/os/FDCache.h
@@ -44,7 +44,7 @@ public:
       return fd;
     }
     ~FD() {
-      TEMP_FAILURE_RETRY(::close(fd));
+      VOID_TEMP_FAILURE_RETRY(::close(fd));
     }
   };
 
diff --git a/src/os/FileJournal.cc b/src/os/FileJournal.cc
index 54c0371..c6bd616 100644
--- a/src/os/FileJournal.cc
+++ b/src/os/FileJournal.cc
@@ -124,7 +124,7 @@ int FileJournal::_open(bool forwrite, bool create)
   return 0;
 
  out_fd:
-  TEMP_FAILURE_RETRY(::close(fd));
+  VOID_TEMP_FAILURE_RETRY(::close(fd));
   return ret;
 }
 
@@ -344,7 +344,7 @@ int FileJournal::check()
   ret = 0;
 
  done:
-  TEMP_FAILURE_RETRY(::close(fd));
+  VOID_TEMP_FAILURE_RETRY(::close(fd));
   fd = -1;
   return ret;
 }
@@ -545,7 +545,7 @@ void FileJournal::close()
   // close
   assert(writeq_empty());
   assert(fd >= 0);
-  TEMP_FAILURE_RETRY(::close(fd));
+  VOID_TEMP_FAILURE_RETRY(::close(fd));
   fd = -1;
 }
 
diff --git a/src/os/FileStore.cc b/src/os/FileStore.cc
index 6a170ce..9d6252c 100644
--- a/src/os/FileStore.cc
+++ b/src/os/FileStore.cc
@@ -270,7 +270,7 @@ int FileStore::lfn_open(coll_t cid,
     if (create && (!exist)) {
       r = (*index)->created(oid, (*path)->path());
       if (r < 0) {
-	TEMP_FAILURE_RETRY(::close(fd));
+	VOID_TEMP_FAILURE_RETRY(::close(fd));
 	derr << "error creating " << oid << " (" << (*path)->path()
 	     << ") in index: " << cpp_strerror(-r) << dendl;
 	goto fail;
@@ -282,7 +282,7 @@ int FileStore::lfn_open(coll_t cid,
     Mutex::Locker l(fdcache_lock);
     *outfd = fdcache.lookup(oid);
     if (*outfd) {
-      TEMP_FAILURE_RETRY(::close(fd));
+      VOID_TEMP_FAILURE_RETRY(::close(fd));
       return 0;
     } else {
       *outfd = fdcache.add(oid, fd);
@@ -709,7 +709,7 @@ int FileStore::mkfs()
     if (initial_seq == 0) {
       int err = write_op_seq(fd, 1);
       if (err < 0) {
-	TEMP_FAILURE_RETRY(::close(fd));
+	VOID_TEMP_FAILURE_RETRY(::close(fd));
 	derr << "mkfs: failed to write to " << current_op_seq_fn << ": "
 	     << cpp_strerror(err) << dendl;
 	goto close_fsid_fd;
@@ -722,15 +722,15 @@ int FileStore::mkfs()
 	char s[NAME_MAX];
 	snprintf(s, sizeof(s), COMMIT_SNAP_ITEM, 1ull);
 	ret = backend->create_checkpoint(s, NULL);
-	TEMP_FAILURE_RETRY(::close(current_fd));
+	VOID_TEMP_FAILURE_RETRY(::close(current_fd));
 	if (ret < 0 && ret != -EEXIST) {
-	  TEMP_FAILURE_RETRY(::close(fd));  
+	  VOID_TEMP_FAILURE_RETRY(::close(fd));  
 	  derr << "mkfs: failed to create snap_1: " << cpp_strerror(ret) << dendl;
 	  goto close_fsid_fd;
 	}
       }
     }
-    TEMP_FAILURE_RETRY(::close(fd));  
+    VOID_TEMP_FAILURE_RETRY(::close(fd));  
   }
 
   {
@@ -757,10 +757,10 @@ int FileStore::mkfs()
   ret = 0;
 
  close_fsid_fd:
-  TEMP_FAILURE_RETRY(::close(fsid_fd));
+  VOID_TEMP_FAILURE_RETRY(::close(fsid_fd));
   fsid_fd = -1;
  close_basedir_fd:
-  TEMP_FAILURE_RETRY(::close(basedir_fd));
+  VOID_TEMP_FAILURE_RETRY(::close(basedir_fd));
   if (backend != generic_backend) {
     delete backend;
     backend = generic_backend;
@@ -783,10 +783,10 @@ int FileStore::mkjournal()
   ret = read_fsid(fd, &fsid);
   if (ret < 0) {
     derr << "FileStore::mkjournal: read error: " << cpp_strerror(ret) << dendl;
-    TEMP_FAILURE_RETRY(::close(fd));
+    VOID_TEMP_FAILURE_RETRY(::close(fd));
     return ret;
   }
-  TEMP_FAILURE_RETRY(::close(fd));
+  VOID_TEMP_FAILURE_RETRY(::close(fd));
 
   ret = 0;
 
@@ -857,7 +857,7 @@ bool FileStore::test_mount_in_use()
   if (fsid_fd < 0)
     return 0;   // no fsid, ok.
   bool inuse = lock_fsid() < 0;
-  TEMP_FAILURE_RETRY(::close(fsid_fd));
+  VOID_TEMP_FAILURE_RETRY(::close(fsid_fd));
   fsid_fd = -1;
   return inuse;
 }
@@ -934,7 +934,7 @@ int FileStore::_detect_fs()
     *_dout << "If you are using ext3 or ext4, be sure to mount the underlying "
 	   << "file system with the 'user_xattr' option." << dendl;
     ::unlink(fn);
-    TEMP_FAILURE_RETRY(::close(tmpfd));
+    VOID_TEMP_FAILURE_RETRY(::close(tmpfd));
     return -ENOTSUP;
   }
 
@@ -955,7 +955,7 @@ int FileStore::_detect_fs()
   chain_fremovexattr(tmpfd, "user.test5");
 
   ::unlink(fn);
-  TEMP_FAILURE_RETRY(::close(tmpfd));
+  VOID_TEMP_FAILURE_RETRY(::close(tmpfd));
 
   return 0;
 }
@@ -1094,7 +1094,7 @@ int FileStore::read_op_seq(uint64_t *seq)
   int ret = safe_read(op_fd, s, sizeof(s) - 1);
   if (ret < 0) {
     derr << "error reading " << current_op_seq_fn << ": " << cpp_strerror(ret) << dendl;
-    TEMP_FAILURE_RETRY(::close(op_fd));
+    VOID_TEMP_FAILURE_RETRY(::close(op_fd));
     assert(!m_filestore_fail_eio || ret != -EIO);
     return ret;
   }
@@ -1261,7 +1261,7 @@ int FileStore::mount()
 	{
 	  int fd = read_op_seq(&curr_seq);
 	  if (fd >= 0) {
-	    TEMP_FAILURE_RETRY(::close(fd));
+	    VOID_TEMP_FAILURE_RETRY(::close(fd));
 	  }
 	}
 	if (curr_seq)
@@ -1336,7 +1336,7 @@ int FileStore::mount()
       derr << "FileStore::mount: failed to create current/nosnap" << dendl;
       goto close_current_fd;
     }
-    TEMP_FAILURE_RETRY(::close(r));
+    VOID_TEMP_FAILURE_RETRY(::close(r));
   } else {
     // clear nosnap marker, if present.
     ::unlink(nosnapfn);
@@ -1495,13 +1495,13 @@ int FileStore::mount()
   return 0;
 
 close_current_fd:
-  TEMP_FAILURE_RETRY(::close(current_fd));
+  VOID_TEMP_FAILURE_RETRY(::close(current_fd));
   current_fd = -1;
 close_basedir_fd:
-  TEMP_FAILURE_RETRY(::close(basedir_fd));
+  VOID_TEMP_FAILURE_RETRY(::close(basedir_fd));
   basedir_fd = -1;
 close_fsid_fd:
-  TEMP_FAILURE_RETRY(::close(fsid_fd));
+  VOID_TEMP_FAILURE_RETRY(::close(fsid_fd));
   fsid_fd = -1;
 done:
   assert(!m_filestore_fail_eio || ret != -EIO);
@@ -1529,19 +1529,19 @@ int FileStore::umount()
   ondisk_finisher.stop();
 
   if (fsid_fd >= 0) {
-    TEMP_FAILURE_RETRY(::close(fsid_fd));
+    VOID_TEMP_FAILURE_RETRY(::close(fsid_fd));
     fsid_fd = -1;
   }
   if (op_fd >= 0) {
-    TEMP_FAILURE_RETRY(::close(op_fd));
+    VOID_TEMP_FAILURE_RETRY(::close(op_fd));
     op_fd = -1;
   }
   if (current_fd >= 0) {
-    TEMP_FAILURE_RETRY(::close(current_fd));
+    VOID_TEMP_FAILURE_RETRY(::close(current_fd));
     current_fd = -1;
   }
   if (basedir_fd >= 0) {
-    TEMP_FAILURE_RETRY(::close(basedir_fd));
+    VOID_TEMP_FAILURE_RETRY(::close(basedir_fd));
     basedir_fd = -1;
   }
 
@@ -1910,7 +1910,7 @@ void FileStore::_set_global_replay_guard(coll_t cid,
 
   _inject_failure();
 
-  TEMP_FAILURE_RETRY(::close(fd));
+  VOID_TEMP_FAILURE_RETRY(::close(fd));
   dout(10) << __func__ << ": " << spos << " done" << dendl;
 }
 
@@ -1933,7 +1933,7 @@ int FileStore::_check_global_replay_guard(coll_t cid,
   if (r < 0) {
     dout(20) << __func__ << " no xattr" << dendl;
     assert(!m_filestore_fail_eio || r != -EIO);
-    TEMP_FAILURE_RETRY(::close(fd));
+    VOID_TEMP_FAILURE_RETRY(::close(fd));
     return 1;  // no xattr
   }
   bufferlist bl;
@@ -1943,7 +1943,7 @@ int FileStore::_check_global_replay_guard(coll_t cid,
   bufferlist::iterator p = bl.begin();
   ::decode(opos, p);
 
-  TEMP_FAILURE_RETRY(::close(fd));
+  VOID_TEMP_FAILURE_RETRY(::close(fd));
   return spos >= opos ? 1 : -1;
 }
 
@@ -2081,7 +2081,7 @@ int FileStore::_check_replay_guard(coll_t cid, const SequencerPosition& spos)
     return 1;  // if collection does not exist, there is no guard, and we can replay.
   }
   int ret = _check_replay_guard(fd, spos);
-  TEMP_FAILURE_RETRY(::close(fd));
+  VOID_TEMP_FAILURE_RETRY(::close(fd));
   return ret;
 }
 
@@ -3835,7 +3835,7 @@ int FileStore::collection_getattr(coll_t c, const char *name,
   char n[PATH_MAX];
   get_attrname(name, n, PATH_MAX);
   r = chain_fgetxattr(fd, n, value, size);
-  TEMP_FAILURE_RETRY(::close(fd));
+  VOID_TEMP_FAILURE_RETRY(::close(fd));
  out:
   dout(10) << "collection_getattr " << fn << " '" << name << "' len " << size << " = " << r << dendl;
   assert(!m_filestore_fail_eio || r != -EIO);
@@ -3858,7 +3858,7 @@ int FileStore::collection_getattr(coll_t c, const char *name, bufferlist& bl)
   }
   r = _fgetattr(fd, n, bp);
   bl.push_back(bp);
-  TEMP_FAILURE_RETRY(::close(fd));
+  VOID_TEMP_FAILURE_RETRY(::close(fd));
  out:
   dout(10) << "collection_getattr " << fn << " '" << name << "' = " << r << dendl;
   assert(!m_filestore_fail_eio || r != -EIO);
@@ -3877,7 +3877,7 @@ int FileStore::collection_getattrs(coll_t cid, map<string,bufferptr>& aset)
     goto out;
   }
   r = _fgetattrs(fd, aset, true);
-  TEMP_FAILURE_RETRY(::close(fd));
+  VOID_TEMP_FAILURE_RETRY(::close(fd));
  out:
   dout(10) << "collection_getattrs " << fn << " = " << r << dendl;
   assert(!m_filestore_fail_eio || r != -EIO);
@@ -3900,7 +3900,7 @@ int FileStore::_collection_setattr(coll_t c, const char *name,
   }
   get_attrname(name, n, PATH_MAX);
   r = chain_fsetxattr(fd, n, value, size);
-  TEMP_FAILURE_RETRY(::close(fd));
+  VOID_TEMP_FAILURE_RETRY(::close(fd));
  out:
   dout(10) << "collection_setattr " << fn << " '" << name << "' len " << size << " = " << r << dendl;
   return r;
@@ -3920,7 +3920,7 @@ int FileStore::_collection_rmattr(coll_t c, const char *name)
     goto out;
   }
   r = chain_fremovexattr(fd, n);
-  TEMP_FAILURE_RETRY(::close(fd));
+  VOID_TEMP_FAILURE_RETRY(::close(fd));
  out:
   dout(10) << "collection_rmattr " << fn << " = " << r << dendl;
   return r;
@@ -3947,7 +3947,7 @@ int FileStore::_collection_setattrs(coll_t cid, map<string,bufferptr>& aset)
     if (r < 0)
       break;
   }
-  TEMP_FAILURE_RETRY(::close(fd));
+  VOID_TEMP_FAILURE_RETRY(::close(fd));
  out:
   dout(10) << "collection_setattrs " << fn << " = " << r << dendl;
   return r;
@@ -4025,7 +4025,7 @@ int FileStore::_collection_rename(const coll_t &cid, const coll_t &ncid,
     int fd = ::open(new_coll, O_RDONLY);
     assert(fd >= 0);
     _set_replay_guard(fd, spos);
-    TEMP_FAILURE_RETRY(::close(fd));
+    VOID_TEMP_FAILURE_RETRY(::close(fd));
   }
 
   dout(10) << "collection_rename '" << cid << "' to '" << ncid << "'"
diff --git a/src/os/GenericFileStoreBackend.cc b/src/os/GenericFileStoreBackend.cc
index f19ba7d..56deeb2 100644
--- a/src/os/GenericFileStoreBackend.cc
+++ b/src/os/GenericFileStoreBackend.cc
@@ -98,13 +98,13 @@ int GenericFileStoreBackend::detect_features()
     if (r < 0) {
       r = -errno;
       derr << "detect_features: failed to lseek " << fn << ": " << cpp_strerror(r) << dendl;
-      TEMP_FAILURE_RETRY(::close(fd));
+      VOID_TEMP_FAILURE_RETRY(::close(fd));
       return r;
     }
     r = write(fd, buf, sizeof(buf));
     if (r < 0) {
       derr << "detect_features: failed to write to " << fn << ": " << cpp_strerror(r) << dendl;
-      TEMP_FAILURE_RETRY(::close(fd));
+      VOID_TEMP_FAILURE_RETRY(::close(fd));
       return r;
     }
   }
@@ -132,7 +132,7 @@ int GenericFileStoreBackend::detect_features()
   }
 
   ::unlink(fn);
-  TEMP_FAILURE_RETRY(::close(fd));
+  VOID_TEMP_FAILURE_RETRY(::close(fd));
 
 
   bool have_syncfs = false;
diff --git a/src/os/HashIndex.cc b/src/os/HashIndex.cc
index 134deb9..d556cbc 100644
--- a/src/os/HashIndex.cc
+++ b/src/os/HashIndex.cc
@@ -418,13 +418,14 @@ int HashIndex::set_info(const vector<string> &path, const subdir_info_s &info) {
 
 bool HashIndex::must_merge(const subdir_info_s &info) {
   return (info.hash_level > 0 &&
+          merge_threshold > 0 &&
 	  info.objs < (unsigned)merge_threshold &&
 	  info.subdirs == 0);
 }
 
 bool HashIndex::must_split(const subdir_info_s &info) {
   return (info.hash_level < (unsigned)MAX_HASH_LEVEL &&
-	  info.objs > ((unsigned)merge_threshold * 16 * split_multiplier));
+	  info.objs > ((unsigned)(abs(merge_threshold)) * 16 * split_multiplier));
 			    
 }
 
diff --git a/src/os/HashIndex.h b/src/os/HashIndex.h
index bdfee2e..4bf5c31 100644
--- a/src/os/HashIndex.h
+++ b/src/os/HashIndex.h
@@ -43,7 +43,7 @@
  * would be located in (root)/2/D/0/
  * 
  * Subdirectories are created when the number of objects in a directory
- * exceed 32*merge_threshhold.  The number of objects in a directory 
+ * exceed (abs(merge_threshhold)) * 16 * split_multiplier.  The number of objects in a directory 
  * is encoded as subdir_info_s in an xattr on the directory.
  */
 class HashIndex : public LFNIndex {
@@ -60,7 +60,8 @@ private:
   /**
    * Merges occur when the number of object drops below
    * merge_threshold and splits occur when the number of objects
-   * exceeds 16 * merge_threshold * split_multiplier.
+   * exceeds 16 * abs(merge_threshold) * split_multiplier.
+   * Please note if merge_threshold is less than zero, it will never do merging
    */
   int merge_threshold;
   int split_multiplier;
diff --git a/src/os/KeyValueStore.cc b/src/os/KeyValueStore.cc
index 8151789..cc117fa 100644
--- a/src/os/KeyValueStore.cc
+++ b/src/os/KeyValueStore.cc
@@ -339,7 +339,7 @@ int KeyValueStore::BufferTransaction::get_buffer_keys(
     }
   }
 
-  if (need_lookup.size()) {
+  if (!need_lookup.empty()) {
     int r = store->backend->get_values_with_header(strip_header, prefix,
                                                    need_lookup, out);
     if (r < 0) {
@@ -662,7 +662,7 @@ int KeyValueStore::mkfs()
   ret = 0;
 
  close_fsid_fd:
-  TEMP_FAILURE_RETRY(::close(fsid_fd));
+  VOID_TEMP_FAILURE_RETRY(::close(fsid_fd));
   fsid_fd = -1;
   return ret;
 }
@@ -718,7 +718,7 @@ bool KeyValueStore::test_mount_in_use()
   if (fsid_fd < 0)
     return 0;   // no fsid, ok.
   bool inuse = lock_fsid() < 0;
-  TEMP_FAILURE_RETRY(::close(fsid_fd));
+  VOID_TEMP_FAILURE_RETRY(::close(fsid_fd));
   fsid_fd = -1;
   return inuse;
 }
@@ -882,10 +882,10 @@ int KeyValueStore::mount()
   return 0;
 
 close_current_fd:
-  TEMP_FAILURE_RETRY(::close(current_fd));
+  VOID_TEMP_FAILURE_RETRY(::close(current_fd));
   current_fd = -1;
 close_fsid_fd:
-  TEMP_FAILURE_RETRY(::close(fsid_fd));
+  VOID_TEMP_FAILURE_RETRY(::close(fsid_fd));
   fsid_fd = -1;
 done:
   return ret;
@@ -900,15 +900,15 @@ int KeyValueStore::umount()
   ondisk_finisher.stop();
 
   if (fsid_fd >= 0) {
-    TEMP_FAILURE_RETRY(::close(fsid_fd));
+    VOID_TEMP_FAILURE_RETRY(::close(fsid_fd));
     fsid_fd = -1;
   }
   if (op_fd >= 0) {
-    TEMP_FAILURE_RETRY(::close(op_fd));
+    VOID_TEMP_FAILURE_RETRY(::close(op_fd));
     op_fd = -1;
   }
   if (current_fd >= 0) {
-    TEMP_FAILURE_RETRY(::close(current_fd));
+    VOID_TEMP_FAILURE_RETRY(::close(current_fd));
     current_fd = -1;
   }
 
@@ -2674,7 +2674,7 @@ int KeyValueStore::omap_get(coll_t c, const ghobject_t &hoid,
     return r;
   }
 
-  if (got.size()) {
+  if (!got.empty()) {
     assert(got.size() == 1);
     bl->swap(got.begin()->second);
   }
diff --git a/src/os/LFNIndex.cc b/src/os/LFNIndex.cc
index 0310cb5..a460e5c 100644
--- a/src/os/LFNIndex.cc
+++ b/src/os/LFNIndex.cc
@@ -162,7 +162,7 @@ int LFNIndex::fsync_dir(const vector<string> &path)
     return -errno;
   maybe_inject_failure();
   int r = ::fsync(fd);
-  TEMP_FAILURE_RETRY(::close(fd));
+  VOID_TEMP_FAILURE_RETRY(::close(fd));
   maybe_inject_failure();
   if (r < 0)
     return -errno;
diff --git a/src/os/ObjectStore.h b/src/os/ObjectStore.h
index c19ebd0..15ed31f 100644
--- a/src/os/ObjectStore.h
+++ b/src/os/ObjectStore.h
@@ -1,4 +1,4 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
 // vim: ts=8 sw=2 smarttab
 /*
  * Ceph - scalable distributed file system
@@ -7,9 +7,9 @@
  *
  * This is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
- * License version 2.1, as published by the Free Software 
+ * License version 2.1, as published by the Free Software
  * Foundation.  See file COPYING.
- * 
+ *
  */
 #ifndef CEPH_OBJECTSTORE_H
 #define CEPH_OBJECTSTORE_H
@@ -86,9 +86,11 @@ protected:
 
 public:
   /**
-   * create - create an ObjectStore instance
+   * create - create an ObjectStore instance.
+   *
+   * This is invoked once at initialization time.
    *
-   * @param type type of store
+   * @param type type of store. This is a string from the configuration file.
    * @param data path (or other descriptor) for data
    * @param journal path (or other descriptor) for journal (optional)
    */
@@ -99,6 +101,13 @@ public:
 
   Logger *logger;
 
+  /**
+   * Fetch Object Store statistics.
+   *
+   * Currently only latency of write and apply times are measured.
+   *
+   * This appears to be called with nothing locked.
+   */
   virtual objectstore_perf_stat_t get_cur_stats() = 0;
 
   /**
@@ -107,11 +116,24 @@ public:
    * Any transactions queued under a given sequencer will be applied in
    * sequence.  Transactions queued under different sequencers may run
    * in parallel.
+   *
+   * Clients of ObjectStore create and maintain their own Sequencer objects.
+   * When a list of transactions is queued the caller specifies a Sequencer to be used.
+   *
+   */
+
+  /**
+   * ABC for Sequencer implementation, private to the ObjectStore derived class.
+   * created in ...::queue_transaction(s)
    */
   struct Sequencer_impl {
     virtual void flush() = 0;
     virtual ~Sequencer_impl() {}
   };
+
+  /**
+   * External (opaque) sequencer implementation
+   */
   struct Sequencer {
     string name;
     Sequencer_impl *p;
@@ -132,10 +154,150 @@ public:
 	p->flush();
     }
   };
-  
+
+  /*********************************
+   *
+   * Object Contents and semantics
+   *
+   * All ObjectStore objects are identified as a named object
+   * (ghobject_t and hobject_t) in a named collection (coll_t).
+   * ObjectStore operations support the creation, mutation, deletion
+   * and enumeration of objects within a collection.  Enumeration is
+   * in sorted key order (where keys are sorted by hash). Object names
+   * are globally unique.
+   *
+   * Each object has four distinct parts: byte data, xattrs, omap_header
+   * and omap entries.
+   *
+   * The data portion of an object is conceptually equivalent to a
+   * file in a file system. Random and Partial access for both read
+   * and operations is required. The ability to have a sparse
+   * implementation of the data portion of an object is beneficial for
+   * some workloads, but not required. There is a system-wide limit on
+   * the maximum size of an object, which is typically around 100 MB.
+   *
+   * Xattrs are equivalent to the extended attributes of file
+   * systems. Xattrs are a set of key/value pairs.  Sub-value access
+   * is not required. It is possible to enumerate the set of xattrs in
+   * key order.  At the implementation level, xattrs are used
+   * exclusively internal to Ceph and the implementer can expect the
+   * total size of all of the xattrs on an object to be relatively
+   * small, i.e., less than 64KB. Much of Ceph assumes that accessing
+   * xattrs on temporally adjacent object accesses (recent past or
+   * near future) is inexpensive.
+   *
+   * omap_header is a single blob of data. It can be read or written
+   * in total.
+   *
+   * Omap entries are conceptually the same as xattrs
+   * but in a different address space. In other words, you can have
+   * the same key as an xattr and an omap entry and they have distinct
+   * values. Enumeration of xattrs doesn't include omap entries and
+   * vice versa. The size and access characteristics of omap entries
+   * are very different from xattrs. In particular, the value portion
+   * of an omap entry can be quite large (MBs).  More importantly, the
+   * interface must support efficient range queries on omap entries even
+   * when there are a large numbers of entries.
+   *
+   *********************************/
+
+  /*******************************
+   *
+   * Collections
+   *
+   * A collection is simply a grouping of objects. Collections have
+   * names (coll_t) and can be enumerated in order.  Like an
+   * individual object, a collection also has a set of xattrs.
+   *
+   *
+   */
+
 
   /*********************************
    * transaction
+   *
+   * A Transaction represents a sequence of primitive mutation
+   * operations.
+   *
+   * Three events in the life of a Transaction result in
+   * callbacks. Any Transaction can contain any number of callback
+   * objects (Context) for any combination of the three classes of
+   * callbacks:
+   *
+   *    on_applied_sync, on_applied, and on_commit.
+   *
+   * The "on_applied" and "on_applied_sync" callbacks are invoked when
+   * the modifications requested by the Transaction are visible to
+   * subsequent ObjectStore operations, i.e., the results are
+   * readable. The only conceptual difference between on_applied and
+   * on_applied_sync is the specific thread and locking environment in
+   * which the callbacks operate.  "on_applied_sync" is called
+   * directly by an ObjectStore execution thread. It is expected to
+   * execute quickly and must not acquire any locks of the calling
+   * environment. Conversely, "on_applied" is called from the separate
+   * Finisher thread, meaning that it can contend for calling
+   * environment locks. NB, on_applied and on_applied sync are
+   * sometimes called on_readable and on_readable_sync.
+   *
+   * The "on_commit" callback is also called from the Finisher thread
+   * and indicates that all of the mutations have been durably
+   * committed to stable storage (i.e., are now software/hardware
+   * crashproof).
+   *
+   * At the implementation level, each mutation primitive (and its
+   * associated data) can be serialized to a single buffer.  That
+   * serialization, however, does not copy any data, but (using the
+   * bufferlist library) will reference the original buffers.  This
+   * implies that the buffer that contains the data being submitted
+   * must remain stable until the on_commit callback completes.  In
+   * practice, bufferlist handles all of this for you and this
+   * subtlety is only relevant if you are referencing an existing
+   * buffer via buffer::raw_static.
+   *
+   * Some implementations of ObjectStore choose to implement their own
+   * form of journaling that uses the serialized form of a
+   * Transaction. This requires that the encode/decode logic properly
+   * version itself and handle version upgrades that might change the
+   * format of the encoded Transaction. This has already happened a
+   * couple of times and the Transaction object contains some helper
+   * variables that aid in this legacy decoding:
+   *
+   *   sobject_encoding detects an older/simpler version of oid
+   *   present in pre-bobtail versions of ceph.  use_pool_override
+   *   also detects a situation where the pool of an oid can be
+   *   override for legacy operations/buffers.  For non-legacy
+   *   implementation of ObjectStore, neither of these fields is
+   *   relevant.
+   *
+   *
+   * TRANSACTION ISOLATION
+   *
+   * Except as noted below, isolation is the responsibility of the
+   * caller. In other words, if any storage element (storage element
+   * == any of the four portions of an object as described above) is
+   * altered by a transaction (including deletion), the caller
+   * promises not to attempt to read that element while the
+   * transaction is pending (here pending means from the time of
+   * issuance until the "on_applied_sync" callback has been
+   * received). Violations of isolation need not be detected by
+   * ObjectStore and there is no corresponding error mechanism for
+   * reporting an isolation violation (crashing would be the
+   * appropriate way to report an isolation violation if detected).
+   *
+   * Enumeration operations may violate transaction isolation as
+   * described above when a storage element is being created or
+   * deleted as part of a transaction. In this case, ObjectStore is
+   * allowed to consider the enumeration operation to either preceed
+   * or follow the violating transaction element. In other words, the
+   * presence/absence of the mutated element in the enumeration is
+   * entirely at the discretion of ObjectStore. The arbitrary ordering
+   * applies independently to each transaction element. For example,
+   * if a transaction contains two mutating elements "create A" and
+   * "delete B". And an enumeration operation is performed while this
+   * transaction is pending. It is permissable for ObjectStore to
+   * report any of the four possible combinations of the existance of
+   * A and B.
+   *
    */
   class Transaction {
   public:
@@ -164,7 +326,7 @@ public:
       OP_COLL_SETATTRS = 26,  // cid, attrset
       OP_COLL_MOVE =    8,   // newcid, oldcid, oid
 
-      OP_STARTSYNC =    27,  // start a sync 
+      OP_STARTSYNC =    27,  // start a sync
 
       OP_RMATTRS =      28,  // cid, oid
       OP_COLL_RENAME =       29,  // cid, newcid
@@ -201,6 +363,8 @@ public:
     void set_tolerate_collection_add_enoent() {
       tolerate_collection_add_enoent = true;
     }
+
+    /* Operations on callback contexts */
     void register_on_applied(Context *c) {
       if (!c) return;
       on_applied.push_back(c);
@@ -251,6 +415,7 @@ public:
       return C_Contexts::list_to_context(on_applied_sync);
     }
 
+    /// For legacy transactions, provide the pool to override the encoded pool with
     void set_pool_override(int64_t pool) {
       pool_override = pool;
     }
@@ -270,6 +435,7 @@ public:
       tbl.swap(other.tbl);
     }
 
+    /// Append the operations of the parameter to this Transaction. Those operations are removed from the parameter Transaction
     void append(Transaction& other) {
       ops += other.ops;
       assert(pad_unused_bytes == 0);
@@ -285,6 +451,9 @@ public:
       on_applied_sync.splice(on_applied_sync.end(), other.on_applied_sync);
     }
 
+    /** Inquires about the Transaction as a whole. */
+
+    /// How big is the encoded Transaction buffer?
     uint64_t get_encoded_bytes() {
       return 1 + 8 + 8 + 4 + 4 + 4 + 4 + tbl.length();
     }
@@ -292,10 +461,11 @@ public:
     uint64_t get_num_bytes() {
       return get_encoded_bytes();
     }
-
+    /// Size of largest data buffer to the "write" operation encountered so far
     uint32_t get_data_length() {
       return largest_data_len;
     }
+    /// offset within the encoded buffer to the start of the first data buffer that's encoded
     uint32_t get_data_offset() {
       if (largest_data_off_in_tbl) {
 	return largest_data_off_in_tbl +
@@ -311,21 +481,30 @@ public:
       }
       return 0;  // none
     }
+    /// offset of buffer as aligned to destination within object.
     int get_data_alignment() {
       if (!largest_data_len)
 	return -1;
       return (largest_data_off - get_data_offset()) & ~CEPH_PAGE_MASK;
     }
-
+    /// Is the Transaction empty (no operations)
     bool empty() {
       return !ops;
     }
-
+    /// Number of operations in the transation
     int get_num_ops() {
       return ops;
     }
 
-    // ---- iterator ----
+    /**
+     * iterator
+     *
+     * Helper object to parse Transactions.
+     *
+     * ObjectStore instances use this object to step down the encoded
+     * buffer decoding operation codes and parameters as we go.
+     *
+     */
     class iterator {
       bufferlist::iterator p;
       bool sobject_encoding;
@@ -349,9 +528,15 @@ public:
       bool tolerate_collection_add_enoent() const {
 	return _tolerate_collection_add_enoent;
       }
+      /// true if there are more operations left to be enumerated
       bool have_op() {
 	return !p.end();
       }
+
+      /* Decode the specified type of object from the input
+       * stream. There is no checking that the encoded data is of the
+       * correct type.
+       */
       int get_op() {
 	__u32 op;
 	::decode(op, p);
@@ -360,6 +545,7 @@ public:
       void get_bl(bufferlist& bl) {
 	::decode(bl, p);
       }
+      /// Get an oid, recognize various legacy forms and update them.
       ghobject_t get_oid() {
 	ghobject_t oid;
 	if (sobject_encoding) {
@@ -418,18 +604,34 @@ public:
     iterator begin() {
       return iterator(this);
     }
-    // -----------------------------
 
+    /**
+     * Helper functions to encode the various mutation elements of a
+     * transaction.  These are 1:1 with the operation codes (see
+     * enumeration above).  These routines ensure that the
+     * encoder/creator of a transaction gets the right data in the
+     * right place. Sadly, there's no corresponding version nor any
+     * form of seat belts for the decoder.
+     */
+
+    /// Commence a global file system sync operation.
     void start_sync() {
       __u32 op = OP_STARTSYNC;
       ::encode(op, tbl);
       ops++;
     }
+    /// noop. 'nuf said
     void nop() {
       __u32 op = OP_NOP;
       ::encode(op, tbl);
       ops++;
     }
+    /**
+     * touch
+     *
+     * Ensure the existance of an object in a collection. Create an
+     * empty object if necessary
+     */
     void touch(coll_t cid, const ghobject_t& oid) {
       __u32 op = OP_TOUCH;
       ::encode(op, tbl);
@@ -437,7 +639,18 @@ public:
       ::encode(oid, tbl);
       ops++;
     }
-    void write(coll_t cid, const ghobject_t& oid, uint64_t off, uint64_t len, const bufferlist& data) {
+    /**
+     * Write data to an offset within an object. If the object is too
+     * small, it is expanded as needed.  It is possible to specify an
+     * offset beyond the current end of an object and it will be
+     * expanded as needed. Simple implementations of ObjectStore will
+     * just zero the data between the old end of the object and the
+     * newly provided data. More sophisticated implementations of
+     * ObjectStore will omit the untouched data and store it as a
+     * "hole" in the file.
+     */
+    void write(coll_t cid, const ghobject_t& oid, uint64_t off, uint64_t len,
+	       const bufferlist& data) {
       __u32 op = OP_WRITE;
       ::encode(op, tbl);
       ::encode(cid, tbl);
@@ -448,11 +661,16 @@ public:
       if (data.length() > largest_data_len) {
 	largest_data_len = data.length();
 	largest_data_off = off;
-	largest_data_off_in_tbl = tbl.length() + sizeof(__u32);  // we are about to 
+	largest_data_off_in_tbl = tbl.length() + sizeof(__u32);  // we are about to
       }
       ::encode(data, tbl);
       ops++;
     }
+    /**
+     * zero out the indicated byte range within an object. Some
+     * ObjectStore instances may optimize this to release the
+     * underlying storage space.
+     */
     void zero(coll_t cid, const ghobject_t& oid, uint64_t off, uint64_t len) {
       __u32 op = OP_ZERO;
       ::encode(op, tbl);
@@ -462,6 +680,7 @@ public:
       ::encode(len, tbl);
       ops++;
     }
+    /// Discard all data in the object beyond the specified size.
     void truncate(coll_t cid, const ghobject_t& oid, uint64_t off) {
       __u32 op = OP_TRUNCATE;
       ::encode(op, tbl);
@@ -470,6 +689,7 @@ public:
       ::encode(off, tbl);
       ops++;
     }
+    /// Remove an object. All four parts of the object are removed.
     void remove(coll_t cid, const ghobject_t& oid) {
       __u32 op = OP_REMOVE;
       ::encode(op, tbl);
@@ -477,10 +697,12 @@ public:
       ::encode(oid, tbl);
       ops++;
     }
+    /// Set an xattr of an object
     void setattr(coll_t cid, const ghobject_t& oid, const char* name, bufferlist& val) {
       string n(name);
       setattr(cid, oid, n, val);
     }
+    /// Set an xattr of an object
     void setattr(coll_t cid, const ghobject_t& oid, const string& s, bufferlist& val) {
       __u32 op = OP_SETATTR;
       ::encode(op, tbl);
@@ -490,6 +712,7 @@ public:
       ::encode(val, tbl);
       ops++;
     }
+    /// Set multiple xattrs of an object
     void setattrs(coll_t cid, const ghobject_t& oid, map<string,bufferptr>& attrset) {
       __u32 op = OP_SETATTRS;
       ::encode(op, tbl);
@@ -498,6 +721,7 @@ public:
       ::encode(attrset, tbl);
       ops++;
     }
+    /// Set multiple xattrs of an object
     void setattrs(coll_t cid, const ghobject_t& oid, map<string,bufferlist>& attrset) {
       __u32 op = OP_SETATTRS;
       ::encode(op, tbl);
@@ -506,10 +730,12 @@ public:
       ::encode(attrset, tbl);
       ops++;
     }
+    /// remove an xattr from an object
     void rmattr(coll_t cid, const ghobject_t& oid, const char *name) {
       string n(name);
       rmattr(cid, oid, n);
     }
+    /// remove an xattr from an object
     void rmattr(coll_t cid, const ghobject_t& oid, const string& s) {
       __u32 op = OP_RMATTR;
       ::encode(op, tbl);
@@ -518,6 +744,7 @@ public:
       ::encode(s, tbl);
       ops++;
     }
+    /// remove all xattrs from an object
     void rmattrs(coll_t cid, const ghobject_t& oid) {
       __u32 op = OP_RMATTRS;
       ::encode(op, tbl);
@@ -525,6 +752,17 @@ public:
       ::encode(oid, tbl);
       ops++;
     }
+    /**
+     * Clone an object into another object.
+     *
+     * Low-cost (e.g., O(1)) cloning (if supported) is best, but
+     * fallback to an O(n) copy is allowed.  All four parts of the
+     * object are cloned (data, xattrs, omap header, omap
+     * entries).
+     *
+     * The destination named object may already exist in
+     * which case its previous contents are discarded.
+     */
     void clone(coll_t cid, const ghobject_t& oid, ghobject_t noid) {
       __u32 op = OP_CLONE;
       ::encode(op, tbl);
@@ -533,6 +771,13 @@ public:
       ::encode(noid, tbl);
       ops++;
     }
+    /**
+     * Clone a byte range from one object to another.
+     *
+     * The data portion of the destination object receives a copy of a
+     * portion of the data from the source object. None of the other
+     * three parts of an object is copied from the source.
+     */
     void clone_range(coll_t cid, const ghobject_t& oid, ghobject_t noid,
 		     uint64_t srcoff, uint64_t srclen, uint64_t dstoff) {
       __u32 op = OP_CLONERANGE2;
@@ -545,18 +790,29 @@ public:
       ::encode(dstoff, tbl);
       ops++;
     }
+    /// Create the collection
     void create_collection(coll_t cid) {
       __u32 op = OP_MKCOLL;
       ::encode(op, tbl);
       ::encode(cid, tbl);
       ops++;
     }
+    /// remove the collection, the collection must be empty
     void remove_collection(coll_t cid) {
       __u32 op = OP_RMCOLL;
       ::encode(op, tbl);
       ::encode(cid, tbl);
       ops++;
     }
+    /**
+     * Add object to another collection (DEPRECATED)
+     *
+     * The Object is added to the new collection. This is a virtual
+     * add, we now have two names for the same object.  This is only
+     * used for conversion of old stores to new stores and is not
+     * needed for new implementations unless they expect to make use
+     * of the conversion infrastructure.
+     */
     void collection_add(coll_t cid, coll_t ocid, const ghobject_t& oid) {
       __u32 op = OP_COLL_ADD;
       ::encode(op, tbl);
@@ -588,10 +844,12 @@ public:
       ops++;
     }
 
+    /// Set an xattr on a collection
     void collection_setattr(coll_t cid, const char* name, bufferlist& val) {
       string n(name);
       collection_setattr(cid, n, val);
     }
+    /// Set an xattr on a collection
     void collection_setattr(coll_t cid, const string& name, bufferlist& val) {
       __u32 op = OP_COLL_SETATTR;
       ::encode(op, tbl);
@@ -601,10 +859,12 @@ public:
       ops++;
     }
 
+    /// Remove an xattr from a collection
     void collection_rmattr(coll_t cid, const char* name) {
       string n(name);
       collection_rmattr(cid, n);
     }
+    /// Remove an xattr from a collection
     void collection_rmattr(coll_t cid, const string& name) {
       __u32 op = OP_COLL_RMATTR;
       ::encode(op, tbl);
@@ -612,6 +872,7 @@ public:
       ::encode(name, tbl);
       ops++;
     }
+    /// Set multiple xattrs on a collection
     void collection_setattrs(coll_t cid, map<string,bufferptr>& aset) {
       __u32 op = OP_COLL_SETATTRS;
       ::encode(op, tbl);
@@ -619,6 +880,7 @@ public:
       ::encode(aset, tbl);
       ops++;
     }
+    /// Set multiple xattrs on a collection
     void collection_setattrs(coll_t cid, map<string,bufferlist>& aset) {
       __u32 op = OP_COLL_SETATTRS;
       ::encode(op, tbl);
@@ -626,6 +888,7 @@ public:
       ::encode(aset, tbl);
       ops++;
     }
+    /// Change the name of a collection
     void collection_rename(coll_t cid, coll_t ncid) {
       __u32 op = OP_COLL_RENAME;
       ::encode(op, tbl);
@@ -675,9 +938,9 @@ public:
     /// Remove key range from oid omap
     void omap_rmkeyrange(
       coll_t cid,             ///< [in] Collection containing oid
-      const ghobject_t &oid,  ///< [in] Object from which to remove the omap
+      const ghobject_t &oid,  ///< [in] Object from which to remove the omap keys
       const string& first,    ///< [in] first key in range
-      const string& last      ///< [in] first key past range
+      const string& last      ///< [in] first key past range, range is [first,last)
       ) {
       __u32 op = OP_OMAP_RMKEYRANGE;
       ::encode(op, tbl);
@@ -691,7 +954,7 @@ public:
     /// Set omap header
     void omap_setheader(
       coll_t cid,             ///< [in] Collection containing oid
-      const ghobject_t &oid,  ///< [in] Object from which to remove the omap
+      const ghobject_t &oid,  ///< [in] Object
       const bufferlist &bl    ///< [in] Header value
       ) {
       __u32 op = OP_OMAP_SETHEADER;
@@ -702,7 +965,8 @@ public:
       ops++;
     }
 
-    /// Split collection based on given prefixes
+    /// Split collection based on given prefixes, objects matching the specified bits/rem are
+    /// moved to the new collection
     void split_collection(
       coll_t cid,
       uint32_t bits,
@@ -753,7 +1017,7 @@ public:
       replica(false),
       tolerate_collection_add_enoent(false) {
       bufferlist::iterator dp = nbl.begin();
-      decode(dp); 
+      decode(dp);
     }
 
     void encode(bufferlist& bl) const {
@@ -834,7 +1098,7 @@ public:
     list<Transaction *> tls;
     tls.push_back(t);
     return queue_transactions(osr, tls, new C_DeleteTransaction(t),
-                              NULL, NULL, TrackedOpRef(), handle);
+	                      NULL, NULL, TrackedOpRef(), handle);
   }
 
   int queue_transaction(Sequencer *osr, Transaction *t, Context *onreadable, Context *ondisk=0,
@@ -844,7 +1108,7 @@ public:
     list<Transaction*> tls;
     tls.push_back(t);
     return queue_transactions(osr, tls, onreadable, ondisk, onreadable_sync,
-                              op, handle);
+	                      op, handle);
   }
 
   int queue_transactions(Sequencer *osr, list<Transaction*>& tls,
@@ -965,15 +1229,50 @@ public:
    */
   virtual int get_ideal_list_max() { return 64; }
 
-  // objects
+  /**
+   * Synchronous read operations
+   */
+
+
+  /**
+   * exists -- Test for existance of object
+   *
+   * @param cid collection for object
+   * @param oid oid of object
+   * @returns true if object exists, false otherwise
+   */
   virtual bool exists(coll_t cid, const ghobject_t& oid) = 0;                   // useful?
+
+  /**
+   * stat -- get information for an object
+   *
+   * @param cid collection for object
+   * @param oid oid of object
+   * @param st output information for the object
+   * @param allow_eio if false, assert on -EIO operation failure
+   * @returns 0 on success, negative error code on failure.
+   */
   virtual int stat(
     coll_t cid,
     const ghobject_t& oid,
     struct stat *st,
     bool allow_eio = false) = 0; // struct stat?
 
-  virtual int read(
+  /**
+   * read -- read a byte range of data from an object
+   *
+   * Note: if reading from an offset past the end of the object, we
+   * return 0 (not, say, -EINVAL).
+   *
+   * @param cid collection for object
+   * @param oid oid of object
+   * @param offset location offset of first byte to be read
+   * @param len number of bytes to be read
+   * @param bl output bufferlist
+   * @param allow_eio if false, assert on -EIO operation failure
+   * @returns number of bytes read on success, or negative error code on failure.
+   */
+   virtual int read(
     coll_t cid,
     const ghobject_t& oid,
     uint64_t offset,
@@ -981,9 +1280,44 @@ public:
     bufferlist& bl,
     bool allow_eio = false) = 0;
 
+  /**
+   * fiemap -- get extent map of data of an object
+   *
+   * Returns an encoded map of the extents of an object's data portion
+   * (map<offset,size>).
+   *
+   * A non-enlightend implementation is free to return the extent (offset, len)
+   * as the sole extent.
+   *
+   * @param cid collection for object
+   * @param oid oid of object
+   * @param offset location offset of first byte to be read
+   * @param len number of bytes to be read
+   * @param bl output bufferlist for extent map information.
+   * @returns 0 on success, negative error code on failure.
+   */
   virtual int fiemap(coll_t cid, const ghobject_t& oid, uint64_t offset, size_t len, bufferlist& bl) = 0;
 
+  /**
+   * getattr -- get an xattr of an object
+   *
+   * @param cid collection for object
+   * @param oid oid of object
+   * @param name name of attr to read
+   * @param value place to put output result.
+   * @returns 0 on success, negative error code on failure.
+   */
   virtual int getattr(coll_t cid, const ghobject_t& oid, const char *name, bufferptr& value) = 0;
+
+  /**
+   * getattr -- get an xattr of an object
+   *
+   * @param cid collection for object
+   * @param oid oid of object
+   * @param name name of attr to read
+   * @param value place to put output result.
+   * @returns 0 on success, negative error code on failure.
+   */
   int getattr(coll_t cid, const ghobject_t& oid, const char *name, bufferlist& value) {
     bufferptr bp;
     int r = getattr(cid, oid, name, bp);
@@ -999,7 +1333,27 @@ public:
     value.push_back(bp);
     return r;
   }
+
+  /**
+   * getattrs -- get all of the xattrs of an object
+   *
+   * @param cid collection for object
+   * @param oid oid of object
+   * @param aset place to put output result.
+   * @param user_only true -> only user attributes are return else all attributes are returned
+   * @returns 0 on success, negative error code on failure.
+   */
   virtual int getattrs(coll_t cid, const ghobject_t& oid, map<string,bufferptr>& aset, bool user_only = false) = 0;
+
+  /**
+   * getattrs -- get all of the xattrs of an object
+   *
+   * @param cid collection for object
+   * @param oid oid of object
+   * @param aset place to put output result.
+   * @param user_only true -> only user attributes are return else all attributes are returned
+   * @returns 0 on success, negative error code on failure.
+   */
   int getattrs(coll_t cid, const ghobject_t& oid, map<string,bufferlist>& aset, bool user_only = false) {
     map<string,bufferptr> bmap;
     int r = getattrs(cid, oid, bmap, user_only);
@@ -1011,19 +1365,71 @@ public:
     return r;
   }
 
-   
+
   // collections
+
+  /**
+   * list_collections -- get all of the collections known to this ObjectStore
+   *
+   * @param ls list of the collections in sorted order.
+   * @returns 0 on success, negative error code on failure.
+   */
   virtual int list_collections(vector<coll_t>& ls) = 0;
-  virtual int collection_version_current(coll_t c, uint32_t *version) { 
+
+  virtual int collection_version_current(coll_t c, uint32_t *version) {
     *version = 0;
     return 1;
   }
+  /**
+   * does a collection exist?
+   *
+   * @param c collection
+   * @returns true if it exists, false otherwise
+   */
   virtual bool collection_exists(coll_t c) = 0;
+  /**
+   * collection_getattr - get an xattr of a collection
+   *
+   * @param cid collection name
+   * @param name xattr name
+   * @param value pointer of buffer to receive value
+   * @param size size of buffer to receive value
+   * @returns 0 on success, negative error code on failure
+   */
   virtual int collection_getattr(coll_t cid, const char *name,
-                                 void *value, size_t size) = 0;
+	                         void *value, size_t size) = 0;
+  /**
+   * collection_getattr - get an xattr of a collection
+   *
+   * @param cid collection name
+   * @param name xattr name
+   * @param bl buffer to receive value
+   * @returns 0 on success, negative error code on failure
+   */
   virtual int collection_getattr(coll_t cid, const char *name, bufferlist& bl) = 0;
+  /**
+   * collection_getattrs - get all xattrs of a collection
+   *
+   * @param cid collection name
+   * @param asert map of keys and buffers that contain the values
+   * @returns 0 on success, negative error code on failure
+   */
   virtual int collection_getattrs(coll_t cid, map<string,bufferptr> &aset) = 0;
+  /**
+   * is a collection empty?
+   *
+   * @param c collection
+   * @returns true if empty, false otherwise
+   */
   virtual bool collection_empty(coll_t c) = 0;
+
+  /**
+   * collection_list - get all objects of a collection in sorted order
+   *
+   * @param c collection name
+   * @param o [out] list of objects
+   * @returns 0 on success, negative error code on failure
+   */
   virtual int collection_list(coll_t c, vector<ghobject_t>& o) = 0;
 
   /**
@@ -1039,7 +1445,7 @@ public:
    * @return zero on success, or negative error
    */
   virtual int collection_list_partial(coll_t c, ghobject_t start,
-				      int min, int max, snapid_t snap, 
+				      int min, int max, snapid_t snap,
 				      vector<ghobject_t> *ls, ghobject_t *next) = 0;
 
   /**
@@ -1053,7 +1459,7 @@ public:
    * @return zero on success, or negative error
    */
   virtual int collection_list_range(coll_t c, ghobject_t start, ghobject_t end,
-                                    snapid_t seq, vector<ghobject_t> *ls) = 0;
+	                            snapid_t seq, vector<ghobject_t> *ls) = 0;
 
   //TODO: Remove
   int collection_list(coll_t c, vector<hobject_t>& o);
@@ -1063,7 +1469,7 @@ public:
 				      vector<hobject_t> *ls, hobject_t *next);
 
   int collection_list_range(coll_t c, hobject_t start, hobject_t end,
-                                    snapid_t seq, vector<hobject_t> *ls);
+	                            snapid_t seq, vector<hobject_t> *ls);
 
   /// OMAP
   /// Get omap contents
@@ -1127,7 +1533,10 @@ public:
   virtual int dump_journal(ostream& out) { return -EOPNOTSUPP; }
 
   virtual int snapshot(const string& name) { return -EOPNOTSUPP; }
-    
+
+  /**
+   * Set and get internal fsid for this instance. No external data is modified
+   */
   virtual void set_fsid(uuid_d u) = 0;
   virtual uuid_d get_fsid() = 0;
 
diff --git a/src/osd/ECBackend.cc b/src/osd/ECBackend.cc
index 5738ab3..dc2a26f 100644
--- a/src/osd/ECBackend.cc
+++ b/src/osd/ECBackend.cc
@@ -703,13 +703,13 @@ bool ECBackend::handle_message(
 struct SubWriteCommitted : public Context {
   ECBackend *pg;
   OpRequestRef msg;
-  tid_t tid;
+  ceph_tid_t tid;
   eversion_t version;
   eversion_t last_complete;
   SubWriteCommitted(
     ECBackend *pg,
     OpRequestRef msg,
-    tid_t tid,
+    ceph_tid_t tid,
     eversion_t version,
     eversion_t last_complete)
     : pg(pg), msg(msg), tid(tid),
@@ -721,7 +721,7 @@ struct SubWriteCommitted : public Context {
   }
 };
 void ECBackend::sub_write_committed(
-  tid_t tid, eversion_t version, eversion_t last_complete) {
+  ceph_tid_t tid, eversion_t version, eversion_t last_complete) {
   if (get_parent()->pgb_is_primary()) {
     ECSubWriteReply reply;
     reply.tid = tid;
@@ -748,12 +748,12 @@ void ECBackend::sub_write_committed(
 struct SubWriteApplied : public Context {
   ECBackend *pg;
   OpRequestRef msg;
-  tid_t tid;
+  ceph_tid_t tid;
   eversion_t version;
   SubWriteApplied(
     ECBackend *pg,
     OpRequestRef msg,
-    tid_t tid,
+    ceph_tid_t tid,
     eversion_t version)
     : pg(pg), msg(msg), tid(tid), version(version) {}
   void finish(int) {
@@ -763,7 +763,7 @@ struct SubWriteApplied : public Context {
   }
 };
 void ECBackend::sub_write_applied(
-  tid_t tid, eversion_t version) {
+  ceph_tid_t tid, eversion_t version) {
   parent->op_applied(version);
   if (get_parent()->pgb_is_primary()) {
     ECSubWriteReply reply;
@@ -797,7 +797,7 @@ void ECBackend::handle_sub_write(
   if (!get_parent()->pgb_is_primary())
     get_parent()->update_stats(op.stats);
   ObjectStore::Transaction *localt = new ObjectStore::Transaction;
-  if (op.temp_added.size()) {
+  if (!op.temp_added.empty()) {
     get_temp_coll(localt);
     add_temp_objs(op.temp_added);
   }
@@ -901,7 +901,7 @@ void ECBackend::handle_sub_write_reply(
   pg_shard_t from,
   ECSubWriteReply &op)
 {
-  map<tid_t, Op>::iterator i = tid_to_op_map.find(op.tid);
+  map<ceph_tid_t, Op>::iterator i = tid_to_op_map.find(op.tid);
   assert(i != tid_to_op_map.end());
   if (op.committed) {
     assert(i->second.pending_commit.count(from));
@@ -923,7 +923,7 @@ void ECBackend::handle_sub_read_reply(
   RecoveryMessages *m)
 {
   dout(10) << __func__ << ": reply " << op << dendl;
-  map<tid_t, ReadOp>::iterator iter = tid_to_read_map.find(op.tid);
+  map<ceph_tid_t, ReadOp>::iterator iter = tid_to_read_map.find(op.tid);
   if (iter == tid_to_read_map.end()) {
     //canceled
     return;
@@ -978,7 +978,8 @@ void ECBackend::handle_sub_read_reply(
       rop.complete[i->first].r = i->second;
   }
 
-  map<pg_shard_t, set<tid_t> >::iterator siter = shard_to_read_map.find(from);
+  map<pg_shard_t, set<ceph_tid_t> >::iterator siter =
+shard_to_read_map.find(from);
   assert(siter != shard_to_read_map.end());
   assert(siter->second.count(op.tid));
   siter->second.erase(op.tid);
@@ -1013,8 +1014,8 @@ void ECBackend::complete_read_op(ReadOp &rop, RecoveryMessages *m)
 
 struct FinishReadOp : public GenContext<ThreadPool::TPHandle&>  {
   ECBackend *ec;
-  tid_t tid;
-  FinishReadOp(ECBackend *ec, tid_t tid) : ec(ec), tid(tid) {}
+  ceph_tid_t tid;
+  FinishReadOp(ECBackend *ec, ceph_tid_t tid) : ec(ec), tid(tid) {}
   void finish(ThreadPool::TPHandle &handle) {
     assert(ec->tid_to_read_map.count(tid));
     int priority = ec->tid_to_read_map[tid].priority;
@@ -1088,8 +1089,9 @@ void ECBackend::filter_read_op(
 
 void ECBackend::check_recovery_sources(const OSDMapRef osdmap)
 {
-  set<tid_t> tids_to_filter;
-  for (map<pg_shard_t, set<tid_t> >::iterator i = shard_to_read_map.begin();
+  set<ceph_tid_t> tids_to_filter;
+  for (map<pg_shard_t, set<ceph_tid_t> >::iterator 
+       i = shard_to_read_map.begin();
        i != shard_to_read_map.end();
        ) {
     if (osdmap->is_down(i->first.osd)) {
@@ -1099,10 +1101,10 @@ void ECBackend::check_recovery_sources(const OSDMapRef osdmap)
       ++i;
     }
   }
-  for (set<tid_t>::iterator i = tids_to_filter.begin();
+  for (set<ceph_tid_t>::iterator i = tids_to_filter.begin();
        i != tids_to_filter.end();
        ++i) {
-    map<tid_t, ReadOp>::iterator j = tid_to_read_map.find(*i);
+    map<ceph_tid_t, ReadOp>::iterator j = tid_to_read_map.find(*i);
     assert(j != tid_to_read_map.end());
     filter_read_op(osdmap, j->second);
   }
@@ -1112,7 +1114,7 @@ void ECBackend::_on_change(ObjectStore::Transaction *t)
 {
   writing.clear();
   tid_to_op_map.clear();
-  for (map<tid_t, ReadOp>::iterator i = tid_to_read_map.begin();
+  for (map<ceph_tid_t, ReadOp>::iterator i = tid_to_read_map.begin();
        i != tid_to_read_map.end();
        ++i) {
     dout(10) << __func__ << ": cancelling " << i->second << dendl;
@@ -1157,7 +1159,7 @@ void ECBackend::dump_recovery_info(Formatter *f) const
   }
   f->close_section();
   f->open_array_section("read_ops");
-  for (map<tid_t, ReadOp>::const_iterator i = tid_to_read_map.begin();
+  for (map<ceph_tid_t, ReadOp>::const_iterator i = tid_to_read_map.begin();
        i != tid_to_read_map.end();
        ++i) {
     f->open_object_section("read_op");
@@ -1202,7 +1204,7 @@ void ECBackend::submit_transaction(
   Context *on_local_applied_sync,
   Context *on_all_applied,
   Context *on_all_commit,
-  tid_t tid,
+  ceph_tid_t tid,
   osd_reqid_t reqid,
   OpRequestRef client_op
   )
@@ -1343,7 +1345,7 @@ void ECBackend::start_read_op(
   map<hobject_t, read_request_t> &to_read,
   OpRequestRef _op)
 {
-  tid_t tid = get_parent()->get_tid();
+  ceph_tid_t tid = get_parent()->get_tid();
   assert(!tid_to_read_map.count(tid));
   ReadOp &op(tid_to_read_map[tid]);
   op.priority = priority;
@@ -1467,7 +1469,7 @@ void ECBackend::check_op(Op *op)
     writing.pop_front();
     tid_to_op_map.erase(op->tid);
   }
-  for (map<tid_t, Op>::iterator i = tid_to_op_map.begin();
+  for (map<ceph_tid_t, Op>::iterator i = tid_to_op_map.begin();
        i != tid_to_op_map.end();
        ++i) {
     dout(20) << __func__ << " tid " << i->first <<": " << i->second << dendl;
diff --git a/src/osd/ECBackend.h b/src/osd/ECBackend.h
index 7844563..0aa37c1 100644
--- a/src/osd/ECBackend.h
+++ b/src/osd/ECBackend.h
@@ -55,9 +55,9 @@ public:
   friend struct SubWriteApplied;
   friend struct SubWriteCommitted;
   void sub_write_applied(
-    tid_t tid, eversion_t version);
+    ceph_tid_t tid, eversion_t version);
   void sub_write_committed(
-    tid_t tid, eversion_t version, eversion_t last_complete);
+    ceph_tid_t tid, eversion_t version, eversion_t last_complete);
   void handle_sub_write(
     pg_shard_t from,
     OpRequestRef msg,
@@ -101,7 +101,7 @@ public:
     Context *on_local_applied_sync,
     Context *on_all_applied,
     Context *on_all_commit,
-    tid_t tid,
+    ceph_tid_t tid,
     osd_reqid_t reqid,
     OpRequestRef op
     );
@@ -281,7 +281,7 @@ public:
 
   struct ReadOp {
     int priority;
-    tid_t tid;
+    ceph_tid_t tid;
     OpRequestRef op; // may be null if not on behalf of a client
 
     map<hobject_t, read_request_t> to_read;
@@ -300,8 +300,8 @@ public:
     ReadOp &op);
   void complete_read_op(ReadOp &rop, RecoveryMessages *m);
   friend ostream &operator<<(ostream &lhs, const ReadOp &rhs);
-  map<tid_t, ReadOp> tid_to_read_map;
-  map<pg_shard_t, set<tid_t> > shard_to_read_map;
+  map<ceph_tid_t, ReadOp> tid_to_read_map;
+  map<pg_shard_t, set<ceph_tid_t> > shard_to_read_map;
   void start_read_op(
     int priority,
     map<hobject_t, read_request_t> &to_read,
@@ -329,7 +329,7 @@ public:
     Context *on_local_applied_sync;
     Context *on_all_applied;
     Context *on_all_commit;
-    tid_t tid;
+    ceph_tid_t tid;
     osd_reqid_t reqid;
     OpRequestRef client_op;
 
@@ -370,7 +370,7 @@ public:
     pg_shard_t from,
     RecoveryMessages *m);
 
-  map<tid_t, Op> tid_to_op_map; /// lists below point into here
+  map<ceph_tid_t, Op> tid_to_op_map; /// lists below point into here
   list<Op*> writing;
 
   CephContext *cct;
diff --git a/src/osd/ECMsgTypes.h b/src/osd/ECMsgTypes.h
index cadeb25..d1ad2cb 100644
--- a/src/osd/ECMsgTypes.h
+++ b/src/osd/ECMsgTypes.h
@@ -21,7 +21,7 @@
 
 struct ECSubWrite {
   pg_shard_t from;
-  tid_t tid;
+  ceph_tid_t tid;
   osd_reqid_t reqid;
   hobject_t soid;
   pg_stat_t stats;
@@ -34,11 +34,11 @@ struct ECSubWrite {
   ECSubWrite() {}
   ECSubWrite(
     pg_shard_t from,
-    tid_t tid,
+    ceph_tid_t tid,
     osd_reqid_t reqid,
     hobject_t soid,
-    pg_stat_t stats,
-    ObjectStore::Transaction t,
+    const pg_stat_t &stats,
+    const ObjectStore::Transaction &t,
     eversion_t at_version,
     eversion_t trim_to,
     vector<pg_log_entry_t> log_entries,
@@ -59,7 +59,7 @@ WRITE_CLASS_ENCODER(ECSubWrite)
 
 struct ECSubWriteReply {
   pg_shard_t from;
-  tid_t tid;
+  ceph_tid_t tid;
   eversion_t last_complete;
   bool committed;
   bool applied;
@@ -73,7 +73,7 @@ WRITE_CLASS_ENCODER(ECSubWriteReply)
 
 struct ECSubRead {
   pg_shard_t from;
-  tid_t tid;
+  ceph_tid_t tid;
   map<hobject_t, list<pair<uint64_t, uint64_t> > > to_read;
   set<hobject_t> attrs_to_read;
   void encode(bufferlist &bl) const;
@@ -85,7 +85,7 @@ WRITE_CLASS_ENCODER(ECSubRead)
 
 struct ECSubReadReply {
   pg_shard_t from;
-  tid_t tid;
+  ceph_tid_t tid;
   map<hobject_t, list<pair<uint64_t, bufferlist> > > buffers_read;
   map<hobject_t, map<string, bufferlist> > attrs_read;
   map<hobject_t, int> errors;
diff --git a/src/osd/Makefile.am b/src/osd/Makefile.am
index 3e91d7d..8a2cb2b 100644
--- a/src/osd/Makefile.am
+++ b/src/osd/Makefile.am
@@ -19,7 +19,7 @@ libosd_la_SOURCES = \
 	osd/osd_types.cc \
 	osd/ECUtil.cc \
 	objclass/class_api.cc
-libosd_la_LIBADD = $(LIBOSDC) $(LIBOS) $(LIBERASURE_CODE)
+libosd_la_LIBADD = $(LIBOSDC) $(LIBOS)
 noinst_LTLIBRARIES += libosd.la
 
 noinst_HEADERS += \
diff --git a/src/osd/OSD.cc b/src/osd/OSD.cc
index db14031..baa9848 100644
--- a/src/osd/OSD.cc
+++ b/src/osd/OSD.cc
@@ -2115,8 +2115,6 @@ void OSD::load_pgs()
 
     service.init_splits_between(pg->info.pgid, pg->get_osdmap(), osdmap);
 
-    pg->reg_next_scrub();
-
     // generate state for PG's current mapping
     int primary, up_primary;
     vector<int> acting, up;
@@ -2130,6 +2128,8 @@ void OSD::load_pgs()
     int role = OSDMap::calc_pg_role(whoami, pg->acting);
     pg->set_role(role);
 
+    pg->reg_next_scrub();
+
     PG::RecoveryCtx rctx(0, 0, 0, 0, 0, 0);
     pg->handle_loaded(&rctx);
 
@@ -3012,9 +3012,9 @@ void OSD::handle_osd_ping(MOSDPing *m)
     break;
 
   case MOSDPing::YOU_DIED:
-    dout(10) << "handle_osd_ping " << m->get_source_inst() << " says i am down in " << m->map_epoch
-	     << dendl;
-    osdmap_subscribe(m->map_epoch, false);
+    dout(10) << "handle_osd_ping " << m->get_source_inst()
+	     << " says i am down in " << m->map_epoch << dendl;
+    osdmap_subscribe(curmap->get_epoch()+1, false);
     break;
   }
 
@@ -4175,7 +4175,7 @@ COMMAND("reset_pg_recovery_stats", "reset pg recovery statistics",
 	"osd", "rw", "cli,rest")
 };
 
-void OSD::do_command(Connection *con, tid_t tid, vector<string>& cmd, bufferlist& data)
+void OSD::do_command(Connection *con, ceph_tid_t tid, vector<string>& cmd, bufferlist& data)
 {
   int r = 0;
   stringstream ss, ds;
@@ -7590,6 +7590,16 @@ void OSD::OpWQ::_process(PGRef pg, ThreadPool::TPHandle &handle)
     if (!(pg_for_processing[&*pg].size()))
       pg_for_processing.erase(&*pg);
   }
+
+  lgeneric_subdout(osd->cct, osd, 30) << "dequeue status: ";
+  Formatter *f = new_formatter("json");
+  f->open_object_section("q");
+  dump(f);
+  f->close_section();
+  f->flush(*_dout);
+  delete f;
+  *_dout << dendl;
+
   osd->dequeue_op(pg, op, handle);
   pg->unlock();
 }
diff --git a/src/osd/OSD.h b/src/osd/OSD.h
index 7ee3442..9192fcc 100644
--- a/src/osd/OSD.h
+++ b/src/osd/OSD.h
@@ -580,10 +580,10 @@ public:
 
   // -- tids --
   // for ops i issue
-  tid_t last_tid;
+  ceph_tid_t last_tid;
   Mutex tid_lock;
-  tid_t get_tid() {
-    tid_t t;
+  ceph_tid_t get_tid() {
+    ceph_tid_t t;
     tid_lock.Lock();
     t = ++last_tid;
     tid_lock.Unlock();
@@ -1114,8 +1114,9 @@ private:
     {}
 
     void dump(Formatter *f) {
-      Mutex::Locker l(qlock);
+      lock();
       pqueue.dump(f);
+      unlock();
     }
 
     void _enqueue_front(pair<PGRef, OpRequestRef> item);
@@ -1485,7 +1486,7 @@ protected:
     pg_stat_queue_lock.Unlock();
   }
 
-  tid_t get_tid() {
+  ceph_tid_t get_tid() {
     return service.get_tid();
   }
 
@@ -1530,11 +1531,11 @@ protected:
   // -- commands --
   struct Command {
     vector<string> cmd;
-    tid_t tid;
+    ceph_tid_t tid;
     bufferlist indata;
     ConnectionRef con;
 
-    Command(vector<string>& c, tid_t t, bufferlist& bl, Connection *co)
+    Command(vector<string>& c, ceph_tid_t t, bufferlist& bl, Connection *co)
       : cmd(c), tid(t), indata(bl), con(co) {}
   };
   list<Command*> command_queue;
@@ -1582,7 +1583,7 @@ protected:
 
   void handle_command(class MMonCommand *m);
   void handle_command(class MCommand *m);
-  void do_command(Connection *con, tid_t tid, vector<string>& cmd, bufferlist& data);
+  void do_command(Connection *con, ceph_tid_t tid, vector<string>& cmd, bufferlist& data);
 
   // -- pg recovery --
   xlist<PG*> recovery_queue;
diff --git a/src/osd/OSDMap.cc b/src/osd/OSDMap.cc
index 57b7082..a764f34 100644
--- a/src/osd/OSDMap.cc
+++ b/src/osd/OSDMap.cc
@@ -4,6 +4,9 @@
  * Ceph - scalable distributed file system
  *
  * Copyright (C) 2004-2006 Sage Weil <sage at newdream.net>
+ * Copyright (C) 2013,2014 Cloudwatt <libre.licensing at cloudwatt.com>
+ *
+ * Author: Loic Dachary <loic at dachary.org>
  *
  * This is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -17,6 +20,7 @@
 #include "common/config.h"
 #include "common/Formatter.h"
 #include "include/ceph_features.h"
+#include "include/str_map.h"
 
 #include "common/code_environment.h"
 
@@ -388,7 +392,7 @@ void OSDMap::Incremental::encode(bufferlist& bl, uint64_t features) const
   ENCODE_START(7, 7, bl);
 
   {
-    ENCODE_START(2, 1, bl); // client-usable data
+    ENCODE_START(3, 1, bl); // client-usable data
     ::encode(fsid, bl);
     ::encode(epoch, bl);
     ::encode(modified, bl);
@@ -407,6 +411,8 @@ void OSDMap::Incremental::encode(bufferlist& bl, uint64_t features) const
     ::encode(new_pg_temp, bl);
     ::encode(new_primary_temp, bl);
     ::encode(new_primary_affinity, bl);
+    ::encode(new_erasure_code_profiles, bl);
+    ::encode(old_erasure_code_profiles, bl);
     ENCODE_FINISH(bl); // client-usable data
   }
 
@@ -542,7 +548,7 @@ void OSDMap::Incremental::decode(bufferlist::iterator& bl)
     return;
   }
   {
-    DECODE_START(2, bl); // client-usable data
+    DECODE_START(3, bl); // client-usable data
     ::decode(fsid, bl);
     ::decode(epoch, bl);
     ::decode(modified, bl);
@@ -564,6 +570,13 @@ void OSDMap::Incremental::decode(bufferlist::iterator& bl)
       ::decode(new_primary_affinity, bl);
     else
       new_primary_affinity.clear();
+    if (struct_v >= 3) {
+      ::decode(new_erasure_code_profiles, bl);
+      ::decode(old_erasure_code_profiles, bl);
+    } else {
+      new_erasure_code_profiles.clear();
+      old_erasure_code_profiles.clear();
+    }
     DECODE_FINISH(bl); // client-usable data
   }
 
@@ -763,6 +776,15 @@ void OSDMap::Incremental::dump(Formatter *f) const
     f->close_section();
   }
   f->close_section();
+
+  OSDMap::dump_erasure_code_profiles(new_erasure_code_profiles, f);
+  f->open_array_section("old_erasure_code_profiles");
+  for (vector<string>::const_iterator p = old_erasure_code_profiles.begin();
+       p != old_erasure_code_profiles.end();
+       p++) {
+    f->dump_string("old", p->c_str());
+  }
+  f->close_section();
 }
 
 void OSDMap::Incremental::generate_test_instances(list<Incremental*>& o)
@@ -1191,6 +1213,19 @@ int OSDMap::apply_incremental(const Incremental &inc)
     set_primary_affinity(i->first, i->second);
   }
 
+  // erasure_code_profiles
+  for (map<string,map<string,string> >::const_iterator i =
+	 inc.new_erasure_code_profiles.begin();
+       i != inc.new_erasure_code_profiles.end();
+       i++) {
+    set_erasure_code_profile(i->first, i->second);
+  }
+  
+  for (vector<string>::const_iterator i = inc.old_erasure_code_profiles.begin();
+       i != inc.old_erasure_code_profiles.end();
+       i++)
+    erasure_code_profiles.erase(*i);
+  
   // up/down
   for (map<int32_t,uint8_t>::const_iterator i = inc.new_state.begin();
        i != inc.new_state.end();
@@ -1725,7 +1760,7 @@ void OSDMap::encode(bufferlist& bl, uint64_t features) const
   ENCODE_START(7, 7, bl);
 
   {
-    ENCODE_START(2, 1, bl); // client-usable data
+    ENCODE_START(3, 1, bl); // client-usable data
     // base
     ::encode(fsid, bl);
     ::encode(epoch, bl);
@@ -1756,6 +1791,7 @@ void OSDMap::encode(bufferlist& bl, uint64_t features) const
     bufferlist cbl;
     crush->encode(cbl);
     ::encode(cbl, bl);
+    ::encode(erasure_code_profiles, bl);
     ENCODE_FINISH(bl); // client-usable data
   }
 
@@ -1913,7 +1949,7 @@ void OSDMap::decode(bufferlist::iterator& bl)
    * Since we made it past that hurdle, we can use our normal paths.
    */
   {
-    DECODE_START(2, bl); // client-usable data
+    DECODE_START(3, bl); // client-usable data
     // base
     ::decode(fsid, bl);
     ::decode(epoch, bl);
@@ -1947,6 +1983,11 @@ void OSDMap::decode(bufferlist::iterator& bl)
     ::decode(cbl, bl);
     bufferlist::iterator cblp = cbl.begin();
     crush->decode(cblp);
+    if (struct_v >= 3) {
+      ::decode(erasure_code_profiles, bl);
+    } else {
+      erasure_code_profiles.clear();
+    }
     DECODE_FINISH(bl); // client-usable data
   }
 
@@ -1981,6 +2022,24 @@ void OSDMap::post_decode()
   calc_num_osds();
 }
 
+void OSDMap::dump_erasure_code_profiles(const map<string,map<string,string> > &profiles,
+					Formatter *f)
+{
+  f->open_object_section("erasure_code_profiles");
+  for (map<string,map<string,string> >::const_iterator i = profiles.begin();
+       i != profiles.end();
+       i++) {
+    f->open_object_section(i->first.c_str());
+    for (map<string,string>::const_iterator j = i->second.begin();
+	 j != i->second.end();
+	 j++) {
+      f->dump_string(j->first.c_str(), j->second.c_str());
+    }
+    f->close_section();
+  }
+  f->close_section();
+}
+
 void OSDMap::dump_json(ostream& out) const
 {
   JSONFormatter jsf(true);
@@ -2085,6 +2144,8 @@ void OSDMap::dump(Formatter *f) const
     f->dump_stream(ss.str().c_str()) << p->second;
   }
   f->close_section();
+
+  dump_erasure_code_profiles(erasure_code_profiles, f);
 }
 
 void OSDMap::generate_test_instances(list<OSDMap*>& o)
@@ -2487,6 +2548,13 @@ int OSDMap::build_simple(CephContext *cct, epoch_t e, uuid_d &fsid,
     set_weight(i, CEPH_OSD_OUT);
   }
 
+  map<string,string> erasure_code_profile_map;
+  r = get_str_map(cct->_conf->osd_pool_default_erasure_code_profile,
+		  ss,
+		  &erasure_code_profile_map);
+  erasure_code_profile_map["directory"] =
+    cct->_conf->osd_pool_default_erasure_code_directory;
+  set_erasure_code_profile("default", erasure_code_profile_map);
   return r;
 }
 
diff --git a/src/osd/OSDMap.h b/src/osd/OSDMap.h
index 44da1b0..650957d 100644
--- a/src/osd/OSDMap.h
+++ b/src/osd/OSDMap.h
@@ -4,6 +4,9 @@
  * Ceph - scalable distributed file system
  *
  * Copyright (C) 2004-2006 Sage Weil <sage at newdream.net>
+ * Copyright (C) 2013,2014 Cloudwatt <libre.licensing at cloudwatt.com>
+ *
+ * Author: Loic Dachary <loic at dachary.org>
  *
  * This is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -129,6 +132,8 @@ public:
     map<int64_t,pg_pool_t> new_pools;
     map<int64_t,string> new_pool_names;
     set<int64_t> old_pools;
+    map<string,map<string,string> > new_erasure_code_profiles;
+    vector<string> old_erasure_code_profiles;
     map<int32_t,entity_addr_t> new_up_client;
     map<int32_t,entity_addr_t> new_up_cluster;
     map<int32_t,uint8_t> new_state;             // XORed onto previous state.
@@ -179,6 +184,15 @@ public:
 	new_pools[pool] = *orig;
       return &new_pools[pool];
     }
+    bool has_erasure_code_profile(const string &name) const {
+      map<string,map<string,string> >::const_iterator i =
+	new_erasure_code_profiles.find(name);
+      return i != new_erasure_code_profiles.end();
+    }
+    void set_erasure_code_profile(const string &name,
+				  const map<string,string> &profile) {
+      new_erasure_code_profiles[name] = profile;
+    }
 
     /// propage update pools' snap metadata to any of their tiers
     int propagate_snaps_to_tiers(CephContext *cct, const OSDMap &base);
@@ -213,6 +227,7 @@ private:
 
   map<int64_t,pg_pool_t> pools;
   map<int64_t,string> pool_name;
+  map<string,map<string,string> > erasure_code_profiles;
   map<string,int64_t> name_pool;
 
   ceph::shared_ptr< vector<uuid_d> > osd_uuid;
@@ -360,6 +375,31 @@ public:
     return (float)get_primary_affinity(o) / (float)CEPH_OSD_MAX_PRIMARY_AFFINITY;
   }
 
+  bool has_erasure_code_profile(const string &name) const {
+    map<string,map<string,string> >::const_iterator i =
+      erasure_code_profiles.find(name);
+    return i != erasure_code_profiles.end();
+  }
+  void set_erasure_code_profile(const string &name,
+				const map<string,string> &profile) {
+    erasure_code_profiles[name] = profile;
+  }
+  const map<string,string> &get_erasure_code_profile(const string &name) const {
+    map<string,map<string,string> >::const_iterator i =
+      erasure_code_profiles.find(name);
+    static map<string,string> empty;
+    if (i == erasure_code_profiles.end())
+      return empty;
+    else
+      return i->second;
+  }
+  map<string,string> &get_erasure_code_profile(const string &name) {
+    return erasure_code_profiles[name];
+  }
+  const map<string,map<string,string> > &get_erasure_code_profiles() const {
+    return erasure_code_profiles;
+  }
+
   bool exists(int osd) const {
     //assert(osd >= 0);
     return osd >= 0 && osd < max_osd && (osd_state[osd] & CEPH_OSD_EXISTS);
@@ -370,7 +410,7 @@ public:
   }
 
   bool is_down(int osd) const {
-    return !exists(osd) || !is_up(osd);
+    return !is_up(osd);
   }
 
   bool is_out(int osd) const {
@@ -378,7 +418,7 @@ public:
   }
 
   bool is_in(int osd) const {
-    return exists(osd) && !is_out(osd);
+    return !is_out(osd);
   }
 
   /**
@@ -778,6 +818,8 @@ public:
 
   string get_flag_string() const;
   static string get_flag_string(unsigned flags);
+  static void dump_erasure_code_profiles(const map<string,map<string,string> > &profiles,
+					 Formatter *f);
   void dump_json(ostream& out) const;
   void dump(Formatter *f) const;
   static void generate_test_instances(list<OSDMap*>& o);
diff --git a/src/osd/OpRequest.h b/src/osd/OpRequest.h
index 7e07340..569b6fc 100644
--- a/src/osd/OpRequest.h
+++ b/src/osd/OpRequest.h
@@ -31,12 +31,12 @@
  */
 struct osd_reqid_t {
   entity_name_t name; // who
-  tid_t         tid;
+  ceph_tid_t         tid;
   int32_t       inc;  // incarnation
 
   osd_reqid_t()
     : tid(0), inc(0) {}
-  osd_reqid_t(const entity_name_t& a, int i, tid_t t)
+  osd_reqid_t(const entity_name_t& a, int i, ceph_tid_t t)
     : name(a), tid(t), inc(i) {}
 
   void encode(bufferlist &bl) const;
diff --git a/src/osd/PG.cc b/src/osd/PG.cc
index 82b1bdd..49503ef 100644
--- a/src/osd/PG.cc
+++ b/src/osd/PG.cc
@@ -141,6 +141,15 @@ void PGPool::update(OSDMapRef map)
   } else {
     newly_removed_snaps.clear();
   }
+  lgeneric_subdout(g_ceph_context, osd, 20)
+    << "PGPool::update cached_removed_snaps "
+    << cached_removed_snaps
+    << " newly_removed_snaps "
+    << newly_removed_snaps
+    << " snapc " << snapc
+    << (pi->get_snap_epoch() == map->get_epoch() ?
+	" (updated)":" (no change)")
+    << dendl;
 }
 
 PG::PG(OSDService *o, OSDMapRef curmap,
@@ -625,7 +634,6 @@ void PG::generate_past_intervals()
 
   OSDMapRef last_map, cur_map;
   int primary = -1;
-  int old_primary = -1;
   vector<int> acting, up, old_acting, old_up;
 
   cur_map = osd->get_map(cur_epoch);
@@ -636,10 +644,10 @@ void PG::generate_past_intervals()
 	   << end_epoch << dendl;
   ++cur_epoch;
   for (; cur_epoch <= end_epoch; ++cur_epoch) {
+    int old_primary = primary;
     last_map.swap(cur_map);
     old_up.swap(up);
     old_acting.swap(acting);
-    old_primary = primary;
 
     cur_map = osd->get_map(cur_epoch);
     cur_map->pg_to_up_acting_osds(
@@ -1164,12 +1172,13 @@ bool PG::choose_acting(pg_shard_t &auth_log_shard_id)
       dout(10) << "choose_acting no suitable info found (incomplete backfills?),"
 	       << " reverting to up" << dendl;
       want_acting = up;
-      return true;
+      vector<int> empty;
+      osd->queue_want_pg_temp(info.pgid.pgid, empty);
     } else {
       dout(10) << "choose_acting failed" << dendl;
       assert(want_acting.empty());
-      return false;
     }
+    return false;
   }
 
   if ((up.size() &&
@@ -1437,6 +1446,8 @@ void PG::activate(ObjectStore::Transaction& t,
   
   // initialize snap_trimq
   if (is_primary()) {
+    dout(20) << "activate - purged_snaps " << info.purged_snaps
+	     << " cached_removed_snaps " << pool.cached_removed_snaps << dendl;
     snap_trimq = pool.cached_removed_snaps;
     snap_trimq.subtract(info.purged_snaps);
     dout(10) << "activate - snap_trimq " << snap_trimq << dendl;
@@ -2986,12 +2997,14 @@ void PG::reg_next_scrub()
   } else {
     scrubber.scrub_reg_stamp = info.history.last_scrub_stamp;
   }
-  osd->reg_last_pg_scrub(info.pgid, scrubber.scrub_reg_stamp);
+  if (is_primary())
+    osd->reg_last_pg_scrub(info.pgid, scrubber.scrub_reg_stamp);
 }
 
 void PG::unreg_next_scrub()
 {
-  osd->unreg_last_pg_scrub(info.pgid, scrubber.scrub_reg_stamp);
+  if (is_primary())
+    osd->unreg_last_pg_scrub(info.pgid, scrubber.scrub_reg_stamp);
 }
 
 void PG::sub_op_scrub_map(OpRequestRef op)
@@ -4609,6 +4622,8 @@ void PG::start_peering_interval(
   vector<int> oldacting, oldup;
   int oldrole = get_role();
 
+  unreg_next_scrub();
+
   pg_shard_t old_acting_primary = get_primary();
   pg_shard_t old_up_primary = up_primary;
   bool was_old_primary = is_primary();
@@ -4640,11 +4655,13 @@ void PG::start_peering_interval(
     state_clear(PG_STATE_REMAPPED);
 
   int role = osdmap->calc_pg_role(osd->whoami, acting, acting.size());
-  if (role == pg_whoami.shard)
+  if (pool.info.is_replicated() || role == pg_whoami.shard)
     set_role(role);
   else
     set_role(-1);
 
+  reg_next_scrub();
+
   // did acting, up, primary|acker change?
   if (!lastmap) {
     dout(10) << " no lastmap" << dendl;
@@ -5697,6 +5714,29 @@ PG::RecoveryState::WaitRemoteBackfillReserved::react(const RemoteReservationReje
 {
   PG *pg = context< RecoveryMachine >().pg;
   pg->osd->local_reserver.cancel_reservation(pg->info.pgid);
+
+  // Send REJECT to all previously acquired reservations
+  set<pg_shard_t>::const_iterator it, begin, end, next;
+  begin = context< Active >().sorted_backfill_set.begin();
+  end = context< Active >().sorted_backfill_set.end();
+  assert(begin != end);
+  for (next = it = begin, ++next ; next != backfill_osd_it; ++it, ++next) {
+    //The primary never backfills itself
+    assert(*it != pg->pg_whoami);
+    ConnectionRef con = pg->osd->get_con_osd_cluster(
+      it->osd, pg->get_osdmap()->get_epoch());
+    if (con) {
+      if (con->has_feature(CEPH_FEATURE_BACKFILL_RESERVATION)) {
+        pg->osd->send_message_osd_cluster(
+          new MBackfillReserve(
+	  MBackfillReserve::REJECT,
+	  spg_t(pg->info.pgid.pgid, it->shard),
+	  pg->get_osdmap()->get_epoch()),
+	con.get());
+      }
+    }
+  }
+
   pg->state_clear(PG_STATE_BACKFILL_WAIT);
   pg->state_set(PG_STATE_BACKFILL_TOOFULL);
 
@@ -5810,9 +5850,13 @@ boost::statechart::result
 PG::RecoveryState::RepNotRecovering::react(const RequestBackfillPrio &evt)
 {
   PG *pg = context< RecoveryMachine >().pg;
-
   double ratio, max_ratio;
-  if (pg->osd->too_full_for_backfill(&ratio, &max_ratio) &&
+
+  if (g_conf->osd_debug_reject_backfill_probability > 0 &&
+      (rand()%1000 < (g_conf->osd_debug_reject_backfill_probability*1000.0))) {
+    dout(10) << "backfill reservation rejected: failure injection" << dendl;
+    post_event(RemoteReservationRejected());
+  } else if (pg->osd->too_full_for_backfill(&ratio, &max_ratio) &&
       !pg->cct->_conf->osd_debug_skip_full_check_in_backfill_reservation) {
     dout(10) << "backfill reservation rejected: full ratio is "
 	     << ratio << ", which is greater than max allowed ratio "
diff --git a/src/osd/PG.h b/src/osd/PG.h
index 4c1b2cf..f6873ad 100644
--- a/src/osd/PG.h
+++ b/src/osd/PG.h
@@ -719,7 +719,7 @@ public:
 
   bool calc_min_last_complete_ondisk() {
     eversion_t min = last_complete_ondisk;
-    assert(actingbackfill.size() > 0);
+    assert(!actingbackfill.empty());
     for (set<pg_shard_t>::iterator i = actingbackfill.begin();
 	 i != actingbackfill.end();
 	 ++i) {
@@ -1650,6 +1650,7 @@ public:
     struct RepRecovering : boost::statechart::state< RepRecovering, ReplicaActive >, NamedState {
       typedef boost::mpl::list<
 	boost::statechart::transition< RecoveryDone, RepNotRecovering >,
+	boost::statechart::transition< RemoteReservationRejected, RepNotRecovering >,
 	boost::statechart::custom_reaction< BackfillTooFull >
 	> reactions;
       RepRecovering(my_context ctx);
diff --git a/src/osd/PGBackend.cc b/src/osd/PGBackend.cc
index 19f3d99..dad17f9 100644
--- a/src/osd/PGBackend.cc
+++ b/src/osd/PGBackend.cc
@@ -3,7 +3,10 @@
 /*
  * Ceph - scalable distributed file system
  *
- * Copyright (C) 2013 Inktank Storage, Inc.
+ * Copyright (C) 2013,2014 Inktank Storage, Inc.
+ * Copyright (C) 2013,2014 Cloudwatt <libre.licensing at cloudwatt.com>
+ *
+ * Author: Loic Dachary <loic at dachary.org>
  *
  * This is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -265,6 +268,7 @@ void PGBackend::trim_stashed_object(
 
 PGBackend *PGBackend::build_pg_backend(
   const pg_pool_t &pool,
+  const OSDMapRef curmap,
   Listener *l,
   coll_t coll,
   coll_t temp_coll,
@@ -277,11 +281,14 @@ PGBackend *PGBackend::build_pg_backend(
   }
   case pg_pool_t::TYPE_ERASURE: {
     ErasureCodeInterfaceRef ec_impl;
-    assert(pool.properties.count("erasure-code-plugin"));
+    const map<string,string> &profile = curmap->get_erasure_code_profile(pool.erasure_code_profile);
+    assert(profile.count("plugin"));
+    stringstream ss;
     ceph::ErasureCodePluginRegistry::instance().factory(
-      pool.properties.find("erasure-code-plugin")->second,
-      pool.properties,
-      &ec_impl);
+      profile.find("plugin")->second,
+      profile,
+      &ec_impl,
+      ss);
     assert(ec_impl);
     return new ECBackend(
       l,
diff --git a/src/osd/PGBackend.h b/src/osd/PGBackend.h
index d805782..bd18a47 100644
--- a/src/osd/PGBackend.h
+++ b/src/osd/PGBackend.h
@@ -3,7 +3,10 @@
 /*
  * Ceph - scalable distributed file system
  *
- * Copyright (C) 2013 Inktank Storage, Inc.
+ * Copyright (C) 2013,2014 Inktank Storage, Inc.
+ * Copyright (C) 2013,2014 Cloudwatt <libre.licensing at cloudwatt.com>
+ *
+ * Author: Loic Dachary <loic at dachary.org>
  *
  * This is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -157,6 +160,7 @@
      virtual bool pgb_is_primary() const = 0;
      virtual OSDMapRef pgb_get_osdmap() const = 0;
      virtual const pg_info_t &get_info() const = 0;
+     virtual const pg_pool_t &get_pool() const = 0;
 
      virtual ObjectContextRef get_obc(
        const hobject_t &hoid,
@@ -210,7 +214,7 @@
 
      virtual PerfCounters *get_logger() = 0;
 
-     virtual tid_t get_tid() = 0;
+     virtual ceph_tid_t get_tid() = 0;
 
      virtual LogClientTemp clog_error() = 0;
 
@@ -489,9 +493,9 @@
      const eversion_t &trim_to,           ///< [in] trim log to here
      vector<pg_log_entry_t> &log_entries, ///< [in] log entries for t
      Context *on_local_applied_sync,      ///< [in] called when applied locally
-     Context *on_all_applied,               ///< [in] called when all acked
+     Context *on_all_applied,             ///< [in] called when all acked
      Context *on_all_commit,              ///< [in] called when all commit
-     tid_t tid,                           ///< [in] tid
+     ceph_tid_t tid,                      ///< [in] tid
      osd_reqid_t reqid,                   ///< [in] reqid
      OpRequestRef op                      ///< [in] op
      ) = 0;
@@ -597,6 +601,7 @@
 
    static PGBackend *build_pg_backend(
      const pg_pool_t &pool,
+     const OSDMapRef curmap,
      Listener *l,
      coll_t coll,
      coll_t temp_coll,
diff --git a/src/osd/ReplicatedBackend.cc b/src/osd/ReplicatedBackend.cc
index 5a9e814..8856461 100644
--- a/src/osd/ReplicatedBackend.cc
+++ b/src/osd/ReplicatedBackend.cc
@@ -194,7 +194,7 @@ void ReplicatedBackend::clear_state()
 
 void ReplicatedBackend::_on_change(ObjectStore::Transaction *t)
 {
-  for (map<tid_t, InProgressOp>::iterator i = in_progress_ops.begin();
+  for (map<ceph_tid_t, InProgressOp>::iterator i = in_progress_ops.begin();
        i != in_progress_ops.end();
        in_progress_ops.erase(i++)) {
     if (i->second.on_commit)
@@ -497,7 +497,7 @@ void ReplicatedBackend::submit_transaction(
   Context *on_local_applied_sync,
   Context *on_all_acked,
   Context *on_all_commit,
-  tid_t tid,
+  ceph_tid_t tid,
   osd_reqid_t reqid,
   OpRequestRef orig_op)
 {
@@ -611,11 +611,11 @@ void ReplicatedBackend::sub_op_modify_reply(OpRequestRef op)
   op->mark_started();
 
   // must be replication.
-  tid_t rep_tid = r->get_tid();
+  ceph_tid_t rep_tid = r->get_tid();
   pg_shard_t from = r->from;
 
   if (in_progress_ops.count(rep_tid)) {
-    map<tid_t, InProgressOp>::iterator iter =
+    map<ceph_tid_t, InProgressOp>::iterator iter =
       in_progress_ops.find(rep_tid);
     InProgressOp &ip_op = iter->second;
     MOSDOp *m = NULL;
diff --git a/src/osd/ReplicatedBackend.h b/src/osd/ReplicatedBackend.h
index 64e91a6..cfad2ed 100644
--- a/src/osd/ReplicatedBackend.h
+++ b/src/osd/ReplicatedBackend.h
@@ -315,7 +315,7 @@ private:
    * Client IO
    */
   struct InProgressOp {
-    tid_t tid;
+    ceph_tid_t tid;
     set<pg_shard_t> waiting_for_commit;
     set<pg_shard_t> waiting_for_applied;
     Context *on_commit;
@@ -323,7 +323,7 @@ private:
     OpRequestRef op;
     eversion_t v;
     InProgressOp(
-      tid_t tid, Context *on_commit, Context *on_applied,
+      ceph_tid_t tid, Context *on_commit, Context *on_applied,
       OpRequestRef op, eversion_t v)
       : tid(tid), on_commit(on_commit), on_applied(on_applied),
 	op(op), v(v) {}
@@ -332,7 +332,7 @@ private:
 	waiting_for_applied.empty();
     }
   };
-  map<tid_t, InProgressOp> in_progress_ops;
+  map<ceph_tid_t, InProgressOp> in_progress_ops;
 public:
   PGTransaction *get_transaction();
   friend class C_OSD_OnOpCommit;
@@ -346,7 +346,7 @@ public:
     Context *on_local_applied_sync,
     Context *on_all_applied,
     Context *on_all_commit,
-    tid_t tid,
+    ceph_tid_t tid,
     osd_reqid_t reqid,
     OpRequestRef op
     );
@@ -355,7 +355,7 @@ private:
   void issue_op(
     const hobject_t &soid,
     const eversion_t &at_version,
-    tid_t tid,
+    ceph_tid_t tid,
     osd_reqid_t reqid,
     eversion_t pg_trim_to,
     hobject_t new_temp_oid,
diff --git a/src/osd/ReplicatedPG.cc b/src/osd/ReplicatedPG.cc
index f0987bf..1b798c1 100644
--- a/src/osd/ReplicatedPG.cc
+++ b/src/osd/ReplicatedPG.cc
@@ -4,7 +4,7 @@
  * Ceph - scalable distributed file system
  *
  * Copyright (C) 2004-2006 Sage Weil <sage at newdream.net>
- * Copyright (C) 2013 Cloudwatt <libre.licensing at cloudwatt.com>
+ * Copyright (C) 2013,2014 Cloudwatt <libre.licensing at cloudwatt.com>
  *
  * Author: Loic Dachary <loic at dachary.org>
  *
@@ -1033,7 +1033,7 @@ ReplicatedPG::ReplicatedPG(OSDService *o, OSDMapRef curmap,
   PG(o, curmap, _pool, p, oid, ioid),
   pgbackend(
     PGBackend::build_pg_backend(
-      _pool.info, this, coll_t(p), coll_t::make_temp_coll(p), o->store, cct)),
+      _pool.info, curmap, this, coll_t(p), coll_t::make_temp_coll(p), o->store, cct)),
   snapset_contexts_lock("ReplicatedPG::snapset_contexts"),
   temp_seq(0),
   snap_trimmer_machine(this)
@@ -1780,10 +1780,10 @@ void ReplicatedPG::execute_ctx(OpContext *ctx)
 
   // verify that we are doing this in order?
   if (cct->_conf->osd_debug_op_order && m->get_source().is_client()) {
-    map<client_t,tid_t>& cm = debug_op_order[obc->obs.oi.soid];
-    tid_t t = m->get_tid();
+    map<client_t,ceph_tid_t>& cm = debug_op_order[obc->obs.oi.soid];
+    ceph_tid_t t = m->get_tid();
     client_t n = m->get_source().num();
-    map<client_t,tid_t>::iterator p = cm.find(n);
+    map<client_t,ceph_tid_t>::iterator p = cm.find(n);
     if (p == cm.end()) {
       dout(20) << " op order client." << n << " tid " << t << " (first)" << dendl;
       cm[n] = t;
@@ -1798,7 +1798,7 @@ void ReplicatedPG::execute_ctx(OpContext *ctx)
   }
 
   // issue replica writes
-  tid_t rep_tid = osd->get_tid();
+  ceph_tid_t rep_tid = osd->get_tid();
   RepGather *repop = new_repop(ctx, obc, rep_tid);  // new repop claims our obc, src_obc refs
   // note: repop now owns ctx AND ctx->op
 
@@ -3247,7 +3247,7 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
 	  if (result < 0)
 	    break;
 	}
-	result = _delete_head(ctx, true);
+	result = _delete_oid(ctx, true);
 	osd->logger->inc(l_osd_tier_evict);
       }
       break;
@@ -3653,7 +3653,20 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
 	  ctx->mod_desc.create();
 	  t->append(soid, op.extent.offset, op.extent.length, osd_op.indata);
 	  if (obs.exists) {
-	    t->setattrs(soid, ctx->obc->attr_cache);
+	    map<string, bufferlist> to_set = ctx->obc->attr_cache;
+	    map<string, boost::optional<bufferlist> > &overlay =
+	      ctx->pending_attrs[ctx->obc];
+	    for (map<string, boost::optional<bufferlist> >::iterator i =
+		   overlay.begin();
+		 i != overlay.end();
+		 ++i) {
+	      if (i->second) {
+		to_set[i->first] = *(i->second);
+	      } else {
+		to_set.erase(i->first);
+	      }
+	    }
+	    t->setattrs(soid, to_set);
 	  }
 	} else {
 	  ctx->mod_desc.mark_unrollbackable();
@@ -3735,12 +3748,15 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
 	      }
 	    }
 	  }
-	  if (result >= 0 && !obs.exists) {
-	    ctx->mod_desc.create();
-	    t->touch(soid);
-	    ctx->delta_stats.num_objects++;
-	    obs.exists = true;
-	  }
+          if (result >= 0) {
+            if (!obs.exists)
+              ctx->mod_desc.create();
+            t->touch(soid);
+            if (!obs.exists) {
+              ctx->delta_stats.num_objects++;
+              obs.exists = true;
+            }
+          }
 	}
       }
       break;
@@ -3803,7 +3819,7 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
 	// Cannot delete an object with watchers
 	result = -EBUSY;
       } else {
-	result = _delete_head(ctx, false);
+	result = _delete_oid(ctx, false);
       }
       break;
 
@@ -4063,10 +4079,6 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
 
       // OMAP Read ops
     case CEPH_OSD_OP_OMAPGETKEYS:
-      if (pool.info.require_rollback()) {
-	result = -EOPNOTSUPP;
-	break;
-      }
       ++ctx->num_read;
       {
 	string start_after;
@@ -4081,7 +4093,7 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
 	}
 	set<string> out_set;
 
-	{
+	if (!pool.info.require_rollback()) {
 	  ObjectMap::ObjectMapIterator iter = osd->store->get_omap_iterator(
 	    coll, soid
 	    );
@@ -4092,7 +4104,7 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
 	       ++i, iter->next()) {
 	    out_set.insert(iter->key());
 	  }
-	}
+	} // else return empty out_set
 	::encode(out_set, osd_op.outdata);
 	ctx->delta_stats.num_rd_kb += SHIFT_ROUND_UP(osd_op.outdata.length(), 10);
 	ctx->delta_stats.num_rd++;
@@ -4100,10 +4112,6 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
       break;
 
     case CEPH_OSD_OP_OMAPGETVALS:
-      if (pool.info.require_rollback()) {
-	result = -EOPNOTSUPP;
-	break;
-      }
       ++ctx->num_read;
       {
 	string start_after;
@@ -4120,7 +4128,7 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
 	}
 	map<string, bufferlist> out_set;
 
-	{
+	if (!pool.info.require_rollback()) {
 	  ObjectMap::ObjectMapIterator iter = osd->store->get_omap_iterator(
 	    coll, soid
 	    );
@@ -4137,7 +4145,7 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
 	    dout(20) << "Found key " << iter->key() << dendl;
 	    out_set.insert(make_pair(iter->key(), iter->value()));
 	  }
-	}
+	} // else return empty out_set
 	::encode(out_set, osd_op.outdata);
 	ctx->delta_stats.num_rd_kb += SHIFT_ROUND_UP(osd_op.outdata.length(), 10);
 	ctx->delta_stats.num_rd++;
@@ -4146,7 +4154,7 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
 
     case CEPH_OSD_OP_OMAPGETHEADER:
       if (pool.info.require_rollback()) {
-	result = -EOPNOTSUPP;
+	// return empty header
 	break;
       }
       ++ctx->num_read;
@@ -4158,10 +4166,6 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
       break;
 
     case CEPH_OSD_OP_OMAPGETVALSBYKEYS:
-      if (pool.info.require_rollback()) {
-	result = -EOPNOTSUPP;
-	break;
-      }
       ++ctx->num_read;
       {
 	set<string> keys_to_get;
@@ -4173,7 +4177,9 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
 	  goto fail;
 	}
 	map<string, bufferlist> out;
-	osd->store->omap_get_values(coll, soid, keys_to_get, &out);
+	if (!pool.info.require_rollback()) {
+	  osd->store->omap_get_values(coll, soid, keys_to_get, &out);
+	} // else return empty omap entries
 	::encode(out, osd_op.outdata);
 	ctx->delta_stats.num_rd_kb += SHIFT_ROUND_UP(osd_op.outdata.length(), 10);
 	ctx->delta_stats.num_rd++;
@@ -4181,10 +4187,6 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
       break;
 
     case CEPH_OSD_OP_OMAP_CMP:
-      if (pool.info.require_rollback()) {
-	result = -EOPNOTSUPP;
-	break;
-      }
       ++ctx->num_read;
       {
 	if (!obs.exists || oi.is_whiteout()) {
@@ -4201,20 +4203,24 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
 	}
 	
 	map<string, bufferlist> out;
-	set<string> to_get;
-	for (map<string, pair<bufferlist, int> >::iterator i = assertions.begin();
-	     i != assertions.end();
-	     ++i)
-	  to_get.insert(i->first);
-	int r = osd->store->omap_get_values(coll, soid, to_get, &out);
-	if (r < 0) {
-	  result = r;
-	  break;
-	}
+
+	if (!pool.info.require_rollback()) {
+	  set<string> to_get;
+	  for (map<string, pair<bufferlist, int> >::iterator i = assertions.begin();
+	       i != assertions.end();
+	       ++i)
+	    to_get.insert(i->first);
+	  int r = osd->store->omap_get_values(coll, soid, to_get, &out);
+	  if (r < 0) {
+	    result = r;
+	    break;
+	  }
+	} // else leave out empty
+
 	//Should set num_rd_kb based on encode length of map
 	ctx->delta_stats.num_rd++;
 
-	r = 0;
+	int r = 0;
 	bufferlist empty;
 	for (map<string, pair<bufferlist, int> >::iterator i = assertions.begin();
 	     i != assertions.end();
@@ -4470,7 +4476,7 @@ int ReplicatedPG::_verify_no_head_clones(const hobject_t& soid,
   return 0;
 }
 
-inline int ReplicatedPG::_delete_head(OpContext *ctx, bool no_whiteout)
+inline int ReplicatedPG::_delete_oid(OpContext *ctx, bool no_whiteout)
 {
   SnapSet& snapset = ctx->new_snapset;
   ObjectState& obs = ctx->new_obs;
@@ -4519,7 +4525,8 @@ inline int ReplicatedPG::_delete_head(OpContext *ctx, bool no_whiteout)
     dout(20) << __func__ << " deleting whiteout on " << soid << dendl;
     ctx->delta_stats.num_whiteouts--;
   }
-  snapset.head_exists = false;
+  if (soid.is_head())
+    snapset.head_exists = false;
   obs.exists = false;
   return 0;
 }
@@ -4564,7 +4571,7 @@ int ReplicatedPG::_rollback_to(OpContext *ctx, ceph_osd_op& op)
       // Cannot delete an object with watchers
       ret = -EBUSY;
     } else {
-      _delete_head(ctx, false);
+      _delete_oid(ctx, false);
       ret = 0;
     }
   } else if (ret) {
@@ -4719,6 +4726,8 @@ void ReplicatedPG::make_writeable(OpContext *ctx)
       ctx->clone_obc->destructor_callback = new C_PG_ObjectContext(this, ctx->clone_obc.get());
       ctx->clone_obc->obs.oi = static_snap_oi;
       ctx->clone_obc->obs.exists = true;
+      ctx->clone_obc->ssc = ctx->obc->ssc;
+      ctx->clone_obc->ssc->ref++;
       if (pool.info.require_rollback())
 	ctx->clone_obc->attr_cache = ctx->obc->attr_cache;
       snap_oi = &ctx->clone_obc->obs.oi;
@@ -5090,6 +5099,9 @@ void ReplicatedPG::finish_ctx(OpContext *ctx, int log_op_type)
 	changing.insert(OI_ATTR);
 	changing.insert(SS_ATTR);
 	ctx->obc->fill_in_setattrs(changing, &(ctx->mod_desc));
+      } else {
+	// replicated pools are never rollbackable in this case
+	ctx->mod_desc.mark_unrollbackable();
       }
     } else {
       dout(10) << " no snapset (this is a clone)" << dendl;
@@ -5182,7 +5194,7 @@ struct C_Copyfrom : public Context {
   ReplicatedPGRef pg;
   hobject_t oid;
   epoch_t last_peering_reset;
-  tid_t tid;
+  ceph_tid_t tid;
   C_Copyfrom(ReplicatedPG *p, hobject_t o, epoch_t lpr)
     : pg(p), oid(o), last_peering_reset(lpr),
       tid(0)
@@ -5202,9 +5214,15 @@ struct C_CopyFrom_AsyncReadCb : public Context {
   OSDOp *osd_op;
   object_copy_data_t reply_obj;
   bool classic;
+  size_t len;
   C_CopyFrom_AsyncReadCb(OSDOp *osd_op, bool classic) :
-    osd_op(osd_op), classic(classic) {}
+    osd_op(osd_op), classic(classic), len(0) {}
   void finish(int r) {
+    assert(len > 0);
+    assert(len <= reply_obj.data.length());
+    bufferlist bl;
+    bl.substr_of(reply_obj.data, 0, len);
+    reply_obj.data.swap(bl);
     if (classic) {
       reply_obj.encode_classic(osd_op->outdata);
     } else {
@@ -5282,6 +5300,7 @@ int ReplicatedPG::fill_in_copy_get(
 	    make_pair(cursor.data_offset, left),
 	    make_pair(&bl, cb)));
 	result = MIN(oi.size - cursor.data_offset, (uint64_t)left);
+	cb->len = result;
       } else {
 	result = pgbackend->objects_read_sync(
 	  oi.soid, cursor.data_offset, left, &bl);
@@ -5400,7 +5419,7 @@ void ReplicatedPG::_copy_some(ObjectContextRef obc, CopyOpRef cop)
     ObjectOperation op;
     op.list_snaps(&cop->results.snapset, NULL);
     osd->objecter_lock.Lock();
-    tid_t tid = osd->objecter->read(cop->src.oid, cop->oloc, op,
+    ceph_tid_t tid = osd->objecter->read(cop->src.oid, cop->oloc, op,
 				    CEPH_SNAPDIR, NULL,
 				    flags, gather.new_sub(), NULL);
     cop->objecter_tid2 = tid;
@@ -5428,7 +5447,7 @@ void ReplicatedPG::_copy_some(ObjectContextRef obc, CopyOpRef cop)
 				       &osd->objecter_finisher));
 
   osd->objecter_lock.Lock();
-  tid_t tid = osd->objecter->read(cop->src.oid, cop->oloc, op,
+  ceph_tid_t tid = osd->objecter->read(cop->src.oid, cop->oloc, op,
 				  cop->src.snap, NULL,
 				  flags,
 				  gather.new_sub(),
@@ -5440,7 +5459,7 @@ void ReplicatedPG::_copy_some(ObjectContextRef obc, CopyOpRef cop)
   osd->objecter_lock.Unlock();
 }
 
-void ReplicatedPG::process_copy_chunk(hobject_t oid, tid_t tid, int r)
+void ReplicatedPG::process_copy_chunk(hobject_t oid, ceph_tid_t tid, int r)
 {
   dout(10) << __func__ << " " << oid << " tid " << tid
 	   << " " << cpp_strerror(r) << dendl;
@@ -5852,7 +5871,7 @@ struct C_Flush : public Context {
   ReplicatedPGRef pg;
   hobject_t oid;
   epoch_t last_peering_reset;
-  tid_t tid;
+  ceph_tid_t tid;
   C_Flush(ReplicatedPG *p, hobject_t o, epoch_t lpr)
     : pg(p), oid(o), last_peering_reset(lpr),
       tid(0)
@@ -5979,7 +5998,7 @@ int ReplicatedPG::start_flush(OpContext *ctx, bool blocking)
   }
 
   osd->objecter_lock.Lock();
-  tid_t tid = osd->objecter->mutate(soid.oid, base_oloc, o, snapc, oi.mtime,
+  ceph_tid_t tid = osd->objecter->mutate(soid.oid, base_oloc, o, snapc, oi.mtime,
 				    CEPH_OSD_FLAG_IGNORE_OVERLAY,
 				    NULL,
 				    new C_OnFinisher(fin,
@@ -5992,7 +6011,7 @@ int ReplicatedPG::start_flush(OpContext *ctx, bool blocking)
   return -EINPROGRESS;
 }
 
-void ReplicatedPG::finish_flush(hobject_t oid, tid_t tid, int r)
+void ReplicatedPG::finish_flush(hobject_t oid, ceph_tid_t tid, int r)
 {
   dout(10) << __func__ << " " << oid << " tid " << tid
 	   << " " << cpp_strerror(r) << dendl;
@@ -6088,7 +6107,7 @@ int ReplicatedPG::try_flush_mark_clean(FlushOpRef fop)
   }
 
   dout(10) << __func__ << " clearing DIRTY flag for " << oid << dendl;
-  tid_t rep_tid = osd->get_tid();
+  ceph_tid_t rep_tid = osd->get_tid();
   RepGather *repop = new_repop(fop->ctx, obc, rep_tid);
   OpContext *ctx = fop->ctx;
   if (!fop->blocking) {
@@ -6449,7 +6468,7 @@ void ReplicatedPG::issue_repop(RepGather *repop, utime_t now)
 void ReplicatedBackend::issue_op(
   const hobject_t &soid,
   const eversion_t &at_version,
-  tid_t tid,
+  ceph_tid_t tid,
   osd_reqid_t reqid,
   eversion_t pg_trim_to,
   hobject_t new_temp_oid,
@@ -6516,7 +6535,7 @@ void ReplicatedBackend::issue_op(
 }
 
 ReplicatedPG::RepGather *ReplicatedPG::new_repop(OpContext *ctx, ObjectContextRef obc,
-						 tid_t rep_tid)
+						 ceph_tid_t rep_tid)
 {
   if (ctx->op)
     dout(10) << "new_repop rep_tid " << rep_tid << " on " << *ctx->op->get_req() << dendl;
@@ -6551,7 +6570,7 @@ ReplicatedPG::RepGather *ReplicatedPG::simple_repop_create(ObjectContextRef obc)
 {
   dout(20) << __func__ << " " << obc->obs.oi.soid << dendl;
   vector<OSDOp> ops;
-  tid_t rep_tid = osd->get_tid();
+  ceph_tid_t rep_tid = osd->get_tid();
   osd_reqid_t reqid(osd->get_cluster_msgr_name(), 0, rep_tid);
   OpContext *ctx = new OpContext(OpRequestRef(), reqid, ops,
 				 &obc->obs, obc->ssc, this);
@@ -6695,7 +6714,7 @@ void ReplicatedPG::handle_watch_timeout(WatchRef watch)
   watch->remove();
 
   vector<OSDOp> ops;
-  tid_t rep_tid = osd->get_tid();
+  ceph_tid_t rep_tid = osd->get_tid();
   osd_reqid_t reqid(osd->get_cluster_msgr_name(), 0, rep_tid);
   OpContext *ctx = new OpContext(OpRequestRef(), reqid, ops,
 				 &obc->obs, obc->ssc, this);
@@ -7310,6 +7329,11 @@ void ReplicatedBackend::calc_head_subsets(
   if (size)
     data_subset.insert(0, size);
 
+  if (get_parent()->get_pool().cache_mode != pg_pool_t::CACHEMODE_NONE) {
+    dout(10) << __func__ << ": caching enabled, skipping clone subsets" << dendl;
+    return;
+  }
+
   if (!cct->_conf->osd_recover_clone_overlap) {
     dout(10) << "calc_head_subsets " << head << " -- osd_recover_clone_overlap disabled" << dendl;
     return;
@@ -7365,6 +7389,11 @@ void ReplicatedBackend::calc_clone_subsets(
   if (size)
     data_subset.insert(0, size);
 
+  if (get_parent()->get_pool().cache_mode != pg_pool_t::CACHEMODE_NONE) {
+    dout(10) << __func__ << ": caching enabled, skipping clone subsets" << dendl;
+    return;
+  }
+
   if (!cct->_conf->osd_recover_clone_overlap) {
     dout(10) << "calc_clone_subsets " << soid << " -- osd_recover_clone_overlap disabled" << dendl;
     return;
@@ -7606,7 +7635,7 @@ int ReplicatedPG::recover_missing(
 void ReplicatedPG::send_remove_op(
   const hobject_t& oid, eversion_t v, pg_shard_t peer)
 {
-  tid_t tid = osd->get_tid();
+  ceph_tid_t tid = osd->get_tid();
   osd_reqid_t rid(osd->get_cluster_msgr_name(), 0, tid);
 
   dout(10) << "send_remove_op " << oid << " from osd." << peer
@@ -7739,7 +7768,7 @@ int ReplicatedBackend::send_pull_legacy(int prio, pg_shard_t peer,
 					ObjectRecoveryProgress progress)
 {
   // send op
-  tid_t tid = get_parent()->get_tid();
+  ceph_tid_t tid = get_parent()->get_tid();
   osd_reqid_t rid(get_parent()->get_cluster_msgr_name(), 0, tid);
 
   dout(10) << "send_pull_op " << recovery_info.soid << " "
@@ -8191,7 +8220,7 @@ int ReplicatedBackend::build_push_op(const ObjectRecoveryInfo &recovery_info,
 
 int ReplicatedBackend::send_push_op_legacy(int prio, pg_shard_t peer, PushOp &pop)
 {
-  tid_t tid = get_parent()->get_tid();
+  ceph_tid_t tid = get_parent()->get_tid();
   osd_reqid_t rid(get_parent()->get_cluster_msgr_name(), 0, tid);
   MOSDSubOp *subop = new MOSDSubOp(
     rid, parent->whoami_shard(),
@@ -10361,6 +10390,26 @@ void ReplicatedPG::hit_set_persist()
   if (is_degraded_object(oid))
     return;
 
+  // If backfill is in progress and we could possibly overlap with the
+  // hit_set_* objects, back off.  Since these all have
+  // hobject_t::hash set to pgid.ps(), and those sort first, we can
+  // look just at that.  This is necessary because our transactions
+  // may include a modify of the new hit_set *and* a delete of the
+  // old one, and this may span the backfill boundary.
+  for (set<pg_shard_t>::iterator p = backfill_targets.begin();
+       p != backfill_targets.end();
+       ++p) {
+    assert(peer_info.count(*p));
+    const pg_info_t& pi = peer_info[*p];
+    if (pi.last_backfill == hobject_t() ||
+	pi.last_backfill.hash == info.pgid.ps()) {
+      dout(10) << __func__ << " backfill target osd." << *p
+	       << " last_backfill has not progressed past pgid ps"
+	       << dendl;
+      return;
+    }
+  }
+
   if (!info.hit_set.current_info.begin)
     info.hit_set.current_info.begin = hit_set_start_stamp;
 
@@ -10747,7 +10796,7 @@ bool ReplicatedPG::agent_maybe_flush(ObjectContextRef& obc)
   // ages we expect.
 
   vector<OSDOp> ops;
-  tid_t rep_tid = osd->get_tid();
+  ceph_tid_t rep_tid = osd->get_tid();
   osd_reqid_t reqid(osd->get_cluster_msgr_name(), 0, rep_tid);
   OpContext *ctx = new OpContext(OpRequestRef(), reqid, ops,
 				 &obc->obs, obc->ssc, this);
@@ -10834,7 +10883,7 @@ bool ReplicatedPG::agent_maybe_evict(ObjectContextRef& obc)
   OpContext *ctx = repop->ctx;
   ctx->at_version = get_next_version();
   assert(ctx->new_obs.exists);
-  int r = _delete_head(ctx, true);
+  int r = _delete_oid(ctx, true);
   assert(r == 0);
   finish_ctx(ctx, pg_log_entry_t::DELETE);
   simple_repop_submit(repop);
@@ -11031,6 +11080,7 @@ void ReplicatedPG::_scrub(ScrubMap& scrubmap)
   hobject_t head;
   SnapSet snapset;
   vector<snapid_t>::reverse_iterator curclone;
+  hobject_t next_clone;
 
   bufferlist last_data;
 
@@ -11057,7 +11107,8 @@ void ReplicatedPG::_scrub(ScrubMap& scrubmap)
       ::decode(snapset, blp);
 
       // did we finish the last oid?
-      if (head != hobject_t()) {
+      if (head != hobject_t() &&
+	  pool.info.cache_mode == pg_pool_t::CACHEMODE_NONE) {
 	osd->clog.error() << mode << " " << info.pgid << " " << head
 			  << " missing clones";
         ++scrubber.shallow_errors;
@@ -11069,6 +11120,7 @@ void ReplicatedPG::_scrub(ScrubMap& scrubmap)
       else {
 	curclone = snapset.clones.rbegin();
 	head = p->first;
+	next_clone = hobject_t();
 	dout(20) << "  snapset " << snapset << dendl;
       }
 
@@ -11083,11 +11135,6 @@ void ReplicatedPG::_scrub(ScrubMap& scrubmap)
 	}	  
       }
     }
-    if (soid.snap == CEPH_SNAPDIR) {
-      string cat;
-      scrub_cstat.add(stat, cat);
-      continue;
-    }
 
     // basic checks.
     if (p->second.attrs.count(OI_ATTR) == 0) {
@@ -11114,22 +11161,60 @@ void ReplicatedPG::_scrub(ScrubMap& scrubmap)
 
     stat.num_bytes += oi.size;
 
-    if (oi.is_dirty())
-      ++stat.num_objects_dirty;
-    if (oi.is_whiteout())
-      ++stat.num_whiteouts;
+    if (!soid.is_snapdir()) {
+      if (oi.is_dirty())
+	++stat.num_objects_dirty;
+      if (oi.is_whiteout())
+	++stat.num_whiteouts;
+    }
 
     //bufferlist data;
     //osd->store->read(c, poid, 0, 0, data);
     //assert(data.length() == p->size);
     //
 
-    if (soid.snap == CEPH_NOSNAP) {
-      if (!snapset.head_exists) {
+    if (!next_clone.is_min() && next_clone != soid &&
+	pool.info.cache_mode != pg_pool_t::CACHEMODE_NONE) {
+      // it is okay to be missing one or more clones in a cache tier.
+      // skip higher-numbered clones in the list.
+      while (curclone != snapset.clones.rend() &&
+	     soid.snap < *curclone)
+	++curclone;
+      if (curclone != snapset.clones.rend() &&
+	  soid.snap == *curclone) {
+	dout(20) << __func__ << " skipped some clones in cache tier" << dendl;
+	next_clone.snap = *curclone;
+      }
+      if (curclone == snapset.clones.rend() ||
+	  soid.snap == CEPH_NOSNAP) {
+	dout(20) << __func__ << " skipped remaining clones in cache tier"
+		 << dendl;
+	next_clone = hobject_t();
+	head = hobject_t();
+      }
+    }
+    if (!next_clone.is_min() && next_clone != soid) {
+      osd->clog.error() << mode << " " << info.pgid << " " << soid
+			<< " expected clone " << next_clone;
+      ++scrubber.shallow_errors;
+    }
+
+    if (soid.snap == CEPH_NOSNAP || soid.snap == CEPH_SNAPDIR) {
+      if (soid.snap == CEPH_NOSNAP && !snapset.head_exists) {
 	osd->clog.error() << mode << " " << info.pgid << " " << soid
-			  << " snapset.head_exists=false, but object exists";
+			  << " snapset.head_exists=false, but head exists";
         ++scrubber.shallow_errors;
-	continue;
+      }
+      if (soid.snap == CEPH_SNAPDIR && snapset.head_exists) {
+	osd->clog.error() << mode << " " << info.pgid << " " << soid
+			  << " snapset.head_exists=true, but snapdir exists";
+        ++scrubber.shallow_errors;
+      }
+      if (curclone == snapset.clones.rend()) {
+	next_clone = hobject_t();
+      } else {
+	next_clone = soid;
+	next_clone.snap = *curclone;
       }
     } else if (soid.snap) {
       // it's a clone
@@ -11143,31 +11228,45 @@ void ReplicatedPG::_scrub(ScrubMap& scrubmap)
       }
 
       if (soid.snap != *curclone) {
-	osd->clog.error() << mode << " " << info.pgid << " " << soid
-			  << " expected clone " << *curclone;
-        ++scrubber.shallow_errors;
-	assert(soid.snap == *curclone);
+	continue; // we warn above.  we could do better here...
       }
 
-      assert(oi.size == snapset.clone_size[*curclone]);
+      if (oi.size != snapset.clone_size[*curclone]) {
+	osd->clog.error() << mode << " " << info.pgid << " " << soid
+			  << " size " << oi.size << " != clone_size "
+			  << snapset.clone_size[*curclone];
+	++scrubber.shallow_errors;
+      }
 
       // verify overlap?
       // ...
 
       // what's next?
-      if (curclone != snapset.clones.rend())
+      if (curclone != snapset.clones.rend()) {
 	++curclone;
-
-      if (curclone == snapset.clones.rend())
+      }
+      if (curclone == snapset.clones.rend()) {
 	head = hobject_t();
+	next_clone = hobject_t();
+      } else {
+	next_clone.snap = *curclone;
+      }
 
     } else {
       // it's unversioned.
+      next_clone = hobject_t();
     }
 
     string cat; // fixme
     scrub_cstat.add(stat, cat);
   }
+
+  if (!next_clone.is_min() &&
+      pool.info.cache_mode == pg_pool_t::CACHEMODE_NONE) {
+    osd->clog.error() << mode << " " << info.pgid
+		      << " expected clone " << next_clone;
+    ++scrubber.shallow_errors;
+  }
   
   dout(10) << "_scrub (" << mode << ") finish" << dendl;
 }
diff --git a/src/osd/ReplicatedPG.h b/src/osd/ReplicatedPG.h
index 4ddd8d0..4d6000d 100644
--- a/src/osd/ReplicatedPG.h
+++ b/src/osd/ReplicatedPG.h
@@ -124,8 +124,8 @@ public:
     bool mirror_snapset;
     map<string, bufferlist> attrs; ///< src user attrs
     CopyResults() : object_size(0), started_temp_obj(false),
-		    user_version(0), should_requeue(false),
-		    mirror_snapset(false) {}
+		    final_tx(NULL), user_version(0), 
+		    should_requeue(false), mirror_snapset(false) {}
   };
 
   struct CopyOp {
@@ -138,8 +138,8 @@ public:
 
     CopyResults results;
 
-    tid_t objecter_tid;
-    tid_t objecter_tid2;
+    ceph_tid_t objecter_tid;
+    ceph_tid_t objecter_tid2;
 
     object_copy_cursor_t cursor;
     map<string,bufferlist> attrs;
@@ -199,7 +199,7 @@ public:
     OpContext *ctx;             ///< the parent OpContext
     list<OpRequestRef> dup_ops; ///< dup flush requests
     version_t flushed_version;  ///< user version we are flushing
-    tid_t objecter_tid;         ///< copy-from request tid
+    ceph_tid_t objecter_tid;    ///< copy-from request tid
     int rval;                   ///< copy-from result
     bool blocking;              ///< whether we are blocking updates
     bool removal;               ///< we are removing the backend object
@@ -329,6 +329,9 @@ public:
   const pg_info_t &get_info() const {
     return info;
   }
+  const pg_pool_t &get_pool() const {
+    return pool.info;
+  }
   ObjectContextRef get_obc(
     const hobject_t &hoid,
     map<string, bufferlist> &attrs) {
@@ -400,7 +403,7 @@ public:
 
   PerfCounters *get_logger();
 
-  tid_t get_tid() { return osd->get_tid(); }
+  ceph_tid_t get_tid() { return osd->get_tid(); }
 
   LogClientTemp clog_error() { return osd->clog.error(); }
 
@@ -585,7 +588,7 @@ public:
     ObjectContextRef obc;
     map<hobject_t,ObjectContextRef> src_obc;
 
-    tid_t rep_tid;
+    ceph_tid_t rep_tid;
 
     bool rep_aborted, rep_done;
 
@@ -603,7 +606,7 @@ public:
 
     Context *on_applied;
     
-    RepGather(OpContext *c, ObjectContextRef pi, tid_t rt, 
+    RepGather(OpContext *c, ObjectContextRef pi, ceph_tid_t rt,
 	      eversion_t lc) :
       queue_item(this),
       nref(1),
@@ -729,7 +732,7 @@ protected:
   // replica ops
   // [primary|tail]
   xlist<RepGather*> repop_queue;
-  map<tid_t, RepGather*> repop_map;
+  map<ceph_tid_t, RepGather*> repop_map;
 
   friend class C_OSD_RepopApplied;
   friend class C_OSD_RepopCommit;
@@ -737,7 +740,7 @@ protected:
   void repop_all_committed(RepGather *repop);
   void eval_repop(RepGather*);
   void issue_repop(RepGather *repop, utime_t now);
-  RepGather *new_repop(OpContext *ctx, ObjectContextRef obc, tid_t rep_tid);
+  RepGather *new_repop(OpContext *ctx, ObjectContextRef obc, ceph_tid_t rep_tid);
   void remove_repop(RepGather *repop);
 
   RepGather *simple_repop_create(ObjectContextRef obc);
@@ -828,7 +831,7 @@ protected:
   Mutex snapset_contexts_lock;
 
   // debug order that client ops are applied
-  map<hobject_t, map<client_t, tid_t> > debug_op_order;
+  map<hobject_t, map<client_t, ceph_tid_t> > debug_op_order;
 
   void populate_obc_watchers(ObjectContextRef obc);
   void check_blacklisted_obc_watchers(ObjectContextRef obc);
@@ -1155,7 +1158,7 @@ protected:
   void start_copy(CopyCallback *cb, ObjectContextRef obc, hobject_t src,
 		  object_locator_t oloc, version_t version, unsigned flags,
 		  bool mirror_snapset);
-  void process_copy_chunk(hobject_t oid, tid_t tid, int r);
+  void process_copy_chunk(hobject_t oid, ceph_tid_t tid, int r);
   void _write_copy_chunk(CopyOpRef cop, PGBackend::PGTransaction *t);
   uint64_t get_copy_chunk_size() const {
     uint64_t size = cct->_conf->osd_copyfrom_max_chunk;
@@ -1182,7 +1185,7 @@ protected:
   map<hobject_t, FlushOpRef> flush_ops;
 
   int start_flush(OpContext *ctx, bool blocking);
-  void finish_flush(hobject_t oid, tid_t tid, int r);
+  void finish_flush(hobject_t oid, ceph_tid_t tid, int r);
   int try_flush_mark_clean(FlushOpRef fop);
   void cancel_flush(FlushOpRef fop, bool requeue);
   void cancel_flush_ops(bool requeue);
@@ -1316,7 +1319,7 @@ private:
 
   int _verify_no_head_clones(const hobject_t& soid,
 			     const SnapSet& ss);
-  int _delete_head(OpContext *ctx, bool no_whiteout);
+  int _delete_oid(OpContext *ctx, bool no_whiteout);
   int _rollback_to(OpContext *ctx, ceph_osd_op& op);
 public:
   bool same_for_read_since(epoch_t e);
diff --git a/src/osd/Watch.cc b/src/osd/Watch.cc
index ffa3adc..4ef4bd1 100644
--- a/src/osd/Watch.cc
+++ b/src/osd/Watch.cc
@@ -261,7 +261,7 @@ Watch::Watch(
   uint32_t timeout,
   uint64_t cookie,
   entity_name_t entity,
-  entity_addr_t addr)
+  const entity_addr_t &addr)
   : cb(NULL),
     osd(osd),
     pg(pg),
@@ -418,7 +418,7 @@ void Watch::notify_ack(uint64_t notify_id)
 
 WatchRef Watch::makeWatchRef(
   ReplicatedPG *pg, OSDService *osd,
-  ObjectContextRef obc, uint32_t timeout, uint64_t cookie, entity_name_t entity, entity_addr_t addr)
+  ObjectContextRef obc, uint32_t timeout, uint64_t cookie, entity_name_t entity, const entity_addr_t& addr)
 {
   WatchRef ret(new Watch(pg, osd, obc, timeout, cookie, entity, addr));
   ret->set_self(ret);
diff --git a/src/osd/Watch.h b/src/osd/Watch.h
index 8e98c9d..e2cbfc1 100644
--- a/src/osd/Watch.h
+++ b/src/osd/Watch.h
@@ -167,7 +167,7 @@ class Watch {
     ReplicatedPG *pg, OSDService *osd,
     ceph::shared_ptr<ObjectContext> obc, uint32_t timeout,
     uint64_t cookie, entity_name_t entity,
-    entity_addr_t addr);
+    const entity_addr_t& addr);
 
   /// Registers the timeout callback with watch_timer
   void register_cb();
@@ -187,7 +187,7 @@ public:
   string gen_dbg_prefix();
   static WatchRef makeWatchRef(
     ReplicatedPG *pg, OSDService *osd,
-    ceph::shared_ptr<ObjectContext> obc, uint32_t timeout, uint64_t cookie, entity_name_t entity, entity_addr_t addr);
+    ceph::shared_ptr<ObjectContext> obc, uint32_t timeout, uint64_t cookie, entity_name_t entity, const entity_addr_t &addr);
   void set_self(WatchRef _self) {
     self = _self;
   }
diff --git a/src/osd/osd_types.cc b/src/osd/osd_types.cc
index 9e6a8f6..c183dca 100644
--- a/src/osd/osd_types.cc
+++ b/src/osd/osd_types.cc
@@ -4,6 +4,9 @@
  * Ceph - scalable distributed file system
  *
  * Copyright (C) 2011 New Dream Network
+ * Copyright (C) 2013,2014 Cloudwatt <libre.licensing at cloudwatt.com>
+ *
+ * Author: Loic Dachary <loic at dachary.org>
  *
  * This is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -433,6 +436,7 @@ unsigned pg_t::get_split_bits(unsigned pg_num) const {
 
   // Find unique p such that pg_num \in [2^(p-1), 2^p)
   unsigned p = pg_pool_t::calc_bits_of(pg_num);
+  assert(p); // silence coverity #751330 
 
   if ((m_seed % (1<<(p-1))) < (pg_num % (1<<(p-1))))
     return p;
@@ -781,14 +785,7 @@ void pg_pool_t::dump(Formatter *f) const
 		   cache_target_full_ratio_micro);
   f->dump_unsigned("cache_min_flush_age", cache_min_flush_age);
   f->dump_unsigned("cache_min_evict_age", cache_min_evict_age);
-  f->open_object_section("properties");
-  for (map<string,string>::const_iterator i = properties.begin();
-       i != properties.end();
-       ++i) {
-    string name = i->first;
-    f->dump_string(name.c_str(), i->second);
-  }
-  f->close_section();
+  f->dump_string("erasure_code_profile", erasure_code_profile);
   f->open_object_section("hit_set_params");
   hit_set_params.dump(f);
   f->close_section(); // hit_set_params
@@ -1046,7 +1043,7 @@ void pg_pool_t::encode(bufferlist& bl, uint64_t features) const
   }
 
   __u8 encode_compat = 5;
-  ENCODE_START(13, encode_compat, bl);
+  ENCODE_START(14, encode_compat, bl);
   ::encode(type, bl);
   ::encode(size, bl);
   ::encode(crush_ruleset, bl);
@@ -1074,8 +1071,6 @@ void pg_pool_t::encode(bufferlist& bl, uint64_t features) const
   ::encode(read_tier, bl);
   ::encode(write_tier, bl);
   ::encode(properties, bl);
-  if (hit_set_params.get_type() != HitSet::TYPE_NONE)
-    encode_compat = MAX(encode_compat, 11); // need to be able to understand all the data!
   ::encode(hit_set_params, bl);
   ::encode(hit_set_period, bl);
   ::encode(hit_set_count, bl);
@@ -1086,12 +1081,13 @@ void pg_pool_t::encode(bufferlist& bl, uint64_t features) const
   ::encode(cache_target_full_ratio_micro, bl);
   ::encode(cache_min_flush_age, bl);
   ::encode(cache_min_evict_age, bl);
-  ENCODE_FINISH_NEW_COMPAT(bl, encode_compat);
+  ::encode(erasure_code_profile, bl);
+  ENCODE_FINISH(bl);
 }
 
 void pg_pool_t::decode(bufferlist::iterator& bl)
 {
-  DECODE_START_LEGACY_COMPAT_LEN(13, 5, 5, bl);
+  DECODE_START_LEGACY_COMPAT_LEN(14, 5, 5, bl);
   ::decode(type, bl);
   ::decode(size, bl);
   ::decode(crush_ruleset, bl);
@@ -1185,6 +1181,9 @@ void pg_pool_t::decode(bufferlist::iterator& bl)
     cache_min_flush_age = 0;
     cache_min_evict_age = 0;
   }
+  if (struct_v >= 14) {
+    ::decode(erasure_code_profile, bl);
+  }
 
   DECODE_FINISH(bl);
   calc_pg_masks();
@@ -1227,8 +1226,6 @@ void pg_pool_t::generate_test_instances(list<pg_pool_t*>& o)
   a.cache_mode = CACHEMODE_WRITEBACK;
   a.read_tier = 1;
   a.write_tier = 1;
-  a.properties["p-1"] = "v-1";
-  a.properties["empty"] = string();
   a.hit_set_params = HitSet::Params(new BloomHitSet::Params);
   a.hit_set_period = 3600;
   a.hit_set_count = 8;
@@ -1239,6 +1236,7 @@ void pg_pool_t::generate_test_instances(list<pg_pool_t*>& o)
   a.cache_target_full_ratio_micro = 987222;
   a.cache_min_flush_age = 231;
   a.cache_min_evict_age = 2321;
+  a.erasure_code_profile = "profile in osdmap";
   o.push_back(new pg_pool_t(a));
 }
 
@@ -4279,6 +4277,7 @@ ostream& operator<<(ostream& out, const OSDOp& op)
     case CEPH_OSD_OP_COPY_GET:
     case CEPH_OSD_OP_COPY_GET_CLASSIC:
       out << " max " << op.op.copy_get.max;
+      break;
     case CEPH_OSD_OP_COPY_FROM:
       out << " ver " << op.op.copy_from.src_version;
       break;
diff --git a/src/osd/osd_types.h b/src/osd/osd_types.h
index f529c30..e055281 100644
--- a/src/osd/osd_types.h
+++ b/src/osd/osd_types.h
@@ -4,6 +4,9 @@
  * Ceph - scalable distributed file system
  *
  * Copyright (C) 2004-2006 Sage Weil <sage at newdream.net>
+ * Copyright (C) 2013,2014 Cloudwatt <libre.licensing at cloudwatt.com>
+ *
+ * Author: Loic Dachary <loic at dachary.org>
  *
  * This is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -875,7 +878,8 @@ private:
 
 
 public:
-  map<string,string> properties;  ///< interpreted according to the pool type
+  map<string,string> properties;  ///< OBSOLETE
+  string erasure_code_profile; ///< name of the erasure code profile in OSDMap
   epoch_t last_change;      ///< most recent epoch changed, exclusing snapshot changes
   snapid_t snap_seq;        ///< seq for per-pool snapshot
   epoch_t snap_epoch;       ///< osdmap epoch of last snap
@@ -2445,7 +2449,7 @@ struct watch_info_t {
   entity_addr_t addr;
 
   watch_info_t() : cookie(0), timeout_seconds(0) { }
-  watch_info_t(uint64_t c, uint32_t t, entity_addr_t a) : cookie(c), timeout_seconds(t), addr(a) {}
+  watch_info_t(uint64_t c, uint32_t t, const entity_addr_t& a) : cookie(c), timeout_seconds(t), addr(a) {}
 
   void encode(bufferlist& bl) const;
   void decode(bufferlist::iterator& bl);
@@ -3085,7 +3089,7 @@ struct watch_item_t {
 
   watch_item_t() : cookie(0), timeout_seconds(0) { }
   watch_item_t(entity_name_t name, uint64_t cookie, uint32_t timeout,
-     entity_addr_t addr)
+     const entity_addr_t& addr)
     : name(name), cookie(cookie), timeout_seconds(timeout),
     addr(addr) { }
 
diff --git a/src/osdc/Journaler.h b/src/osdc/Journaler.h
index 51241c1..e3a5713 100644
--- a/src/osdc/Journaler.h
+++ b/src/osdc/Journaler.h
@@ -98,6 +98,38 @@ public:
       ::decode(write_pos, bl);
       ::decode(layout, bl);
     }
+
+    void dump(Formatter *f) const {
+      f->open_object_section("journal_header");
+      {
+	f->dump_string("magic", magic);
+	f->dump_unsigned("write_pos", write_pos);
+	f->dump_unsigned("expire_pos", expire_pos);
+	f->dump_unsigned("trimmed_pos", trimmed_pos);
+	f->open_object_section("layout");
+	{
+	  f->dump_unsigned("stripe_unit", layout.fl_stripe_unit);
+	  f->dump_unsigned("stripe_count", layout.fl_stripe_unit);
+	  f->dump_unsigned("object_size", layout.fl_stripe_unit);
+	  f->dump_unsigned("cas_hash", layout.fl_stripe_unit);
+	  f->dump_unsigned("object_stripe_unit", layout.fl_stripe_unit);
+	  f->dump_unsigned("pg_pool", layout.fl_stripe_unit);
+	}
+	f->close_section(); // layout
+      }
+      f->close_section(); // journal_header
+    }
+
+    static void generate_test_instances(list<Header*> &ls)
+    {
+      ls.push_back(new Header());
+      ls.push_back(new Header());
+      ls.back()->trimmed_pos = 1;
+      ls.back()->expire_pos = 2;
+      ls.back()->unused_field = 3;
+      ls.back()->write_pos = 4;
+      ls.back()->magic = "magique";
+    }
   } last_written, last_committed;
   WRITE_CLASS_ENCODER(Header)
 
diff --git a/src/osdc/ObjectCacher.cc b/src/osdc/ObjectCacher.cc
index 29dcaaa..6ecfe82 100644
--- a/src/osdc/ObjectCacher.cc
+++ b/src/osdc/ObjectCacher.cc
@@ -625,7 +625,7 @@ void ObjectCacher::bh_read(BufferHead *bh)
   ++reads_outstanding;
 }
 
-void ObjectCacher::bh_read_finish(int64_t poolid, sobject_t oid, tid_t tid,
+void ObjectCacher::bh_read_finish(int64_t poolid, sobject_t oid, ceph_tid_t tid,
 				  loff_t start, uint64_t length,
 				  bufferlist &bl, int r,
 				  bool trust_enoent)
@@ -810,7 +810,7 @@ void ObjectCacher::bh_write(BufferHead *bh)
   C_WriteCommit *oncommit = new C_WriteCommit(this, bh->ob->oloc.pool,
                                               bh->ob->get_soid(), bh->start(), bh->length());
   // go
-  tid_t tid = writeback_handler.write(bh->ob->get_oid(), bh->ob->get_oloc(),
+  ceph_tid_t tid = writeback_handler.write(bh->ob->get_oid(), bh->ob->get_oloc(),
 				      bh->start(), bh->length(),
 				      bh->snapc, bh->bl, bh->last_write,
 				      bh->ob->truncate_size, bh->ob->truncate_seq,
@@ -830,7 +830,7 @@ void ObjectCacher::bh_write(BufferHead *bh)
 }
 
 void ObjectCacher::bh_write_commit(int64_t poolid, sobject_t oid, loff_t start,
-				   uint64_t length, tid_t tid, int r)
+				   uint64_t length, ceph_tid_t tid, int r)
 {
   assert(lock.is_locked());
   ldout(cct, 7) << "bh_write_commit " 
@@ -1245,6 +1245,8 @@ int ObjectCacher::_readx(OSDRead *rd, ObjectSet *oset, Context *onfinish,
     ldout(cct, 10) << "readx  result is " << rd->bl->length() << dendl;
   } else {
     ldout(cct, 10) << "readx  no bufferlist ptr (readahead?), done." << dendl;
+    map<uint64_t,bufferlist>::reverse_iterator i = stripe_map.rbegin();
+    pos = i->first + i->second.length();
   }
 
   // done with read.
diff --git a/src/osdc/ObjectCacher.h b/src/osdc/ObjectCacher.h
index 54f028f..01d18ce 100644
--- a/src/osdc/ObjectCacher.h
+++ b/src/osdc/ObjectCacher.h
@@ -103,8 +103,8 @@ class ObjectCacher {
   public:
     Object *ob;
     bufferlist  bl;
-    tid_t last_write_tid;  // version of bh (if non-zero)
-    tid_t last_read_tid;   // tid of last read op (if any)
+    ceph_tid_t last_write_tid;  // version of bh (if non-zero)
+    ceph_tid_t last_read_tid;   // tid of last read op (if any)
     utime_t last_write;
     SnapContext snapc;
     int error; // holds return value for failed reads
@@ -181,12 +181,12 @@ class ObjectCacher {
   public:
     map<loff_t, BufferHead*>     data;
 
-    tid_t last_write_tid;  // version of bh (if non-zero)
-    tid_t last_commit_tid; // last update commited.
+    ceph_tid_t last_write_tid;  // version of bh (if non-zero)
+    ceph_tid_t last_commit_tid; // last update commited.
 
     int dirty_or_tx;
 
-    map< tid_t, list<Context*> > waitfor_commit;
+    map< ceph_tid_t, list<Context*> > waitfor_commit;
     xlist<C_ReadFinish*> reads;
 
   public:
@@ -341,7 +341,7 @@ class ObjectCacher {
 
   vector<ceph::unordered_map<sobject_t, Object*> > objects; // indexed by pool_id
 
-  tid_t last_read_tid;
+  ceph_tid_t last_read_tid;
 
   set<BufferHead*>    dirty_bh;
   LRU   bh_lru_dirty, bh_lru_rest;
@@ -459,12 +459,12 @@ class ObjectCacher {
 	     bool external_call);
 
  public:
-  void bh_read_finish(int64_t poolid, sobject_t oid, tid_t tid,
+  void bh_read_finish(int64_t poolid, sobject_t oid, ceph_tid_t tid,
 		      loff_t offset, uint64_t length,
 		      bufferlist &bl, int r,
 		      bool trust_enoent);
   void bh_write_commit(int64_t poolid, sobject_t oid, loff_t offset,
-		       uint64_t length, tid_t t, int r);
+		       uint64_t length, ceph_tid_t t, int r);
 
   class C_ReadFinish : public Context {
     ObjectCacher *oc;
@@ -474,11 +474,11 @@ class ObjectCacher {
     uint64_t length;
     xlist<C_ReadFinish*>::item set_item;
     bool trust_enoent;
-    tid_t tid;
+    ceph_tid_t tid;
 
   public:
     bufferlist bl;
-    C_ReadFinish(ObjectCacher *c, Object *ob, tid_t t, loff_t s, uint64_t l) :
+    C_ReadFinish(ObjectCacher *c, Object *ob, ceph_tid_t t, loff_t s, uint64_t l) :
       oc(c), poolid(ob->oloc.pool), oid(ob->get_soid()), start(s), length(l),
       set_item(this), trust_enoent(true),
       tid(t) {
@@ -505,7 +505,7 @@ class ObjectCacher {
     loff_t start;
     uint64_t length;
   public:
-    tid_t tid;
+    ceph_tid_t tid;
     C_WriteCommit(ObjectCacher *c, int64_t _poolid, sobject_t o, loff_t s, uint64_t l) :
       oc(c), poolid(_poolid), oid(o), start(s), length(l), tid(0) {}
     void finish(int r) {
diff --git a/src/osdc/Objecter.cc b/src/osdc/Objecter.cc
index a295466..f876262 100644
--- a/src/osdc/Objecter.cc
+++ b/src/osdc/Objecter.cc
@@ -383,7 +383,7 @@ void Objecter::unregister_linger(uint64_t linger_id)
   }
 }
 
-tid_t Objecter::linger_mutate(const object_t& oid, const object_locator_t& oloc,
+ceph_tid_t Objecter::linger_mutate(const object_t& oid, const object_locator_t& oloc,
 			      ObjectOperation& op,
 			      const SnapContext& snapc, utime_t mtime,
 			      bufferlist& inbl, int flags,
@@ -415,7 +415,7 @@ tid_t Objecter::linger_mutate(const object_t& oid, const object_locator_t& oloc,
   return info->linger_id;
 }
 
-tid_t Objecter::linger_read(const object_t& oid, const object_locator_t& oloc,
+ceph_tid_t Objecter::linger_read(const object_t& oid, const object_locator_t& oloc,
 			    ObjectOperation& op,
 			    snapid_t snap, bufferlist& inbl, bufferlist *poutbl, int flags,
 			    Context *onfinish,
@@ -479,12 +479,12 @@ void Objecter::dispatch(Message *m)
 
 void Objecter::scan_requests(bool force_resend,
 			     bool force_resend_writes,
-			     map<tid_t, Op*>& need_resend,
+			     map<ceph_tid_t, Op*>& need_resend,
 			     list<LingerOp*>& need_resend_linger,
-			     map<tid_t, CommandOp*>& need_resend_command)
+			     map<ceph_tid_t, CommandOp*>& need_resend_command)
 {
   // check for changed linger mappings (_before_ regular ops)
-  map<tid_t,LingerOp*>::iterator lp = linger_ops.begin();
+  map<ceph_tid_t,LingerOp*>::iterator lp = linger_ops.begin();
   while (lp != linger_ops.end()) {
     LingerOp *op = lp->second;
     ++lp;   // check_linger_pool_dne() may touch linger_ops; prevent iterator invalidation
@@ -506,7 +506,7 @@ void Objecter::scan_requests(bool force_resend,
   }
 
   // check for changed request mappings
-  map<tid_t,Op*>::iterator p = ops.begin();
+  map<ceph_tid_t,Op*>::iterator p = ops.begin();
   while (p != ops.end()) {
     Op *op = p->second;
     ++p;   // check_op_pool_dne() may touch ops; prevent iterator invalidation
@@ -529,7 +529,7 @@ void Objecter::scan_requests(bool force_resend,
   }
 
   // commands
-  map<tid_t,CommandOp*>::iterator cp = command_ops.begin();
+  map<ceph_tid_t,CommandOp*>::iterator cp = command_ops.begin();
   while (cp != command_ops.end()) {
     CommandOp *c = cp->second;
     ++cp;
@@ -567,12 +567,12 @@ void Objecter::handle_osd_map(MOSDMap *m)
   }
 
   bool was_pauserd = osdmap->test_flag(CEPH_OSDMAP_PAUSERD);
-  bool was_full = osdmap->test_flag(CEPH_OSDMAP_FULL);
+  bool was_full = osdmap_full_flag();
   bool was_pausewr = osdmap->test_flag(CEPH_OSDMAP_PAUSEWR) || was_full;
 
   list<LingerOp*> need_resend_linger;
-  map<tid_t, Op*> need_resend;
-  map<tid_t, CommandOp*> need_resend_command;
+  map<ceph_tid_t, Op*> need_resend;
+  map<ceph_tid_t, CommandOp*> need_resend_command;
 
   if (m->get_last() <= osdmap->get_epoch()) {
     ldout(cct, 3) << "handle_osd_map ignoring epochs [" 
@@ -618,7 +618,7 @@ void Objecter::handle_osd_map(MOSDMap *m)
 	}
 	logger->set(l_osdc_map_epoch, osdmap->get_epoch());
 
-	was_full = was_full || osdmap->test_flag(CEPH_OSDMAP_FULL);
+	was_full = was_full || osdmap_full_flag();
 	scan_requests(skipped_map, was_full, need_resend, need_resend_linger,
 		      need_resend_command);
 
@@ -655,14 +655,14 @@ void Objecter::handle_osd_map(MOSDMap *m)
   }
 
   bool pauserd = osdmap->test_flag(CEPH_OSDMAP_PAUSERD);
-  bool pausewr = osdmap->test_flag(CEPH_OSDMAP_PAUSEWR) || osdmap->test_flag(CEPH_OSDMAP_FULL);
+  bool pausewr = osdmap->test_flag(CEPH_OSDMAP_PAUSEWR) || osdmap_full_flag();
 
   // was/is paused?
   if (was_pauserd || was_pausewr || pauserd || pausewr)
     maybe_request_map();
 
   // resend requests
-  for (map<tid_t, Op*>::iterator p = need_resend.begin(); p != need_resend.end(); ++p) {
+  for (map<ceph_tid_t, Op*>::iterator p = need_resend.begin(); p != need_resend.end(); ++p) {
     Op *op = p->second;
     if (op->should_resend) {
       if (op->session && !op->paused) {
@@ -680,7 +680,7 @@ void Objecter::handle_osd_map(MOSDMap *m)
       send_linger(op);
     }
   }
-  for (map<tid_t,CommandOp*>::iterator p = need_resend_command.begin(); p != need_resend_command.end(); ++p) {
+  for (map<ceph_tid_t,CommandOp*>::iterator p = need_resend_command.begin(); p != need_resend_command.end(); ++p) {
     CommandOp *c = p->second;
     if (c->session) {
       _send_command(c);
@@ -722,7 +722,7 @@ void Objecter::C_Op_Map_Latest::finish(int r)
 
   Mutex::Locker l(objecter->client_lock);
 
-  map<tid_t, Op*>::iterator iter =
+  map<ceph_tid_t, Op*>::iterator iter =
     objecter->check_latest_map_ops.find(tid);
   if (iter == objecter->check_latest_map_ops.end()) {
     lgeneric_subdout(objecter->cct, objecter, 10) << "op_map_latest op " << tid << " not found" << dendl;
@@ -781,7 +781,7 @@ void Objecter::_send_op_map_check(Op *op)
 void Objecter::op_cancel_map_check(Op *op)
 {
   assert(client_lock.is_locked());
-  map<tid_t, Op*>::iterator iter =
+  map<ceph_tid_t, Op*>::iterator iter =
     check_latest_map_ops.find(op->tid);
   if (iter != check_latest_map_ops.end()) {
     check_latest_map_ops.erase(iter);
@@ -1021,7 +1021,7 @@ void Objecter::_get_latest_version(epoch_t oldest, epoch_t newest, Context *fin)
 void Objecter::maybe_request_map()
 {
   int flag = 0;
-  if (osdmap->test_flag(CEPH_OSDMAP_FULL)) {
+  if (osdmap_full_flag()) {
     ldout(cct, 10) << "maybe_request_map subscribing (continuous) to next osd map (FULL flag is set)" << dendl;
   } else {
     ldout(cct, 10) << "maybe_request_map subscribing (onetime) to next osd map" << dendl;
@@ -1043,7 +1043,7 @@ void Objecter::kick_requests(OSDSession *session)
   ldout(cct, 10) << "kick_requests for osd." << session->osd << dendl;
 
   // resend ops
-  map<tid_t,Op*> resend;  // resend in tid order
+  map<ceph_tid_t,Op*> resend;  // resend in tid order
   for (xlist<Op*>::iterator p = session->ops.begin(); !p.end();) {
     Op *op = *p;
     ++p;
@@ -1107,7 +1107,7 @@ void Objecter::tick()
   cutoff -= cct->_conf->objecter_timeout;  // timeout
 
   unsigned laggy_ops = 0;
-  for (map<tid_t,Op*>::iterator p = ops.begin();
+  for (map<ceph_tid_t,Op*>::iterator p = ops.begin();
        p != ops.end();
        ++p) {
     Op *op = p->second;
@@ -1164,22 +1164,22 @@ void Objecter::resend_mon_ops()
   assert(client_lock.is_locked());
   ldout(cct, 10) << "resend_mon_ops" << dendl;
 
-  for (map<tid_t,PoolStatOp*>::iterator p = poolstat_ops.begin(); p!=poolstat_ops.end(); ++p) {
+  for (map<ceph_tid_t,PoolStatOp*>::iterator p = poolstat_ops.begin(); p!=poolstat_ops.end(); ++p) {
     poolstat_submit(p->second);
     logger->inc(l_osdc_poolstat_resend);
   }
 
-  for (map<tid_t,StatfsOp*>::iterator p = statfs_ops.begin(); p!=statfs_ops.end(); ++p) {
+  for (map<ceph_tid_t,StatfsOp*>::iterator p = statfs_ops.begin(); p!=statfs_ops.end(); ++p) {
     fs_stats_submit(p->second);
     logger->inc(l_osdc_statfs_resend);
   }
 
-  for (map<tid_t,PoolOp*>::iterator p = pool_ops.begin(); p!=pool_ops.end(); ++p) {
+  for (map<ceph_tid_t,PoolOp*>::iterator p = pool_ops.begin(); p!=pool_ops.end(); ++p) {
     _pool_op_submit(p->second);
     logger->inc(l_osdc_poolop_resend);
   }
 
-  for (map<tid_t, Op*>::iterator p = check_latest_map_ops.begin();
+  for (map<ceph_tid_t, Op*>::iterator p = check_latest_map_ops.begin();
        p != check_latest_map_ops.end();
        ++p) {
     C_Op_Map_Latest *c = new C_Op_Map_Latest(this, p->second->tid);
@@ -1218,7 +1218,7 @@ public:
   }
 };
 
-tid_t Objecter::op_submit(Op *op)
+ceph_tid_t Objecter::op_submit(Op *op)
 {
   assert(client_lock.is_locked());
   assert(initialized);
@@ -1239,10 +1239,10 @@ tid_t Objecter::op_submit(Op *op)
   return _op_submit(op);
 }
 
-tid_t Objecter::_op_submit(Op *op)
+ceph_tid_t Objecter::_op_submit(Op *op)
 {
   // pick tid
-  tid_t mytid = ++last_tid;
+  ceph_tid_t mytid = ++last_tid;
   op->tid = mytid;
   assert(client_inc >= 0);
 
@@ -1328,8 +1328,7 @@ tid_t Objecter::_op_submit(Op *op)
     ldout(cct, 10) << " paused read " << op << " tid " << last_tid << dendl;
     op->paused = true;
     maybe_request_map();
-  } else if ((op->flags & CEPH_OSD_FLAG_WRITE) &&
-	     osdmap->test_flag(CEPH_OSDMAP_FULL)) {
+  } else if ((op->flags & CEPH_OSD_FLAG_WRITE) && osdmap_full_flag()) {
     ldout(cct, 0) << " FULL, paused modify " << op << " tid " << last_tid << dendl;
     op->paused = true;
     maybe_request_map();
@@ -1348,12 +1347,12 @@ tid_t Objecter::_op_submit(Op *op)
   return op->tid;
 }
 
-int Objecter::op_cancel(tid_t tid, int r)
+int Objecter::op_cancel(ceph_tid_t tid, int r)
 {
   assert(client_lock.is_locked());
   assert(initialized);
 
-  map<tid_t, Op*>::iterator p = ops.find(tid);
+  map<ceph_tid_t, Op*>::iterator p = ops.find(tid);
   if (p == ops.end()) {
     ldout(cct, 10) << __func__ << " tid " << tid << " dne" << dendl;
     return -ENOENT;
@@ -1395,12 +1394,24 @@ bool Objecter::is_pg_changed(
 bool Objecter::op_should_be_paused(Op *op)
 {
   bool pauserd = osdmap->test_flag(CEPH_OSDMAP_PAUSERD);
-  bool pausewr = osdmap->test_flag(CEPH_OSDMAP_PAUSEWR) || osdmap->test_flag(CEPH_OSDMAP_FULL);
+  bool pausewr = osdmap->test_flag(CEPH_OSDMAP_PAUSEWR) || osdmap_full_flag();
 
   return (op->flags & CEPH_OSD_FLAG_READ && pauserd) ||
          (op->flags & CEPH_OSD_FLAG_WRITE && pausewr);
 }
 
+
+/**
+ * Wrapper around osdmap->test_flag for special handling of the FULL flag.
+ */
+bool Objecter::osdmap_full_flag() const
+{
+  // Ignore the FULL flag if we are working on behalf of an MDS, in order to permit
+  // MDS journal writes for file deletions.
+  return osdmap->test_flag(CEPH_OSDMAP_FULL) && (messenger->get_myname().type() != entity_name_t::TYPE_MDS);
+}
+
+
 int64_t Objecter::get_object_hash_position(int64_t pool, const string& key,
 					   const string& ns)
 {
@@ -1707,7 +1718,7 @@ void Objecter::handle_osd_op_reply(MOSDOpReply *m)
   ldout(cct, 10) << "in handle_osd_op_reply" << dendl;
 
   // get pio
-  tid_t tid = m->get_tid();
+  ceph_tid_t tid = m->get_tid();
 
   if (ops.count(tid) == 0) {
     ldout(cct, 7) << "handle_osd_op_reply " << tid
@@ -2144,11 +2155,11 @@ int Objecter::change_pool_auid(int64_t pool, Context *onfinish, uint64_t auid)
 
 class C_CancelPoolOp : public Context
 {
-  tid_t tid;
+  ceph_tid_t tid;
   Objecter *objecter;
 public:
-  C_CancelPoolOp(tid_t tid, Objecter *objecter) : tid(tid),
-						  objecter(objecter) {}
+  C_CancelPoolOp(ceph_tid_t tid, Objecter *objecter) : tid(tid),
+						       objecter(objecter) {}
   void finish(int r) {
     // note that objecter lock == timer lock, and is already held
     objecter->pool_op_cancel(tid, -ETIMEDOUT);
@@ -2190,7 +2201,7 @@ void Objecter::handle_pool_op_reply(MPoolOpReply *m)
   assert(client_lock.is_locked());
   assert(initialized);
   ldout(cct, 10) << "handle_pool_op_reply " << *m << dendl;
-  tid_t tid = m->get_tid();
+  ceph_tid_t tid = m->get_tid();
   if (pool_ops.count(tid)) {
     PoolOp *op = pool_ops[tid];
     ldout(cct, 10) << "have request " << tid << " at " << op << " Op: " << ceph_pool_op_name(op->pool_op) << dendl;
@@ -2214,12 +2225,12 @@ void Objecter::handle_pool_op_reply(MPoolOpReply *m)
   m->put();
 }
 
-int Objecter::pool_op_cancel(tid_t tid, int r)
+int Objecter::pool_op_cancel(ceph_tid_t tid, int r)
 {
   assert(client_lock.is_locked());
   assert(initialized);
 
-  map<tid_t, PoolOp*>::iterator it = pool_ops.find(tid);
+  map<ceph_tid_t, PoolOp*>::iterator it = pool_ops.find(tid);
   if (it == pool_ops.end()) {
     ldout(cct, 10) << __func__ << " tid " << tid << " dne" << dendl;
     return -ENOENT;
@@ -2249,11 +2260,11 @@ void Objecter::finish_pool_op(PoolOp *op)
 
 class C_CancelPoolStatOp : public Context
 {
-  tid_t tid;
+  ceph_tid_t tid;
   Objecter *objecter;
 public:
-  C_CancelPoolStatOp(tid_t tid, Objecter *objecter) : tid(tid),
-						      objecter(objecter) {}
+  C_CancelPoolStatOp(ceph_tid_t tid, Objecter *objecter) : tid(tid),
+						           objecter(objecter) {}
   void finish(int r) {
     // note that objecter lock == timer lock, and is already held
     objecter->pool_stat_op_cancel(tid, -ETIMEDOUT);
@@ -2296,7 +2307,7 @@ void Objecter::handle_get_pool_stats_reply(MGetPoolStatsReply *m)
   assert(client_lock.is_locked());
   assert(initialized);
   ldout(cct, 10) << "handle_get_pool_stats_reply " << *m << dendl;
-  tid_t tid = m->get_tid();
+  ceph_tid_t tid = m->get_tid();
 
   if (poolstat_ops.count(tid)) {
     PoolStatOp *op = poolstat_ops[tid];
@@ -2313,12 +2324,12 @@ void Objecter::handle_get_pool_stats_reply(MGetPoolStatsReply *m)
   m->put();
 }
 
-int Objecter::pool_stat_op_cancel(tid_t tid, int r)
+int Objecter::pool_stat_op_cancel(ceph_tid_t tid, int r)
 {
   assert(client_lock.is_locked());
   assert(initialized);
 
-  map<tid_t, PoolStatOp*>::iterator it = poolstat_ops.find(tid);
+  map<ceph_tid_t, PoolStatOp*>::iterator it = poolstat_ops.find(tid);
   if (it == poolstat_ops.end()) {
     ldout(cct, 10) << __func__ << " tid " << tid << " dne" << dendl;
     return -ENOENT;
@@ -2346,11 +2357,11 @@ void Objecter::finish_pool_stat_op(PoolStatOp *op)
 
 class C_CancelStatfsOp : public Context
 {
-  tid_t tid;
+  ceph_tid_t tid;
   Objecter *objecter;
 public:
-  C_CancelStatfsOp(tid_t tid, Objecter *objecter) : tid(tid),
-						    objecter(objecter) {}
+  C_CancelStatfsOp(ceph_tid_t tid, Objecter *objecter) : tid(tid),
+							 objecter(objecter) {}
   void finish(int r) {
     // note that objecter lock == timer lock, and is already held
     objecter->statfs_op_cancel(tid, -ETIMEDOUT);
@@ -2391,7 +2402,7 @@ void Objecter::handle_fs_stats_reply(MStatfsReply *m)
   assert(client_lock.is_locked());
   assert(initialized);
   ldout(cct, 10) << "handle_fs_stats_reply " << *m << dendl;
-  tid_t tid = m->get_tid();
+  ceph_tid_t tid = m->get_tid();
 
   if (statfs_ops.count(tid)) {
     StatfsOp *op = statfs_ops[tid];
@@ -2408,12 +2419,12 @@ void Objecter::handle_fs_stats_reply(MStatfsReply *m)
   m->put();
 }
 
-int Objecter::statfs_op_cancel(tid_t tid, int r)
+int Objecter::statfs_op_cancel(ceph_tid_t tid, int r)
 {
   assert(client_lock.is_locked());
   assert(initialized);
 
-  map<tid_t, StatfsOp*>::iterator it = statfs_ops.find(tid);
+  map<ceph_tid_t, StatfsOp*>::iterator it = statfs_ops.find(tid);
   if (it == statfs_ops.end()) {
     ldout(cct, 10) << __func__ << " tid " << tid << " dne" << dendl;
     return -ENOENT;
@@ -2511,7 +2522,7 @@ void Objecter::ms_handle_remote_reset(Connection *con)
 void Objecter::dump_active()
 {
   ldout(cct, 20) << "dump_active .. " << num_homeless_ops << " homeless" << dendl;
-  for (map<tid_t,Op*>::iterator p = ops.begin(); p != ops.end(); ++p) {
+  for (map<ceph_tid_t,Op*>::iterator p = ops.begin(); p != ops.end(); ++p) {
     Op *op = p->second;
     ldout(cct, 20) << op->tid << "\t" << op->pgid << "\tosd." << (op->session ? op->session->osd : -1)
 	    << "\t" << op->base_oid << "\t" << op->ops << dendl;
@@ -2535,7 +2546,7 @@ void Objecter::dump_requests(Formatter *fmt) const
 void Objecter::dump_ops(Formatter *fmt) const
 {
   fmt->open_array_section("ops");
-  for (map<tid_t,Op*>::const_iterator p = ops.begin();
+  for (map<ceph_tid_t,Op*>::const_iterator p = ops.begin();
        p != ops.end();
        ++p) {
     Op *op = p->second;
@@ -2611,7 +2622,7 @@ void Objecter::dump_command_ops(Formatter *fmt) const
 void Objecter::dump_pool_ops(Formatter *fmt) const
 {
   fmt->open_array_section("pool_ops");
-  for (map<tid_t, PoolOp*>::const_iterator p = pool_ops.begin();
+  for (map<ceph_tid_t, PoolOp*>::const_iterator p = pool_ops.begin();
        p != pool_ops.end();
        ++p) {
     PoolOp *op = p->second;
@@ -2632,7 +2643,7 @@ void Objecter::dump_pool_ops(Formatter *fmt) const
 void Objecter::dump_pool_stat_ops(Formatter *fmt) const
 {
   fmt->open_array_section("pool_stat_ops");
-  for (map<tid_t, PoolStatOp*>::const_iterator p = poolstat_ops.begin();
+  for (map<ceph_tid_t, PoolStatOp*>::const_iterator p = poolstat_ops.begin();
        p != poolstat_ops.end();
        ++p) {
     PoolStatOp *op = p->second;
@@ -2656,7 +2667,7 @@ void Objecter::dump_pool_stat_ops(Formatter *fmt) const
 void Objecter::dump_statfs_ops(Formatter *fmt) const
 {
   fmt->open_array_section("statfs_ops");
-  for (map<tid_t, StatfsOp*>::const_iterator p = statfs_ops.begin();
+  for (map<ceph_tid_t, StatfsOp*>::const_iterator p = statfs_ops.begin();
        p != statfs_ops.end();
        ++p) {
     StatfsOp *op = p->second;
@@ -2711,7 +2722,7 @@ void Objecter::blacklist_self(bool set)
 
 void Objecter::handle_command_reply(MCommandReply *m)
 {
-  map<tid_t,CommandOp*>::iterator p = command_ops.find(m->get_tid());
+  map<ceph_tid_t,CommandOp*>::iterator p = command_ops.find(m->get_tid());
   if (p == command_ops.end()) {
     ldout(cct, 10) << "handle_command_reply tid " << m->get_tid() << " not found" << dendl;
     m->put();
@@ -2734,20 +2745,20 @@ void Objecter::handle_command_reply(MCommandReply *m)
 
 class C_CancelCommandOp : public Context
 {
-  tid_t tid;
+  ceph_tid_t tid;
   Objecter *objecter;
 public:
-  C_CancelCommandOp(tid_t tid, Objecter *objecter) : tid(tid),
-						     objecter(objecter) {}
+  C_CancelCommandOp(ceph_tid_t tid, Objecter *objecter) : tid(tid),
+						          objecter(objecter) {}
   void finish(int r) {
     // note that objecter lock == timer lock, and is already held
     objecter->command_op_cancel(tid, -ETIMEDOUT);
   }
 };
 
-int Objecter::_submit_command(CommandOp *c, tid_t *ptid)
+int Objecter::_submit_command(CommandOp *c, ceph_tid_t *ptid)
 {
-  tid_t tid = ++last_tid;
+  ceph_tid_t tid = ++last_tid;
   ldout(cct, 10) << "_submit_command " << tid << " " << c->cmd << dendl;
   c->tid = tid;
   if (osd_timeout > 0) {
@@ -2828,12 +2839,12 @@ void Objecter::_send_command(CommandOp *c)
   logger->inc(l_osdc_command_send);
 }
 
-int Objecter::command_op_cancel(tid_t tid, int r)
+int Objecter::command_op_cancel(ceph_tid_t tid, int r)
 {
   assert(client_lock.is_locked());
   assert(initialized);
 
-  map<tid_t, CommandOp*>::iterator it = command_ops.find(tid);
+  map<ceph_tid_t, CommandOp*>::iterator it = command_ops.find(tid);
   if (it == command_ops.end()) {
     ldout(cct, 10) << __func__ << " tid " << tid << " dne" << dendl;
     return -ENOENT;
diff --git a/src/osdc/Objecter.h b/src/osdc/Objecter.h
index 2311f55..d18e653 100644
--- a/src/osdc/Objecter.h
+++ b/src/osdc/Objecter.h
@@ -1013,7 +1013,7 @@ public:
   bool initialized;
 
 private:
-  tid_t last_tid;
+  ceph_tid_t last_tid;
   int client_inc;
   uint64_t max_linger_id;
   int num_unacked;
@@ -1095,7 +1095,7 @@ public:
     int flags, priority;
     Context *onack, *oncommit, *ontimeout;
 
-    tid_t tid;
+    ceph_tid_t tid;
     eversion_t replay_version;        // for op replay
     int attempts;
 
@@ -1158,9 +1158,9 @@ public:
 
   struct C_Op_Map_Latest : public Context {
     Objecter *objecter;
-    tid_t tid;
+    ceph_tid_t tid;
     version_t latest;
-    C_Op_Map_Latest(Objecter *o, tid_t t) : objecter(o), tid(t), latest(0) {}
+    C_Op_Map_Latest(Objecter *o, ceph_tid_t t) : objecter(o), tid(t), latest(0) {}
     void finish(int r);
   };
 
@@ -1168,7 +1168,7 @@ public:
     Objecter *objecter;
     uint64_t tid;
     version_t latest;
-    C_Command_Map_Latest(Objecter *o, tid_t t) :  objecter(o), tid(t), latest(0) {}
+    C_Command_Map_Latest(Objecter *o, ceph_tid_t t) :  objecter(o), tid(t), latest(0) {}
     void finish(int r);
   };
 
@@ -1263,7 +1263,7 @@ public:
   };
   
   struct PoolStatOp {
-    tid_t tid;
+    ceph_tid_t tid;
     list<string> pools;
 
     map<string,pool_stat_t> *pool_stats;
@@ -1273,7 +1273,7 @@ public:
   };
 
   struct StatfsOp {
-    tid_t tid;
+    ceph_tid_t tid;
     struct ceph_statfs *stats;
     Context *onfinish, *ontimeout;
 
@@ -1281,7 +1281,7 @@ public:
   };
 
   struct PoolOp {
-    tid_t tid;
+    ceph_tid_t tid;
     int64_t pool;
     string name;
     Context *onfinish, *ontimeout;
@@ -1300,7 +1300,7 @@ public:
   struct CommandOp : public RefCountedObject {
     xlist<CommandOp*>::item session_item;
     OSDSession *session;
-    tid_t tid;
+    ceph_tid_t tid;
     vector<string> cmd;
     bufferlist inbl;
     bufferlist *poutbl;
@@ -1322,10 +1322,10 @@ public:
 	onfinish(NULL), ontimeout(NULL) {}
   };
 
-  int _submit_command(CommandOp *c, tid_t *ptid);
+  int _submit_command(CommandOp *c, ceph_tid_t *ptid);
   int recalc_command_target(CommandOp *c);
   void _send_command(CommandOp *c);
-  int command_op_cancel(tid_t tid, int r);
+  int command_op_cancel(ceph_tid_t tid, int r);
   void _finish_command(CommandOp *c, int r, string rs);
   void handle_command_reply(MCommandReply *m);
 
@@ -1357,7 +1357,7 @@ public:
     OSDSession *session;
     xlist<LingerOp*>::item session_item;
 
-    tid_t register_tid;
+    ceph_tid_t register_tid;
     epoch_t map_dne_bound;
 
     LingerOp() : linger_id(0), primary(-1),
@@ -1429,19 +1429,19 @@ public:
 
  private:
   // pending ops
-  map<tid_t,Op*>            ops;
+  map<ceph_tid_t,Op*>       ops;
   int                       num_homeless_ops;
   map<uint64_t, LingerOp*>  linger_ops;
-  map<tid_t,PoolStatOp*>    poolstat_ops;
-  map<tid_t,StatfsOp*>      statfs_ops;
-  map<tid_t,PoolOp*>        pool_ops;
-  map<tid_t,CommandOp*>     command_ops;
+  map<ceph_tid_t,PoolStatOp*>    poolstat_ops;
+  map<ceph_tid_t,StatfsOp*>      statfs_ops;
+  map<ceph_tid_t,PoolOp*>        pool_ops;
+  map<ceph_tid_t,CommandOp*>     command_ops;
 
   // ops waiting for an osdmap with a new pool or confirmation that
   // the pool does not exist (may be expanded to other uses later)
-  map<uint64_t, LingerOp*>  check_latest_map_lingers;
-  map<tid_t, Op*>           check_latest_map_ops;
-  map<tid_t, CommandOp*>    check_latest_map_commands;
+  map<uint64_t, LingerOp*>       check_latest_map_lingers;
+  map<ceph_tid_t, Op*>           check_latest_map_ops;
+  map<ceph_tid_t, CommandOp*>    check_latest_map_commands;
 
   map<epoch_t,list< pair<Context*, int> > > waiting_for_map;
 
@@ -1463,6 +1463,7 @@ public:
     RECALC_OP_TARGET_OSD_DNE,
     RECALC_OP_TARGET_OSD_DOWN,
   };
+  bool osdmap_full_flag() const;
   bool op_should_be_paused(Op *op);
   int recalc_op_target(Op *op);
   bool recalc_linger_op_target(LingerOp *op);
@@ -1565,9 +1566,9 @@ public:
 
   void scan_requests(bool force_resend,
 		     bool force_resend_writes,
-		     map<tid_t, Op*>& need_resend,
+		     map<ceph_tid_t, Op*>& need_resend,
 		     list<LingerOp*>& need_resend_linger,
-		     map<tid_t, CommandOp*>& need_resend_command);
+		     map<ceph_tid_t, CommandOp*>& need_resend_command);
 
   int64_t get_object_hash_position(int64_t pool, const string& key, const string& ns);
   int64_t get_object_pg_hash_position(int64_t pool, const string& key, const string& ns);
@@ -1581,12 +1582,12 @@ public:
 
 private:
   // low-level
-  tid_t _op_submit(Op *op);
+  ceph_tid_t _op_submit(Op *op);
   inline void unregister_op(Op *op);
 
   // public interface
 public:
-  tid_t op_submit(Op *op);
+  ceph_tid_t op_submit(Op *op);
   bool is_active() {
     return !(ops.empty() && linger_ops.empty() && poolstat_ops.empty() && statfs_ops.empty());
   }
@@ -1618,11 +1619,11 @@ public:
   void clear_global_op_flag(int flags) { global_op_flags &= ~flags; }
 
   /// cancel an in-progress request with the given return code
-  int op_cancel(tid_t tid, int r);
+  int op_cancel(ceph_tid_t tid, int r);
 
   // commands
   int osd_command(int osd, vector<string>& cmd,
-		  const bufferlist& inbl, tid_t *ptid,
+		  const bufferlist& inbl, ceph_tid_t *ptid,
 		  bufferlist *poutbl, string *prs, Context *onfinish) {
     assert(osd >= 0);
     CommandOp *c = new CommandOp;
@@ -1635,7 +1636,7 @@ public:
     return _submit_command(c, ptid);
   }
   int pg_command(pg_t pgid, vector<string>& cmd,
-		 const bufferlist& inbl, tid_t *ptid,
+		 const bufferlist& inbl, ceph_tid_t *ptid,
 		 bufferlist *poutbl, string *prs, Context *onfinish) {
     CommandOp *c = new CommandOp;
     c->cmd = cmd;
@@ -1648,7 +1649,7 @@ public:
   }
 
   // mid-level helpers
-  Op *prepare_mutate_op(const object_t& oid, const object_locator_t& oloc, 
+  Op *prepare_mutate_op(const object_t& oid, const object_locator_t& oloc,
 	       ObjectOperation& op,
 	       const SnapContext& snapc, utime_t mtime, int flags,
 	       Context *onack, Context *oncommit, version_t *objver = NULL) {
@@ -1659,7 +1660,7 @@ public:
     o->out_rval.swap(op.out_rval);
     return o;
   }
-  tid_t mutate(const object_t& oid, const object_locator_t& oloc, 
+  ceph_tid_t mutate(const object_t& oid, const object_locator_t& oloc,
 	       ObjectOperation& op,
 	       const SnapContext& snapc, utime_t mtime, int flags,
 	       Context *onack, Context *oncommit, version_t *objver = NULL) {
@@ -1679,14 +1680,14 @@ public:
     o->out_rval.swap(op.out_rval);
     return o;
   }
-  tid_t read(const object_t& oid, const object_locator_t& oloc,
+  ceph_tid_t read(const object_t& oid, const object_locator_t& oloc,
 	     ObjectOperation& op,
 	     snapid_t snapid, bufferlist *pbl, int flags,
 	     Context *onack, version_t *objver = NULL) {
     Op *o = prepare_read_op(oid, oloc, op, snapid, pbl, flags, onack, objver);
     return op_submit(o);
   }
-  tid_t pg_read(uint32_t hash, object_locator_t oloc,
+  ceph_tid_t pg_read(uint32_t hash, object_locator_t oloc,
 		ObjectOperation& op,
 		bufferlist *pbl, int flags,
 		Context *onack,
@@ -1705,13 +1706,13 @@ public:
     o->reply_epoch = reply_epoch;
     return op_submit(o);
   }
-  tid_t linger_mutate(const object_t& oid, const object_locator_t& oloc,
+  ceph_tid_t linger_mutate(const object_t& oid, const object_locator_t& oloc,
 		      ObjectOperation& op,
 		      const SnapContext& snapc, utime_t mtime,
 		      bufferlist& inbl, int flags,
 		      Context *onack, Context *onfinish,
 		      version_t *objver);
-  tid_t linger_read(const object_t& oid, const object_locator_t& oloc,
+  ceph_tid_t linger_read(const object_t& oid, const object_locator_t& oloc,
 		    ObjectOperation& op,
 		    snapid_t snap, bufferlist& inbl, bufferlist *poutbl, int flags,
 		    Context *onack,
@@ -1746,7 +1747,7 @@ public:
 
 
   // high-level helpers
-  tid_t stat(const object_t& oid, const object_locator_t& oloc, snapid_t snap,
+  ceph_tid_t stat(const object_t& oid, const object_locator_t& oloc, snapid_t snap,
 	     uint64_t *psize, utime_t *pmtime, int flags, 
 	     Context *onfinish,
 	     version_t *objver = NULL, ObjectOperation *extra_ops = NULL) {
@@ -1760,7 +1761,7 @@ public:
     return op_submit(o);
   }
 
-  tid_t read(const object_t& oid, const object_locator_t& oloc, 
+  ceph_tid_t read(const object_t& oid, const object_locator_t& oloc,
 	     uint64_t off, uint64_t len, snapid_t snap, bufferlist *pbl, int flags,
 	     Context *onfinish,
 	     version_t *objver = NULL, ObjectOperation *extra_ops = NULL) {
@@ -1777,7 +1778,7 @@ public:
     return op_submit(o);
   }
 
-  tid_t read_trunc(const object_t& oid, const object_locator_t& oloc, 
+  ceph_tid_t read_trunc(const object_t& oid, const object_locator_t& oloc,
 	     uint64_t off, uint64_t len, snapid_t snap, bufferlist *pbl, int flags,
 	     uint64_t trunc_size, __u32 trunc_seq,
 	     Context *onfinish,
@@ -1794,7 +1795,7 @@ public:
     o->outbl = pbl;
     return op_submit(o);
   }
-  tid_t mapext(const object_t& oid, const object_locator_t& oloc,
+  ceph_tid_t mapext(const object_t& oid, const object_locator_t& oloc,
 	     uint64_t off, uint64_t len, snapid_t snap, bufferlist *pbl, int flags,
 	     Context *onfinish,
 	     version_t *objver = NULL, ObjectOperation *extra_ops = NULL) {
@@ -1810,7 +1811,7 @@ public:
     o->outbl = pbl;
     return op_submit(o);
   }
-  tid_t getxattr(const object_t& oid, const object_locator_t& oloc,
+  ceph_tid_t getxattr(const object_t& oid, const object_locator_t& oloc,
 	     const char *name, snapid_t snap, bufferlist *pbl, int flags,
 	     Context *onfinish,
 	     version_t *objver = NULL, ObjectOperation *extra_ops = NULL) {
@@ -1827,7 +1828,7 @@ public:
     return op_submit(o);
   }
 
-  tid_t getxattrs(const object_t& oid, const object_locator_t& oloc, snapid_t snap,
+  ceph_tid_t getxattrs(const object_t& oid, const object_locator_t& oloc, snapid_t snap,
 		  map<string,bufferlist>& attrset,
 		  int flags, Context *onfinish,
 		  version_t *objver = NULL, ObjectOperation *extra_ops = NULL) {
@@ -1841,7 +1842,7 @@ public:
     return op_submit(o);
   }
 
-  tid_t read_full(const object_t& oid, const object_locator_t& oloc,
+  ceph_tid_t read_full(const object_t& oid, const object_locator_t& oloc,
 		  snapid_t snap, bufferlist *pbl, int flags,
 		  Context *onfinish,
 	          version_t *objver = NULL, ObjectOperation *extra_ops = NULL) {
@@ -1850,7 +1851,7 @@ public:
 
      
   // writes
-  tid_t _modify(const object_t& oid, const object_locator_t& oloc,
+  ceph_tid_t _modify(const object_t& oid, const object_locator_t& oloc,
 		vector<OSDOp>& ops, utime_t mtime,
 		const SnapContext& snapc, int flags,
 	        Context *onack, Context *oncommit,
@@ -1860,7 +1861,7 @@ public:
     o->snapc = snapc;
     return op_submit(o);
   }
-  tid_t write(const object_t& oid, const object_locator_t& oloc,
+  ceph_tid_t write(const object_t& oid, const object_locator_t& oloc,
 	      uint64_t off, uint64_t len, const SnapContext& snapc, const bufferlist &bl,
 	      utime_t mtime, int flags,
 	      Context *onack, Context *oncommit,
@@ -1878,7 +1879,7 @@ public:
     o->snapc = snapc;
     return op_submit(o);
   }
-  tid_t append(const object_t& oid, const object_locator_t& oloc,
+  ceph_tid_t append(const object_t& oid, const object_locator_t& oloc,
 	       uint64_t len, const SnapContext& snapc, const bufferlist &bl,
 	       utime_t mtime, int flags,
 	       Context *onack, Context *oncommit,
@@ -1896,7 +1897,7 @@ public:
     o->snapc = snapc;
     return op_submit(o);
   }
-  tid_t write_trunc(const object_t& oid, const object_locator_t& oloc,
+  ceph_tid_t write_trunc(const object_t& oid, const object_locator_t& oloc,
 	      uint64_t off, uint64_t len, const SnapContext& snapc, const bufferlist &bl,
 	      utime_t mtime, int flags,
 	      uint64_t trunc_size, __u32 trunc_seq,
@@ -1915,7 +1916,7 @@ public:
     o->snapc = snapc;
     return op_submit(o);
   }
-  tid_t write_full(const object_t& oid, const object_locator_t& oloc,
+  ceph_tid_t write_full(const object_t& oid, const object_locator_t& oloc,
 		   const SnapContext& snapc, const bufferlist &bl, utime_t mtime, int flags,
 		   Context *onack, Context *oncommit,
 		   version_t *objver = NULL, ObjectOperation *extra_ops = NULL) {
@@ -1930,7 +1931,7 @@ public:
     o->snapc = snapc;
     return op_submit(o);
   }
-  tid_t trunc(const object_t& oid, const object_locator_t& oloc,
+  ceph_tid_t trunc(const object_t& oid, const object_locator_t& oloc,
 	      const SnapContext& snapc,
 	      utime_t mtime, int flags,
 	      uint64_t trunc_size, __u32 trunc_seq,
@@ -1947,7 +1948,7 @@ public:
     o->snapc = snapc;
     return op_submit(o);
   }
-  tid_t zero(const object_t& oid, const object_locator_t& oloc, 
+  ceph_tid_t zero(const object_t& oid, const object_locator_t& oloc,
 	     uint64_t off, uint64_t len, const SnapContext& snapc, utime_t mtime, int flags,
              Context *onack, Context *oncommit,
 	     version_t *objver = NULL, ObjectOperation *extra_ops = NULL) {
@@ -1961,7 +1962,7 @@ public:
     o->snapc = snapc;
     return op_submit(o);
   }
-  tid_t rollback_object(const object_t& oid, const object_locator_t& oloc,
+  ceph_tid_t rollback_object(const object_t& oid, const object_locator_t& oloc,
 		 const SnapContext& snapc, snapid_t snapid,
 		 utime_t mtime, Context *onack, Context *oncommit,
 		 version_t *objver = NULL, ObjectOperation *extra_ops = NULL) {
@@ -1974,7 +1975,7 @@ public:
     o->snapc = snapc;
     return op_submit(o);
   }
-  tid_t create(const object_t& oid, const object_locator_t& oloc, 
+  ceph_tid_t create(const object_t& oid, const object_locator_t& oloc,
 	     const SnapContext& snapc, utime_t mtime,
              int global_flags, int create_flags,
              Context *onack, Context *oncommit,
@@ -1988,7 +1989,7 @@ public:
     o->snapc = snapc;
     return op_submit(o);
   }
-  tid_t remove(const object_t& oid, const object_locator_t& oloc, 
+  ceph_tid_t remove(const object_t& oid, const object_locator_t& oloc,
 	       const SnapContext& snapc, utime_t mtime, int flags,
 	       Context *onack, Context *oncommit,
 	       version_t *objver = NULL, ObjectOperation *extra_ops = NULL) {
@@ -2001,7 +2002,7 @@ public:
     return op_submit(o);
   }
 
-  tid_t lock(const object_t& oid, const object_locator_t& oloc, int op, int flags,
+  ceph_tid_t lock(const object_t& oid, const object_locator_t& oloc, int op, int flags,
 	     Context *onack, Context *oncommit, version_t *objver = NULL, ObjectOperation *extra_ops = NULL) {
     SnapContext snapc;  // no snapc for lock ops
     vector<OSDOp> ops;
@@ -2011,7 +2012,7 @@ public:
     o->snapc = snapc;
     return op_submit(o);
   }
-  tid_t setxattr(const object_t& oid, const object_locator_t& oloc,
+  ceph_tid_t setxattr(const object_t& oid, const object_locator_t& oloc,
 	      const char *name, const SnapContext& snapc, const bufferlist &bl,
 	      utime_t mtime, int flags,
 	      Context *onack, Context *oncommit,
@@ -2029,7 +2030,7 @@ public:
     o->snapc = snapc;
     return op_submit(o);
   }
-  tid_t removexattr(const object_t& oid, const object_locator_t& oloc,
+  ceph_tid_t removexattr(const object_t& oid, const object_locator_t& oloc,
 	      const char *name, const SnapContext& snapc,
 	      utime_t mtime, int flags,
 	      Context *onack, Context *oncommit,
@@ -2067,7 +2068,7 @@ public:
   int change_pool_auid(int64_t pool, Context *onfinish, uint64_t auid);
 
   void handle_pool_op_reply(MPoolOpReply *m);
-  int pool_op_cancel(tid_t tid, int r);
+  int pool_op_cancel(ceph_tid_t tid, int r);
   void finish_pool_op(PoolOp *op);
 
   // --------------------------
@@ -2078,7 +2079,7 @@ public:
   void handle_get_pool_stats_reply(MGetPoolStatsReply *m);
   void get_pool_stats(list<string>& pools, map<string,pool_stat_t> *result,
 		      Context *onfinish);
-  int pool_stat_op_cancel(tid_t tid, int r);
+  int pool_stat_op_cancel(ceph_tid_t tid, int r);
   void finish_pool_stat_op(PoolStatOp *op);
 
   // ---------------------------
@@ -2088,7 +2089,7 @@ private:
 public:
   void handle_fs_stats_reply(MStatfsReply *m);
   void get_fs_stats(struct ceph_statfs& result, Context *onfinish);
-  int statfs_op_cancel(tid_t tid, int r);
+  int statfs_op_cancel(ceph_tid_t tid, int r);
   void finish_statfs_op(StatfsOp *op);
 
   // ---------------------------
diff --git a/src/osdc/WritebackHandler.h b/src/osdc/WritebackHandler.h
index 17e1f68..4869837 100644
--- a/src/osdc/WritebackHandler.h
+++ b/src/osdc/WritebackHandler.h
@@ -28,12 +28,13 @@ class WritebackHandler {
    * @param snapid read snapid
    */
   virtual bool may_copy_on_write(const object_t& oid, uint64_t read_off, uint64_t read_len, snapid_t snapid) = 0;
-  virtual tid_t write(const object_t& oid, const object_locator_t& oloc,
-		      uint64_t off, uint64_t len, const SnapContext& snapc,
-		      const bufferlist &bl, utime_t mtime, uint64_t trunc_size,
-		      __u32 trunc_seq, Context *oncommit) = 0;
-  virtual tid_t lock(const object_t& oid, const object_locator_t& oloc, int op,
-		     int flags, Context *onack, Context *oncommit) {
+  virtual ceph_tid_t write(const object_t& oid, const object_locator_t& oloc,
+			   uint64_t off, uint64_t len, const SnapContext& snapc,
+			   const bufferlist &bl, utime_t mtime,
+			   uint64_t trunc_size, __u32 trunc_seq,
+			   Context *oncommit) = 0;
+  virtual ceph_tid_t lock(const object_t& oid, const object_locator_t& oloc,
+			  int op, int flags, Context *onack, Context *oncommit) {
     assert(0 == "this WritebackHandler does not support the lock operation");
   }
 };
diff --git a/src/pybind/ceph_argparse.py b/src/pybind/ceph_argparse.py
index 1f6e90b..8f2eb8f 100644
--- a/src/pybind/ceph_argparse.py
+++ b/src/pybind/ceph_argparse.py
@@ -1061,9 +1061,14 @@ def send_command(cluster, target=('mon', ''), cmd=None, inbuf='', timeout=0,
                 ret, outbuf, outs = cluster.mon_command(cmd, inbuf, timeout)
             else:
                 ret, outbuf, outs = cluster.mon_command(cmd, inbuf, timeout, target[1])
+        else:
+            raise ArgumentValid("Bad target type '{0}'".format(target[0]))
 
     except Exception as e:
-        raise RuntimeError('"{0}": exception {1}'.format(cmd, e))
+        if not isinstance(e, ArgumentError):
+            raise RuntimeError('"{0}": exception {1}'.format(cmd, e))
+        else:
+            raise
 
     return ret, outbuf, outs
 
@@ -1103,7 +1108,10 @@ def json_command(cluster, target=('mon', ''), prefix=None, argdict=None,
                                          inbuf, timeout, verbose)
 
     except Exception as e:
-        raise RuntimeError('"{0}": exception {1}'.format(prefix, e))
+        if not isinstance(e, ArgumentError):
+            raise RuntimeError('"{0}": exception {1}'.format(cmd, e))
+        else:
+            raise
 
     return ret, outbuf, outs
 
diff --git a/src/pybind/rados.py b/src/pybind/rados.py
index 0989ebb..098e200 100644
--- a/src/pybind/rados.py
+++ b/src/pybind/rados.py
@@ -429,13 +429,13 @@ Rados object in state %s." % (self.state))
 
         :returns: dict - contains the following keys:
 
-            *``kb`` (int) - total space 
+            - ``kb`` (int) - total space 
 
-            *``kb_used`` (int) - space used
+            - ``kb_used`` (int) - space used
 
-            *``kb_avail`` (int) - free space available
+            - ``kb_avail`` (int) - free space available
 
-            *``num_objects`` (int) - number of objects
+            - ``num_objects`` (int) - number of objects
 
         """
         stats = rados_cluster_stat_t()
@@ -1100,6 +1100,30 @@ class Ioctx(object):
             raise make_ex(ret, "error reading %s" % object_name)
         return completion
 
+    def aio_remove(self, object_name, oncomplete=None, onsafe=None):
+        """
+        Asychronously remove an object
+
+        :param object_name: name of the object to remove
+        :type object_name: str
+        :param oncomplete: what to do when the remove is safe and complete in memory
+            on all replicas
+        :type oncomplete: completion
+        :param onsafe:  what to do when the remove is safe and complete on storage
+            on all replicas
+        :type onsafe: completion
+
+        :raises: :class:`Error`
+        :returns: completion object
+        """
+        completion = self.__get_completion(oncomplete, onsafe)
+        ret = run_in_thread(self.librados.rados_aio_remove,
+                            (self.io, c_char_p(object_name),
+                            completion.rados_comp))
+        if ret < 0:
+            raise make_ex(ret, "error removing %s" % object_name)
+        return completion
+
     def require_ioctx_open(self):
         """
         Checks if the rados.Ioctx object state is 'open'
@@ -1238,7 +1262,7 @@ written." % (self.name, ret, length))
 
     def read(self, key, length=8192, offset=0):
         """
-        Write data to an object synchronously
+        Read data from an object synchronously
 
         :param key: name of the object
         :type key: str
@@ -1268,30 +1292,30 @@ written." % (self.name, ret, length))
 
         :returns: dict - contains the following keys:
 
-            *``num_bytes`` (int) - size of pool in bytes
+            - ``num_bytes`` (int) - size of pool in bytes
 
-            *``num_kb`` (int) - size of pool in kbytes
+            - ``num_kb`` (int) - size of pool in kbytes
 
-            *``num_objects`` (int) - number of objects in the pool
+            - ``num_objects`` (int) - number of objects in the pool
 
-            *``num_object_clones`` (int) - number of object clones
+            - ``num_object_clones`` (int) - number of object clones
 
-            *``num_object_copies`` (int) - number of object copies
+            - ``num_object_copies`` (int) - number of object copies
 
-            *``num_objects_missing_on_primary`` (int) - number of objets
+            - ``num_objects_missing_on_primary`` (int) - number of objets
                 missing on primary
 
-            *``num_objects_unfound`` (int) - number of unfound objects
+            - ``num_objects_unfound`` (int) - number of unfound objects
 
-            *``num_objects_degraded`` (int) - number of degraded objects
+            - ``num_objects_degraded`` (int) - number of degraded objects
 
-            *``num_rd`` (int) - bytes read
+            - ``num_rd`` (int) - bytes read
 
-            *``num_rd_kb`` (int) - kbytes read
+            - ``num_rd_kb`` (int) - kbytes read
 
-            *``num_wr`` (int) - bytes written
+            - ``num_wr`` (int) - bytes written
 
-            *``num_wr_kb`` (int) - kbytes written
+            - ``num_wr_kb`` (int) - kbytes written
         """
         self.require_ioctx_open()
         stats = rados_pool_stat_t()
diff --git a/src/rbd.cc b/src/rbd.cc
index c6a3dcf..f8c4307 100644
--- a/src/rbd.cc
+++ b/src/rbd.cc
@@ -511,6 +511,10 @@ static int do_show_info(const char *imgname, librbd::Image& image,
       return r;
   }
 
+  char prefix[RBD_MAX_BLOCK_NAME_SIZE + 1];
+  strncpy(prefix, info.block_name_prefix, RBD_MAX_BLOCK_NAME_SIZE);
+  prefix[RBD_MAX_BLOCK_NAME_SIZE] = '\0';
+
   if (f) {
     f->open_object_section("image");
     f->dump_string("name", imgname);
@@ -518,7 +522,7 @@ static int do_show_info(const char *imgname, librbd::Image& image,
     f->dump_unsigned("objects", info.num_objs);
     f->dump_int("order", info.order);
     f->dump_unsigned("object_size", info.obj_size);
-    f->dump_string("block_name_prefix", info.block_name_prefix);
+    f->dump_string("block_name_prefix", prefix);
     f->dump_int("format", (old_format ? 1 : 2));
   } else {
     cout << "rbd image '" << imgname << "':\n"
@@ -528,7 +532,7 @@ static int do_show_info(const char *imgname, librbd::Image& image,
 	 << "\torder " << info.order
 	 << " (" << prettybyte_t(info.obj_size) << " objects)"
 	 << std::endl
-	 << "\tblock_name_prefix: " << info.block_name_prefix
+	 << "\tblock_name_prefix: " << prefix
 	 << std::endl
 	 << "\tformat: " << (old_format ? "1" : "2")
 	 << std::endl;
diff --git a/src/rgw/logrotate.conf b/src/rgw/logrotate.conf
index 7c6f74e..ec47f00 100644
--- a/src/rgw/logrotate.conf
+++ b/src/rgw/logrotate.conf
@@ -22,4 +22,5 @@
         fi
     endscript
     missingok
+    notifempty
 }
diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h
index 1be0587..4d7a118 100644
--- a/src/rgw/rgw_common.h
+++ b/src/rgw/rgw_common.h
@@ -71,7 +71,6 @@ using ceph::crypto::MD5;
 
 #define RGW_BUCKETS_OBJ_SUFFIX ".buckets"
 
-#define RGW_MAX_CHUNK_SIZE	(512*1024)
 #define RGW_MAX_PENDING_CHUNKS  16
 #define RGW_MAX_PUT_SIZE        (5ULL*1024*1024*1024)
 #define RGW_MIN_MULTIPART_SIZE (5ULL*1024*1024)
@@ -565,6 +564,7 @@ WRITE_CLASS_ENCODER(RGWUserInfo)
 struct rgw_bucket {
   std::string name;
   std::string data_pool;
+  std::string data_extra_pool; /* if not set, then we should use data_pool instead */
   std::string index_pool;
   std::string marker;
   std::string bucket_id;
@@ -577,6 +577,7 @@ struct rgw_bucket {
   rgw_bucket(const cls_user_bucket& b) {
     name = b.name;
     data_pool = b.data_pool;
+    data_extra_pool = b.data_extra_pool;
     index_pool = b.index_pool;
     marker = b.marker;
     bucket_id = b.bucket_id;
@@ -592,30 +593,24 @@ struct rgw_bucket {
   void convert(cls_user_bucket *b) {
     b->name = name;
     b->data_pool = data_pool;
+    b->data_extra_pool = data_extra_pool;
     b->index_pool = index_pool;
     b->marker = marker;
     b->bucket_id = bucket_id;
   }
 
-  void clear() {
-    name = "";
-    data_pool = "";
-    index_pool = "";
-    marker = "";
-    bucket_id = "";
-  }
-
   void encode(bufferlist& bl) const {
-     ENCODE_START(6, 3, bl);
+     ENCODE_START(7, 3, bl);
     ::encode(name, bl);
     ::encode(data_pool, bl);
     ::encode(marker, bl);
     ::encode(bucket_id, bl);
     ::encode(index_pool, bl);
+    ::encode(data_extra_pool, bl);
     ENCODE_FINISH(bl);
   }
   void decode(bufferlist::iterator& bl) {
-    DECODE_START_LEGACY_COMPAT_LEN(6, 3, 3, bl);
+    DECODE_START_LEGACY_COMPAT_LEN(7, 3, 3, bl);
     ::decode(name, bl);
     ::decode(data_pool, bl);
     if (struct_v >= 2) {
@@ -635,8 +630,19 @@ struct rgw_bucket {
     } else {
       index_pool = data_pool;
     }
+    if (struct_v >= 7) {
+      ::decode(data_extra_pool, bl);
+    }
     DECODE_FINISH(bl);
   }
+
+  const string& get_data_extra_pool() {
+    if (data_extra_pool.empty()) {
+      return data_pool;
+    }
+    return data_extra_pool;
+  }
+
   void dump(Formatter *f) const;
   void decode_json(JSONObj *obj);
   static void generate_test_instances(list<rgw_bucket*>& o);
@@ -651,8 +657,19 @@ inline ostream& operator<<(ostream& out, const rgw_bucket &b) {
   out << b.name;
   if (b.name.compare(b.data_pool)) {
     out << "(@";
+    string s;
     if (!b.index_pool.empty() && b.data_pool.compare(b.index_pool))
-      out << "{i=" << b.index_pool << "}";
+      s = "i=" + b.index_pool;
+    if (!b.data_extra_pool.empty() && b.data_pool.compare(b.data_extra_pool)) {
+      if (!s.empty()) {
+        s += ",";
+      }
+      s += "e=" + b.data_extra_pool;
+    }
+    if (!s.empty()) {
+      out << "{"  << s << "}";
+    }
+
     out << b.data_pool << "[" << b.marker << "])";
   }
   return out;
@@ -998,23 +1015,25 @@ public:
   std::string ns;
   std::string object;
 
-  rgw_obj() {}
-  rgw_obj(const char *b, const char *o) {
+  bool in_extra_data; /* in-memory only member, does not serialize */
+
+  rgw_obj() : in_extra_data(false) {}
+  rgw_obj(const char *b, const char *o) : in_extra_data(false) {
     rgw_bucket _b(b);
     std::string _o(o);
     init(_b, _o);
   }
-  rgw_obj(rgw_bucket& b, const char *o) {
+  rgw_obj(rgw_bucket& b, const char *o) : in_extra_data(false) {
     std::string _o(o);
     init(b, _o);
   }
-  rgw_obj(rgw_bucket& b, const std::string& o) {
+  rgw_obj(rgw_bucket& b, const std::string& o) : in_extra_data(false) {
     init(b, o);
   }
-  rgw_obj(rgw_bucket& b, const std::string& o, const std::string& k) {
+  rgw_obj(rgw_bucket& b, const std::string& o, const std::string& k) : in_extra_data(false) {
     init(b, o, k);
   }
-  rgw_obj(rgw_bucket& b, const std::string& o, const std::string& k, const std::string& n) {
+  rgw_obj(rgw_bucket& b, const std::string& o, const std::string& k, const std::string& n) : in_extra_data(false) {
     init(b, o, k, n);
   }
   void init(rgw_bucket& b, const std::string& o, const std::string& k, const std::string& n) {
@@ -1158,6 +1177,14 @@ public:
     return true;
   }
 
+  void set_in_extra_data(bool val) {
+    in_extra_data = val;
+  }
+
+  bool is_in_extra_data() const {
+    return in_extra_data;
+  }
+
   void encode(bufferlist& bl) const {
     ENCODE_START(3, 3, bl);
     ::encode(bucket.name, bl);
diff --git a/src/rgw/rgw_json_enc.cc b/src/rgw/rgw_json_enc.cc
index 81ec599..4df7daf 100644
--- a/src/rgw/rgw_json_enc.cc
+++ b/src/rgw/rgw_json_enc.cc
@@ -487,6 +487,7 @@ void rgw_bucket::dump(Formatter *f) const
 {
   encode_json("name", name, f);
   encode_json("pool", data_pool, f);
+  encode_json("data_extra_pool", data_extra_pool, f);
   encode_json("index_pool", index_pool, f);
   encode_json("marker", marker, f);
   encode_json("bucket_id", bucket_id, f);
@@ -495,6 +496,7 @@ void rgw_bucket::dump(Formatter *f) const
 void rgw_bucket::decode_json(JSONObj *obj) {
   JSONDecoder::decode_json("name", name, obj);
   JSONDecoder::decode_json("pool", data_pool, obj);
+  JSONDecoder::decode_json("data_extra_pool", data_extra_pool, obj);
   JSONDecoder::decode_json("index_pool", index_pool, obj);
   JSONDecoder::decode_json("marker", marker, obj);
   JSONDecoder::decode_json("bucket_id", bucket_id, obj);
@@ -614,12 +616,14 @@ void RGWZonePlacementInfo::dump(Formatter *f) const
 {
   encode_json("index_pool", index_pool, f);
   encode_json("data_pool", data_pool, f);
+  encode_json("data_extra_pool", data_extra_pool, f);
 }
 
 void RGWZonePlacementInfo::decode_json(JSONObj *obj)
 {
   JSONDecoder::decode_json("index_pool", index_pool, obj);
   JSONDecoder::decode_json("data_pool", data_pool, obj);
+  JSONDecoder::decode_json("data_extra_pool", data_extra_pool, obj);
 }
 
 void RGWZoneParams::decode_json(JSONObj *obj)
diff --git a/src/rgw/rgw_main.cc b/src/rgw/rgw_main.cc
index f104109..9614b07 100644
--- a/src/rgw/rgw_main.cc
+++ b/src/rgw/rgw_main.cc
@@ -93,13 +93,8 @@ struct RGWRequest
   RGWRequest() : id(0), s(NULL), op(NULL) {
   }
 
-  ~RGWRequest() {
-    delete s;
-  }
- 
-  req_state *init_state(CephContext *cct, RGWEnv *env) { 
-    s = new req_state(cct, env);
-    return s;
+  void init_state(req_state *_s) {
+    s = _s;
   }
 
   void log_format(struct req_state *s, const char *fmt, ...)
@@ -516,8 +511,12 @@ static int process_request(RGWRados *store, RGWREST *rest, RGWRequest *req, RGWC
 
   RGWEnv& rgw_env = client_io->get_env();
 
-  struct req_state *s = req->init_state(g_ceph_context, &rgw_env);
-  s->obj_ctx = store->create_context(s);
+  struct req_state rstate(g_ceph_context, &rgw_env);
+
+  struct req_state *s = &rstate;
+
+  RGWRadosCtx rados_ctx(store, s);
+  s->obj_ctx = &rados_ctx;
   store->set_intent_cb(s->obj_ctx, call_log_intent);
 
   s->req_id = store->unique_id(req->id);
@@ -616,7 +615,6 @@ done:
   if (handler)
     handler->put_op(op);
   rest->put_handler(handler);
-  store->destroy_context(s->obj_ctx);
 
   dout(1) << "====== req done req=" << hex << req << dec << " http_status=" << http_ret << " ======" << dendl;
 
diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc
index 074e7d8..f3501fb 100644
--- a/src/rgw/rgw_op.cc
+++ b/src/rgw/rgw_op.cc
@@ -280,6 +280,7 @@ static int read_policy(RGWRados *store, struct req_state *s,
     RGWMPObj mp(oid, upload_id);
     oid = mp.get_meta();
     obj.init_ns(bucket, oid, mp_ns);
+    obj.set_in_extra_data(true);
   } else {
     obj.init(bucket, oid);
   }
@@ -1457,6 +1458,7 @@ int RGWPutObjProcessor_Multipart::do_complete(string& etag, time_t *mtime, time_
 
   rgw_obj meta_obj;
   meta_obj.init_ns(bucket, multipart_meta_obj, mp_ns);
+  meta_obj.set_in_extra_data(true);
 
   r = store->omap_set(meta_obj, p, bl);
 
@@ -2387,6 +2389,7 @@ void RGWInitMultipart::execute()
 
     obj.init_ns(s->bucket, tmp_obj_name, mp_ns);
     // the meta object will be indexed with 0 size, we c
+    obj.set_in_extra_data(true);
     ret = store->put_obj_meta(s->obj_ctx, obj, 0, NULL, attrs, RGW_OBJ_CATEGORY_MULTIMETA, PUT_OBJ_CREATE_EXCL, s->owner.get_id());
   } while (ret == -EEXIST);
 }
@@ -2400,6 +2403,7 @@ static int get_multipart_info(RGWRados *store, struct req_state *s, string& meta
 
   rgw_obj obj;
   obj.init_ns(s->bucket, meta_oid, mp_ns);
+  obj.set_in_extra_data(true);
 
   int ret = get_obj_attrs(store, s, obj, attrs, NULL, NULL);
   if (ret < 0)
@@ -2438,6 +2442,7 @@ static int list_multipart_parts(RGWRados *store, struct req_state *s,
 
   rgw_obj obj;
   obj.init_ns(s->bucket, meta_oid, mp_ns);
+  obj.set_in_extra_data(true);
 
   bool sorted_omap = is_v2_upload_id(upload_id) && !assume_unsorted;
 
@@ -2682,6 +2687,7 @@ void RGWCompleteMultipart::execute()
 
   // remove the upload obj
   meta_obj.init_ns(s->bucket, meta_oid, mp_ns);
+  meta_obj.set_in_extra_data(true);
   store->delete_obj(s->obj_ctx, s->bucket_owner.get_id(), meta_obj);
 }
 
@@ -2755,6 +2761,7 @@ void RGWAbortMultipart::execute()
 
   // and also remove the metadata obj
   meta_obj.init_ns(s->bucket, meta_oid, mp_ns);
+  meta_obj.set_in_extra_data(true);
   ret = store->delete_obj(s->obj_ctx, owner, meta_obj);
   if (ret == -ENOENT) {
     ret = -ERR_NO_SUCH_BUCKET;
diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc
index cb82e05..405f00f 100644
--- a/src/rgw/rgw_rados.cc
+++ b/src/rgw/rgw_rados.cc
@@ -680,10 +680,11 @@ void RGWObjManifest::obj_iterator::operator++()
       part_ofs += rule->part_size;
       stripe_ofs = part_ofs;
 
+      bool last_rule = (next_rule_iter == manifest->rules.end());
       /* move to the next rule? */
-      if (next_rule_iter->second.start_ofs >= stripe_ofs) {
+      if (!last_rule && stripe_ofs >= next_rule_iter->second.start_ofs) {
         rule_iter = next_rule_iter;
-        bool last_rule = (next_rule_iter == manifest->rules.end());
+        last_rule = (next_rule_iter == manifest->rules.end());
         if (!last_rule) {
           ++next_rule_iter;
         }
@@ -1147,11 +1148,13 @@ int RGWPutObjProcessor_Atomic::handle_data(bufferlist& bl, off_t ofs, void **pha
     }
   }
 
+  uint64_t max_chunk_size = store->get_max_chunk_size();
+
   pending_data_bl.claim_append(bl);
-  if (pending_data_bl.length() < RGW_MAX_CHUNK_SIZE)
+  if (pending_data_bl.length() < max_chunk_size)
     return 0;
 
-  pending_data_bl.splice(0, RGW_MAX_CHUNK_SIZE, &bl);
+  pending_data_bl.splice(0, max_chunk_size, &bl);
 
   if (!data_ofs && !immutable_head()) {
     first_chunk.claim(bl);
@@ -1174,7 +1177,9 @@ int RGWPutObjProcessor_Atomic::prepare(RGWRados *store, void *obj_ctx)
 
   head_obj.init(bucket, obj_str);
 
-  manifest.set_trivial_rule(RGW_MAX_CHUNK_SIZE, store->ctx()->_conf->rgw_obj_stripe_size);
+  uint64_t max_chunk_size = store->get_max_chunk_size();
+
+  manifest.set_trivial_rule(max_chunk_size, store->ctx()->_conf->rgw_obj_stripe_size);
 
   int r = manifest_gen.create_begin(store->ctx(), &manifest, bucket, head_obj);
   if (r < 0) {
@@ -1332,6 +1337,8 @@ int RGWRados::init_rados()
 {
   int ret;
 
+  max_chunk_size = cct->_conf->rgw_max_chunk_size;
+
   rados = new Rados();
   if (!rados)
     return -ENOMEM;
@@ -1646,6 +1653,15 @@ int RGWRados::open_bucket_data_ctx(rgw_bucket& bucket, librados::IoCtx& data_ctx
   return 0;
 }
 
+int RGWRados::open_bucket_data_extra_ctx(rgw_bucket& bucket, librados::IoCtx& data_ctx)
+{
+  int r = open_bucket_pool_ctx(bucket.name, bucket.data_extra_pool, data_ctx);
+  if (r < 0)
+    return r;
+
+  return 0;
+}
+
 int RGWRados::open_bucket_index_ctx(rgw_bucket& bucket, librados::IoCtx& index_ctx)
 {
   int r = open_bucket_pool_ctx(bucket.name, bucket.index_pool, index_ctx);
@@ -2479,6 +2495,7 @@ int RGWRados::set_bucket_location_by_rule(const string& location_rule, const std
   RGWZonePlacementInfo& placement_info = piter->second;
 
   bucket.data_pool = placement_info.data_pool;
+  bucket.data_extra_pool = placement_info.data_extra_pool;
   bucket.index_pool = placement_info.index_pool;
 
   return 0;
@@ -2675,6 +2692,52 @@ int RGWRados::create_pools(vector<string>& names, vector<int>& retcodes)
   return 0;
 }
 
+
+int RGWRados::get_obj_ioctx(const rgw_obj& obj, librados::IoCtx *ioctx)
+{
+  rgw_bucket bucket;
+  string oid, key;
+  get_obj_bucket_and_oid_key(obj, bucket, oid, key);
+
+  int r;
+
+  if (!obj.is_in_extra_data()) {
+    r = open_bucket_data_ctx(bucket, *ioctx);
+  } else {
+    r = open_bucket_data_extra_ctx(bucket, *ioctx);
+  }
+  if (r < 0)
+    return r;
+
+  ioctx->locator_set_key(key);
+
+  return 0;
+}
+
+int RGWRados::get_obj_ref(const rgw_obj& obj, rgw_rados_ref *ref, rgw_bucket *bucket, bool ref_system_obj)
+{
+  get_obj_bucket_and_oid_key(obj, *bucket, ref->oid, ref->key);
+
+  int r;
+
+  if (ref_system_obj && ref->oid.empty()) {
+    ref->oid = bucket->name;
+    *bucket = zone.domain_root;
+
+    r = open_bucket_data_ctx(*bucket, ref->ioctx);
+  } else if (!obj.is_in_extra_data()) {
+    r = open_bucket_data_ctx(*bucket, ref->ioctx);
+  } else {
+    r = open_bucket_data_extra_ctx(*bucket, ref->ioctx);
+  }
+  if (r < 0)
+    return r;
+
+  ref->ioctx.locator_set_key(ref->key);
+
+  return 0;
+}
+
 /**
  * Write/overwrite an object to the bucket storage.
  * bucket: the bucket to store the object in
@@ -2700,16 +2763,12 @@ int RGWRados::put_obj_meta_impl(void *ctx, rgw_obj& obj,  uint64_t size,
                   const string& bucket_owner)
 {
   rgw_bucket bucket;
-  std::string oid, key;
-  get_obj_bucket_and_oid_key(obj, bucket, oid, key);
-  librados::IoCtx io_ctx;
-  RGWRadosCtx *rctx = static_cast<RGWRadosCtx *>(ctx);
-
-  int r = open_bucket_data_ctx(bucket, io_ctx);
+  rgw_rados_ref ref;
+  int r = get_obj_ref(obj, &ref, &bucket);
   if (r < 0)
     return r;
 
-  io_ctx.locator_set_key(key);
+  RGWRadosCtx *rctx = static_cast<RGWRadosCtx *>(ctx);
 
   ObjectWriteOperation op;
 
@@ -2802,7 +2861,7 @@ int RGWRados::put_obj_meta_impl(void *ctx, rgw_obj& obj,  uint64_t size,
   if (r < 0)
     return r;
 
-  r = io_ctx.operate(oid, &op);
+  r = ref.ioctx.operate(ref.oid, &op);
   if (r < 0) /* we can expect to get -ECANCELED if object was replaced under,
                 or -ENOENT if was removed, or -EEXIST if it did not exist
                 before and now it does */
@@ -2812,8 +2871,8 @@ int RGWRados::put_obj_meta_impl(void *ctx, rgw_obj& obj,  uint64_t size,
     objv_tracker->apply_write();
   }
 
-  epoch = io_ctx.get_last_version();
-  poolid = io_ctx.get_id();
+  epoch = ref.ioctx.get_last_version();
+  poolid = ref.ioctx.get_id();
 
   r = complete_atomic_overwrite(rctx, state, obj);
   if (r < 0) {
@@ -2882,16 +2941,12 @@ int RGWRados::aio_put_obj_data(void *ctx, rgw_obj& obj, bufferlist& bl,
 			       off_t ofs, bool exclusive,
                                void **handle)
 {
+  rgw_rados_ref ref;
   rgw_bucket bucket;
-  std::string oid, key;
-  get_obj_bucket_and_oid_key(obj, bucket, oid, key);
-  librados::IoCtx io_ctx;
-
-  int r = open_bucket_data_ctx(bucket, io_ctx);
-  if (r < 0)
+  int r = get_obj_ref(obj, &ref, &bucket);
+  if (r < 0) {
     return r;
-
-  io_ctx.locator_set_key(key);
+  }
 
   AioCompletion *c = librados::Rados::aio_create_completion(NULL, NULL, NULL);
   *handle = c;
@@ -2906,7 +2961,7 @@ int RGWRados::aio_put_obj_data(void *ctx, rgw_obj& obj, bufferlist& bl,
   } else {
     op.write(ofs, bl);
   }
-  r = io_ctx.aio_operate(oid, c, &op);
+  r = ref.ioctx.aio_operate(ref.oid, c, &op);
   if (r < 0)
     return r;
 
@@ -3185,8 +3240,9 @@ set_err_state:
       copy_data = true;
     } else {
       uint64_t head_size = astate->manifest.get_head_size();
+
       if (head_size > 0) {
-	if (head_size > RGW_MAX_CHUNK_SIZE)  // should never happen
+	if (head_size > max_chunk_size)  // should never happen
 	  copy_data = true;
 	else
           copy_first = true;
@@ -3224,15 +3280,13 @@ set_err_state:
   if (copy_first) // we need to copy first chunk, not increase refcount
     ++miter;
 
-  string oid, key;
+  rgw_rados_ref ref;
   rgw_bucket bucket;
-  get_obj_bucket_and_oid_key(miter.get_location(), bucket, oid, key);
-  librados::IoCtx io_ctx;
-  PutObjMetaExtraParams ep;
-
-  ret = open_bucket_data_ctx(bucket, io_ctx);
-  if (ret < 0)
+  ret = get_obj_ref(miter.get_location(), &ref, &bucket);
+  if (ret < 0) {
     return ret;
+  }
+  PutObjMetaExtraParams ep;
 
   bufferlist first_chunk;
 
@@ -3256,14 +3310,15 @@ set_err_state:
     if (tail_bucket.name.empty()) {
       manifest.set_tail_bucket(src_obj.bucket);
     }
+    string oid, key;
     for (; miter != astate->manifest.obj_end(); ++miter) {
       ObjectWriteOperation op;
       cls_refcount_get(op, tag, true);
       const rgw_obj& loc = miter.get_location();
       get_obj_bucket_and_oid_key(loc, bucket, oid, key);
-      io_ctx.locator_set_key(key);
+      ref.ioctx.locator_set_key(key);
 
-      ret = io_ctx.operate(oid, &op);
+      ret = ref.ioctx.operate(oid, &op);
       if (ret < 0)
         goto done_ret;
 
@@ -3278,7 +3333,7 @@ set_err_state:
   }
 
   if (copy_first) {
-    ret = get_obj(ctx, NULL, &handle, src_obj, first_chunk, 0, RGW_MAX_CHUNK_SIZE);
+    ret = get_obj(ctx, NULL, &handle, src_obj, first_chunk, 0, max_chunk_size);
     if (ret < 0)
       goto done_ret;
 
@@ -3302,15 +3357,17 @@ done_ret:
   if (!copy_itself) {
     vector<rgw_obj>::iterator riter;
 
+    string oid, key;
+
     /* rollback reference */
     for (riter = ref_objs.begin(); riter != ref_objs.end(); ++riter) {
       ObjectWriteOperation op;
       cls_refcount_put(op, tag, true);
 
       get_obj_bucket_and_oid_key(*riter, bucket, oid, key);
-      io_ctx.locator_set_key(key);
+      ref.ioctx.locator_set_key(key);
 
-      int r = io_ctx.operate(oid, &op);
+      int r = ref.ioctx.operate(oid, &op);
       if (r < 0) {
         ldout(cct, 0) << "ERROR: cleanup after error failed to drop reference on obj=" << *riter << dendl;
       }
@@ -3355,8 +3412,8 @@ int RGWRados::copy_obj_data(void *ctx,
 
     const char *data = bl.c_str();
 
-    if (ofs < RGW_MAX_CHUNK_SIZE) {
-      off_t len = min(RGW_MAX_CHUNK_SIZE - ofs, (off_t)ret);
+    if ((uint64_t)ofs < max_chunk_size) {
+      uint64_t len = min(max_chunk_size - ofs, (uint64_t)ret);
       first_chunk.append(data, len);
       ofs += len;
       ret -= len;
@@ -3380,11 +3437,11 @@ int RGWRados::copy_obj_data(void *ctx,
   first_part->loc_ofs = 0;
   first_part->size = first_chunk.length();
 
-  if (ofs > RGW_MAX_CHUNK_SIZE) {
-    RGWObjManifestPart& tail = objs[RGW_MAX_CHUNK_SIZE];
+  if ((uint64_t)ofs > max_chunk_size) {
+    RGWObjManifestPart& tail = objs[max_chunk_size];
     tail.loc = shadow_obj;
-    tail.loc_ofs = RGW_MAX_CHUNK_SIZE;
-    tail.size = ofs - RGW_MAX_CHUNK_SIZE;
+    tail.loc_ofs = max_chunk_size;
+    tail.size = ofs - max_chunk_size;
   }
 
   manifest.set_explicit(ofs, objs);
@@ -3653,16 +3710,13 @@ int RGWRados::defer_gc(void *ctx, rgw_obj& obj)
  */
 int RGWRados::delete_obj_impl(void *ctx, const string& bucket_owner, rgw_obj& obj, RGWObjVersionTracker *objv_tracker)
 {
+  rgw_rados_ref ref;
   rgw_bucket bucket;
-  std::string oid, key;
-  get_obj_bucket_and_oid_key(obj, bucket, oid, key);
-  librados::IoCtx io_ctx;
-  RGWRadosCtx *rctx = static_cast<RGWRadosCtx *>(ctx);
-  int r = open_bucket_data_ctx(bucket, io_ctx);
-  if (r < 0)
+  int r = get_obj_ref(obj, &ref, &bucket);
+  if (r < 0) {
     return r;
-
-  io_ctx.locator_set_key(key);
+  }
+  RGWRadosCtx *rctx = static_cast<RGWRadosCtx *>(ctx);
 
   ObjectWriteOperation op;
 
@@ -3683,12 +3737,12 @@ int RGWRados::delete_obj_impl(void *ctx, const string& bucket_owner, rgw_obj& ob
   }
 
   cls_refcount_put(op, tag, true);
-  r = io_ctx.operate(oid, &op);
+  r = ref.ioctx.operate(ref.oid, &op);
   bool removed = (r >= 0);
 
-  int64_t poolid = io_ctx.get_id();
+  int64_t poolid = ref.ioctx.get_id();
   if (r >= 0 || r == -ENOENT) {
-    uint64_t epoch = io_ctx.get_last_version();
+    uint64_t epoch = ref.ioctx.get_last_version();
     r = complete_update_index_del(bucket, obj.object, tag, poolid, epoch);
   } else {
     int ret = complete_update_index_cancel(bucket, obj.object, tag);
@@ -3860,24 +3914,13 @@ int RGWRados::get_obj_state(RGWRadosCtx *rctx, rgw_obj& obj, RGWObjState **state
  */
 int RGWRados::get_attr(void *ctx, rgw_obj& obj, const char *name, bufferlist& dest)
 {
+  rgw_rados_ref ref;
   rgw_bucket bucket;
-  std::string oid, key;
-  get_obj_bucket_and_oid_key(obj, bucket, oid, key);
-  librados::IoCtx io_ctx;
-  rgw_bucket actual_bucket = bucket;
-  string actual_obj = oid;
-  RGWRadosCtx *rctx = static_cast<RGWRadosCtx *>(ctx);
-
-  if (actual_obj.size() == 0) {
-    actual_obj = bucket.name;
-    actual_bucket = zone.domain_root;
-  }
-
-  int r = open_bucket_data_ctx(actual_bucket, io_ctx);
-  if (r < 0)
+  int r = get_obj_ref(obj, &ref, &bucket, true);
+  if (r < 0) {
     return r;
-
-  io_ctx.locator_set_key(key);
+  }
+  RGWRadosCtx *rctx = static_cast<RGWRadosCtx *>(ctx);
 
   if (rctx) {
     RGWObjState *state;
@@ -3896,7 +3939,7 @@ int RGWRados::get_attr(void *ctx, rgw_obj& obj, const char *name, bufferlist& de
   int rval;
   op.getxattr(name, &dest, &rval);
   
-  r = io_ctx.operate(actual_obj, &op, NULL);
+  r = ref.ioctx.operate(ref.oid, &op, NULL);
   if (r < 0)
     return r;
 
@@ -4016,24 +4059,13 @@ int RGWRados::set_attrs(void *ctx, rgw_obj& obj,
                         map<string, bufferlist>* rmattrs,
                         RGWObjVersionTracker *objv_tracker)
 {
+  rgw_rados_ref ref;
   rgw_bucket bucket;
-  std::string oid, key;
-  get_obj_bucket_and_oid_key(obj, bucket, oid, key);
-  librados::IoCtx io_ctx;
-  string actual_obj = oid;
-  RGWRadosCtx *rctx = static_cast<RGWRadosCtx *>(ctx);
-  rgw_bucket actual_bucket = bucket;
-
-  if (actual_obj.size() == 0) {
-    actual_obj = bucket.name;
-    actual_bucket = zone.domain_root;
-  }
-
-  int r = open_bucket_data_ctx(actual_bucket, io_ctx);
-  if (r < 0)
+  int r = get_obj_ref(obj, &ref, &bucket, true);
+  if (r < 0) {
     return r;
-
-  io_ctx.locator_set_key(key);
+  }
+  RGWRadosCtx *rctx = static_cast<RGWRadosCtx *>(ctx);
 
   ObjectWriteOperation op;
   RGWObjState *state = NULL;
@@ -4067,7 +4099,7 @@ int RGWRados::set_attrs(void *ctx, rgw_obj& obj,
   if (!op.size())
     return 0;
 
-  r = io_ctx.operate(actual_obj, &op);
+  r = ref.ioctx.operate(ref.oid, &op);
   if (r < 0)
     return r;
 
@@ -4122,10 +4154,6 @@ int RGWRados::prepare_get_obj(void *ctx, rgw_obj& obj,
             void **handle,
             struct rgw_err *err)
 {
-  rgw_bucket bucket;
-  std::string oid, key;
-  get_obj_bucket_and_oid_key(obj, bucket, oid, key);
-  int r = -EINVAL;
   bufferlist etag;
   time_t ctime;
   RGWRadosCtx *rctx = static_cast<RGWRadosCtx *>(ctx);
@@ -4144,11 +4172,11 @@ int RGWRados::prepare_get_obj(void *ctx, rgw_obj& obj,
 
   *handle = state;
 
-  r = open_bucket_data_ctx(bucket, state->io_ctx);
-  if (r < 0)
-    goto done_err;
-
-  state->io_ctx.locator_set_key(key);
+  int r = get_obj_ioctx(obj, &state->io_ctx);
+  if (r < 0) {
+    delete state;
+    return r;
+  }
 
   if (!rctx) {
     new_ctx = new RGWRadosCtx(this);
@@ -4518,8 +4546,8 @@ int RGWRados::get_obj(void *ctx, RGWObjVersionTracker *objv_tracker, void **hand
     }
   }
 
-  if (len > RGW_MAX_CHUNK_SIZE)
-    len = RGW_MAX_CHUNK_SIZE;
+  if (len > max_chunk_size)
+    len = max_chunk_size;
 
 
   state->io_ctx.locator_set_key(key);
@@ -4532,7 +4560,7 @@ int RGWRados::get_obj(void *ctx, RGWObjVersionTracker *objv_tracker, void **hand
     if (r < 0)
       goto done_ret;
 
-    if (astate) {
+    if (astate && astate->prefetch_data) {
       if (!ofs && astate->data.length() >= len) {
         bl = astate->data;
         goto done;
@@ -5049,17 +5077,14 @@ done_err:
 /* a simple object read */
 int RGWRados::read(void *ctx, rgw_obj& obj, off_t ofs, size_t size, bufferlist& bl)
 {
+  rgw_rados_ref ref;
   rgw_bucket bucket;
-  std::string oid, key;
-  get_obj_bucket_and_oid_key(obj, bucket, oid, key);
-  librados::IoCtx io_ctx;
+  int r = get_obj_ref(obj, &ref, &bucket);
+  if (r < 0) {
+    return r;
+  }
   RGWRadosCtx *rctx = static_cast<RGWRadosCtx *>(ctx);
   RGWObjState *astate = NULL;
-  int r = open_bucket_data_ctx(bucket, io_ctx);
-  if (r < 0)
-    return r;
-
-  io_ctx.locator_set_key(key);
 
   ObjectReadOperation op;
 
@@ -5069,21 +5094,18 @@ int RGWRados::read(void *ctx, rgw_obj& obj, off_t ofs, size_t size, bufferlist&
 
   op.read(ofs, size, &bl, NULL);
 
-  return io_ctx.operate(oid, &op, NULL);
+  return ref.ioctx.operate(ref.oid, &op, NULL);
 }
 
 int RGWRados::obj_stat(void *ctx, rgw_obj& obj, uint64_t *psize, time_t *pmtime, uint64_t *epoch, map<string, bufferlist> *attrs, bufferlist *first_chunk,
                        RGWObjVersionTracker *objv_tracker)
 {
+  rgw_rados_ref ref;
   rgw_bucket bucket;
-  std::string oid, key;
-  get_obj_bucket_and_oid_key(obj, bucket, oid, key);
-  librados::IoCtx io_ctx;
-  int r = open_bucket_data_ctx(bucket, io_ctx);
-  if (r < 0)
+  int r = get_obj_ref(obj, &ref, &bucket);
+  if (r < 0) {
     return r;
-
-  io_ctx.locator_set_key(key);
+  }
 
   map<string, bufferlist> unfiltered_attrset;
   uint64_t size = 0;
@@ -5096,13 +5118,13 @@ int RGWRados::obj_stat(void *ctx, rgw_obj& obj, uint64_t *psize, time_t *pmtime,
   op.getxattrs(&unfiltered_attrset, NULL);
   op.stat(&size, &mtime, NULL);
   if (first_chunk) {
-    op.read(0, RGW_MAX_CHUNK_SIZE, first_chunk, NULL);
+    op.read(0, cct->_conf->rgw_max_chunk_size, first_chunk, NULL);
   }
   bufferlist outbl;
-  r = io_ctx.operate(oid, &op, &outbl);
+  r = ref.ioctx.operate(ref.oid, &op, &outbl);
 
   if (epoch)
-    *epoch = io_ctx.get_last_version();
+    *epoch = ref.ioctx.get_last_version();
 
   if (r < 0)
     return r;
@@ -5469,18 +5491,14 @@ int RGWRados::put_linked_bucket_info(RGWBucketInfo& info, bool exclusive, time_t
 
 int RGWRados::omap_get_vals(rgw_obj& obj, bufferlist& header, const string& marker, uint64_t count, std::map<string, bufferlist>& m)
 {
-  bufferlist bl;
-  librados::IoCtx io_ctx;
+  rgw_rados_ref ref;
   rgw_bucket bucket;
-  std::string oid, key;
-  get_obj_bucket_and_oid_key(obj, bucket, oid, key);
-  int r = open_bucket_data_ctx(bucket, io_ctx);
-  if (r < 0)
+  int r = get_obj_ref(obj, &ref, &bucket);
+  if (r < 0) {
     return r;
+  }
 
-  io_ctx.locator_set_key(key);
-
-  r = io_ctx.omap_get_vals(oid, marker, count, &m);
+  r = ref.ioctx.omap_get_vals(ref.oid, marker, count, &m);
   if (r < 0)
     return r;
 
@@ -5497,62 +5515,49 @@ int RGWRados::omap_get_all(rgw_obj& obj, bufferlist& header, std::map<string, bu
 
 int RGWRados::omap_set(rgw_obj& obj, std::string& key, bufferlist& bl)
 {
+  rgw_rados_ref ref;
   rgw_bucket bucket;
-  std::string oid, okey;
-  get_obj_bucket_and_oid_key(obj, bucket, oid, okey);
-
-  ldout(cct, 15) << "omap_set bucket=" << bucket << " oid=" << oid << " key=" << key << dendl;
-
-  librados::IoCtx io_ctx;
-  int r = open_bucket_data_ctx(bucket, io_ctx);
-  if (r < 0)
+  int r = get_obj_ref(obj, &ref, &bucket);
+  if (r < 0) {
     return r;
-
-  io_ctx.locator_set_key(okey);
+  }
+  ldout(cct, 15) << "omap_set bucket=" << bucket << " oid=" << ref.oid << " key=" << key << dendl;
 
   map<string, bufferlist> m;
   m[key] = bl;
 
-  r = io_ctx.omap_set(oid, m);
+  r = ref.ioctx.omap_set(ref.oid, m);
 
   return r;
 }
 
 int RGWRados::omap_set(rgw_obj& obj, std::map<std::string, bufferlist>& m)
 {
+  rgw_rados_ref ref;
   rgw_bucket bucket;
-  std::string oid, key;
-  get_obj_bucket_and_oid_key(obj, bucket, oid, key);
-
-  librados::IoCtx io_ctx;
-  int r = open_bucket_data_ctx(bucket, io_ctx);
-  if (r < 0)
+  int r = get_obj_ref(obj, &ref, &bucket);
+  if (r < 0) {
     return r;
+  }
 
-  io_ctx.locator_set_key(key);
-
-  r = io_ctx.omap_set(oid, m);
+  r = ref.ioctx.omap_set(ref.oid, m);
 
   return r;
 }
 
 int RGWRados::omap_del(rgw_obj& obj, const std::string& key)
 {
+  rgw_rados_ref ref;
   rgw_bucket bucket;
-  std::string oid, okey;
-  get_obj_bucket_and_oid_key(obj, bucket, oid, okey);
-
-  librados::IoCtx io_ctx;
-  int r = open_bucket_data_ctx(bucket, io_ctx);
-  if (r < 0)
+  int r = get_obj_ref(obj, &ref, &bucket);
+  if (r < 0) {
     return r;
-
-  io_ctx.locator_set_key(okey);
+  }
 
   set<string> k;
   k.insert(key);
 
-  r = io_ctx.omap_rm_keys(oid, k);
+  r = ref.ioctx.omap_rm_keys(ref.oid, k);
   return r;
 }
 
@@ -5586,18 +5591,15 @@ int RGWRados::update_containers_stats(map<string, RGWBucketEnt>& m)
 
 int RGWRados::append_async(rgw_obj& obj, size_t size, bufferlist& bl)
 {
+  rgw_rados_ref ref;
   rgw_bucket bucket;
-  std::string oid, key;
-  get_obj_bucket_and_oid_key(obj, bucket, oid, key);
-  librados::IoCtx io_ctx;
-  int r = open_bucket_data_ctx(bucket, io_ctx);
-  if (r < 0)
+  int r = get_obj_ref(obj, &ref, &bucket);
+  if (r < 0) {
     return r;
+  }
   librados::AioCompletion *completion = rados->aio_create_completion(NULL, NULL, NULL);
 
-  io_ctx.locator_set_key(key);
-
-  r = io_ctx.aio_append(oid, completion, bl, size);
+  r = ref.ioctx.aio_append(ref.oid, completion, bl, size);
   completion->release();
   return r;
 }
@@ -6168,19 +6170,18 @@ int RGWRados::cls_user_get_header(const string& user_id, cls_user_header *header
   rgw_get_buckets_obj(user_id, buckets_obj_id);
   rgw_obj obj(zone.user_uid_pool, buckets_obj_id);
 
-  librados::IoCtx io_ctx;
+  rgw_rados_ref ref;
   rgw_bucket bucket;
-  std::string oid, key;
-  get_obj_bucket_and_oid_key(obj, bucket, oid, key);
-  int r = open_bucket_data_ctx(bucket, io_ctx);
-  if (r < 0)
+  int r = get_obj_ref(obj, &ref, &bucket);
+  if (r < 0) {
     return r;
+  }
 
   librados::ObjectReadOperation op;
   int rc;
   ::cls_user_get_header(op, header, &rc);
   bufferlist ibl;
-  r = io_ctx.operate(oid, &op, &ibl);
+  r = ref.ioctx.operate(ref.oid, &op, &ibl);
   if (r < 0)
     return r;
   if (rc < 0)
@@ -6195,15 +6196,14 @@ int RGWRados::cls_user_get_header_async(const string& user_id, RGWGetUserHeader_
   rgw_get_buckets_obj(user_id, buckets_obj_id);
   rgw_obj obj(zone.user_uid_pool, buckets_obj_id);
 
-  librados::IoCtx io_ctx;
+  rgw_rados_ref ref;
   rgw_bucket bucket;
-  std::string oid, key;
-  get_obj_bucket_and_oid_key(obj, bucket, oid, key);
-  int r = open_bucket_data_ctx(bucket, io_ctx);
-  if (r < 0)
+  int r = get_obj_ref(obj, &ref, &bucket);
+  if (r < 0) {
     return r;
+  }
 
-  r = ::cls_user_get_header_async(io_ctx, oid, ctx);
+  r = ::cls_user_get_header_async(ref.ioctx, ref.oid, ctx);
   if (r < 0)
     return r;
 
@@ -6272,20 +6272,19 @@ int RGWRados::cls_user_list_buckets(rgw_obj& obj,
                                     list<cls_user_bucket_entry>& entries,
                                     string *out_marker, bool *truncated)
 {
-  librados::IoCtx io_ctx;
+  rgw_rados_ref ref;
   rgw_bucket bucket;
-  std::string oid, key;
-  get_obj_bucket_and_oid_key(obj, bucket, oid, key);
-  int r = open_bucket_data_ctx(bucket, io_ctx);
-  if (r < 0)
+  int r = get_obj_ref(obj, &ref, &bucket);
+  if (r < 0) {
     return r;
+  }
 
   librados::ObjectReadOperation op;
   int rc;
 
   cls_user_bucket_list(op, in_marker, max_entries, entries, out_marker, truncated, &rc);
   bufferlist ibl;
-  r = io_ctx.operate(oid, &op, &ibl);
+  r = ref.ioctx.operate(ref.oid, &op, &ibl);
   if (r < 0)
     return r;
   if (rc < 0)
@@ -6296,18 +6295,16 @@ int RGWRados::cls_user_list_buckets(rgw_obj& obj,
 
 int RGWRados::cls_user_update_buckets(rgw_obj& obj, list<cls_user_bucket_entry>& entries, bool add)
 {
-  bufferlist bl;
-  librados::IoCtx io_ctx;
+  rgw_rados_ref ref;
   rgw_bucket bucket;
-  std::string oid, key;
-  get_obj_bucket_and_oid_key(obj, bucket, oid, key);
-  int r = open_bucket_data_ctx(bucket, io_ctx);
-  if (r < 0)
+  int r = get_obj_ref(obj, &ref, &bucket);
+  if (r < 0) {
     return r;
+  }
 
   librados::ObjectWriteOperation op;
   cls_user_set_buckets(op, entries, add);
-  r = io_ctx.operate(oid, &op);
+  r = ref.ioctx.operate(ref.oid, &op);
   if (r < 0)
     return r;
 
@@ -6324,18 +6321,16 @@ int RGWRados::complete_sync_user_stats(const string& user_id)
 
 int RGWRados::cls_user_complete_stats_sync(rgw_obj& obj)
 {
-  bufferlist bl;
-  librados::IoCtx io_ctx;
+  rgw_rados_ref ref;
   rgw_bucket bucket;
-  std::string oid, key;
-  get_obj_bucket_and_oid_key(obj, bucket, oid, key);
-  int r = open_bucket_data_ctx(bucket, io_ctx);
-  if (r < 0)
+  int r = get_obj_ref(obj, &ref, &bucket);
+  if (r < 0) {
     return r;
+  }
 
   librados::ObjectWriteOperation op;
   ::cls_user_complete_stats_sync(op);
-  r = io_ctx.operate(oid, &op);
+  r = ref.ioctx.operate(ref.oid, &op);
   if (r < 0)
     return r;
 
@@ -6352,18 +6347,16 @@ int RGWRados::cls_user_add_bucket(rgw_obj& obj, const cls_user_bucket_entry& ent
 
 int RGWRados::cls_user_remove_bucket(rgw_obj& obj, const cls_user_bucket& bucket)
 {
-  bufferlist bl;
-  librados::IoCtx io_ctx;
   rgw_bucket b;
-  std::string oid, key;
-  get_obj_bucket_and_oid_key(obj, b, oid, key);
-  int r = open_bucket_data_ctx(b, io_ctx);
-  if (r < 0)
+  rgw_rados_ref ref;
+  int r = get_obj_ref(obj, &ref, &b);
+  if (r < 0) {
     return r;
+  }
 
   librados::ObjectWriteOperation op;
   ::cls_user_remove_bucket(op, bucket);
-  r = io_ctx.operate(oid, &op);
+  r = ref.ioctx.operate(ref.oid, &op);
   if (r < 0)
     return r;
 
diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h
index f6a810e..b0c233b 100644
--- a/src/rgw/rgw_rados.h
+++ b/src/rgw/rgw_rados.h
@@ -470,7 +470,8 @@ public:
     RGWObjManifestRule rule;
 
   public:
-    generator() : last_ofs(0), cur_part_ofs(0), cur_part_id(0), cur_stripe(0), cur_stripe_size(0) {}
+    generator() : manifest(NULL), last_ofs(0), cur_part_ofs(0), cur_part_id(0), 
+		  cur_stripe(0), cur_stripe_size(0) {}
     int create_begin(CephContext *cct, RGWObjManifest *manifest, rgw_bucket& bucket, rgw_obj& head);
 
     int create_next(uint64_t ofs);
@@ -702,6 +703,7 @@ struct RGWRadosCtx {
   void *user_ctx;
 
   RGWRadosCtx(RGWRados *_store) : store(_store), intent_cb(NULL), user_ctx(NULL) { }
+  RGWRadosCtx(RGWRados *_store, void *_user_ctx) : store(_store), intent_cb(NULL), user_ctx(_user_ctx) { }
 
   RGWObjState *get_state(rgw_obj& obj);
   void set_atomic(rgw_obj& obj);
@@ -737,20 +739,31 @@ struct RGWRegion;
 struct RGWZonePlacementInfo {
   string index_pool;
   string data_pool;
+  string data_extra_pool; /* if not set we should use data_pool */
 
   void encode(bufferlist& bl) const {
-    ENCODE_START(3, 1, bl);
+    ENCODE_START(4, 1, bl);
     ::encode(index_pool, bl);
     ::encode(data_pool, bl);
+    ::encode(data_extra_pool, bl);
     ENCODE_FINISH(bl);
   }
 
   void decode(bufferlist::iterator& bl) {
-    DECODE_START(1, bl);
+    DECODE_START(4, bl);
     ::decode(index_pool, bl);
     ::decode(data_pool, bl);
+    if (struct_v >= 4) {
+      ::decode(data_extra_pool, bl);
+    }
     DECODE_FINISH(bl);
   }
+  const string& get_data_extra_pool() {
+    if (data_extra_pool.empty()) {
+      return data_pool;
+    }
+    return data_extra_pool;
+  }
   void dump(Formatter *f) const;
   void decode_json(JSONObj *obj);
 };
@@ -931,7 +944,7 @@ struct RGWRegion {
   CephContext *cct;
   RGWRados *store;
 
-  RGWRegion() : is_master(false) {}
+  RGWRegion() : is_master(false), cct(NULL), store(NULL) {}
 
   void encode(bufferlist& bl) const {
     ENCODE_START(1, 1, bl);
@@ -1144,6 +1157,12 @@ public:
 class RGWGetDirHeader_CB;
 class RGWGetUserHeader_CB;
 
+struct rgw_rados_ref {
+  string oid;
+  string key;
+  librados::IoCtx ioctx;
+};
+
 
 class RGWRados
 {
@@ -1158,6 +1177,7 @@ class RGWRados
   int open_bucket_pool_ctx(const string& bucket_name, const string& pool, librados::IoCtx&  io_ctx);
   int open_bucket_index_ctx(rgw_bucket& bucket, librados::IoCtx&  index_ctx);
   int open_bucket_data_ctx(rgw_bucket& bucket, librados::IoCtx&  io_ctx);
+  int open_bucket_data_extra_ctx(rgw_bucket& bucket, librados::IoCtx&  io_ctx);
   int open_bucket_index(rgw_bucket& bucket, librados::IoCtx&  index_ctx, string& bucket_oid);
 
   struct GetObjState {
@@ -1191,8 +1211,13 @@ class RGWRados
   bool watch_initialized;
 
   Mutex bucket_id_lock;
+
+  int get_obj_ioctx(const rgw_obj& obj, librados::IoCtx *ioctx);
+  int get_obj_ref(const rgw_obj& obj, rgw_rados_ref *ref, rgw_bucket *bucket, bool ref_system_obj = false);
   uint64_t max_bucket_id;
 
+  uint64_t max_chunk_size;
+
   int get_obj_state(RGWRadosCtx *rctx, rgw_obj& obj, RGWObjState **state, RGWObjVersionTracker *objv_tracker);
   int append_atomic_test(RGWRadosCtx *rctx, rgw_obj& obj,
                          librados::ObjectOperation& op, RGWObjState **state);
@@ -1257,6 +1282,7 @@ public:
                num_watchers(0), watchers(NULL), watch_handles(NULL),
                watch_initialized(false),
                bucket_id_lock("rados_bucket_id"), max_bucket_id(0),
+               max_chunk_size(0),
                cct(NULL), rados(NULL),
                pools_initialized(false),
                quota_handler(NULL),
@@ -1294,6 +1320,10 @@ public:
     }
   }
 
+  uint64_t get_max_chunk_size() {
+    return max_chunk_size;
+  }
+
   int list_raw_objects(rgw_bucket& pool, const string& prefix_filter, int max,
                        RGWListRawObjsCtx& ctx, list<string>& oids,
                        bool *is_truncated);
diff --git a/src/rgw/rgw_rest.cc b/src/rgw/rgw_rest.cc
index 2201d4f..6473c61 100644
--- a/src/rgw/rgw_rest.cc
+++ b/src/rgw/rgw_rest.cc
@@ -708,12 +708,13 @@ int RGWPutObj_ObjStore::get_params()
 int RGWPutObj_ObjStore::get_data(bufferlist& bl)
 {
   size_t cl;
+  uint64_t chunk_size = s->cct->_conf->rgw_max_chunk_size;
   if (s->length) {
     cl = atoll(s->length) - ofs;
-    if (cl > RGW_MAX_CHUNK_SIZE)
-      cl = RGW_MAX_CHUNK_SIZE;
+    if (cl > chunk_size)
+      cl = chunk_size;
   } else {
-    cl = RGW_MAX_CHUNK_SIZE;
+    cl = chunk_size;
   }
 
   int len = 0;
diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc
index 9dfede4..b28c2a9 100644
--- a/src/rgw/rgw_rest_s3.cc
+++ b/src/rgw/rgw_rest_s3.cc
@@ -711,7 +711,8 @@ int RGWPostObj_ObjStore_S3::read_form_part_header(struct post_form_part *part,
 {
   bufferlist bl;
   bool reached_boundary;
-  int r = read_line(bl, RGW_MAX_CHUNK_SIZE, &reached_boundary, done);
+  uint64_t chunk_size = s->cct->_conf->rgw_max_chunk_size;
+  int r = read_line(bl, chunk_size, &reached_boundary, done);
   if (r < 0)
     return r;
 
@@ -720,7 +721,7 @@ int RGWPostObj_ObjStore_S3::read_form_part_header(struct post_form_part *part,
   }
 
   if (reached_boundary) { // skip the first boundary
-    r = read_line(bl, RGW_MAX_CHUNK_SIZE, &reached_boundary, done);
+    r = read_line(bl, chunk_size, &reached_boundary, done);
     if (r < 0)
       return r;
     if (*done)
@@ -752,7 +753,7 @@ int RGWPostObj_ObjStore_S3::read_form_part_header(struct post_form_part *part,
     if (reached_boundary)
       break;
 
-    r = read_line(bl, RGW_MAX_CHUNK_SIZE, &reached_boundary, done);
+    r = read_line(bl, chunk_size, &reached_boundary, done);
   }
 
   return 0;
@@ -877,7 +878,8 @@ int RGWPostObj_ObjStore_S3::get_params()
     }
 
     bool boundary;
-    r = read_data(part.data, RGW_MAX_CHUNK_SIZE, &boundary, &done);
+    uint64_t chunk_size = s->cct->_conf->rgw_max_chunk_size;
+    r = read_data(part.data, chunk_size, &boundary, &done);
     if (!boundary) {
       err_msg = "Couldn't find boundary";
       return -EINVAL;
@@ -1059,7 +1061,8 @@ int RGWPostObj_ObjStore_S3::complete_get_params()
     
     bufferlist part_data;
     bool boundary;
-    r = read_data(part.data, RGW_MAX_CHUNK_SIZE, &boundary, &done);
+    uint64_t chunk_size = s->cct->_conf->rgw_max_chunk_size;
+    r = read_data(part.data, chunk_size, &boundary, &done);
     if (!boundary) {
       return -EINVAL;
     }
@@ -1075,7 +1078,8 @@ int RGWPostObj_ObjStore_S3::get_data(bufferlist& bl)
   bool boundary;
   bool done;
 
-  int r = read_data(bl, RGW_MAX_CHUNK_SIZE, &boundary, &done);
+  uint64_t chunk_size = s->cct->_conf->rgw_max_chunk_size;
+  int r = read_data(bl, chunk_size, &boundary, &done);
   if (r < 0)
     return r;
 
@@ -1385,7 +1389,7 @@ int RGWPutCORS_ObjStore_S3::get_params()
     goto done_err;
   }
 
-  if (!parser.parse(data, len, 1)) {
+  if (!data || !parser.parse(data, len, 1)) {
     r = -EINVAL;
     goto done_err;
   }
diff --git a/src/rgw/rgw_rest_user.cc b/src/rgw/rgw_rest_user.cc
index 0613c49..30f46f0 100644
--- a/src/rgw/rgw_rest_user.cc
+++ b/src/rgw/rgw_rest_user.cc
@@ -784,7 +784,7 @@ void RGWOp_Quota_Set::execute()
 
   bool use_http_params;
 
-  if (s->length > 0) {
+  if (s->content_length > 0) {
     use_http_params = false;
   } else {
     const char *encoding = s->info.env->get("HTTP_TRANSFER_ENCODING");
diff --git a/src/stop.sh b/src/stop.sh
index 1a498ba..d7ce234 100755
--- a/src/stop.sh
+++ b/src/stop.sh
@@ -1,4 +1,4 @@
-#!/bin/bash -x
+#!/bin/bash
 #
 # Copyright (C) 2013 Inktank <info at inktank.com>
 # Copyright (C) 2013 Cloudwatt <libre.licensing at cloudwatt.com>
@@ -18,10 +18,12 @@
 
 test -d dev/osd0/. && test -e dev/sudo && SUDO="sudo"
 
+[ -z "$CEPH_BIN" ] && CEPH_BIN=.
+
 do_killall() {
-	pg=`pgrep -f ceph-run.*$1`
-	[ -n "$pg" ] && kill $pg
-	$SUDO killall $1
+    pg=`pgrep -f ceph-run.*$1`
+    [ -n "$pg" ] && kill $pg
+    $SUDO killall $1
 }
 
 usage="usage: $0 [all] [mon] [mds] [osd]\n"
@@ -34,43 +36,58 @@ stop_rgw=0
 
 while [ $# -ge 1 ]; do
     case $1 in
-	all )
-	    stop_all=1
-	    ;;
-	mon | ceph-mon )
-	    stop_mon=1
-	    stop_all=0
-	    ;;
-	mds | ceph-mds )
-	    stop_mds=1
-	    stop_all=0
-	    ;;
-	osd | ceph-osd )
-	    stop_osd=1
-	    stop_all=0
-	    ;;
-	* )
-	    printf "$usage"
-	    exit
+        all )
+            stop_all=1
+            ;;
+        mon | ceph-mon )
+            stop_mon=1
+            stop_all=0
+            ;;
+        mds | ceph-mds )
+            stop_mds=1
+            stop_all=0
+            ;;
+        osd | ceph-osd )
+            stop_osd=1
+            stop_all=0
+            ;;
+        * )
+            printf "$usage"
+            exit
     esac
     shift
 done
 
 if [ $stop_all -eq 1 ]; then
-	for p in ceph-mon ceph-mds ceph-osd radosgw lt-radosgw apache2 ; do
-            for try in 0 1 1 1 1 ; do
-                if ! pkill $p ; then
-                    break
-                fi
-                sleep $try
-            done
+    while read DEV; do
+        # While it is currently possible to create an rbd image with
+        # whitespace chars in its name, krbd will refuse mapping such
+        # an image, so we can safely split on whitespace here.  (The
+        # same goes for whitespace chars in names of the pools that
+        # contain rbd images).
+        DEV="$(echo "${DEV}" | tr -s '[:space:]' | awk '{ print $5 }')"
+        sudo "${CEPH_BIN}"/rbd unmap "${DEV}"
+    done < <("${CEPH_BIN}"/rbd showmapped | tail -n +2)
+
+    if [ -n "$("${CEPH_BIN}"/rbd showmapped)" ]; then
+        echo "WARNING: Some rbd images are still mapped!" >&2
+    fi
+
+    for p in ceph-mon ceph-mds ceph-osd radosgw lt-radosgw apache2 ; do
+        for try in 0 1 1 1 1 ; do
+            if ! pkill $p ; then
+                break
+            fi
+            sleep $try
         done
-	pkill -f valgrind.bin.\*ceph-mon
-	$SUDO pkill -f valgrind.bin.\*ceph-osd
-	pkill -f valgrind.bin.\*ceph-mds
+    done
+
+    pkill -f valgrind.bin.\*ceph-mon
+    $SUDO pkill -f valgrind.bin.\*ceph-osd
+    pkill -f valgrind.bin.\*ceph-mds
 else
-	[ $stop_mon -eq 1 ] && do_killall ceph-mon
-	[ $stop_mds -eq 1 ] && do_killall ceph-mds
-	[ $stop_osd -eq 1 ] && do_killall ceph-osd
-	[ $stop_rgw -eq 1 ] && do_killall radosgw lt-radosgw apache2
+    [ $stop_mon -eq 1 ] && do_killall ceph-mon
+    [ $stop_mds -eq 1 ] && do_killall ceph-mds
+    [ $stop_osd -eq 1 ] && do_killall ceph-osd
+    [ $stop_rgw -eq 1 ] && do_killall radosgw lt-radosgw apache2
 fi
diff --git a/src/test/Makefile.am b/src/test/Makefile.am
index 1f07a75..71f2a7f 100644
--- a/src/test/Makefile.am
+++ b/src/test/Makefile.am
@@ -236,6 +236,7 @@ check_SCRIPTS += \
 	test/mon/osd-pool-create.sh \
 	test/mon/misc.sh \
 	test/mon/osd-crush.sh \
+	test/mon/osd-erasure-code-profile.sh \
 	test/mon/mkfs.sh \
 	test/ceph-disk.sh \
 	test/mon/mon-handle-forward.sh \
@@ -426,6 +427,11 @@ unittest_crypto_LDADD = $(UNITTEST_LDADD) $(CEPH_GLOBAL)
 unittest_crypto_CXXFLAGS = $(UNITTEST_CXXFLAGS)
 check_PROGRAMS += unittest_crypto
 
+unittest_crypto_init_SOURCES = test/crypto_init.cc
+unittest_crypto_init_LDADD = $(UNITTEST_LDADD) $(CEPH_GLOBAL)
+unittest_crypto_init_CXXFLAGS = $(UNITTEST_CXXFLAGS)
+check_PROGRAMS += unittest_crypto_init
+
 unittest_perf_counters_SOURCES = test/perf_counters.cc
 unittest_perf_counters_LDADD = $(UNITTEST_LDADD) $(CEPH_GLOBAL)
 unittest_perf_counters_CXXFLAGS = $(UNITTEST_CXXFLAGS)
diff --git a/src/test/bench/distribution.h b/src/test/bench/distribution.h
index 8e26571..d3525b8 100644
--- a/src/test/bench/distribution.h
+++ b/src/test/bench/distribution.h
@@ -45,7 +45,7 @@ class RandomDist : public Distribution<T> {
   rngen_t rng;
   std::map<uint64_t, T> contents;
 public:
-  RandomDist(rngen_t rng, std::set<T> &initial) : rng(rng) {
+  RandomDist(const rngen_t &rng, std::set<T> &initial) : rng(rng) {
     uint64_t count = 0;
     for (typename std::set<T>::iterator i = initial.begin();
 	 i != initial.end();
@@ -66,7 +66,7 @@ class WeightedDist : public Distribution<T> {
   double total;
   std::map<double, T> contents;
 public:
-  WeightedDist(rngen_t rng, const std::set<std::pair<double, T> > &initial)
+  WeightedDist(const rngen_t &rng, const std::set<std::pair<double, T> > &initial)
     : rng(rng), total(0) {
     for (typename std::set<std::pair<double, T> >::const_iterator i =
 	   initial.begin();
@@ -105,7 +105,7 @@ class UniformRandom : public Distribution<uint64_t> {
   uint64_t min;
   uint64_t max;
 public:
-  UniformRandom(rngen_t rng, uint64_t min, uint64_t max) :
+  UniformRandom(const rngen_t &rng, uint64_t min, uint64_t max) :
     rng(rng), min(min), max(max) {}
   virtual uint64_t operator()() {
     return boost::uniform_int<uint64_t>(min, max)(rng);
diff --git a/src/test/crypto_init.cc b/src/test/crypto_init.cc
new file mode 100644
index 0000000..d4b2562
--- /dev/null
+++ b/src/test/crypto_init.cc
@@ -0,0 +1,48 @@
+#include <errno.h>
+#include <time.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <vector>
+
+#include "include/types.h"
+#include "common/code_environment.h"
+#include "global/global_context.h"
+#include "global/global_init.h"
+#include "include/msgr.h"
+#include "gtest/gtest.h"
+#include "auth/Crypto.h"
+#include "common/ceph_crypto.h"
+
+#ifdef USE_NSS
+void *init_crypto(void *p) {
+  ceph::crypto::init(g_ceph_context);
+  return NULL;
+}
+
+// Tests for a race condition in libnss when calling crypto_init
+// multiple times simultaneously from different threads.
+TEST(CRYPTO_INIT, NSS_RACE) {
+  std::vector<const char*> args;
+  global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY,
+	      CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
+  // Most reliably reproduced with more threads than cores.
+  long n_thread = sysconf(_SC_NPROCESSORS_ONLN) * 2;
+  pthread_t *ts = (pthread_t*)malloc(n_thread * sizeof(pthread_t));
+  int i;
+  for (i = 0; i < n_thread; i++) {
+    pthread_create(&ts[i], NULL, init_crypto, NULL);
+  }
+  for (i = 0; i < n_thread; i++) {
+    int k;
+    void *p = (void*)&k;
+    pthread_join(ts[i], &p);
+  }
+  free(ts);
+}
+
+#endif
+
+int main(int argc, char **argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/src/test/encoding/ceph_dencoder.cc b/src/test/encoding/ceph_dencoder.cc
index bb69fdd..8391f33 100644
--- a/src/test/encoding/ceph_dencoder.cc
+++ b/src/test/encoding/ceph_dencoder.cc
@@ -47,7 +47,7 @@ void usage(ostream &out)
 }
 struct Dencoder {
   virtual ~Dencoder() {}
-  virtual string decode(bufferlist bl) = 0;
+  virtual string decode(bufferlist bl, uint64_t seek) = 0;
   virtual void encode(bufferlist& out, uint64_t features) = 0;
   virtual void dump(ceph::Formatter *f) = 0;
   virtual void copy() {
@@ -75,8 +75,9 @@ public:
     delete m_object;
   }
 
-  string decode(bufferlist bl) {
+  string decode(bufferlist bl, uint64_t seek) {
     bufferlist::iterator p = bl.begin();
+    p.seek(seek);
     try {
       m_object->decode(p);
     }
@@ -168,8 +169,9 @@ public:
     m_object->put();
   }
 
-  string decode(bufferlist bl) {
+  string decode(bufferlist bl, uint64_t seek) {
     bufferlist::iterator p = bl.begin();
+    p.seek(seek);
     try {
       Message *n = decode_message(g_ceph_context, p);
       if (!n)
@@ -253,6 +255,7 @@ int main(int argc, const char **argv)
   Dencoder *den = NULL;
   uint64_t features = CEPH_FEATURES_SUPPORTED_DEFAULT;
   bufferlist encbl;
+  uint64_t skip = 0;
 
   if (args.empty()) {
     usage(cerr);
@@ -285,6 +288,13 @@ int main(int argc, const char **argv)
       }
       den = dencoders[cname];
       den->generate();
+    } else if (*i == string("skip")) {
+      ++i;
+      if (i == args.end()) {
+	usage(cerr);
+	exit(1);
+      }
+      skip = atoi(*i);
     } else if (*i == string("get_features")) {
       cout << CEPH_FEATURES_SUPPORTED_DEFAULT << std::endl;
       exit(0);
@@ -309,7 +319,7 @@ int main(int argc, const char **argv)
 	usage(cerr);
 	exit(1);
       }
-      err = den->decode(encbl);
+      err = den->decode(encbl, skip);
     } else if (*i == string("copy_ctor")) {
       if (!den) {
 	cerr << "must first select type with 'type <name>'" << std::endl;
@@ -348,6 +358,7 @@ int main(int argc, const char **argv)
         cerr << "error reading " << *i << ": " << err << std::endl;
         exit(1);
       }
+
     } else if (*i == string("export")) {
       ++i;
       if (i == args.end()) {
diff --git a/src/test/encoding/types.h b/src/test/encoding/types.h
index 678bb62..7df2b6c 100644
--- a/src/test/encoding/types.h
+++ b/src/test/encoding/types.h
@@ -129,6 +129,9 @@ TYPE(MonCap)
 TYPE(DBObjectMap::_Header)
 TYPE(DBObjectMap::State)
 
+#include "osdc/Journaler.h"
+TYPE(Journaler::Header)
+
 #include "mds/Anchor.h"
 TYPE(Anchor)
 
@@ -164,7 +167,13 @@ TYPE_FEATUREFUL(MDSMap::mds_info_t)
 TYPE_NOCOPY(Capability)
 
 #include "mds/AnchorServer.h"
-TYPE(AnchorServer)
+TYPEWITHSTRAYDATA(AnchorServer)
+
+#include "mds/InoTable.h"
+TYPE(InoTable)
+
+#include "mds/SnapServer.h"
+TYPEWITHSTRAYDATA(SnapServer)
 
 #include "mds/SessionMap.h"
 TYPE(SessionMap)
diff --git a/src/test/erasure-code/Makefile.am b/src/test/erasure-code/Makefile.am
index 30f461c..fdbe003 100644
--- a/src/test/erasure-code/Makefile.am
+++ b/src/test/erasure-code/Makefile.am
@@ -52,6 +52,27 @@ libec_fail_to_register_la_LIBADD = $(PTHREAD_LIBS) $(EXTRALIBS)
 libec_fail_to_register_la_LDFLAGS = ${AM_LDFLAGS} -export-symbols-regex '.*__erasure_code_.*'
 erasure_codelib_LTLIBRARIES += libec_fail_to_register.la
 
+libec_test_jerasure_sse4_la_SOURCES = test/erasure-code/TestJerasurePluginSSE4.cc
+libec_test_jerasure_sse4_la_CFLAGS = ${AM_CFLAGS}
+libec_test_jerasure_sse4_la_CXXFLAGS= ${AM_CXXFLAGS}
+libec_test_jerasure_sse4_la_LIBADD = $(PTHREAD_LIBS) $(EXTRALIBS)
+libec_test_jerasure_sse4_la_LDFLAGS = ${AM_LDFLAGS} -export-symbols-regex '.*__erasure_code_.*'
+erasure_codelib_LTLIBRARIES += libec_test_jerasure_sse4.la
+
+libec_test_jerasure_sse3_la_SOURCES = test/erasure-code/TestJerasurePluginSSE3.cc
+libec_test_jerasure_sse3_la_CFLAGS = ${AM_CFLAGS}
+libec_test_jerasure_sse3_la_CXXFLAGS= ${AM_CXXFLAGS}
+libec_test_jerasure_sse3_la_LIBADD = $(PTHREAD_LIBS) $(EXTRALIBS)
+libec_test_jerasure_sse3_la_LDFLAGS = ${AM_LDFLAGS} -export-symbols-regex '.*__erasure_code_.*'
+erasure_codelib_LTLIBRARIES += libec_test_jerasure_sse3.la
+
+libec_test_jerasure_generic_la_SOURCES = test/erasure-code/TestJerasurePluginGeneric.cc
+libec_test_jerasure_generic_la_CFLAGS = ${AM_CFLAGS}
+libec_test_jerasure_generic_la_CXXFLAGS= ${AM_CXXFLAGS}
+libec_test_jerasure_generic_la_LIBADD = $(PTHREAD_LIBS) $(EXTRALIBS)
+libec_test_jerasure_generic_la_LDFLAGS = ${AM_LDFLAGS} -export-symbols-regex '.*__erasure_code_.*'
+erasure_codelib_LTLIBRARIES += libec_test_jerasure_generic.la
+
 unittest_erasure_code_plugin_SOURCES = test/erasure-code/TestErasureCodePlugin.cc 
 unittest_erasure_code_plugin_CXXFLAGS = $(UNITTEST_CXXFLAGS)
 unittest_erasure_code_plugin_LDADD = $(LIBOSD) $(LIBCOMMON) $(UNITTEST_LDADD) $(CEPH_GLOBAL)
@@ -62,8 +83,13 @@ check_PROGRAMS += unittest_erasure_code_plugin
 
 unittest_erasure_code_jerasure_SOURCES = \
 	test/erasure-code/TestErasureCodeJerasure.cc \
-	$(libec_jerasure_la_SOURCES)
-unittest_erasure_code_jerasure_CXXFLAGS = $(UNITTEST_CXXFLAGS)
+	${jerasure_sources}
+unittest_erasure_code_jerasure_CFLAGS = $(AM_CFLAGS) \
+	-Ierasure-code/jerasure/gf-complete/include \
+	-Ierasure-code/jerasure/jerasure/include
+unittest_erasure_code_jerasure_CXXFLAGS = $(UNITTEST_CXXFLAGS) \
+	-Ierasure-code/jerasure/gf-complete/include \
+	-Ierasure-code/jerasure/jerasure/include
 unittest_erasure_code_jerasure_LDADD = $(LIBOSD) $(LIBCOMMON) $(UNITTEST_LDADD) $(CEPH_GLOBAL)
 if LINUX
 unittest_erasure_code_jerasure_LDADD += -ldl
diff --git a/src/test/erasure-code/TestErasureCodeJerasure.cc b/src/test/erasure-code/TestErasureCodeJerasure.cc
index 87f5966..4b768a8 100644
--- a/src/test/erasure-code/TestErasureCodeJerasure.cc
+++ b/src/test/erasure-code/TestErasureCodeJerasure.cc
@@ -3,7 +3,7 @@
 /*
  * Ceph - scalable distributed file system
  *
- * Copyright (C) 2013 Cloudwatt <libre.licensing at cloudwatt.com>
+ * Copyright (C) 2013,2014 Cloudwatt <libre.licensing at cloudwatt.com>
  *
  * Author: Loic Dachary <loic at dachary.org>
  *
@@ -44,10 +44,10 @@ TYPED_TEST(ErasureCodeTest, encode_decode)
 {
   TypeParam jerasure;
   map<std::string,std::string> parameters;
-  parameters["erasure-code-k"] = "2";
-  parameters["erasure-code-m"] = "2";
-  parameters["erasure-code-w"] = "7";
-  parameters["erasure-code-packetsize"] = "8";
+  parameters["k"] = "2";
+  parameters["m"] = "2";
+  parameters["w"] = "7";
+  parameters["packetsize"] = "8";
   jerasure.init(parameters);
 
 #define LARGE_ENOUGH 2048
@@ -113,10 +113,10 @@ TYPED_TEST(ErasureCodeTest, minimum_to_decode)
 {
   TypeParam jerasure;
   map<std::string,std::string> parameters;
-  parameters["erasure-code-k"] = "2";
-  parameters["erasure-code-m"] = "2";
-  parameters["erasure-code-w"] = "7";
-  parameters["erasure-code-packetsize"] = "8";
+  parameters["k"] = "2";
+  parameters["m"] = "2";
+  parameters["w"] = "7";
+  parameters["packetsize"] = "8";
   jerasure.init(parameters);
 
   //
@@ -211,9 +211,9 @@ TEST(ErasureCodeTest, encode)
 {
   ErasureCodeJerasureReedSolomonVandermonde jerasure;
   map<std::string,std::string> parameters;
-  parameters["erasure-code-k"] = "2";
-  parameters["erasure-code-m"] = "2";
-  parameters["erasure-code-w"] = "8";
+  parameters["k"] = "2";
+  parameters["m"] = "2";
+  parameters["w"] = "8";
   jerasure.init(parameters);
 
   unsigned alignment = jerasure.get_alignment();
@@ -292,9 +292,9 @@ TEST(ErasureCodeTest, create_ruleset)
     stringstream ss;
     ErasureCodeJerasureReedSolomonVandermonde jerasure;
     map<std::string,std::string> parameters;
-    parameters["erasure-code-k"] = "2";
-    parameters["erasure-code-m"] = "2";
-    parameters["erasure-code-w"] = "8";
+    parameters["k"] = "2";
+    parameters["m"] = "2";
+    parameters["w"] = "8";
     jerasure.init(parameters);
     int ruleset = jerasure.create_ruleset("myrule", *c, &ss);
     EXPECT_EQ(0, ruleset);
@@ -316,10 +316,10 @@ TEST(ErasureCodeTest, create_ruleset)
     stringstream ss;
     ErasureCodeJerasureReedSolomonVandermonde jerasure;
     map<std::string,std::string> parameters;
-    parameters["erasure-code-k"] = "2";
-    parameters["erasure-code-m"] = "2";
-    parameters["erasure-code-w"] = "8";
-    parameters["erasure-code-ruleset-root"] = "BAD";
+    parameters["k"] = "2";
+    parameters["m"] = "2";
+    parameters["w"] = "8";
+    parameters["ruleset-root"] = "BAD";
     jerasure.init(parameters);
     EXPECT_EQ(-ENOENT, jerasure.create_ruleset("otherrule", *c, &ss));
     EXPECT_EQ("root item BAD does not exist", ss.str());
@@ -328,10 +328,10 @@ TEST(ErasureCodeTest, create_ruleset)
     stringstream ss;
     ErasureCodeJerasureReedSolomonVandermonde jerasure;
     map<std::string,std::string> parameters;
-    parameters["erasure-code-k"] = "2";
-    parameters["erasure-code-m"] = "2";
-    parameters["erasure-code-w"] = "8";
-    parameters["erasure-code-ruleset-failure-domain"] = "WORSE";
+    parameters["k"] = "2";
+    parameters["m"] = "2";
+    parameters["w"] = "8";
+    parameters["ruleset-failure-domain"] = "WORSE";
     jerasure.init(parameters);
     EXPECT_EQ(-EINVAL, jerasure.create_ruleset("otherrule", *c, &ss));
     EXPECT_EQ("unknown type WORSE", ss.str());
diff --git a/src/test/erasure-code/TestErasureCodePlugin.cc b/src/test/erasure-code/TestErasureCodePlugin.cc
index f97b140..a896e3f 100644
--- a/src/test/erasure-code/TestErasureCodePlugin.cc
+++ b/src/test/erasure-code/TestErasureCodePlugin.cc
@@ -3,7 +3,7 @@
 /*
  * Ceph - scalable distributed file system
  *
- * Copyright (C) 2013 Cloudwatt <libre.licensing at cloudwatt.com>
+ * Copyright (C) 2013,2014 Cloudwatt <libre.licensing at cloudwatt.com>
  *
  * Author: Loic Dachary <loic at dachary.org>
  *
@@ -30,10 +30,11 @@ protected:
   public:
     virtual void *entry() {
       map<std::string,std::string> parameters;
-      parameters["erasure-code-directory"] = ".libs";
+      parameters["directory"] = ".libs";
       ErasureCodePluginRegistry &instance = ErasureCodePluginRegistry::instance();
       ErasureCodeInterfaceRef erasure_code;
-      instance.factory("hangs", parameters, &erasure_code);
+      stringstream ss;
+      instance.factory("hangs", parameters, &erasure_code, ss);
       return NULL;
     }
   };
@@ -71,25 +72,26 @@ TEST_F(ErasureCodePluginRegistryTest, factory_mutex) {
 TEST_F(ErasureCodePluginRegistryTest, all)
 {
   map<std::string,std::string> parameters;
-  parameters["erasure-code-directory"] = ".libs";
+  parameters["directory"] = ".libs";
   ErasureCodeInterfaceRef erasure_code;
   ErasureCodePluginRegistry &instance = ErasureCodePluginRegistry::instance();
+  stringstream ss;
   EXPECT_FALSE(erasure_code);
-  EXPECT_EQ(-EIO, instance.factory("invalid", parameters, &erasure_code));
+  EXPECT_EQ(-EIO, instance.factory("invalid", parameters, &erasure_code, ss));
   EXPECT_FALSE(erasure_code);
   EXPECT_EQ(-ENOENT, instance.factory("missing_entry_point", parameters,
-				      &erasure_code));
+				      &erasure_code, ss));
   EXPECT_FALSE(erasure_code);
   EXPECT_EQ(-ESRCH, instance.factory("fail_to_initialize", parameters,
-				     &erasure_code));
+				     &erasure_code, ss));
   EXPECT_FALSE(erasure_code);
   EXPECT_EQ(-EBADF, instance.factory("fail_to_register", parameters,
-				     &erasure_code));
+				     &erasure_code, ss));
   EXPECT_FALSE(erasure_code);
-  EXPECT_EQ(0, instance.factory("example", parameters, &erasure_code));
+  EXPECT_EQ(0, instance.factory("example", parameters, &erasure_code, ss));
   EXPECT_TRUE(erasure_code);
   ErasureCodePlugin *plugin = 0;
-  EXPECT_EQ(-EEXIST, instance.load("example", parameters, &plugin));
+  EXPECT_EQ(-EEXIST, instance.load("example", parameters, &plugin, ss));
 }
 
 int main(int argc, char **argv) {
diff --git a/src/test/erasure-code/TestErasureCodePluginJerasure.cc b/src/test/erasure-code/TestErasureCodePluginJerasure.cc
index 0013ce8..21f6615 100644
--- a/src/test/erasure-code/TestErasureCodePluginJerasure.cc
+++ b/src/test/erasure-code/TestErasureCodePluginJerasure.cc
@@ -1,9 +1,9 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
+// -*- 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 Cloudwatt <libre.licensing at cloudwatt.com>
+ * Copyright (C) 2013,2014 Cloudwatt <libre.licensing at cloudwatt.com>
  *
  * Author: Loic Dachary <loic at dachary.org>
  *
@@ -11,10 +11,12 @@
  *  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 "global/global_init.h"
 #include "erasure-code/ErasureCodePlugin.h"
 #include "common/ceph_argparse.h"
@@ -25,11 +27,12 @@ TEST(ErasureCodePlugin, factory)
 {
   ErasureCodePluginRegistry &instance = ErasureCodePluginRegistry::instance();
   map<std::string,std::string> parameters;
-  parameters["erasure-code-directory"] = ".libs";
+  parameters["directory"] = ".libs";
   {
     ErasureCodeInterfaceRef erasure_code;
     EXPECT_FALSE(erasure_code);
-    EXPECT_EQ(-ENOENT, instance.factory("jerasure", parameters, &erasure_code));
+    EXPECT_EQ(-ENOENT, instance.factory("jerasure", parameters,
+                                        &erasure_code, cerr));
     EXPECT_FALSE(erasure_code);
   }
   const char *techniques[] = {
@@ -44,10 +47,169 @@ TEST(ErasureCodePlugin, factory)
   };
   for(const char **technique = techniques; *technique; technique++) {
     ErasureCodeInterfaceRef erasure_code;
-    parameters["erasure-code-technique"] = *technique;
+    parameters["technique"] = *technique;
+    EXPECT_FALSE(erasure_code);
+    EXPECT_EQ(0, instance.factory("jerasure", parameters,
+                                  &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;
+
+  ErasureCodePluginRegistry &instance = ErasureCodePluginRegistry::instance();
+  map<std::string,std::string> parameters;
+  // load test plugins instead of actual plugins to assert the desired side effect
+  // happens
+  parameters["jerasure-name"] = "test_jerasure";
+  parameters["directory"] = ".libs";
+  parameters["technique"] = "reed_sol_van";
+
+  // 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;
+
+    ErasureCodeInterfaceRef erasure_code;
+    int sse4_side_effect = -444;
+    EXPECT_EQ(sse4_side_effect, instance.factory("jerasure", parameters,
+                                                 &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;
+
+    ErasureCodeInterfaceRef erasure_code;
+    int sse3_side_effect = -333;
+    EXPECT_EQ(sse3_side_effect, instance.factory("jerasure", parameters,
+                                                 &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;
+
+    ErasureCodeInterfaceRef erasure_code;
+    int generic_side_effect = -111;
+    EXPECT_EQ(generic_side_effect, instance.factory("jerasure", parameters,
+                                                 &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;
+}
+
+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> parameters;
+  parameters["directory"] = ".libs";
+  parameters["technique"] = "reed_sol_van";
+  parameters["k"] = "2";
+  parameters["m"] = "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("jerasure", parameters, &erasure_code));
+    EXPECT_EQ(0, instance.factory("jerasure_" + *sse_variant, parameters,
+                                  &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));
+
   }
 }
 
@@ -63,12 +225,11 @@ int main(int argc, char **argv)
   return RUN_ALL_TESTS();
 }
 
-/* 
+/*
  * Local Variables:
- * compile-command: "cd ../.. ; make -j4 && 
- *   make unittest_erasure_code_plugin_jerasure && 
+ * compile-command: "cd ../.. ; make -j4 &&
+ *   make unittest_erasure_code_plugin_jerasure &&
  *   valgrind --tool=memcheck ./unittest_erasure_code_plugin_jerasure \
  *      --gtest_filter=*.* --log-to-stderr=true --debug-osd=20"
  * End:
  */
-
diff --git a/src/test/erasure-code/TestJerasurePluginGeneric.cc b/src/test/erasure-code/TestJerasurePluginGeneric.cc
new file mode 100644
index 0000000..f273bd6
--- /dev/null
+++ b/src/test/erasure-code/TestJerasurePluginGeneric.cc
@@ -0,0 +1,23 @@
+// -*- 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) 2014 Cloudwatt <libre.licensing at cloudwatt.com>
+ *
+ * Author: Loic Dachary <loic at dachary.org>
+ *
+ *  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 "erasure-code/ErasureCodePlugin.h"
+
+int __erasure_code_init(char *plugin_name)
+{
+  return -111;
+}
diff --git a/src/test/erasure-code/TestJerasurePluginSSE3.cc b/src/test/erasure-code/TestJerasurePluginSSE3.cc
new file mode 100644
index 0000000..9d74d52
--- /dev/null
+++ b/src/test/erasure-code/TestJerasurePluginSSE3.cc
@@ -0,0 +1,23 @@
+// -*- 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) 2014 Cloudwatt <libre.licensing at cloudwatt.com>
+ *
+ * Author: Loic Dachary <loic at dachary.org>
+ *
+ *  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 "erasure-code/ErasureCodePlugin.h"
+
+int __erasure_code_init(char *plugin_name)
+{
+  return -333;
+}
diff --git a/src/test/erasure-code/TestJerasurePluginSSE4.cc b/src/test/erasure-code/TestJerasurePluginSSE4.cc
new file mode 100644
index 0000000..7bb6f7e
--- /dev/null
+++ b/src/test/erasure-code/TestJerasurePluginSSE4.cc
@@ -0,0 +1,23 @@
+// -*- 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) 2014 Cloudwatt <libre.licensing at cloudwatt.com>
+ *
+ * Author: Loic Dachary <loic at dachary.org>
+ *
+ *  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 "erasure-code/ErasureCodePlugin.h"
+
+int __erasure_code_init(char *plugin_name)
+{
+  return -444;
+}
diff --git a/src/test/erasure-code/ceph_erasure_code.cc b/src/test/erasure-code/ceph_erasure_code.cc
index a364de5..f99e845 100644
--- a/src/test/erasure-code/ceph_erasure_code.cc
+++ b/src/test/erasure-code/ceph_erasure_code.cc
@@ -103,10 +103,10 @@ int ErasureCodeCommand::setup(int argc, char** argv) {
     }
   }
 
-  if (parameters.count("erasure-code-directory") == 0)
-    parameters["erasure-code-directory"] = ".libs";
-  if (parameters.count("erasure-code-plugin") == 0) {
-    cerr << "--parameter erasure-code-plugin=<plugin> is mandatory" << endl;
+  if (parameters.count("directory") == 0)
+    parameters["directory"] = ".libs";
+  if (parameters.count("plugin") == 0) {
+    cerr << "--parameter plugin=<plugin> is mandatory" << endl;
     return 1;
   }
 
@@ -117,9 +117,9 @@ int ErasureCodeCommand::run() {
   ErasureCodePluginRegistry &instance = ErasureCodePluginRegistry::instance();
   instance.disable_dlclose = true;
   ErasureCodeInterfaceRef erasure_code;
-  int code = instance.factory(parameters["erasure-code-plugin"],
+  int code = instance.factory(parameters["plugin"],
 			      parameters,
-			      &erasure_code);
+			      &erasure_code, cerr);
   if (code)
     return code;
 
@@ -153,11 +153,11 @@ int main(int argc, char** argv) {
  *   make -j4 ceph_erasure_code &&
  *   valgrind --tool=memcheck --leak-check=full \
  *      ./ceph_erasure_code \
- *      --parameter erasure-code-plugin=jerasure \
- *      --parameter erasure-code-directory=.libs \
- *      --parameter erasure-code-technique=reed_sol_van \
- *      --parameter erasure-code-k=2 \
- *      --parameter erasure-code-m=2 \
+ *      --parameter plugin=jerasure \
+ *      --parameter directory=.libs \
+ *      --parameter technique=reed_sol_van \
+ *      --parameter k=2 \
+ *      --parameter m=2 \
  *      --get_chunk_size 1024 \
  *      --get_data_chunk_count \
  *      --get_chunk_count \
diff --git a/src/test/erasure-code/ceph_erasure_code_benchmark.cc b/src/test/erasure-code/ceph_erasure_code_benchmark.cc
index ce768ae..9d70296 100644
--- a/src/test/erasure-code/ceph_erasure_code_benchmark.cc
+++ b/src/test/erasure-code/ceph_erasure_code_benchmark.cc
@@ -98,8 +98,8 @@ int ErasureCodeBench::setup(int argc, char** argv) {
     }
   }
 
-  if (parameters.count("erasure-code-directory") == 0)
-    parameters["erasure-code-directory"] = ".libs";
+  if (parameters.count("directory") == 0)
+    parameters["directory"] = ".libs";
 
   in_size = vm["size"].as<int>();
   max_iterations = vm["iterations"].as<int>();
@@ -124,11 +124,11 @@ int ErasureCodeBench::encode()
 {
   ErasureCodePluginRegistry &instance = ErasureCodePluginRegistry::instance();
   ErasureCodeInterfaceRef erasure_code;
-  int code = instance.factory(plugin, parameters, &erasure_code);
+  int code = instance.factory(plugin, parameters, &erasure_code, cerr);
   if (code)
     return code;
-  int k = atoi(parameters["erasure-code-k"].c_str());
-  int m = atoi(parameters["erasure-code-m"].c_str());
+  int k = atoi(parameters["k"].c_str());
+  int m = atoi(parameters["m"].c_str());
 
   bufferlist in;
   in.append(string(in_size, 'X'));
@@ -152,11 +152,11 @@ int ErasureCodeBench::decode()
 {
   ErasureCodePluginRegistry &instance = ErasureCodePluginRegistry::instance();
   ErasureCodeInterfaceRef erasure_code;
-  int code = instance.factory(plugin, parameters, &erasure_code);
+  int code = instance.factory(plugin, parameters, &erasure_code, cerr);
   if (code)
     return code;
-  int k = atoi(parameters["erasure-code-k"].c_str());
-  int m = atoi(parameters["erasure-code-m"].c_str());
+  int k = atoi(parameters["k"].c_str());
+  int m = atoi(parameters["m"].c_str());
 
   bufferlist in;
   in.append(string(in_size, 'X'));
@@ -208,10 +208,10 @@ int main(int argc, char** argv) {
  *   valgrind --tool=memcheck --leak-check=full \
  *      ./ceph_erasure_code_benchmark \
  *      --plugin jerasure \
- *      --parameter erasure-code-directory=.libs \
- *      --parameter erasure-code-technique=reed_sol_van \
- *      --parameter erasure-code-k=2 \
- *      --parameter erasure-code-m=2 \
+ *      --parameter directory=.libs \
+ *      --parameter technique=reed_sol_van \
+ *      --parameter k=2 \
+ *      --parameter m=2 \
  *      --iterations 1
  * "
  * End:
diff --git a/src/test/libcephfs/test.cc b/src/test/libcephfs/test.cc
index b42a8e8..9d917f5 100644
--- a/src/test/libcephfs/test.cc
+++ b/src/test/libcephfs/test.cc
@@ -69,6 +69,7 @@ TEST(LibCephFS, MountNonExist) {
   ASSERT_EQ(0, ceph_conf_parse_env(cmount, NULL));
   ASSERT_EQ(0, ceph_conf_read_file(cmount, NULL));
   ASSERT_NE(0, ceph_mount(cmount, "/non-exist"));
+  ceph_shutdown(cmount);
 }
 
 TEST(LibCephFS, MountDouble) {
@@ -848,6 +849,8 @@ TEST(LibCephFS, BadFileDesc) {
   ASSERT_EQ(ceph_get_file_stripe_unit(cmount, -1), -EBADF);
   ASSERT_EQ(ceph_get_file_pool(cmount, -1), -EBADF);
   ASSERT_EQ(ceph_get_file_replication(cmount, -1), -EBADF);
+
+  ceph_shutdown(cmount);
 }
 
 TEST(LibCephFS, ReadEmptyFile) {
diff --git a/src/test/librados/TestCase.cc b/src/test/librados/TestCase.cc
index 70c5ac8..d9e5e49 100644
--- a/src/test/librados/TestCase.cc
+++ b/src/test/librados/TestCase.cc
@@ -27,6 +27,7 @@ void RadosTest::SetUp()
   ASSERT_EQ(0, rados_ioctx_create(cluster, pool_name.c_str(), &ioctx));
   std::string nspace = get_temp_pool_name();
   rados_ioctx_set_namespace(ioctx, nspace.c_str());
+  ASSERT_FALSE(rados_ioctx_pool_requires_alignment(ioctx));
 }
 
 void RadosTest::TearDown()
@@ -72,6 +73,7 @@ void RadosTestPP::SetUp()
   ASSERT_EQ(0, cluster.ioctx_create(pool_name.c_str(), ioctx));
   ns = get_temp_pool_name();
   ioctx.set_namespace(ns);
+  ASSERT_FALSE(ioctx.pool_requires_alignment());
 }
 
 void RadosTestPP::TearDown()
@@ -91,3 +93,94 @@ void RadosTestPP::cleanup_default_namespace(librados::IoCtx ioctx)
     ASSERT_EQ(0, ioctx.remove(it->first));
   }
 }
+
+std::string RadosTestEC::pool_name;
+rados_t RadosTestEC::s_cluster = NULL;
+
+void RadosTestEC::SetUpTestCase()
+{
+  pool_name = get_temp_pool_name();
+  ASSERT_EQ("", create_one_ec_pool(pool_name, &s_cluster));
+}
+
+void RadosTestEC::TearDownTestCase()
+{
+  ASSERT_EQ(0, destroy_one_ec_pool(pool_name, &s_cluster));
+}
+
+void RadosTestEC::SetUp()
+{
+  cluster = RadosTestEC::s_cluster;
+  ASSERT_EQ(0, rados_ioctx_create(cluster, pool_name.c_str(), &ioctx));
+  std::string nspace = get_temp_pool_name();
+  rados_ioctx_set_namespace(ioctx, nspace.c_str());
+  ASSERT_TRUE(rados_ioctx_pool_requires_alignment(ioctx));
+  alignment = rados_ioctx_pool_required_alignment(ioctx);
+  ASSERT_NE((unsigned)0, alignment);
+}
+
+void RadosTestEC::TearDown()
+{
+  cleanup_default_namespace(ioctx);
+  rados_ioctx_destroy(ioctx);
+}
+
+void RadosTestEC::cleanup_default_namespace(rados_ioctx_t ioctx)
+{
+  // remove all objects from the default namespace to avoid polluting
+  // other tests
+  rados_ioctx_set_namespace(ioctx, "");
+  rados_list_ctx_t list_ctx;
+  ASSERT_EQ(0, rados_objects_list_open(ioctx, &list_ctx));
+  int r;
+  const char *entry = NULL;
+  const char *key = NULL;
+  while ((r = rados_objects_list_next(list_ctx, &entry, &key)) != -ENOENT) {
+    ASSERT_EQ(0, r);
+    rados_ioctx_locator_set_key(ioctx, key);
+    ASSERT_EQ(0, rados_remove(ioctx, entry));
+  }
+  rados_objects_list_close(list_ctx);
+}
+
+std::string RadosTestECPP::pool_name;
+Rados RadosTestECPP::s_cluster;
+
+void RadosTestECPP::SetUpTestCase()
+{
+  pool_name = get_temp_pool_name();
+  ASSERT_EQ("", create_one_ec_pool_pp(pool_name, s_cluster));
+}
+
+void RadosTestECPP::TearDownTestCase()
+{
+  ASSERT_EQ(0, destroy_one_ec_pool_pp(pool_name, s_cluster));
+}
+
+void RadosTestECPP::SetUp()
+{
+  ASSERT_EQ(0, cluster.ioctx_create(pool_name.c_str(), ioctx));
+  ns = get_temp_pool_name();
+  ioctx.set_namespace(ns);
+  ASSERT_TRUE(ioctx.pool_requires_alignment());
+  alignment = ioctx.pool_required_alignment();
+  ASSERT_NE((unsigned)0, alignment);
+}
+
+void RadosTestECPP::TearDown()
+{
+  cleanup_default_namespace(ioctx);
+  ioctx.close();
+}
+
+void RadosTestECPP::cleanup_default_namespace(librados::IoCtx ioctx)
+{
+  // remove all objects from the default namespace to avoid polluting
+  // other tests
+  ioctx.set_namespace("");
+  for (ObjectIterator it = ioctx.objects_begin();
+       it != ioctx.objects_end(); ++it) {
+    ioctx.locator_set_key(it->second);
+    ASSERT_EQ(0, ioctx.remove(it->first));
+  }
+}
diff --git a/src/test/librados/TestCase.h b/src/test/librados/TestCase.h
index 31fa040..ccc0359 100644
--- a/src/test/librados/TestCase.h
+++ b/src/test/librados/TestCase.h
@@ -53,4 +53,41 @@ protected:
   std::string ns;
 };
 
+class RadosTestEC : public ::testing::Test {
+public:
+  RadosTestEC() {}
+  virtual ~RadosTestEC() {}
+protected:
+  static void SetUpTestCase();
+  static void TearDownTestCase();
+  static void cleanup_default_namespace(rados_ioctx_t ioctx);
+  static rados_t s_cluster;
+  static std::string pool_name;
+
+  virtual void SetUp();
+  virtual void TearDown();
+  rados_t cluster;
+  rados_ioctx_t ioctx;
+  uint64_t alignment;
+};
+
+class RadosTestECPP : public ::testing::Test {
+public:
+  RadosTestECPP() : cluster(s_cluster) {};
+  virtual ~RadosTestECPP() {};
+protected:
+  static void SetUpTestCase();
+  static void TearDownTestCase();
+  static void cleanup_default_namespace(librados::IoCtx ioctx);
+  static librados::Rados s_cluster;
+  static std::string pool_name;
+
+  virtual void SetUp();
+  virtual void TearDown();
+  librados::Rados &cluster;
+  librados::IoCtx ioctx;
+  std::string ns;
+  uint64_t alignment;
+};
+
 #endif
diff --git a/src/test/librados/aio.cc b/src/test/librados/aio.cc
index 30c794a..bb83f3e 100644
--- a/src/test/librados/aio.cc
+++ b/src/test/librados/aio.cc
@@ -20,6 +20,7 @@ class AioTestData
 public:
   AioTestData()
     : m_cluster(NULL),
+      m_ioctx(NULL),
       m_init(false),
       m_complete(false),
       m_safe(false)
@@ -176,16 +177,17 @@ TEST(LibRadosAio, SimpleWrite) {
 }
 
 TEST(LibRadosAio, SimpleWritePP) {
+  char buf[128];
+  memset(buf, 0xcc, sizeof(buf));
+  bufferlist bl1;
+  bl1.append(buf, sizeof(buf));
+  {
   AioTestDataPP test_data;
   ASSERT_EQ("", test_data.init());
   AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
 	  (void*)&test_data, set_completion_complete, set_completion_safe);
   AioCompletion *my_completion_null = NULL;
   ASSERT_NE(my_completion, my_completion_null);
-  char buf[128];
-  memset(buf, 0xcc, sizeof(buf));
-  bufferlist bl1;
-  bl1.append(buf, sizeof(buf));
   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo",
 			       my_completion, bl1, sizeof(buf), 0));
   {
@@ -194,10 +196,13 @@ TEST(LibRadosAio, SimpleWritePP) {
     sem_wait(&test_data.m_sem);
   }
   delete my_completion;
+  }
 
+  {
+  AioTestDataPP test_data;
   ASSERT_EQ("", test_data.init());
   test_data.m_ioctx.set_namespace("nspace");
-  my_completion = test_data.m_cluster.aio_create_completion(
+  AioCompletion *my_completion = test_data.m_cluster.aio_create_completion(
 	  (void*)&test_data, set_completion_complete, set_completion_safe);
   ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo",
 			       my_completion, bl1, sizeof(buf), 0));
@@ -207,6 +212,7 @@ TEST(LibRadosAio, SimpleWritePP) {
     sem_wait(&test_data.m_sem);
   }
   delete my_completion;
+  }
 }
 
 TEST(LibRadosAio, WaitForSafe) {
@@ -1285,4 +1291,5 @@ TEST(LibRadosAio, OmapPP) {
   }
 
   ioctx.remove("test_obj");
+  destroy_one_pool_pp(pool_name, cluster);
 }
diff --git a/src/test/librados/io.cc b/src/test/librados/io.cc
index 75742bf..ebad7c7 100644
--- a/src/test/librados/io.cc
+++ b/src/test/librados/io.cc
@@ -13,7 +13,9 @@ using namespace librados;
 using std::string;
 
 typedef RadosTest LibRadosIo;
+typedef RadosTestEC LibRadosIoEC;
 typedef RadosTestPP LibRadosIoPP;
+typedef RadosTestECPP LibRadosIoECPP;
 
 TEST_F(LibRadosIo, SimpleWrite) {
   char buf[128];
@@ -449,3 +451,460 @@ TEST_F(LibRadosIoPP, XattrListPP) {
     }
   }
 }
+
+TEST_F(LibRadosIoEC, SimpleWrite) {
+  char buf[128];
+  memset(buf, 0xcc, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), rados_write(ioctx, "foo", buf, sizeof(buf), 0));
+  rados_ioctx_set_namespace(ioctx, "nspace");
+  ASSERT_EQ((int)sizeof(buf), rados_write(ioctx, "foo", buf, sizeof(buf), 0));
+}
+
+TEST_F(LibRadosIoECPP, SimpleWritePP) {
+  char buf[128];
+  memset(buf, 0xcc, sizeof(buf));
+  bufferlist bl;
+  bl.append(buf, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), ioctx.write("foo", bl, sizeof(buf), 0));
+  ioctx.set_namespace("nspace");
+  ASSERT_EQ((int)sizeof(buf), ioctx.write("foo", bl, sizeof(buf), 0));
+}
+
+TEST_F(LibRadosIoECPP, ReadOpPP) {
+  char buf[128];
+  memset(buf, 0xcc, sizeof(buf));
+  bufferlist bl;
+  bl.append(buf, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), ioctx.write("foo", bl, sizeof(buf), 0));
+
+  {
+      bufferlist op_bl;
+      ObjectReadOperation op;
+      op.read(0, sizeof(buf), NULL, NULL);
+      ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
+      ASSERT_EQ(sizeof(buf), op_bl.length());
+      ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
+  }
+
+  {
+      bufferlist read_bl, op_bl;
+      ObjectReadOperation op;
+      op.read(0, sizeof(buf), &read_bl, NULL);
+      ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
+      ASSERT_EQ(sizeof(buf), read_bl.length());
+      ASSERT_EQ(sizeof(buf), op_bl.length());
+      ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
+      ASSERT_EQ(0, memcmp(read_bl.c_str(), buf, sizeof(buf)));
+  }
+
+  {
+      bufferlist op_bl;
+      int rval = 1000;
+      ObjectReadOperation op;
+      op.read(0, sizeof(buf), NULL, &rval);
+      ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
+      ASSERT_EQ(sizeof(buf), op_bl.length());
+      ASSERT_EQ(0, rval);
+      ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
+  }
+
+  {
+      bufferlist read_bl, op_bl;
+      int rval = 1000;
+      ObjectReadOperation op;
+      op.read(0, sizeof(buf), &read_bl, &rval);
+      ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
+      ASSERT_EQ(sizeof(buf), read_bl.length());
+      ASSERT_EQ(sizeof(buf), op_bl.length());
+      ASSERT_EQ(0, rval);
+      ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
+      ASSERT_EQ(0, memcmp(read_bl.c_str(), buf, sizeof(buf)));
+  }
+
+  {
+      bufferlist read_bl1, read_bl2, op_bl;
+      int rval1 = 1000, rval2 = 1002;
+      ObjectReadOperation op;
+      op.read(0, sizeof(buf), &read_bl1, &rval1);
+      op.read(0, sizeof(buf), &read_bl2, &rval2);
+      ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
+      ASSERT_EQ(sizeof(buf), read_bl1.length());
+      ASSERT_EQ(sizeof(buf), read_bl2.length());
+      ASSERT_EQ(sizeof(buf) * 2, op_bl.length());
+      ASSERT_EQ(0, rval1);
+      ASSERT_EQ(0, rval2);
+      ASSERT_EQ(0, memcmp(read_bl1.c_str(), buf, sizeof(buf)));
+      ASSERT_EQ(0, memcmp(read_bl2.c_str(), buf, sizeof(buf)));
+      ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
+      ASSERT_EQ(0, memcmp(op_bl.c_str() + sizeof(buf), buf, sizeof(buf)));
+  }
+
+  {
+      bufferlist op_bl;
+      ObjectReadOperation op;
+      op.read(0, sizeof(buf), NULL, NULL);
+      ASSERT_EQ(0, ioctx.operate("foo", &op, &op_bl));
+      ASSERT_EQ(sizeof(buf), op_bl.length());
+      ASSERT_EQ(0, memcmp(op_bl.c_str(), buf, sizeof(buf)));
+  }
+
+  {
+      bufferlist read_bl;
+      ObjectReadOperation op;
+      op.read(0, sizeof(buf), &read_bl, NULL);
+      ASSERT_EQ(0, ioctx.operate("foo", &op, NULL));
+      ASSERT_EQ(sizeof(buf), read_bl.length());
+      ASSERT_EQ(0, memcmp(read_bl.c_str(), buf, sizeof(buf)));
+  }
+
+  {
+      int rval = 1000;
+      ObjectReadOperation op;
+      op.read(0, sizeof(buf), NULL, &rval);
+      ASSERT_EQ(0, ioctx.operate("foo", &op, NULL));
+      ASSERT_EQ(0, rval);
+  }
+
+  {
+      bufferlist read_bl;
+      int rval = 1000;
+      ObjectReadOperation op;
+      op.read(0, sizeof(buf), &read_bl, &rval);
+      ASSERT_EQ(0, ioctx.operate("foo", &op, NULL));
+      ASSERT_EQ(sizeof(buf), read_bl.length());
+      ASSERT_EQ(0, rval);
+      ASSERT_EQ(0, memcmp(read_bl.c_str(), buf, sizeof(buf)));
+  }
+
+  {
+      bufferlist read_bl1, read_bl2;
+      int rval1 = 1000, rval2 = 1002;
+      ObjectReadOperation op;
+      op.read(0, sizeof(buf), &read_bl1, &rval1);
+      op.read(0, sizeof(buf), &read_bl2, &rval2);
+      ASSERT_EQ(0, ioctx.operate("foo", &op, NULL));
+      ASSERT_EQ(sizeof(buf), read_bl1.length());
+      ASSERT_EQ(sizeof(buf), read_bl2.length());
+      ASSERT_EQ(0, rval1);
+      ASSERT_EQ(0, rval2);
+      ASSERT_EQ(0, memcmp(read_bl1.c_str(), buf, sizeof(buf)));
+      ASSERT_EQ(0, memcmp(read_bl2.c_str(), buf, sizeof(buf)));
+  }
+}
+
+TEST_F(LibRadosIoEC, RoundTrip) {
+  char buf[128];
+  char buf2[128];
+  memset(buf, 0xcc, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), rados_write(ioctx, "foo", buf, sizeof(buf), 0));
+  memset(buf2, 0, sizeof(buf2));
+  ASSERT_EQ((int)sizeof(buf2), rados_read(ioctx, "foo", buf2, sizeof(buf2), 0));
+  ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
+}
+
+TEST_F(LibRadosIoECPP, RoundTripPP) {
+  char buf[128];
+  char buf2[128];
+  Rados cluster;
+  memset(buf, 0xcc, sizeof(buf));
+  bufferlist bl;
+  bl.append(buf, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), ioctx.write("foo", bl, sizeof(buf), 0));
+  bufferlist cl;
+  ASSERT_EQ((int)sizeof(buf2), ioctx.read("foo", cl, sizeof(buf), 0));
+  ASSERT_EQ(0, memcmp(buf, cl.c_str(), sizeof(buf)));
+}
+
+TEST_F(LibRadosIoEC, OverlappingWriteRoundTrip) {
+  int bsize = alignment;
+  int dbsize = bsize * 2;
+  char *buf = (char *)new char[dbsize];
+  char *buf2 = (char *)new char[bsize];
+  char *buf3 = (char *)new char[dbsize];
+  memset(buf, 0xcc, dbsize);
+  ASSERT_EQ(dbsize, rados_write(ioctx, "foo", buf, dbsize, 0));
+  memset(buf2, 0xdd, sizeof(buf2));
+  ASSERT_EQ(-EOPNOTSUPP, rados_write(ioctx, "foo", buf2, bsize, 0));
+  memset(buf3, 0xdd, sizeof(buf3));
+  ASSERT_EQ(dbsize, rados_read(ioctx, "foo", buf3, dbsize, 0));
+  // Read the same as first write
+  ASSERT_EQ(0, memcmp(buf3, buf, dbsize));
+
+  delete[] buf;
+  delete[] buf2;
+  delete[] buf3;
+}
+
+TEST_F(LibRadosIoECPP, OverlappingWriteRoundTripPP) {
+  int bsize = alignment;
+  int dbsize = bsize * 2;
+  char *buf = (char *)new char[dbsize];
+  char *buf2 = (char *)new char[bsize];
+  memset(buf, 0xcc, dbsize);
+  bufferlist bl1;
+  bl1.append(buf, dbsize);
+  ASSERT_EQ(dbsize, ioctx.write("foo", bl1, dbsize, 0));
+  memset(buf2, 0xdd, bsize);
+  bufferlist bl2;
+  bl2.append(buf2, bsize);
+  ASSERT_EQ(-EOPNOTSUPP, ioctx.write("foo", bl2, bsize, 0));
+  bufferlist bl3;
+  ASSERT_EQ(dbsize, ioctx.read("foo", bl3, dbsize, 0));
+  // Read the same as first write
+  ASSERT_EQ(0, memcmp(bl3.c_str(), buf, dbsize));
+
+  delete[] buf;
+  delete[] buf2;
+}
+
+TEST_F(LibRadosIoEC, WriteFullRoundTrip) {
+  char buf[128];
+  char buf2[64];
+  char buf3[128];
+  memset(buf, 0xcc, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), rados_write(ioctx, "foo", buf, sizeof(buf), 0));
+  memset(buf2, 0xdd, sizeof(buf2));
+  ASSERT_EQ(0, rados_write_full(ioctx, "foo", buf2, sizeof(buf2)));
+  memset(buf3, 0xdd, sizeof(buf3));
+  ASSERT_EQ((int)sizeof(buf2), rados_read(ioctx, "foo", buf3, sizeof(buf3), 0));
+  ASSERT_EQ(0, memcmp(buf2, buf2, sizeof(buf2)));
+}
+
+TEST_F(LibRadosIoECPP, WriteFullRoundTripPP) {
+  char buf[128];
+  char buf2[64];
+  memset(buf, 0xcc, sizeof(buf));
+  bufferlist bl1;
+  bl1.append(buf, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), ioctx.write("foo", bl1, sizeof(buf), 0));
+  memset(buf2, 0xdd, sizeof(buf2));
+  bufferlist bl2;
+  bl2.append(buf2, sizeof(buf2));
+  ASSERT_EQ(0, ioctx.write_full("foo", bl2));
+  bufferlist bl3;
+  ASSERT_EQ((int)sizeof(buf2), ioctx.read("foo", bl3, sizeof(buf), 0));
+  ASSERT_EQ(0, memcmp(bl3.c_str(), buf2, sizeof(buf2)));
+}
+
+TEST_F(LibRadosIoEC, AppendRoundTrip) {
+  char *buf = (char *)new char[alignment];
+  char *buf2 = (char *)new char[alignment];
+  char *buf3 = (char *)new char[alignment *2];
+  memset(buf, 0xde, alignment);
+  ASSERT_EQ((int)alignment, rados_append(ioctx, "foo", buf, alignment));
+  memset(buf2, 0xad, alignment);
+  ASSERT_EQ((int)alignment, rados_append(ioctx, "foo", buf2, alignment));
+  memset(buf3, 0, alignment*2);
+  ASSERT_EQ((int)alignment*2, rados_read(ioctx, "foo", buf3, alignment*2, 0));
+  ASSERT_EQ(0, memcmp(buf3, buf, alignment));
+  ASSERT_EQ(0, memcmp(buf3 + alignment, buf2, alignment));
+
+  delete[] buf;
+  delete[] buf2;
+  delete[] buf3;
+}
+
+TEST_F(LibRadosIoECPP, AppendRoundTripPP) {
+  char *buf = (char *)new char[alignment];
+  char *buf2 = (char *)new char[alignment];
+  memset(buf, 0xde, alignment);
+  bufferlist bl1;
+  bl1.append(buf, alignment);
+  ASSERT_EQ((int)alignment, ioctx.append("foo", bl1, alignment));
+  memset(buf2, 0xad, alignment);
+  bufferlist bl2;
+  bl2.append(buf2, alignment);
+  ASSERT_EQ((int)alignment, ioctx.append("foo", bl2, alignment));
+  bufferlist bl3;
+  ASSERT_EQ((int)(alignment * 2),
+	    ioctx.read("foo", bl3, (alignment * 2), 0));
+  const char *bl3_str = bl3.c_str();
+  ASSERT_EQ(0, memcmp(bl3_str, buf, alignment));
+  ASSERT_EQ(0, memcmp(bl3_str + alignment, buf2, alignment));
+
+  delete[] buf;
+  delete[] buf2;
+}
+
+TEST_F(LibRadosIoEC, TruncTest) {
+  char buf[128];
+  char buf2[sizeof(buf)];
+  memset(buf, 0xaa, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), rados_append(ioctx, "foo", buf, sizeof(buf)));
+  ASSERT_EQ(-EOPNOTSUPP, rados_trunc(ioctx, "foo", sizeof(buf) / 2));
+  memset(buf2, 0, sizeof(buf2));
+  // Same size
+  ASSERT_EQ((int)sizeof(buf), rados_read(ioctx, "foo", buf2, sizeof(buf2), 0));
+  // No change
+  ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
+}
+
+TEST_F(LibRadosIoECPP, TruncTestPP) {
+  char buf[128];
+  memset(buf, 0xaa, sizeof(buf));
+  bufferlist bl;
+  bl.append(buf, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), ioctx.append("foo", bl, sizeof(buf)));
+  ASSERT_EQ(-EOPNOTSUPP, ioctx.trunc("foo", sizeof(buf) / 2));
+  bufferlist bl2;
+  // Same size
+  ASSERT_EQ((int)sizeof(buf), ioctx.read("foo", bl2, sizeof(buf), 0));
+  // No change
+  ASSERT_EQ(0, memcmp(bl2.c_str(), buf, sizeof(buf)));
+}
+
+TEST_F(LibRadosIoEC, RemoveTest) {
+  char buf[128];
+  char buf2[sizeof(buf)];
+  memset(buf, 0xaa, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), rados_append(ioctx, "foo", buf, sizeof(buf)));
+  ASSERT_EQ(0, rados_remove(ioctx, "foo"));
+  memset(buf2, 0, sizeof(buf2));
+  ASSERT_EQ(-ENOENT, rados_read(ioctx, "foo", buf2, sizeof(buf2), 0));
+}
+
+TEST_F(LibRadosIoECPP, RemoveTestPP) {
+  char buf[128];
+  memset(buf, 0xaa, sizeof(buf));
+  bufferlist bl1;
+  bl1.append(buf, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), ioctx.append("foo", bl1, sizeof(buf)));
+  ASSERT_EQ(0, ioctx.remove("foo"));
+  bufferlist bl2;
+  ASSERT_EQ(-ENOENT, ioctx.read("foo", bl2, sizeof(buf), 0));
+}
+
+TEST_F(LibRadosIoEC, XattrsRoundTrip) {
+  char buf[128];
+  char attr1[] = "attr1";
+  char attr1_buf[] = "foo bar baz";
+  memset(buf, 0xaa, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), rados_append(ioctx, "foo", buf, sizeof(buf)));
+  ASSERT_EQ(-ENODATA, rados_getxattr(ioctx, "foo", attr1, buf, sizeof(buf)));
+  ASSERT_EQ(0, rados_setxattr(ioctx, "foo", attr1, attr1_buf, sizeof(attr1_buf)));
+  ASSERT_EQ((int)sizeof(attr1_buf),
+	    rados_getxattr(ioctx, "foo", attr1, buf, sizeof(buf)));
+  ASSERT_EQ(0, memcmp(attr1_buf, buf, sizeof(attr1_buf)));
+}
+
+TEST_F(LibRadosIoECPP, XattrsRoundTripPP) {
+  char buf[128];
+  char attr1[] = "attr1";
+  char attr1_buf[] = "foo bar baz";
+  memset(buf, 0xaa, sizeof(buf));
+  bufferlist bl1;
+  bl1.append(buf, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), ioctx.append("foo", bl1, sizeof(buf)));
+  bufferlist bl2;
+  ASSERT_EQ(-ENODATA, ioctx.getxattr("foo", attr1, bl2));
+  bufferlist bl3;
+  bl3.append(attr1_buf, sizeof(attr1_buf));
+  ASSERT_EQ(0, ioctx.setxattr("foo", attr1, bl3));
+  bufferlist bl4;
+  ASSERT_EQ((int)sizeof(attr1_buf),
+      ioctx.getxattr("foo", attr1, bl4));
+  ASSERT_EQ(0, memcmp(bl4.c_str(), attr1_buf, sizeof(attr1_buf)));
+}
+
+TEST_F(LibRadosIoEC, RmXattr) {
+  char buf[128];
+  char attr1[] = "attr1";
+  char attr1_buf[] = "foo bar baz";
+  memset(buf, 0xaa, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), rados_append(ioctx, "foo", buf, sizeof(buf)));
+  ASSERT_EQ(0,
+      rados_setxattr(ioctx, "foo", attr1, attr1_buf, sizeof(attr1_buf)));
+  ASSERT_EQ(0, rados_rmxattr(ioctx, "foo", attr1));
+  ASSERT_EQ(-ENODATA, rados_getxattr(ioctx, "foo", attr1, buf, sizeof(buf)));
+}
+
+TEST_F(LibRadosIoECPP, RmXattrPP) {
+  char buf[128];
+  char attr1[] = "attr1";
+  char attr1_buf[] = "foo bar baz";
+  memset(buf, 0xaa, sizeof(buf));
+  bufferlist bl1;
+  bl1.append(buf, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), ioctx.append("foo", bl1, sizeof(buf)));
+  bufferlist bl2;
+  bl2.append(attr1_buf, sizeof(attr1_buf));
+  ASSERT_EQ(0, ioctx.setxattr("foo", attr1, bl2));
+  ASSERT_EQ(0, ioctx.rmxattr("foo", attr1));
+  bufferlist bl3;
+  ASSERT_EQ(-ENODATA, ioctx.getxattr("foo", attr1, bl3));
+}
+
+TEST_F(LibRadosIoEC, XattrIter) {
+  char buf[128];
+  char attr1[] = "attr1";
+  char attr1_buf[] = "foo bar baz";
+  char attr2[] = "attr2";
+  char attr2_buf[256];
+  for (size_t j = 0; j < sizeof(attr2_buf); ++j) {
+    attr2_buf[j] = j % 0xff;
+  }
+  memset(buf, 0xaa, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), rados_append(ioctx, "foo", buf, sizeof(buf)));
+  ASSERT_EQ(0, rados_setxattr(ioctx, "foo", attr1, attr1_buf, sizeof(attr1_buf)));
+  ASSERT_EQ(0, rados_setxattr(ioctx, "foo", attr2, attr2_buf, sizeof(attr2_buf)));
+  rados_xattrs_iter_t iter;
+  ASSERT_EQ(0, rados_getxattrs(ioctx, "foo", &iter));
+  int num_seen = 0;
+  while (true) {
+    const char *name;
+    const char *val;
+    size_t len;
+    ASSERT_EQ(0, rados_getxattrs_next(iter, &name, &val, &len));
+    if (name == NULL) {
+      break;
+    }
+    ASSERT_LT(num_seen, 2);
+    if ((strcmp(name, attr1) == 0) && (memcmp(val, attr1_buf, len) == 0)) {
+      num_seen++;
+      continue;
+    }
+    else if ((strcmp(name, attr2) == 0) && (memcmp(val, attr2_buf, len) == 0)) {
+      num_seen++;
+      continue;
+    }
+    else {
+      ASSERT_EQ(0, 1);
+    }
+  }
+  rados_getxattrs_end(iter);
+}
+
+TEST_F(LibRadosIoECPP, XattrListPP) {
+  char buf[128];
+  char attr1[] = "attr1";
+  char attr1_buf[] = "foo bar baz";
+  char attr2[] = "attr2";
+  char attr2_buf[256];
+  for (size_t j = 0; j < sizeof(attr2_buf); ++j) {
+    attr2_buf[j] = j % 0xff;
+  }
+  memset(buf, 0xaa, sizeof(buf));
+  bufferlist bl1;
+  bl1.append(buf, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), ioctx.append("foo", bl1, sizeof(buf)));
+  bufferlist bl2;
+  bl2.append(attr1_buf, sizeof(attr1_buf));
+  ASSERT_EQ(0, ioctx.setxattr("foo", attr1, bl2));
+  bufferlist bl3;
+  bl3.append(attr2_buf, sizeof(attr2_buf));
+  ASSERT_EQ(0, ioctx.setxattr("foo", attr2, bl3));
+  std::map<std::string, bufferlist> attrset;
+  ASSERT_EQ(0, ioctx.getxattrs("foo", attrset));
+  for (std::map<std::string, bufferlist>::iterator i = attrset.begin();
+       i != attrset.end(); ++i) {
+    if (i->first == string(attr1)) {
+      ASSERT_EQ(0, memcmp(i->second.c_str(), attr1_buf, sizeof(attr1_buf)));
+    }
+    else if (i->first == string(attr2)) {
+      ASSERT_EQ(0, memcmp(i->second.c_str(), attr2_buf, sizeof(attr2_buf)));
+    }
+    else {
+      ASSERT_EQ(0, 1);
+    }
+  }
+}
diff --git a/src/test/librados/list.cc b/src/test/librados/list.cc
index c530b60..2e400d5 100644
--- a/src/test/librados/list.cc
+++ b/src/test/librados/list.cc
@@ -14,6 +14,8 @@ using namespace librados;
 
 typedef RadosTest LibRadosList;
 typedef RadosTestPP LibRadosListPP;
+typedef RadosTestEC LibRadosListEC;
+typedef RadosTestECPP LibRadosListECPP;
 
 TEST_F(LibRadosList, ListObjects) {
   char buf[128];
@@ -339,3 +341,293 @@ TEST_F(LibRadosListPP, ListObjectsStartPP) {
     ++p;
   }
 }
+
+TEST_F(LibRadosListEC, ListObjects) {
+  char buf[128];
+  memset(buf, 0xcc, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), rados_write(ioctx, "foo", buf, sizeof(buf), 0));
+  rados_list_ctx_t ctx;
+  ASSERT_EQ(0, rados_objects_list_open(ioctx, &ctx));
+  const char *entry;
+  bool foundit = false;
+  while (rados_objects_list_next(ctx, &entry, NULL) != -ENOENT) {
+    foundit = true;
+    ASSERT_EQ(std::string(entry), "foo");
+  }
+  ASSERT_TRUE(foundit);
+  rados_objects_list_close(ctx);
+}
+
+TEST_F(LibRadosListECPP, ListObjectsPP) {
+  char buf[128];
+  memset(buf, 0xcc, sizeof(buf));
+  bufferlist bl1;
+  bl1.append(buf, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), ioctx.write("foo", bl1, sizeof(buf), 0));
+  ObjectIterator iter(ioctx.objects_begin());
+  bool foundit = false;
+  while (iter != ioctx.objects_end()) {
+    foundit = true;
+    ASSERT_EQ((*iter).first, "foo");
+    ++iter;
+  }
+  ASSERT_TRUE(foundit);
+}
+
+TEST_F(LibRadosListECPP, ListObjectsTwicePP) {
+  char buf[128];
+  memset(buf, 0xcc, sizeof(buf));
+  bufferlist bl1;
+  bl1.append(buf, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), ioctx.write("foo", bl1, sizeof(buf), 0));
+  ObjectIterator iter(ioctx.objects_begin());
+  bool foundit = false;
+  while (iter != ioctx.objects_end()) {
+    foundit = true;
+    ASSERT_EQ((*iter).first, "foo");
+    ++iter;
+  }
+  ASSERT_TRUE(foundit);
+  ++iter;
+  ASSERT_TRUE(iter == ioctx.objects_end());
+  foundit = false;
+  iter.seek(0);
+  while (iter != ioctx.objects_end()) {
+    foundit = true;
+    ASSERT_EQ((*iter).first, "foo");
+    ++iter;
+  }
+  ASSERT_TRUE(foundit);
+}
+
+TEST_F(LibRadosListECPP, ListObjectsCopyIterPP) {
+  char buf[128];
+  memset(buf, 0xcc, sizeof(buf));
+  bufferlist bl1;
+  bl1.append(buf, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), ioctx.write("foo", bl1, sizeof(buf), 0));
+
+  // make sure this is still valid after the original iterators are gone
+  ObjectIterator iter3;
+  {
+    ObjectIterator iter(ioctx.objects_begin());
+    ObjectIterator iter2(iter);
+    iter3 = iter2;
+    ASSERT_EQ((*iter).first, "foo");
+    ++iter;
+    ASSERT_TRUE(iter == ioctx.objects_end());
+    ++iter;
+    ASSERT_TRUE(iter == ioctx.objects_end());
+
+    ASSERT_EQ(iter2->first, "foo");
+    ASSERT_EQ(iter3->first, "foo");
+    ++iter2;
+    ASSERT_TRUE(iter2 == ioctx.objects_end());
+  }
+
+  ASSERT_EQ(iter3->first, "foo");
+  iter3 = iter3;
+  ASSERT_EQ(iter3->first, "foo");
+  ++iter3;
+  ASSERT_TRUE(iter3 == ioctx.objects_end());
+}
+
+TEST_F(LibRadosListECPP, ListObjectsEndIter) {
+  char buf[128];
+  memset(buf, 0xcc, sizeof(buf));
+  bufferlist bl1;
+  bl1.append(buf, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), ioctx.write("foo", bl1, sizeof(buf), 0));
+
+  ObjectIterator iter(ioctx.objects_begin());
+  ObjectIterator iter_end(ioctx.objects_end());
+  ObjectIterator iter_end2 = ioctx.objects_end();
+  ASSERT_TRUE(iter_end == iter_end2);
+  ASSERT_TRUE(iter_end == ioctx.objects_end());
+  ASSERT_TRUE(iter_end2 == ioctx.objects_end());
+
+  ASSERT_EQ(iter->first, "foo");
+  ++iter;
+  ASSERT_TRUE(iter == ioctx.objects_end());
+  ASSERT_TRUE(iter == iter_end);
+  ASSERT_TRUE(iter == iter_end2);
+  ObjectIterator iter2 = iter;
+  ASSERT_TRUE(iter2 == ioctx.objects_end());
+  ASSERT_TRUE(iter2 == iter_end);
+  ASSERT_TRUE(iter2 == iter_end2);
+}
+
+TEST_F(LibRadosListEC, ListObjectsNS) {
+  char buf[128];
+  memset(buf, 0xcc, sizeof(buf));
+  // Create :foo1, :foo2, :foo3, n1:foo1, ns1:foo4, ns1:foo5, ns2:foo6, n2:foo7
+  rados_ioctx_set_namespace(ioctx, "");
+  ASSERT_EQ((int)sizeof(buf), rados_write(ioctx, "foo1", buf, sizeof(buf), 0));
+  rados_ioctx_set_namespace(ioctx, "ns1");
+  ASSERT_EQ((int)sizeof(buf), rados_write(ioctx, "foo1", buf, sizeof(buf), 0));
+  rados_ioctx_set_namespace(ioctx, "");
+  ASSERT_EQ((int)sizeof(buf), rados_write(ioctx, "foo2", buf, sizeof(buf), 0));
+  ASSERT_EQ((int)sizeof(buf), rados_write(ioctx, "foo3", buf, sizeof(buf), 0));
+  rados_ioctx_set_namespace(ioctx, "ns1");
+  ASSERT_EQ((int)sizeof(buf), rados_write(ioctx, "foo4", buf, sizeof(buf), 0));
+  ASSERT_EQ((int)sizeof(buf), rados_write(ioctx, "foo5", buf, sizeof(buf), 0));
+  rados_ioctx_set_namespace(ioctx, "ns2");
+  ASSERT_EQ((int)sizeof(buf), rados_write(ioctx, "foo6", buf, sizeof(buf), 0));
+  ASSERT_EQ((int)sizeof(buf), rados_write(ioctx, "foo7", buf, sizeof(buf), 0));
+
+  std::set<std::string> def, ns1, ns2;
+  def.insert(std::string("foo1"));
+  def.insert(std::string("foo2"));
+  def.insert(std::string("foo3"));
+  ns1.insert(std::string("foo1"));
+  ns1.insert(std::string("foo4"));
+  ns1.insert(std::string("foo5"));
+  ns2.insert(std::string("foo6"));
+  ns2.insert(std::string("foo7"));
+
+  rados_list_ctx_t ctx;
+  // Check default namespace ""
+  rados_ioctx_set_namespace(ioctx, "");
+  ASSERT_EQ(0, rados_objects_list_open(ioctx, &ctx));
+  check_list(def, ctx);
+  rados_objects_list_close(ctx);
+
+  // Check default namespace "ns1"
+  rados_ioctx_set_namespace(ioctx, "ns1");
+  ASSERT_EQ(0, rados_objects_list_open(ioctx, &ctx));
+  check_list(ns1, ctx);
+  rados_objects_list_close(ctx);
+
+  // Check default namespace "ns2"
+  rados_ioctx_set_namespace(ioctx, "ns2");
+  ASSERT_EQ(0, rados_objects_list_open(ioctx, &ctx));
+  check_list(ns2, ctx);
+  rados_objects_list_close(ctx);
+}
+
+TEST_F(LibRadosListECPP, ListObjectsPPNS) {
+  char buf[128];
+  memset(buf, 0xcc, sizeof(buf));
+  bufferlist bl1;
+  bl1.append(buf, sizeof(buf));
+  // Create :foo1, :foo2, :foo3, n1:foo1, ns1:foo4, ns1:foo5, ns2:foo6, n2:foo7
+  ioctx.set_namespace("");
+  ASSERT_EQ((int)sizeof(buf), ioctx.write("foo1", bl1, sizeof(buf), 0));
+  ioctx.set_namespace("ns1");
+  ASSERT_EQ((int)sizeof(buf), ioctx.write("foo1", bl1, sizeof(buf), 0));
+  ioctx.set_namespace("");
+  ASSERT_EQ((int)sizeof(buf), ioctx.write("foo2", bl1, sizeof(buf), 0));
+  ASSERT_EQ((int)sizeof(buf), ioctx.write("foo3", bl1, sizeof(buf), 0));
+  ioctx.set_namespace("ns1");
+  ASSERT_EQ((int)sizeof(buf), ioctx.write("foo4", bl1, sizeof(buf), 0));
+  ASSERT_EQ((int)sizeof(buf), ioctx.write("foo5", bl1, sizeof(buf), 0));
+  ioctx.set_namespace("ns2");
+  ASSERT_EQ((int)sizeof(buf), ioctx.write("foo6", bl1, sizeof(buf), 0));
+  ASSERT_EQ((int)sizeof(buf), ioctx.write("foo7", bl1, sizeof(buf), 0));
+
+  std::set<std::string> def, ns1, ns2;
+  def.insert(std::string("foo1"));
+  def.insert(std::string("foo2"));
+  def.insert(std::string("foo3"));
+  ns1.insert(std::string("foo1"));
+  ns1.insert(std::string("foo4"));
+  ns1.insert(std::string("foo5"));
+  ns2.insert(std::string("foo6"));
+  ns2.insert(std::string("foo7"));
+
+  ioctx.set_namespace("");
+  check_listpp(def, ioctx);
+
+  ioctx.set_namespace("ns1");
+  check_listpp(ns1, ioctx);
+
+  ioctx.set_namespace("ns2");
+  check_listpp(ns2, ioctx);
+}
+
+TEST_F(LibRadosListECPP, ListObjectsManyPP) {
+  char buf[128];
+  memset(buf, 0xcc, sizeof(buf));
+  bufferlist bl;
+  bl.append(buf, sizeof(buf));
+
+  for (int i=0; i<256; ++i) {
+    ASSERT_EQ((int)sizeof(buf), ioctx.write(stringify(i), bl, bl.length(), 0));
+  }
+
+  librados::ObjectIterator it = ioctx.objects_begin();
+  std::set<std::string> saw_obj;
+  std::set<int> saw_pg;
+  for (; it != ioctx.objects_end(); ++it) {
+    std::cout << it->first
+	      << " " << it.get_pg_hash_position() << std::endl;
+    saw_obj.insert(it->first);
+    saw_pg.insert(it.get_pg_hash_position());
+  }
+  std::cout << "saw " << saw_pg.size() << " pgs " << std::endl;
+
+  // make sure they are 0..n
+  for (unsigned i = 0; i < saw_pg.size(); ++i)
+    ASSERT_TRUE(saw_pg.count(i));
+}
+
+TEST_F(LibRadosListEC, ListObjectsStart) {
+  char buf[128];
+  memset(buf, 0xcc, sizeof(buf));
+
+  for (int i=0; i<16; ++i) {
+    string n = stringify(i);
+    ASSERT_EQ((int)sizeof(buf), rados_write(ioctx, n.c_str(), buf, sizeof(buf), 0));
+  }
+
+  rados_list_ctx_t ctx;
+  ASSERT_EQ(0, rados_objects_list_open(ioctx, &ctx));
+  std::map<int, std::set<std::string> > pg_to_obj;
+  const char *entry;
+  while (rados_objects_list_next(ctx, &entry, NULL) == 0) {
+    uint32_t pos = rados_objects_list_get_pg_hash_position(ctx);
+    std::cout << entry << " " << pos << std::endl;
+    pg_to_obj[pos].insert(entry);
+  }
+  rados_objects_list_close(ctx);
+
+  std::map<int, std::set<std::string> >::reverse_iterator p =
+    pg_to_obj.rbegin();
+  ASSERT_EQ(0, rados_objects_list_open(ioctx, &ctx));
+  while (p != pg_to_obj.rend()) {
+    ASSERT_EQ((uint32_t)p->first, rados_objects_list_seek(ctx, p->first));
+    ASSERT_EQ(0, rados_objects_list_next(ctx, &entry, NULL));
+    std::cout << "have " << entry << " expect one of " << p->second << std::endl;
+    ASSERT_TRUE(p->second.count(entry));
+    ++p;
+  }
+  rados_objects_list_close(ctx);
+}
+
+TEST_F(LibRadosListECPP, ListObjectsStartPP) {
+  char buf[128];
+  memset(buf, 0xcc, sizeof(buf));
+  bufferlist bl;
+  bl.append(buf, sizeof(buf));
+
+  for (int i=0; i<16; ++i) {
+    ASSERT_EQ((int)sizeof(buf), ioctx.write(stringify(i), bl, bl.length(), 0));
+  }
+
+  librados::ObjectIterator it = ioctx.objects_begin();
+  std::map<int, std::set<std::string> > pg_to_obj;
+  for (; it != ioctx.objects_end(); ++it) {
+    std::cout << it->first << " " << it.get_pg_hash_position() << std::endl;
+    pg_to_obj[it.get_pg_hash_position()].insert(it->first);
+  }
+
+  std::map<int, std::set<std::string> >::reverse_iterator p =
+    pg_to_obj.rbegin();
+  it = ioctx.objects_begin(p->first);
+  while (p != pg_to_obj.rend()) {
+    ASSERT_EQ((uint32_t)p->first, it.seek(p->first));
+    std::cout << "have " << it->first << " expect one of " << p->second << std::endl;
+    ASSERT_TRUE(p->second.count(it->first));
+    ++p;
+  }
+}
diff --git a/src/test/librados/lock.cc b/src/test/librados/lock.cc
index 6894ed4..1a7c583 100644
--- a/src/test/librados/lock.cc
+++ b/src/test/librados/lock.cc
@@ -13,6 +13,8 @@ using namespace librados;
 
 typedef RadosTest LibRadosLock;
 typedef RadosTestPP LibRadosLockPP;
+typedef RadosTestEC LibRadosLockEC;
+typedef RadosTestECPP LibRadosLockECPP;
 
 TEST_F(LibRadosLock, LockExclusive) {
   ASSERT_EQ(0, rados_lock_exclusive(ioctx, "foo", "TestLock", "Cookie", "", NULL,  0));
@@ -191,3 +193,182 @@ TEST_F(LibRadosLockPP, BreakLockPP) {
   ASSERT_EQ("Cookie", it->cookie);
   ASSERT_EQ(0, ioctx.break_lock("foo", "TestLock", it->client, "Cookie"));
 }
+
+// EC testing
+TEST_F(LibRadosLockEC, LockExclusive) {
+  ASSERT_EQ(0, rados_lock_exclusive(ioctx, "foo", "TestLock", "Cookie", "", NULL,  0));
+  ASSERT_EQ(-EEXIST, rados_lock_exclusive(ioctx, "foo", "TestLock", "Cookie", "", NULL, 0));
+}
+
+TEST_F(LibRadosLockECPP, LockExclusivePP) {
+  ASSERT_EQ(0, ioctx.lock_exclusive("foo", "TestLock", "Cookie", "", NULL,  0));
+  ASSERT_EQ(-EEXIST, ioctx.lock_exclusive("foo", "TestLock", "Cookie", "", NULL, 0));
+}
+
+TEST_F(LibRadosLockEC, LockShared) {
+  ASSERT_EQ(0, rados_lock_shared(ioctx, "foo", "TestLock", "Cookie", "Tag", "", NULL, 0));
+  ASSERT_EQ(-EEXIST, rados_lock_shared(ioctx, "foo", "TestLock", "Cookie", "Tag", "", NULL, 0));
+}
+
+TEST_F(LibRadosLockECPP, LockSharedPP) {
+  ASSERT_EQ(0, ioctx.lock_shared("foo", "TestLock", "Cookie", "Tag", "", NULL, 0));
+  ASSERT_EQ(-EEXIST, ioctx.lock_shared("foo", "TestLock", "Cookie", "Tag", "", NULL, 0));
+}
+
+TEST_F(LibRadosLockEC, LockExclusiveDur) {
+  struct timeval tv;
+  tv.tv_sec = 1;
+  tv.tv_usec = 0;
+  ASSERT_EQ(0, rados_lock_exclusive(ioctx, "foo", "TestLock", "Cookie", "", &tv,  0));
+  sleep(1);
+  ASSERT_EQ(0, rados_lock_exclusive(ioctx, "foo", "TestLock", "Cookie", "", NULL, 0));
+}
+
+TEST_F(LibRadosLockECPP, LockExclusiveDurPP) {
+  struct timeval tv;
+  tv.tv_sec = 1;
+  tv.tv_usec = 0;
+  ASSERT_EQ(0, ioctx.lock_exclusive("foo", "TestLock", "Cookie", "", &tv,  0));
+  sleep(1);
+  ASSERT_EQ(0, ioctx.lock_exclusive("foo", "TestLock", "Cookie", "", NULL, 0));
+}
+
+TEST_F(LibRadosLockEC, LockSharedDur) {
+  struct timeval tv;
+  tv.tv_sec = 1;
+  tv.tv_usec = 0;
+  ASSERT_EQ(0, rados_lock_shared(ioctx, "foo", "TestLock", "Cookie", "Tag", "", &tv, 0));
+  sleep(1);
+  ASSERT_EQ(0, rados_lock_shared(ioctx, "foo", "TestLock", "Cookie", "Tag", "", NULL, 0));
+}
+
+TEST_F(LibRadosLockECPP, LockSharedDurPP) {
+  struct timeval tv;
+  tv.tv_sec = 1;
+  tv.tv_usec = 0;
+  ASSERT_EQ(0, ioctx.lock_shared("foo", "TestLock", "Cookie", "Tag", "", &tv, 0));
+  sleep(1);
+  ASSERT_EQ(0, ioctx.lock_shared("foo", "TestLock", "Cookie", "Tag", "", NULL, 0));
+}
+
+TEST_F(LibRadosLockEC, LockRenew) {
+  ASSERT_EQ(0, rados_lock_exclusive(ioctx, "foo", "TestLock", "Cookie", "", NULL, 0));
+  ASSERT_EQ(-EEXIST, rados_lock_exclusive(ioctx, "foo", "TestLock", "Cookie", "", NULL, 0));
+  ASSERT_EQ(0, rados_lock_exclusive(ioctx, "foo", "TestLock", "Cookie", "", NULL, LOCK_FLAG_RENEW));
+}
+
+TEST_F(LibRadosLockECPP, LockRenewPP) {
+  ASSERT_EQ(0, ioctx.lock_exclusive("foo", "TestLock", "Cookie", "", NULL, 0));
+  ASSERT_EQ(-EEXIST, ioctx.lock_exclusive("foo", "TestLock", "Cookie", "", NULL, 0));
+  ASSERT_EQ(0, ioctx.lock_exclusive("foo", "TestLock", "Cookie", "", NULL, LOCK_FLAG_RENEW));
+}
+
+TEST_F(LibRadosLockEC, Unlock) {
+  ASSERT_EQ(0, rados_lock_exclusive(ioctx, "foo", "TestLock", "Cookie", "", NULL, 0));
+  ASSERT_EQ(0, rados_unlock(ioctx, "foo", "TestLock", "Cookie"));
+  ASSERT_EQ(0, rados_lock_exclusive(ioctx, "foo", "TestLock", "Cookie", "", NULL,  0));
+}
+
+TEST_F(LibRadosLockECPP, UnlockPP) {
+  ASSERT_EQ(0, ioctx.lock_exclusive("foo", "TestLock", "Cookie", "", NULL, 0));
+  ASSERT_EQ(0, ioctx.unlock("foo", "TestLock", "Cookie"));
+  ASSERT_EQ(0, ioctx.lock_exclusive("foo", "TestLock", "Cookie", "", NULL, 0));
+}
+
+TEST_F(LibRadosLockEC, ListLockers) {
+  int exclusive;
+  char tag[1024];
+  char clients[1024];
+  char cookies[1024];
+  char addresses[1024];
+  size_t tag_len = 1024;
+  size_t clients_len = 1024;
+  size_t cookies_len = 1024;
+  size_t addresses_len = 1024;
+  std::stringstream sstm;
+  sstm << "client." << rados_get_instance_id(cluster);
+  std::string me = sstm.str();
+  ASSERT_EQ(0, rados_lock_shared(ioctx, "foo", "TestLock", "Cookie", "Tag", "", NULL, 0));
+  ASSERT_EQ(0, rados_unlock(ioctx, "foo", "TestLock", "Cookie"));
+  ASSERT_EQ(0, rados_list_lockers(ioctx, "foo", "TestLock", &exclusive, tag, &tag_len, clients, &clients_len, cookies, &cookies_len, addresses, &addresses_len ));
+  ASSERT_EQ(0, rados_lock_shared(ioctx, "foo", "TestLock", "Cookie", "Tag", "", NULL, 0));
+  ASSERT_EQ(-34, rados_list_lockers(ioctx, "foo", "TestLock", &exclusive, tag, &tag_len, clients, &clients_len, cookies, &cookies_len, addresses, &addresses_len ));
+  tag_len = 1024;
+  clients_len = 1024;
+  cookies_len = 1024;
+  addresses_len = 1024;
+  ASSERT_EQ(1, rados_list_lockers(ioctx, "foo", "TestLock", &exclusive, tag, &tag_len, clients, &clients_len, cookies, &cookies_len, addresses, &addresses_len ));
+  ASSERT_EQ(0, exclusive);
+  ASSERT_EQ(0, strcmp(tag, "Tag"));
+  ASSERT_EQ(strlen("Tag") + 1, tag_len);
+  ASSERT_EQ(0, strcmp(me.c_str(), clients));
+  ASSERT_EQ(me.size() + 1, clients_len);
+  ASSERT_EQ(0, strcmp(cookies, "Cookie"));
+  ASSERT_EQ(strlen("Cookie") + 1, cookies_len);
+}
+
+TEST_F(LibRadosLockECPP, ListLockersPP) {
+  std::stringstream sstm;
+  sstm << "client." << cluster.get_instance_id();
+  std::string me = sstm.str();
+  ASSERT_EQ(0, ioctx.lock_shared("foo", "TestLock", "Cookie", "Tag", "", NULL, 0));
+  ASSERT_EQ(0, ioctx.unlock("foo", "TestLock", "Cookie"));
+  {
+    int exclusive;
+    std::string tag;
+    std::list<librados::locker_t> lockers;
+    ASSERT_EQ(0, ioctx.list_lockers("foo", "TestLock", &exclusive, &tag, &lockers));
+  }
+  ASSERT_EQ(0, ioctx.lock_shared("foo", "TestLock", "Cookie", "Tag", "", NULL, 0));
+  {
+    int exclusive;
+    std::string tag;
+    std::list<librados::locker_t> lockers;
+    ASSERT_EQ(1, ioctx.list_lockers("foo", "TestLock", &exclusive, &tag, &lockers));
+    std::list<librados::locker_t>::iterator it = lockers.begin();
+    ASSERT_FALSE(lockers.end() == it);
+    ASSERT_EQ(me, it->client);
+    ASSERT_EQ("Cookie", it->cookie);
+  }
+}
+
+TEST_F(LibRadosLockEC, BreakLock) {
+  int exclusive;
+  char tag[1024];
+  char clients[1024];
+  char cookies[1024];
+  char addresses[1024];
+  size_t tag_len = 1024;
+  size_t clients_len = 1024;
+  size_t cookies_len = 1024;
+  size_t addresses_len = 1024;
+  std::stringstream sstm;
+  sstm << "client." << rados_get_instance_id(cluster);
+  std::string me = sstm.str();
+  ASSERT_EQ(0, rados_lock_exclusive(ioctx, "foo", "TestLock", "Cookie", "", NULL, 0));
+  ASSERT_EQ(1, rados_list_lockers(ioctx, "foo", "TestLock", &exclusive, tag, &tag_len, clients, &clients_len, cookies, &cookies_len, addresses, &addresses_len ));
+  ASSERT_EQ(1, exclusive);
+  ASSERT_EQ(0, strcmp(tag, ""));
+  ASSERT_EQ(1U, tag_len);
+  ASSERT_EQ(0, strcmp(me.c_str(), clients));
+  ASSERT_EQ(me.size() + 1, clients_len);
+  ASSERT_EQ(0, strcmp(cookies, "Cookie"));
+  ASSERT_EQ(strlen("Cookie") + 1, cookies_len);
+  ASSERT_EQ(0, rados_break_lock(ioctx, "foo", "TestLock", clients, "Cookie"));
+}
+
+TEST_F(LibRadosLockECPP, BreakLockPP) {
+  int exclusive;
+  std::string tag;
+  std::list<librados::locker_t> lockers;
+  std::stringstream sstm;
+  sstm << "client." << cluster.get_instance_id();
+  std::string me = sstm.str();
+  ASSERT_EQ(0, ioctx.lock_exclusive("foo", "TestLock", "Cookie",  "", NULL, 0));
+  ASSERT_EQ(1, ioctx.list_lockers("foo", "TestLock", &exclusive, &tag, &lockers));
+  std::list<librados::locker_t>::iterator it = lockers.begin();
+  ASSERT_FALSE(lockers.end() == it);
+  ASSERT_EQ(me, it->client);
+  ASSERT_EQ("Cookie", it->cookie);
+  ASSERT_EQ(0, ioctx.break_lock("foo", "TestLock", it->client, "Cookie"));
+}
diff --git a/src/test/librados/snapshots.cc b/src/test/librados/snapshots.cc
index 947d9c6..436b918 100644
--- a/src/test/librados/snapshots.cc
+++ b/src/test/librados/snapshots.cc
@@ -14,6 +14,10 @@ typedef RadosTest LibRadosSnapshots;
 typedef RadosTest LibRadosSnapshotsSelfManaged;
 typedef RadosTestPP LibRadosSnapshotsPP;
 typedef RadosTestPP LibRadosSnapshotsSelfManagedPP;
+typedef RadosTestEC LibRadosSnapshotsEC;
+typedef RadosTestEC LibRadosSnapshotsSelfManagedEC;
+typedef RadosTestECPP LibRadosSnapshotsECPP;
+typedef RadosTestECPP LibRadosSnapshotsSelfManagedECPP;
 
 const int bufsize = 128;
 
@@ -460,3 +464,335 @@ TEST_F(LibRadosSnapshotsSelfManagedPP, SnapOverlapPP) {
   my_snaps.pop_back();
   readioctx.close();
 }
+
+// EC testing
+TEST_F(LibRadosSnapshotsEC, SnapList) {
+  char buf[bufsize];
+  memset(buf, 0xcc, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), rados_write(ioctx, "foo", buf, sizeof(buf), 0));
+  ASSERT_EQ(0, rados_ioctx_snap_create(ioctx, "snap1"));
+  rados_snap_t snaps[10];
+  EXPECT_EQ(1, rados_ioctx_snap_list(ioctx, snaps,
+				     sizeof(snaps) / sizeof(snaps[0])));
+  rados_snap_t rid;
+  EXPECT_EQ(0, rados_ioctx_snap_lookup(ioctx, "snap1", &rid));
+  EXPECT_EQ(rid, snaps[0]);
+  EXPECT_EQ(0, rados_ioctx_snap_remove(ioctx, "snap1"));
+}
+
+TEST_F(LibRadosSnapshotsECPP, SnapListPP) {
+  char buf[bufsize];
+  memset(buf, 0xcc, sizeof(buf));
+  bufferlist bl1;
+  bl1.append(buf, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), ioctx.write("foo", bl1, sizeof(buf), 0));
+  ASSERT_EQ(0, ioctx.snap_create("snap1"));
+  std::vector<snap_t> snaps;
+  EXPECT_EQ(0, ioctx.snap_list(&snaps));
+  EXPECT_EQ(1U, snaps.size());
+  snap_t rid;
+  EXPECT_EQ(0, ioctx.snap_lookup("snap1", &rid));
+  EXPECT_EQ(rid, snaps[0]);
+  EXPECT_EQ(0, ioctx.snap_remove("snap1"));
+}
+
+TEST_F(LibRadosSnapshotsEC, SnapRemove) {
+  char buf[bufsize];
+  memset(buf, 0xcc, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), rados_write(ioctx, "foo", buf, sizeof(buf), 0));
+  ASSERT_EQ(0, rados_ioctx_snap_create(ioctx, "snap1"));
+  rados_snap_t rid;
+  ASSERT_EQ(0, rados_ioctx_snap_lookup(ioctx, "snap1", &rid));
+  ASSERT_EQ(-EEXIST, rados_ioctx_snap_create(ioctx, "snap1"));
+  ASSERT_EQ(0, rados_ioctx_snap_remove(ioctx, "snap1"));
+  ASSERT_EQ(-ENOENT, rados_ioctx_snap_lookup(ioctx, "snap1", &rid));
+}
+
+TEST_F(LibRadosSnapshotsECPP, SnapRemovePP) {
+  char buf[bufsize];
+  memset(buf, 0xcc, sizeof(buf));
+  bufferlist bl1;
+  bl1.append(buf, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), ioctx.write("foo", bl1, sizeof(buf), 0));
+  ASSERT_EQ(0, ioctx.snap_create("snap1"));
+  rados_snap_t rid;
+  ASSERT_EQ(0, ioctx.snap_lookup("snap1", &rid));
+  ASSERT_EQ(0, ioctx.snap_remove("snap1"));
+  ASSERT_EQ(-ENOENT, ioctx.snap_lookup("snap1", &rid));
+}
+
+TEST_F(LibRadosSnapshotsEC, Rollback) {
+  char buf[bufsize];
+  memset(buf, 0xcc, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), rados_write(ioctx, "foo", buf, sizeof(buf), 0));
+  ASSERT_EQ(0, rados_ioctx_snap_create(ioctx, "snap1"));
+  char buf2[sizeof(buf)];
+  memset(buf2, 0xdd, sizeof(buf2));
+  EXPECT_EQ(0, rados_write_full(ioctx, "foo", buf2, sizeof(buf2)));
+  EXPECT_EQ(0, rados_rollback(ioctx, "foo", "snap1"));
+  char buf3[sizeof(buf)];
+  EXPECT_EQ((int)sizeof(buf3), rados_read(ioctx, "foo", buf3, sizeof(buf3), 0));
+  EXPECT_EQ(0, memcmp(buf, buf3, sizeof(buf)));
+  EXPECT_EQ(0, rados_ioctx_snap_remove(ioctx, "snap1"));
+}
+
+TEST_F(LibRadosSnapshotsECPP, RollbackPP) {
+  char buf[bufsize];
+  memset(buf, 0xcc, sizeof(buf));
+  bufferlist bl1;
+  bl1.append(buf, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), ioctx.write("foo", bl1, sizeof(buf), 0));
+  ASSERT_EQ(0, ioctx.snap_create("snap1"));
+  char buf2[sizeof(buf)];
+  memset(buf2, 0xdd, sizeof(buf2));
+  bufferlist bl2;
+  bl2.append(buf2, sizeof(buf2));
+  EXPECT_EQ(0, ioctx.write_full("foo", bl2));
+  EXPECT_EQ(0, ioctx.rollback("foo", "snap1"));
+  bufferlist bl3;
+  EXPECT_EQ((int)sizeof(buf), ioctx.read("foo", bl3, sizeof(buf), 0));
+  EXPECT_EQ(0, memcmp(buf, bl3.c_str(), sizeof(buf)));
+  EXPECT_EQ(0, ioctx.snap_remove("snap1"));
+}
+
+TEST_F(LibRadosSnapshotsEC, SnapGetName) {
+  char buf[bufsize];
+  memset(buf, 0xcc, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), rados_write(ioctx, "foo", buf, sizeof(buf), 0));
+  ASSERT_EQ(0, rados_ioctx_snap_create(ioctx, "snapfoo"));
+  rados_snap_t rid;
+  EXPECT_EQ(0, rados_ioctx_snap_lookup(ioctx, "snapfoo", &rid));
+  EXPECT_EQ(-ENOENT, rados_ioctx_snap_lookup(ioctx, "snapbar", &rid));
+  char name[128];
+  memset(name, 0, sizeof(name));
+  EXPECT_EQ(0, rados_ioctx_snap_get_name(ioctx, rid, name, sizeof(name)));
+  time_t snaptime;
+  EXPECT_EQ(0, rados_ioctx_snap_get_stamp(ioctx, rid, &snaptime));
+  EXPECT_EQ(0, strcmp(name, "snapfoo"));
+  EXPECT_EQ(0, rados_ioctx_snap_remove(ioctx, "snapfoo"));
+}
+
+TEST_F(LibRadosSnapshotsECPP, SnapGetNamePP) {
+  char buf[bufsize];
+  memset(buf, 0xcc, sizeof(buf));
+  bufferlist bl;
+  bl.append(buf, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), ioctx.write("foo", bl, sizeof(buf), 0));
+  ASSERT_EQ(0, ioctx.snap_create("snapfoo"));
+  rados_snap_t rid;
+  EXPECT_EQ(0, ioctx.snap_lookup("snapfoo", &rid));
+  EXPECT_EQ(-ENOENT, ioctx.snap_lookup("snapbar", &rid));
+  std::string name;
+  EXPECT_EQ(0, ioctx.snap_get_name(rid, &name));
+  time_t snaptime;
+  EXPECT_EQ(0, ioctx.snap_get_stamp(rid, &snaptime));
+  EXPECT_EQ(0, strcmp(name.c_str(), "snapfoo"));
+  EXPECT_EQ(0, ioctx.snap_remove("snapfoo"));
+}
+
+TEST_F(LibRadosSnapshotsSelfManagedEC, Snap) {
+  std::vector<uint64_t> my_snaps;
+  my_snaps.push_back(-2);
+  ASSERT_EQ(0, rados_ioctx_selfmanaged_snap_create(ioctx, &my_snaps.back()));
+  ::std::reverse(my_snaps.begin(), my_snaps.end());
+  ASSERT_EQ(0, rados_ioctx_selfmanaged_snap_set_write_ctx(ioctx, my_snaps[0],
+					&my_snaps[0], my_snaps.size()));
+  ::std::reverse(my_snaps.begin(), my_snaps.end());
+  int bsize = alignment;
+  char *buf = (char *)new char[bsize];
+  memset(buf, 0xcc, bsize);
+  ASSERT_EQ(bsize, rados_write(ioctx, "foo", buf, bsize, 0));
+
+  my_snaps.push_back(-2);
+  ASSERT_EQ(0, rados_ioctx_selfmanaged_snap_create(ioctx, &my_snaps.back()));
+  ::std::reverse(my_snaps.begin(), my_snaps.end());
+  ASSERT_EQ(0, rados_ioctx_selfmanaged_snap_set_write_ctx(ioctx, my_snaps[0],
+					&my_snaps[0], my_snaps.size()));
+  ::std::reverse(my_snaps.begin(), my_snaps.end());
+  char *buf2 = (char *)new char[bsize];
+  memset(buf2, 0xdd, sizeof(buf2));
+  ASSERT_EQ(bsize, rados_write(ioctx, "foo", buf2, bsize, bsize));
+  rados_ioctx_snap_set_read(ioctx, my_snaps[1]-1);
+  char *buf3 = (char *)new char[bsize*2];
+  ASSERT_EQ(-ENOENT, rados_read(ioctx, "foo", buf3, bsize*2, 0));
+
+  rados_ioctx_snap_set_read(ioctx, my_snaps[1]);
+  ASSERT_EQ(bsize, rados_read(ioctx, "foo", buf3, bsize*2, 0));
+  ASSERT_EQ(0, memcmp(buf3, buf, bsize));
+
+  ASSERT_EQ(0, rados_ioctx_selfmanaged_snap_remove(ioctx, my_snaps.back()));
+  my_snaps.pop_back();
+  ASSERT_EQ(0, rados_ioctx_selfmanaged_snap_remove(ioctx, my_snaps.back()));
+  my_snaps.pop_back();
+  rados_ioctx_snap_set_read(ioctx, LIBRADOS_SNAP_HEAD);
+  ASSERT_EQ(0, rados_remove(ioctx, "foo"));
+  delete[] buf;
+  delete[] buf2;
+  delete[] buf3;
+}
+
+TEST_F(LibRadosSnapshotsSelfManagedEC, Rollback) {
+  std::vector<uint64_t> my_snaps;
+  my_snaps.push_back(-2);
+  ASSERT_EQ(0, rados_ioctx_selfmanaged_snap_create(ioctx, &my_snaps.back()));
+  ::std::reverse(my_snaps.begin(), my_snaps.end());
+  ASSERT_EQ(0, rados_ioctx_selfmanaged_snap_set_write_ctx(ioctx, my_snaps[0],
+					&my_snaps[0], my_snaps.size()));
+  ::std::reverse(my_snaps.begin(), my_snaps.end());
+  int bsize = alignment;
+  char *buf = (char *)new char[bsize];
+  memset(buf, 0xcc, sizeof(buf));
+  ASSERT_EQ(bsize, rados_write(ioctx, "foo", buf, bsize, 0));
+
+  my_snaps.push_back(-2);
+  ASSERT_EQ(0, rados_ioctx_selfmanaged_snap_create(ioctx, &my_snaps.back()));
+  ::std::reverse(my_snaps.begin(), my_snaps.end());
+  ASSERT_EQ(0, rados_ioctx_selfmanaged_snap_set_write_ctx(ioctx, my_snaps[0],
+					&my_snaps[0], my_snaps.size()));
+  ::std::reverse(my_snaps.begin(), my_snaps.end());
+  char *buf2 = (char *)new char[bsize];
+  memset(buf2, 0xdd, sizeof(buf2));
+
+  ASSERT_EQ(bsize, rados_write(ioctx, "foo", buf2, bsize, bsize));
+  rados_ioctx_selfmanaged_snap_rollback(ioctx, "foo", my_snaps[1]);
+  char *buf3 = (char *)new char[bsize*2];
+  ASSERT_EQ(bsize, rados_read(ioctx, "foo", buf3, bsize*2, 0));
+  ASSERT_EQ(0, memcmp(buf3, buf, bsize));
+
+  ASSERT_EQ(0, rados_ioctx_selfmanaged_snap_remove(ioctx, my_snaps.back()));
+  my_snaps.pop_back();
+  ASSERT_EQ(0, rados_ioctx_selfmanaged_snap_remove(ioctx, my_snaps.back()));
+  my_snaps.pop_back();
+  ASSERT_EQ(0, rados_remove(ioctx, "foo"));
+  delete[] buf;
+  delete[] buf2;
+  delete[] buf3;
+}
+
+TEST_F(LibRadosSnapshotsSelfManagedECPP, SnapPP) {
+  std::vector<uint64_t> my_snaps;
+  my_snaps.push_back(-2);
+  ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
+  ::std::reverse(my_snaps.begin(), my_snaps.end());
+  ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
+  ::std::reverse(my_snaps.begin(), my_snaps.end());
+  int bsize = alignment;
+  char *buf = (char *)new char[bsize];
+  memset(buf, 0xcc, sizeof(buf));
+  bufferlist bl1;
+  bl1.append(buf, bsize);
+  ASSERT_EQ(bsize, ioctx.write("foo", bl1, bsize, 0));
+
+  my_snaps.push_back(-2);
+  ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
+  ::std::reverse(my_snaps.begin(), my_snaps.end());
+  ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
+  ::std::reverse(my_snaps.begin(), my_snaps.end());
+  char *buf2 = (char *)new char[bsize];
+  memset(buf2, 0xdd, bsize);
+  bufferlist bl2;
+  bl2.append(buf2, bsize);
+  // Add another aligned buffer
+  ASSERT_EQ(bsize, ioctx.write("foo", bl2, bsize, bsize));
+
+  ioctx.snap_set_read(my_snaps[1]);
+  bufferlist bl3;
+  ASSERT_EQ(bsize, ioctx.read("foo", bl3, bsize*3, 0));
+  ASSERT_EQ(0, memcmp(bl3.c_str(), buf, bsize));
+
+  ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
+  my_snaps.pop_back();
+  ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
+  my_snaps.pop_back();
+  ioctx.snap_set_read(LIBRADOS_SNAP_HEAD);
+  ASSERT_EQ(0, ioctx.remove("foo"));
+  delete[] buf;
+  delete[] buf2;
+}
+
+TEST_F(LibRadosSnapshotsSelfManagedECPP, RollbackPP) {
+  std::vector<uint64_t> my_snaps;
+  IoCtx readioctx;
+  ASSERT_EQ(0, cluster.ioctx_create(pool_name.c_str(), readioctx));
+  readioctx.set_namespace(ns);
+  readioctx.snap_set_read(LIBRADOS_SNAP_DIR);
+
+  my_snaps.push_back(-2);
+  ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
+  ::std::reverse(my_snaps.begin(), my_snaps.end());
+  ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
+  ::std::reverse(my_snaps.begin(), my_snaps.end());
+  int bsize = alignment;
+  char *buf = (char *)new char[bsize];
+  memset(buf, 0xcc, bsize);
+  bufferlist bl1;
+  bl1.append(buf, bsize);
+  //Write 3 consecutive buffers
+  ASSERT_EQ(bsize, ioctx.write("foo", bl1, bsize, 0));
+  ASSERT_EQ(bsize, ioctx.write("foo", bl1, bsize, bsize));
+  ASSERT_EQ(bsize, ioctx.write("foo", bl1, bsize, bsize*2));
+
+  snap_set_t ss;
+
+  snap_t head = SNAP_HEAD;
+  ASSERT_EQ(0, readioctx.list_snaps("foo", &ss));
+  ASSERT_EQ(1u, ss.clones.size());
+  ASSERT_EQ(head, ss.clones[0].cloneid);
+  ASSERT_EQ(0u, ss.clones[0].snaps.size());
+  ASSERT_EQ(0u, ss.clones[0].overlap.size());
+  ASSERT_EQ((unsigned)(bsize*3), ss.clones[0].size);
+
+  my_snaps.push_back(-2);
+  ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps.back()));
+  ::std::reverse(my_snaps.begin(), my_snaps.end());
+  ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0], my_snaps));
+  ::std::reverse(my_snaps.begin(), my_snaps.end());
+  char *buf2 = (char *)new char[bsize];
+  memset(buf2, 0xdd, bsize);
+  bufferlist bl2;
+  bl2.append(buf2, bsize);
+  //Change the middle buffer
+  //ASSERT_EQ((int)sizeof(buf2), ioctx.write("foo", bl2, sizeof(buf2), bufsize));
+  //Add another after
+  ASSERT_EQ(bsize, ioctx.write("foo", bl2, bsize, bsize*3));
+
+  ASSERT_EQ(-EINVAL, ioctx.list_snaps("foo", &ss));
+  ObjectReadOperation o;
+  o.list_snaps(&ss, NULL);
+  ASSERT_EQ(-EINVAL, ioctx.operate("foo", &o, NULL));
+
+  ASSERT_EQ(0, readioctx.list_snaps("foo", &ss));
+  ASSERT_EQ(2u, ss.clones.size());
+  ASSERT_EQ(my_snaps[1], ss.clones[0].cloneid);
+  ASSERT_EQ(1u, ss.clones[0].snaps.size());
+  ASSERT_EQ(my_snaps[1], ss.clones[0].snaps[0]);
+  ASSERT_EQ(1u, ss.clones[0].overlap.size());
+  ASSERT_EQ(0u, ss.clones[0].overlap[0].first);
+  ASSERT_EQ((unsigned)bsize*3, ss.clones[0].overlap[0].second);
+  ASSERT_EQ((unsigned)bsize*3, ss.clones[0].size);
+  ASSERT_EQ(head, ss.clones[1].cloneid);
+  ASSERT_EQ(0u, ss.clones[1].snaps.size());
+  ASSERT_EQ(0u, ss.clones[1].overlap.size());
+  ASSERT_EQ((unsigned)bsize*4, ss.clones[1].size);
+
+  ioctx.selfmanaged_snap_rollback("foo", my_snaps[1]);
+
+  bufferlist bl3;
+  ASSERT_EQ(bsize, ioctx.read("foo", bl3, bsize, 0));
+  ASSERT_EQ(0, memcmp(bl3.c_str(), buf, bsize));
+  ASSERT_EQ(bsize, ioctx.read("foo", bl3, bsize, bsize));
+  ASSERT_EQ(0, memcmp(bl3.c_str(), buf, bsize));
+  ASSERT_EQ(bsize, ioctx.read("foo", bl3, bsize, bsize*2));
+  ASSERT_EQ(0, memcmp(bl3.c_str(), buf, bsize));
+  ASSERT_EQ(0, ioctx.read("foo", bl3, bsize, bsize*3));
+
+  ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
+  my_snaps.pop_back();
+  ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps.back()));
+  my_snaps.pop_back();
+  readioctx.close();
+
+  delete[] buf;
+  delete[] buf2;
+}
+
diff --git a/src/test/librados/stat.cc b/src/test/librados/stat.cc
index 47706dd..f15edd3 100644
--- a/src/test/librados/stat.cc
+++ b/src/test/librados/stat.cc
@@ -11,6 +11,8 @@ using namespace librados;
 
 typedef RadosTest LibRadosStat;
 typedef RadosTestPP LibRadosStatPP;
+typedef RadosTestEC LibRadosStatEC;
+typedef RadosTestECPP LibRadosStatECPP;
 
 TEST_F(LibRadosStat, Stat) {
   char buf[128];
@@ -127,3 +129,119 @@ TEST_F(LibRadosStatPP, PoolStatPP) {
   std::map<std::string,stats_map> stats;
   ASSERT_EQ(0, cluster.get_pool_stats(v, stats));
 }
+
+TEST_F(LibRadosStatEC, Stat) {
+  char buf[128];
+  memset(buf, 0xcc, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), rados_write(ioctx, "foo", buf, sizeof(buf), 0));
+  uint64_t size;
+  time_t mtime;
+  ASSERT_EQ(0, rados_stat(ioctx, "foo", &size, &mtime));
+  ASSERT_EQ(sizeof(buf), size);
+  ASSERT_EQ(-ENOENT, rados_stat(ioctx, "nonexistent", &size, &mtime));
+}
+
+TEST_F(LibRadosStatECPP, StatPP) {
+  char buf[128];
+  memset(buf, 0xcc, sizeof(buf));
+  bufferlist bl;
+  bl.append(buf, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), ioctx.write("foo", bl, sizeof(buf), 0));
+  uint64_t size;
+  time_t mtime;
+  ASSERT_EQ(0, ioctx.stat("foo", &size, &mtime));
+  ASSERT_EQ(sizeof(buf), size);
+  ASSERT_EQ(-ENOENT, ioctx.stat("nonexistent", &size, &mtime));
+}
+
+TEST_F(LibRadosStatEC, StatNS) {
+  char buf[128];
+  memset(buf, 0xcc, sizeof(buf));
+  rados_ioctx_set_namespace(ioctx, "");
+  ASSERT_EQ((int)sizeof(buf), rados_write(ioctx, "foo", buf, sizeof(buf), 0));
+  ASSERT_EQ((int)sizeof(buf), rados_write(ioctx, "foo2", buf, sizeof(buf), 0));
+
+  char buf2[64];
+  memset(buf2, 0xcc, sizeof(buf2));
+  rados_ioctx_set_namespace(ioctx, "nspace");
+  ASSERT_EQ((int)sizeof(buf2), rados_write(ioctx, "foo", buf2, sizeof(buf2), 0));
+
+  uint64_t size;
+  time_t mtime;
+  rados_ioctx_set_namespace(ioctx, "");
+  ASSERT_EQ(0, rados_stat(ioctx, "foo", &size, &mtime));
+  ASSERT_EQ(sizeof(buf), size);
+  ASSERT_EQ(-ENOENT, rados_stat(ioctx, "nonexistent", &size, &mtime));
+
+  rados_ioctx_set_namespace(ioctx, "nspace");
+  ASSERT_EQ(0, rados_stat(ioctx, "foo", &size, &mtime));
+  ASSERT_EQ(sizeof(buf2), size);
+  ASSERT_EQ(-ENOENT, rados_stat(ioctx, "nonexistent", &size, &mtime));
+  ASSERT_EQ(-ENOENT, rados_stat(ioctx, "foo2", &size, &mtime));
+}
+
+TEST_F(LibRadosStatECPP, StatPPNS) {
+  char buf[128];
+  memset(buf, 0xcc, sizeof(buf));
+  bufferlist bl;
+  bl.append(buf, sizeof(buf));
+  ioctx.set_namespace("");
+  ASSERT_EQ((int)sizeof(buf), ioctx.write("foo", bl, sizeof(buf), 0));
+  ASSERT_EQ((int)sizeof(buf), ioctx.write("foo2", bl, sizeof(buf), 0));
+
+  char buf2[64];
+  memset(buf2, 0xbb, sizeof(buf2));
+  bufferlist bl2;
+  bl2.append(buf2, sizeof(buf2));
+  ioctx.set_namespace("nspace");
+  ASSERT_EQ((int)sizeof(buf2), ioctx.write("foo", bl2, sizeof(buf2), 0));
+
+  uint64_t size;
+  time_t mtime;
+  ioctx.set_namespace("");
+  ASSERT_EQ(0, ioctx.stat("foo", &size, &mtime));
+  ASSERT_EQ(sizeof(buf), size);
+  ASSERT_EQ(-ENOENT, ioctx.stat("nonexistent", &size, &mtime));
+
+  ioctx.set_namespace("nspace");
+  ASSERT_EQ(0, ioctx.stat("foo", &size, &mtime));
+  ASSERT_EQ(sizeof(buf2), size);
+  ASSERT_EQ(-ENOENT, ioctx.stat("nonexistent", &size, &mtime));
+  ASSERT_EQ(-ENOENT, ioctx.stat("foo2", &size, &mtime));
+}
+
+TEST_F(LibRadosStatEC, ClusterStat) {
+  struct rados_cluster_stat_t result;
+  ASSERT_EQ(0, rados_cluster_stat(cluster, &result));
+}
+
+TEST_F(LibRadosStatECPP, ClusterStatPP) {
+  cluster_stat_t cstat;
+  ASSERT_EQ(0, cluster.cluster_stat(cstat));
+}
+
+TEST_F(LibRadosStatEC, PoolStat) {
+  char buf[128];
+  char actual_pool_name[80];
+  unsigned l = rados_ioctx_get_pool_name(ioctx, actual_pool_name, sizeof(actual_pool_name));
+  ASSERT_EQ(strlen(actual_pool_name), l);
+  ASSERT_EQ(0, strcmp(actual_pool_name, pool_name.c_str()));
+  memset(buf, 0xff, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), rados_write(ioctx, "foo", buf, sizeof(buf), 0));
+  struct rados_pool_stat_t stats;
+  memset(&stats, 0, sizeof(stats));
+  ASSERT_EQ(0, rados_ioctx_pool_stat(ioctx, &stats));
+}
+
+TEST_F(LibRadosStatECPP, PoolStatPP) {
+  std::string n = ioctx.get_pool_name();
+  ASSERT_EQ(n, pool_name);
+  char buf[128];
+  memset(buf, 0xff, sizeof(buf));
+  bufferlist bl1;
+  bl1.append(buf, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), ioctx.write("foo", bl1, sizeof(buf), 0));
+  std::list<std::string> v;
+  std::map<std::string,stats_map> stats;
+  ASSERT_EQ(0, cluster.get_pool_stats(v, stats));
+}
diff --git a/src/test/librados/test.cc b/src/test/librados/test.cc
index 83f11b0..f8a92a2 100644
--- a/src/test/librados/test.cc
+++ b/src/test/librados/test.cc
@@ -43,6 +43,46 @@ std::string create_one_pool(const std::string &pool_name, rados_t *cluster)
   return "";
 }
 
+std::string create_one_ec_pool(const std::string &pool_name, rados_t *cluster)
+{
+  std::string err = connect_cluster(cluster);
+  if (err.length())
+    return err;
+
+  char *cmd[2];
+
+  cmd[1] = NULL;
+
+  cmd[0] = (char *)"{\"prefix\": \"osd erasure-code-profile set\", \"name\": \"testprofile\", \"profile\": [ \"k=2\", \"m=1\", \"ruleset-failure-domain=osd\"]}";
+  int ret = rados_mon_command(*cluster, (const char **)cmd, 1, "", 0, NULL, NULL, NULL, NULL);
+  if (ret) {
+    rados_shutdown(*cluster);
+    std::ostringstream oss;
+    oss << "rados_mon_command erasure-code-profile set name:testprofile failed with error " << ret;
+    return oss.str();
+  }
+    
+  std::string cmdstr = "{\"prefix\": \"osd pool create\", \"pool\": \"" +
+     pool_name + "\", \"pool_type\":\"erasure\", \"pg_num\":8, \"pgp_num\":8, \"erasure_code_profile\":\"testprofile\"}";
+  cmd[0] = (char *)cmdstr.c_str();
+  ret = rados_mon_command(*cluster, (const char **)cmd, 1, "", 0, NULL, 0, NULL, 0);
+  if (ret) {
+    std::ostringstream oss;
+
+    cmd[0] = (char *)"{\"prefix\": \"osd erasure-code-profile rm\", \"name\": \"testprofile\"}";
+    int ret2 = rados_mon_command(*cluster, (const char **)cmd, 1, "", 0, NULL, 0, NULL, 0);
+    if (ret2)
+      oss << "rados_mon_command osd erasure-code-profile rm name:testprofile failed with error " << ret2 << std::endl;
+
+    rados_shutdown(*cluster);
+    oss << "rados_mon_command erasure-code-profile set name:testprofile failed with error " << ret;
+    return oss.str();
+  }
+
+  rados_wait_for_latest_osdmap(*cluster);
+  return "";
+}
+
 std::string create_one_pool_pp(const std::string &pool_name, Rados &cluster)
 {
   std::string err = connect_cluster_pp(cluster);
@@ -58,6 +98,44 @@ std::string create_one_pool_pp(const std::string &pool_name, Rados &cluster)
   return "";
 }
 
+std::string create_one_ec_pool_pp(const std::string &pool_name, Rados &cluster)
+{
+  std::string err = connect_cluster_pp(cluster);
+  if (err.length())
+    return err;
+
+  bufferlist inbl;
+  int ret = cluster.mon_command(
+    "{\"prefix\": \"osd erasure-code-profile set\", \"name\": \"testprofile\", \"profile\": [ \"k=2\", \"m=1\", \"ruleset-failure-domain=osd\"]}",
+    inbl, NULL, NULL);
+  if (ret) {
+    cluster.shutdown();
+    std::ostringstream oss;
+    oss << "mon_command erasure-code-profile set name:testprofile failed with error " << ret;
+    return oss.str();
+  }
+    
+  ret = cluster.mon_command(
+    "{\"prefix\": \"osd pool create\", \"pool\": \"" + pool_name + "\", \"pool_type\":\"erasure\", \"pg_num\":8, \"pgp_num\":8, \"erasure_code_profile\":\"testprofile\"}",
+    inbl, NULL, NULL);
+  if (ret) {
+    std::ostringstream oss;
+    bufferlist inbl;
+    int ret2 = cluster.mon_command(
+      "{\"prefix\": \"osd erasure-code-profile rm\", \"name\": \"testprofile\"}",
+      inbl, NULL, NULL);
+    if (ret2)
+      oss << "mon_command osd erasure-code-profile rm name:testprofile failed with error " << ret2 << std::endl;
+
+    cluster.shutdown();
+    oss << "mon_command osd pool create pool:" << pool_name << " pool_type:erasure failed with error " << ret;
+    return oss.str();
+  }
+
+  cluster.wait_for_latest_osdmap();
+  return "";
+}
+
 std::string connect_cluster(rados_t *cluster)
 {
   char *id = getenv("CEPH_CLIENT_ID");
@@ -129,6 +207,26 @@ int destroy_one_pool(const std::string &pool_name, rados_t *cluster)
   return 0;
 }
 
+int destroy_one_ec_pool(const std::string &pool_name, rados_t *cluster)
+{
+  int ret = rados_pool_delete(*cluster, pool_name.c_str());
+  if (ret == 0) {
+    char *cmd[2];
+
+    cmd[1] = NULL;
+
+    cmd[0] = (char *)"{\"prefix\": \"osd erasure-code-profile rm\", \"name\": \"testprofile\"}";
+    int ret2 = rados_mon_command(*cluster, (const char **)cmd, 1, "", 0, NULL, 0, NULL, 0);
+    if (ret2) {
+      rados_shutdown(*cluster);
+      return ret2;
+    }
+    rados_wait_for_latest_osdmap(*cluster);
+  }
+  rados_shutdown(*cluster);
+  return ret;
+}
+
 int destroy_one_pool_pp(const std::string &pool_name, Rados &cluster)
 {
   int ret = cluster.pool_delete(pool_name.c_str());
@@ -139,3 +237,21 @@ int destroy_one_pool_pp(const std::string &pool_name, Rados &cluster)
   cluster.shutdown();
   return 0;
 }
+
+int destroy_one_ec_pool_pp(const std::string &pool_name, Rados &cluster)
+{
+  int ret = cluster.pool_delete(pool_name.c_str());
+  bufferlist inbl;
+  if (ret == 0) {
+    int ret2 = cluster.mon_command(
+      "{\"prefix\": \"osd erasure-code-profile rm\", \"name\": \"testprofile\"}",
+      inbl, NULL, NULL);
+    if (ret2) {
+      cluster.shutdown();
+      return ret2;
+    }
+    cluster.wait_for_latest_osdmap();
+  }
+  cluster.shutdown();
+  return ret;
+}
diff --git a/src/test/librados/test.h b/src/test/librados/test.h
index 652c235..6cf522d 100644
--- a/src/test/librados/test.h
+++ b/src/test/librados/test.h
@@ -24,12 +24,17 @@
 std::string get_temp_pool_name();
 
 std::string create_one_pool(const std::string &pool_name, rados_t *cluster);
+std::string create_one_ec_pool(const std::string &pool_name, rados_t *cluster);
 std::string create_one_pool_pp(const std::string &pool_name,
 			    librados::Rados &cluster);
+std::string create_one_ec_pool_pp(const std::string &pool_name,
+			    librados::Rados &cluster);
 std::string connect_cluster(rados_t *cluster);
 std::string connect_cluster_pp(librados::Rados &cluster);
 int destroy_one_pool(const std::string &pool_name, rados_t *cluster);
+int destroy_one_ec_pool(const std::string &pool_name, rados_t *cluster);
 int destroy_one_pool_pp(const std::string &pool_name, librados::Rados &cluster);
+int destroy_one_ec_pool_pp(const std::string &pool_name, librados::Rados &cluster);
 
 class TestAlarm
 {
diff --git a/src/test/librados/tier.cc b/src/test/librados/tier.cc
index 1ff3d2e..1543cbd 100644
--- a/src/test/librados/tier.cc
+++ b/src/test/librados/tier.cc
@@ -32,6 +32,7 @@ using std::ostringstream;
 using std::string;
 
 typedef RadosTestPP LibRadosTierPP;
+typedef RadosTestECPP LibRadosTierECPP;
 
 class LibRadosTwoPoolsPP : public RadosTestPP
 {
@@ -189,6 +190,9 @@ TEST_F(LibRadosTwoPoolsPP, Overlay) {
     "{\"prefix\": \"osd tier remove\", \"pool\": \"" + pool_name +
     "\", \"tierpool\": \"" + cache_pool_name + "\"}",
     inbl, NULL, NULL));
+
+  // wait for maps to settle before next test
+  cluster.wait_for_latest_osdmap();
 }
 
 TEST_F(LibRadosTwoPoolsPP, Promote) {
@@ -253,6 +257,9 @@ TEST_F(LibRadosTwoPoolsPP, Promote) {
     "{\"prefix\": \"osd tier remove\", \"pool\": \"" + pool_name +
     "\", \"tierpool\": \"" + cache_pool_name + "\"}",
     inbl, NULL, NULL));
+
+  // wait for maps to settle before next test
+  cluster.wait_for_latest_osdmap();
 }
 
 TEST_F(LibRadosTwoPoolsPP, PromoteSnap) {
@@ -403,8 +410,121 @@ TEST_F(LibRadosTwoPoolsPP, PromoteSnap) {
     "{\"prefix\": \"osd tier remove\", \"pool\": \"" + pool_name +
     "\", \"tierpool\": \"" + cache_pool_name + "\"}",
     inbl, NULL, NULL));
+
+  // wait for maps to settle before next test
+  cluster.wait_for_latest_osdmap();
+}
+
+TEST_F(LibRadosTwoPoolsPP, PromoteSnapScrub) {
+  int num = 100;
+
+  // create objects
+  for (int i=0; i<num; ++i) {
+    bufferlist bl;
+    bl.append("hi there");
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, ioctx.operate(string("foo") + stringify(i), &op));
+  }
+
+  vector<uint64_t> my_snaps;
+  for (int snap=0; snap<4; ++snap) {
+    // create a snapshot, clone
+    vector<uint64_t> ns(1);
+    ns.insert(ns.end(), my_snaps.begin(), my_snaps.end());
+    my_snaps.swap(ns);
+    ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps[0]));
+    cout << "my_snaps " << my_snaps << std::endl;
+    ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0],
+						      my_snaps));
+    for (int i=0; i<num; ++i) {
+      bufferlist bl;
+      bl.append(string("ciao! snap") + stringify(snap));
+      ObjectWriteOperation op;
+      op.write_full(bl);
+      ASSERT_EQ(0, ioctx.operate(string("foo") + stringify(i), &op));
+    }
+  }
+
+  // configure cache
+  bufferlist inbl;
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier add\", \"pool\": \"" + pool_name +
+    "\", \"tierpool\": \"" + cache_pool_name +
+    "\", \"force_nonempty\": \"--force-nonempty\" }",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier set-overlay\", \"pool\": \"" + pool_name +
+    "\", \"overlaypool\": \"" + cache_pool_name + "\"}",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier cache-mode\", \"pool\": \"" + cache_pool_name +
+    "\", \"mode\": \"writeback\"}",
+    inbl, NULL, NULL));
+
+  // wait for maps to settle
+  cluster.wait_for_latest_osdmap();
+
+  // read, trigger a promote on _some_ heads to make sure we handle cases
+  // where snaps are present and where they are not.
+  cout << "promoting some heads" << std::endl;
+  for (int i=0; i<num; ++i) {
+    if (i % 5 == 0 || i > num - 3) {
+      bufferlist bl;
+      ASSERT_EQ(1, ioctx.read(string("foo") + stringify(i), bl, 1, 0));
+      ASSERT_EQ('c', bl[0]);
+    }
+  }
+
+  for (unsigned snap = 0; snap < my_snaps.size(); ++snap) {
+    cout << "promoting from clones for snap " << my_snaps[snap] << std::endl;
+    ioctx.snap_set_read(my_snaps[snap]);
+
+    // read some snaps, semi-randomly
+    for (int i=0; i<50; ++i) {
+      bufferlist bl;
+      string o = string("foo") + stringify((snap * i * 137) % 80);
+      //cout << o << std::endl;
+      ASSERT_EQ(1, ioctx.read(o, bl, 1, 0));
+    }
+  }
+
+  // ok, stop and scrub this pool (to make sure scrub can handle
+  // missing clones in the cache tier).
+  {
+    IoCtx cache_ioctx;
+    ASSERT_EQ(0, cluster.ioctx_create(cache_pool_name.c_str(), cache_ioctx));
+    for (int i=0; i<10; ++i) {
+      ostringstream ss;
+      ss << "{\"prefix\": \"pg scrub\", \"pgid\": \""
+	 << cache_ioctx.get_id() << "." << i
+	 << "\"}";
+      cluster.mon_command(ss.str(), inbl, NULL, NULL);
+    }
+
+    // give it a few seconds to go.  this is sloppy but is usually enough time
+    cout << "waiting for scrubs..." << std::endl;
+    sleep(30);
+    cout << "done waiting" << std::endl;
+  }
+
+  ioctx.snap_set_read(librados::SNAP_HEAD);
+
+  // tear down tiers
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier remove-overlay\", \"pool\": \"" + pool_name +
+    "\"}",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier remove\", \"pool\": \"" + pool_name +
+    "\", \"tierpool\": \"" + cache_pool_name + "\"}",
+    inbl, NULL, NULL));
+
+  // wait for maps to settle before next test
+  cluster.wait_for_latest_osdmap();
 }
 
+
 TEST_F(LibRadosTwoPoolsPP, PromoteSnapTrimRace) {
   // create object
   {
@@ -467,6 +587,9 @@ TEST_F(LibRadosTwoPoolsPP, PromoteSnapTrimRace) {
     "{\"prefix\": \"osd tier remove\", \"pool\": \"" + pool_name +
     "\", \"tierpool\": \"" + cache_pool_name + "\"}",
     inbl, NULL, NULL));
+
+  // wait for maps to settle before next test
+  cluster.wait_for_latest_osdmap();
 }
 
 TEST_F(LibRadosTwoPoolsPP, Whiteout) {
@@ -540,6 +663,9 @@ TEST_F(LibRadosTwoPoolsPP, Whiteout) {
     "{\"prefix\": \"osd tier remove\", \"pool\": \"" + pool_name +
     "\", \"tierpool\": \"" + cache_pool_name + "\"}",
     inbl, NULL, NULL));
+
+  // wait for maps to settle before next test
+  cluster.wait_for_latest_osdmap();
 }
 
 TEST_F(LibRadosTwoPoolsPP, Evict) {
@@ -640,6 +766,9 @@ TEST_F(LibRadosTwoPoolsPP, Evict) {
     "{\"prefix\": \"osd tier remove\", \"pool\": \"" + pool_name +
     "\", \"tierpool\": \"" + cache_pool_name + "\"}",
     inbl, NULL, NULL));
+
+  // wait for maps to settle before next test
+  cluster.wait_for_latest_osdmap();
 }
 
 TEST_F(LibRadosTwoPoolsPP, EvictSnap) {
@@ -885,6 +1014,9 @@ TEST_F(LibRadosTwoPoolsPP, EvictSnap) {
     "{\"prefix\": \"osd tier remove\", \"pool\": \"" + pool_name +
     "\", \"tierpool\": \"" + cache_pool_name + "\"}",
     inbl, NULL, NULL));
+
+  // wait for maps to settle before next test
+  cluster.wait_for_latest_osdmap();
 }
 
 TEST_F(LibRadosTwoPoolsPP, TryFlush) {
@@ -1003,6 +1135,9 @@ TEST_F(LibRadosTwoPoolsPP, TryFlush) {
     "{\"prefix\": \"osd tier remove\", \"pool\": \"" + pool_name +
     "\", \"tierpool\": \"" + cache_pool_name + "\"}",
     inbl, NULL, NULL));
+
+  // wait for maps to settle before next test
+  cluster.wait_for_latest_osdmap();
 }
 
 TEST_F(LibRadosTwoPoolsPP, Flush) {
@@ -1173,6 +1308,9 @@ TEST_F(LibRadosTwoPoolsPP, Flush) {
     "{\"prefix\": \"osd tier remove\", \"pool\": \"" + pool_name +
     "\", \"tierpool\": \"" + cache_pool_name + "\"}",
     inbl, NULL, NULL));
+
+  // wait for maps to settle before next test
+  cluster.wait_for_latest_osdmap();
 }
 
 TEST_F(LibRadosTwoPoolsPP, FlushSnap) {
@@ -1476,6 +1614,12 @@ TEST_F(LibRadosTierPP, FlushWriteRaces) {
     "{\"prefix\": \"osd tier remove\", \"pool\": \"" + pool_name +
     "\", \"tierpool\": \"" + cache_pool_name + "\"}",
     inbl, NULL, NULL));
+
+  // wait for maps to settle before next test
+  cluster.wait_for_latest_osdmap();
+
+  ASSERT_EQ(0, cluster.pool_delete(cache_pool_name.c_str()));
+  ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
 }
 
 TEST_F(LibRadosTwoPoolsPP, FlushTryFlushRaces) {
@@ -1652,6 +1796,9 @@ TEST_F(LibRadosTwoPoolsPP, FlushTryFlushRaces) {
     "{\"prefix\": \"osd tier remove\", \"pool\": \"" + pool_name +
     "\", \"tierpool\": \"" + cache_pool_name + "\"}",
     inbl, NULL, NULL));
+
+  // wait for maps to settle before next test
+  cluster.wait_for_latest_osdmap();
 }
 
 
@@ -1758,6 +1905,9 @@ TEST_F(LibRadosTwoPoolsPP, TryFlushReadRace) {
     "{\"prefix\": \"osd tier remove\", \"pool\": \"" + pool_name +
     "\", \"tierpool\": \"" + cache_pool_name + "\"}",
     inbl, NULL, NULL));
+
+  // wait for maps to settle before next test
+  cluster.wait_for_latest_osdmap();
 }
 
 TEST_F(LibRadosTierPP, HitSetNone) {
@@ -2012,6 +2162,1970 @@ TEST_F(LibRadosTierPP, HitSetTrim) {
   }
 }
 
+class LibRadosTwoPoolsECPP : public RadosTestECPP
+{
+public:
+  LibRadosTwoPoolsECPP() {};
+  virtual ~LibRadosTwoPoolsECPP() {};
+protected:
+  static void SetUpTestCase() {
+    pool_name = get_temp_pool_name();
+    ASSERT_EQ("", create_one_ec_pool_pp(pool_name, s_cluster));
+    cache_pool_name = get_temp_pool_name();
+    ASSERT_EQ(0, s_cluster.pool_create(cache_pool_name.c_str()));
+  }
+  static void TearDownTestCase() {
+    ASSERT_EQ(0, s_cluster.pool_delete(cache_pool_name.c_str()));
+    ASSERT_EQ(0, destroy_one_ec_pool_pp(pool_name, s_cluster));
+  }
+  static std::string cache_pool_name;
+
+  virtual void SetUp() {
+    RadosTestECPP::SetUp();
+    ASSERT_EQ(0, cluster.ioctx_create(cache_pool_name.c_str(), cache_ioctx));
+    cache_ioctx.set_namespace(ns);
+  }
+  virtual void TearDown() {
+    RadosTestECPP::TearDown();
+    cleanup_default_namespace(cache_ioctx);
+    cache_ioctx.close();
+  }
+  librados::IoCtx cache_ioctx;
+};
+
+std::string LibRadosTwoPoolsECPP::cache_pool_name;
+
+TEST_F(LibRadosTierECPP, Dirty) {
+  {
+    ObjectWriteOperation op;
+    op.undirty();
+    ASSERT_EQ(0, ioctx.operate("foo", &op)); // still get 0 if it dne
+  }
+  {
+    ObjectWriteOperation op;
+    op.create(true);
+    ASSERT_EQ(0, ioctx.operate("foo", &op));
+  }
+  {
+    bool dirty = false;
+    int r = -1;
+    ObjectReadOperation op;
+    op.is_dirty(&dirty, &r);
+    ASSERT_EQ(0, ioctx.operate("foo", &op, NULL));
+    ASSERT_TRUE(dirty);
+    ASSERT_EQ(0, r);
+  }
+  {
+    ObjectWriteOperation op;
+    op.undirty();
+    ASSERT_EQ(0, ioctx.operate("foo", &op));
+  }
+  {
+    ObjectWriteOperation op;
+    op.undirty();
+    ASSERT_EQ(0, ioctx.operate("foo", &op));  // still 0 if already clean
+  }
+  {
+    bool dirty = false;
+    int r = -1;
+    ObjectReadOperation op;
+    op.is_dirty(&dirty, &r);
+    ASSERT_EQ(0, ioctx.operate("foo", &op, NULL));
+    ASSERT_FALSE(dirty);
+    ASSERT_EQ(0, r);
+  }
+  //{
+  //  ObjectWriteOperation op;
+  //  op.truncate(0);  // still a write even tho it is a no-op
+  //  ASSERT_EQ(0, ioctx.operate("foo", &op));
+  //}
+  //{
+  //  bool dirty = false;
+  //  int r = -1;
+  //  ObjectReadOperation op;
+  //  op.is_dirty(&dirty, &r);
+  //  ASSERT_EQ(0, ioctx.operate("foo", &op, NULL));
+  //  ASSERT_TRUE(dirty);
+  //  ASSERT_EQ(0, r);
+  //}
+}
+
+TEST_F(LibRadosTwoPoolsECPP, Overlay) {
+  // create objects
+  {
+    bufferlist bl;
+    bl.append("base");
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, ioctx.operate("foo", &op));
+  }
+  {
+    bufferlist bl;
+    bl.append("cache");
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, cache_ioctx.operate("foo", &op));
+  }
+
+  // configure cache
+  bufferlist inbl;
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier add\", \"pool\": \"" + pool_name +
+    "\", \"tierpool\": \"" + cache_pool_name +
+    "\", \"force_nonempty\": \"--force-nonempty\" }",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier set-overlay\", \"pool\": \"" + pool_name +
+    "\", \"overlaypool\": \"" + cache_pool_name + "\"}",
+    inbl, NULL, NULL));
+
+  // wait for maps to settle
+  cluster.wait_for_latest_osdmap();
+
+  // by default, the overlay sends us to cache pool
+  {
+    bufferlist bl;
+    ASSERT_EQ(1, ioctx.read("foo", bl, 1, 0));
+    ASSERT_EQ('c', bl[0]);
+  }
+  {
+    bufferlist bl;
+    ASSERT_EQ(1, cache_ioctx.read("foo", bl, 1, 0));
+    ASSERT_EQ('c', bl[0]);
+  }
+
+  // unless we say otherwise
+  {
+    bufferlist bl;
+    ObjectReadOperation op;
+    op.read(0, 1, &bl, NULL);
+    librados::AioCompletion *completion = cluster.aio_create_completion();
+    ASSERT_EQ(0, ioctx.aio_operate(
+	"foo", completion, &op,
+	librados::OPERATION_IGNORE_OVERLAY, NULL));
+    completion->wait_for_safe();
+    ASSERT_EQ(0, completion->get_return_value());
+    completion->release();
+    ASSERT_EQ('b', bl[0]);
+  }
+
+  // tear down tiers
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier remove-overlay\", \"pool\": \"" + pool_name +
+    "\"}",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier remove\", \"pool\": \"" + pool_name +
+    "\", \"tierpool\": \"" + cache_pool_name + "\"}",
+    inbl, NULL, NULL));
+
+  // wait for maps to settle before next test
+  cluster.wait_for_latest_osdmap();
+}
+
+TEST_F(LibRadosTwoPoolsECPP, Promote) {
+  // create object
+  {
+    bufferlist bl;
+    bl.append("hi there");
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, ioctx.operate("foo", &op));
+  }
+
+  // configure cache
+  bufferlist inbl;
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier add\", \"pool\": \"" + pool_name +
+    "\", \"tierpool\": \"" + cache_pool_name +
+    "\", \"force_nonempty\": \"--force-nonempty\" }",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier set-overlay\", \"pool\": \"" + pool_name +
+    "\", \"overlaypool\": \"" + cache_pool_name + "\"}",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier cache-mode\", \"pool\": \"" + cache_pool_name +
+    "\", \"mode\": \"writeback\"}",
+    inbl, NULL, NULL));
+
+  // wait for maps to settle
+  cluster.wait_for_latest_osdmap();
+
+  // read, trigger a promote
+  {
+    bufferlist bl;
+    ASSERT_EQ(1, ioctx.read("foo", bl, 1, 0));
+  }
+
+  // read, trigger a whiteout
+  {
+    bufferlist bl;
+    ASSERT_EQ(-ENOENT, ioctx.read("bar", bl, 1, 0));
+    ASSERT_EQ(-ENOENT, ioctx.read("bar", bl, 1, 0));
+  }
+
+  // verify the object is present in the cache tier
+  {
+    ObjectIterator it = cache_ioctx.objects_begin();
+    ASSERT_TRUE(it != cache_ioctx.objects_end());
+    ASSERT_TRUE(it->first == string("foo") || it->first == string("bar"));
+    ++it;
+    ASSERT_TRUE(it->first == string("foo") || it->first == string("bar"));
+    ++it;
+    ASSERT_TRUE(it == cache_ioctx.objects_end());
+  }
+
+  // tear down tiers
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier remove-overlay\", \"pool\": \"" + pool_name +
+    "\"}",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier remove\", \"pool\": \"" + pool_name +
+    "\", \"tierpool\": \"" + cache_pool_name + "\"}",
+    inbl, NULL, NULL));
+
+  // wait for maps to settle before next test
+  cluster.wait_for_latest_osdmap();
+}
+
+TEST_F(LibRadosTwoPoolsECPP, PromoteSnap) {
+  // create object
+  {
+    bufferlist bl;
+    bl.append("hi there");
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, ioctx.operate("foo", &op));
+  }
+  {
+    bufferlist bl;
+    bl.append("hi there");
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, ioctx.operate("bar", &op));
+  }
+  {
+    bufferlist bl;
+    bl.append("hi there");
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, ioctx.operate("baz", &op));
+  }
+  {
+    bufferlist bl;
+    bl.append("hi there");
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, ioctx.operate("bam", &op));
+  }
+
+  // create a snapshot, clone
+  vector<uint64_t> my_snaps(1);
+  ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps[0]));
+  ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0],
+							 my_snaps));
+  {
+    bufferlist bl;
+    bl.append("ciao!");
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, ioctx.operate("foo", &op));
+  }
+  {
+    bufferlist bl;
+    bl.append("ciao!");
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, ioctx.operate("bar", &op));
+  }
+  {
+    ObjectWriteOperation op;
+    op.remove();
+    ASSERT_EQ(0, ioctx.operate("baz", &op));
+  }
+  {
+    bufferlist bl;
+    bl.append("ciao!");
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, ioctx.operate("bam", &op));
+  }
+
+  // configure cache
+  bufferlist inbl;
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier add\", \"pool\": \"" + pool_name +
+    "\", \"tierpool\": \"" + cache_pool_name +
+    "\", \"force_nonempty\": \"--force-nonempty\" }",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier set-overlay\", \"pool\": \"" + pool_name +
+    "\", \"overlaypool\": \"" + cache_pool_name + "\"}",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier cache-mode\", \"pool\": \"" + cache_pool_name +
+    "\", \"mode\": \"writeback\"}",
+    inbl, NULL, NULL));
+
+  // wait for maps to settle
+  cluster.wait_for_latest_osdmap();
+
+  // read, trigger a promote on the head
+  {
+    bufferlist bl;
+    ASSERT_EQ(1, ioctx.read("foo", bl, 1, 0));
+    ASSERT_EQ('c', bl[0]);
+  }
+  {
+    bufferlist bl;
+    ASSERT_EQ(1, ioctx.read("bam", bl, 1, 0));
+    ASSERT_EQ('c', bl[0]);
+  }
+
+  ioctx.snap_set_read(my_snaps[0]);
+
+  // stop and scrub this pg (to make sure scrub can handle missing
+  // clones in the cache tier)
+  // This test requires cache tier and base tier to have the same pg_num/pgp_num
+  {
+    IoCtx cache_ioctx;
+    ASSERT_EQ(0, cluster.ioctx_create(cache_pool_name.c_str(), cache_ioctx));
+    ostringstream ss;
+    ss << "{\"prefix\": \"pg scrub\", \"pgid\": \""
+       << cache_ioctx.get_id() << "."
+       << ioctx.get_object_pg_hash_position("foo")
+       << "\"}";
+    ASSERT_EQ(0, cluster.mon_command(ss.str(), inbl, NULL, NULL));
+
+    // give it a few seconds to go.  this is sloppy but is usually enough time
+    cout << "waiting for scrub..." << std::endl;
+    sleep(15);
+    cout << "done waiting" << std::endl;
+  }
+
+  // read foo snap
+  {
+    bufferlist bl;
+    ASSERT_EQ(1, ioctx.read("foo", bl, 1, 0));
+    ASSERT_EQ('h', bl[0]);
+  }
+
+  // read bar snap
+  {
+    bufferlist bl;
+    ASSERT_EQ(1, ioctx.read("bar", bl, 1, 0));
+    ASSERT_EQ('h', bl[0]);
+  }
+
+  // read baz snap
+  {
+    bufferlist bl;
+    ASSERT_EQ(1, ioctx.read("baz", bl, 1, 0));
+    ASSERT_EQ('h', bl[0]);
+  }
+
+  ioctx.snap_set_read(librados::SNAP_HEAD);
+
+  // read foo
+  {
+    bufferlist bl;
+    ASSERT_EQ(1, ioctx.read("foo", bl, 1, 0));
+    ASSERT_EQ('c', bl[0]);
+  }
+
+  // read bar
+  {
+    bufferlist bl;
+    ASSERT_EQ(1, ioctx.read("bar", bl, 1, 0));
+    ASSERT_EQ('c', bl[0]);
+  }
+
+  // read baz
+  {
+    bufferlist bl;
+    ASSERT_EQ(-ENOENT, ioctx.read("baz", bl, 1, 0));
+  }
+
+  // tear down tiers
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier remove-overlay\", \"pool\": \"" + pool_name +
+    "\"}",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier remove\", \"pool\": \"" + pool_name +
+    "\", \"tierpool\": \"" + cache_pool_name + "\"}",
+    inbl, NULL, NULL));
+
+  // wait for maps to settle before next test
+  cluster.wait_for_latest_osdmap();
+}
+
+TEST_F(LibRadosTwoPoolsECPP, PromoteSnapTrimRace) {
+  // create object
+  {
+    bufferlist bl;
+    bl.append("hi there");
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, ioctx.operate("foo", &op));
+  }
+
+  // create a snapshot, clone
+  vector<uint64_t> my_snaps(1);
+  ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps[0]));
+  ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0],
+							 my_snaps));
+  {
+    bufferlist bl;
+    bl.append("ciao!");
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, ioctx.operate("foo", &op));
+  }
+
+  // configure cache
+  bufferlist inbl;
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier add\", \"pool\": \"" + pool_name +
+    "\", \"tierpool\": \"" + cache_pool_name +
+    "\", \"force_nonempty\": \"--force-nonempty\" }",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier set-overlay\", \"pool\": \"" + pool_name +
+    "\", \"overlaypool\": \"" + cache_pool_name + "\"}",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier cache-mode\", \"pool\": \"" + cache_pool_name +
+    "\", \"mode\": \"writeback\"}",
+    inbl, NULL, NULL));
+
+  // wait for maps to settle
+  cluster.wait_for_latest_osdmap();
+
+  // delete the snap
+  ASSERT_EQ(0, ioctx.selfmanaged_snap_remove(my_snaps[0]));
+
+  ioctx.snap_set_read(my_snaps[0]);
+
+  // read foo snap
+  {
+    bufferlist bl;
+    ASSERT_EQ(-ENOENT, ioctx.read("foo", bl, 1, 0));
+  }
+
+  // tear down tiers
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier remove-overlay\", \"pool\": \"" + pool_name +
+    "\"}",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier remove\", \"pool\": \"" + pool_name +
+    "\", \"tierpool\": \"" + cache_pool_name + "\"}",
+    inbl, NULL, NULL));
+
+  // wait for maps to settle before next test
+  cluster.wait_for_latest_osdmap();
+}
+
+TEST_F(LibRadosTwoPoolsECPP, Whiteout) {
+  // create object
+  {
+    bufferlist bl;
+    bl.append("hi there");
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, ioctx.operate("foo", &op));
+  }
+
+  // configure cache
+  bufferlist inbl;
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier add\", \"pool\": \"" + pool_name +
+    "\", \"tierpool\": \"" + cache_pool_name +
+    "\", \"force_nonempty\": \"--force-nonempty\" }",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier set-overlay\", \"pool\": \"" + pool_name +
+    "\", \"overlaypool\": \"" + cache_pool_name + "\"}",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier cache-mode\", \"pool\": \"" + cache_pool_name +
+    "\", \"mode\": \"writeback\"}",
+    inbl, NULL, NULL));
+
+  // wait for maps to settle
+  cluster.wait_for_latest_osdmap();
+
+  // create some whiteouts, verify they behave
+  ASSERT_EQ(0, ioctx.remove("foo"));
+
+  ASSERT_EQ(-ENOENT, ioctx.remove("bar"));
+  ASSERT_EQ(-ENOENT, ioctx.remove("bar"));
+
+  // verify the whiteouts are there in the cache tier
+  {
+    ObjectIterator it = cache_ioctx.objects_begin();
+    ASSERT_TRUE(it != cache_ioctx.objects_end());
+    ASSERT_TRUE(it->first == string("foo") || it->first == string("bar"));
+    ++it;
+    ASSERT_TRUE(it->first == string("foo") || it->first == string("bar"));
+    ++it;
+    ASSERT_TRUE(it == cache_ioctx.objects_end());
+  }
+
+  ASSERT_EQ(-ENOENT, ioctx.remove("foo"));
+
+  // recreate an object and verify we can read it
+  {
+    bufferlist bl;
+    bl.append("hi there");
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, ioctx.operate("foo", &op));
+  }
+  {
+    bufferlist bl;
+    ASSERT_EQ(1, ioctx.read("foo", bl, 1, 0));
+    ASSERT_EQ('h', bl[0]);
+  }
+
+  // tear down tiers
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier remove-overlay\", \"pool\": \"" + pool_name +
+    "\"}",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier remove\", \"pool\": \"" + pool_name +
+    "\", \"tierpool\": \"" + cache_pool_name + "\"}",
+    inbl, NULL, NULL));
+
+  // wait for maps to settle before next test
+  cluster.wait_for_latest_osdmap();
+}
+
+TEST_F(LibRadosTwoPoolsECPP, Evict) {
+  // create object
+  {
+    bufferlist bl;
+    bl.append("hi there");
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, ioctx.operate("foo", &op));
+  }
+
+  // configure cache
+  bufferlist inbl;
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier add\", \"pool\": \"" + pool_name +
+    "\", \"tierpool\": \"" + cache_pool_name +
+    "\", \"force_nonempty\": \"--force-nonempty\" }",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier set-overlay\", \"pool\": \"" + pool_name +
+    "\", \"overlaypool\": \"" + cache_pool_name + "\"}",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier cache-mode\", \"pool\": \"" + cache_pool_name +
+    "\", \"mode\": \"writeback\"}",
+    inbl, NULL, NULL));
+
+  // wait for maps to settle
+  cluster.wait_for_latest_osdmap();
+
+  // read, trigger a promote
+  {
+    bufferlist bl;
+    ASSERT_EQ(1, ioctx.read("foo", bl, 1, 0));
+  }
+
+  // read, trigger a whiteout, and a dirty object
+  {
+    bufferlist bl;
+    ASSERT_EQ(-ENOENT, ioctx.read("bar", bl, 1, 0));
+    ASSERT_EQ(-ENOENT, ioctx.read("bar", bl, 1, 0));
+    ASSERT_EQ(0, ioctx.write("bar", bl, bl.length(), 0));
+  }
+
+  // verify the object is present in the cache tier
+  {
+    ObjectIterator it = cache_ioctx.objects_begin();
+    ASSERT_TRUE(it != cache_ioctx.objects_end());
+    ASSERT_TRUE(it->first == string("foo") || it->first == string("bar"));
+    ++it;
+    ASSERT_TRUE(it->first == string("foo") || it->first == string("bar"));
+    ++it;
+    ASSERT_TRUE(it == cache_ioctx.objects_end());
+  }
+
+  // evict
+  {
+    ObjectReadOperation op;
+    op.cache_evict();
+    librados::AioCompletion *completion = cluster.aio_create_completion();
+    ASSERT_EQ(0, cache_ioctx.aio_operate("foo", completion, &op,
+					 librados::OPERATION_IGNORE_CACHE,
+					 NULL));
+    completion->wait_for_safe();
+    ASSERT_EQ(0, completion->get_return_value());
+    completion->release();
+  }
+  {
+    ObjectReadOperation op;
+    op.cache_evict();
+    librados::AioCompletion *completion = cluster.aio_create_completion();
+    ASSERT_EQ(0, cache_ioctx.aio_operate(
+      "fooberdoodle", completion, &op,
+      librados::OPERATION_IGNORE_CACHE, NULL));
+    completion->wait_for_safe();
+    ASSERT_EQ(-ENOENT, completion->get_return_value());
+    completion->release();
+  }
+  {
+    ObjectReadOperation op;
+    op.cache_evict();
+    librados::AioCompletion *completion = cluster.aio_create_completion();
+    ASSERT_EQ(0, cache_ioctx.aio_operate(
+      "bar", completion, &op,
+      librados::OPERATION_IGNORE_CACHE, NULL));
+    completion->wait_for_safe();
+    ASSERT_EQ(-EBUSY, completion->get_return_value());
+    completion->release();
+  }
+
+  // tear down tiers
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier remove-overlay\", \"pool\": \"" + pool_name +
+    "\"}",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier remove\", \"pool\": \"" + pool_name +
+    "\", \"tierpool\": \"" + cache_pool_name + "\"}",
+    inbl, NULL, NULL));
+
+  // wait for maps to settle before next test
+  cluster.wait_for_latest_osdmap();
+}
+
+TEST_F(LibRadosTwoPoolsECPP, EvictSnap) {
+  // create object
+  {
+    bufferlist bl;
+    bl.append("hi there");
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, ioctx.operate("foo", &op));
+  }
+  {
+    bufferlist bl;
+    bl.append("hi there");
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, ioctx.operate("bar", &op));
+  }
+  {
+    bufferlist bl;
+    bl.append("hi there");
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, ioctx.operate("baz", &op));
+  }
+  {
+    bufferlist bl;
+    bl.append("hi there");
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, ioctx.operate("bam", &op));
+  }
+
+  // create a snapshot, clone
+  vector<uint64_t> my_snaps(1);
+  ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps[0]));
+  ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0],
+							 my_snaps));
+  {
+    bufferlist bl;
+    bl.append("ciao!");
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, ioctx.operate("foo", &op));
+  }
+  {
+    bufferlist bl;
+    bl.append("ciao!");
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, ioctx.operate("bar", &op));
+  }
+  {
+    ObjectWriteOperation op;
+    op.remove();
+    ASSERT_EQ(0, ioctx.operate("baz", &op));
+  }
+  {
+    bufferlist bl;
+    bl.append("ciao!");
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, ioctx.operate("bam", &op));
+  }
+
+  // configure cache
+  bufferlist inbl;
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier add\", \"pool\": \"" + pool_name +
+    "\", \"tierpool\": \"" + cache_pool_name +
+    "\", \"force_nonempty\": \"--force-nonempty\" }",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier set-overlay\", \"pool\": \"" + pool_name +
+    "\", \"overlaypool\": \"" + cache_pool_name + "\"}",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier cache-mode\", \"pool\": \"" + cache_pool_name +
+    "\", \"mode\": \"writeback\"}",
+    inbl, NULL, NULL));
+
+  // wait for maps to settle
+  cluster.wait_for_latest_osdmap();
+
+  // read, trigger a promote on the head
+  {
+    bufferlist bl;
+    ASSERT_EQ(1, ioctx.read("foo", bl, 1, 0));
+    ASSERT_EQ('c', bl[0]);
+  }
+  {
+    bufferlist bl;
+    ASSERT_EQ(1, ioctx.read("bam", bl, 1, 0));
+    ASSERT_EQ('c', bl[0]);
+  }
+
+  // evict bam
+  {
+    ObjectReadOperation op;
+    op.cache_evict();
+    librados::AioCompletion *completion = cluster.aio_create_completion();
+    ASSERT_EQ(0, cache_ioctx.aio_operate(
+      "bam", completion, &op,
+      librados::OPERATION_IGNORE_CACHE, NULL));
+    completion->wait_for_safe();
+    ASSERT_EQ(0, completion->get_return_value());
+    completion->release();
+  }
+  {
+    bufferlist bl;
+    ObjectReadOperation op;
+    op.read(1, 0, &bl, NULL);
+    librados::AioCompletion *completion = cluster.aio_create_completion();
+    ASSERT_EQ(0, cache_ioctx.aio_operate(
+      "bam", completion, &op,
+      librados::OPERATION_IGNORE_CACHE, NULL));
+    completion->wait_for_safe();
+    ASSERT_EQ(-ENOENT, completion->get_return_value());
+    completion->release();
+  }
+
+  // read foo snap
+  ioctx.snap_set_read(my_snaps[0]);
+  {
+    bufferlist bl;
+    ASSERT_EQ(1, ioctx.read("foo", bl, 1, 0));
+    ASSERT_EQ('h', bl[0]);
+  }
+
+  // evict foo snap
+  {
+    ObjectReadOperation op;
+    op.cache_evict();
+    librados::AioCompletion *completion = cluster.aio_create_completion();
+    ASSERT_EQ(0, ioctx.aio_operate(
+      "foo", completion, &op,
+      librados::OPERATION_IGNORE_CACHE, NULL));
+    completion->wait_for_safe();
+    ASSERT_EQ(0, completion->get_return_value());
+    completion->release();
+  }
+  // snap is gone...
+  {
+    bufferlist bl;
+    ObjectReadOperation op;
+    op.read(1, 0, &bl, NULL);
+    librados::AioCompletion *completion = cluster.aio_create_completion();
+    ASSERT_EQ(0, ioctx.aio_operate(
+      "foo", completion, &op,
+      librados::OPERATION_IGNORE_CACHE, NULL));
+    completion->wait_for_safe();
+    ASSERT_EQ(-ENOENT, completion->get_return_value());
+    completion->release();
+  }
+  // head is still there...
+  ioctx.snap_set_read(librados::SNAP_HEAD);
+  {
+    bufferlist bl;
+    ObjectReadOperation op;
+    op.read(1, 0, &bl, NULL);
+    librados::AioCompletion *completion = cluster.aio_create_completion();
+    ASSERT_EQ(0, ioctx.aio_operate(
+      "foo", completion, &op,
+      librados::OPERATION_IGNORE_CACHE, NULL));
+    completion->wait_for_safe();
+    ASSERT_EQ(0, completion->get_return_value());
+    completion->release();
+  }
+
+  // promote head + snap of bar
+  ioctx.snap_set_read(librados::SNAP_HEAD);
+  {
+    bufferlist bl;
+    ASSERT_EQ(1, ioctx.read("bar", bl, 1, 0));
+    ASSERT_EQ('c', bl[0]);
+  }
+  ioctx.snap_set_read(my_snaps[0]);
+  {
+    bufferlist bl;
+    ASSERT_EQ(1, ioctx.read("bar", bl, 1, 0));
+    ASSERT_EQ('h', bl[0]);
+  }
+
+  // evict bar head (fail)
+  ioctx.snap_set_read(librados::SNAP_HEAD);
+  {
+    ObjectReadOperation op;
+    op.cache_evict();
+    librados::AioCompletion *completion = cluster.aio_create_completion();
+    ASSERT_EQ(0, ioctx.aio_operate(
+      "bar", completion, &op,
+      librados::OPERATION_IGNORE_CACHE, NULL));
+    completion->wait_for_safe();
+    ASSERT_EQ(-EBUSY, completion->get_return_value());
+    completion->release();
+  }
+
+  // evict bar snap
+  ioctx.snap_set_read(my_snaps[0]);
+  {
+    ObjectReadOperation op;
+    op.cache_evict();
+    librados::AioCompletion *completion = cluster.aio_create_completion();
+    ASSERT_EQ(0, ioctx.aio_operate(
+      "bar", completion, &op,
+      librados::OPERATION_IGNORE_CACHE, NULL));
+    completion->wait_for_safe();
+    ASSERT_EQ(0, completion->get_return_value());
+    completion->release();
+  }
+  // ...and then head
+  ioctx.snap_set_read(librados::SNAP_HEAD);
+  {
+    bufferlist bl;
+    ObjectReadOperation op;
+    op.read(1, 0, &bl, NULL);
+    librados::AioCompletion *completion = cluster.aio_create_completion();
+    ASSERT_EQ(0, ioctx.aio_operate(
+      "bar", completion, &op,
+      librados::OPERATION_IGNORE_CACHE, NULL));
+    completion->wait_for_safe();
+    ASSERT_EQ(0, completion->get_return_value());
+    completion->release();
+  }
+  {
+    ObjectReadOperation op;
+    op.cache_evict();
+    librados::AioCompletion *completion = cluster.aio_create_completion();
+    ASSERT_EQ(0, ioctx.aio_operate(
+      "bar", completion, &op,
+      librados::OPERATION_IGNORE_CACHE, NULL));
+    completion->wait_for_safe();
+    ASSERT_EQ(0, completion->get_return_value());
+    completion->release();
+  }
+
+  // tear down tiers
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier remove-overlay\", \"pool\": \"" + pool_name +
+    "\"}",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier remove\", \"pool\": \"" + pool_name +
+    "\", \"tierpool\": \"" + cache_pool_name + "\"}",
+    inbl, NULL, NULL));
+
+  // wait for maps to settle before next test
+  cluster.wait_for_latest_osdmap();
+}
+
+TEST_F(LibRadosTwoPoolsECPP, TryFlush) {
+  // configure cache
+  bufferlist inbl;
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier add\", \"pool\": \"" + pool_name +
+    "\", \"tierpool\": \"" + cache_pool_name +
+    "\", \"force_nonempty\": \"--force-nonempty\" }",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier set-overlay\", \"pool\": \"" + pool_name +
+    "\", \"overlaypool\": \"" + cache_pool_name + "\"}",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier cache-mode\", \"pool\": \"" + cache_pool_name +
+    "\", \"mode\": \"writeback\"}",
+    inbl, NULL, NULL));
+
+  // wait for maps to settle
+  cluster.wait_for_latest_osdmap();
+
+  // create object
+  {
+    bufferlist bl;
+    bl.append("hi there");
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, ioctx.operate("foo", &op));
+  }
+
+  // verify the object is present in the cache tier
+  {
+    ObjectIterator it = cache_ioctx.objects_begin();
+    ASSERT_TRUE(it != cache_ioctx.objects_end());
+    ASSERT_TRUE(it->first == string("foo"));
+    ++it;
+    ASSERT_TRUE(it == cache_ioctx.objects_end());
+  }
+
+  // verify the object is NOT present in the base tier
+  {
+    ObjectIterator it = ioctx.objects_begin();
+    ASSERT_TRUE(it == ioctx.objects_end());
+  }
+
+  // verify dirty
+  {
+    bool dirty = false;
+    int r = -1;
+    ObjectReadOperation op;
+    op.is_dirty(&dirty, &r);
+    ASSERT_EQ(0, cache_ioctx.operate("foo", &op, NULL));
+    ASSERT_TRUE(dirty);
+    ASSERT_EQ(0, r);
+  }
+
+  // flush
+  {
+    ObjectReadOperation op;
+    op.cache_try_flush();
+    librados::AioCompletion *completion = cluster.aio_create_completion();
+    ASSERT_EQ(0, cache_ioctx.aio_operate(
+      "foo", completion, &op,
+      librados::OPERATION_IGNORE_OVERLAY |
+      librados::OPERATION_SKIPRWLOCKS, NULL));
+    completion->wait_for_safe();
+    ASSERT_EQ(0, completion->get_return_value());
+    completion->release();
+  }
+
+  // verify clean
+  {
+    bool dirty = false;
+    int r = -1;
+    ObjectReadOperation op;
+    op.is_dirty(&dirty, &r);
+    ASSERT_EQ(0, cache_ioctx.operate("foo", &op, NULL));
+    ASSERT_FALSE(dirty);
+    ASSERT_EQ(0, r);
+  }
+
+  // verify in base tier
+  {
+    ObjectIterator it = ioctx.objects_begin();
+    ASSERT_TRUE(it != ioctx.objects_end());
+    ASSERT_TRUE(it->first == string("foo"));
+    ++it;
+    ASSERT_TRUE(it == ioctx.objects_end());
+  }
+
+  // evict it
+  {
+    ObjectReadOperation op;
+    op.cache_evict();
+    librados::AioCompletion *completion = cluster.aio_create_completion();
+    ASSERT_EQ(0, cache_ioctx.aio_operate(
+	 "foo", completion, &op, librados::OPERATION_IGNORE_CACHE, NULL));
+    completion->wait_for_safe();
+    ASSERT_EQ(0, completion->get_return_value());
+    completion->release();
+  }
+
+  // verify no longer in cache tier
+  {
+    ObjectIterator it = cache_ioctx.objects_begin();
+    ASSERT_TRUE(it == cache_ioctx.objects_end());
+  }
+
+  // tear down tiers
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier remove-overlay\", \"pool\": \"" + pool_name +
+    "\"}",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier remove\", \"pool\": \"" + pool_name +
+    "\", \"tierpool\": \"" + cache_pool_name + "\"}",
+    inbl, NULL, NULL));
+
+  // wait for maps to settle before next test
+  cluster.wait_for_latest_osdmap();
+}
+
+TEST_F(LibRadosTwoPoolsECPP, Flush) {
+  // configure cache
+  bufferlist inbl;
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier add\", \"pool\": \"" + pool_name +
+    "\", \"tierpool\": \"" + cache_pool_name +
+    "\", \"force_nonempty\": \"--force-nonempty\" }",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier set-overlay\", \"pool\": \"" + pool_name +
+    "\", \"overlaypool\": \"" + cache_pool_name + "\"}",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier cache-mode\", \"pool\": \"" + cache_pool_name +
+    "\", \"mode\": \"writeback\"}",
+    inbl, NULL, NULL));
+
+  // wait for maps to settle
+  cluster.wait_for_latest_osdmap();
+
+  uint64_t user_version = 0;
+
+  // create object
+  {
+    bufferlist bl;
+    bl.append("hi there");
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, ioctx.operate("foo", &op));
+  }
+
+  // verify the object is present in the cache tier
+  {
+    ObjectIterator it = cache_ioctx.objects_begin();
+    ASSERT_TRUE(it != cache_ioctx.objects_end());
+    ASSERT_TRUE(it->first == string("foo"));
+    ++it;
+    ASSERT_TRUE(it == cache_ioctx.objects_end());
+  }
+
+  // verify the object is NOT present in the base tier
+  {
+    ObjectIterator it = ioctx.objects_begin();
+    ASSERT_TRUE(it == ioctx.objects_end());
+  }
+
+  // verify dirty
+  {
+    bool dirty = false;
+    int r = -1;
+    ObjectReadOperation op;
+    op.is_dirty(&dirty, &r);
+    ASSERT_EQ(0, cache_ioctx.operate("foo", &op, NULL));
+    ASSERT_TRUE(dirty);
+    ASSERT_EQ(0, r);
+    user_version = cache_ioctx.get_last_version();
+  }
+
+  // flush
+  {
+    ObjectReadOperation op;
+    op.cache_flush();
+    librados::AioCompletion *completion = cluster.aio_create_completion();
+    ASSERT_EQ(0, cache_ioctx.aio_operate(
+      "foo", completion, &op,
+      librados::OPERATION_IGNORE_OVERLAY, NULL));
+    completion->wait_for_safe();
+    ASSERT_EQ(0, completion->get_return_value());
+    completion->release();
+  }
+
+  // verify clean
+  {
+    bool dirty = false;
+    int r = -1;
+    ObjectReadOperation op;
+    op.is_dirty(&dirty, &r);
+    ASSERT_EQ(0, cache_ioctx.operate("foo", &op, NULL));
+    ASSERT_FALSE(dirty);
+    ASSERT_EQ(0, r);
+  }
+
+  // verify in base tier
+  {
+    ObjectIterator it = ioctx.objects_begin();
+    ASSERT_TRUE(it != ioctx.objects_end());
+    ASSERT_TRUE(it->first == string("foo"));
+    ++it;
+    ASSERT_TRUE(it == ioctx.objects_end());
+  }
+
+  // evict it
+  {
+    ObjectReadOperation op;
+    op.cache_evict();
+    librados::AioCompletion *completion = cluster.aio_create_completion();
+    ASSERT_EQ(0, cache_ioctx.aio_operate(
+	 "foo", completion, &op, librados::OPERATION_IGNORE_CACHE, NULL));
+    completion->wait_for_safe();
+    ASSERT_EQ(0, completion->get_return_value());
+    completion->release();
+  }
+
+  // verify no longer in cache tier
+  {
+    ObjectIterator it = cache_ioctx.objects_begin();
+    ASSERT_TRUE(it == cache_ioctx.objects_end());
+  }
+
+  // read it again and verify the version is consistent
+  {
+    bufferlist bl;
+    ASSERT_EQ(1, cache_ioctx.read("foo", bl, 1, 0));
+    ASSERT_EQ(user_version, cache_ioctx.get_last_version());
+  }
+
+  // erase it
+  {
+    ObjectWriteOperation op;
+    op.remove();
+    ASSERT_EQ(0, ioctx.operate("foo", &op));
+  }
+
+  // flush whiteout
+  {
+    ObjectReadOperation op;
+    op.cache_flush();
+    librados::AioCompletion *completion = cluster.aio_create_completion();
+    ASSERT_EQ(0, cache_ioctx.aio_operate(
+      "foo", completion, &op,
+      librados::OPERATION_IGNORE_OVERLAY, NULL));
+    completion->wait_for_safe();
+    ASSERT_EQ(0, completion->get_return_value());
+    completion->release();
+  }
+
+  // evict
+  {
+    ObjectReadOperation op;
+    op.cache_evict();
+    librados::AioCompletion *completion = cluster.aio_create_completion();
+    ASSERT_EQ(0, cache_ioctx.aio_operate(
+	 "foo", completion, &op, librados::OPERATION_IGNORE_CACHE, NULL));
+    completion->wait_for_safe();
+    ASSERT_EQ(0, completion->get_return_value());
+    completion->release();
+  }
+
+  // verify no longer in cache tier
+  {
+    ObjectIterator it = cache_ioctx.objects_begin();
+    ASSERT_TRUE(it == cache_ioctx.objects_end());
+  }
+  // or base tier
+  {
+    ObjectIterator it = ioctx.objects_begin();
+    ASSERT_TRUE(it == ioctx.objects_end());
+  }
+
+  // tear down tiers
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier remove-overlay\", \"pool\": \"" + pool_name +
+    "\"}",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier remove\", \"pool\": \"" + pool_name +
+    "\", \"tierpool\": \"" + cache_pool_name + "\"}",
+    inbl, NULL, NULL));
+
+  // wait for maps to settle before next test
+  cluster.wait_for_latest_osdmap();
+}
+
+TEST_F(LibRadosTwoPoolsECPP, FlushSnap) {
+  // configure cache
+  bufferlist inbl;
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier add\", \"pool\": \"" + pool_name +
+    "\", \"tierpool\": \"" + cache_pool_name +
+    "\", \"force_nonempty\": \"--force-nonempty\" }",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier set-overlay\", \"pool\": \"" + pool_name +
+    "\", \"overlaypool\": \"" + cache_pool_name + "\"}",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier cache-mode\", \"pool\": \"" + cache_pool_name +
+    "\", \"mode\": \"writeback\"}",
+    inbl, NULL, NULL));
+
+  // wait for maps to settle
+  cluster.wait_for_latest_osdmap();
+
+  // create object
+  {
+    bufferlist bl;
+    bl.append("a");
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, ioctx.operate("foo", &op));
+  }
+
+  // create a snapshot, clone
+  vector<uint64_t> my_snaps(1);
+  ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps[0]));
+  ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0],
+							 my_snaps));
+  {
+    bufferlist bl;
+    bl.append("b");
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, ioctx.operate("foo", &op));
+  }
+
+  // and another
+  my_snaps.resize(2);
+  my_snaps[1] = my_snaps[0];
+  ASSERT_EQ(0, ioctx.selfmanaged_snap_create(&my_snaps[0]));
+  ASSERT_EQ(0, ioctx.selfmanaged_snap_set_write_ctx(my_snaps[0],
+							 my_snaps));
+  {
+    bufferlist bl;
+    bl.append("c");
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, ioctx.operate("foo", &op));
+  }
+
+  // verify the object is present in the cache tier
+  {
+    ObjectIterator it = cache_ioctx.objects_begin();
+    ASSERT_TRUE(it != cache_ioctx.objects_end());
+    ASSERT_TRUE(it->first == string("foo"));
+    ++it;
+    ASSERT_TRUE(it == cache_ioctx.objects_end());
+  }
+
+  // verify the object is NOT present in the base tier
+  {
+    ObjectIterator it = ioctx.objects_begin();
+    ASSERT_TRUE(it == ioctx.objects_end());
+  }
+
+  // flush on head (should fail)
+  ioctx.snap_set_read(librados::SNAP_HEAD);
+  {
+    ObjectReadOperation op;
+    op.cache_flush();
+    librados::AioCompletion *completion = cluster.aio_create_completion();
+    ASSERT_EQ(0, ioctx.aio_operate(
+      "foo", completion, &op,
+      librados::OPERATION_IGNORE_CACHE, NULL));
+    completion->wait_for_safe();
+    ASSERT_EQ(-EBUSY, completion->get_return_value());
+    completion->release();
+  }
+  // flush on recent snap (should fail)
+  ioctx.snap_set_read(my_snaps[0]);
+  {
+    ObjectReadOperation op;
+    op.cache_flush();
+    librados::AioCompletion *completion = cluster.aio_create_completion();
+    ASSERT_EQ(0, ioctx.aio_operate(
+      "foo", completion, &op,
+      librados::OPERATION_IGNORE_CACHE, NULL));
+    completion->wait_for_safe();
+    ASSERT_EQ(-EBUSY, completion->get_return_value());
+    completion->release();
+  }
+  // flush on oldest snap
+  ioctx.snap_set_read(my_snaps[1]);
+  {
+    ObjectReadOperation op;
+    op.cache_flush();
+    librados::AioCompletion *completion = cluster.aio_create_completion();
+    ASSERT_EQ(0, ioctx.aio_operate(
+      "foo", completion, &op,
+      librados::OPERATION_IGNORE_CACHE, NULL));
+    completion->wait_for_safe();
+    ASSERT_EQ(0, completion->get_return_value());
+    completion->release();
+  }
+  // flush on next oldest snap
+  ioctx.snap_set_read(my_snaps[0]);
+  {
+    ObjectReadOperation op;
+    op.cache_flush();
+    librados::AioCompletion *completion = cluster.aio_create_completion();
+    ASSERT_EQ(0, ioctx.aio_operate(
+      "foo", completion, &op,
+      librados::OPERATION_IGNORE_CACHE, NULL));
+    completion->wait_for_safe();
+    ASSERT_EQ(0, completion->get_return_value());
+    completion->release();
+  }
+  // flush on head
+  ioctx.snap_set_read(librados::SNAP_HEAD);
+  {
+    ObjectReadOperation op;
+    op.cache_flush();
+    librados::AioCompletion *completion = cluster.aio_create_completion();
+    ASSERT_EQ(0, ioctx.aio_operate(
+      "foo", completion, &op,
+      librados::OPERATION_IGNORE_CACHE, NULL));
+    completion->wait_for_safe();
+    ASSERT_EQ(0, completion->get_return_value());
+    completion->release();
+  }
+
+  // verify i can read the snaps from the cache pool
+  ioctx.snap_set_read(librados::SNAP_HEAD);
+  {
+    bufferlist bl;
+    ASSERT_EQ(1, ioctx.read("foo", bl, 1, 0));
+    ASSERT_EQ('c', bl[0]);
+  }
+  ioctx.snap_set_read(my_snaps[0]);
+  {
+    bufferlist bl;
+    ASSERT_EQ(1, ioctx.read("foo", bl, 1, 0));
+    ASSERT_EQ('b', bl[0]);
+  }
+  ioctx.snap_set_read(my_snaps[1]);
+  {
+    bufferlist bl;
+    ASSERT_EQ(1, ioctx.read("foo", bl, 1, 0));
+    ASSERT_EQ('a', bl[0]);
+  }
+
+  // tear down tiers
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier remove-overlay\", \"pool\": \"" + pool_name +
+    "\"}",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier remove\", \"pool\": \"" + pool_name +
+    "\", \"tierpool\": \"" + cache_pool_name + "\"}",
+    inbl, NULL, NULL));
+
+  // wait for maps to settle
+  cluster.wait_for_latest_osdmap();
+
+  // verify i can read the snaps from the base pool
+  ioctx.snap_set_read(librados::SNAP_HEAD);
+  {
+    bufferlist bl;
+    ASSERT_EQ(1, ioctx.read("foo", bl, 1, 0));
+    ASSERT_EQ('c', bl[0]);
+  }
+  ioctx.snap_set_read(my_snaps[0]);
+  {
+    bufferlist bl;
+    ASSERT_EQ(1, ioctx.read("foo", bl, 1, 0));
+    ASSERT_EQ('b', bl[0]);
+  }
+  ioctx.snap_set_read(my_snaps[1]);
+  {
+    bufferlist bl;
+    ASSERT_EQ(1, ioctx.read("foo", bl, 1, 0));
+    ASSERT_EQ('a', bl[0]);
+  }
+}
+
+TEST_F(LibRadosTierECPP, FlushWriteRaces) {
+  Rados cluster;
+  std::string pool_name = get_temp_pool_name();
+  std::string cache_pool_name = pool_name + "-cache";
+  ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
+  ASSERT_EQ(0, cluster.pool_create(cache_pool_name.c_str()));
+  IoCtx cache_ioctx;
+  ASSERT_EQ(0, cluster.ioctx_create(cache_pool_name.c_str(), cache_ioctx));
+  IoCtx ioctx;
+  ASSERT_EQ(0, cluster.ioctx_create(pool_name.c_str(), ioctx));
+
+  // configure cache
+  bufferlist inbl;
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier add\", \"pool\": \"" + pool_name +
+    "\", \"tierpool\": \"" + cache_pool_name + "\"}",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier set-overlay\", \"pool\": \"" + pool_name +
+    "\", \"overlaypool\": \"" + cache_pool_name + "\"}",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier cache-mode\", \"pool\": \"" + cache_pool_name +
+    "\", \"mode\": \"writeback\"}",
+    inbl, NULL, NULL));
+
+  // wait for maps to settle
+  cluster.wait_for_latest_osdmap();
+
+  // create/dirty object
+  bufferlist bl;
+  bl.append("hi there");
+  {
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, ioctx.operate("foo", &op));
+  }
+
+  // flush + write
+  {
+    ObjectReadOperation op;
+    op.cache_flush();
+    librados::AioCompletion *completion = cluster.aio_create_completion();
+    ASSERT_EQ(0, cache_ioctx.aio_operate(
+      "foo", completion, &op,
+      librados::OPERATION_IGNORE_OVERLAY, NULL));
+
+    ObjectWriteOperation op2;
+    op2.write_full(bl);
+    librados::AioCompletion *completion2 = cluster.aio_create_completion();
+    ASSERT_EQ(0, ioctx.aio_operate(
+      "foo", completion2, &op2, 0));
+
+    completion->wait_for_safe();
+    completion2->wait_for_safe();
+    ASSERT_EQ(0, completion->get_return_value());
+    ASSERT_EQ(0, completion2->get_return_value());
+    completion->release();
+    completion2->release();
+  }
+
+  int tries = 1000;
+  do {
+    // create/dirty object
+    {
+      bufferlist bl;
+      bl.append("hi there");
+      ObjectWriteOperation op;
+      op.write_full(bl);
+      ASSERT_EQ(0, ioctx.operate("foo", &op));
+    }
+
+    // try-flush + write
+    {
+      ObjectReadOperation op;
+      op.cache_try_flush();
+      librados::AioCompletion *completion = cluster.aio_create_completion();
+      ASSERT_EQ(0, cache_ioctx.aio_operate(
+        "foo", completion, &op,
+	librados::OPERATION_IGNORE_OVERLAY |
+	librados::OPERATION_SKIPRWLOCKS, NULL));
+
+      ObjectWriteOperation op2;
+      op2.write_full(bl);
+      librados::AioCompletion *completion2 = cluster.aio_create_completion();
+      ASSERT_EQ(0, ioctx.aio_operate("foo", completion2, &op2, 0));
+
+      completion->wait_for_safe();
+      completion2->wait_for_safe();
+      int r = completion->get_return_value();
+      ASSERT_TRUE(r == -EBUSY || r == 0);
+      ASSERT_EQ(0, completion2->get_return_value());
+      completion->release();
+      completion2->release();
+      if (r == -EBUSY)
+	break;
+      cout << "didn't get EBUSY, trying again" << std::endl;
+    }
+    ASSERT_TRUE(--tries);
+  } while (true);
+
+  // tear down tiers
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier remove-overlay\", \"pool\": \"" + pool_name +
+    "\"}",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier remove\", \"pool\": \"" + pool_name +
+    "\", \"tierpool\": \"" + cache_pool_name + "\"}",
+    inbl, NULL, NULL));
+
+  // wait for maps to settle before next test
+  cluster.wait_for_latest_osdmap();
+
+  ASSERT_EQ(0, cluster.pool_delete(cache_pool_name.c_str()));
+  ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
+}
+
+TEST_F(LibRadosTwoPoolsECPP, FlushTryFlushRaces) {
+  // configure cache
+  bufferlist inbl;
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier add\", \"pool\": \"" + pool_name +
+    "\", \"tierpool\": \"" + cache_pool_name +
+    "\", \"force_nonempty\": \"--force-nonempty\" }",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier set-overlay\", \"pool\": \"" + pool_name +
+    "\", \"overlaypool\": \"" + cache_pool_name + "\"}",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier cache-mode\", \"pool\": \"" + cache_pool_name +
+    "\", \"mode\": \"writeback\"}",
+    inbl, NULL, NULL));
+
+  // wait for maps to settle
+  cluster.wait_for_latest_osdmap();
+
+  // create/dirty object
+  {
+    bufferlist bl;
+    bl.append("hi there");
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, ioctx.operate("foo", &op));
+  }
+
+  // flush + flush
+  {
+    ObjectReadOperation op;
+    op.cache_flush();
+    librados::AioCompletion *completion = cluster.aio_create_completion();
+    ASSERT_EQ(0, cache_ioctx.aio_operate(
+      "foo", completion, &op,
+      librados::OPERATION_IGNORE_OVERLAY, NULL));
+
+    ObjectReadOperation op2;
+    op2.cache_flush();
+    librados::AioCompletion *completion2 = cluster.aio_create_completion();
+    ASSERT_EQ(0, cache_ioctx.aio_operate(
+      "foo", completion2, &op2,
+      librados::OPERATION_IGNORE_OVERLAY, NULL));
+
+    completion->wait_for_safe();
+    completion2->wait_for_safe();
+    ASSERT_EQ(0, completion->get_return_value());
+    ASSERT_EQ(0, completion2->get_return_value());
+    completion->release();
+    completion2->release();
+  }
+
+  // create/dirty object
+  {
+    bufferlist bl;
+    bl.append("hi there");
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, ioctx.operate("foo", &op));
+  }
+
+  // flush + try-flush
+  {
+    ObjectReadOperation op;
+    op.cache_flush();
+    librados::AioCompletion *completion = cluster.aio_create_completion();
+    ASSERT_EQ(0, cache_ioctx.aio_operate(
+      "foo", completion, &op,
+      librados::OPERATION_IGNORE_OVERLAY, NULL));
+
+    ObjectReadOperation op2;
+    op2.cache_try_flush();
+    librados::AioCompletion *completion2 = cluster.aio_create_completion();
+    ASSERT_EQ(0, cache_ioctx.aio_operate(
+      "foo", completion2, &op2,
+      librados::OPERATION_IGNORE_OVERLAY |
+      librados::OPERATION_SKIPRWLOCKS, NULL));
+
+    completion->wait_for_safe();
+    completion2->wait_for_safe();
+    ASSERT_EQ(0, completion->get_return_value());
+    ASSERT_EQ(0, completion2->get_return_value());
+    completion->release();
+    completion2->release();
+  }
+
+  // create/dirty object
+  int tries = 1000;
+  do {
+    {
+      bufferlist bl;
+      bl.append("hi there");
+      ObjectWriteOperation op;
+      op.write_full(bl);
+      ASSERT_EQ(0, ioctx.operate("foo", &op));
+    }
+
+    // try-flush + flush
+    //  (flush will not piggyback on try-flush)
+    {
+      ObjectReadOperation op;
+      op.cache_try_flush();
+      librados::AioCompletion *completion = cluster.aio_create_completion();
+      ASSERT_EQ(0, cache_ioctx.aio_operate(
+        "foo", completion, &op,
+	librados::OPERATION_IGNORE_OVERLAY |
+	librados::OPERATION_SKIPRWLOCKS, NULL));
+
+      ObjectReadOperation op2;
+      op2.cache_flush();
+      librados::AioCompletion *completion2 = cluster.aio_create_completion();
+      ASSERT_EQ(0, cache_ioctx.aio_operate(
+        "foo", completion2, &op2,
+	librados::OPERATION_IGNORE_OVERLAY, NULL));
+
+      completion->wait_for_safe();
+      completion2->wait_for_safe();
+      int r = completion->get_return_value();
+      ASSERT_TRUE(r == -EBUSY || r == 0);
+      ASSERT_EQ(0, completion2->get_return_value());
+      completion->release();
+      completion2->release();
+      if (r == -EBUSY)
+	break;
+      cout << "didn't get EBUSY, trying again" << std::endl;
+    }
+    ASSERT_TRUE(--tries);
+  } while (true);
+
+  // create/dirty object
+  {
+    bufferlist bl;
+    bl.append("hi there");
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, ioctx.operate("foo", &op));
+  }
+
+  // try-flush + try-flush
+  {
+    ObjectReadOperation op;
+    op.cache_try_flush();
+    librados::AioCompletion *completion = cluster.aio_create_completion();
+    ASSERT_EQ(0, cache_ioctx.aio_operate(
+      "foo", completion, &op,
+      librados::OPERATION_IGNORE_OVERLAY |
+      librados::OPERATION_SKIPRWLOCKS, NULL));
+
+    ObjectReadOperation op2;
+    op2.cache_try_flush();
+    librados::AioCompletion *completion2 = cluster.aio_create_completion();
+    ASSERT_EQ(0, cache_ioctx.aio_operate(
+      "foo", completion2, &op2,
+      librados::OPERATION_IGNORE_OVERLAY |
+      librados::OPERATION_SKIPRWLOCKS, NULL));
+
+    completion->wait_for_safe();
+    completion2->wait_for_safe();
+    ASSERT_EQ(0, completion->get_return_value());
+    ASSERT_EQ(0, completion2->get_return_value());
+    completion->release();
+    completion2->release();
+  }
+
+  // tear down tiers
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier remove-overlay\", \"pool\": \"" + pool_name +
+    "\"}",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier remove\", \"pool\": \"" + pool_name +
+    "\", \"tierpool\": \"" + cache_pool_name + "\"}",
+    inbl, NULL, NULL));
+
+  // wait for maps to settle before next test
+  cluster.wait_for_latest_osdmap();
+}
+
+TEST_F(LibRadosTwoPoolsECPP, TryFlushReadRace) {
+  // configure cache
+  bufferlist inbl;
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier add\", \"pool\": \"" + pool_name +
+    "\", \"tierpool\": \"" + cache_pool_name +
+    "\", \"force_nonempty\": \"--force-nonempty\" }",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier set-overlay\", \"pool\": \"" + pool_name +
+    "\", \"overlaypool\": \"" + cache_pool_name + "\"}",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier cache-mode\", \"pool\": \"" + cache_pool_name +
+    "\", \"mode\": \"writeback\"}",
+    inbl, NULL, NULL));
+
+  // wait for maps to settle
+  cluster.wait_for_latest_osdmap();
+
+  // create/dirty object
+  {
+    bufferlist bl;
+    bl.append("hi there");
+    bufferptr bp(4000000);  // make it big!
+    bp.zero();
+    bl.append(bp);
+    ObjectWriteOperation op;
+    op.write_full(bl);
+    ASSERT_EQ(0, ioctx.operate("foo", &op));
+  }
+
+  // start a continuous stream of reads
+  read_ioctx = &ioctx;
+  test_lock.Lock();
+  for (int i = 0; i < max_reads; ++i) {
+    start_flush_read();
+    num_reads++;
+  }
+  test_lock.Unlock();
+
+  // try-flush
+  ObjectReadOperation op;
+  op.cache_try_flush();
+  librados::AioCompletion *completion = cluster.aio_create_completion();
+  ASSERT_EQ(0, cache_ioctx.aio_operate(
+      "foo", completion, &op,
+      librados::OPERATION_IGNORE_OVERLAY |
+      librados::OPERATION_SKIPRWLOCKS, NULL));
+
+  completion->wait_for_safe();
+  ASSERT_EQ(0, completion->get_return_value());
+  completion->release();
+
+  // stop reads
+  test_lock.Lock();
+  max_reads = 0;
+  while (num_reads > 0)
+    cond.Wait(test_lock);
+  test_lock.Unlock();
+
+  // tear down tiers
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier remove-overlay\", \"pool\": \"" + pool_name +
+    "\"}",
+    inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(
+    "{\"prefix\": \"osd tier remove\", \"pool\": \"" + pool_name +
+    "\", \"tierpool\": \"" + cache_pool_name + "\"}",
+    inbl, NULL, NULL));
+
+  // wait for maps to settle before next test
+  cluster.wait_for_latest_osdmap();
+}
+
+TEST_F(LibRadosTierECPP, HitSetNone) {
+  {
+    list< pair<time_t,time_t> > ls;
+    AioCompletion *c = librados::Rados::aio_create_completion();
+    ASSERT_EQ(0, ioctx.hit_set_list(123, c, &ls));
+    c->wait_for_complete();
+    ASSERT_EQ(0, c->get_return_value());
+    ASSERT_TRUE(ls.empty());
+    c->release();
+  }
+  {
+    bufferlist bl;
+    AioCompletion *c = librados::Rados::aio_create_completion();
+    ASSERT_EQ(0, ioctx.hit_set_get(123, c, 12345, &bl));
+    c->wait_for_complete();
+    ASSERT_EQ(-ENOENT, c->get_return_value());
+    c->release();
+  }
+}
+
+TEST_F(LibRadosTierECPP, HitSetRead) {
+  // enable hitset tracking for this pool
+  bufferlist inbl;
+  ASSERT_EQ(0, cluster.mon_command(set_pool_str(pool_name, "hit_set_count", 2),
+						inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(set_pool_str(pool_name, "hit_set_period", 600),
+						inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(set_pool_str(pool_name, "hit_set_type",
+						"explicit_object"),
+				   inbl, NULL, NULL));
+
+  // wait for maps to settle
+  cluster.wait_for_latest_osdmap();
+
+  ioctx.set_namespace("");
+
+  // keep reading until we see our object appear in the HitSet
+  utime_t start = ceph_clock_now(NULL);
+  utime_t hard_stop = start + utime_t(600, 0);
+
+  while (true) {
+    utime_t now = ceph_clock_now(NULL);
+    ASSERT_TRUE(now < hard_stop);
+
+    string name = "foo";
+    uint32_t hash = ioctx.get_object_hash_position(name);
+    hobject_t oid(sobject_t(name, CEPH_NOSNAP), "", hash,
+		  cluster.pool_lookup(pool_name.c_str()), "");
+
+    bufferlist bl;
+    ASSERT_EQ(-ENOENT, ioctx.read("foo", bl, 1, 0));
+
+    bufferlist hbl;
+    AioCompletion *c = librados::Rados::aio_create_completion();
+    ASSERT_EQ(0, ioctx.hit_set_get(hash, c, now.sec(), &hbl));
+    c->wait_for_complete();
+    c->release();
+
+    if (hbl.length()) {
+      bufferlist::iterator p = hbl.begin();
+      HitSet hs;
+      ::decode(hs, p);
+      if (hs.contains(oid)) {
+	cout << "ok, hit_set contains " << oid << std::endl;
+	break;
+      }
+      cout << "hmm, not in HitSet yet" << std::endl;
+    } else {
+      cout << "hmm, no HitSet yet" << std::endl;
+    }
+
+    sleep(1);
+  }
+}
+
+TEST_F(LibRadosTierECPP, HitSetWrite) {
+  int num_pg = _get_pg_num(cluster, pool_name);
+  assert(num_pg > 0);
+
+  // enable hitset tracking for this pool
+  bufferlist inbl;
+  ASSERT_EQ(0, cluster.mon_command(set_pool_str(pool_name, "hit_set_count", 8),
+						inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(set_pool_str(pool_name, "hit_set_period", 600),
+						inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(set_pool_str(pool_name, "hit_set_type",
+						"explicit_hash"),
+				   inbl, NULL, NULL));
+
+  // wait for maps to settle
+  cluster.wait_for_latest_osdmap();
+
+  ioctx.set_namespace("");
+
+  // do a bunch of writes
+  for (int i=0; i<1000; ++i) {
+    bufferlist bl;
+    bl.append("a");
+    ASSERT_EQ(1, ioctx.write(stringify(i), bl, 1, 0));
+  }
+
+  // get HitSets
+  std::map<int,HitSet> hitsets;
+  for (int i=0; i<num_pg; ++i) {
+    list< pair<time_t,time_t> > ls;
+    AioCompletion *c = librados::Rados::aio_create_completion();
+    ASSERT_EQ(0, ioctx.hit_set_list(i, c, &ls));
+    c->wait_for_complete();
+    c->release();
+    std::cout << "pg " << i << " ls " << ls << std::endl;
+    ASSERT_FALSE(ls.empty());
+
+    // get the latest
+    c = librados::Rados::aio_create_completion();
+    bufferlist bl;
+    ASSERT_EQ(0, ioctx.hit_set_get(i, c, ls.back().first, &bl));
+    c->wait_for_complete();
+    c->release();
+
+    //std::cout << "bl len is " << bl.length() << "\n";
+    //bl.hexdump(std::cout);
+    //std::cout << std::endl;
+
+    bufferlist::iterator p = bl.begin();
+    ::decode(hitsets[i], p);
+
+    // cope with racing splits by refreshing pg_num
+    if (i == num_pg - 1)
+      num_pg = _get_pg_num(cluster, pool_name);
+  }
+
+  for (int i=0; i<1000; ++i) {
+    string n = stringify(i);
+    uint32_t hash = ioctx.get_object_hash_position(n);
+    hobject_t oid(sobject_t(n, CEPH_NOSNAP), "", hash,
+		  cluster.pool_lookup(pool_name.c_str()), "");
+    std::cout << "checking for " << oid << std::endl;
+    bool found = false;
+    for (int p=0; p<num_pg; ++p) {
+      if (hitsets[p].contains(oid)) {
+	found = true;
+	break;
+      }
+    }
+    ASSERT_TRUE(found);
+  }
+}
+
+TEST_F(LibRadosTierECPP, HitSetTrim) {
+  unsigned count = 3;
+  unsigned period = 3;
+
+  // enable hitset tracking for this pool
+  bufferlist inbl;
+  ASSERT_EQ(0, cluster.mon_command(set_pool_str(pool_name, "hit_set_count", count),
+						inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(set_pool_str(pool_name, "hit_set_period", period),
+						inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(set_pool_str(pool_name, "hit_set_type", "bloom"),
+				   inbl, NULL, NULL));
+  ASSERT_EQ(0, cluster.mon_command(set_pool_str(pool_name, "hit_set_fpp", ".01"),
+				   inbl, NULL, NULL));
+
+  // wait for maps to settle
+  cluster.wait_for_latest_osdmap();
+
+  ioctx.set_namespace("");
+
+  // do a bunch of writes and make sure the hitsets rotate
+  utime_t start = ceph_clock_now(NULL);
+  utime_t hard_stop = start + utime_t(count * period * 12, 0);
+
+  time_t first = 0;
+  int bsize = alignment;
+  char *buf = (char *)new char[bsize];
+  memset(buf, 'f', bsize);
+
+  while (true) {
+    string name = "foo";
+    uint32_t hash = ioctx.get_object_hash_position(name);
+    hobject_t oid(sobject_t(name, CEPH_NOSNAP), "", hash, -1, "");
+
+    bufferlist bl;
+    bl.append(buf, bsize);
+    ASSERT_EQ(bsize, ioctx.append("foo", bl, bsize));
+
+    list<pair<time_t, time_t> > ls;
+    AioCompletion *c = librados::Rados::aio_create_completion();
+    ASSERT_EQ(0, ioctx.hit_set_list(hash, c, &ls));
+    c->wait_for_complete();
+    c->release();
+
+    ASSERT_TRUE(ls.size() <= count + 1);
+    cout << " got ls " << ls << std::endl;
+    if (!ls.empty()) {
+      if (!first) {
+	first = ls.front().first;
+	cout << "first is " << first << std::endl;
+      } else {
+	if (ls.front().first != first) {
+	  cout << "first now " << ls.front().first << ", trimmed" << std::endl;
+	  break;
+	}
+      }
+    }
+
+    utime_t now = ceph_clock_now(NULL);
+    ASSERT_TRUE(now < hard_stop);
+
+    sleep(1);
+  }
+  delete[] buf;
+}
 
 int main(int argc, char **argv)
 {
diff --git a/src/test/librados/watch_notify.cc b/src/test/librados/watch_notify.cc
index 8616b5c..44c2a95 100644
--- a/src/test/librados/watch_notify.cc
+++ b/src/test/librados/watch_notify.cc
@@ -12,6 +12,8 @@ using namespace librados;
 
 typedef RadosTest LibRadosWatchNotify;
 typedef RadosTestPP LibRadosWatchNotifyPP;
+typedef RadosTestEC LibRadosWatchNotifyEC;
+typedef RadosTestECPP LibRadosWatchNotifyECPP;
 
 static sem_t sem;
 
@@ -80,3 +82,55 @@ TEST_F(LibRadosWatchNotifyPP, WatchNotifyTimeoutTestPP) {
   ASSERT_EQ(0, ioctx.watch("foo", 0, &handle, &ctx));
   sem_destroy(&sem);
 }
+
+TEST_F(LibRadosWatchNotifyEC, WatchNotifyTest) {
+  ASSERT_EQ(0, sem_init(&sem, 0, 0));
+  char buf[128];
+  memset(buf, 0xcc, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), rados_write(ioctx, "foo", buf, sizeof(buf), 0));
+  uint64_t handle;
+  ASSERT_EQ(0,
+      rados_watch(ioctx, "foo", 0, &handle, watch_notify_test_cb, NULL));
+  ASSERT_EQ(0, rados_notify(ioctx, "foo", 0, NULL, 0));
+  TestAlarm alarm;
+  sem_wait(&sem);
+  rados_unwatch(ioctx, "foo", handle);
+  sem_destroy(&sem);
+}
+
+TEST_F(LibRadosWatchNotifyECPP, WatchNotifyTestPP) {
+  ASSERT_EQ(0, sem_init(&sem, 0, 0));
+  char buf[128];
+  memset(buf, 0xcc, sizeof(buf));
+  bufferlist bl1;
+  bl1.append(buf, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), ioctx.write("foo", bl1, sizeof(buf), 0));
+  uint64_t handle;
+  WatchNotifyTestCtx ctx;
+  ASSERT_EQ(0, ioctx.watch("foo", 0, &handle, &ctx));
+  std::list<obj_watch_t> watches;
+  ASSERT_EQ(0, ioctx.list_watchers("foo", &watches));
+  ASSERT_EQ(watches.size(), 1u);
+  bufferlist bl2;
+  ASSERT_EQ(0, ioctx.notify("foo", 0, bl2));
+  TestAlarm alarm;
+  sem_wait(&sem);
+  ioctx.unwatch("foo", handle);
+  sem_destroy(&sem);
+}
+
+TEST_F(LibRadosWatchNotifyECPP, WatchNotifyTimeoutTestPP) {
+  ASSERT_EQ(0, sem_init(&sem, 0, 0));
+  ioctx.set_notify_timeout(1);
+  uint64_t handle;
+  WatchNotifyTestCtx ctx;
+
+  char buf[128];
+  memset(buf, 0xcc, sizeof(buf));
+  bufferlist bl1;
+  bl1.append(buf, sizeof(buf));
+  ASSERT_EQ((int)sizeof(buf), ioctx.write("foo", bl1, sizeof(buf), 0));
+
+  ASSERT_EQ(0, ioctx.watch("foo", 0, &handle, &ctx));
+  sem_destroy(&sem);
+}
diff --git a/src/test/librbd/test_librbd.cc b/src/test/librbd/test_librbd.cc
index 5169a14..d0b9c99 100644
--- a/src/test/librbd/test_librbd.cc
+++ b/src/test/librbd/test_librbd.cc
@@ -314,6 +314,8 @@ int test_ls_pp(librbd::RBD& rbd, librados::IoCtx& io_ctx, size_t num_expected, .
     assert(listed_name != names.end());
     names.erase(listed_name);
   }
+  va_end(ap);
+
   assert(names.empty());
 
   return num;
diff --git a/src/test/mon/PGMap.cc b/src/test/mon/PGMap.cc
index f7fbe7e..9f7a6b2 100644
--- a/src/test/mon/PGMap.cc
+++ b/src/test/mon/PGMap.cc
@@ -30,54 +30,54 @@ TEST(pgmap, min_last_epoch_clean)
   inc.version = 1;
   inc.update_stat(0, 123, os);
   pg_map.apply_incremental(g_ceph_context, inc);
-  ASSERT_EQ(123u, pg_map.calc_min_last_epoch_clean());
+  ASSERT_EQ(123u, pg_map.get_min_last_epoch_clean());
 
   inc = PGMap::Incremental();
   inc.version = 2;
   inc.update_stat(1, 222, os);
   pg_map.apply_incremental(g_ceph_context, inc);
-  ASSERT_EQ(123u, pg_map.calc_min_last_epoch_clean());
+  ASSERT_EQ(123u, pg_map.get_min_last_epoch_clean());
 
   inc = PGMap::Incremental();
   inc.version = 3;
   inc.update_stat(0, 222, os);
   pg_map.apply_incremental(g_ceph_context, inc);
-  ASSERT_EQ(222u, pg_map.calc_min_last_epoch_clean());
+  ASSERT_EQ(222u, pg_map.get_min_last_epoch_clean());
 
   inc = PGMap::Incremental();
   inc.version = 4;
   inc.update_stat(0, 333, os);
   inc.update_stat(1, 333, os);
   pg_map.apply_incremental(g_ceph_context, inc);
-  ASSERT_EQ(333u, pg_map.calc_min_last_epoch_clean());
+  ASSERT_EQ(333u, pg_map.get_min_last_epoch_clean());
 
   ps.last_epoch_clean = 222;
   inc = PGMap::Incremental();
   inc.version = 5;
   inc.pg_stat_updates[pg_t(1,1)] = ps;
   pg_map.apply_incremental(g_ceph_context, inc);
-  ASSERT_EQ(222u, pg_map.calc_min_last_epoch_clean());
+  ASSERT_EQ(222u, pg_map.get_min_last_epoch_clean());
 
   ps.last_epoch_clean = 223;
   inc = PGMap::Incremental();
   inc.version = 6;
   inc.pg_stat_updates[pg_t(1,1)] = ps;
   pg_map.apply_incremental(g_ceph_context, inc);
-  ASSERT_EQ(223u, pg_map.calc_min_last_epoch_clean());
+  ASSERT_EQ(223u, pg_map.get_min_last_epoch_clean());
 
   ps.last_epoch_clean = 224;
   inc = PGMap::Incremental();
   inc.version = 7;
   inc.pg_stat_updates[pg_t(2,2)] = ps;
   pg_map.apply_incremental(g_ceph_context, inc);
-  ASSERT_EQ(223u, pg_map.calc_min_last_epoch_clean());
+  ASSERT_EQ(223u, pg_map.get_min_last_epoch_clean());
 
   ps.last_epoch_clean = 225;
   inc = PGMap::Incremental();
   inc.version = 8;
   inc.pg_stat_updates[pg_t(1,1)] = ps;
   pg_map.apply_incremental(g_ceph_context, inc);
-  ASSERT_EQ(224u, pg_map.calc_min_last_epoch_clean());
+  ASSERT_EQ(224u, pg_map.get_min_last_epoch_clean());
 
 }
 
diff --git a/src/test/mon/mon-test-helpers.sh b/src/test/mon/mon-test-helpers.sh
index 32db2bb..d228569 100644
--- a/src/test/mon/mon-test-helpers.sh
+++ b/src/test/mon/mon-test-helpers.sh
@@ -1,6 +1,6 @@
 #!/bin/bash
 #
-# Copyright (C) 2013 Cloudwatt <libre.licensing at cloudwatt.com>
+# Copyright (C) 2013,2014 Cloudwatt <libre.licensing at cloudwatt.com>
 #
 # Author: Loic Dachary <loic at dachary.org>
 #
@@ -66,6 +66,31 @@ function kill_daemons() {
     done
 }
 
+function call_TEST_functions() {
+    local dir=$1
+    shift
+    local id=$2
+    shift
+
+    setup $dir || return 1
+    run_mon $dir $id "$@"
+    SHARE_MON_FUNCTIONS=${SHARE_MON_FUNCTIONS:-$(set | sed -n -e 's/^\(SHARE_MON_TEST_[0-9a-z_]*\) .*/\1/p')}
+    for TEST_function in $SHARE_MON_FUNCTIONS ; do
+        if ! $TEST_function $dir $id ; then
+            cat $dir/$id/log
+            return 1
+        fi
+    done
+    teardown $dir || return 1
+
+    FUNCTIONS=${FUNCTIONS:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
+    for TEST_function in $FUNCTIONS ; do
+        setup $dir || return 1
+        $TEST_function $dir || return 1
+        teardown $dir || return 1
+    done
+}
+
 function main() {
     local dir=$1
 
@@ -77,6 +102,12 @@ function main() {
 
     set -x
     setup $dir || return 1
-    run $dir || return 1
+    local code
+    if run $dir ; then
+        code=0
+    else
+        code=1
+    fi
     teardown $dir || return 1
+    return $code
 }
diff --git a/src/test/multi_stress_watch.cc b/src/test/multi_stress_watch.cc
index eb21bda..6203d7b 100644
--- a/src/test/multi_stress_watch.cc
+++ b/src/test/multi_stress_watch.cc
@@ -29,17 +29,106 @@ public:
     }
 };
 
+void
+test_loop(Rados &cluster, std::string pool_name, std::string obj_name)
+{
+  int ret;
+  IoCtx ioctx;
+  ret = cluster.ioctx_create(pool_name.c_str(), ioctx);
+  if (ret < 0) {
+    std::cerr << "ioctx_create " << pool_name << " failed with " << ret << std::endl;
+    exit(1);
+  }
+
+  ret = ioctx.create(obj_name, false);
+  if (ret < 0) {
+    std::cerr << "create failed with " << ret << std::endl;
+    exit(1);
+  }
+
+  for (int i = 0; i < 10000; ++i) {
+    std::cerr << "Iteration " << i << std::endl;
+    uint64_t handle;
+    WatchNotifyTestCtx ctx;
+    ret = ioctx.watch(obj_name, 0, &handle, &ctx);
+    assert(!ret);
+    bufferlist bl2;
+    ret = ioctx.notify(obj_name, 0, bl2);
+    assert(!ret);
+    TestAlarm alarm;
+    sem_wait(&sem);
+    ioctx.unwatch(obj_name, handle);
+  }
+
+  ioctx.close();
+}
+
+void
+test_replicated(Rados &cluster, std::string pool_name, std::string obj_name)
+{
+  // May already exist
+  cluster.pool_create(pool_name.c_str());
+
+  test_loop(cluster, pool_name, obj_name);
+}
+
+void
+test_erasure(Rados &cluster, std::string pool_name, std::string obj_name)
+{
+  string outs;
+  bufferlist inbl;
+  int ret;
+  ret = cluster.mon_command(
+    "{\"prefix\": \"osd erasure-code-profile set\", \"name\": \"testprofile\", \"profile\": [ \"k=2\", \"m=1\", \"ruleset-failure-domain=osd\"]}",
+    inbl, NULL, &outs);
+  if (ret < 0) {
+    std::cerr << "mon_command erasure-code-profile set failed with " << ret << std::endl;
+    exit(1);
+  }
+  //std::cout << outs << std::endl;
+
+  outs.clear();
+  ret = cluster.mon_command(
+    "{\"prefix\": \"osd pool create\", \"pool\": \"" + pool_name + "\", \"pool_type\":\"erasure\", \"pg_num\":12, \"pgp_num\":12, \"erasure_code_profile\":\"testprofile\"}",
+    inbl, NULL, &outs);
+  if (ret < 0) {
+    std::cerr << outs << std::endl;
+    std::cerr << "mon_command create pool failed with " << ret << std::endl;
+    exit(1);
+  }
+  //std::cout << outs << std::endl;
+
+  cluster.wait_for_latest_osdmap();
+  test_loop(cluster, pool_name, obj_name);
+  return;
+}
+
 int main(int args, char **argv)
 {
-  if (args < 3) {
-    std::cerr << "Error: " << argv[0] << " pool_name obj_name" << std::endl;
+  if (args != 3 && args != 4) {
+    std::cerr << "Error: " << argv[0] << " [ec|rep] pool_name obj_name" << std::endl;
     return 1;
   }
 
-  std::string pool_name(argv[1]);
-  std::string obj_name(argv[2]);
+  std::string pool_name, obj_name, type;
+  // For backward compatibility with unmodified teuthology version
+  if (args == 3) {
+    type = "rep";
+    pool_name = argv[1];
+    obj_name = argv[2];
+  } else {
+    type = argv[1];
+    pool_name = argv[2];
+    obj_name = argv[3];
+  }
+  std::cerr << "Test type " << type << std::endl;
   std::cerr << "pool_name, obj_name are " << pool_name << ", " << obj_name << std::endl;
 
+  if (type != "ec" && type != "rep") {
+    std::cerr << "Error: " << argv[0] << " Invalid arg must be 'ec' or 'rep' saw " << type << std::endl;
+    return 1;
+  }
+
   char *id = getenv("CEPH_CLIENT_ID");
   if (id) std::cerr << "Client id is: " << id << std::endl;
   Rados cluster;
@@ -61,30 +150,11 @@ int main(int args, char **argv)
   }
   cluster.connect();
 
-  // May already exist
-  cluster.pool_create(pool_name.c_str());
-
-  IoCtx ioctx;
-  cluster.ioctx_create(pool_name.c_str(), ioctx);
-
-  ioctx.create(obj_name, false);
+  if (type == "rep")
+    test_replicated(cluster, pool_name, obj_name);
+  else if (type == "ec")
+    test_erasure(cluster, pool_name, obj_name);
 
-  
-  for (int i = 0; i < 10000; ++i) {
-    std::cerr << "Iteration " << i << std::endl;
-    uint64_t handle;
-    WatchNotifyTestCtx ctx;
-    ret = ioctx.watch(obj_name, 0, &handle, &ctx);
-    assert(!ret);
-    bufferlist bl2;
-    ret = ioctx.notify(obj_name, 0, bl2);
-    assert(!ret);
-    TestAlarm alarm;
-    sem_wait(&sem);
-    ioctx.unwatch(obj_name, handle);
-  }
-
-  ioctx.close();
   sem_destroy(&sem);
   return 0;
 }
diff --git a/src/test/osd/RadosModel.h b/src/test/osd/RadosModel.h
index f199d03..5bb8d2e 100644
--- a/src/test/osd/RadosModel.h
+++ b/src/test/osd/RadosModel.h
@@ -174,14 +174,14 @@ public:
   const uint64_t min_stride_size;
   const uint64_t max_stride_size;
   AttrGenerator attr_gen;
-  const bool ec_pool;
+  const bool no_omap;
 	
   RadosTestContext(const string &pool_name, 
 		   int max_in_flight,
 		   uint64_t max_size,
 		   uint64_t min_stride_size,
 		   uint64_t max_stride_size,
-		   bool ec_pool,
+		   bool no_omap,
 		   const char *id = 0) :
     state_lock("Context Lock"),
     pool_obj_cont(),
@@ -195,7 +195,7 @@ public:
     max_size(max_size), 
     min_stride_size(min_stride_size), max_stride_size(max_stride_size),
     attr_gen(2000),
-    ec_pool(ec_pool)
+    no_omap(no_omap)
   {
   }
 
@@ -523,11 +523,11 @@ public:
 	  done = true;
 	  return;
 	}
-	if (!context->ec_pool) {
+	if (!context->no_omap) {
 	  op.omap_rm_keys(to_remove);
 	}
       } else {
-	if (!context->ec_pool) {
+	if (!context->no_omap) {
 	  op.omap_clear();
 	}
 	for (map<string, ContDesc>::iterator i = obj.attrs.begin();
@@ -621,7 +621,7 @@ public:
       omap_contents[key] = val_buffer;
       op.setxattr(key.c_str(), val_buffer);
     }
-    if (!context->ec_pool) {
+    if (!context->no_omap) {
       op.omap_set_header(header);
       op.omap_set(omap_contents);
     }
@@ -999,7 +999,7 @@ public:
 	omap_requested_keys.insert(key);
       }
     }
-    if (!context->ec_pool) {
+    if (!context->no_omap) {
       op.omap_get_vals_by_keys(omap_requested_keys, &omap_returned_values, 0);
 
       op.omap_get_keys("", -1, &omap_keys, 0);
@@ -1060,7 +1060,7 @@ public:
       }
 
       // Attributes
-      if (!context->ec_pool) {
+      if (!context->no_omap) {
 	if (!(old_value.header == header)) {
 	  cerr << num << ": oid " << oid << " header does not match, old size: "
 	       << old_value.header.length() << " new size " << header.length()
@@ -1093,7 +1093,7 @@ public:
 	   ++iter) {
 	bufferlist bl = context->attr_gen.gen_bl(
 	  iter->second);
-	if (!context->ec_pool) {
+	if (!context->no_omap) {
 	  map<string, bufferlist>::iterator omap_iter = omap.find(iter->first);
 	  assert(omap_iter != omap.end());
 	  assert(bl.length() == omap_iter->second.length());
@@ -1114,7 +1114,7 @@ public:
 	  assert(*j == *k);
 	}
       }
-      if (!context->ec_pool) {
+      if (!context->no_omap) {
 	for (set<string>::iterator i = omap_requested_keys.begin();
 	     i != omap_requested_keys.end();
 	     ++i) {
@@ -1305,8 +1305,8 @@ public:
 	     const string &_oid,
 	     TestOpStat *stat = 0)
     : TestOp(n, context, stat),
-      oid(_oid),
-      roll_back_to(-1), done(false)
+      oid(_oid), roll_back_to(-1), 
+      done(false), comp(NULL)
   {}
 
   void _begin()
@@ -1398,7 +1398,8 @@ public:
 	     TestOpStat *stat)
     : TestOp(n, context, stat),
       oid(oid), oid_src(oid_src),
-      comp(NULL), done(0), version(0), r(0)
+      comp(NULL), snap(-1), done(0), 
+      version(0), r(0)
   {}
 
   void _begin()
diff --git a/src/test/osd/TestRados.cc b/src/test/osd/TestRados.cc
index 02e7735..15c8ff7 100644
--- a/src/test/osd/TestRados.cc
+++ b/src/test/osd/TestRados.cc
@@ -262,6 +262,7 @@ int main(int argc, char **argv)
   map<TestOpType, unsigned int> op_weights;
   string pool_name = "data";
   bool ec_pool = false;
+  bool no_omap = false;
 
   for (int i = 1; i < argc; ++i) {
     if (strcmp(argv[i], "--max-ops") == 0)
@@ -280,12 +281,15 @@ int main(int argc, char **argv)
       min_stride_size = atoi(argv[++i]);
     else if (strcmp(argv[i], "--max-stride-size") == 0)
       max_stride_size = atoi(argv[++i]);
+    else if (strcmp(argv[i], "--no-omap") == 0)
+      no_omap = true;
     else if (strcmp(argv[i], "--ec-pool") == 0) {
       if (!op_weights.empty()) {
 	cerr << "--ec-pool must be specified prior to any ops" << std::endl;
 	exit(1);
       }
       ec_pool = true;
+      no_omap = true;
     } else if (strcmp(argv[i], "--op") == 0) {
       i++;
       int j;
@@ -363,7 +367,7 @@ int main(int argc, char **argv)
     size,
     min_stride_size,
     max_stride_size,
-    ec_pool,
+    no_omap,
     id);
 
   TestOpStat stats;
diff --git a/src/test/osd/osd-test-helpers.sh b/src/test/osd/osd-test-helpers.sh
index 341c171..5117ae3 100644
--- a/src/test/osd/osd-test-helpers.sh
+++ b/src/test/osd/osd-test-helpers.sh
@@ -38,6 +38,7 @@ function run_osd() {
     ceph_args+=" --osd-data=$osd_data"
     ceph_args+=" --chdir="
     ceph_args+=" --run-dir=$dir"
+    ceph_args+=" --debug-osd=20"
     ceph_args+=" --log-file=$dir/osd-\$id.log"
     ceph_args+=" --pid-file=$dir/osd-\$id.pidfile"
     ceph_args+=" "
diff --git a/src/test/osdc/FakeWriteback.cc b/src/test/osdc/FakeWriteback.cc
index b4cd35e..7c678cf 100644
--- a/src/test/osdc/FakeWriteback.cc
+++ b/src/test/osdc/FakeWriteback.cc
@@ -68,7 +68,7 @@ void FakeWriteback::read(const object_t& oid,
   m_finisher->queue(wrapper, len);
 }
 
-tid_t FakeWriteback::write(const object_t& oid,
+ceph_tid_t FakeWriteback::write(const object_t& oid,
 			   const object_locator_t& oloc,
 			   uint64_t off, uint64_t len,
 			   const SnapContext& snapc,
diff --git a/src/test/osdc/FakeWriteback.h b/src/test/osdc/FakeWriteback.h
index e7d6dc1..2b7fbd6 100644
--- a/src/test/osdc/FakeWriteback.h
+++ b/src/test/osdc/FakeWriteback.h
@@ -22,10 +22,11 @@ public:
 		    bufferlist *pbl, uint64_t trunc_size,  __u32 trunc_seq,
 		    Context *onfinish);
 
-  virtual tid_t write(const object_t& oid, const object_locator_t& oloc,
-		      uint64_t off, uint64_t len, const SnapContext& snapc,
-		      const bufferlist &bl, utime_t mtime, uint64_t trunc_size,
-		      __u32 trunc_seq, Context *oncommit);
+  virtual ceph_tid_t write(const object_t& oid, const object_locator_t& oloc,
+		           uint64_t off, uint64_t len,
+			   const SnapContext& snapc, const bufferlist &bl,
+			   utime_t mtime, uint64_t trunc_size,
+			   __u32 trunc_seq, Context *oncommit);
 
   virtual bool may_copy_on_write(const object_t&, uint64_t, uint64_t, snapid_t);
 private:
diff --git a/src/test/system/rados_list_parallel.cc b/src/test/system/rados_list_parallel.cc
index d530c83..5fc4bfb 100644
--- a/src/test/system/rados_list_parallel.cc
+++ b/src/test/system/rados_list_parallel.cc
@@ -326,6 +326,15 @@ int main(int argc, const char **argv)
     }
   }
 
+  rados_t cl;
+  rados_create(&cl, NULL);
+  rados_conf_parse_argv(cl, argc, argv);
+  rados_conf_parse_argv(cl, argc, argv);
+  rados_conf_read_file(cl, NULL);
+  rados_conf_parse_env(cl, NULL);
+  rados_connect(cl);
+  rados_pool_delete(cl, pool.c_str());
+
   printf("******* SUCCESS **********\n"); 
   return EXIT_SUCCESS;
 }
diff --git a/src/test/test_filejournal.cc b/src/test/test_filejournal.cc
index 3691fa6..e50e5dc 100644
--- a/src/test/test_filejournal.cc
+++ b/src/test/test_filejournal.cc
@@ -72,7 +72,9 @@ int main(int argc, char **argv) {
   finisher = new Finisher(g_ceph_context);
   
   if (!args.empty()) {
-    strcpy(path, args[0]);
+    size_t copy_len = std::min(sizeof(path)-1, strlen(args[0]));
+    strncpy(path, args[0], copy_len);
+    path[copy_len] = '\0';
   } else {
     srand(getpid()+time(0));
     snprintf(path, sizeof(path), "/tmp/ceph_test_filejournal.tmp.%d", rand());
diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am
index 0a386cc..6078eb4 100644
--- a/src/tools/Makefile.am
+++ b/src/tools/Makefile.am
@@ -1,25 +1,25 @@
-ceph_osdomap_tool_SOURCES = tools/ceph-osdomap-tool.cc
+ceph_osdomap_tool_SOURCES = tools/ceph_osdomap_tool.cc
 ceph_osdomap_tool_LDADD = $(LIBOS) $(CEPH_GLOBAL) $(BOOST_PROGRAM_OPTIONS_LIBS)
 bin_DEBUGPROGRAMS += ceph-osdomap-tool
 
-ceph_monstore_tool_SOURCES = tools/ceph-monstore-tool.cc
+ceph_monstore_tool_SOURCES = tools/ceph_monstore_tool.cc
 ceph_monstore_tool_LDADD = $(LIBOS) $(CEPH_GLOBAL) $(BOOST_PROGRAM_OPTIONS_LIBS)
 bin_DEBUGPROGRAMS += ceph-monstore-tool
 
-ceph_kvstore_tool_SOURCES = tools/ceph-kvstore-tool.cc
+ceph_kvstore_tool_SOURCES = tools/ceph_kvstore_tool.cc
 ceph_kvstore_tool_LDADD = $(LIBOS) $(CEPH_GLOBAL)
 ceph_kvstore_tool_CXXFLAGS = $(UNITTEST_CXXFLAGS)
 bin_DEBUGPROGRAMS += ceph-kvstore-tool
 
 
-ceph_filestore_tool_SOURCES = tools/ceph-filestore-tool.cc
+ceph_filestore_tool_SOURCES = tools/ceph_filestore_tool.cc
 ceph_filestore_tool_LDADD = $(LIBOSD) $(LIBOS) $(CEPH_GLOBAL) -lboost_program_options
 if LINUX
 ceph_filestore_tool_LDADD += -ldl
 endif # LINUX
 bin_PROGRAMS += ceph_filestore_tool
 
-ceph_filestore_dump_SOURCES = tools/ceph-filestore-dump.cc
+ceph_filestore_dump_SOURCES = tools/ceph_filestore_dump.cc
 ceph_filestore_dump_LDADD = $(LIBOSD) $(LIBOS) $(CEPH_GLOBAL) $(BOOST_PROGRAM_OPTIONS_LIBS)
 if LINUX
 ceph_filestore_dump_LDADD += -ldl
@@ -58,6 +58,10 @@ ceph_radosacl_SOURCES = tools/radosacl.cc
 ceph_radosacl_LDADD = $(LIBRADOS) $(CEPH_GLOBAL)
 bin_DEBUGPROGRAMS += ceph_radosacl
 
+ceph_client_debug_SOURCES = tools/ceph-client-debug.cc
+ceph_client_debug_LDADD = $(LIBCEPHFS) $(CEPH_GLOBAL) $(LIBCOMMON)
+bin_DEBUGPROGRAMS += ceph-client-debug
+
 rados_SOURCES = \
 	tools/rados/rados.cc \
 	tools/rados/rados_import.cc \
diff --git a/src/tools/ceph-client-debug.cc b/src/tools/ceph-client-debug.cc
new file mode 100644
index 0000000..2ed9332
--- /dev/null
+++ b/src/tools/ceph-client-debug.cc
@@ -0,0 +1,179 @@
+// -*- 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) 2004-2006 Sage Weil <sage at newdream.net>
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation.  See file COPYING.
+ *
+ */
+
+
+#include "common/ceph_argparse.h"
+#include "global/global_init.h"
+#include "common/Formatter.h"
+#include "common/debug.h"
+#include "common/errno.h"
+#include "client/Inode.h"
+#include "client/Dentry.h"
+#include "client/Dir.h"
+#include "include/cephfs/libcephfs.h"
+
+#define dout_subsys ceph_subsys_client
+
+void usage()
+{
+  std::cout << "Usage: ceph-client-debug [options] <inode number>" << std::endl;
+  generic_client_usage();
+}
+
+
+/**
+ * Given an inode, look up the path from the Client cache: assumes
+ * client cache is fully populated.
+ */
+void traverse_dentries(Inode *ino, std::vector<Dentry*> &parts)
+{
+  if (ino->dn_set.empty()) {
+    return;
+  }
+  
+  Dentry* dn = *(ino->dn_set.begin());
+  parts.push_back(dn);
+  traverse_dentries(dn->dir->parent_inode, parts);
+}
+
+
+/**
+ * Given an inode, send lookup requests to the MDS for
+ * all its ancestors, such that the full trace will be
+ * populated in client cache.
+ */
+int lookup_trace(ceph_mount_info *client, inodeno_t const ino)
+{
+  Inode *inode;
+  int r = ceph_ll_lookup_inode(client, ino, &inode);
+  if (r != 0) {
+    return r;
+  } else {
+    if (!inode->dn_set.empty()) {
+      Dentry *dn = *(inode->dn_set.begin());
+      assert(dn->dir);
+      assert(dn->dir->parent_inode);
+      r = lookup_trace(client, dn->dir->parent_inode->ino);
+      if (r) {
+        return r;
+      }
+    } else {
+      // We reached the root of the tree
+      assert(inode->ino == CEPH_INO_ROOT);
+    }
+  }
+
+  return r;
+}
+
+
+int main(int argc, const char **argv)
+{
+  // Argument handling
+  vector<const char*> args;
+  argv_to_vec(argc, argv, args);
+  env_to_vec(args);
+
+  global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY,
+	      CINIT_FLAG_UNPRIVILEGED_DAEMON_DEFAULTS);
+  
+  common_init_finish(g_ceph_context);
+
+  // Expect exactly one positional argument (inode number)
+  if (args.size() != 1) {
+    usage();
+  }
+  char const *inode_str = args[0];
+  inodeno_t inode = strtoll(inode_str, NULL, 0);
+  if (inode <= 0) {
+    derr << "Invalid inode: " << inode_str << dendl;
+    return -1;
+  }
+
+  // Initialize filesystem client
+  struct ceph_mount_info *client;
+  int r = ceph_create_with_context(&client, g_ceph_context);
+  if (r) {
+    derr << "Error initializing libcephfs: " << cpp_strerror(r) << dendl;
+    return r;
+  }
+
+  r = ceph_mount(client, "/");
+  if (r) {
+    derr << "Error mounting: " << cpp_strerror(r) << dendl;
+    ceph_shutdown(client);
+    return r;
+  }
+
+
+  // Populate client cache with inode of interest & ancestors
+  r = lookup_trace(client, inode);
+  if (r) {
+    derr << "Error looking up inode " << std::hex << inode << std::dec <<
+      ": " << cpp_strerror(r) << dendl;
+    return -1;
+  }
+
+  // Retrieve inode of interest
+  struct vinodeno_t vinode;
+  vinode.ino = inode;
+  vinode.snapid = CEPH_NOSNAP;
+  Inode *ino = ceph_ll_get_inode(client, vinode);
+
+  // Retrieve dentry trace
+  std::vector<Dentry*> path;
+  traverse_dentries(ino, path);
+  
+  // Print inode and path as a JSON object
+  JSONFormatter jf(true);
+  jf.open_object_section("client_debug");
+  {
+    jf.open_object_section("inode");
+    {
+      ino->dump(&jf);
+    }
+    jf.close_section(); // inode
+    jf.open_array_section("path");
+    {
+      for (std::vector<Dentry*>::reverse_iterator p = path.rbegin(); p != path.rend(); ++p) {
+        jf.open_object_section("dentry");
+        {
+          (*p)->dump(&jf);
+        }
+        jf.close_section(); // dentry
+      }
+    }
+    jf.close_section(); // path
+  }
+  jf.close_section(); // client_debug
+  jf.flush(std::cout);
+  std::cout << std::endl;
+
+  // Release Inode references
+  ceph_ll_forget(client, ino, 1);
+  for (std::vector<Dentry*>::reverse_iterator p = path.rbegin(); p != path.rend(); ++p) {
+    ceph_ll_forget(client, (*p)->inode, 1);
+  }
+  ino = NULL;
+  path.clear();  
+
+  // Shut down
+  r = ceph_unmount(client);
+  if (r) {
+    derr << "Error mounting: " << cpp_strerror(r) << dendl;
+  }
+  ceph_shutdown(client);
+  
+  return r;
+}
diff --git a/src/tools/ceph_conf.cc b/src/tools/ceph_conf.cc
index 14045f9..09bbc56 100644
--- a/src/tools/ceph_conf.cc
+++ b/src/tools/ceph_conf.cc
@@ -158,8 +158,8 @@ int main(int argc, const char **argv)
   env_to_vec(args);
   vector<const char*> orig_args = args;
 
-  global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_DAEMON,
-	      CINIT_FLAG_NO_DAEMON_ACTIONS);
+  global_pre_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_DAEMON,
+		  CINIT_FLAG_NO_DAEMON_ACTIONS);
 
   // do not common_init_finish(); do not start threads; do not do any of thing
   // wonky things the daemon whose conf we are examining would do (like initialize
diff --git a/src/tools/ceph-filestore-dump.cc b/src/tools/ceph_filestore_dump.cc
similarity index 90%
rename from src/tools/ceph-filestore-dump.cc
rename to src/tools/ceph_filestore_dump.cc
index 6c8b309..87a8387 100644
--- a/src/tools/ceph-filestore-dump.cc
+++ b/src/tools/ceph_filestore_dump.cc
@@ -164,43 +164,64 @@ struct footer {
 };
 
 struct pg_begin {
-  pg_t pgid;
+  spg_t pgid;
   OSDSuperblock superblock;
 
-  pg_begin(pg_t pg, OSDSuperblock sb):
+  pg_begin(spg_t pg, const OSDSuperblock& sb):
     pgid(pg), superblock(sb) { }
   pg_begin() { }
 
   void encode(bufferlist& bl) const {
-    // New super_ver prevents decode from ver 1
-    ENCODE_START(2, 2, bl);
-    ::encode(pgid, bl);
+    // If superblock doesn't include CEPH_FS_FEATURE_INCOMPAT_SHARDS then
+    // shard will be NO_SHARD for a replicated pool.  This means
+    // that we allow the decode by struct_v 2.
+    ENCODE_START(3, 2, bl);
+    ::encode(pgid.pgid, bl);
     ::encode(superblock, bl);
+    ::encode(pgid.shard, bl);
     ENCODE_FINISH(bl);
   }
+  // NOTE: New super_ver prevents decode from ver 1
   void decode(bufferlist::iterator& bl) {
-    DECODE_START(2, bl);
-    ::decode(pgid, bl);
+    DECODE_START(3, bl);
+    ::decode(pgid.pgid, bl);
     if (struct_v > 1) {
       ::decode(superblock, bl);
     }
+    if (struct_v > 2) {
+      ::decode(pgid.shard, bl);
+    } else {
+      pgid.shard = ghobject_t::NO_SHARD;
+    }
     DECODE_FINISH(bl);
   }
 };
 
 struct object_begin {
-  hobject_t hoid;
-  object_begin(const hobject_t &hoid): hoid(hoid) { }
+  ghobject_t hoid;
+  object_begin(const ghobject_t &hoid): hoid(hoid) { }
   object_begin() { }
 
+  // If superblock doesn't include CEPH_FS_FEATURE_INCOMPAT_SHARDS then
+  // generation will be NO_GEN, shard_id will be NO_SHARD for a replicated
+  // pool.  This means we will allow the decode by struct_v 1.
   void encode(bufferlist& bl) const {
-    ENCODE_START(1, 1, bl);
-    ::encode(hoid, bl);
+    ENCODE_START(2, 1, bl);
+    ::encode(hoid.hobj, bl);
+    ::encode(hoid.generation, bl);
+    ::encode(hoid.shard_id, bl);
     ENCODE_FINISH(bl);
   }
   void decode(bufferlist::iterator& bl) {
-    DECODE_START(1, bl);
-    ::decode(hoid, bl);
+    DECODE_START(2, bl);
+    ::decode(hoid.hobj, bl);
+    if (struct_v > 1) {
+      ::decode(hoid.generation, bl);
+      ::decode(hoid.shard_id, bl);
+    } else {
+      hoid.generation = ghobject_t::NO_GEN;
+      hoid.shard_id = ghobject_t::NO_SHARD;
+    }
     DECODE_FINISH(bl);
   }
 };
@@ -354,7 +375,7 @@ static void invalid_path(string &path)
   exit(1);
 }
 
-int get_log(ObjectStore *fs, coll_t coll, pg_t pgid, const pg_info_t &info,
+int get_log(ObjectStore *fs, coll_t coll, spg_t pgid, const pg_info_t &info,
    PGLog::IndexedLog &log, pg_missing_t &missing)
 { 
   map<eversion_t, hobject_t> divergent_priors;
@@ -397,7 +418,6 @@ void remove_coll(ObjectStore *store, const coll_t &coll)
 	 i != objects.end();
 	 ++i, ++num) {
 
-      assert(i->generation == ghobject_t::NO_GEN);
       OSDriver::OSTransaction _t(driver.get_transaction(t));
       cout << "remove " << *i << std::endl;
       int r = mapper.remove_oid(i->hobj, &_t);
@@ -462,18 +482,17 @@ int finish_remove_pgs(ObjectStore *store, uint64_t *next_removal_seq)
   return 0;
 }
 
-int initiate_new_remove_pg(ObjectStore *store, pg_t r_pgid,
+int initiate_new_remove_pg(ObjectStore *store, spg_t r_pgid,
     uint64_t *next_removal_seq)
 {
   ObjectStore::Transaction *rmt = new ObjectStore::Transaction;
 
-  if (store->collection_exists(coll_t(spg_t(r_pgid, ghobject_t::no_shard())))) {
-      coll_t to_remove = coll_t::make_removal_coll((*next_removal_seq)++,
-        spg_t(r_pgid, ghobject_t::no_shard()));
-      cout << "collection rename " << coll_t(spg_t(r_pgid, ghobject_t::no_shard()))
+  if (store->collection_exists(coll_t(r_pgid))) {
+      coll_t to_remove = coll_t::make_removal_coll((*next_removal_seq)++, r_pgid);
+      cout << "collection rename " << coll_t(r_pgid)
 	   << " to " << to_remove
         << std::endl;
-      rmt->collection_rename(coll_t(spg_t(r_pgid, ghobject_t::no_shard())), to_remove);
+      rmt->collection_rename(coll_t(r_pgid), to_remove);
   } else {
     delete rmt;
     return ENOENT;
@@ -563,20 +582,18 @@ int write_pg(ObjectStore::Transaction &t, epoch_t epoch, pg_info_t &info,
   return 0;
 }
 
-int export_file(ObjectStore *store, coll_t cid, hobject_t &obj)
+int export_file(ObjectStore *store, coll_t cid, ghobject_t &obj)
 {
   struct stat st;
   mysize_t total;
-  ostringstream objname;
   footer ft;
 
   int ret = store->stat(cid, obj, &st);
   if (ret < 0)
     return ret;
 
-  objname << obj;
-  if (debug && file_fd != STDOUT_FILENO)
-    cout << "objname=" << objname.str() << std::endl;
+  if (file_fd != STDOUT_FILENO)
+    cout << "read " << obj << std::endl;
 
   total = st.st_size;
   if (debug && file_fd != STDOUT_FILENO)
@@ -669,8 +686,7 @@ int export_files(ObjectStore *store, coll_t coll)
     for (vector<ghobject_t>::iterator i = objects.begin();
 	 i != objects.end();
 	 ++i) {
-      assert(i->generation == ghobject_t::NO_GEN);
-      r = export_file(store, coll, i->hobj);
+      r = export_file(store, coll, *i);
       if (r < 0)
         return r;
     }
@@ -701,12 +717,15 @@ void write_super()
   superbl.write_fd(file_fd);
 }
 
-int do_export(ObjectStore *fs, coll_t coll, pg_t pgid, pg_info_t &info,
-    epoch_t map_epoch, __u8 struct_ver, OSDSuperblock superblock)
+int do_export(ObjectStore *fs, coll_t coll, spg_t pgid, pg_info_t &info,
+    epoch_t map_epoch, __u8 struct_ver, const OSDSuperblock& superblock)
 {
   PGLog::IndexedLog log;
   pg_missing_t missing;
 
+  if (file_fd != STDOUT_FILENO)
+    cout << "Exporting " << pgid << std::endl;
+
   int ret = get_log(fs, coll, pgid, info, log, missing);
   if (ret > 0)
       return ret;
@@ -718,7 +737,12 @@ int do_export(ObjectStore *fs, coll_t coll, pg_t pgid, pg_info_t &info,
   if (ret)
     return ret;
 
-  export_files(fs, coll);
+  ret = export_files(fs, coll);
+  if (ret) {
+    if (file_fd != STDOUT_FILENO)
+      cout << "export_files error " << ret << std::endl;
+    return ret;
+  }
 
   metadata_section ms(struct_ver, map_epoch, info, log);
   ret = write_section(TYPE_PG_METADATA, ms, file_fd);
@@ -777,7 +801,7 @@ int read_section(int fd, sectiontype_t *type, bufferlist *bl)
   return 0;
 }
 
-int get_data(ObjectStore *store, coll_t coll, hobject_t hoid,
+int get_data(ObjectStore *store, coll_t coll, ghobject_t hoid,
     ObjectStore::Transaction *t, bufferlist &bl)
 {
   bufferlist::iterator ebliter = bl.begin();
@@ -790,7 +814,7 @@ int get_data(ObjectStore *store, coll_t coll, hobject_t hoid,
   return 0;
 }
 
-int get_attrs(ObjectStore *store, coll_t coll, hobject_t hoid,
+int get_attrs(ObjectStore *store, coll_t coll, ghobject_t hoid,
     ObjectStore::Transaction *t, bufferlist &bl,
     OSDriver &driver, SnapMapper &snap_mapper)
 {
@@ -802,7 +826,7 @@ int get_attrs(ObjectStore *store, coll_t coll, hobject_t hoid,
     cout << "\tattrs: len " << as.data.size() << std::endl;
   t->setattrs(coll, hoid, as.data);
 
-  if (hoid.snap < CEPH_MAXSNAP) {
+  if (hoid.hobj.snap < CEPH_MAXSNAP && hoid.generation == ghobject_t::NO_GEN) {
     map<string,bufferptr>::iterator mi = as.data.find(OI_ATTR);
     if (mi != as.data.end()) {
       bufferlist attr_bl;
@@ -814,14 +838,14 @@ int get_attrs(ObjectStore *store, coll_t coll, hobject_t hoid,
   
       OSDriver::OSTransaction _t(driver.get_transaction(t));
       set<snapid_t> oi_snaps(oi.snaps.begin(), oi.snaps.end());
-      snap_mapper.add_oid(hoid, oi_snaps, &_t);
+      snap_mapper.add_oid(hoid.hobj, oi_snaps, &_t);
     }
   }
 
   return 0;
 }
 
-int get_omap_hdr(ObjectStore *store, coll_t coll, hobject_t hoid,
+int get_omap_hdr(ObjectStore *store, coll_t coll, ghobject_t hoid,
     ObjectStore::Transaction *t, bufferlist &bl)
 {
   bufferlist::iterator ebliter = bl.begin();
@@ -835,7 +859,7 @@ int get_omap_hdr(ObjectStore *store, coll_t coll, hobject_t hoid,
   return 0;
 }
 
-int get_omap(ObjectStore *store, coll_t coll, hobject_t hoid,
+int get_omap(ObjectStore *store, coll_t coll, ghobject_t hoid,
     ObjectStore::Transaction *t, bufferlist &bl)
 {
   bufferlist::iterator ebliter = bl.begin();
@@ -865,11 +889,7 @@ int get_object(ObjectStore *store, coll_t coll, bufferlist &bl)
 
   t->touch(coll, ob.hoid);
 
-  if (debug) {
-    ostringstream objname;
-    objname << ob.hoid.oid;
-    cout << "name " << objname.str() << " snap " << ob.hoid.snap << std::endl;
-  }
+  cout << "Write " << ob.hoid << std::endl;
 
   bufferlist ebl;
   bool done = false;
@@ -949,7 +969,7 @@ int get_pg_metadata(ObjectStore *store, coll_t coll, bufferlist &bl)
   return 0;
 }
 
-int do_import(ObjectStore *store, OSDSuperblock sb)
+int do_import(ObjectStore *store, OSDSuperblock& sb)
 {
   bufferlist ebl;
   pg_info_t info;
@@ -975,6 +995,8 @@ int do_import(ObjectStore *store, OSDSuperblock sb)
   //First section must be TYPE_PG_BEGIN
   sectiontype_t type;
   ret = read_section(file_fd, &type, &ebl);
+  if (ret)
+    return ret;
   if (type != TYPE_PG_BEGIN) {
     return EFAULT;
   }
@@ -982,7 +1004,7 @@ int do_import(ObjectStore *store, OSDSuperblock sb)
   bufferlist::iterator ebliter = ebl.begin();
   pg_begin pgb;
   pgb.decode(ebliter);
-  pg_t pgid = pgb.pgid;
+  spg_t pgid = pgb.pgid;
 
   if (debug) {
     cout << "Exported features: " << pgb.superblock.compat_features << std::endl;
@@ -993,11 +1015,11 @@ int do_import(ObjectStore *store, OSDSuperblock sb)
     return 1;
   }
 
-  log_oid = OSD::make_pg_log_oid(spg_t(pgid, ghobject_t::no_shard()));
-  biginfo_oid = OSD::make_pg_biginfo_oid(spg_t(pgid, ghobject_t::no_shard()));
+  log_oid = OSD::make_pg_log_oid(pgid);
+  biginfo_oid = OSD::make_pg_biginfo_oid(pgid);
 
   //Check for PG already present.
-  coll_t coll(spg_t(pgid, ghobject_t::no_shard()));
+  coll_t coll(pgid);
   if (store->collection_exists(coll)) {
     cout << "pgid " << pgid << " already exists" << std::endl;
     return 1;
@@ -1005,8 +1027,7 @@ int do_import(ObjectStore *store, OSDSuperblock sb)
 
   //Switch to collection which will be removed automatically if
   //this program is interupted.
-  coll_t rmcoll = coll_t::make_removal_coll(
-    next_removal_seq, spg_t(pgid, ghobject_t::no_shard()));
+  coll_t rmcoll = coll_t::make_removal_coll(next_removal_seq, pgid);
   ObjectStore::Transaction *t = new ObjectStore::Transaction;
   t->create_collection(rmcoll);
   store->apply_transaction(*t);
@@ -1065,9 +1086,9 @@ int main(int argc, char **argv)
     ("journal-path", po::value<string>(&jpath),
      "path to journal, mandatory")
     ("pgid", po::value<string>(&pgidstr),
-     "PG id, mandatory")
+     "PG id, mandatory except for import")
     ("type", po::value<string>(&type),
-     "Type one of info, log, remove, export, or import, mandatory")
+     "Arg is one of [info, log, remove, export, or import], mandatory")
     ("file", po::value<string>(&file),
      "path of file to export or import")
     ("debug", "Enable diagnostic output to stderr")
@@ -1202,7 +1223,7 @@ int main(int argc, char **argv)
     invalid_path(fspath);
   }
 
-  pg_t pgid;
+  spg_t pgid;
   if (pgidstr.length() && !pgid.parse(pgidstr.c_str())) {
     cout << "Invalid pgid '" << pgidstr << "' specified" << std::endl;
     exit(1);
@@ -1236,8 +1257,8 @@ int main(int argc, char **argv)
   bufferlist bl;
   OSDSuperblock superblock;
   bufferlist::iterator p;
-  ret = fs->read(coll_t::META_COLL, OSD_SUPERBLOCK_POBJECT, 0, 0, bl);
-  if (ret < 0) {
+  r = fs->read(coll_t::META_COLL, OSD_SUPERBLOCK_POBJECT, 0, 0, bl);
+  if (r < 0) {
     cout << "Failure to read OSD superblock error= " << r << std::endl;
     goto out;
   }
@@ -1289,11 +1310,13 @@ int main(int argc, char **argv)
     if (ret == EFAULT) {
       cout << "Corrupt input for import" << std::endl;
     }
+    if (ret == 0)
+      cout << "Import successful" << std::endl;
     goto out;
   }
 
-  log_oid = OSD::make_pg_log_oid(spg_t(pgid, ghobject_t::no_shard()));
-  biginfo_oid = OSD::make_pg_biginfo_oid(spg_t(pgid, ghobject_t::no_shard()));
+  log_oid = OSD::make_pg_log_oid(pgid);
+  biginfo_oid = OSD::make_pg_biginfo_oid(pgid);
 
   if (type == "remove") {
     uint64_t next_removal_seq = 0;	//My local seq
@@ -1323,7 +1346,7 @@ int main(int argc, char **argv)
       continue;
     }
 
-    if (tmppgid.pgid != pgid) {
+    if (tmppgid != pgid) {
       continue;
     }
     if (snap != CEPH_NOSNAP && debug) {
@@ -1346,10 +1369,9 @@ int main(int argc, char **argv)
     if (debug)
       cerr << "map_epoch " << map_epoch << std::endl;
 
-    pg_info_t info(spg_t(pgid, ghobject_t::no_shard()));
+    pg_info_t info(pgid);
     map<epoch_t,pg_interval_t> past_intervals;
-    hobject_t biginfo_oid = OSD::make_pg_biginfo_oid(
-      spg_t(pgid, ghobject_t::no_shard()));
+    hobject_t biginfo_oid = OSD::make_pg_biginfo_oid(pgid);
     interval_set<snapid_t> snap_collections;
   
     __u8 struct_ver;
@@ -1365,6 +1387,8 @@ int main(int argc, char **argv)
 
     if (type == "export") {
       ret = do_export(fs, coll, pgid, info, map_epoch, struct_ver, superblock);
+      if (ret == 0 && file_fd != STDOUT_FILENO)
+        cout << "Export successful" << std::endl;
     } else if (type == "info") {
       formatter->open_object_section("info");
       info.dump(formatter);
diff --git a/src/tools/ceph-filestore-tool.cc b/src/tools/ceph_filestore_tool.cc
similarity index 100%
rename from src/tools/ceph-filestore-tool.cc
rename to src/tools/ceph_filestore_tool.cc
diff --git a/src/tools/ceph-kvstore-tool.cc b/src/tools/ceph_kvstore_tool.cc
similarity index 100%
rename from src/tools/ceph-kvstore-tool.cc
rename to src/tools/ceph_kvstore_tool.cc
diff --git a/src/tools/ceph-monstore-tool.cc b/src/tools/ceph_monstore_tool.cc
similarity index 100%
rename from src/tools/ceph-monstore-tool.cc
rename to src/tools/ceph_monstore_tool.cc
diff --git a/src/tools/ceph-osdomap-tool.cc b/src/tools/ceph_osdomap_tool.cc
similarity index 100%
rename from src/tools/ceph-osdomap-tool.cc
rename to src/tools/ceph_osdomap_tool.cc
diff --git a/src/tools/rados/rados.cc b/src/tools/rados/rados.cc
index 9fb60d1..caed62b 100644
--- a/src/tools/rados/rados.cc
+++ b/src/tools/rados/rados.cc
@@ -93,11 +93,11 @@ void usage(ostream& out)
 "   load-gen [options]               generate load on the cluster\n"
 "   listomapkeys <obj-name>          list the keys in the object map\n"
 "   listomapvals <obj-name>          list the keys and vals in the object map \n"
-"   getomapval <obj-name> <key>      show the value for the specified key\n"
+"   getomapval <obj-name> <key> [file] show the value for the specified key\n"
 "                                    in the object's object map\n"
 "   setomapval <obj-name> <key> <val>\n"
 "   rmomapkey <obj-name> <key>\n"
-"   getomapheader <obj-name>\n"
+"   getomapheader <obj-name> [file]\n"
 "   setomapheader <obj-name> <val>\n"
 "   tmap-to-omap <obj-name>          convert tmap keys/values to omap\n"
 "   listwatchers <obj-name>          list the watchers of this object\n"
@@ -155,8 +155,6 @@ void usage(ostream& out)
 "   --snap name\n"
 "        select given snap name for (read) IO\n"
 "   -i infile\n"
-"   -o outfile\n"
-"        specify input or output file (for certain commands)\n"
 "   --create\n"
 "        create the pool or directory that was specified\n"
 "   -N namespace\n"
@@ -189,6 +187,31 @@ static void usage_exit()
   exit(1);
 }
 
+
+static int dump_data(std::string const &filename, bufferlist const &data)
+{
+  int fd;
+  if (filename == "-") {
+    fd = 1;
+  } else {
+    fd = TEMP_FAILURE_RETRY(::open(filename.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644));
+    if (fd < 0) {
+      int err = errno;
+      cerr << "failed to open file: " << cpp_strerror(err) << std::endl;
+      return -err;
+    }
+  }
+
+  int r = data.write_fd(fd);
+
+  if (fd != 1) {
+    VOID_TEMP_FAILURE_RETRY(::close(fd));
+  }
+
+  return r;
+}
+
+
 static int do_get(IoCtx& io_ctx, const char *objname, const char *outfile, unsigned op_size)
 {
   string oid(objname);
@@ -226,7 +249,7 @@ static int do_get(IoCtx& io_ctx, const char *objname, const char *outfile, unsig
 
  out:
   if (fd != 1)
-    TEMP_FAILURE_RETRY(::close(fd));
+    VOID_TEMP_FAILURE_RETRY(::close(fd));
   return ret;
 }
 
@@ -428,7 +451,7 @@ static int do_put(IoCtx& io_ctx, const char *objname, const char *infile, int op
   }
   ret = 0;
  out:
-  TEMP_FAILURE_RETRY(close(fd));
+  VOID_TEMP_FAILURE_RETRY(close(fd));
   delete[] buf;
   return ret;
 }
@@ -1669,6 +1692,10 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
       usage_exit();
 
     string oid(nargs[1]);
+    string outfile;
+    if (nargs.size() >= 3) {
+      outfile = nargs[2];
+    }
 
     bufferlist header;
     ret = io_ctx.omap_get_header(oid, &header);
@@ -1677,9 +1704,14 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
 	   << ": " << cpp_strerror(ret) << std::endl;
       goto out;
     } else {
-      cout << "header (" << header.length() << " bytes) :\n";
-      header.hexdump(cout);
-      cout << std::endl;
+      if (!outfile.empty()) {
+	cerr << "Writing to " << outfile << std::endl;
+	dump_data(outfile, header);
+      } else {
+	cout << "header (" << header.length() << " bytes) :\n";
+	header.hexdump(cout);
+	cout << std::endl;
+      }
       ret = 0;
     }
   } else if (strcmp(nargs[0], "setomapheader") == 0) {
@@ -1730,6 +1762,11 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
     set<string> keys;
     keys.insert(key);
 
+    std::string outfile;
+    if (nargs.size() >= 4) {
+      outfile = nargs[3];
+    }
+
     map<string, bufferlist> values;
     ret = io_ctx.omap_get_vals_by_keys(oid, keys, &values);
     if (ret < 0) {
@@ -1742,8 +1779,14 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
 
     if (values.size() && values.begin()->first == key) {
       cout << " (length " << values.begin()->second.length() << ") : ";
-      values.begin()->second.hexdump(cout);
-      cout << std::endl;
+      if (!outfile.empty()) {
+	cerr << "Writing to " << outfile << std::endl;
+	dump_data(outfile, values.begin()->second);
+      } else {
+	values.begin()->second.hexdump(cout);
+	cout << std::endl;
+      }
+      ret = 0;
     } else {
       cout << "No such key: " << pool_name << "/" << oid << "/" << key
 	   << std::endl;
diff --git a/src/tools/scratchtoolpp.cc b/src/tools/scratchtoolpp.cc
index 6209692..87074a6 100644
--- a/src/tools/scratchtoolpp.cc
+++ b/src/tools/scratchtoolpp.cc
@@ -41,8 +41,12 @@ public:
 
 void testradospp_milestone(void)
 {
+  int c;
   cout << "*** press enter to continue ***" << std::endl;
-  getchar();
+  while ((c = getchar()) != EOF) {
+    if (c == '\n')
+      break;
+  }
 }
 
 int main(int argc, const char **argv) 
diff --git a/src/vstart.sh b/src/vstart.sh
index 181f812..7132ad3 100755
--- a/src/vstart.sh
+++ b/src/vstart.sh
@@ -261,9 +261,9 @@ if [ "$start_all" -eq 1 ]; then
 fi
 $SUDO rm -f core*
 
-test -d out || mkdir out
-test -d dev || mkdir dev
-$SUDO rm -rf out/*
+test -d $CEPH_OUT_DIR || mkdir $CEPH_OUT_DIR
+test -d $CEPH_DEV_DIR || mkdir $CEPH_DEV_DIR
+$SUDO rm -rf $CEPH_OUT_DIR/*
 test -d gmon && $SUDO rm -rf gmon/*
 
 [ "$cephx" -eq 1 ] && [ "$new" -eq 1 ] && test -e $keyring_fn && rm $keyring_fn
@@ -328,6 +328,7 @@ if [ "$start_mon" -eq 1 ]; then
         osd crush chooseleaf type = 0
         osd pool default min size = 1
         osd pool default erasure code directory = .libs
+        osd pool default erasure code profile = plugin=jerasure technique=reed_sol_van k=2 m=1 ruleset-failure-domain=osd
         run dir = $CEPH_OUT_DIR
 EOF
 if [ "$cephx" -eq 1 ] ; then

-- 
Alioth's hooks/post-receive on /srv/git.debian.org/git/pkg-ceph/ceph.git



More information about the Pkg-ceph-commits mailing list