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

Dmitry Smirnov onlyjob at moszumanska.debian.org
Thu Oct 30 01:49:53 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 b2c1536 (upstream)
Author: Dmitry Smirnov <onlyjob at member.fsf.org>
Date:   Thu Oct 30 01:41:00 2014

    Imported Upstream version 0.87
---
 AUTHORS                                            |   2 +
 ChangeLog                                          |  45 ++++++-
 src/.git_version                                   |   2 +-
 src/Makefile.in                                    | 127 +++++++++++++++++--
 src/common/Timer.cc                                |   4 +
 src/common/buffer.cc                               |  91 ++++++++------
 src/common/shared_cache.hpp                        |  50 +++++---
 src/erasure-code/ErasureCode.cc                    |  71 +++++++----
 src/erasure-code/ErasureCode.h                     |   8 +-
 src/include/buffer.h                               |  15 ++-
 src/include/rados/buffer.h                         |  15 ++-
 src/java/native/libcephfs_jni.cc                   |  18 +--
 src/mds/InoTable.cc                                |   7 +-
 src/mds/Server.cc                                  |   1 +
 src/mon/Monitor.cc                                 |  15 ++-
 src/os/FDCache.h                                   |   6 +-
 src/os/FileStore.cc                                |   2 +-
 src/os/LevelDBStore.h                              |   5 +-
 src/os/RocksDBStore.h                              |   5 +-
 src/osd/PG.cc                                      |   8 +-
 src/osd/ReplicatedPG.cc                            |   2 +-
 src/osd/osd_types.cc                               |  53 ++++++--
 src/osd/osd_types.h                                |  19 +++
 src/osdc/ObjectCacher.cc                           |  28 +----
 src/osdc/ObjectCacher.h                            |   1 -
 src/osdc/Objecter.cc                               |  74 +++++++++---
 src/osdc/Objecter.h                                |  13 +-
 src/test/Makefile.am                               |   5 +
 src/test/bufferlist.cc                             |  46 +++++++
 src/test/common/test_shared_cache.cc               |  77 ++++++++++++
 src/test/erasure-code/Makefile.am                  |  14 ++-
 src/test/erasure-code/TestErasureCode.cc           | 134 +++++++++++++++++++++
 .../erasure-code/ceph_erasure_code_benchmark.cc    |   3 +
 33 files changed, 772 insertions(+), 194 deletions(-)

diff --git a/AUTHORS b/AUTHORS
index 830eb3c..87e1e08 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -84,6 +84,7 @@ Erwin, Brock A <Brock.Erwin at pnl.gov>
 Esteban Molina-Estolano <eestolan at lanl.gov>
 Evan Felix <evan.felix at pnnl.gov>
 fangdong <yp.fangdong at gmail.com>
+Federico Gimenez <fgimenez at coit.es>
 Federico Simoncelli <fsimonce at redhat.com>
 Filippos Giannakos <philipgian at grnet.gr>
 Florent Bautista <florent at coppint.com>
@@ -115,6 +116,7 @@ Ilya Dryomov <ilya.dryomov at inktank.com>
 James Page <james.page at ubuntu.com>
 James Ryan Cresawn <jrcresawn at gmail.com>
 Jan Harkes <jaharkes at cs.cmu.edu>
+Janne Grunau <j at jannau.net>
 Jason Dillaman <dillaman at redhat.com>
 Jenkins <jenkins at inktank.com>
 Jens-Christian Fischer <jens-christian.fischer at switch.ch>
diff --git a/ChangeLog b/ChangeLog
index d390985..cb5b916 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,40 @@
-87eb663 (HEAD, tag: v0.87) 0.87
+c51c8f9 (HEAD, tag: v0.87) 0.87
+eea9803 (origin/wip-enoent-race) os/LevelDBStore, RocksDBStore: fix race handling for get store size
+c4b2abd .gitmodules: ignoring changes in rocksdb submodule
+082416f (origin/wip-rbd-revert) Revert "Enforce cache size on read requests"
+544b9a8 Revert "rbd: ObjectCacher reads can hang when reading sparse files"
+3b1eafc Revert "Fix read performance regression in ObjectCacher"
+f76f83c (origin/wip-9873) osdc/Objecter: fix tick_event handling in shutdown vs tick race
+4848435 common/Timer: recheck stopping before sleep if we dropped the lock
+44a8d59 (origin/fix-fstat-mode) java: fill in stat structure correctly
+cb9262a (origin/wip-9806-giant) Objecter: resend linger ops on any interval change
+1a3ad30 ReplicatedPG: writeout hit_set object with correct prior_version
+95a0ee1 qa: use sudo when rsyncing /usr so we can read everything
+4128814 FDCache: purge hoid on clear
+3abbd4c shared_cache: add purge and tests
+c116b4b shared_cache::add: do not delete value if existed
+227ecd8 (origin/wip-9859) mon: Monitor: MMonGetMap doesn't require caps
+d9ff3a6 PG:: reset_interval_flush and in set_last_peering_reset
+a49d745 objecter: Unlock in shutdown before waiting for timer thread
+bc8fd49 erasure-code: use ErasureCode::SIMD_ALIGN in ceph_erasure_code_benchmark
+c894812 erasure-code: add ErasureCode::encode unit test
+0749a29 erasure-code: expose ErasureCode::SIMD_ALIGN as a const
+abc1cfb ceph_erasure_code_benchmark: use 32-byte aligned input
+fdeeeb1 erasure code: use 32-byte aligned buffers
+3ce0615 erasure code: use a function for the chunk mapping index
+6154339 common: add an aligned buffer with less alignment than a page
+681dad8 common: remove dead code in buffer.cc
+65be257 Fix read performance regression in ObjectCacher
+ac3c1cb (origin/wip-9820) qa/workunits: cephtool: don't remove self's key on auth tests
+9e6ae73 (origin/giant-unknown-locktype) mds: reply -EOPNOTSUPP for unknown lock type
+5558afa qa/workunits/rbd/import_export.sh: be case insensitive
+c4bac3e (origin/wip-inotable-init) mds: fix inotable initialization/reset
 f1fccb1 rpm: 95-ceph-osd-alt.rules is not needed for centos7 / rhel7
-d458b4f (origin/wip-9731) PGLog::IndexedLog::trim(): rollback_info_trimmed_to_riter may be log.rend()
+35bbb2d The fix for issue 9614 was not completed, as a result, for those erasure coded PGs with one OSD down, the state was wrongly marked as active+clean+degraded. This patch makes sure the clean flag is not set for such PG. Signed-off-by: Guang Yang <yguang at yahoo-inc.com>
+d947050 (origin/wip-9718) osd/osd_types: consider CRUSH_ITEM_NONE in check_new_interval() min_size check
+809ddd2 (origin/wip-9706) osdc/Objecter: fix use-after-frees in close_session, shutdown
+72a2ab1 osdc/Objecter: fix tick() session locking
+d458b4f PGLog::IndexedLog::trim(): rollback_info_trimmed_to_riter may be log.rend()
 459b2d2 mds: Locker: remove unused variable
 9b18d99 (origin/wip-9696) PG::choose_acting: in mixed cluster case, acting may include backfill
 3cd8a7f (origin/giant-locker-null) mds: Locker: fix a NULL deref in _update_cap_fields
@@ -28,6 +62,7 @@ fe57fab (origin/wip-9663) client: clean-up objecter on failed client init
 73d5bdb (origin/wip-9245-test-mon-pending-giant) tests: remove tests requiring osdmonitor_prepare_command
 e865781 mon: obsolete osdmonitor_prepare_command
 d0c2d7d test: minor case fix
+d0ceb3a (origin/wip-9545) os/FileStore: do not loop in sync_entry on shutdown
 7e2bd22 (origin/wip-9418) mon: Monitor: let 'handle_command()' deal with caps validation
 f0653c0 qa/workunits: mon: auth_caps: account for mon blank caps
 87d06f1 mon: MonCommands: adjust indentation for 'auth add'
@@ -44,7 +79,7 @@ d6b702c mon: MonCap: add new profiles
 8612461 mon: AuthMonitor: validate caps when creating or changing mon caps
 eb2f0f4 (origin/wip-9653-ceph-disk-bootstrap-osd-giant) ceph-disk: bootstrap-osd keyring ignores --statedir
 19be358 PG::actingset should be used when checking the number of acting OSDs for a given PG. Signed-off-by: Guang Yang <yguang at yahoo-inc.com>
-8253ead (origin/wip-rwtimer) osdc/Objecter: use SafeTimer; make callbacks race-tolerant
+8253ead osdc/Objecter: use SafeTimer; make callbacks race-tolerant
 a1aa06b ReplicatedPG: dump snap_trimq on pg query
 34f38b6 ReplicatedPG: do not queue the snap trimmer constantly
 b29bf00 ReplicatedPG: clean out completed trimmed objects as we go
@@ -617,7 +652,7 @@ bcc69ed mds: adapt to new objecter interface
 3a399ea common/RWLock: add get()
 8f9a9db common/RWLock: check return values
 92615ea common/RWLock: track read/write locks via atomics for assertion checks
-74ce4f2 (origin/wip-warning) rbd: fix signess warning
+74ce4f2 rbd: fix signess warning
 f7c0001 common: remove spurious uint32_t in buffer.c
 6ad8e61 Fix FTBFS on alpha due to incorrect check on BLKGETSIZE
 2554243 (origin/wip-mds-pc) mds/Server: rename perfcounters
@@ -1290,7 +1325,7 @@ e3a5756 remove ceph restarts on upgrades for RPMs
 4d6899c qa/workunits/cephtool/test.sh: fix erasure_code_profile get test
 ce9f12d qa/workunits/cephtool/test.sh: test osd pool get erasure_code_profile
 e8ebcb7 mon: OSDMonitor: add "osd pool get <pool> erasure_code_profile" command
-5ccfd37 (origin/wip-vstart) vstart.sh: default to 3 osds
+5ccfd37 vstart.sh: default to 3 osds
 5f6b11a (origin/wip-8857) mon/MDSMonitor: make legacy 'newfs' command idempotent
 b89ab5f rgw: don't try to wait for pending if list is empty
 19e68ac (origin/wip-rbd-defaults) rbd: respect rbd_default_* parameters
diff --git a/src/.git_version b/src/.git_version
index 0ce5d2a..e8d6e73 100644
--- a/src/.git_version
+++ b/src/.git_version
@@ -1,2 +1,2 @@
-87eb6630681251d82486b732eaff54477a65af70
+c51c8f9d80fa4e0168aa52685b8de40e42758578
 v0.87
diff --git a/src/Makefile.in b/src/Makefile.in
index 9e6bf32..33b90ea 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -79,6 +79,7 @@ noinst_PROGRAMS = get_command_descriptions$(EXEEXT)
 sbin_PROGRAMS =
 su_sbin_PROGRAMS = $(am__EXEEXT_17)
 check_PROGRAMS = unittest_erasure_code_plugin$(EXEEXT) \
+	unittest_erasure_code$(EXEEXT) \
 	unittest_erasure_code_jerasure$(EXEEXT) \
 	unittest_erasure_code_plugin_jerasure$(EXEEXT) \
 	$(am__EXEEXT_16) unittest_erasure_code_lrc$(EXEEXT) \
@@ -87,6 +88,7 @@ check_PROGRAMS = unittest_erasure_code_plugin$(EXEEXT) \
 	unittest_encoding$(EXEEXT) unittest_addrs$(EXEEXT) \
 	unittest_bloom_filter$(EXEEXT) unittest_histogram$(EXEEXT) \
 	unittest_str_map$(EXEEXT) unittest_sharedptr_registry$(EXEEXT) \
+	unittest_shared_cache$(EXEEXT) \
 	unittest_sloppy_crc_map$(EXEEXT) unittest_util$(EXEEXT) \
 	unittest_crush_indep$(EXEEXT) unittest_osdmap$(EXEEXT) \
 	unittest_workqueue$(EXEEXT) unittest_striper$(EXEEXT) \
@@ -1644,6 +1646,7 @@ ceph_erasure_code_DEPENDENCIES = $(am__DEPENDENCIES_11) $(LIBCOMMON) \
 	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_7) \
 	$(am__DEPENDENCIES_1)
 am_ceph_erasure_code_benchmark_OBJECTS =  \
+	erasure-code/ErasureCode.$(OBJEXT) \
 	test/erasure-code/ceph_erasure_code_benchmark.$(OBJEXT)
 ceph_erasure_code_benchmark_OBJECTS =  \
 	$(am_ceph_erasure_code_benchmark_OBJECTS)
@@ -2880,6 +2883,16 @@ unittest_encoding_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
 	$(unittest_encoding_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
 	$(LDFLAGS) -o $@
+am_unittest_erasure_code_OBJECTS =  \
+	erasure-code/unittest_erasure_code-ErasureCode.$(OBJEXT) \
+	test/erasure-code/unittest_erasure_code-TestErasureCode.$(OBJEXT)
+unittest_erasure_code_OBJECTS = $(am_unittest_erasure_code_OBJECTS)
+unittest_erasure_code_DEPENDENCIES = $(am__DEPENDENCIES_11) \
+	$(LIBCOMMON) $(am__DEPENDENCIES_14) $(am__DEPENDENCIES_7)
+unittest_erasure_code_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+	$(unittest_erasure_code_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
 am_unittest_erasure_code_example_OBJECTS = erasure-code/unittest_erasure_code_example-ErasureCode.$(OBJEXT) \
 	test/erasure-code/unittest_erasure_code_example-TestErasureCodeExample.$(OBJEXT)
 unittest_erasure_code_example_OBJECTS =  \
@@ -3234,6 +3247,15 @@ unittest_run_cmd_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
 	$(unittest_run_cmd_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
 	$(LDFLAGS) -o $@
+am_unittest_shared_cache_OBJECTS =  \
+	test/common/unittest_shared_cache-test_shared_cache.$(OBJEXT)
+unittest_shared_cache_OBJECTS = $(am_unittest_shared_cache_OBJECTS)
+unittest_shared_cache_DEPENDENCIES = $(am__DEPENDENCIES_14) \
+	$(am__DEPENDENCIES_7)
+unittest_shared_cache_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+	$(unittest_shared_cache_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
 am_unittest_sharedptr_registry_OBJECTS = test/common/unittest_sharedptr_registry-test_sharedptr_registry.$(OBJEXT)
 unittest_sharedptr_registry_OBJECTS =  \
 	$(am_unittest_sharedptr_registry_OBJECTS)
@@ -3541,6 +3563,7 @@ SOURCES = $(libcls_log_client_a_SOURCES) \
 	$(unittest_crypto_init_SOURCES) \
 	$(unittest_daemon_config_SOURCES) \
 	$(unittest_ecbackend_SOURCES) $(unittest_encoding_SOURCES) \
+	$(unittest_erasure_code_SOURCES) \
 	$(unittest_erasure_code_example_SOURCES) \
 	$(unittest_erasure_code_isa_SOURCES) \
 	$(unittest_erasure_code_jerasure_SOURCES) \
@@ -3564,6 +3587,7 @@ SOURCES = $(libcls_log_client_a_SOURCES) \
 	$(unittest_perf_counters_SOURCES) $(unittest_pglog_SOURCES) \
 	$(unittest_prebufferedstreambuf_SOURCES) \
 	$(unittest_rbd_replay_SOURCES) $(unittest_run_cmd_SOURCES) \
+	$(unittest_shared_cache_SOURCES) \
 	$(unittest_sharedptr_registry_SOURCES) \
 	$(unittest_signals_SOURCES) $(unittest_simple_spin_SOURCES) \
 	$(unittest_sloppy_crc_map_SOURCES) \
@@ -3717,6 +3741,7 @@ DIST_SOURCES = $(libcls_log_client_a_SOURCES) \
 	$(unittest_crypto_init_SOURCES) \
 	$(unittest_daemon_config_SOURCES) \
 	$(unittest_ecbackend_SOURCES) $(unittest_encoding_SOURCES) \
+	$(unittest_erasure_code_SOURCES) \
 	$(unittest_erasure_code_example_SOURCES) \
 	$(am__unittest_erasure_code_isa_SOURCES_DIST) \
 	$(unittest_erasure_code_jerasure_SOURCES) \
@@ -3740,6 +3765,7 @@ DIST_SOURCES = $(libcls_log_client_a_SOURCES) \
 	$(unittest_perf_counters_SOURCES) $(unittest_pglog_SOURCES) \
 	$(unittest_prebufferedstreambuf_SOURCES) \
 	$(unittest_rbd_replay_SOURCES) $(unittest_run_cmd_SOURCES) \
+	$(unittest_shared_cache_SOURCES) \
 	$(unittest_sharedptr_registry_SOURCES) \
 	$(unittest_signals_SOURCES) $(unittest_simple_spin_SOURCES) \
 	$(unittest_sloppy_crc_map_SOURCES) \
@@ -4032,13 +4058,13 @@ am__noinst_HEADERS_DIST = arch/intel.h arch/neon.h arch/probe.h \
 	rbd_replay/ImageNameMap.hpp rbd_replay/ios.hpp \
 	rbd_replay/PendingIO.hpp rbd_replay/rbd_loc.hpp \
 	rbd_replay/rbd_replay_debug.hpp rbd_replay/Replayer.hpp \
-	rbd_replay/Ser.hpp test/erasure-code/ErasureCodeExample.h \
+	rbd_replay/Ser.hpp \
 	test/erasure-code/ceph_erasure_code_benchmark.h \
-	test/bench/backend.h test/bench/bencher.h \
-	test/bench/detailed_stat_collector.h test/bench/distribution.h \
-	test/bench/dumb_backend.h test/bench/rados_backend.h \
-	test/bench/rbd_backend.h test/bench/stat_collector.h \
-	test/bench/testfilestore_backend.h \
+	test/erasure-code/ErasureCodeExample.h test/bench/backend.h \
+	test/bench/bencher.h test/bench/detailed_stat_collector.h \
+	test/bench/distribution.h test/bench/dumb_backend.h \
+	test/bench/rados_backend.h test/bench/rbd_backend.h \
+	test/bench/stat_collector.h test/bench/testfilestore_backend.h \
 	test/common/ObjectContents.h test/encoding/types.h \
 	test/objectstore/DeterministicOpSequence.h \
 	test/objectstore/FileStoreDiff.h \
@@ -4601,13 +4627,13 @@ noinst_HEADERS = arch/intel.h arch/neon.h arch/probe.h \
 	rbd_replay/ImageNameMap.hpp rbd_replay/ios.hpp \
 	rbd_replay/PendingIO.hpp rbd_replay/rbd_loc.hpp \
 	rbd_replay/rbd_replay_debug.hpp rbd_replay/Replayer.hpp \
-	rbd_replay/Ser.hpp test/erasure-code/ErasureCodeExample.h \
+	rbd_replay/Ser.hpp \
 	test/erasure-code/ceph_erasure_code_benchmark.h \
-	test/bench/backend.h test/bench/bencher.h \
-	test/bench/detailed_stat_collector.h test/bench/distribution.h \
-	test/bench/dumb_backend.h test/bench/rados_backend.h \
-	test/bench/rbd_backend.h test/bench/stat_collector.h \
-	test/bench/testfilestore_backend.h \
+	test/erasure-code/ErasureCodeExample.h test/bench/backend.h \
+	test/bench/bencher.h test/bench/detailed_stat_collector.h \
+	test/bench/distribution.h test/bench/dumb_backend.h \
+	test/bench/rados_backend.h test/bench/rbd_backend.h \
+	test/bench/stat_collector.h test/bench/testfilestore_backend.h \
 	test/common/ObjectContents.h test/encoding/types.h \
 	test/objectstore/DeterministicOpSequence.h \
 	test/objectstore/FileStoreDiff.h \
@@ -5426,6 +5452,7 @@ rbd_replay_prep_LDADD = $(LIBRBD) \
 	-lboost_date_time
 
 ceph_erasure_code_benchmark_SOURCES = \
+	erasure-code/ErasureCode.cc \
 	test/erasure-code/ceph_erasure_code_benchmark.cc
 
 ceph_erasure_code_benchmark_LDADD = $(LIBOSD) $(LIBCOMMON) \
@@ -5487,6 +5514,12 @@ unittest_erasure_code_plugin_SOURCES = \
 unittest_erasure_code_plugin_CXXFLAGS = $(UNITTEST_CXXFLAGS)
 unittest_erasure_code_plugin_LDADD = $(LIBOSD) $(LIBCOMMON) \
 	$(UNITTEST_LDADD) $(CEPH_GLOBAL) $(am__append_65)
+unittest_erasure_code_SOURCES = \
+	erasure-code/ErasureCode.cc \
+	test/erasure-code/TestErasureCode.cc
+
+unittest_erasure_code_CXXFLAGS = $(UNITTEST_CXXFLAGS)
+unittest_erasure_code_LDADD = $(LIBOSD) $(LIBCOMMON) $(UNITTEST_LDADD) $(CEPH_GLOBAL)
 unittest_erasure_code_jerasure_SOURCES = \
 	test/erasure-code/TestErasureCodeJerasure.cc \
 	${jerasure_sources}
@@ -5743,6 +5776,9 @@ unittest_str_map_LDADD = $(UNITTEST_LDADD) $(CEPH_GLOBAL)
 unittest_sharedptr_registry_SOURCES = test/common/test_sharedptr_registry.cc
 unittest_sharedptr_registry_CXXFLAGS = $(UNITTEST_CXXFLAGS)
 unittest_sharedptr_registry_LDADD = $(UNITTEST_LDADD) $(CEPH_GLOBAL)
+unittest_shared_cache_SOURCES = test/common/test_shared_cache.cc
+unittest_shared_cache_CXXFLAGS = $(UNITTEST_CXXFLAGS)
+unittest_shared_cache_LDADD = $(UNITTEST_LDADD) $(CEPH_GLOBAL)
 unittest_sloppy_crc_map_SOURCES = test/common/test_sloppy_crc_map.cc
 unittest_sloppy_crc_map_CXXFLAGS = $(UNITTEST_CXXFLAGS)
 unittest_sloppy_crc_map_LDADD = $(UNITTEST_LDADD) $(CEPH_GLOBAL)
@@ -8072,6 +8108,8 @@ test/erasure-code/ceph_erasure_code.$(OBJEXT):  \
 ceph_erasure_code$(EXEEXT): $(ceph_erasure_code_OBJECTS) $(ceph_erasure_code_DEPENDENCIES) $(EXTRA_ceph_erasure_code_DEPENDENCIES) 
 	@rm -f ceph_erasure_code$(EXEEXT)
 	$(AM_V_CXXLD)$(CXXLINK) $(ceph_erasure_code_OBJECTS) $(ceph_erasure_code_LDADD) $(LIBS)
+erasure-code/ErasureCode.$(OBJEXT): erasure-code/$(am__dirstamp) \
+	erasure-code/$(DEPDIR)/$(am__dirstamp)
 test/erasure-code/ceph_erasure_code_benchmark.$(OBJEXT):  \
 	test/erasure-code/$(am__dirstamp) \
 	test/erasure-code/$(DEPDIR)/$(am__dirstamp)
@@ -9295,6 +9333,15 @@ test/unittest_encoding-encoding.$(OBJEXT): test/$(am__dirstamp) \
 unittest_encoding$(EXEEXT): $(unittest_encoding_OBJECTS) $(unittest_encoding_DEPENDENCIES) $(EXTRA_unittest_encoding_DEPENDENCIES) 
 	@rm -f unittest_encoding$(EXEEXT)
 	$(AM_V_CXXLD)$(unittest_encoding_LINK) $(unittest_encoding_OBJECTS) $(unittest_encoding_LDADD) $(LIBS)
+erasure-code/unittest_erasure_code-ErasureCode.$(OBJEXT):  \
+	erasure-code/$(am__dirstamp) \
+	erasure-code/$(DEPDIR)/$(am__dirstamp)
+test/erasure-code/unittest_erasure_code-TestErasureCode.$(OBJEXT):  \
+	test/erasure-code/$(am__dirstamp) \
+	test/erasure-code/$(DEPDIR)/$(am__dirstamp)
+unittest_erasure_code$(EXEEXT): $(unittest_erasure_code_OBJECTS) $(unittest_erasure_code_DEPENDENCIES) $(EXTRA_unittest_erasure_code_DEPENDENCIES) 
+	@rm -f unittest_erasure_code$(EXEEXT)
+	$(AM_V_CXXLD)$(unittest_erasure_code_LINK) $(unittest_erasure_code_OBJECTS) $(unittest_erasure_code_LDADD) $(LIBS)
 erasure-code/unittest_erasure_code_example-ErasureCode.$(OBJEXT):  \
 	erasure-code/$(am__dirstamp) \
 	erasure-code/$(DEPDIR)/$(am__dirstamp)
@@ -9569,6 +9616,12 @@ test/unittest_run_cmd-run_cmd.$(OBJEXT): test/$(am__dirstamp) \
 unittest_run_cmd$(EXEEXT): $(unittest_run_cmd_OBJECTS) $(unittest_run_cmd_DEPENDENCIES) $(EXTRA_unittest_run_cmd_DEPENDENCIES) 
 	@rm -f unittest_run_cmd$(EXEEXT)
 	$(AM_V_CXXLD)$(unittest_run_cmd_LINK) $(unittest_run_cmd_OBJECTS) $(unittest_run_cmd_LDADD) $(LIBS)
+test/common/unittest_shared_cache-test_shared_cache.$(OBJEXT):  \
+	test/common/$(am__dirstamp) \
+	test/common/$(DEPDIR)/$(am__dirstamp)
+unittest_shared_cache$(EXEEXT): $(unittest_shared_cache_OBJECTS) $(unittest_shared_cache_DEPENDENCIES) $(EXTRA_unittest_shared_cache_DEPENDENCIES) 
+	@rm -f unittest_shared_cache$(EXEEXT)
+	$(AM_V_CXXLD)$(unittest_shared_cache_LINK) $(unittest_shared_cache_OBJECTS) $(unittest_shared_cache_LDADD) $(LIBS)
 test/common/unittest_sharedptr_registry-test_sharedptr_registry.$(OBJEXT):  \
 	test/common/$(am__dirstamp) \
 	test/common/$(DEPDIR)/$(am__dirstamp)
@@ -10229,6 +10282,7 @@ mostlyclean-compile:
 	-rm -f crush/hash.lo
 	-rm -f crush/mapper.$(OBJEXT)
 	-rm -f crush/mapper.lo
+	-rm -f erasure-code/ErasureCode.$(OBJEXT)
 	-rm -f erasure-code/ErasureCodePlugin.$(OBJEXT)
 	-rm -f erasure-code/ErasureCodePlugin.lo
 	-rm -f erasure-code/isa/isa-l/erasure_code/libec_isa_la-ec_base.$(OBJEXT)
@@ -10429,6 +10483,7 @@ mostlyclean-compile:
 	-rm -f erasure-code/lrc/libec_lrc_la-ErasureCodePluginLrc.lo
 	-rm -f erasure-code/lrc/unittest_erasure_code_lrc-ErasureCodeLrc.$(OBJEXT)
 	-rm -f erasure-code/lrc/unittest_erasure_code_lrc-ErasureCodePluginLrc.$(OBJEXT)
+	-rm -f erasure-code/unittest_erasure_code-ErasureCode.$(OBJEXT)
 	-rm -f erasure-code/unittest_erasure_code_example-ErasureCode.$(OBJEXT)
 	-rm -f erasure-code/unittest_erasure_code_isa-ErasureCode.$(OBJEXT)
 	-rm -f erasure-code/unittest_erasure_code_jerasure-ErasureCode.$(OBJEXT)
@@ -10934,6 +10989,7 @@ mostlyclean-compile:
 	-rm -f test/common/unittest_histogram-histogram.$(OBJEXT)
 	-rm -f test/common/unittest_io_priority-test_io_priority.$(OBJEXT)
 	-rm -f test/common/unittest_lru-test_lru.$(OBJEXT)
+	-rm -f test/common/unittest_shared_cache-test_shared_cache.$(OBJEXT)
 	-rm -f test/common/unittest_sharedptr_registry-test_sharedptr_registry.$(OBJEXT)
 	-rm -f test/common/unittest_sloppy_crc_map-test_sloppy_crc_map.$(OBJEXT)
 	-rm -f test/common/unittest_str_map-test_str_map.$(OBJEXT)
@@ -10962,6 +11018,7 @@ mostlyclean-compile:
 	-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-TestErasureCode.$(OBJEXT)
 	-rm -f test/erasure-code/unittest_erasure_code_example-TestErasureCodeExample.$(OBJEXT)
 	-rm -f test/erasure-code/unittest_erasure_code_isa-TestErasureCodeIsa.$(OBJEXT)
 	-rm -f test/erasure-code/unittest_erasure_code_jerasure-TestErasureCodeJerasure.$(OBJEXT)
@@ -11367,12 +11424,14 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at crush/$(DEPDIR)/crush.Plo at am__quote@
 @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@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/$(DEPDIR)/ErasureCode.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at erasure-code/$(DEPDIR)/ErasureCodePlugin.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at erasure-code/$(DEPDIR)/libec_isa_la-ErasureCode.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at erasure-code/$(DEPDIR)/libec_jerasure_generic_la-ErasureCode.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at erasure-code/$(DEPDIR)/libec_jerasure_sse3_la-ErasureCode.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at erasure-code/$(DEPDIR)/libec_jerasure_sse4_la-ErasureCode.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at erasure-code/$(DEPDIR)/libec_lrc_la-ErasureCode.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at erasure-code/$(DEPDIR)/unittest_erasure_code-ErasureCode.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at erasure-code/$(DEPDIR)/unittest_erasure_code_example-ErasureCode.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at erasure-code/$(DEPDIR)/unittest_erasure_code_isa-ErasureCode.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at erasure-code/$(DEPDIR)/unittest_erasure_code_jerasure-ErasureCode.Po at am__quote@
@@ -11831,6 +11890,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at test/common/$(DEPDIR)/unittest_histogram-histogram.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test/common/$(DEPDIR)/unittest_io_priority-test_io_priority.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test/common/$(DEPDIR)/unittest_lru-test_lru.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at test/common/$(DEPDIR)/unittest_shared_cache-test_shared_cache.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test/common/$(DEPDIR)/unittest_sharedptr_registry-test_sharedptr_registry.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test/common/$(DEPDIR)/unittest_sloppy_crc_map-test_sloppy_crc_map.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test/common/$(DEPDIR)/unittest_str_map-test_str_map.Po at am__quote@
@@ -11850,6 +11910,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at test/erasure-code/$(DEPDIR)/libec_test_jerasure_generic_la-TestJerasurePluginGeneric.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test/erasure-code/$(DEPDIR)/libec_test_jerasure_sse3_la-TestJerasurePluginSSE3.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test/erasure-code/$(DEPDIR)/libec_test_jerasure_sse4_la-TestJerasurePluginSSE4.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at test/erasure-code/$(DEPDIR)/unittest_erasure_code-TestErasureCode.Po 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_isa-TestErasureCodeIsa.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test/erasure-code/$(DEPDIR)/unittest_erasure_code_jerasure-TestErasureCodeJerasure.Po at am__quote@
@@ -16475,6 +16536,34 @@ test/unittest_encoding-encoding.obj: test/encoding.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_encoding_CXXFLAGS) $(CXXFLAGS) -c -o test/unittest_encoding-encoding.obj `if test -f 'test/encoding.cc'; then $(CYGPATH_W) 'test/encoding.cc'; else $(CYGPATH_W) '$(srcdir)/test/encoding.cc'; fi`
 
+erasure-code/unittest_erasure_code-ErasureCode.o: erasure-code/ErasureCode.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_CXXFLAGS) $(CXXFLAGS) -MT erasure-code/unittest_erasure_code-ErasureCode.o -MD -MP -MF erasure-code/$(DEPDIR)/unittest_erasure_code-ErasureCode.Tpo -c -o erasure-code/unittest_erasure_code-ErasureCode.o `test -f 'erasure-code/ErasureCode.cc' || echo '$(srcdir)/'`erasure-code/ErasureCode.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) erasure-code/$(DEPDIR)/unittest_erasure_code-ErasureCode.Tpo erasure-code/$(DEPDIR)/unittest_erasure_code-ErasureCode.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='erasure-code/ErasureCode.cc' object='erasure-code/unittest_erasure_code-ErasureCode.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_erasure_code_CXXFLAGS) $(CXXFLAGS) -c -o erasure-code/unittest_erasure_code-ErasureCode.o `test -f 'erasure-code/ErasureCode.cc' || echo '$(srcdir)/'`erasure-code/ErasureCode.cc
+
+erasure-code/unittest_erasure_code-ErasureCode.obj: erasure-code/ErasureCode.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_CXXFLAGS) $(CXXFLAGS) -MT erasure-code/unittest_erasure_code-ErasureCode.obj -MD -MP -MF erasure-code/$(DEPDIR)/unittest_erasure_code-ErasureCode.Tpo -c -o erasure-code/unittest_erasure_code-ErasureCode.obj `if test -f 'erasure-code/ErasureCode.cc'; then $(CYGPATH_W) 'erasure-code/ErasureCode.cc'; else $(CYGPATH_W) '$(srcdir)/erasure-code/ErasureCode.cc'; fi`
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) erasure-code/$(DEPDIR)/unittest_erasure_code-ErasureCode.Tpo erasure-code/$(DEPDIR)/unittest_erasure_code-ErasureCode.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='erasure-code/ErasureCode.cc' object='erasure-code/unittest_erasure_code-ErasureCode.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_erasure_code_CXXFLAGS) $(CXXFLAGS) -c -o erasure-code/unittest_erasure_code-ErasureCode.obj `if test -f 'erasure-code/ErasureCode.cc'; then $(CYGPATH_W) 'erasure-code/ErasureCode.cc'; else $(CYGPATH_W) '$(srcdir)/erasure-code/ErasureCode.cc'; fi`
+
+test/erasure-code/unittest_erasure_code-TestErasureCode.o: test/erasure-code/TestErasureCode.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_CXXFLAGS) $(CXXFLAGS) -MT test/erasure-code/unittest_erasure_code-TestErasureCode.o -MD -MP -MF test/erasure-code/$(DEPDIR)/unittest_erasure_code-TestErasureCode.Tpo -c -o test/erasure-code/unittest_erasure_code-TestErasureCode.o `test -f 'test/erasure-code/TestErasureCode.cc' || echo '$(srcdir)/'`test/erasure-code/TestErasureCode.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) test/erasure-code/$(DEPDIR)/unittest_erasure_code-TestErasureCode.Tpo test/erasure-code/$(DEPDIR)/unittest_erasure_code-TestErasureCode.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='test/erasure-code/TestErasureCode.cc' object='test/erasure-code/unittest_erasure_code-TestErasureCode.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_erasure_code_CXXFLAGS) $(CXXFLAGS) -c -o test/erasure-code/unittest_erasure_code-TestErasureCode.o `test -f 'test/erasure-code/TestErasureCode.cc' || echo '$(srcdir)/'`test/erasure-code/TestErasureCode.cc
+
+test/erasure-code/unittest_erasure_code-TestErasureCode.obj: test/erasure-code/TestErasureCode.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_CXXFLAGS) $(CXXFLAGS) -MT test/erasure-code/unittest_erasure_code-TestErasureCode.obj -MD -MP -MF test/erasure-code/$(DEPDIR)/unittest_erasure_code-TestErasureCode.Tpo -c -o test/erasure-code/unittest_erasure_code-TestErasureCode.obj `if test -f 'test/erasure-code/TestErasureCode.cc'; then $(CYGPATH_W) 'test/erasure-code/TestErasureCode.cc'; else $(CYGPATH_W) [...]
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) test/erasure-code/$(DEPDIR)/unittest_erasure_code-TestErasureCode.Tpo test/erasure-code/$(DEPDIR)/unittest_erasure_code-TestErasureCode.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='test/erasure-code/TestErasureCode.cc' object='test/erasure-code/unittest_erasure_code-TestErasureCode.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_erasure_code_CXXFLAGS) $(CXXFLAGS) -c -o test/erasure-code/unittest_erasure_code-TestErasureCode.obj `if test -f 'test/erasure-code/TestErasureCode.cc'; then $(CYGPATH_W) 'test/erasure-code/TestErasureCode.cc'; else $(CYGPATH_W) '$(srcdir)/test/erasure-code/TestErasureCode.cc'; fi`
+
 erasure-code/unittest_erasure_code_example-ErasureCode.o: erasure-code/ErasureCode.cc
 @am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_erasure_code_example_CXXFLAGS) $(CXXFLAGS) -MT erasure-code/unittest_erasure_code_example-ErasureCode.o -MD -MP -MF erasure-code/$(DEPDIR)/unittest_erasure_code_example-ErasureCode.Tpo -c -o erasure-code/unittest_erasure_code_example-ErasureCode.o `test -f 'erasure-code/ErasureCode.cc' || echo '$(srcdir)/'`erasure-code/ErasureCode.cc
 @am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) erasure-code/$(DEPDIR)/unittest_erasure_code_example-ErasureCode.Tpo erasure-code/$(DEPDIR)/unittest_erasure_code_example-ErasureCode.Po
@@ -17105,6 +17194,20 @@ test/unittest_run_cmd-run_cmd.obj: test/run_cmd.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_run_cmd_CXXFLAGS) $(CXXFLAGS) -c -o test/unittest_run_cmd-run_cmd.obj `if test -f 'test/run_cmd.cc'; then $(CYGPATH_W) 'test/run_cmd.cc'; else $(CYGPATH_W) '$(srcdir)/test/run_cmd.cc'; fi`
 
+test/common/unittest_shared_cache-test_shared_cache.o: test/common/test_shared_cache.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_shared_cache_CXXFLAGS) $(CXXFLAGS) -MT test/common/unittest_shared_cache-test_shared_cache.o -MD -MP -MF test/common/$(DEPDIR)/unittest_shared_cache-test_shared_cache.Tpo -c -o test/common/unittest_shared_cache-test_shared_cache.o `test -f 'test/common/test_shared_cache.cc' || echo '$(srcdir)/'`test/common/test_shared_cache.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) test/common/$(DEPDIR)/unittest_shared_cache-test_shared_cache.Tpo test/common/$(DEPDIR)/unittest_shared_cache-test_shared_cache.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='test/common/test_shared_cache.cc' object='test/common/unittest_shared_cache-test_shared_cache.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_shared_cache_CXXFLAGS) $(CXXFLAGS) -c -o test/common/unittest_shared_cache-test_shared_cache.o `test -f 'test/common/test_shared_cache.cc' || echo '$(srcdir)/'`test/common/test_shared_cache.cc
+
+test/common/unittest_shared_cache-test_shared_cache.obj: test/common/test_shared_cache.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_shared_cache_CXXFLAGS) $(CXXFLAGS) -MT test/common/unittest_shared_cache-test_shared_cache.obj -MD -MP -MF test/common/$(DEPDIR)/unittest_shared_cache-test_shared_cache.Tpo -c -o test/common/unittest_shared_cache-test_shared_cache.obj `if test -f 'test/common/test_shared_cache.cc'; then $(CYGPATH_W) 'test/common/test_shared_cache.cc'; else $(CYGPATH_W) '$(srcdir)/test/com [...]
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) test/common/$(DEPDIR)/unittest_shared_cache-test_shared_cache.Tpo test/common/$(DEPDIR)/unittest_shared_cache-test_shared_cache.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='test/common/test_shared_cache.cc' object='test/common/unittest_shared_cache-test_shared_cache.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_shared_cache_CXXFLAGS) $(CXXFLAGS) -c -o test/common/unittest_shared_cache-test_shared_cache.obj `if test -f 'test/common/test_shared_cache.cc'; then $(CYGPATH_W) 'test/common/test_shared_cache.cc'; else $(CYGPATH_W) '$(srcdir)/test/common/test_shared_cache.cc'; fi`
+
 test/common/unittest_sharedptr_registry-test_sharedptr_registry.o: test/common/test_sharedptr_registry.cc
 @am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_sharedptr_registry_CXXFLAGS) $(CXXFLAGS) -MT test/common/unittest_sharedptr_registry-test_sharedptr_registry.o -MD -MP -MF test/common/$(DEPDIR)/unittest_sharedptr_registry-test_sharedptr_registry.Tpo -c -o test/common/unittest_sharedptr_registry-test_sharedptr_registry.o `test -f 'test/common/test_sharedptr_registry.cc' || echo '$(srcdir)/'`test/common/test_sharedptr_reg [...]
 @am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) test/common/$(DEPDIR)/unittest_sharedptr_registry-test_sharedptr_registry.Tpo test/common/$(DEPDIR)/unittest_sharedptr_registry-test_sharedptr_registry.Po
diff --git a/src/common/Timer.cc b/src/common/Timer.cc
index 6282eac..e398841 100644
--- a/src/common/Timer.cc
+++ b/src/common/Timer.cc
@@ -107,6 +107,10 @@ void SafeTimer::timer_thread()
 	lock.Lock();
     }
 
+    // recheck stopping if we dropped the lock
+    if (!safe_callbacks && stopping)
+      break;
+
     ldout(cct,20) << "timer_thread going to sleep" << dendl;
     if (schedule.empty())
       cond.Wait(lock);
diff --git a/src/common/buffer.cc b/src/common/buffer.cc
index b141759..9ee2bfe 100644
--- a/src/common/buffer.cc
+++ b/src/common/buffer.cc
@@ -230,20 +230,23 @@ static simple_spinlock_t buffer_debug_lock = SIMPLE_SPINLOCK_INITIALIZER;
   };
 
   class buffer::raw_posix_aligned : public buffer::raw {
+    unsigned align;
   public:
-    raw_posix_aligned(unsigned l) : raw(l) {
+    raw_posix_aligned(unsigned l, unsigned _align) : raw(l) {
+      align = _align;
+      assert((align >= sizeof(void *)) && (align & (align - 1)) == 0);
 #ifdef DARWIN
       data = (char *) valloc (len);
 #else
       data = 0;
-      int r = ::posix_memalign((void**)(void*)&data, CEPH_PAGE_SIZE, len);
+      int r = ::posix_memalign((void**)(void*)&data, align, len);
       if (r)
 	throw bad_alloc();
 #endif /* DARWIN */
       if (!data)
 	throw bad_alloc();
       inc_total_alloc(len);
-      bdout << "raw_posix_aligned " << this << " alloc " << (void *)data << " " << l << " " << buffer::get_total_alloc() << bendl;
+      bdout << "raw_posix_aligned " << this << " alloc " << (void *)data << " l=" << l << ", align=" << align << " total_alloc=" << buffer::get_total_alloc() << bendl;
     }
     ~raw_posix_aligned() {
       ::free((void*)data);
@@ -251,34 +254,36 @@ static simple_spinlock_t buffer_debug_lock = SIMPLE_SPINLOCK_INITIALIZER;
       bdout << "raw_posix_aligned " << this << " free " << (void *)data << " " << buffer::get_total_alloc() << bendl;
     }
     raw* clone_empty() {
-      return new raw_posix_aligned(len);
+      return new raw_posix_aligned(len, align);
     }
   };
 #endif
 
 #ifdef __CYGWIN__
   class buffer::raw_hack_aligned : public buffer::raw {
+    unsigned align;
     char *realdata;
   public:
-    raw_hack_aligned(unsigned l) : raw(l) {
-      realdata = new char[len+CEPH_PAGE_SIZE-1];
-      unsigned off = ((unsigned)realdata) & ~CEPH_PAGE_MASK;
+    raw_hack_aligned(unsigned l, unsigned _align) : raw(l) {
+      align = _align;
+      realdata = new char[len+align-1];
+      unsigned off = ((unsigned)realdata) & (align-1);
       if (off)
-	data = realdata + CEPH_PAGE_SIZE - off;
+	data = realdata + align - off;
       else
 	data = realdata;
-      inc_total_alloc(len+CEPH_PAGE_SIZE-1);
+      inc_total_alloc(len+align-1);
       //cout << "hack aligned " << (unsigned)data
       //<< " in raw " << (unsigned)realdata
       //<< " off " << off << std::endl;
-      assert(((unsigned)data & (CEPH_PAGE_SIZE-1)) == 0);
+      assert(((unsigned)data & (align-1)) == 0);
     }
     ~raw_hack_aligned() {
       delete[] realdata;
-      dec_total_alloc(len+CEPH_PAGE_SIZE-1);
+      dec_total_alloc(len+align-1);
     }
     raw* clone_empty() {
-      return new raw_hack_aligned(len);
+      return new raw_hack_aligned(len, align);
     }
   };
 #endif
@@ -334,10 +339,6 @@ static simple_spinlock_t buffer_debug_lock = SIMPLE_SPINLOCK_INITIALIZER;
       return true;
     }
 
-    bool is_page_aligned() {
-      return false;
-    }
-
     int set_source(int fd, loff_t *off) {
       int flags = SPLICE_F_NONBLOCK;
       ssize_t r = safe_splice(fd, off, pipefds[1], NULL, len, flags);
@@ -520,14 +521,17 @@ static simple_spinlock_t buffer_debug_lock = SIMPLE_SPINLOCK_INITIALIZER;
   buffer::raw* buffer::create_static(unsigned len, char *buf) {
     return new raw_static(buf, len);
   }
-  buffer::raw* buffer::create_page_aligned(unsigned len) {
+  buffer::raw* buffer::create_aligned(unsigned len, unsigned align) {
 #ifndef __CYGWIN__
     //return new raw_mmap_pages(len);
-    return new raw_posix_aligned(len);
+    return new raw_posix_aligned(len, align);
 #else
-    return new raw_hack_aligned(len);
+    return new raw_hack_aligned(len, align);
 #endif
   }
+  buffer::raw* buffer::create_page_aligned(unsigned len) {
+    return create_aligned(len, CEPH_PAGE_SIZE);
+  }
 
   buffer::raw* buffer::create_zero_copy(unsigned len, int fd, int64_t *offset) {
 #ifdef CEPH_HAVE_SPLICE
@@ -1013,22 +1017,22 @@ static simple_spinlock_t buffer_debug_lock = SIMPLE_SPINLOCK_INITIALIZER;
     return true;
   }
 
-  bool buffer::list::is_page_aligned() const
+  bool buffer::list::is_aligned(unsigned align) const
   {
     for (std::list<ptr>::const_iterator it = _buffers.begin();
 	 it != _buffers.end();
 	 ++it) 
-      if (!it->is_page_aligned())
+      if (!it->is_aligned(align))
 	return false;
     return true;
   }
 
-  bool buffer::list::is_n_page_sized() const
+  bool buffer::list::is_n_align_sized(unsigned align) const
   {
     for (std::list<ptr>::const_iterator it = _buffers.begin();
 	 it != _buffers.end();
 	 ++it) 
-      if (!it->is_n_page_sized())
+      if (!it->is_n_align_sized(align))
 	return false;
     return true;
   }
@@ -1078,6 +1082,16 @@ static simple_spinlock_t buffer_debug_lock = SIMPLE_SPINLOCK_INITIALIZER;
     return &(*_buffers.begin()) == &(*_buffers.rbegin());
   }
 
+  bool buffer::list::is_n_page_sized() const
+  {
+    return is_n_align_sized(CEPH_PAGE_SIZE);
+  }
+
+  bool buffer::list::is_page_aligned() const
+  {
+    return is_aligned(CEPH_PAGE_SIZE);
+  }
+
   void buffer::list::rebuild()
   {
     ptr nb;
@@ -1101,16 +1115,16 @@ static simple_spinlock_t buffer_debug_lock = SIMPLE_SPINLOCK_INITIALIZER;
     _buffers.push_back(nb);
   }
 
-void buffer::list::rebuild_page_aligned()
+void buffer::list::rebuild_aligned(unsigned align)
 {
   std::list<ptr>::iterator p = _buffers.begin();
   while (p != _buffers.end()) {
-    // keep anything that's already page sized+aligned
-    if (p->is_page_aligned() && p->is_n_page_sized()) {
+    // keep anything that's already align and sized aligned
+    if (p->is_aligned(align) && p->is_n_align_sized(align)) {
       /*cout << " segment " << (void*)p->c_str()
-	     << " offset " << ((unsigned long)p->c_str() & ~CEPH_PAGE_MASK)
+	     << " offset " << ((unsigned long)p->c_str() & (align - 1))
 	     << " length " << p->length()
-	     << " " << (p->length() & ~CEPH_PAGE_MASK) << " ok" << std::endl;
+	     << " " << (p->length() & (align - 1)) << " ok" << std::endl;
       */
       ++p;
       continue;
@@ -1121,26 +1135,31 @@ void buffer::list::rebuild_page_aligned()
     unsigned offset = 0;
     do {
       /*cout << " segment " << (void*)p->c_str()
-	     << " offset " << ((unsigned long)p->c_str() & ~CEPH_PAGE_MASK)
-	     << " length " << p->length() << " " << (p->length() & ~CEPH_PAGE_MASK)
-	     << " overall offset " << offset << " " << (offset & ~CEPH_PAGE_MASK)
+             << " offset " << ((unsigned long)p->c_str() & (align - 1))
+             << " length " << p->length() << " " << (p->length() & (align - 1))
+             << " overall offset " << offset << " " << (offset & (align - 1))
 	     << " not ok" << std::endl;
       */
       offset += p->length();
       unaligned.push_back(*p);
       _buffers.erase(p++);
     } while (p != _buffers.end() &&
-	     (!p->is_page_aligned() ||
-	      !p->is_n_page_sized() ||
-	      (offset & ~CEPH_PAGE_MASK)));
-    if (!(unaligned.is_contiguous() && unaligned._buffers.front().is_page_aligned())) {
-      ptr nb(buffer::create_page_aligned(unaligned._len));
+	     (!p->is_aligned(align) ||
+	      !p->is_n_align_sized(align) ||
+	      (offset & (align-1))));
+    if (!(unaligned.is_contiguous() && unaligned._buffers.front().is_aligned(align))) {
+      ptr nb(buffer::create_aligned(unaligned._len, align));
       unaligned.rebuild(nb);
     }
     _buffers.insert(p, unaligned._buffers.front());
   }
 }
 
+void buffer::list::rebuild_page_aligned()
+{
+  rebuild_aligned(CEPH_PAGE_SIZE);
+}
+
   // sort-of-like-assignment-op
   void buffer::list::claim(list& bl)
   {
diff --git a/src/common/shared_cache.hpp b/src/common/shared_cache.hpp
index a5079ed..cb478a5 100644
--- a/src/common/shared_cache.hpp
+++ b/src/common/shared_cache.hpp
@@ -35,7 +35,7 @@ class SharedLRU {
   map<K, typename list<pair<K, VPtr> >::iterator > contents;
   list<pair<K, VPtr> > lru;
 
-  map<K, WeakVPtr> weak_refs;
+  map<K, pair<WeakVPtr, V*> > weak_refs;
 
   void trim_cache(list<VPtr> *to_release) {
     while (size > max_size) {
@@ -67,9 +67,12 @@ class SharedLRU {
     }
   }
 
-  void remove(const K& key) {
+  void remove(const K& key, V *valptr) {
     Mutex::Locker l(lock);
-    weak_refs.erase(key);
+    typename map<K, pair<WeakVPtr, V*> >::iterator i = weak_refs.find(key);
+    if (i != weak_refs.end() && i->second.second == valptr) {
+      weak_refs.erase(i);
+    }
     cond.Signal();
   }
 
@@ -79,7 +82,7 @@ class SharedLRU {
     K key;
     Cleanup(SharedLRU<K, V> *cache, K key) : cache(cache), key(key) {}
     void operator()(V *ptr) {
-      cache->remove(key);
+      cache->remove(key, ptr);
       delete ptr;
     }
   };
@@ -110,12 +113,12 @@ public:
   }
 
   void dump_weak_refs(ostream& out) {
-    for (typename map<K, WeakVPtr>::iterator p = weak_refs.begin();
+    for (typename map<K, pair<WeakVPtr, V*> >::iterator p = weak_refs.begin();
 	 p != weak_refs.end();
 	 ++p) {
       out << __func__ << " " << this << " weak_refs: "
-	  << p->first << " = " << p->second.lock().get()
-	  << " with " << p->second.use_count() << " refs"
+	  << p->first << " = " << p->second.second
+	  << " with " << p->second.first.use_count() << " refs"
 	  << std::endl;
     }
   }
@@ -125,12 +128,24 @@ public:
     {
       Mutex::Locker l(lock);
       if (weak_refs.count(key)) {
-	val = weak_refs[key].lock();
+	val = weak_refs[key].first.lock();
       }
       lru_remove(key);
     }
   }
 
+  void purge(const K &key) {
+    VPtr val; // release any ref we have after we drop the lock
+    {
+      Mutex::Locker l(lock);
+      if (weak_refs.count(key)) {
+	val = weak_refs[key].first.lock();
+      }
+      lru_remove(key);
+      weak_refs.erase(key);
+    }
+  }
+
   void set_size(size_t new_size) {
     list<VPtr> to_release;
     {
@@ -156,10 +171,11 @@ public:
 	retry = false;
 	if (weak_refs.empty())
 	  break;
-	typename map<K, WeakVPtr>::iterator i = weak_refs.lower_bound(key);
+	typename map<K, pair<WeakVPtr, V*> >::iterator i =
+	  weak_refs.lower_bound(key);
 	if (i == weak_refs.end())
 	  --i;
-	val = i->second.lock();
+	val = i->second.first.lock();
 	if (val) {
 	  lru_add(i->first, val, &to_release);
 	} else {
@@ -180,9 +196,9 @@ public:
       bool retry = false;
       do {
 	retry = false;
-	typename map<K, WeakVPtr>::iterator i = weak_refs.find(key);
+	typename map<K, pair<WeakVPtr, V*> >::iterator i = weak_refs.find(key);
 	if (i != weak_refs.end()) {
-	  val = i->second.lock();
+	  val = i->second.first.lock();
 	  if (val) {
 	    lru_add(key, val, &to_release);
 	  } else {
@@ -209,22 +225,24 @@ public:
    * @return A reference to the map's value for the given key
    */
   VPtr add(const K& key, V *value, bool *existed = NULL) {
-    VPtr val(value, Cleanup(this, key));
+    VPtr val;
     list<VPtr> to_release;
     {
       Mutex::Locker l(lock);
-      typename map<K, WeakVPtr>::iterator actual = weak_refs.lower_bound(key);
+      typename map<K, pair<WeakVPtr, V*> >::iterator actual =
+	weak_refs.lower_bound(key);
       if (actual != weak_refs.end() && actual->first == key) {
         if (existed) 
           *existed = true;
 
-        return actual->second.lock();
+        return actual->second.first.lock();
       }
 
       if (existed)      
         *existed = false;
 
-      weak_refs.insert(actual, make_pair(key, val));
+      val = VPtr(value, Cleanup(this, key));
+      weak_refs.insert(actual, make_pair(key, make_pair(val, value)));
       lru_add(key, val, &to_release);
     }
     return val;
diff --git a/src/erasure-code/ErasureCode.cc b/src/erasure-code/ErasureCode.cc
index 5953f49..96a6b39 100644
--- a/src/erasure-code/ErasureCode.cc
+++ b/src/erasure-code/ErasureCode.cc
@@ -22,6 +22,13 @@
 #include "common/strtol.h"
 #include "ErasureCode.h"
 
+const unsigned ErasureCode::SIMD_ALIGN = 32;
+
+int ErasureCode::chunk_index(unsigned int i) const
+{
+  return chunk_mapping.size() > i ? chunk_mapping[i] : i;
+}
+
 int ErasureCode::minimum_to_decode(const set<int> &want_to_read,
                                    const set<int> &available_chunks,
                                    set<int> *minimum)
@@ -54,22 +61,46 @@ int ErasureCode::minimum_to_decode_with_cost(const set<int> &want_to_read,
 }
 
 int ErasureCode::encode_prepare(const bufferlist &raw,
-                                bufferlist *prepared) const
+                                map<int, bufferlist> &encoded) const
 {
   unsigned int k = get_data_chunk_count();
   unsigned int m = get_chunk_count() - k;
   unsigned blocksize = get_chunk_size(raw.length());
-  unsigned padded_length = blocksize * k;
-  *prepared = raw;
-  if (padded_length - raw.length() > 0) {
-    bufferptr pad(padded_length - raw.length());
-    pad.zero();
-    prepared->push_back(pad);
+  unsigned pad_len = blocksize * k - raw.length();
+  unsigned padded_chunks = k - raw.length() / blocksize;
+  bufferlist prepared = raw;
+
+  if (!prepared.is_aligned(SIMD_ALIGN)) {
+    // splice padded chunks off to make the rebuild faster
+    if (padded_chunks)
+      prepared.splice((k - padded_chunks) * blocksize,
+                      padded_chunks * blocksize - pad_len);
+    prepared.rebuild_aligned(SIMD_ALIGN);
+  }
+
+  for (unsigned int i = 0; i < k - padded_chunks; i++) {
+    bufferlist &chunk = encoded[chunk_index(i)];
+    chunk.substr_of(prepared, i * blocksize, blocksize);
   }
-  unsigned coding_length = blocksize * m;
-  bufferptr coding(buffer::create_page_aligned(coding_length));
-  prepared->push_back(coding);
-  prepared->rebuild_page_aligned();
+  if (padded_chunks) {
+    unsigned remainder = raw.length() - (k - padded_chunks) * blocksize;
+    bufferptr buf(buffer::create_aligned(blocksize, SIMD_ALIGN));
+
+    raw.copy((k - padded_chunks) * blocksize, remainder, buf.c_str());
+    buf.zero(remainder, blocksize - remainder);
+    encoded[chunk_index(k-padded_chunks)].push_back(buf);
+
+    for (unsigned int i = k - padded_chunks + 1; i < k; i++) {
+      bufferptr buf(buffer::create_aligned(blocksize, SIMD_ALIGN));
+      buf.zero();
+      encoded[chunk_index(i)].push_back(buf);
+    }
+  }
+  for (unsigned int i = k; i < k + m; i++) {
+    bufferlist &chunk = encoded[chunk_index(i)];
+    chunk.push_back(buffer::create_aligned(blocksize, SIMD_ALIGN));
+  }
+
   return 0;
 }
 
@@ -80,15 +111,9 @@ int ErasureCode::encode(const set<int> &want_to_encode,
   unsigned int k = get_data_chunk_count();
   unsigned int m = get_chunk_count() - k;
   bufferlist out;
-  int err = encode_prepare(in, &out);
+  int err = encode_prepare(in, *encoded);
   if (err)
     return err;
-  unsigned blocksize = get_chunk_size(in.length());
-  for (unsigned int i = 0; i < k + m; i++) {
-    int chunk_index = chunk_mapping.size() > 0 ? chunk_mapping[i] : i;
-    bufferlist &chunk = (*encoded)[chunk_index];
-    chunk.substr_of(out, i * blocksize, blocksize);
-  }
   encode_chunks(want_to_encode, encoded);
   for (unsigned int i = 0; i < k + m; i++) {
     if (want_to_encode.count(i) == 0)
@@ -128,11 +153,11 @@ int ErasureCode::decode(const set<int> &want_to_read,
   unsigned blocksize = (*chunks.begin()).second.length();
   for (unsigned int i =  0; i < k + m; i++) {
     if (chunks.find(i) == chunks.end()) {
-      bufferptr ptr(buffer::create_page_aligned(blocksize));
+      bufferptr ptr(buffer::create_aligned(blocksize, SIMD_ALIGN));
       (*decoded)[i].push_front(ptr);
     } else {
       (*decoded)[i] = chunks.find(i)->second;
-      (*decoded)[i].rebuild_page_aligned();
+      (*decoded)[i].rebuild_aligned(SIMD_ALIGN);
     }
   }
   return decode_chunks(want_to_read, chunks, decoded);
@@ -223,15 +248,13 @@ int ErasureCode::decode_concat(const map<int, bufferlist> &chunks,
   set<int> want_to_read;
 
   for (unsigned int i = 0; i < get_data_chunk_count(); i++) {
-    int chunk = chunk_mapping.size() > i ? chunk_mapping[i] : i;
-    want_to_read.insert(chunk);
+    want_to_read.insert(chunk_index(i));
   }
   map<int, bufferlist> decoded_map;
   int r = decode(want_to_read, chunks, &decoded_map);
   if (r == 0) {
     for (unsigned int i = 0; i < get_data_chunk_count(); i++) {
-      int chunk = chunk_mapping.size() > i ? chunk_mapping[i] : i;
-      decoded->claim_append(decoded_map[chunk]);
+      decoded->claim_append(decoded_map[chunk_index(i)]);
     }
   }
   return r;
diff --git a/src/erasure-code/ErasureCode.h b/src/erasure-code/ErasureCode.h
index 7aaea95..b135ade 100644
--- a/src/erasure-code/ErasureCode.h
+++ b/src/erasure-code/ErasureCode.h
@@ -30,6 +30,8 @@ namespace ceph {
 
   class ErasureCode : public ErasureCodeInterface {
   public:
+    static const unsigned SIMD_ALIGN;
+
     vector<int> chunk_mapping;
 
     virtual ~ErasureCode() {}
@@ -46,7 +48,8 @@ namespace ceph {
                                             const map<int, int> &available,
                                             set<int> *minimum);
 
-    int encode_prepare(const bufferlist &raw, bufferlist *prepared) const;
+    int encode_prepare(const bufferlist &raw,
+                       map<int, bufferlist> &encoded) const;
 
     virtual int encode(const set<int> &want_to_encode,
                        const bufferlist &in,
@@ -85,6 +88,9 @@ namespace ceph {
 
     virtual int decode_concat(const map<int, bufferlist> &chunks,
 			      bufferlist *decoded);
+
+  private:
+    int chunk_index(unsigned int i) const;
   };
 }
 
diff --git a/src/include/buffer.h b/src/include/buffer.h
index e5c1b50..3cd0a7a 100644
--- a/src/include/buffer.h
+++ b/src/include/buffer.h
@@ -144,6 +144,7 @@ public:
   static raw* create_malloc(unsigned len);
   static raw* claim_malloc(unsigned len, char *buf);
   static raw* create_static(unsigned len, char *buf);
+  static raw* create_aligned(unsigned len, unsigned align);
   static raw* create_page_aligned(unsigned len);
   static raw* create_zero_copy(unsigned len, int fd, int64_t *offset);
 
@@ -177,8 +178,15 @@ public:
     bool at_buffer_head() const { return _off == 0; }
     bool at_buffer_tail() const;
 
-    bool is_page_aligned() const { return ((long)c_str() & ~CEPH_PAGE_MASK) == 0; }
-    bool is_n_page_sized() const { return (length() & ~CEPH_PAGE_MASK) == 0; }
+    bool is_aligned(unsigned align) const {
+      return ((long)c_str() & (align-1)) == 0;
+    }
+    bool is_page_aligned() const { return is_aligned(CEPH_PAGE_SIZE); }
+    bool is_n_align_sized(unsigned align) const
+    {
+      return (length() & (align-1)) == 0;
+    }
+    bool is_n_page_sized() const { return is_n_align_sized(CEPH_PAGE_SIZE); }
 
     // accessors
     raw *get_raw() const { return _raw; }
@@ -344,7 +352,9 @@ public:
     bool contents_equal(buffer::list& other);
 
     bool can_zero_copy() const;
+    bool is_aligned(unsigned align) const;
     bool is_page_aligned() const;
+    bool is_n_align_sized(unsigned align) const;
     bool is_n_page_sized() const;
 
     bool is_zero() const;
@@ -382,6 +392,7 @@ public:
     bool is_contiguous();
     void rebuild();
     void rebuild(ptr& nb);
+    void rebuild_aligned(unsigned align);
     void rebuild_page_aligned();
 
     // sort-of-like-assignment-op
diff --git a/src/include/rados/buffer.h b/src/include/rados/buffer.h
index e5c1b50..3cd0a7a 100644
--- a/src/include/rados/buffer.h
+++ b/src/include/rados/buffer.h
@@ -144,6 +144,7 @@ public:
   static raw* create_malloc(unsigned len);
   static raw* claim_malloc(unsigned len, char *buf);
   static raw* create_static(unsigned len, char *buf);
+  static raw* create_aligned(unsigned len, unsigned align);
   static raw* create_page_aligned(unsigned len);
   static raw* create_zero_copy(unsigned len, int fd, int64_t *offset);
 
@@ -177,8 +178,15 @@ public:
     bool at_buffer_head() const { return _off == 0; }
     bool at_buffer_tail() const;
 
-    bool is_page_aligned() const { return ((long)c_str() & ~CEPH_PAGE_MASK) == 0; }
-    bool is_n_page_sized() const { return (length() & ~CEPH_PAGE_MASK) == 0; }
+    bool is_aligned(unsigned align) const {
+      return ((long)c_str() & (align-1)) == 0;
+    }
+    bool is_page_aligned() const { return is_aligned(CEPH_PAGE_SIZE); }
+    bool is_n_align_sized(unsigned align) const
+    {
+      return (length() & (align-1)) == 0;
+    }
+    bool is_n_page_sized() const { return is_n_align_sized(CEPH_PAGE_SIZE); }
 
     // accessors
     raw *get_raw() const { return _raw; }
@@ -344,7 +352,9 @@ public:
     bool contents_equal(buffer::list& other);
 
     bool can_zero_copy() const;
+    bool is_aligned(unsigned align) const;
     bool is_page_aligned() const;
+    bool is_n_align_sized(unsigned align) const;
     bool is_n_page_sized() const;
 
     bool is_zero() const;
@@ -382,6 +392,7 @@ public:
     bool is_contiguous();
     void rebuild();
     void rebuild(ptr& nb);
+    void rebuild_aligned(unsigned align);
     void rebuild_page_aligned();
 
     // sort-of-like-assignment-op
diff --git a/src/java/native/libcephfs_jni.cc b/src/java/native/libcephfs_jni.cc
index a96b20d..99ab3f4 100644
--- a/src/java/native/libcephfs_jni.cc
+++ b/src/java/native/libcephfs_jni.cc
@@ -1775,7 +1775,6 @@ JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1fstat
 {
 	struct ceph_mount_info *cmount = get_ceph_mount(j_mntp);
 	CephContext *cct = ceph_get_mount_context(cmount);
-	long long time;
 	struct stat st;
 	int ret;
 
@@ -1793,22 +1792,7 @@ JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1fstat
 		return ret;
 	}
 
-	env->SetIntField(j_cephstat, cephstat_mode_fid, st.st_mode);
-	env->SetIntField(j_cephstat, cephstat_uid_fid, st.st_uid);
-	env->SetIntField(j_cephstat, cephstat_gid_fid, st.st_gid);
-	env->SetLongField(j_cephstat, cephstat_size_fid, st.st_size);
-	env->SetLongField(j_cephstat, cephstat_blksize_fid, st.st_blksize);
-	env->SetLongField(j_cephstat, cephstat_blocks_fid, st.st_blocks);
-
-	time = st.st_mtim.tv_sec;
-	time *= 1000;
-	time += st.st_mtim.tv_nsec / 1000;
-	env->SetLongField(j_cephstat, cephstat_m_time_fid, time);
-
-	time = st.st_atim.tv_sec;
-	time *= 1000;
-	time += st.st_atim.tv_nsec / 1000;
-	env->SetLongField(j_cephstat, cephstat_a_time_fid, time);
+	fill_cephstat(env, j_cephstat, &st);
 
 	return ret;
 }
diff --git a/src/mds/InoTable.cc b/src/mds/InoTable.cc
index a717cd9..5185695 100644
--- a/src/mds/InoTable.cc
+++ b/src/mds/InoTable.cc
@@ -29,13 +29,13 @@ void InoTable::reset_state()
   free.clear();
   //#ifdef __LP64__
   uint64_t start = (uint64_t)(mds->get_nodeid()+1) << 40;
-  uint64_t end = ((uint64_t)(mds->get_nodeid()+2) << 40) - 1;
+  uint64_t len = (uint64_t)1 << 40;
   //#else
   //# warning this looks like a 32-bit system, using small inode numbers.
   //  uint64_t start = (uint64_t)(mds->get_nodeid()+1) << 25;
   //  uint64_t end = ((uint64_t)(mds->get_nodeid()+2) << 25) - 1;
   //#endif
-  free.insert(start, end);
+  free.insert(start, len);
 
   projected_free = free;
 }
@@ -147,9 +147,8 @@ void InoTable::skip_inos(inodeno_t i)
 {
   dout(10) << "skip_inos was " << free << dendl;
   inodeno_t first = free.range_start();
-  inodeno_t last = first + i;
   interval_set<inodeno_t> s;
-  s.insert(first, last);
+  s.insert(first, i);
   s.intersection_of(free);
   free.subtract(s);
   projected_free = free;
diff --git a/src/mds/Server.cc b/src/mds/Server.cc
index 22b00d7..b35cb56 100644
--- a/src/mds/Server.cc
+++ b/src/mds/Server.cc
@@ -3188,6 +3188,7 @@ void Server::handle_client_file_setlock(MDRequestRef& mdr)
   default:
     dout(10) << "got unknown lock type " << set_lock.type
 	     << ", dropping request!" << dendl;
+    reply_request(mdr, -EOPNOTSUPP);
     return;
   }
 
diff --git a/src/mon/Monitor.cc b/src/mon/Monitor.cc
index a9f10bd..52df6f0 100644
--- a/src/mon/Monitor.cc
+++ b/src/mon/Monitor.cc
@@ -3179,6 +3179,17 @@ void Monitor::dispatch(MonSession *s, Message *m, const bool src_is_mon)
       handle_ping(static_cast<MPing*>(m));
       break;
 
+    /* MMonGetMap may be used by clients to obtain a monmap *before*
+     * authenticating with the monitor.  We need to handle these without
+     * checking caps because, even on a cluster without cephx, we only set
+     * session caps *after* the auth handshake.  A good example of this
+     * is when a client calls MonClient::get_monmap_privately(), which does
+     * not authenticate when obtaining a monmap.
+     */
+    case CEPH_MSG_MON_GET_MAP:
+      handle_mon_get_map(static_cast<MMonGetMap*>(m));
+      break;
+
     default:
       dealt_with = false;
       break;
@@ -3249,10 +3260,6 @@ void Monitor::dispatch(MonSession *s, Message *m, const bool src_is_mon)
   switch (m->get_type()) {
 
     // misc
-    case CEPH_MSG_MON_GET_MAP:
-      handle_mon_get_map(static_cast<MMonGetMap*>(m));
-      break;
-
     case CEPH_MSG_MON_GET_VERSION:
       handle_get_version(static_cast<MMonGetVersion*>(m));
       break;
diff --git a/src/os/FDCache.h b/src/os/FDCache.h
index 5b06e34..9e77873 100644
--- a/src/os/FDCache.h
+++ b/src/os/FDCache.h
@@ -85,11 +85,7 @@ public:
   /// clear cached fd for hoid, subsequent lookups will get an empty FD
   void clear(const ghobject_t &hoid) {
     int registry_id = hoid.hobj.hash % registry_shards;
-    registry[registry_id].clear(hoid);
-    if (registry[registry_id].lookup(hoid)) {
-      registry[registry_id].dump_weak_refs();
-      assert(!registry[registry_id].lookup(hoid));
-    }
+    registry[registry_id].purge(hoid);
   }
 
   /// md_config_obs_t
diff --git a/src/os/FileStore.cc b/src/os/FileStore.cc
index 99a2502..1bb4de9 100644
--- a/src/os/FileStore.cc
+++ b/src/os/FileStore.cc
@@ -3533,7 +3533,7 @@ void FileStore::sync_entry()
       dout(10) << "sync_entry more waiters, committing again" << dendl;
       goto again;
     }
-    if (journal && journal->should_commit_now()) {
+    if (!stop && journal && journal->should_commit_now()) {
       dout(10) << "sync_entry journal says we should commit again (probably is/was full)" << dendl;
       goto again;
     }
diff --git a/src/os/LevelDBStore.h b/src/os/LevelDBStore.h
index 3dbc0f9..4617c5c 100644
--- a/src/os/LevelDBStore.h
+++ b/src/os/LevelDBStore.h
@@ -341,7 +341,10 @@ public:
       // happen when those files are being updated, data is being shuffled
       // and files get removed, in which case there's not much of a problem
       // as we'll get to them next time around.
-      if ((err < 0) && (err != -ENOENT)) {
+      if (err == -ENOENT) {
+	continue;
+      }
+      if (err < 0) {
         lderr(cct) << __func__ << " error obtaining stats for " << fpath
                    << ": " << cpp_strerror(err) << dendl;
         goto err;
diff --git a/src/os/RocksDBStore.h b/src/os/RocksDBStore.h
index 318f259..5c3160f 100644
--- a/src/os/RocksDBStore.h
+++ b/src/os/RocksDBStore.h
@@ -285,7 +285,10 @@ public:
       // happen when those files are being updated, data is being shuffled
       // and files get removed, in which case there's not much of a problem
       // as we'll get to them next time around.
-      if ((err < 0) && (err != -ENOENT)) {
+      if (err == -ENOENT) {
+	continue;
+      }
+      if (err < 0) {
         lderr(cct) << __func__ << " error obtaining stats for " << fpath
                    << ": " << cpp_strerror(err) << dendl;
         goto err;
diff --git a/src/osd/PG.cc b/src/osd/PG.cc
index c9cb756..eedc26b 100644
--- a/src/osd/PG.cc
+++ b/src/osd/PG.cc
@@ -1895,7 +1895,7 @@ void PG::mark_clean()
 {
   // only mark CLEAN if we have the desired number of replicas AND we
   // are not remapped.
-  if (acting.size() == get_osdmap()->get_pg_size(info.pgid.pgid) &&
+  if (actingset.size() == get_osdmap()->get_pg_size(info.pgid.pgid) &&
       up == acting)
     state_set(PG_STATE_CLEAN);
 
@@ -4568,7 +4568,10 @@ bool PG::old_peering_msg(epoch_t reply_epoch, epoch_t query_epoch)
 void PG::set_last_peering_reset()
 {
   dout(20) << "set_last_peering_reset " << get_osdmap()->get_epoch() << dendl;
-  last_peering_reset = get_osdmap()->get_epoch();
+  if (last_peering_reset != get_osdmap()->get_epoch()) {
+    last_peering_reset = get_osdmap()->get_epoch();
+    reset_interval_flush();
+  }
 }
 
 struct FlushState {
@@ -4622,7 +4625,6 @@ void PG::start_peering_interval(
   const OSDMapRef osdmap = get_osdmap();
 
   set_last_peering_reset();
-  reset_interval_flush();
 
   vector<int> oldacting, oldup;
   int oldrole = get_role();
diff --git a/src/osd/ReplicatedPG.cc b/src/osd/ReplicatedPG.cc
index d3311b8..b90f1c0 100644
--- a/src/osd/ReplicatedPG.cc
+++ b/src/osd/ReplicatedPG.cc
@@ -11185,7 +11185,7 @@ void ReplicatedPG::hit_set_persist()
       pg_log_entry_t::MODIFY,
       oid,
       ctx->at_version,
-      ctx->obs->oi.version,
+      eversion_t(),
       0,
       osd_reqid_t(),
       ctx->mtime)
diff --git a/src/osd/osd_types.cc b/src/osd/osd_types.cc
index d7081b9..ed06c4f 100644
--- a/src/osd/osd_types.cc
+++ b/src/osd/osd_types.cc
@@ -2329,18 +2329,45 @@ bool pg_interval_t::is_new_interval(
   int new_up_primary,
   const vector<int> &old_up,
   const vector<int> &new_up,
-  OSDMapRef osdmap,
-  OSDMapRef lastmap,
+  int old_min_size,
+  int new_min_size,
+  unsigned old_pg_num,
+  unsigned new_pg_num,
   pg_t pgid) {
   return old_acting_primary != new_acting_primary ||
     new_acting != old_acting ||
     old_up_primary != new_up_primary ||
     new_up != old_up ||
-    (!(lastmap->get_pools().count(pgid.pool()))) ||
-    (lastmap->get_pools().find(pgid.pool())->second.min_size !=
-     osdmap->get_pools().find(pgid.pool())->second.min_size)  ||
-    pgid.is_split(lastmap->get_pg_num(pgid.pool()),
-		  osdmap->get_pg_num(pgid.pool()), 0);
+    old_min_size != new_min_size ||
+    pgid.is_split(old_pg_num, new_pg_num, 0);
+}
+
+bool pg_interval_t::is_new_interval(
+  int old_acting_primary,
+  int new_acting_primary,
+  const vector<int> &old_acting,
+  const vector<int> &new_acting,
+  int old_up_primary,
+  int new_up_primary,
+  const vector<int> &old_up,
+  const vector<int> &new_up,
+  OSDMapRef osdmap,
+  OSDMapRef lastmap,
+  pg_t pgid) {
+  return !(lastmap->get_pools().count(pgid.pool())) ||
+    is_new_interval(old_acting_primary,
+		    new_acting_primary,
+		    old_acting,
+		    new_acting,
+		    old_up_primary,
+		    new_up_primary,
+		    old_up,
+		    new_up,
+		    lastmap->get_pools().find(pgid.pool())->second.min_size,
+		    osdmap->get_pools().find(pgid.pool())->second.min_size,
+		    lastmap->get_pg_num(pgid.pool()),
+		    osdmap->get_pg_num(pgid.pool()),
+		    pgid);
 }
 
 bool pg_interval_t::check_new_interval(
@@ -2384,9 +2411,15 @@ bool pg_interval_t::check_new_interval(
     i.primary = old_acting_primary;
     i.up_primary = old_up_primary;
 
-    if (!i.acting.empty() && i.primary != -1 &&
-	i.acting.size() >=
-	lastmap->get_pools().find(pgid.pool())->second.min_size) {
+    unsigned num_acting = 0;
+    for (vector<int>::const_iterator p = i.acting.begin(); p != i.acting.end();
+	 ++p)
+      if (*p != CRUSH_ITEM_NONE)
+	++num_acting;
+
+    if (num_acting &&
+	i.primary != -1 &&
+	num_acting >= lastmap->get_pools().find(pgid.pool())->second.min_size) {
       if (out)
 	*out << "generate_past_intervals " << i
 	     << ": not rw,"
diff --git a/src/osd/osd_types.h b/src/osd/osd_types.h
index 9840bf1..988cebe 100644
--- a/src/osd/osd_types.h
+++ b/src/osd/osd_types.h
@@ -1777,6 +1777,25 @@ struct pg_interval_t {
    * Determines whether there is an interval change
    */
   static bool is_new_interval(
+    int old_acting_primary,
+    int new_acting_primary,
+    const vector<int> &old_acting,
+    const vector<int> &new_acting,
+    int old_up_primary,
+    int new_up_primary,
+    const vector<int> &old_up,
+    const vector<int> &new_up,
+    int old_min_size,
+    int new_min_size,
+    unsigned old_pg_num,
+    unsigned new_pg_num,
+    pg_t pgid
+    );
+
+  /**
+   * Determines whether there is an interval change
+   */
+  static bool is_new_interval(
     int old_acting_primary,                     ///< [in] primary as of lastmap
     int new_acting_primary,                     ///< [in] primary as of lastmap
     const vector<int> &old_acting,              ///< [in] acting as of lastmap
diff --git a/src/osdc/ObjectCacher.cc b/src/osdc/ObjectCacher.cc
index 93cede5..8455fb6 100644
--- a/src/osdc/ObjectCacher.cc
+++ b/src/osdc/ObjectCacher.cc
@@ -709,9 +709,6 @@ void ObjectCacher::bh_read_finish(int64_t poolid, sobject_t oid, ceph_tid_t tid,
       }
     }
 
-    ls.splice(ls.end(), waitfor_read);
-    waitfor_read.clear();
-
     // apply to bh's!
     loff_t opos = start;
     while (true) {
@@ -1113,26 +1110,13 @@ int ObjectCacher::_readx(OSDRead *rd, ObjectSet *oset, Context *onfinish,
       for (map<loff_t, BufferHead*>::iterator bh_it = missing.begin();
            bh_it != missing.end();
            ++bh_it) {
-        loff_t clean = get_stat_clean() + get_stat_rx() +
-                       bh_it->second->length();
-        if (get_stat_rx() > 0 && static_cast<uint64_t>(clean) > max_size) {
-          // cache is full -- wait for rx's to complete
-          ldout(cct, 10) << "readx missed, waiting on cache to free "
-                         << (clean - max_size) << " bytes" << dendl;
-          if (success) {
-            waitfor_read.push_back(new C_RetryRead(this, rd, oset, onfinish));
-          }
-          bh_remove(o, bh_it->second);
-          delete bh_it->second;
-        } else {
-          bh_read(bh_it->second);
-          if (success && onfinish) {
-            ldout(cct, 10) << "readx missed, waiting on " << *bh_it->second 
-                     << " off " << bh_it->first << dendl;
-	    bh_it->second->waitfor_read[bh_it->first].push_back( new C_RetryRead(this, rd, oset, onfinish) );
-          }
-          bytes_not_in_cache += bh_it->second->length();
+        bh_read(bh_it->second);
+        if (success && onfinish) {
+          ldout(cct, 10) << "readx missed, waiting on " << *bh_it->second 
+                   << " off " << bh_it->first << dendl;
+	  bh_it->second->waitfor_read[bh_it->first].push_back( new C_RetryRead(this, rd, oset, onfinish) );
         }
+        bytes_not_in_cache += bh_it->second->length();
 	success = false;
       }
 
diff --git a/src/osdc/ObjectCacher.h b/src/osdc/ObjectCacher.h
index 9685ee3..ca16138 100644
--- a/src/osdc/ObjectCacher.h
+++ b/src/osdc/ObjectCacher.h
@@ -340,7 +340,6 @@ class ObjectCacher {
   void *flush_set_callback_arg;
 
   vector<ceph::unordered_map<sobject_t, Object*> > objects; // indexed by pool_id
-  list<Context*> waitfor_read;
 
   ceph_tid_t last_read_tid;
 
diff --git a/src/osdc/Objecter.cc b/src/osdc/Objecter.cc
index a2c4ddb..e9d0ade 100644
--- a/src/osdc/Objecter.cc
+++ b/src/osdc/Objecter.cc
@@ -292,7 +292,7 @@ void Objecter::shutdown()
 {
   assert(initialized.read());
 
-  RWLock::WLocker wl(rwlock);
+  rwlock.get_write();
 
   initialized.set(0);
 
@@ -342,38 +342,43 @@ void Objecter::shutdown()
   while(!homeless_session->linger_ops.empty()) {
     std::map<uint64_t, LingerOp*>::iterator i = homeless_session->linger_ops.begin();
     ldout(cct, 10) << " linger_op " << i->first << dendl;
+    LingerOp *lop = i->second;
     {
       RWLock::WLocker wl(homeless_session->lock);
-      _session_linger_op_remove(homeless_session, i->second);
+      _session_linger_op_remove(homeless_session, lop);
     }
-    linger_ops.erase(i->second->linger_id);
-    i->second->put();
+    linger_ops.erase(lop->linger_id);
+    lop->put();
   }
 
   while(!homeless_session->ops.empty()) {
     std::map<ceph_tid_t, Op*>::iterator i = homeless_session->ops.begin();
     ldout(cct, 10) << " op " << i->first << dendl;
+    Op *op = i->second;
     {
       RWLock::WLocker wl(homeless_session->lock);
-      _session_op_remove(homeless_session, i->second);
+      _session_op_remove(homeless_session, op);
     }
-    i->second->put();
+    op->put();
   }
 
   while(!homeless_session->command_ops.empty()) {
     std::map<ceph_tid_t, CommandOp*>::iterator i = homeless_session->command_ops.begin();
     ldout(cct, 10) << " command_op " << i->first << dendl;
+    CommandOp *cop = i->second;
     {
       RWLock::WLocker wl(homeless_session->lock);
-      _session_command_op_remove(homeless_session, i->second);
+      _session_command_op_remove(homeless_session, cop);
     }
-    i->second->put();
+    cop->put();
   }
 
   if (tick_event) {
     Mutex::Locker l(timer_lock);
-    if (timer.cancel_event(tick_event))
+    if (timer.cancel_event(tick_event)) {
+      ldout(cct, 10) <<  " successfully canceled tick" << dendl;
       tick_event = NULL;
+    }
   }
 
   if (m_request_state_hook) {
@@ -389,11 +394,15 @@ void Objecter::shutdown()
     logger = NULL;
   }
 
+  // Let go of Objecter write lock so timer thread can shutdown
+  rwlock.unlock();
+
   {
     Mutex::Locker l(timer_lock);
     timer.shutdown();
   }
 
+  assert(tick_event == NULL);
 }
 
 void Objecter::_send_linger(LingerOp *info)
@@ -1303,22 +1312,22 @@ void Objecter::close_session(OSDSession *s)
   while(!s->linger_ops.empty()) {
     std::map<uint64_t, LingerOp*>::iterator i = s->linger_ops.begin();
     ldout(cct, 10) << " linger_op " << i->first << dendl;
-    _session_linger_op_remove(s, i->second);
     homeless_lingers.push_back(i->second);
+    _session_linger_op_remove(s, i->second);
   }
 
   while(!s->ops.empty()) {
     std::map<ceph_tid_t, Op*>::iterator i = s->ops.begin();
     ldout(cct, 10) << " op " << i->first << dendl;
-    _session_op_remove(s, i->second);
     homeless_ops.push_back(i->second);
+    _session_op_remove(s, i->second);
   }
 
   while(!s->command_ops.empty()) {
     std::map<ceph_tid_t, CommandOp*>::iterator i = s->command_ops.begin();
     ldout(cct, 10) << " command_op " << i->first << dendl;
-    _session_command_op_remove(s, i->second);
     homeless_commands.push_back(i->second);
+    _session_command_op_remove(s, i->second);
   }
 
   osd_sessions.erase(s->osd);
@@ -1546,6 +1555,7 @@ void Objecter::tick()
 
   if (!initialized.read()) {
     // we raced with shutdown
+    ldout(cct, 10) << __func__ << " raced with shutdown" << dendl;
     return;
   }
 
@@ -1563,6 +1573,7 @@ void Objecter::tick()
     laggy_ops = 0;
     for (map<int,OSDSession*>::iterator siter = osd_sessions.begin(); siter != osd_sessions.end(); ++siter) {
       OSDSession *s = siter->second;
+      RWLock::RLocker l(s->lock);
       for (map<ceph_tid_t,Op*>::iterator p = s->ops.begin();
            p != s->ops.end();
            ++p) {
@@ -2043,9 +2054,29 @@ int Objecter::_calc_target(op_target_t *t, bool any_change)
       return RECALC_OP_TARGET_POOL_DNE;
     }
   }
-  int primary;
-  vector<int> acting;
-  osdmap->pg_to_acting_osds(pgid, &acting, &primary);
+
+  int min_size = pi->min_size;
+  unsigned pg_num = pi->get_pg_num();
+  int up_primary, acting_primary;
+  vector<int> up, acting;
+  osdmap->pg_to_up_acting_osds(pgid, &up, &up_primary,
+			       &acting, &acting_primary);
+  if (any_change && pg_interval_t::is_new_interval(
+          t->acting_primary,
+	  acting_primary,
+	  t->acting,
+	  acting,
+	  t->up_primary,
+	  up_primary,
+	  t->up,
+	  up,
+	  t->min_size,
+	  min_size,
+	  t->pg_num,
+	  pg_num,
+	  pi->raw_pg_to_pg(pgid))) {
+    force_resend = true;
+  }
 
   bool need_resend = false;
 
@@ -2057,15 +2088,20 @@ int Objecter::_calc_target(op_target_t *t, bool any_change)
 
   if (t->pgid != pgid ||
       is_pg_changed(
-	t->primary, t->acting, primary, acting, t->used_replica || any_change) ||
+	t->acting_primary, t->acting, acting_primary, acting,
+	t->used_replica || any_change) ||
       force_resend) {
     t->pgid = pgid;
     t->acting = acting;
-    t->primary = primary;
+    t->acting_primary = acting_primary;
+    t->up_primary = up_primary;
+    t->up = up;
+    t->min_size = min_size;
+    t->pg_num = pg_num;
     ldout(cct, 10) << __func__ << " "
 		   << " pgid " << pgid << " acting " << acting << dendl;
     t->used_replica = false;
-    if (primary == -1) {
+    if (acting_primary == -1) {
       t->osd = -1;
     } else {
       int osd;
@@ -2101,7 +2137,7 @@ int Objecter::_calc_target(op_target_t *t, bool any_change)
 	assert(best >= 0);
 	osd = acting[best];
       } else {
-	osd = primary;
+	osd = acting_primary;
       }
       t->osd = osd;
     }
diff --git a/src/osdc/Objecter.h b/src/osdc/Objecter.h
index b45f406..8bf1350 100644
--- a/src/osdc/Objecter.h
+++ b/src/osdc/Objecter.h
@@ -1078,8 +1078,12 @@ public:
     pg_t base_pgid;      ///< explciti pg target, if any
 
     pg_t pgid;           ///< last pg we mapped to
-    vector<int> acting;  ///< acting for last pg we mapped to
-    int primary;         ///< primary for last pg we mapped to
+    unsigned pg_num;     ///< last pg_num we mapped to
+    vector<int> up;      ///< set of up osds for last pg we mapped to
+    vector<int> acting;  ///< set of acting osds for last pg we mapped to
+    int up_primary;      ///< primary for last pg we mapped to based on the up set
+    int acting_primary;  ///< primary for last pg we mapped to based on the acting set
+    int min_size;        ///< the min size of the pool when were were last mapped
 
     bool used_replica;
     bool paused;
@@ -1091,7 +1095,10 @@ public:
 	base_oid(oid),
 	base_oloc(oloc),
 	precalc_pgid(false),
-	primary(-1),
+	pg_num(0),
+	up_primary(-1),
+	acting_primary(-1),
+	min_size(-1),
 	used_replica(false),
 	paused(false),
 	osd(-1)
diff --git a/src/test/Makefile.am b/src/test/Makefile.am
index 2c9b848..bbc9c97 100644
--- a/src/test/Makefile.am
+++ b/src/test/Makefile.am
@@ -293,6 +293,11 @@ unittest_sharedptr_registry_CXXFLAGS = $(UNITTEST_CXXFLAGS)
 unittest_sharedptr_registry_LDADD = $(UNITTEST_LDADD) $(CEPH_GLOBAL)
 check_PROGRAMS += unittest_sharedptr_registry
 
+unittest_shared_cache_SOURCES = test/common/test_shared_cache.cc
+unittest_shared_cache_CXXFLAGS = $(UNITTEST_CXXFLAGS)
+unittest_shared_cache_LDADD = $(UNITTEST_LDADD) $(CEPH_GLOBAL)
+check_PROGRAMS += unittest_shared_cache
+
 unittest_sloppy_crc_map_SOURCES = test/common/test_sloppy_crc_map.cc
 unittest_sloppy_crc_map_CXXFLAGS = $(UNITTEST_CXXFLAGS)
 unittest_sloppy_crc_map_LDADD = $(UNITTEST_LDADD) $(CEPH_GLOBAL)
diff --git a/src/test/bufferlist.cc b/src/test/bufferlist.cc
index 3b379af..da4d33f 100644
--- a/src/test/bufferlist.cc
+++ b/src/test/bufferlist.cc
@@ -1122,6 +1122,52 @@ TEST(BufferList, contents_equal) {
   ASSERT_FALSE(bl1.contents_equal(bl3)); // same length different content
 }
 
+TEST(BufferList, is_aligned) {
+  const int SIMD_ALIGN = 32;
+  {
+    bufferlist bl;
+    EXPECT_TRUE(bl.is_aligned(SIMD_ALIGN));
+  }
+  {
+    bufferlist bl;
+    bufferptr ptr(buffer::create_aligned(2, SIMD_ALIGN));
+    ptr.set_offset(1);
+    ptr.set_length(1);
+    bl.append(ptr);
+    EXPECT_FALSE(bl.is_aligned(SIMD_ALIGN));
+    bl.rebuild_aligned(SIMD_ALIGN);
+    EXPECT_TRUE(bl.is_aligned(SIMD_ALIGN));
+  }
+  {
+    bufferlist bl;
+    bufferptr ptr(buffer::create_aligned(SIMD_ALIGN + 1, SIMD_ALIGN));
+    ptr.set_offset(1);
+    ptr.set_length(SIMD_ALIGN);
+    bl.append(ptr);
+    EXPECT_FALSE(bl.is_aligned(SIMD_ALIGN));
+    bl.rebuild_aligned(SIMD_ALIGN);
+    EXPECT_TRUE(bl.is_aligned(SIMD_ALIGN));
+  }
+}
+
+TEST(BufferList, is_n_align_sized) {
+  const int SIMD_ALIGN = 32;
+  {
+    bufferlist bl;
+    EXPECT_TRUE(bl.is_n_align_sized(SIMD_ALIGN));
+  }
+  {
+    bufferlist bl;
+    bl.append_zero(1);
+    EXPECT_FALSE(bl.is_n_align_sized(SIMD_ALIGN));
+  }
+  {
+    bufferlist bl;
+    bl.append_zero(SIMD_ALIGN);
+    EXPECT_TRUE(bl.is_n_align_sized(SIMD_ALIGN));
+  }
+}
+
 TEST(BufferList, is_page_aligned) {
   {
     bufferlist bl;
diff --git a/src/test/common/test_shared_cache.cc b/src/test/common/test_shared_cache.cc
new file mode 100644
index 0000000..bafef26
--- /dev/null
+++ b/src/test/common/test_shared_cache.cc
@@ -0,0 +1,77 @@
+// -*- 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>
+ *
+ * Author: Loic Dachary <loic at dachary.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library Public License for more details.
+ *
+ */
+
+#include <stdio.h>
+#include <signal.h>
+#include "common/Thread.h"
+#include "common/shared_cache.hpp"
+#include "common/ceph_argparse.h"
+#include "global/global_init.h"
+#include <gtest/gtest.h>
+
+using namespace std::tr1;
+
+TEST(SharedCache_all, add) {
+  SharedLRU<int, int> cache;
+  unsigned int key = 1;
+  int value = 2;
+  shared_ptr<int> ptr = cache.add(key, new int(value));
+  ASSERT_EQ(ptr, cache.lookup(key));
+  ASSERT_EQ(value, *cache.lookup(key));
+}
+
+TEST(SharedCache_all, lru) {
+  const size_t SIZE = 5;
+  SharedLRU<int, int> cache(NULL, SIZE);
+
+  bool existed = false;
+  shared_ptr<int> ptr = cache.add(0, new int(0), &existed);
+  ASSERT_FALSE(existed);
+  {
+    int *tmpint = new int(0);
+    shared_ptr<int> ptr2 = cache.add(0, tmpint, &existed);
+    ASSERT_TRUE(existed);
+    delete tmpint;
+  }
+  for (size_t i = 1; i < 2*SIZE; ++i) {
+    cache.add(i, new int(i), &existed);
+    ASSERT_FALSE(existed);
+  }
+
+  ASSERT_TRUE(cache.lookup(0));
+  ASSERT_EQ(0, *cache.lookup(0));
+
+  ASSERT_FALSE(cache.lookup(SIZE-1));
+  ASSERT_FALSE(cache.lookup(SIZE));
+  ASSERT_TRUE(cache.lookup(SIZE+1));
+  ASSERT_EQ(SIZE+1, *cache.lookup(SIZE+1));
+
+  cache.purge(0);
+  ASSERT_FALSE(cache.lookup(0));
+  shared_ptr<int> ptr2 = cache.add(0, new int(0), &existed);
+  ASSERT_FALSE(ptr == ptr2);
+  ptr = shared_ptr<int>();
+  ASSERT_TRUE(cache.lookup(0));
+}
+
+// Local Variables:
+// compile-command: "cd ../.. ; make unittest_sharedptr_registry && ./unittest_sharedptr_registry # --gtest_filter=*.* --log-to-stderr=true"
+// End:
diff --git a/src/test/erasure-code/Makefile.am b/src/test/erasure-code/Makefile.am
index 6cef359..60f6ee1 100644
--- a/src/test/erasure-code/Makefile.am
+++ b/src/test/erasure-code/Makefile.am
@@ -2,6 +2,7 @@ check_SCRIPTS += \
 	test/erasure-code/test-erasure-code.sh
 
 ceph_erasure_code_benchmark_SOURCES = \
+	erasure-code/ErasureCode.cc \
 	test/erasure-code/ceph_erasure_code_benchmark.cc
 ceph_erasure_code_benchmark_LDADD = $(LIBOSD) $(LIBCOMMON) $(BOOST_PROGRAM_OPTIONS_LIBS) $(CEPH_GLOBAL)
 if LINUX
@@ -9,6 +10,9 @@ ceph_erasure_code_benchmark_LDADD += -ldl
 endif
 bin_DEBUGPROGRAMS += ceph_erasure_code_benchmark
 
+noinst_HEADERS += \
+	test/erasure-code/ceph_erasure_code_benchmark.h
+
 ceph_erasure_code_SOURCES = \
 	test/erasure-code/ceph_erasure_code.cc
 ceph_erasure_code_LDADD = $(LIBOSD) $(LIBCOMMON) $(BOOST_PROGRAM_OPTIONS_LIBS) $(CEPH_GLOBAL)
@@ -98,6 +102,13 @@ unittest_erasure_code_plugin_LDADD += -ldl
 endif
 check_PROGRAMS += unittest_erasure_code_plugin
 
+unittest_erasure_code_SOURCES = \
+	erasure-code/ErasureCode.cc \
+	test/erasure-code/TestErasureCode.cc
+unittest_erasure_code_CXXFLAGS = $(UNITTEST_CXXFLAGS)
+unittest_erasure_code_LDADD = $(LIBOSD) $(LIBCOMMON) $(UNITTEST_LDADD) $(CEPH_GLOBAL)
+check_PROGRAMS += unittest_erasure_code
+
 unittest_erasure_code_jerasure_SOURCES = \
 	test/erasure-code/TestErasureCodeJerasure.cc \
 	${jerasure_sources}
@@ -170,6 +181,3 @@ noinst_HEADERS += test/erasure-code/ErasureCodeExample.h
 unittest_erasure_code_example_CXXFLAGS = $(UNITTEST_CXXFLAGS)
 unittest_erasure_code_example_LDADD = $(LIBOSD) $(LIBCOMMON) $(UNITTEST_LDADD) $(CEPH_GLOBAL)
 check_PROGRAMS += unittest_erasure_code_example
-
-noinst_HEADERS += \
-	test/erasure-code/ceph_erasure_code_benchmark.h
diff --git a/src/test/erasure-code/TestErasureCode.cc b/src/test/erasure-code/TestErasureCode.cc
new file mode 100644
index 0000000..c572cdc
--- /dev/null
+++ b/src/test/erasure-code/TestErasureCode.cc
@@ -0,0 +1,134 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph distributed storage system
+ *
+ * Copyright (C) 2014 Red Hat <contact at redhat.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 "global/global_init.h"
+#include "erasure-code/ErasureCode.h"
+#include "common/ceph_argparse.h"
+#include "global/global_context.h"
+#include "gtest/gtest.h"
+
+class ErasureCodeTest : public ErasureCode {
+public:
+  map<int, bufferlist> encode_chunks_encoded;
+  unsigned int k;
+  unsigned int m;
+  unsigned int chunk_size;
+
+  ErasureCodeTest(unsigned int _k, unsigned int _m, unsigned int _chunk_size) :
+    k(_k), m(_m), chunk_size(_chunk_size) {}
+  virtual ~ErasureCodeTest() {}
+
+  virtual unsigned int get_chunk_count() const { return k + m; }
+  virtual unsigned int get_data_chunk_count() const { return k; }
+  virtual unsigned int get_chunk_size(unsigned int object_size) const {
+    return chunk_size;
+  }
+  virtual int encode_chunks(const set<int> &want_to_encode,
+			    map<int, bufferlist> *encoded) {
+    encode_chunks_encoded = *encoded;
+    return 0;
+  }
+  virtual int create_ruleset(const string &name,
+			     CrushWrapper &crush,
+			     ostream *ss) const { return 0; }
+
+};
+
+/*
+ *  If we have a buffer of 5 bytes (X below) and a chunk size of 3
+ *  bytes, for k=3, m=1 an additional 7 bytes (P and C below) will
+ *  need to be allocated for padding (P) and the 3 coding bytes (C).
+ *
+ *  X -+ +----------+ +-X
+ *  X  | | data   0 | | X
+ *  X  | +----------+ | X
+ *  X  | +----------+ | X -> +-X
+ *  X -+ | data   1 | +-X -> | X
+ *  P -+ +----------+        | P
+ *  P  | +----------+        | P
+ *  P  | | data   2 |        | P
+ *  P  | +----------+        | P
+ *  C  | +----------+        | C
+ *  C  | | coding 3 |        | C
+ *  C -+ +----------+        +-C
+ *
+ *  The data chunks 1 and 2 (data 1 and data 2 above) overflow the
+ *  original buffer because it needs padding. A new buffer will
+ *  be allocated to contain the chunk that overflows and all other
+ *  chunks after it, including the coding chunk(s).
+ *
+ *  The following test creates a siguation where the buffer provided
+ *  for encoding is not memory aligned. After encoding it asserts that:
+ *
+ *   a) each chunk is SIMD aligned
+ *   b) the data 1 chunk content is as expected which implies that its
+ *      content has been copied over.
+ *
+ *  It is possible for a flawed implementation to pas the test because the
+ *  underlying allocation function enforces it.
+ */
+TEST(ErasureCodeTest, encode_memory_align)
+{
+  int k = 3;
+  int m = 1;
+  unsigned chunk_size = ErasureCode::SIMD_ALIGN * 7;
+  ErasureCodeTest erasure_code(k, m, chunk_size);
+
+  set<int> want_to_encode;
+  for (unsigned int i = 0; i < erasure_code.get_chunk_count(); i++)
+    want_to_encode.insert(i);
+  string data(chunk_size + chunk_size / 2, 'X'); // uses 1.5 chunks out of 3
+  // make sure nothing is memory aligned
+  bufferptr ptr(buffer::create_aligned(data.length() + 1, ErasureCode::SIMD_ALIGN));
+  ptr.copy_in(1, data.length(), data.c_str());
+  ptr.set_offset(1);
+  ptr.set_length(data.length());
+  bufferlist in;
+  in.append(ptr);
+  map<int, bufferlist> encoded;
+
+  ASSERT_FALSE(in.is_aligned(ErasureCode::SIMD_ALIGN));
+  ASSERT_EQ(0, erasure_code.encode(want_to_encode, in, &encoded));
+  for (unsigned int i = 0; i < erasure_code.get_chunk_count(); i++)
+    ASSERT_TRUE(encoded[i].is_aligned(ErasureCode::SIMD_ALIGN));
+  for (unsigned i = 0; i < chunk_size / 2; i++)
+    ASSERT_EQ(encoded[1][i], 'X');
+  ASSERT_NE(encoded[1][chunk_size / 2], 'X');
+}
+
+int main(int argc, char **argv)
+{
+  vector<const char*> args;
+  argv_to_vec(argc, (const char **)argv, args);
+
+  global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0);
+  common_init_finish(g_ceph_context);
+
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
+
+/*
+ * Local Variables:
+ * compile-command: "cd ../.. ;
+ *   make -j4 unittest_erasure_code &&
+ *   valgrind --tool=memcheck --leak-check=full \
+ *      ./unittest_erasure_code \
+ *      --gtest_filter=*.* --log-to-stderr=true"
+ * End:
+ */
diff --git a/src/test/erasure-code/ceph_erasure_code_benchmark.cc b/src/test/erasure-code/ceph_erasure_code_benchmark.cc
index c6a4228..da90d85 100644
--- a/src/test/erasure-code/ceph_erasure_code_benchmark.cc
+++ b/src/test/erasure-code/ceph_erasure_code_benchmark.cc
@@ -31,6 +31,7 @@
 #include "common/Clock.h"
 #include "include/utime.h"
 #include "erasure-code/ErasureCodePlugin.h"
+#include "erasure-code/ErasureCode.h"
 
 namespace po = boost::program_options;
 
@@ -144,6 +145,7 @@ int ErasureCodeBench::encode()
 
   bufferlist in;
   in.append(string(in_size, 'X'));
+  in.rebuild_aligned(ErasureCode::SIMD_ALIGN);
   set<int> want_to_encode;
   for (int i = 0; i < k + m; i++) {
     want_to_encode.insert(i);
@@ -183,6 +185,7 @@ int ErasureCodeBench::decode()
   }
   bufferlist in;
   in.append(string(in_size, 'X'));
+  in.rebuild_aligned(ErasureCode::SIMD_ALIGN);
 
   set<int> want_to_encode;
   for (int i = 0; i < k + m; i++) {

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ceph/ceph.git



More information about the Pkg-ceph-commits mailing list