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

Gaudenz Steinlin gaudenz at moszumanska.debian.org
Fri Sep 18 15:33:58 UTC 2015


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

gaudenz pushed a commit to branch experimental
in repository ceph.

commit 580fef784d71ac1bbb4ec3928174252459c76af3
Author: Gaudenz Steinlin <gaudenz at debian.org>
Date:   Fri Aug 28 14:38:07 2015 +0200

    Imported Upstream version 0.94.3
---
 AUTHORS                                            |  16 +
 ChangeLog                                          | 156 +++-
 Makefile.am                                        |   6 +-
 Makefile.in                                        |   6 +-
 ceph.spec                                          |  33 +-
 ceph.spec.in                                       |  31 +-
 configure                                          | 113 ++-
 configure.ac                                       |  23 +-
 man/Makefile-server.am                             |   1 +
 man/Makefile.in                                    |   1 +
 man/ceph-create-keys.8                             |  97 ++
 src/.git_version                                   |   4 +-
 src/Makefile-env.am                                |   7 +
 src/Makefile.in                                    | 992 ++++++++++++---------
 src/acconfig.h.in                                  |   3 +
 src/ceph-disk                                      |  14 +-
 src/ceph-post-file.in                              |  20 +-
 src/ceph.in                                        |  38 +-
 src/client/Client.cc                               |  24 +-
 src/client/Client.h                                |   6 +-
 src/client/Fh.h                                    |   7 +-
 src/common/Throttle.cc                             |   6 +
 src/common/Throttle.h                              |   3 +-
 src/common/WorkQueue.h                             |  33 +-
 src/common/admin_socket.cc                         |  50 +-
 src/common/admin_socket.h                          |   1 +
 src/common/config.cc                               |  26 +-
 src/common/config_opts.h                           |  14 +
 src/common/dummy.cc                                |  20 -
 src/common/strtol.cc                               |  32 +-
 src/common/strtol.h                                |  18 +
 src/crush/CrushTester.cc                           |  59 +-
 src/crush/CrushTester.h                            |  11 +-
 src/crush/CrushWrapper.cc                          |  77 ++
 src/crush/CrushWrapper.h                           |   2 +
 src/crush/mapper.c                                 |  11 +-
 src/include/Makefile.am                            |   1 +
 src/include/interval_set.h                         |   1 +
 src/include/krbd.h                                 |   7 +-
 src/include/rados/librados.h                       |   1 +
 src/include/rbd/object_map_types.h                 |  12 +
 src/json_spirit/json_spirit_reader_template.h      |  34 +-
 src/krbd.cc                                        |   5 +-
 src/librbd/AioCompletion.cc                        |  24 +-
 src/librbd/AioCompletion.h                         |   6 +-
 src/librbd/AioRequest.cc                           |  28 +-
 src/librbd/AioRequest.h                            |   6 +-
 src/librbd/AsyncFlattenRequest.cc                  |   3 +-
 src/librbd/AsyncOperation.h                        |   4 +
 src/librbd/AsyncTrimRequest.cc                     |   7 +-
 src/librbd/CopyupRequest.cc                        |  10 +-
 src/librbd/ImageCtx.cc                             |  29 +-
 src/librbd/ImageCtx.h                              |   3 +
 src/librbd/ImageWatcher.cc                         |  14 +-
 src/librbd/ImageWatcher.h                          |   7 +-
 src/librbd/ObjectMap.cc                            |  21 +-
 src/librbd/ObjectMap.h                             |   9 +-
 src/librbd/TaskFinisher.h                          |   1 +
 src/librbd/internal.cc                             | 155 ++--
 src/librbd/internal.h                              |  16 +-
 src/librbd/librbd.cc                               | 200 ++++-
 src/log/Log.cc                                     |   4 +
 src/mds/CDir.cc                                    |  10 +-
 src/mon/MDSMonitor.cc                              |  47 +-
 src/mon/MDSMonitor.h                               |   6 +-
 src/mon/MonCommands.h                              |  11 +-
 src/mon/Monitor.cc                                 |  56 +-
 src/mon/OSDMonitor.cc                              |  26 +-
 src/mon/PGMap.cc                                   |   2 +-
 src/mon/PGMap.h                                    |   2 +-
 src/osd/OSD.cc                                     |  50 +-
 src/osd/OSD.h                                      |  32 +-
 src/osd/PG.cc                                      |  12 +-
 src/osd/ReplicatedPG.cc                            |  66 +-
 src/osd/ReplicatedPG.h                             |  15 +-
 src/osd/osd_types.cc                               |  29 +-
 src/osd/osd_types.h                                |   5 +-
 src/osdc/ObjectCacher.cc                           |   2 +-
 src/perfglue/Makefile.am                           |   7 +
 src/perfglue/heap_profiler.cc                      |  15 +-
 src/pybind/rbd.py                                  |   8 +-
 src/rgw/logrotate.conf                             |   2 +-
 src/rgw/rgw_admin.cc                               |  65 +-
 src/rgw/rgw_civetweb.cc                            |  32 +-
 src/rgw/rgw_civetweb.h                             |   2 +
 src/rgw/rgw_client_io.cc                           |   7 +-
 src/rgw/rgw_common.h                               |   2 +-
 src/rgw/rgw_op.cc                                  |  11 +-
 src/rgw/rgw_rados.cc                               | 202 ++++-
 src/rgw/rgw_rados.h                                |   7 +-
 src/rgw/rgw_rest.cc                                |  71 +-
 src/rgw/rgw_rest_s3.cc                             |   2 +-
 src/rgw/rgw_rest_swift.cc                          |   3 +-
 src/rgw/rgw_rest_user.cc                           |   1 +
 src/rgw/rgw_swift.cc                               |   7 +
 src/test/Makefile-client.am                        |  30 +-
 src/test/Makefile.am                               |   1 +
 src/test/centos-6/ceph.spec.in                     |  31 +-
 src/test/centos-7/ceph.spec.in                     |  31 +-
 .../cli/crushtool/check-names.empty.crushmap.txt   |  11 +
 src/test/cli/crushtool/check-names.empty.t         |   5 +
 src/test/cli/crushtool/check-names.max-id.t        |   7 +
 src/test/cli/crushtool/help.t                      |   4 +
 src/test/daemon_config.cc                          |  46 +
 src/test/librados/snapshots.cc                     |  68 ++
 src/test/librados/tier.cc                          |  12 +-
 src/test/librados_test_stub/LibradosTestStub.cc    |  29 +-
 src/test/librados_test_stub/TestMemIoCtxImpl.cc    |   2 +-
 src/test/librados_test_stub/TestWatchNotify.cc     |   2 +
 src/test/librbd/{fsx.c => fsx.cc}                  |  65 +-
 src/test/librbd/test_ImageWatcher.cc               |  31 +-
 src/test/librbd/test_ObjectMap.cc                  | 124 +++
 src/test/librbd/test_fixture.cc                    |  27 +-
 src/test/librbd/test_fixture.h                     |  12 -
 src/test/librbd/test_internal.cc                   |  15 +-
 src/test/librbd/test_librbd.cc                     |  98 +-
 src/test/librbd/test_main.cc                       |  16 +-
 src/test/librbd/test_support.cc                    |  30 +
 src/test/librbd/test_support.h                     |  19 +
 src/test/mon/osd-crush.sh                          |  27 +-
 src/test/mon/osd-pool-create.sh                    |  15 +
 src/test/osd/RadosModel.h                          |  21 +-
 src/test/osd/TestRados.cc                          |  23 +-
 src/test/strtol.cc                                 |  13 +-
 src/tools/cephfs/Dumper.cc                         |  54 +-
 src/tools/crushtool.cc                             |  23 +-
 126 files changed, 3167 insertions(+), 1109 deletions(-)

diff --git a/AUTHORS b/AUTHORS
index 73e5b79..c2e21b2 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,4 +1,5 @@
 9seconds <nineseconds at yandex.ru>
+Abhishek L <abhishekl.2006 at gmail.com>
 Abhishek Lekshmanan <abhishek.lekshmanan at ril.com>
 Accela Zhao <accelazh at gmail.com>
 Adam C. Emerson <aemerson at linuxbox.com>
@@ -32,6 +33,7 @@ Andrey Kuznetsov <Andrey_Kuznetsov at epam.com>
 Andrey Stepachev <octo at yandex-team.ru>
 Andy Allan <github at gravitystorm.co.uk>
 Anols <ayari_anis at live.fr>
+Anton Aksola <anton.aksola at nebula.fi>
 Anton Blanchard <anton at samba.org>
 apovzner <apovzner at 29311d96-e01e-0410-9327-a35deaab8ce9>
 Ariela <Dell at ARIELA.(none)>
@@ -126,6 +128,7 @@ Greg Farnum <gfarnum at redhat.com>
 Greg Farnum <greg at inktank.com>
 Guangliang Zhao <guangliang at unitedstack.com>
 Guang Yang <yguang at yahoo-inc.com>
+guce <guce at h3c.com>
 Guilhem Lettron <guilhem at lettron.fr>
 Haifeng Liu <haifeng at yahoo-inc.com>
 Hannes Reinecke <hare at suse.de>
@@ -135,18 +138,22 @@ Haomai Wang <yuyuyu101 at 163.com>
 Harpreet Dhillon <harpreet at ironsystems.com>
 Hazem <hazem at hazem-Inspiron-3537.(none)>
 Henry C Chang <henry_c_chang at tcloudcomputing.com>
+Henry Chang <henry at bigtera.com>
 Herb Shiu <herb_shiu at tcloudcomputing.com>
+Hervé Rousseau <hroussea at cern.ch>
 Holger Macht <hmacht at suse.de>
 Huamin Chen <hchen at redhat.com>
 Huang Jun <hjwsm1989 at gmail.com>
 Ian Holsman <lists at holsman.net>
 Ilya Dryomov <idryomov at redhat.com>
 Ilya Dryomov <ilya.dryomov at inktank.com>
+islepnev <islepnev at gmail.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>
+Javier M. Mellid <jmunhoz at igalia.com>
 Jenkins <jenkins at inktank.com>
 Jens-Christian Fischer <jens-christian.fischer at switch.ch>
 Jerry7X <875016668 at qq.com>
@@ -167,8 +174,10 @@ John Wilkins <jwilkins at redhat.com>
 Jojy George Varghese <jvarghese at scalecomputing.com>
 Jonathan Davies <jonathan.davies at canonical.com>
 Jonathan Dieter <jdieter at lesbg.com>
+Jon Bernard <jbernard at tuxion.com>
 Jordi Llonch <llonchj at gmail.com>
 Josef Bacik <josef at redhat.com>
+Joseph McDonald <joseph.mcdonald at alcatel-lucent.com>
 Josh Durgin <jdurgin at redhat.com>
 Josh Durgin <josh.durgin at inktank.com>
 Josh Pieper <jjp at pobox.com>
@@ -232,6 +241,8 @@ Mouad Benchchaoui <m.benchchaoui at x-ion.de>
 Mykola Golub <mgolub at mirantis.com>
 Mykola Golub <mgolub at zhuzha.mirantis.lviv.net>
 nairolf21 <fcoste21 at gmail.com>
+Nathan Cutler <ncutler at suse.com>
+Nathan Cutler <ncutler at suse.cz>
 Neil Horman <nhorman at tuxdriver.com>
 Neil Levine <neil.levine at inktank.com>
 Nikola Kotur <kotnick at gmail.com>
@@ -316,6 +327,7 @@ Thomas Mueller <thomas at chaschperli.ch>
 Thorsten Behrens <tbehrens at suse.com>
 Thorsten Glaser <tg at mirbsd.de>
 Tim Freund <tim at freunds.net>
+Tim Serong <tserong at suse.com>
 t-miyamae <miyamae.takeshi at jp.fujitsu.com>
 tmuthamizhan <tamil.muthamizhan at inktank.com>
 Tobias Florek <tobias.florek at bytesandbutter.de>
@@ -342,6 +354,8 @@ Wei Luo <luowei at yahoo-inc.com>
 Wesley Spikes <wesley.spikes at dreamhost.com>
 Wido den Hollander <wido at 42on.com>
 William A. Kennington III <william at wkennington.com>
+wuxingyi <wuxingyi2015 at outlook.com>
+wuxingyi <wuxingyi at letv.com>
 Wyllys Ingersoll <wyllys.ingersoll at keepertech.com>
 Xan Peng <xanpeng at gmail.com>
 Xiaoxi Chen <xiaoxi.chen at intel.com>
@@ -352,6 +366,7 @@ Xiong Yiliang <xiongyiliang at xunlei.com>
 Yann Dupont <yann at objoo.org>
 Yan, Zheng <zheng.z.yan at intel.com>
 Yan, Zheng <zyan at redhat.com>
+Yazen Ghannam <yazen.ghannam at linaro.org>
 Yehuda Sadeh <yehuda at inktank.com>
 Yehuda Sadeh <ysadehwe at redhat.com>
 Yongyue Sun <abioy.sun at gmail.com>
@@ -360,3 +375,4 @@ Yunchuan Wen <yunchuanwen at ubuntukylin.com>
 Yuri Weinstein <yuri.weinstein at inktank.com>
 Zhe Zhang <zzxuanyuan at gmail.com>
 Zhiqiang Wang <zhiqiang.wang at intel.com>
+Zhi Zhang <zhangz.david at outlook.com>
diff --git a/ChangeLog b/ChangeLog
index 548c5f4..2ad0178 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,8 +1,152 @@
-5fb8561 (HEAD, tag: v0.94.2) 0.94.2
-968573b (origin/wip-11806-hammer) debian: ceph-dbg steals ceph-objectstore-tool from ceph-test-dbg
+95cefea (HEAD, tag: v0.94.3) 0.94.3
+81a311a (origin/hammer-12709) Workunits : fs/misc/chmod.sh : Include ACL characters in permission check.
+2ecb3b7 Fh ref count will leak if readahead does not need to do read from osd
+4c199bf (origin/wip-11998-hammer) debian/control: ceph-common (>> 0.94.2) must be >= 0.94.2-2
+e19f928 (origin/wip-12502-hammer) rgw: conversion tool to fix broken multipart objects
+28d32f6 rgw: only scan for objects not in namespace
+e22e2b4 rgw_admin: add --remove-bad flag to bucket check
+154f18c (origin/wip-12465-hammer) Log::reopen_log_file: take m_flush_mutex
+b872882 (origin/wip-12237-hammer) librados_test_stub: read op should return number of bytes read
+7d9fce3 tests: fixed TestObjectMap.InvalidateFlagInMemoryOnly
+4a77be0 librbd: don't attempt to invalidate an object map in R/O mode
+0aea70f tests: add new unit tests for object map invalidation
+c732cb8 librbd: move object map codes to common location
+27c99ea librbd: only update image flags when holding exclusive lock
+ef45363 librbd: new ImageWatcher::is_lock_supported method
+e4b55b3 Fixes: #12286 radosgw-admin: after subuser modify print only once user info.
+9458b84 rgw: fix ListParts response
+2357b6c rgw: If the client sends a Connection: close header respond accordingly.
+f819332 ceph.spec.in: install 95-ceph-osd.rules, mount.ceph, and mount.fuse.ceph properly on SUSE
+d8733be debian: move ceph_argparse into ceph-common
+f99f312 (origin/wip-12384-hammer) test: potential memory leak in FlushAioPP
+a4fc63a pybind: fix valgrind warning on rbd_get_parent_info call
+aa3eb28 osdc: invalid read of freed memory
+18ede75 krbd: fix incorrect types in the krbd API
+488578c fsx: cleanup crypto library at exit
+97ff6cb tests: add run-rbd-valgrind-unit-tests.sh
+e690907 valgrind: update valgrind suppressions for lttng-ust
+fe013e0 librbd: TaskFinisher should finish all queued tasks
+43cd3ac tests: fix valgrind errors with librbd unit test
+5d8d6a1 tests: librbd should release global data before exit
+13f926e librados_test_stub: cleanup singleton memory allocation
+1063f52 PG::find_best_info: ignore info.les for incomplete peer
+7132277 Conditional-compile against minimal tcmalloc.
+ad5745b OSD: add command_wq suicide timeout
+059a579 OSD: add remove_wq suicide timeout
+b8826bc OSD: add scrub_wq suicide timeout
+878dd40 OSD: add snap_trim_wq suicide timeout
+1157583 OSD: add recovery_wq suicide timeout
+a82b450 OSD: add op_wq suicide timeout
+89aa8ff (origin/wip-11833-hammer) mon: add an "osd crush tree" command
+03c07d7 librbd: assertion failure race condition if watch disconnected
+5c812c1 librbd: prevent object map updates from being interrupted
+e50caab rgw: fix empty json response when getting user quota
+ec70533 rgw: error out if frontend did not send all data
+557865c rgw: fix reset_loc()
+b1618a9 rgw: fix lack of account name in XML listing of Swift account.
+e39dce7 rgw: generate the "Date" HTTP header for civetweb.
+a5dbcbb Swift: Set Content-Length when requesting/checking Keystone tokens
+3c8cdea client: reference counting 'struct Fh'
+c78cc00 rgw: rectify 202 Accepted in response for PUT on existing bucket.
+7f1c0cc crush/CrushTester: return EINVAL if crushtool returns non-zero
+2aaeea1 tests: TEST_crush_reject_empty must not run a mon
+80afb81 ceph-helpers: implement test_expect_failure
+6b5e9a1 tests: display the output of failed make check runs
+5141301 (origin/wip-11975-hammer) mon: add "--check" to CrushTester::test_with_crushtool()
+5ec27cf crushtool: rename "--check-names" to "--check"
+2a8fe88 mon: check the new crush map against osdmap.max_osd
+c0b0f52 crushtool: enable check against max_id
+f041bbe crush/CrushTester: check if any item id is too large
+cc1cc03 mon: validate new crush for unknown names
+ff29a7f crushtool: add the "--check-names" option
+960ea49 crush/CrushTester: add check_name_maps() method
+5e72479 (origin/wip-12021-hammer) OSDMonitor: allow addition of cache pool with non-empty snaps with config
+ecac1a4 Always provide summary for non-healthy cluster
+1a32379 mon/PGMap: add more constness
+84ebc3d mon/PGMap: sort pg states by the states in "pg ls" spec
+e310461 mon: s/recovery/recoverying/ in "pg ls*" commands' spec
+524f4a5 mon: always reply mdsbeacon
+413e407 mon/MDSMonitor: rename labels to a better name
+a03968a mon: send no_reply() to peon to drop ignored mdsbeacon
+39f3459 mon: remove unnecessary error handling
+0e5e7e1 mon: remove unused variable
+7034720 ReplicatedPG::finish_promote: handle results->snaps is empty case
+3e44dc1 ReplicatedPG::finish_promote: fix snap promote head snaps
+5ef0846 tools: chunk reads in Dumper
+408880b qa: update to newer Linux tarball
+56c2688 rgw: simplify content length handling
+d9bbef3 rgw: make compatability deconfliction optional.
+0260abd rgw: improve content-length env var handling
+8abc46a rgw: fix data corruption when race condition
+89d0266 (origin/wip-fix-doc-hammer) doc: add the corresponding @endcond command for @cond
+2aa77b3 doc: remove orphan: directive in ceph-create-keys.rst
+ad66e40 doc: let doxygen ignore src/tracing
+356bd2c (origin/wip-11806-hammer) debian: ceph-dbg steals ceph-objectstore-tool from ceph-test-dbg (take 2)
+c5c627f rgw/logrotate.conf: Rename service name
+582cf73 (origin/wip-12109-hammer, origin/wip-12109) tests: add librbd watch/notify version compatibility test
+43b9aef qa/workunits/rbd: add notify_master/slave bootstrap scripts
+f995fb5 qa/workunits/rbd: add new test_librbd_api workunit
+a09da2a tests: create librbd API-only integration test suite
+e149916 Increase max files open limit for OSD daemon.
+22f58ce Makefile: install ceph-post-file keys with mode 600
+3e65a10 ceph-post-file: improve check for a source install
+c1f6743 ceph-post-file: behave when sftp doesn't take -i
+38d36b1 packaging: move SuSEfirewall2 templates out of src
+24bc9f2 packaging: add SuSEfirewall2 service files
+8acfb99 Bug fix to ceph systemV compatability script.
+bd3fd92 Fixes to rcceph script
+37d77d3 Increase max files open limit for OSD daemon.
+78d894a qa/workunits/rados/test-upgarde-v9.0.1: fix exclude syntax
+3e8d60a qa/workunits/rados/test-upgrade-v9.0.1: skip one more evict test
+348a3d3 qa: add compatibility filtered rados api tests for upgrades
+f68bf94 (origin/wip-11493-hammer) OSDMonitor: disallow ec pools as tiers
+13c8d58 mon: prevent pool with snapshot state from being used as a tier
+58e6266 test/librados/tier.cc: destroy and recreate cache pool on every test
+3db1026 doc/release-notes: v0.94.2
+ed5442b (origin/wip-11770-hammer) tests: verify librbd blocking aio code path
+20e1048 librbd: new rbd_non_blocking_aio config option
+b4571b3 PendingReleaseNotes: document changes to librbd's aio_read methods
+9ea1edd librbd: AioRequest::send no longer returns a result
+272df2a tests: update librbd AIO tests to remove result code
+dd2e4c1 librbd: internal AIO methods no longer return result
+dbd4e29 Throttle: added pending_error method to SimpleThrottle
+7df6091 librbd: add new fail method to AioCompletion
+cf6e1f5 librbd: avoid blocking AIO API methods
+e61974a librbd: add task pool / work queue for requests
+5fb8561 (tag: v0.94.2) 0.94.2
+bfb1442 ReplicatedPG::release_op_ctx_locks: requeue in scrub queue if blocked
+c7b6a63 ReplicatedPG::finish_ctx: take excl lock if operation is rw
+1550a56 RadosModel: randomly prefix delete with assert_exists
+4cdc5f7 RadosModel: assert exists on subsequent writes
+25c730b test/librados/snapshots.cc: add test for 11677
+3d74164 ReplicatedPG::trim_object: write filtered snapset while we're at it
+a116154 ReplicatedPG: start_flush: use filtered snapset
+82988d6 ceph-disk: support NVMe device partitions
+bd91fb0 mon: prevent bucket deletion when referenced by a rule
+56565ee crush: fix crash from invalid 'take' argument
+1440122 common/config: detect overflow of float values
+9b947fa common/config: detect overflow of int values
+d723e11 mds: clear CDir::STATE_REJOINUNDEF after fetching dirfrag
+54f4e7d rgw: Use attrs from source bucket on copy
+9dfef60 rgw: always check if token is expired
+fdb43eb ceph.spec.in: tweak ceph-common for SUSE/openSUSE
+ba1a016 admin/build-doc: fix dependency checks
+5a60a03 (origin/wip-4846) man/ceph-create-keys.8: add missing file
+19305b8 doc: add ceph-create-keys.8
+ffd0933 WorkQueue: added virtual destructor
+a28adfb WorkQueue: add new ContextWQ work queue
+1a321e4 rgw: Do not enclose the Bucket header in quotes
+968573b debian: ceph-dbg steals ceph-objectstore-tool from ceph-test-dbg
+a62c3aa ceph.in: handle unknown Exception correctly
+cc7f744 ceph.in: improve the interactive mode
+eb26388 ceph.in: parse quote correctly in interactive mode
 344328d (origin/wip-11733-hammer) debian: set rest-bench-dbg ceph-test-dbg dependencies
 293affe (origin/wip-11622-hammer) rgw: merge manifests correctly when there's prefix override
 a43d248 rgw: restore buffer of multipart upload after EEXIST
+558d639 json_sprit: fix the FTBFS on old gcc
+678b3e6 json_spirit: use utf8 intenally when parsing \uHHHH
+ef6641c ceph.spec: update OpenSUSE BuildRequires
+0b6d442 (origin/wip-hammer-11535-admin-socket) common/admin_socket: close socket descriptor in destructor
 95818da (origin/wip-hammer-package-perf-objectstore) packaging: include ceph_perf_objectstore
 6e2dd40 (origin/hammer-uclient-checking) client: fix error handling in check_pool_perm
 3c2e6ae client: use SaferCond in check_pool_perm
@@ -300,7 +444,7 @@ e0e765f osd/OSDMap: cache get_up_osd_features
 10d8686 librbd: minor cleanup of ImageWatcher messages
 0ed296b (origin/wip-librbd-exclusive-lock-config) rbd: disable RBD exclusive locking by default
 2b63dd2 DBObjectMap: lock header_lock on sync()
-170c88d (origin/wip-cmake-vstart) cmake: radosgw, radosgw-admin related fixes
+170c88d cmake: radosgw, radosgw-admin related fixes
 4feb171 vstart.sh: can use binaries outside of ceph/src
 55d3db9 (origin/wip-10919) cls_rbd: invalidate bufferlist CRC when updating object map
 970bb49 (origin/wip-10883) osd: Fix FileJournal wrap to get header out first
@@ -4135,7 +4279,7 @@ d358741 Wait tx state buffer in flush_set
 9061988 osd: init local_connection for fast_dispatch in _send_boot()
 b6f3aff Fix mismatched tags (struct vs. class) inconsistency
 2aa3edc (origin/wip-8174) os/FileStore: fix max object name limit
-f4bffec (origin/wip-memstore) ceph_test_objectstore: test memstore
+f4bffec ceph_test_objectstore: test memstore
 6f312b0 os/MemStore: copy attrs on clone
 8dd6b8f os/MemStore: fix wrlock ordering checks
 a2594a5 osd/MemStore: handle collection_move_rename within the same collection
@@ -7411,7 +7555,7 @@ ebb3ad9 osd/PG: move some pg stat update into a helper
 05274f3 osd: include peer_info in pg query
 5fdcc56 mds: fix bug in MDCache::open_ino_finish
 71d1eb3 mds: add CEPH_FEATURE_EXPORT_PEER and bump the protocal version
-d0b744a client: handle session flush message
+d0b744a1 client: handle session flush message
 05b192f mds: simplify how to export non-auth caps
 9dc52ff mds: send cap import messages to clients after importing subtree succeeds
 6a56588 mds: re-send cap exports in resolve message.
@@ -21893,7 +22037,7 @@ e37878e mds: fix discover tid assignment
 6025dee osd: move watch/notify effects out of do_osd_ops
 0aeab99 obsync: implement RadosStore
 ccf11fb osd: mention invalid snapc in log
-896de0a osd: include (some) osd op flags in MOSDOp print method
+896de0ac osd: include (some) osd op flags in MOSDOp print method
 b08ee2c osd: add RWORDERED osd op flag
 a44065d radostool: fix getxattr / setxattr return code
 9c2f0f0 rbd: make showmapped output a bit prettier
diff --git a/Makefile.am b/Makefile.am
index 73817e5..527dd22 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -20,9 +20,9 @@ EXTRA_DIST += \
 # why is it so hard to make autotools to this?
 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/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
+	-install -m 600 share/known_hosts_drop.ceph.com $(DESTDIR)$(datadir)/ceph/known_hosts_drop.ceph.com
+	-install -m 600 share/id_dsa_drop.ceph.com $(DESTDIR)$(datadir)/ceph/id_dsa_drop.ceph.com
+	-install -m 600 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 96998b5..6de298a 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -881,9 +881,9 @@ uninstall-am:
 # why is it so hard to make autotools to this?
 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/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
+	-install -m 600 share/known_hosts_drop.ceph.com $(DESTDIR)$(datadir)/ceph/known_hosts_drop.ceph.com
+	-install -m 600 share/id_dsa_drop.ceph.com $(DESTDIR)$(datadir)/ceph/id_dsa_drop.ceph.com
+	-install -m 600 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/ceph.spec b/ceph.spec
index 9c44b99..c00f449 100644
--- a/ceph.spec
+++ b/ceph.spec
@@ -9,7 +9,7 @@
 # common
 #################################################################################
 Name:		ceph
-Version:	0.94.2
+Version:	0.94.3
 Release:	0%{?dist}
 Epoch:		1
 Summary:	User space components of the Ceph file system
@@ -39,7 +39,9 @@ Requires:	cryptsetup
 Requires(post):	binutils
 BuildRequires:	gcc-c++
 BuildRequires:	boost-devel
+%if ! 0%{defined suse_version}
 BuildRequires:  bzip2-devel
+%endif
 BuildRequires:	cryptsetup
 BuildRequires:	gdbm
 BuildRequires:	hdparm
@@ -66,9 +68,12 @@ BuildRequires:	xfsprogs
 BuildRequires:	xfsprogs-devel
 BuildRequires:	xmlstarlet
 BuildRequires:	yasm
-%if 0%{?rhel} || 0%{?centos} || 0%{?fedora}
+%if 0%{?rhel} || 0%{?centos} || 0%{?fedora} || 0%{?suse_version}
 BuildRequires:	snappy-devel
 %endif
+%if 0%{?suse_version}
+BuildRequires:	net-tools
+%endif
 
 #################################################################################
 # specific
@@ -121,7 +126,12 @@ Requires:	python-rados = %{epoch}:%{version}-%{release}
 Requires:	python-rbd = %{epoch}:%{version}-%{release}
 Requires:	python-cephfs = %{epoch}:%{version}-%{release}
 Requires:	python-requests
-Requires:	redhat-lsb-core
+%if 0%{defined suse_version}
+Requires:  python-argparse
+%endif
+%if 0%{?rhel} || 0%{?fedora}
+Requires:  redhat-lsb-core
+%endif
 %description -n ceph-common
 Common utilities to mount and interact with a ceph storage cluster.
 
@@ -480,6 +490,12 @@ install -m 0644 -D src/rgw/logrotate.conf $RPM_BUILD_ROOT%{_sysconfdir}/logrotat
 chmod 0644 $RPM_BUILD_ROOT%{_docdir}/ceph/sample.ceph.conf
 chmod 0644 $RPM_BUILD_ROOT%{_docdir}/ceph/sample.fetch_config
 
+# firewall templates
+%if 0%{?suse_version}
+install -m 0644 -D etc/sysconfig/SuSEfirewall2.d/services/ceph-mon %{buildroot}%{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/ceph-mon
+install -m 0644 -D etc/sysconfig/SuSEfirewall2.d/services/ceph-osd-mds %{buildroot}%{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/ceph-osd-mds
+%endif
+
 # udev rules
 %if 0%{?rhel} >= 7 || 0%{?fedora}
 install -m 0644 -D udev/50-rbd.rules $RPM_BUILD_ROOT/usr/lib/udev/rules.d/50-rbd.rules
@@ -495,7 +511,7 @@ install -m 0644 -D udev/95-ceph-osd-alt.rules $RPM_BUILD_ROOT/lib/udev/rules.d/9
 install -m 0644 -D udev/95-ceph-osd.rules $RPM_BUILD_ROOT/lib/udev/rules.d/95-ceph-osd.rules
 %endif
 
-%if 0%{?rhel} >= 7 || 0%{?fedora}
+%if 0%{?rhel} >= 7 || 0%{?fedora} || 0%{?suse_version}
 mv $RPM_BUILD_ROOT/lib/udev/rules.d/95-ceph-osd.rules $RPM_BUILD_ROOT/usr/lib/udev/rules.d/95-ceph-osd.rules
 mv $RPM_BUILD_ROOT/sbin/mount.ceph $RPM_BUILD_ROOT/usr/sbin/mount.ceph
 mv $RPM_BUILD_ROOT/sbin/mount.fuse.ceph $RPM_BUILD_ROOT/usr/sbin/mount.fuse.ceph
@@ -577,7 +593,7 @@ fi
 %{_sbindir}/ceph-disk-udev
 %{_sbindir}/ceph-create-keys
 %{_sbindir}/rcceph
-%if 0%{?rhel} >= 7 || 0%{?fedora}
+%if 0%{?rhel} >= 7 || 0%{?fedora} || 0%{?suse_version}
 %{_sbindir}/mount.ceph
 %else
 /sbin/mount.ceph
@@ -608,8 +624,13 @@ fi
 %endif
 %config %{_sysconfdir}/bash_completion.d/ceph
 %config(noreplace) %{_sysconfdir}/logrotate.d/ceph
+%if 0%{?suse_version}
+%config %{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/ceph-mon
+%config %{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/ceph-osd-mds
+%endif
 %{_mandir}/man8/ceph-deploy.8*
 %{_mandir}/man8/ceph-disk.8*
+%{_mandir}/man8/ceph-create-keys.8*
 %{_mandir}/man8/ceph-mon.8*
 %{_mandir}/man8/ceph-mds.8*
 %{_mandir}/man8/ceph-osd.8*
@@ -684,7 +705,7 @@ fi
 %defattr(-,root,root,-)
 %{_bindir}/ceph-fuse
 %{_mandir}/man8/ceph-fuse.8*
-%if 0%{?rhel} >= 7 || 0%{?fedora}
+%if 0%{?rhel} >= 7 || 0%{?fedora} || 0%{?suse_version}
 %{_sbindir}/mount.fuse.ceph
 %else
 /sbin/mount.fuse.ceph
diff --git a/ceph.spec.in b/ceph.spec.in
index f3cfaf0..b36a0b9 100644
--- a/ceph.spec.in
+++ b/ceph.spec.in
@@ -39,7 +39,9 @@ Requires:	cryptsetup
 Requires(post):	binutils
 BuildRequires:	gcc-c++
 BuildRequires:	boost-devel
+%if ! 0%{defined suse_version}
 BuildRequires:  bzip2-devel
+%endif
 BuildRequires:	cryptsetup
 BuildRequires:	gdbm
 BuildRequires:	hdparm
@@ -66,9 +68,12 @@ BuildRequires:	xfsprogs
 BuildRequires:	xfsprogs-devel
 BuildRequires:	xmlstarlet
 BuildRequires:	yasm
-%if 0%{?rhel} || 0%{?centos} || 0%{?fedora}
+%if 0%{?rhel} || 0%{?centos} || 0%{?fedora} || 0%{?suse_version}
 BuildRequires:	snappy-devel
 %endif
+%if 0%{?suse_version}
+BuildRequires:	net-tools
+%endif
 
 #################################################################################
 # specific
@@ -121,7 +126,12 @@ Requires:	python-rados = %{epoch}:%{version}-%{release}
 Requires:	python-rbd = %{epoch}:%{version}-%{release}
 Requires:	python-cephfs = %{epoch}:%{version}-%{release}
 Requires:	python-requests
-Requires:	redhat-lsb-core
+%if 0%{defined suse_version}
+Requires:  python-argparse
+%endif
+%if 0%{?rhel} || 0%{?fedora}
+Requires:  redhat-lsb-core
+%endif
 %description -n ceph-common
 Common utilities to mount and interact with a ceph storage cluster.
 
@@ -480,6 +490,12 @@ install -m 0644 -D src/rgw/logrotate.conf $RPM_BUILD_ROOT%{_sysconfdir}/logrotat
 chmod 0644 $RPM_BUILD_ROOT%{_docdir}/ceph/sample.ceph.conf
 chmod 0644 $RPM_BUILD_ROOT%{_docdir}/ceph/sample.fetch_config
 
+# firewall templates
+%if 0%{?suse_version}
+install -m 0644 -D etc/sysconfig/SuSEfirewall2.d/services/ceph-mon %{buildroot}%{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/ceph-mon
+install -m 0644 -D etc/sysconfig/SuSEfirewall2.d/services/ceph-osd-mds %{buildroot}%{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/ceph-osd-mds
+%endif
+
 # udev rules
 %if 0%{?rhel} >= 7 || 0%{?fedora}
 install -m 0644 -D udev/50-rbd.rules $RPM_BUILD_ROOT/usr/lib/udev/rules.d/50-rbd.rules
@@ -495,7 +511,7 @@ install -m 0644 -D udev/95-ceph-osd-alt.rules $RPM_BUILD_ROOT/lib/udev/rules.d/9
 install -m 0644 -D udev/95-ceph-osd.rules $RPM_BUILD_ROOT/lib/udev/rules.d/95-ceph-osd.rules
 %endif
 
-%if 0%{?rhel} >= 7 || 0%{?fedora}
+%if 0%{?rhel} >= 7 || 0%{?fedora} || 0%{?suse_version}
 mv $RPM_BUILD_ROOT/lib/udev/rules.d/95-ceph-osd.rules $RPM_BUILD_ROOT/usr/lib/udev/rules.d/95-ceph-osd.rules
 mv $RPM_BUILD_ROOT/sbin/mount.ceph $RPM_BUILD_ROOT/usr/sbin/mount.ceph
 mv $RPM_BUILD_ROOT/sbin/mount.fuse.ceph $RPM_BUILD_ROOT/usr/sbin/mount.fuse.ceph
@@ -577,7 +593,7 @@ fi
 %{_sbindir}/ceph-disk-udev
 %{_sbindir}/ceph-create-keys
 %{_sbindir}/rcceph
-%if 0%{?rhel} >= 7 || 0%{?fedora}
+%if 0%{?rhel} >= 7 || 0%{?fedora} || 0%{?suse_version}
 %{_sbindir}/mount.ceph
 %else
 /sbin/mount.ceph
@@ -608,8 +624,13 @@ fi
 %endif
 %config %{_sysconfdir}/bash_completion.d/ceph
 %config(noreplace) %{_sysconfdir}/logrotate.d/ceph
+%if 0%{?suse_version}
+%config %{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/ceph-mon
+%config %{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/ceph-osd-mds
+%endif
 %{_mandir}/man8/ceph-deploy.8*
 %{_mandir}/man8/ceph-disk.8*
+%{_mandir}/man8/ceph-create-keys.8*
 %{_mandir}/man8/ceph-mon.8*
 %{_mandir}/man8/ceph-mds.8*
 %{_mandir}/man8/ceph-osd.8*
@@ -684,7 +705,7 @@ fi
 %defattr(-,root,root,-)
 %{_bindir}/ceph-fuse
 %{_mandir}/man8/ceph-fuse.8*
-%if 0%{?rhel} >= 7 || 0%{?fedora}
+%if 0%{?rhel} >= 7 || 0%{?fedora} || 0%{?suse_version}
 %{_sbindir}/mount.fuse.ceph
 %else
 /sbin/mount.fuse.ceph
diff --git a/configure b/configure
index 44958df..0efc087 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.69 for ceph 0.94.2.
+# Generated by GNU Autoconf 2.69 for ceph 0.94.3.
 #
 # Report bugs to <ceph-devel at vger.kernel.org>.
 #
@@ -590,8 +590,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='ceph'
 PACKAGE_TARNAME='ceph'
-PACKAGE_VERSION='0.94.2'
-PACKAGE_STRING='ceph 0.94.2'
+PACKAGE_VERSION='0.94.3'
+PACKAGE_STRING='ceph 0.94.3'
 PACKAGE_BUGREPORT='ceph-devel at vger.kernel.org'
 PACKAGE_URL=''
 
@@ -716,6 +716,8 @@ ENABLE_CEPHFS_JAVA_FALSE
 ENABLE_CEPHFS_JAVA_TRUE
 WITH_TCMALLOC_FALSE
 WITH_TCMALLOC_TRUE
+WITH_TCMALLOC_MINIMAL_FALSE
+WITH_TCMALLOC_MINIMAL_TRUE
 LIBTCMALLOC
 WITH_JEMALLOC_FALSE
 WITH_JEMALLOC_TRUE
@@ -947,6 +949,7 @@ with_debug
 enable_coverage
 with_fuse
 with_jemalloc
+with_tcmalloc_minimal
 with_tcmalloc
 enable_pgrefdebugging
 enable_cephfs_java
@@ -1535,7 +1538,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.94.2 to adapt to many kinds of systems.
+\`configure' configures ceph 0.94.3 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1606,7 +1609,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of ceph 0.94.2:";;
+     short | recursive ) echo "Configuration of ceph 0.94.3:";;
    esac
   cat <<\_ACEOF
 
@@ -1656,6 +1659,8 @@ Optional Packages:
   --with-debug            build extra debug binaries
   --without-fuse          disable FUSE userspace client
   --with-jemalloc         enable jemalloc for memory allocations
+  --with-tcmalloc-minimal enable minimal tcmalloc support for memory
+                          allocations
   --without-tcmalloc      disable tcmalloc for memory allocations
   --with-jdk-dir(=DIR)    Path to JDK directory
   --without-libatomic-ops disable libatomic-ops for the atomic_t type
@@ -1776,7 +1781,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-ceph configure 0.94.2
+ceph configure 0.94.3
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2852,7 +2857,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.94.2, which was
+It was created by ceph $as_me 0.94.3, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -4969,7 +4974,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='ceph'
- VERSION='0.94.2'
+ VERSION='0.94.3'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -12873,7 +12878,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='ceph'
- VERSION='0.94.2'
+ VERSION='0.94.3'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -19640,6 +19645,83 @@ else
 fi
 
 
+# tcmalloc-minimal?
+
+# Check whether --with-tcmalloc-minimal was given.
+if test "${with_tcmalloc_minimal+set}" = set; then :
+  withval=$with_tcmalloc_minimal;
+else
+  with_tcmalloc_minimal=no
+fi
+
+
+if test "x$with_jemalloc" = "xyes"; then :
+  with_tcmalloc_minimal=no
+fi
+
+TCMALLOC_MINIMAL=
+if test "x$with_tcmalloc_minimal" != xno; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for malloc in -ltcmalloc_minimal" >&5
+$as_echo_n "checking for malloc in -ltcmalloc_minimal... " >&6; }
+if ${ac_cv_lib_tcmalloc_minimal_malloc+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ltcmalloc_minimal  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char malloc ();
+int
+main ()
+{
+return malloc ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_tcmalloc_minimal_malloc=yes
+else
+  ac_cv_lib_tcmalloc_minimal_malloc=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_tcmalloc_minimal_malloc" >&5
+$as_echo "$ac_cv_lib_tcmalloc_minimal_malloc" >&6; }
+if test "x$ac_cv_lib_tcmalloc_minimal_malloc" = xyes; then :
+  LIBTCMALLOC="-ltcmalloc_minimal"
+
+
+$as_echo "#define HAVE_LIBTCMALLOC_MINIMAL 1" >>confdefs.h
+
+	       HAVE_LIBTCMALLOC_MINIMAL=1
+
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no tcmalloc found (do not use --with-tcmalloc-minimal)
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+fi
+ if test "$HAVE_LIBTCMALLOC_MINIMAL" = "1"; then
+  WITH_TCMALLOC_MINIMAL_TRUE=
+  WITH_TCMALLOC_MINIMAL_FALSE='#'
+else
+  WITH_TCMALLOC_MINIMAL_TRUE='#'
+  WITH_TCMALLOC_MINIMAL_FALSE=
+fi
+
+
 # tcmalloc?
 
 # Check whether --with-tcmalloc was given.
@@ -19653,6 +19735,9 @@ fi
 if test "x$with_jemalloc" = "xyes"; then :
   with_tcmalloc=no
 fi
+if test "x$with_tcmalloc_minimal" = "xyes"; then :
+  with_tcmalloc=no
+fi
 
 TCMALLOC=
 if test "x$with_tcmalloc" != xno; then :
@@ -19938,7 +20023,7 @@ else
 JAVA_TEST=Test.java
 CLASS_TEST=Test.class
 cat << \EOF > $JAVA_TEST
-/* #line 19941 "configure" */
+/* #line 20026 "configure" */
 public class Test {
 }
 EOF
@@ -24043,6 +24128,10 @@ if test -z "${WITH_JEMALLOC_TRUE}" && test -z "${WITH_JEMALLOC_FALSE}"; then
   as_fn_error $? "conditional \"WITH_JEMALLOC\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${WITH_TCMALLOC_MINIMAL_TRUE}" && test -z "${WITH_TCMALLOC_MINIMAL_FALSE}"; then
+  as_fn_error $? "conditional \"WITH_TCMALLOC_MINIMAL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 if test -z "${WITH_TCMALLOC_TRUE}" && test -z "${WITH_TCMALLOC_FALSE}"; then
   as_fn_error $? "conditional \"WITH_TCMALLOC\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -24528,7 +24617,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.94.2, which was
+This file was extended by ceph $as_me 0.94.3, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -24594,7 +24683,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.94.2
+ceph config.status 0.94.3
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff --git a/configure.ac b/configure.ac
index 3d86ecd..d90058d 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.94.2], [ceph-devel at vger.kernel.org])
+AC_INIT([ceph], [0.94.3], [ceph-devel at vger.kernel.org])
 
 # Create release string.  Used with VERSION for RPMs.
 RPM_RELEASE=0
@@ -500,6 +500,26 @@ AS_IF([test "x$with_jemalloc" = xyes],
 		  [no jemalloc found (do not use --with-jemalloc)])])])
 AM_CONDITIONAL(WITH_JEMALLOC, [test "$HAVE_LIBJEMALLOC" = "1"])
 
+# tcmalloc-minimal?
+AC_ARG_WITH([tcmalloc-minimal],
+	    [AS_HELP_STRING([--with-tcmalloc-minimal], [enable minimal tcmalloc support for memory allocations])],
+	    [],
+	    [with_tcmalloc_minimal=no])
+
+AS_IF([test "x$with_jemalloc" = "xyes"],[with_tcmalloc_minimal=no],[])
+
+TCMALLOC_MINIMAL=
+AS_IF([test "x$with_tcmalloc_minimal" != xno],
+        [AC_CHECK_LIB([tcmalloc_minimal], [malloc],
+         [AC_SUBST([LIBTCMALLOC], ["-ltcmalloc_minimal"])
+	       AC_DEFINE([HAVE_LIBTCMALLOC_MINIMAL], [1],
+	       		 [Define if you have tcmalloc])
+	       HAVE_LIBTCMALLOC_MINIMAL=1
+	     ],
+	    [AC_MSG_FAILURE(
+		  [no tcmalloc found (do not use --with-tcmalloc-minimal)])])])
+AM_CONDITIONAL(WITH_TCMALLOC_MINIMAL, [test "$HAVE_LIBTCMALLOC_MINIMAL" = "1"])
+
 # tcmalloc?
 AC_ARG_WITH([tcmalloc],
 	    [AS_HELP_STRING([--without-tcmalloc], [disable tcmalloc for memory allocations])],
@@ -507,6 +527,7 @@ AC_ARG_WITH([tcmalloc],
 	    [with_tcmalloc=yes])
 
 AS_IF([test "x$with_jemalloc" = "xyes"],[with_tcmalloc=no],[])
+AS_IF([test "x$with_tcmalloc_minimal" = "xyes"],[with_tcmalloc=no],[])
 
 TCMALLOC=
 AS_IF([test "x$with_tcmalloc" != xno],
diff --git a/man/Makefile-server.am b/man/Makefile-server.am
index 794275b..a780ebe 100644
--- a/man/Makefile-server.am
+++ b/man/Makefile-server.am
@@ -3,6 +3,7 @@ dist_man_MANS += \
 	crushtool.8 \
 	ceph-run.8 \
 	mount.ceph.8 \
+	ceph-create-keys.8 \
 	ceph-rest-api.8 \
 	ceph-debugpack.8
 
diff --git a/man/Makefile.in b/man/Makefile.in
index 8998031..29a26d6 100644
--- a/man/Makefile.in
+++ b/man/Makefile.in
@@ -116,6 +116,7 @@ DIST_COMMON = $(srcdir)/Makefile-client.am \
 @ENABLE_SERVER_TRUE@	crushtool.8 \
 @ENABLE_SERVER_TRUE@	ceph-run.8 \
 @ENABLE_SERVER_TRUE@	mount.ceph.8 \
+ at ENABLE_SERVER_TRUE@	ceph-create-keys.8 \
 @ENABLE_SERVER_TRUE@	ceph-rest-api.8 \
 @ENABLE_SERVER_TRUE@	ceph-debugpack.8
 
diff --git a/man/ceph-create-keys.8 b/man/ceph-create-keys.8
new file mode 100644
index 0000000..a634e7a
--- /dev/null
+++ b/man/ceph-create-keys.8
@@ -0,0 +1,97 @@
+.\" Man page generated from reStructuredText.
+.
+.TH "CEPH-CREATE-KEYS" "8" "June 02, 2015" "dev" "Ceph"
+.SH NAME
+ceph-create-keys \- ceph keyring generate tool
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH SYNOPSIS
+.nf
+\fBceph\-create\-keys\fP [\-h] [\-v] [\-\-cluster \fIname\fP] \-\-id \fIid\fP
+.fi
+.sp
+.SH DESCRIPTION
+.sp
+\fBceph\-create\-keys\fP is a utility to generate bootstrap keyrings using
+the given monitor when it is ready.
+.sp
+it creates following auth entities (or users)
+.sp
+\fBclient.admin\fP
+.INDENT 0.0
+.INDENT 3.5
+and its key for your client host.
+.UNINDENT
+.UNINDENT
+.sp
+\fBclient.bootstrap\-{osd, rgw, mds}\fP
+.INDENT 0.0
+.INDENT 3.5
+and their keys for bootstrapping corresponding services
+.UNINDENT
+.UNINDENT
+.sp
+To list all users in cluster:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+ceph auth list
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.B \-\-cluster
+name of the cluster (default \(aqceph\(aq).
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-i, \-\-id
+id of a ceph\-mon that is coming up. \fBceph\-create\-keys\fP will wait until it joins quorum.
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \-v, \-\-verbose
+be more verbose.
+.UNINDENT
+.SH AVAILABILITY
+.sp
+\fBceph\-create\-keys\fP is part of Ceph, a massively scalable, open\-source, distributed storage system.  Please refer
+to the Ceph documentation at \fI\%http://ceph.com/docs\fP for more
+information.
+.SH SEE ALSO
+.sp
+\fBceph\fP(8)
+.SH COPYRIGHT
+2010-2014, Inktank Storage, Inc. and contributors. Licensed under Creative Commons BY-SA
+.\" Generated by docutils manpage writer.
+.
diff --git a/src/.git_version b/src/.git_version
index c2544b9..7a78c9a 100644
--- a/src/.git_version
+++ b/src/.git_version
@@ -1,2 +1,2 @@
-5fb85614ca8f354284c713a2f9c610860720bbf3
-v0.94.2
+95cefea9fd9ab740263bf8bb4796fd864d9afe2b
+v0.94.3
diff --git a/src/Makefile-env.am b/src/Makefile-env.am
index 93d5a9a..b9374ad 100644
--- a/src/Makefile-env.am
+++ b/src/Makefile-env.am
@@ -35,6 +35,9 @@ check_PROGRAMS =
 # tests scripts will be appended to this
 check_SCRIPTS =
 
+# display the output of failed check_SCRIPTS after a failed make check
+export VERBOSE = true
+
 # python unit tests need to know where the scripts are located
 export PYTHONPATH=$(top_srcdir)/src/pybind
 
@@ -175,6 +178,10 @@ if WITH_LIBROCKSDB
 LIBOS += libos_rocksdb.la
 endif # WITH_LIBROCKSDB
 
+if WITH_TCMALLOC_MINIMAL
+LIBPERFGLUE += -ltcmalloc_minimal
+endif # WITH_TCMALLOC_MINIMAL
+
 if WITH_TCMALLOC
 LIBPERFGLUE += -ltcmalloc
 endif # WITH_TCMALLOC
diff --git a/src/Makefile.in b/src/Makefile.in
index de2a629..503810d 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -177,17 +177,18 @@ check_PROGRAMS = $(am__EXEEXT_44) $(am__EXEEXT_45) $(am__EXEEXT_46) \
 @WITH_LIBAIO_TRUE at am__append_10 = -laio
 @WITH_LIBZFS_TRUE at am__append_11 = libos_zfs.a -lzfs
 @WITH_LIBROCKSDB_TRUE at am__append_12 = libos_rocksdb.la
- at WITH_TCMALLOC_TRUE@am__append_13 = -ltcmalloc
- at WITH_JEMALLOC_TRUE@am__append_14 = -ljemalloc
+ at WITH_TCMALLOC_MINIMAL_TRUE@am__append_13 = -ltcmalloc_minimal
+ at WITH_TCMALLOC_TRUE@am__append_14 = -ltcmalloc
 @WITH_JEMALLOC_TRUE at am__append_15 = -ljemalloc
 @WITH_JEMALLOC_TRUE at am__append_16 = -ljemalloc
 @WITH_JEMALLOC_TRUE at am__append_17 = -ljemalloc
- at ENABLE_COVERAGE_TRUE@am__append_18 = -lgcov
- at ENABLE_CLIENT_TRUE@am__append_19 = brag/client/ceph-brag ceph \
+ at WITH_JEMALLOC_TRUE@am__append_18 = -ljemalloc
+ at ENABLE_COVERAGE_TRUE@am__append_19 = -lgcov
+ at ENABLE_CLIENT_TRUE@am__append_20 = brag/client/ceph-brag ceph \
 @ENABLE_CLIENT_TRUE@	ceph-post-file
- at ENABLE_CLIENT_TRUE@am__append_20 = brag/server brag/README.md brag/client
- at ENABLE_SERVER_TRUE@@WITH_MON_TRUE at am__append_21 = libmon.la
- at ENABLE_SERVER_TRUE@@WITH_MON_TRUE at am__append_22 = \
+ at ENABLE_CLIENT_TRUE@am__append_21 = brag/server brag/README.md brag/client
+ at ENABLE_SERVER_TRUE@@WITH_MON_TRUE at am__append_22 = libmon.la
+ at ENABLE_SERVER_TRUE@@WITH_MON_TRUE at am__append_23 = \
 @ENABLE_SERVER_TRUE@@WITH_MON_TRUE@	mon/AuthMonitor.h \
 @ENABLE_SERVER_TRUE@@WITH_MON_TRUE@	mon/DataHealthService.h \
 @ENABLE_SERVER_TRUE@@WITH_MON_TRUE@	mon/Elector.h \
@@ -216,14 +217,14 @@ check_PROGRAMS = $(am__EXEEXT_44) $(am__EXEEXT_45) $(am__EXEEXT_46) \
 
 
 # There are no libmds_types so use the full mds library for dencoder for now
- at ENABLE_CLIENT_TRUE@am__append_23 = $(LIBMDS_SOURCES)
- at ENABLE_CLIENT_TRUE@am__append_24 = $(LIBMDS_DEPS) \
+ at ENABLE_CLIENT_TRUE@am__append_24 = $(LIBMDS_SOURCES)
+ at ENABLE_CLIENT_TRUE@am__append_25 = $(LIBMDS_DEPS) \
 @ENABLE_CLIENT_TRUE@	libcls_lock_client.la \
 @ENABLE_CLIENT_TRUE@	libcls_refcount_client.la \
 @ENABLE_CLIENT_TRUE@	libcls_replica_log_client.a \
 @ENABLE_CLIENT_TRUE@	libcls_rgw_client.la libcls_user_client.a
- at ENABLE_SERVER_TRUE@@WITH_MDS_TRUE at am__append_25 = libmds.la
- at ENABLE_SERVER_TRUE@@WITH_MDS_TRUE at am__append_26 =  \
+ at ENABLE_SERVER_TRUE@@WITH_MDS_TRUE at am__append_26 = libmds.la
+ at ENABLE_SERVER_TRUE@@WITH_MDS_TRUE at am__append_27 =  \
 @ENABLE_SERVER_TRUE@@WITH_MDS_TRUE@	mds/inode_backtrace.h \
 @ENABLE_SERVER_TRUE@@WITH_MDS_TRUE@	mds/flock.h mds/locks.c \
 @ENABLE_SERVER_TRUE@@WITH_MDS_TRUE@	mds/locks.h mds/CDentry.h \
@@ -273,12 +274,12 @@ check_PROGRAMS = $(am__EXEEXT_44) $(am__EXEEXT_45) $(am__EXEEXT_46) \
 @ENABLE_SERVER_TRUE@@WITH_MDS_TRUE@	mds/events/ETableClient.h \
 @ENABLE_SERVER_TRUE@@WITH_MDS_TRUE@	mds/events/ETableServer.h \
 @ENABLE_SERVER_TRUE@@WITH_MDS_TRUE@	mds/events/EUpdate.h
- at ENABLE_SERVER_TRUE@@LINUX_TRUE at am__append_27 = os/BtrfsFileStoreBackend.cc
- at ENABLE_SERVER_TRUE@@WITH_LIBXFS_TRUE at am__append_28 = os/XfsFileStoreBackend.cc
- at ENABLE_SERVER_TRUE@@WITH_LIBZFS_TRUE at am__append_29 = os/ZFSFileStoreBackend.cc
- at ENABLE_SERVER_TRUE@@WITH_LTTNG_TRUE at am__append_30 = $(LIBOS_TP)
- at ENABLE_SERVER_TRUE@am__append_31 = libos.la
- at ENABLE_SERVER_TRUE@am__append_32 = \
+ at ENABLE_SERVER_TRUE@@LINUX_TRUE at am__append_28 = os/BtrfsFileStoreBackend.cc
+ at ENABLE_SERVER_TRUE@@WITH_LIBXFS_TRUE at am__append_29 = os/XfsFileStoreBackend.cc
+ at ENABLE_SERVER_TRUE@@WITH_LIBZFS_TRUE at am__append_30 = os/ZFSFileStoreBackend.cc
+ at ENABLE_SERVER_TRUE@@WITH_LTTNG_TRUE at am__append_31 = $(LIBOS_TP)
+ at ENABLE_SERVER_TRUE@am__append_32 = libos.la
+ at ENABLE_SERVER_TRUE@am__append_33 = \
 @ENABLE_SERVER_TRUE@	os/btrfs_ioctl.h \
 @ENABLE_SERVER_TRUE@	os/chain_xattr.h \
 @ENABLE_SERVER_TRUE@	os/BtrfsFileStoreBackend.h \
@@ -306,20 +307,20 @@ check_PROGRAMS = $(am__EXEEXT_44) $(am__EXEEXT_45) $(am__EXEEXT_46) \
 @ENABLE_SERVER_TRUE@	os/XfsFileStoreBackend.h \
 @ENABLE_SERVER_TRUE@	os/ZFSFileStoreBackend.h
 
- at ENABLE_SERVER_TRUE@@WITH_SLIBROCKSDB_TRUE at am__append_33 = libos_rocksdb.la
- at ENABLE_SERVER_TRUE@@WITH_SLIBROCKSDB_TRUE at am__append_34 = os/RocksDBStore.h
- at ENABLE_SERVER_TRUE@@WITH_DLIBROCKSDB_TRUE at am__append_35 = libos_rocksdb.la
- at ENABLE_SERVER_TRUE@@WITH_DLIBROCKSDB_TRUE at am__append_36 = os/RocksDBStore.h
- at ENABLE_SERVER_TRUE@@WITH_LIBZFS_TRUE at am__append_37 = libos_zfs.a
- at ENABLE_SERVER_TRUE@@WITH_LIBZFS_TRUE at am__append_38 = os/ZFS.h
- at ENABLE_SERVER_TRUE@@WITH_KINETIC_TRUE at am__append_39 = os/KineticStore.cc
- at ENABLE_SERVER_TRUE@@WITH_KINETIC_TRUE at am__append_40 = -std=gnu++11
- at ENABLE_SERVER_TRUE@@WITH_KINETIC_TRUE at am__append_41 = -lkinetic_client -lprotobuf -lglog -lgflags libcrypto.a
- at ENABLE_SERVER_TRUE@@WITH_KINETIC_TRUE at am__append_42 = os/KineticStore.h
- at ENABLE_SERVER_TRUE@@WITH_KINETIC_TRUE@@WITH_OSD_TRUE at am__append_43 = -std=gnu++11
- at ENABLE_SERVER_TRUE@@WITH_LTTNG_TRUE@@WITH_OSD_TRUE at am__append_44 = $(LIBOSD_TP)
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_45 = libosd.la
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_46 = \
+ at ENABLE_SERVER_TRUE@@WITH_SLIBROCKSDB_TRUE at am__append_34 = libos_rocksdb.la
+ at ENABLE_SERVER_TRUE@@WITH_SLIBROCKSDB_TRUE at am__append_35 = os/RocksDBStore.h
+ at ENABLE_SERVER_TRUE@@WITH_DLIBROCKSDB_TRUE at am__append_36 = libos_rocksdb.la
+ at ENABLE_SERVER_TRUE@@WITH_DLIBROCKSDB_TRUE at am__append_37 = os/RocksDBStore.h
+ at ENABLE_SERVER_TRUE@@WITH_LIBZFS_TRUE at am__append_38 = libos_zfs.a
+ at ENABLE_SERVER_TRUE@@WITH_LIBZFS_TRUE at am__append_39 = os/ZFS.h
+ at ENABLE_SERVER_TRUE@@WITH_KINETIC_TRUE at am__append_40 = os/KineticStore.cc
+ at ENABLE_SERVER_TRUE@@WITH_KINETIC_TRUE at am__append_41 = -std=gnu++11
+ at ENABLE_SERVER_TRUE@@WITH_KINETIC_TRUE at am__append_42 = -lkinetic_client -lprotobuf -lglog -lgflags libcrypto.a
+ at ENABLE_SERVER_TRUE@@WITH_KINETIC_TRUE at am__append_43 = os/KineticStore.h
+ at ENABLE_SERVER_TRUE@@WITH_KINETIC_TRUE@@WITH_OSD_TRUE at am__append_44 = -std=gnu++11
+ at ENABLE_SERVER_TRUE@@WITH_LTTNG_TRUE@@WITH_OSD_TRUE at am__append_45 = $(LIBOSD_TP)
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_46 = libosd.la
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_47 = \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	osd/Ager.h \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	osd/ClassHandler.h \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	osd/HitSet.h \
@@ -342,19 +343,19 @@ check_PROGRAMS = $(am__EXEEXT_44) $(am__EXEEXT_45) $(am__EXEEXT_46) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	osd/Watch.h \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	osd/osd_types.h
 
- at LINUX_TRUE@am__append_47 = -export-symbols-regex '.*__erasure_code_.*'
 @LINUX_TRUE at am__append_48 = -export-symbols-regex '.*__erasure_code_.*'
- at HAVE_NEON_TRUE@am__append_49 = libec_jerasure_neon.la
- at LINUX_TRUE@am__append_50 = -export-symbols-regex '.*__erasure_code_.*'
- at HAVE_SSSE3_TRUE@am__append_51 = libec_jerasure_sse3.la
- at LINUX_TRUE@am__append_52 = -export-symbols-regex '.*__erasure_code_.*'
- at HAVE_SSE4_PCLMUL_TRUE@am__append_53 = libec_jerasure_sse4.la
- at LINUX_TRUE@am__append_54 = -export-symbols-regex '.*__erasure_code_.*'
+ at LINUX_TRUE@am__append_49 = -export-symbols-regex '.*__erasure_code_.*'
+ at HAVE_NEON_TRUE@am__append_50 = libec_jerasure_neon.la
+ at LINUX_TRUE@am__append_51 = -export-symbols-regex '.*__erasure_code_.*'
+ at HAVE_SSSE3_TRUE@am__append_52 = libec_jerasure_sse3.la
+ at LINUX_TRUE@am__append_53 = -export-symbols-regex '.*__erasure_code_.*'
+ at HAVE_SSE4_PCLMUL_TRUE@am__append_54 = libec_jerasure_sse4.la
 @LINUX_TRUE at am__append_55 = -export-symbols-regex '.*__erasure_code_.*'
 @LINUX_TRUE at am__append_56 = -export-symbols-regex '.*__erasure_code_.*'
+ at LINUX_TRUE@am__append_57 = -export-symbols-regex '.*__erasure_code_.*'
 
 # ISA
- at WITH_BETTER_YASM_ELF64_TRUE@am__append_57 = \
+ at WITH_BETTER_YASM_ELF64_TRUE@am__append_58 = \
 @WITH_BETTER_YASM_ELF64_TRUE@	erasure-code/isa/ErasureCodeIsa.h \
 @WITH_BETTER_YASM_ELF64_TRUE@	erasure-code/isa/ErasureCodeIsaTableCache.h \
 @WITH_BETTER_YASM_ELF64_TRUE@	erasure-code/isa/xor_op.h \
@@ -365,10 +366,10 @@ check_PROGRAMS = $(am__EXEEXT_44) $(am__EXEEXT_45) $(am__EXEEXT_46) \
 @WITH_BETTER_YASM_ELF64_TRUE@	erasure-code/isa/isa-l/include/gf_vect_mul.h \
 @WITH_BETTER_YASM_ELF64_TRUE@	erasure-code/isa/isa-l/include/types.h
 
- at LINUX_TRUE@@WITH_BETTER_YASM_ELF64_TRUE at am__append_58 = -export-symbols-regex '.*__erasure_code_.*'
- at WITH_BETTER_YASM_ELF64_TRUE@am__append_59 = libec_isa.la
- at ENABLE_CLIENT_TRUE@am__append_60 = libclient.la
- at ENABLE_CLIENT_TRUE@am__append_61 = \
+ at LINUX_TRUE@@WITH_BETTER_YASM_ELF64_TRUE at am__append_59 = -export-symbols-regex '.*__erasure_code_.*'
+ at WITH_BETTER_YASM_ELF64_TRUE@am__append_60 = libec_isa.la
+ at ENABLE_CLIENT_TRUE@am__append_61 = libclient.la
+ at ENABLE_CLIENT_TRUE@am__append_62 = \
 @ENABLE_CLIENT_TRUE@	client/Client.h \
 @ENABLE_CLIENT_TRUE@	client/Dentry.h \
 @ENABLE_CLIENT_TRUE@	client/Dir.h \
@@ -382,34 +383,37 @@ check_PROGRAMS = $(am__EXEEXT_44) $(am__EXEEXT_45) $(am__EXEEXT_46) \
 @ENABLE_CLIENT_TRUE@	client/ioctl.h \
 @ENABLE_CLIENT_TRUE@	client/ObjecterWriteback.h
 
- at ENABLE_CLIENT_TRUE@@WITH_FUSE_TRUE at am__append_62 = libclient_fuse.la
- at ENABLE_CLIENT_TRUE@@WITH_FUSE_TRUE at am__append_63 = client/fuse_ll.h
- at ENABLE_CLIENT_TRUE@am__append_64 = ceph_test_ioctls
- at WITH_TCMALLOC_TRUE@am__append_65 = perfglue/heap_profiler.cc
- at WITH_TCMALLOC_TRUE@am__append_66 = -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free
+ at ENABLE_CLIENT_TRUE@@WITH_FUSE_TRUE at am__append_63 = libclient_fuse.la
+ at ENABLE_CLIENT_TRUE@@WITH_FUSE_TRUE at am__append_64 = client/fuse_ll.h
+ at ENABLE_CLIENT_TRUE@am__append_65 = ceph_test_ioctls
+ at WITH_TCMALLOC_TRUE@am__append_66 = perfglue/heap_profiler.cc
 @WITH_TCMALLOC_TRUE at am__append_67 = -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free
- at WITH_TCMALLOC_FALSE@am__append_68 = perfglue/disabled_heap_profiler.cc
- at WITH_PROFILER_TRUE@am__append_69 = perfglue/cpu_profiler.cc
- at WITH_PROFILER_FALSE@am__append_70 = perfglue/disabled_stubs.cc
- at WITH_RBD_TRUE@am__append_71 = \
+ at WITH_TCMALLOC_TRUE@am__append_68 = -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free
+ at WITH_TCMALLOC_FALSE@@WITH_TCMALLOC_MINIMAL_TRUE at am__append_69 = perfglue/heap_profiler.cc
+ at WITH_TCMALLOC_FALSE@@WITH_TCMALLOC_MINIMAL_TRUE at am__append_70 = -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free
+ at WITH_TCMALLOC_FALSE@@WITH_TCMALLOC_MINIMAL_TRUE at am__append_71 = -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free
+ at WITH_TCMALLOC_FALSE@@WITH_TCMALLOC_MINIMAL_FALSE at am__append_72 = perfglue/disabled_heap_profiler.cc
+ at WITH_PROFILER_TRUE@am__append_73 = perfglue/cpu_profiler.cc
+ at WITH_PROFILER_FALSE@am__append_74 = perfglue/disabled_stubs.cc
+ at WITH_RBD_TRUE@am__append_75 = \
 @WITH_RBD_TRUE@	common/blkdev.cc
 
- at ENABLE_XIO_TRUE@am__append_72 = \
+ at ENABLE_XIO_TRUE@am__append_76 = \
 @ENABLE_XIO_TRUE@	common/address_helper.cc
 
- at WITH_GOOD_YASM_ELF64_TRUE@am__append_73 = common/crc32c_intel_fast_asm.S common/crc32c_intel_fast_zero_asm.S
- at LINUX_TRUE@am__append_74 = -lrt
- at ENABLE_XIO_TRUE@am__append_75 = \
+ at WITH_GOOD_YASM_ELF64_TRUE@am__append_77 = common/crc32c_intel_fast_asm.S common/crc32c_intel_fast_zero_asm.S
+ at LINUX_TRUE@am__append_78 = -lrt
+ at ENABLE_XIO_TRUE@am__append_79 = \
 @ENABLE_XIO_TRUE@	common/address_helper.h
 
- at LINUX_TRUE@am__append_76 = libsecret.la
- at LINUX_TRUE@am__append_77 = msg/async/EventEpoll.cc
- at DARWIN_TRUE@am__append_78 = msg/async/EventKqueue.cc
- at FREEBSD_TRUE@am__append_79 = msg/async/EventKqueue.cc
- at LINUX_TRUE@am__append_80 = msg/async/EventEpoll.h
- at DARWIN_TRUE@am__append_81 = msg/async/EventKqueue.h
- at FREEBSD_TRUE@am__append_82 = msg/async/EventKqueue.h
- at ENABLE_XIO_TRUE@am__append_83 = \
+ at LINUX_TRUE@am__append_80 = libsecret.la
+ at LINUX_TRUE@am__append_81 = msg/async/EventEpoll.cc
+ at DARWIN_TRUE@am__append_82 = msg/async/EventKqueue.cc
+ at FREEBSD_TRUE@am__append_83 = msg/async/EventKqueue.cc
+ at LINUX_TRUE@am__append_84 = msg/async/EventEpoll.h
+ at DARWIN_TRUE@am__append_85 = msg/async/EventKqueue.h
+ at FREEBSD_TRUE@am__append_86 = msg/async/EventKqueue.h
+ at ENABLE_XIO_TRUE@am__append_87 = \
 @ENABLE_XIO_TRUE@	msg/xio/QueueStrategy.cc \
 @ENABLE_XIO_TRUE@	msg/xio/XioConnection.cc \
 @ENABLE_XIO_TRUE@	msg/xio/XioMessenger.cc \
@@ -417,7 +421,7 @@ check_PROGRAMS = $(am__EXEEXT_44) $(am__EXEEXT_45) $(am__EXEEXT_46) \
 @ENABLE_XIO_TRUE@	msg/xio/XioPortal.cc \
 @ENABLE_XIO_TRUE@	msg/xio/XioPool.cc
 
- at ENABLE_XIO_TRUE@am__append_84 = \
+ at ENABLE_XIO_TRUE@am__append_88 = \
 @ENABLE_XIO_TRUE@	msg/xio/DispatchStrategy.h \
 @ENABLE_XIO_TRUE@	msg/xio/FastStrategy.h \
 @ENABLE_XIO_TRUE@	msg/xio/QueueStrategy.h \
@@ -429,18 +433,18 @@ check_PROGRAMS = $(am__EXEEXT_44) $(am__EXEEXT_45) $(am__EXEEXT_46) \
 @ENABLE_XIO_TRUE@	msg/xio/XioPortal.h \
 @ENABLE_XIO_TRUE@	msg/xio/XioSubmit.h
 
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__append_85 =  \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__append_89 =  \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	librados_internal.la \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	librados_api.la
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__append_86 = \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__append_90 = \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	librados_internal.la libcls_lock_client.la \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	$(LIBOSDC) $(LIBCOMMON_DEPS)
 
- at ENABLE_CLIENT_TRUE@@WITH_LTTNG_TRUE@@WITH_RADOS_TRUE at am__append_87 = $(LIBRADOS_TP)
- at ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE at am__append_88 = -fvisibility=hidden -fvisibility-inlines-hidden
- at ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE at am__append_89 = -Xcompiler -Xlinker -Xcompiler '--exclude-libs=ALL'
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__append_90 = librados.la
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__append_91 = \
+ at ENABLE_CLIENT_TRUE@@WITH_LTTNG_TRUE@@WITH_RADOS_TRUE at am__append_91 = $(LIBRADOS_TP)
+ at ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE at am__append_92 = -fvisibility=hidden -fvisibility-inlines-hidden
+ at ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE at am__append_93 = -Xcompiler -Xlinker -Xcompiler '--exclude-libs=ALL'
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__append_94 = librados.la
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__append_95 = \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	librados/snap_set_diff.h \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	librados/AioCompletionImpl.h \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	librados/IoCtxImpl.h \
@@ -449,18 +453,18 @@ check_PROGRAMS = $(am__EXEEXT_44) $(am__EXEEXT_45) $(am__EXEEXT_46) \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	librados/RadosXattrIter.h \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	librados/ListObjectImpl.h
 
- at ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOSSTRIPER_TRUE@@WITH_RADOS_TRUE at am__append_92 = -export-symbols-regex '^radosstriper_.*'
- at ENABLE_CLIENT_TRUE@@WITH_RADOSSTRIPER_TRUE@@WITH_RADOS_TRUE at am__append_93 = libradosstriper.la
- at ENABLE_CLIENT_TRUE@@WITH_RADOSSTRIPER_TRUE@@WITH_RADOS_TRUE at am__append_94 = \
+ at ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOSSTRIPER_TRUE@@WITH_RADOS_TRUE at am__append_96 = -export-symbols-regex '^radosstriper_.*'
+ at ENABLE_CLIENT_TRUE@@WITH_RADOSSTRIPER_TRUE@@WITH_RADOS_TRUE at am__append_97 = libradosstriper.la
+ at ENABLE_CLIENT_TRUE@@WITH_RADOSSTRIPER_TRUE@@WITH_RADOS_TRUE at am__append_98 = \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSSTRIPER_TRUE@@WITH_RADOS_TRUE@	libradosstriper/RadosStriperImpl.h \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSSTRIPER_TRUE@@WITH_RADOS_TRUE@	libradosstriper/MultiAioCompletionImpl.h
 
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_95 = librbd_internal.la \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_99 = librbd_internal.la \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	librbd_api.la
- at ENABLE_CLIENT_TRUE@@WITH_LTTNG_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_96 = $(LIBRBD_TP)
- at ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_97 = -Xcompiler -Xlinker -Xcompiler '--exclude-libs=ALL'
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_98 = librbd.la
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_99 = \
+ at ENABLE_CLIENT_TRUE@@WITH_LTTNG_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_100 = $(LIBRBD_TP)
+ at ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_101 = -Xcompiler -Xlinker -Xcompiler '--exclude-libs=ALL'
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_102 = librbd.la
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_103 = \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	librbd/AioCompletion.h \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	librbd/AioRequest.h \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	librbd/AsyncFlattenRequest.h \
@@ -482,16 +486,16 @@ check_PROGRAMS = $(am__EXEEXT_44) $(am__EXEEXT_45) $(am__EXEEXT_46) \
 
 
 # inject rgw stuff in the decoder testcase
- at ENABLE_CLIENT_TRUE@am__append_100 = \
+ at ENABLE_CLIENT_TRUE@am__append_104 = \
 @ENABLE_CLIENT_TRUE@	rgw/rgw_dencoder.cc \
 @ENABLE_CLIENT_TRUE@	rgw/rgw_acl.cc \
 @ENABLE_CLIENT_TRUE@	rgw/rgw_common.cc \
 @ENABLE_CLIENT_TRUE@	rgw/rgw_env.cc \
 @ENABLE_CLIENT_TRUE@	rgw/rgw_json_enc.cc
 
- at ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE at am__append_101 = librgw.la \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE at am__append_105 = librgw.la \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE@	libcivetweb.la
- at ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE at am__append_102 = \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE at am__append_106 = \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE@	$(LIBRADOS) \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE@	libcls_rgw_client.la \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE@	libcls_log_client.a \
@@ -507,11 +511,11 @@ check_PROGRAMS = $(am__EXEEXT_44) $(am__EXEEXT_45) $(am__EXEEXT_46) \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE@	-lfcgi \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE@	-ldl
 
- at ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE at am__append_103 = radosgw \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE at am__append_107 = radosgw \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE@	radosgw-admin
- at ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE at am__append_104 = ceph_rgw_multiparser \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE at am__append_108 = ceph_rgw_multiparser \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE@	ceph_rgw_jsonparser
- at ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE at am__append_105 = \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE at am__append_109 = \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE@	rgw/logrotate.conf \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE@	rgw/rgw_acl.h \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE@	rgw/rgw_acl_s3.h \
@@ -569,15 +573,15 @@ check_PROGRAMS = $(am__EXEEXT_44) $(am__EXEEXT_45) $(am__EXEEXT_46) \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE@	civetweb/include/civetweb_conf.h \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE@	civetweb/src/md5.h
 
- at ENABLE_CLIENT_TRUE@am__append_106 = libcls_lock_client.la \
+ at ENABLE_CLIENT_TRUE@am__append_110 = libcls_lock_client.la \
 @ENABLE_CLIENT_TRUE@	libcls_refcount_client.la \
 @ENABLE_CLIENT_TRUE@	libcls_rgw_client.la libcls_rbd_client.la
- at ENABLE_CLIENT_TRUE@am__append_107 = libcls_version_client.a \
+ at ENABLE_CLIENT_TRUE@am__append_111 = libcls_version_client.a \
 @ENABLE_CLIENT_TRUE@	libcls_log_client.a \
 @ENABLE_CLIENT_TRUE@	libcls_statelog_client.a \
 @ENABLE_CLIENT_TRUE@	libcls_replica_log_client.a \
 @ENABLE_CLIENT_TRUE@	libcls_user_client.a
- at ENABLE_CLIENT_TRUE@am__append_108 = \
+ at ENABLE_CLIENT_TRUE@am__append_112 = \
 @ENABLE_CLIENT_TRUE@	cls/lock/cls_lock_types.h \
 @ENABLE_CLIENT_TRUE@	cls/lock/cls_lock_ops.h \
 @ENABLE_CLIENT_TRUE@	cls/lock/cls_lock_client.h \
@@ -604,7 +608,7 @@ check_PROGRAMS = $(am__EXEEXT_44) $(am__EXEEXT_45) $(am__EXEEXT_46) \
 @ENABLE_CLIENT_TRUE@	cls/user/cls_user_ops.h \
 @ENABLE_CLIENT_TRUE@	cls/user/cls_user_types.h
 
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_109 = libcls_hello.la \
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_113 = libcls_hello.la \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	libcls_rbd.la \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	libcls_lock.la \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	libcls_refcount.la \
@@ -614,15 +618,15 @@ check_PROGRAMS = $(am__EXEEXT_44) $(am__EXEEXT_45) $(am__EXEEXT_46) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	libcls_replica_log.la \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	libcls_user.la \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	libcls_rgw.la
- at ENABLE_SERVER_TRUE@@LINUX_TRUE@@WITH_OSD_TRUE at am__append_110 = libcls_kvs.la
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_111 = \
+ at ENABLE_SERVER_TRUE@@LINUX_TRUE@@WITH_OSD_TRUE at am__append_114 = libcls_kvs.la
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_115 = \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	key_value_store/key_value_structure.h \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	key_value_store/kv_flat_btree_async.h \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	key_value_store/kvs_arg_types.h
 
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_112 = librbd_replay.la \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_116 = librbd_replay.la \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	librbd_replay_ios.la
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_113 = rbd_replay/BoundedBuffer.hpp \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_117 = rbd_replay/BoundedBuffer.hpp \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	rbd_replay/actions.hpp \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	rbd_replay/Deser.hpp \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	rbd_replay/ImageNameMap.hpp \
@@ -633,21 +637,21 @@ check_PROGRAMS = $(am__EXEEXT_44) $(am__EXEEXT_45) $(am__EXEEXT_46) \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	rbd_replay/Replayer.hpp \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	rbd_replay/Ser.hpp
 
- at ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_114 = rbd-replay
- at ENABLE_CLIENT_TRUE@@WITH_BABELTRACE_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_115 = rbd-replay-prep
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_116 = \
+ at ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_118 = rbd-replay
+ at ENABLE_CLIENT_TRUE@@WITH_BABELTRACE_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_119 = rbd-replay-prep
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_120 = \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	test/erasure-code/test-erasure-code.sh
 
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_117 = test/erasure-code/ceph_erasure_code_benchmark.h \
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_121 = test/erasure-code/ceph_erasure_code_benchmark.h \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	test/erasure-code/ceph_erasure_code_benchmark.h \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	test/erasure-code/ErasureCodeExample.h
- at ENABLE_SERVER_TRUE@@LINUX_TRUE@@WITH_OSD_TRUE at am__append_118 = -ldl
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_119 = ceph_erasure_code_benchmark \
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	ceph_erasure_code
- at ENABLE_SERVER_TRUE@@LINUX_TRUE@@WITH_OSD_TRUE at am__append_120 = -ldl
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_121 = ceph_erasure_code_non_regression
 @ENABLE_SERVER_TRUE@@LINUX_TRUE@@WITH_OSD_TRUE at am__append_122 = -ldl
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_123 = libec_example.la \
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_123 = ceph_erasure_code_benchmark \
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	ceph_erasure_code
+ at ENABLE_SERVER_TRUE@@LINUX_TRUE@@WITH_OSD_TRUE at am__append_124 = -ldl
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_125 = ceph_erasure_code_non_regression
+ at ENABLE_SERVER_TRUE@@LINUX_TRUE@@WITH_OSD_TRUE at am__append_126 = -ldl
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_127 = libec_example.la \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	libec_missing_entry_point.la \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	libec_missing_version.la \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	libec_hangs.la \
@@ -657,59 +661,59 @@ check_PROGRAMS = $(am__EXEEXT_44) $(am__EXEEXT_45) $(am__EXEEXT_46) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	libec_test_jerasure_sse4.la \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	libec_test_jerasure_sse3.la \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	libec_test_jerasure_generic.la
- at ENABLE_SERVER_TRUE@@LINUX_TRUE@@WITH_OSD_TRUE at am__append_124 = -ldl
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_125 = unittest_erasure_code_plugin \
+ at ENABLE_SERVER_TRUE@@LINUX_TRUE@@WITH_OSD_TRUE at am__append_128 = -ldl
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_129 = unittest_erasure_code_plugin \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	unittest_erasure_code \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	unittest_erasure_code_jerasure \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	unittest_erasure_code_plugin_jerasure
- at ENABLE_SERVER_TRUE@@LINUX_TRUE@@WITH_OSD_TRUE at am__append_126 = -ldl
- at ENABLE_SERVER_TRUE@@LINUX_TRUE@@WITH_OSD_TRUE at am__append_127 = -ldl
- at ENABLE_SERVER_TRUE@@LINUX_TRUE@@WITH_BETTER_YASM_ELF64_TRUE@@WITH_OSD_TRUE at am__append_128 = -ldl
- at ENABLE_SERVER_TRUE@@WITH_BETTER_YASM_ELF64_TRUE@@WITH_OSD_TRUE at am__append_129 = unittest_erasure_code_isa \
- at ENABLE_SERVER_TRUE@@WITH_BETTER_YASM_ELF64_TRUE@@WITH_OSD_TRUE@	unittest_erasure_code_plugin_isa
- at ENABLE_SERVER_TRUE@@LINUX_TRUE@@WITH_BETTER_YASM_ELF64_TRUE@@WITH_OSD_TRUE at am__append_130 = -ldl
+ at ENABLE_SERVER_TRUE@@LINUX_TRUE@@WITH_OSD_TRUE at am__append_130 = -ldl
 @ENABLE_SERVER_TRUE@@LINUX_TRUE@@WITH_OSD_TRUE at am__append_131 = -ldl
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_132 =  \
+ at ENABLE_SERVER_TRUE@@LINUX_TRUE@@WITH_BETTER_YASM_ELF64_TRUE@@WITH_OSD_TRUE at am__append_132 = -ldl
+ at ENABLE_SERVER_TRUE@@WITH_BETTER_YASM_ELF64_TRUE@@WITH_OSD_TRUE at am__append_133 = unittest_erasure_code_isa \
+ at ENABLE_SERVER_TRUE@@WITH_BETTER_YASM_ELF64_TRUE@@WITH_OSD_TRUE@	unittest_erasure_code_plugin_isa
+ at ENABLE_SERVER_TRUE@@LINUX_TRUE@@WITH_BETTER_YASM_ELF64_TRUE@@WITH_OSD_TRUE at am__append_134 = -ldl
+ at ENABLE_SERVER_TRUE@@LINUX_TRUE@@WITH_OSD_TRUE at am__append_135 = -ldl
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_136 =  \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	unittest_erasure_code_lrc \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	unittest_erasure_code_plugin_lrc \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	unittest_erasure_code_shec \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	unittest_erasure_code_shec_all \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	unittest_erasure_code_shec_thread \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	unittest_erasure_code_example
- at ENABLE_SERVER_TRUE@@LINUX_TRUE@@WITH_OSD_TRUE at am__append_133 = -ldl
- at ENABLE_SERVER_TRUE@@LINUX_TRUE@@WITH_OSD_TRUE at am__append_134 = -ldl
- at ENABLE_SERVER_TRUE@@LINUX_TRUE@@WITH_OSD_TRUE at am__append_135 = -ldl
- at ENABLE_SERVER_TRUE@@LINUX_TRUE@@WITH_OSD_TRUE at am__append_136 = -ldl
- at ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE at am__append_137 = test/messenger/message_helper.h \
+ at ENABLE_SERVER_TRUE@@LINUX_TRUE@@WITH_OSD_TRUE at am__append_137 = -ldl
+ at ENABLE_SERVER_TRUE@@LINUX_TRUE@@WITH_OSD_TRUE at am__append_138 = -ldl
+ at ENABLE_SERVER_TRUE@@LINUX_TRUE@@WITH_OSD_TRUE at am__append_139 = -ldl
+ at ENABLE_SERVER_TRUE@@LINUX_TRUE@@WITH_OSD_TRUE at am__append_140 = -ldl
+ at ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE at am__append_141 = test/messenger/message_helper.h \
 @ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@	test/messenger/simple_dispatcher.h \
 @ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@	test/messenger/xio_dispatcher.h
- at ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@@LINUX_TRUE at am__append_138 = -ldl
- at ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@@LINUX_TRUE at am__append_139 = -ldl
- at ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE at am__append_140 = simple_server \
+ at ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@@LINUX_TRUE at am__append_142 = -ldl
+ at ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@@LINUX_TRUE at am__append_143 = -ldl
+ at ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE at am__append_144 = simple_server \
 @ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@	simple_client xio_server \
 @ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@	xio_client
- at ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@@LINUX_TRUE at am__append_141 = -ldl
- at ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@@LINUX_TRUE at am__append_142 = -ldl
- at COMPILER_HAS_VTA_TRUE@@ENABLE_CLIENT_TRUE at am__append_143 = -fno-var-tracking-assignments
- at COMPILER_HAS_VTA_TRUE@@ENABLE_CLIENT_TRUE at am__append_144 = -fno-var-tracking-assignments
- at ENABLE_CLIENT_TRUE@am__append_145 = ceph-dencoder
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__append_146 = libradostest.la \
+ at ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@@LINUX_TRUE at am__append_145 = -ldl
+ at ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@@LINUX_TRUE at am__append_146 = -ldl
+ at COMPILER_HAS_VTA_TRUE@@ENABLE_CLIENT_TRUE at am__append_147 = -fno-var-tracking-assignments
+ at COMPILER_HAS_VTA_TRUE@@ENABLE_CLIENT_TRUE at am__append_148 = -fno-var-tracking-assignments
+ at ENABLE_CLIENT_TRUE@am__append_149 = ceph-dencoder
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__append_150 = libradostest.la \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	librados_test_stub.la
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__append_147 = ceph_test_rados \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__append_151 = ceph_test_rados \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	ceph_test_mutate
- at ENABLE_CLIENT_TRUE@@WITH_BUILD_TESTS_TRUE@@WITH_RADOS_TRUE at am__append_148 = test_build_librados
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__append_149 =  \
+ at ENABLE_CLIENT_TRUE@@WITH_BUILD_TESTS_TRUE@@WITH_RADOS_TRUE at am__append_152 = test_build_librados
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__append_153 =  \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	ceph_smalliobench \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	ceph_omapbench
- at ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE at am__append_150 = ceph_kvstorebench \
+ at ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE at am__append_154 = ceph_kvstorebench \
 @ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE@	ceph_test_rados_list_parallel \
 @ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE@	ceph_test_rados_open_pools_parallel \
 @ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE@	ceph_test_rados_delete_pools_parallel \
 @ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE@	ceph_test_rados_watch_notify
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__append_151 =  \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__append_155 =  \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	unittest_librados \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	unittest_librados_config
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__append_152 =  \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__append_156 =  \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	ceph_multi_stress_watch \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	ceph_test_cls_rbd \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	ceph_test_cls_refcount \
@@ -735,7 +739,7 @@ check_PROGRAMS = $(am__EXEEXT_44) $(am__EXEEXT_45) $(am__EXEEXT_46) \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	ceph_test_rados_api_tier \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	ceph_test_rados_api_lock \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	ceph_test_stress_watch
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__append_153 = \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__append_157 = \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	test/librados_test_stub/TestClassHandler.h \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	test/librados_test_stub/TestRadosClient.h \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	test/librados_test_stub/TestMemRadosClient.h \
@@ -743,41 +747,43 @@ check_PROGRAMS = $(am__EXEEXT_44) $(am__EXEEXT_45) $(am__EXEEXT_46) \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	test/librados_test_stub/TestMemIoCtxImpl.h \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	test/librados_test_stub/TestIoCtxImpl.h
 
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_154 = ceph_smalliobenchrbd \
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	ceph_test_librbd
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_155 = unittest_rbd_replay \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_158 = ceph_smalliobenchrbd \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	ceph_test_librbd \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	ceph_test_librbd_api
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_159 = unittest_rbd_replay \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	unittest_librbd
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_156 = librbd_test.la
- at ENABLE_CLIENT_TRUE@@WITH_LTTNG_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_157 = $(LIBRBD_TP)
- at ENABLE_CLIENT_TRUE@@WITH_LTTNG_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_158 = $(LIBRBD_TP)
- at ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_159 = ceph_test_librbd_fsx
- at ENABLE_CLIENT_TRUE@@WITH_RADOSSTRIPER_TRUE@@WITH_RADOS_TRUE at am__append_160 = libradosstripertest.la
- at ENABLE_CLIENT_TRUE@@WITH_RADOSSTRIPER_TRUE@@WITH_RADOS_TRUE at am__append_161 = ceph_test_rados_striper_api_io \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_160 = librbd_test.la
+ at ENABLE_CLIENT_TRUE@@WITH_LTTNG_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_161 = $(LIBRBD_TP)
+ at ENABLE_CLIENT_TRUE@@WITH_LTTNG_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_162 = $(LIBRBD_TP)
+ at ENABLE_CLIENT_TRUE@@WITH_LTTNG_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_163 = $(LIBRBD_TP)
+ at ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_164 = ceph_test_librbd_fsx
+ at ENABLE_CLIENT_TRUE@@WITH_RADOSSTRIPER_TRUE@@WITH_RADOS_TRUE at am__append_165 = libradosstripertest.la
+ at ENABLE_CLIENT_TRUE@@WITH_RADOSSTRIPER_TRUE@@WITH_RADOS_TRUE at am__append_166 = ceph_test_rados_striper_api_io \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSSTRIPER_TRUE@@WITH_RADOS_TRUE@	ceph_test_rados_striper_api_aio \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSSTRIPER_TRUE@@WITH_RADOS_TRUE@	ceph_test_rados_striper_api_striping
- at ENABLE_CLIENT_TRUE@@WITH_BUILD_TESTS_TRUE@@WITH_CEPHFS_TRUE@@WITH_RADOS_TRUE at am__append_162 = test_build_libcephfs
- at ENABLE_CLIENT_TRUE@@WITH_CEPHFS_TRUE@@WITH_RADOS_TRUE at am__append_163 = unittest_encoding \
+ at ENABLE_CLIENT_TRUE@@WITH_BUILD_TESTS_TRUE@@WITH_CEPHFS_TRUE@@WITH_RADOS_TRUE at am__append_167 = test_build_libcephfs
+ at ENABLE_CLIENT_TRUE@@WITH_CEPHFS_TRUE@@WITH_RADOS_TRUE at am__append_168 = unittest_encoding \
 @ENABLE_CLIENT_TRUE@@WITH_CEPHFS_TRUE@@WITH_RADOS_TRUE@	unittest_base64 \
 @ENABLE_CLIENT_TRUE@@WITH_CEPHFS_TRUE@@WITH_RADOS_TRUE@	unittest_run_cmd \
 @ENABLE_CLIENT_TRUE@@WITH_CEPHFS_TRUE@@WITH_RADOS_TRUE@	unittest_simple_spin \
 @ENABLE_CLIENT_TRUE@@WITH_CEPHFS_TRUE@@WITH_RADOS_TRUE@	unittest_libcephfs_config
- at ENABLE_CLIENT_TRUE@@WITH_CEPHFS_TRUE@@WITH_RADOS_TRUE at am__append_164 = ceph_test_libcephfs \
+ at ENABLE_CLIENT_TRUE@@WITH_CEPHFS_TRUE@@WITH_RADOS_TRUE at am__append_169 = ceph_test_libcephfs \
 @ENABLE_CLIENT_TRUE@@WITH_CEPHFS_TRUE@@WITH_RADOS_TRUE@	ceph_test_c_headers
- at ENABLE_CLIENT_TRUE@@WITH_BUILD_TESTS_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE at am__append_165 = test_build_librgw
- at ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE at am__append_166 = ceph_test_cors \
+ at ENABLE_CLIENT_TRUE@@WITH_BUILD_TESTS_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE at am__append_170 = test_build_librgw
+ at ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE at am__append_171 = ceph_test_cors \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE@	ceph_test_rgw_manifest \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE@	ceph_test_cls_rgw_meta \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE@	ceph_test_cls_rgw_log \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE@	ceph_test_cls_rgw_opstate \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE@	ceph_test_cls_rgw
- at ENABLE_SERVER_TRUE@am__append_167 = ceph_test_async_driver \
+ at ENABLE_SERVER_TRUE@am__append_172 = ceph_test_async_driver \
 @ENABLE_SERVER_TRUE@	ceph_test_msgr ceph_streamtest \
 @ENABLE_SERVER_TRUE@	ceph_test_trans ceph_test_mon_workloadgen \
 @ENABLE_SERVER_TRUE@	ceph_test_mon_msg ceph_perf_objectstore
- at ENABLE_SERVER_TRUE@@LINUX_TRUE at am__append_168 =  \
+ at ENABLE_SERVER_TRUE@@LINUX_TRUE at am__append_173 =  \
 @ENABLE_SERVER_TRUE@@LINUX_TRUE@	ceph_test_objectstore \
 @ENABLE_SERVER_TRUE@@LINUX_TRUE@	ceph_test_filestore
- at ENABLE_SERVER_TRUE@am__append_169 =  \
+ at ENABLE_SERVER_TRUE@am__append_174 =  \
 @ENABLE_SERVER_TRUE@	ceph_test_objectstore_workloadgen \
 @ENABLE_SERVER_TRUE@	ceph_test_filestore_idempotent \
 @ENABLE_SERVER_TRUE@	ceph_test_filestore_idempotent_sequence \
@@ -785,48 +791,48 @@ check_PROGRAMS = $(am__EXEEXT_44) $(am__EXEEXT_45) $(am__EXEEXT_46) \
 @ENABLE_SERVER_TRUE@	ceph_test_object_map \
 @ENABLE_SERVER_TRUE@	ceph_test_keyvaluedb_atomicity \
 @ENABLE_SERVER_TRUE@	ceph_test_keyvaluedb_iterators
- at ENABLE_CLIENT_TRUE@@ENABLE_SERVER_TRUE@@WITH_RADOS_TRUE at am__append_170 = ceph_smalliobenchfs \
+ at ENABLE_CLIENT_TRUE@@ENABLE_SERVER_TRUE@@WITH_RADOS_TRUE at am__append_175 = ceph_smalliobenchfs \
 @ENABLE_CLIENT_TRUE@@ENABLE_SERVER_TRUE@@WITH_RADOS_TRUE@	ceph_smalliobenchdumb \
 @ENABLE_CLIENT_TRUE@@ENABLE_SERVER_TRUE@@WITH_RADOS_TRUE@	ceph_tpbench
- at ENABLE_SERVER_TRUE@@WITH_MON_TRUE at am__append_171 = ceph_test_keys
- at ENABLE_SERVER_TRUE@@WITH_MON_TRUE at am__append_172 = get_command_descriptions
- at ENABLE_SERVER_TRUE@@WITH_MON_TRUE at am__append_173 =  \
+ at ENABLE_SERVER_TRUE@@WITH_MON_TRUE at am__append_176 = ceph_test_keys
+ at ENABLE_SERVER_TRUE@@WITH_MON_TRUE at am__append_177 = get_command_descriptions
+ at ENABLE_SERVER_TRUE@@WITH_MON_TRUE at am__append_178 =  \
 @ENABLE_SERVER_TRUE@@WITH_MON_TRUE@	unittest_mon_moncap \
 @ENABLE_SERVER_TRUE@@WITH_MON_TRUE@	unittest_mon_pgmap
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_174 =  \
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_179 =  \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	unittest_ecbackend \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	unittest_osdscrub \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	unittest_pglog \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	unittest_hitset \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	unittest_osd_osdcap
- at ENABLE_SERVER_TRUE@@LINUX_TRUE@@WITH_OSD_TRUE at am__append_175 = -ldl
- at ENABLE_SERVER_TRUE@@LINUX_TRUE@@WITH_OSD_TRUE at am__append_176 = -ldl
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_177 = ceph_test_snap_mapper
- at ENABLE_SERVER_TRUE@am__append_178 = unittest_chain_xattr \
+ at ENABLE_SERVER_TRUE@@LINUX_TRUE@@WITH_OSD_TRUE at am__append_180 = -ldl
+ at ENABLE_SERVER_TRUE@@LINUX_TRUE@@WITH_OSD_TRUE at am__append_181 = -ldl
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_182 = ceph_test_snap_mapper
+ at ENABLE_SERVER_TRUE@am__append_183 = unittest_chain_xattr \
 @ENABLE_SERVER_TRUE@	unittest_flatindex unittest_lfnindex
- at ENABLE_SERVER_TRUE@@WITH_MDS_TRUE at am__append_179 = unittest_mds_authcap
- at WITH_BUILD_TESTS_TRUE@am__append_180 = test_build_libcommon
- at LINUX_TRUE@am__append_181 = libsystest.la
- at ENABLE_ROOT_MAKE_CHECK_TRUE@am__append_182 = test/ceph-disk-root.sh
- at ENABLE_ROOT_MAKE_CHECK_FALSE@am__append_183 = test/ceph-disk.sh
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__append_184 =  \
+ at ENABLE_SERVER_TRUE@@WITH_MDS_TRUE at am__append_184 = unittest_mds_authcap
+ at WITH_BUILD_TESTS_TRUE@am__append_185 = test_build_libcommon
+ at LINUX_TRUE@am__append_186 = libsystest.la
+ at ENABLE_ROOT_MAKE_CHECK_TRUE@am__append_187 = test/ceph-disk-root.sh
+ at ENABLE_ROOT_MAKE_CHECK_FALSE@am__append_188 = test/ceph-disk.sh
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__append_189 =  \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	ceph_scratchtool \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	ceph_scratchtoolpp \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	ceph_radosacl
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__append_185 = rados
- at ENABLE_CLIENT_TRUE@@WITH_CEPHFS_TRUE@@WITH_RADOS_TRUE at am__append_186 = ceph-client-debug
- at ENABLE_SERVER_TRUE@am__append_187 = ceph-osdomap-tool \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__append_190 = rados
+ at ENABLE_CLIENT_TRUE@@WITH_CEPHFS_TRUE@@WITH_RADOS_TRUE at am__append_191 = ceph-client-debug
+ at ENABLE_SERVER_TRUE@am__append_192 = ceph-osdomap-tool \
 @ENABLE_SERVER_TRUE@	ceph-monstore-tool ceph-kvstore-tool
- at ENABLE_SERVER_TRUE@@LINUX_TRUE@@WITH_OSD_TRUE at am__append_188 = -ldl
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_189 = ceph-objectstore-tool
- at ENABLE_CLIENT_TRUE@@ENABLE_SERVER_TRUE@@WITH_MDS_TRUE@@WITH_RADOS_TRUE at am__append_190 = cephfs-journal-tool \
+ at ENABLE_SERVER_TRUE@@LINUX_TRUE@@WITH_OSD_TRUE at am__append_193 = -ldl
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_194 = ceph-objectstore-tool
+ at ENABLE_CLIENT_TRUE@@ENABLE_SERVER_TRUE@@WITH_MDS_TRUE@@WITH_RADOS_TRUE at am__append_195 = cephfs-journal-tool \
 @ENABLE_CLIENT_TRUE@@ENABLE_SERVER_TRUE@@WITH_MDS_TRUE@@WITH_RADOS_TRUE@	cephfs-table-tool
- at WITH_REST_BENCH_TRUE@am__append_191 = rest-bench
- at WITH_REST_BENCH_TRUE@@WITH_SYSTEM_LIBS3_TRUE at am__append_192 = -ls3
- at WITH_REST_BENCH_TRUE@@WITH_SYSTEM_LIBS3_FALSE at am__append_193 = libs3/build/lib/libs3.a -lcurl -lxml2
- at WITH_REST_BENCH_TRUE@@WITH_SYSTEM_LIBS3_FALSE at am__append_194 = libs3
- at WITH_SLIBROCKSDB_TRUE@am__append_195 = rocksdb
- at WITH_SLIBROCKSDB_FALSE@am__append_196 = \
+ at WITH_REST_BENCH_TRUE@am__append_196 = rest-bench
+ at WITH_REST_BENCH_TRUE@@WITH_SYSTEM_LIBS3_TRUE at am__append_197 = -ls3
+ at WITH_REST_BENCH_TRUE@@WITH_SYSTEM_LIBS3_FALSE at am__append_198 = libs3/build/lib/libs3.a -lcurl -lxml2
+ at WITH_REST_BENCH_TRUE@@WITH_SYSTEM_LIBS3_FALSE at am__append_199 = libs3
+ at WITH_SLIBROCKSDB_TRUE@am__append_200 = rocksdb
+ at WITH_SLIBROCKSDB_FALSE@am__append_201 = \
 @WITH_SLIBROCKSDB_FALSE@        rocksdb/.arcconfig \
 @WITH_SLIBROCKSDB_FALSE@        rocksdb/.clang-format \
 @WITH_SLIBROCKSDB_FALSE@        rocksdb/.gitignore \
@@ -1195,50 +1201,50 @@ check_PROGRAMS = $(am__EXEEXT_44) $(am__EXEEXT_45) $(am__EXEEXT_46) \
 @WITH_SLIBROCKSDB_FALSE@        rocksdb/utilities/ttl/db_ttl_impl.h \
 @WITH_SLIBROCKSDB_FALSE@        rocksdb/utilities/ttl/ttl_test.cc
 
- at ENABLE_CLIENT_TRUE@am__append_197 = pybind/ceph_argparse.py
- at ENABLE_CLIENT_TRUE@am__append_198 = ceph-syn
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__append_199 = \
+ at ENABLE_CLIENT_TRUE@am__append_202 = pybind/ceph_argparse.py
+ at ENABLE_CLIENT_TRUE@am__append_203 = ceph-syn
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__append_204 = \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	$(srcdir)/bash_completion/rados \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	$(srcdir)/bash_completion/radosgw-admin
 
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__append_200 = pybind/rados.py
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__append_201 = librados-config
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_202 = \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__append_205 = pybind/rados.py
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__append_206 = librados-config
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_207 = \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(srcdir)/bash_completion/rbd
 
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_203 = \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_208 = \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	ceph-rbdnamer \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	rbd-replay-many
 
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_204 = pybind/rbd.py
- at ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_205 = libkrbd.la
- at ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_206 = rbd
- at ENABLE_CLIENT_TRUE@@WITH_FUSE_TRUE@@WITH_RADOS_TRUE at am__append_207 = ceph-fuse \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_209 = pybind/rbd.py
+ at ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_210 = libkrbd.la
+ at ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__append_211 = rbd
+ at ENABLE_CLIENT_TRUE@@WITH_FUSE_TRUE@@WITH_RADOS_TRUE at am__append_212 = ceph-fuse \
 @ENABLE_CLIENT_TRUE@@WITH_FUSE_TRUE@@WITH_RADOS_TRUE@	rbd-fuse
- at ENABLE_CLIENT_TRUE@@WITH_CEPHFS_TRUE@@WITH_RADOS_TRUE at am__append_208 = cephfs
- at ENABLE_CLIENT_TRUE@@WITH_CEPHFS_TRUE@@WITH_RADOS_TRUE at am__append_209 = pybind/cephfs.py
- at ENABLE_CLIENT_TRUE@@WITH_CEPHFS_TRUE@@WITH_RADOS_TRUE at am__append_210 = libcephfs.la
- at ENABLE_CEPHFS_JAVA_TRUE@@ENABLE_CLIENT_TRUE@@WITH_CEPHFS_TRUE@@WITH_RADOS_TRUE at am__append_211 = libcephfs_jni.la
- at ENABLE_SERVER_TRUE@am__append_212 = ceph-run ceph-rest-api \
+ at ENABLE_CLIENT_TRUE@@WITH_CEPHFS_TRUE@@WITH_RADOS_TRUE at am__append_213 = cephfs
+ at ENABLE_CLIENT_TRUE@@WITH_CEPHFS_TRUE@@WITH_RADOS_TRUE at am__append_214 = pybind/cephfs.py
+ at ENABLE_CLIENT_TRUE@@WITH_CEPHFS_TRUE@@WITH_RADOS_TRUE at am__append_215 = libcephfs.la
+ at ENABLE_CEPHFS_JAVA_TRUE@@ENABLE_CLIENT_TRUE@@WITH_CEPHFS_TRUE@@WITH_RADOS_TRUE at am__append_216 = libcephfs_jni.la
+ at ENABLE_SERVER_TRUE@am__append_217 = ceph-run ceph-rest-api \
 @ENABLE_SERVER_TRUE@	ceph-debugpack ceph-crush-location \
 @ENABLE_SERVER_TRUE@	ceph-coverage
- at ENABLE_SERVER_TRUE@am__append_213 = pybind/ceph_rest_api.py
- at ENABLE_SERVER_TRUE@am__append_214 = ceph-coverage init-ceph
- at ENABLE_SERVER_TRUE@am__append_215 = init-ceph
- at ENABLE_SERVER_TRUE@@LINUX_TRUE at am__append_216 = mount.ceph
- at ENABLE_SERVER_TRUE@am__append_217 = mount.fuse.ceph
- at ENABLE_SERVER_TRUE@@WITH_MON_TRUE at am__append_218 = ceph-mon
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_219 = \
+ at ENABLE_SERVER_TRUE@am__append_218 = pybind/ceph_rest_api.py
+ at ENABLE_SERVER_TRUE@am__append_219 = ceph-coverage init-ceph
+ at ENABLE_SERVER_TRUE@am__append_220 = init-ceph
+ at ENABLE_SERVER_TRUE@@LINUX_TRUE at am__append_221 = mount.ceph
+ at ENABLE_SERVER_TRUE@am__append_222 = mount.fuse.ceph
+ at ENABLE_SERVER_TRUE@@WITH_MON_TRUE at am__append_223 = ceph-mon
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_224 = \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	ceph-disk \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	ceph-disk-prepare \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	ceph-disk-activate \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	ceph-disk-udev
 
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_220 = \
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_225 = \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	ceph-clsinfo
 
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_221 = ceph-osd
- at ENABLE_SERVER_TRUE@@WITH_MDS_TRUE at am__append_222 = ceph-mds
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am__append_226 = ceph-osd
+ at ENABLE_SERVER_TRUE@@WITH_MDS_TRUE at am__append_227 = ceph-mds
 subdir = src
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_classpath.m4 \
@@ -2217,7 +2223,7 @@ libmsg_la_OBJECTS = $(am_libmsg_la_OBJECTS)
 @ENABLE_SERVER_TRUE@@WITH_KINETIC_TRUE at am__DEPENDENCIES_6 =  \
 @ENABLE_SERVER_TRUE@@WITH_KINETIC_TRUE@	libcrypto.a
 @ENABLE_SERVER_TRUE at libos_la_DEPENDENCIES = $(LIBOS_TYPES) \
- at ENABLE_SERVER_TRUE@	$(am__append_30) $(am__DEPENDENCIES_6)
+ at ENABLE_SERVER_TRUE@	$(am__append_31) $(am__DEPENDENCIES_6)
 am__libos_la_SOURCES_DIST = os/chain_xattr.cc os/DBObjectMap.cc \
 	os/GenericObjectMap.cc os/FileJournal.cc os/FileStore.cc \
 	os/FlatIndex.cc os/GenericFileStoreBackend.cc os/HashIndex.cc \
@@ -2280,7 +2286,7 @@ libos_types_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__DEPENDENCIES_5) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(LIBOSD_TYPES) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(LIBOS_TYPES) \
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_44)
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_45)
 am__libosd_la_SOURCES_DIST = osd/PG.cc osd/ReplicatedPG.cc \
 	osd/ReplicatedBackend.cc osd/ECBackend.cc osd/ECMsgTypes.cc \
 	osd/ECTransaction.cc osd/PGBackend.cc osd/Ager.cc \
@@ -2327,19 +2333,19 @@ am__libperfglue_la_SOURCES_DIST = perfglue/heap_profiler.cc \
 	perfglue/disabled_heap_profiler.cc perfglue/cpu_profiler.cc \
 	perfglue/disabled_stubs.cc
 @WITH_TCMALLOC_TRUE at am__objects_20 = perfglue/heap_profiler.lo
- at WITH_TCMALLOC_FALSE@am__objects_21 =  \
- at WITH_TCMALLOC_FALSE@	perfglue/disabled_heap_profiler.lo
- at WITH_PROFILER_TRUE@am__objects_22 = perfglue/cpu_profiler.lo
- at WITH_PROFILER_FALSE@am__objects_23 = perfglue/disabled_stubs.lo
+ at WITH_TCMALLOC_FALSE@@WITH_TCMALLOC_MINIMAL_TRUE at am__objects_21 = perfglue/heap_profiler.lo
+ at WITH_TCMALLOC_FALSE@@WITH_TCMALLOC_MINIMAL_FALSE at am__objects_22 = perfglue/disabled_heap_profiler.lo
+ at WITH_PROFILER_TRUE@am__objects_23 = perfglue/cpu_profiler.lo
+ at WITH_PROFILER_FALSE@am__objects_24 = perfglue/disabled_stubs.lo
 am_libperfglue_la_OBJECTS = $(am__objects_20) $(am__objects_21) \
-	$(am__objects_22) $(am__objects_23)
+	$(am__objects_22) $(am__objects_23) $(am__objects_24)
 libperfglue_la_OBJECTS = $(am_libperfglue_la_OBJECTS)
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__DEPENDENCIES_7 =  \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	librados_internal.la \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	libcls_lock_client.la \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	$(LIBOSDC) \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	$(am__DEPENDENCIES_3)
-am__DEPENDENCIES_8 = $(am__DEPENDENCIES_7) $(am__append_87)
+am__DEPENDENCIES_8 = $(am__DEPENDENCIES_7) $(am__append_91)
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at librados_la_DEPENDENCIES =  \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	$(am__DEPENDENCIES_8) \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	$(am__DEPENDENCIES_1) \
@@ -2438,7 +2444,7 @@ libradostest_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	libcls_lock_client.la \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(am__DEPENDENCIES_1) \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(am__DEPENDENCIES_2) \
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(am__append_96)
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(am__append_100)
 am__librbd_la_SOURCES_DIST = librbd/librbd.cc
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am_librbd_la_OBJECTS = librbd/librbd_la-librbd.lo
 librbd_la_OBJECTS = $(am_librbd_la_OBJECTS)
@@ -2507,13 +2513,15 @@ librbd_replay_ios_la_OBJECTS = $(am_librbd_replay_ios_la_OBJECTS)
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am_librbd_replay_ios_la_rpath =
 librbd_test_la_LIBADD =
 am__librbd_test_la_SOURCES_DIST = test/librbd/test_fixture.cc \
-	test/librbd/test_librbd.cc test/librbd/test_ImageWatcher.cc \
-	test/librbd/test_internal.cc test/librbd/test_main.cc
+	test/librbd/test_support.cc test/librbd/test_librbd.cc \
+	test/librbd/test_ImageWatcher.cc test/librbd/test_internal.cc \
+	test/librbd/test_ObjectMap.cc
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am_librbd_test_la_OBJECTS = test/librbd/librbd_test_la-test_fixture.lo \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	test/librbd/librbd_test_la-test_support.lo \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	test/librbd/librbd_test_la-test_librbd.lo \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	test/librbd/librbd_test_la-test_ImageWatcher.lo \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	test/librbd/librbd_test_la-test_internal.lo \
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	test/librbd/librbd_test_la-test_main.lo
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	test/librbd/librbd_test_la-test_ObjectMap.lo
 librbd_test_la_OBJECTS = $(am_librbd_test_la_OBJECTS)
 librbd_test_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
@@ -2631,7 +2639,8 @@ libsystest_la_OBJECTS = $(am_libsystest_la_OBJECTS)
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	ceph_test_rados_api_lock$(EXEEXT) \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	ceph_test_stress_watch$(EXEEXT)
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__EXEEXT_9 = ceph_smalliobenchrbd$(EXEEXT) \
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	ceph_test_librbd$(EXEEXT)
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	ceph_test_librbd$(EXEEXT) \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	ceph_test_librbd_api$(EXEEXT)
 @ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am__EXEEXT_10 = ceph_test_librbd_fsx$(EXEEXT)
 @ENABLE_CLIENT_TRUE@@WITH_RADOSSTRIPER_TRUE@@WITH_RADOS_TRUE at am__EXEEXT_11 = ceph_test_rados_striper_api_io$(EXEEXT) \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSSTRIPER_TRUE@@WITH_RADOS_TRUE@	ceph_test_rados_striper_api_aio$(EXEEXT) \
@@ -2779,7 +2788,7 @@ am__ceph_dencoder_SOURCES_DIST = test/encoding/ceph_dencoder.cc \
 	perfglue/disabled_heap_profiler.cc perfglue/disabled_stubs.cc \
 	rgw/rgw_dencoder.cc rgw/rgw_acl.cc rgw/rgw_common.cc \
 	rgw/rgw_env.cc rgw/rgw_json_enc.cc
-am__objects_24 = mds/ceph_dencoder-Capability.$(OBJEXT) \
+am__objects_25 = mds/ceph_dencoder-Capability.$(OBJEXT) \
 	mds/ceph_dencoder-MDS.$(OBJEXT) \
 	mds/ceph_dencoder-Beacon.$(OBJEXT) \
 	mds/ceph_dencoder-locks.$(OBJEXT) \
@@ -2808,19 +2817,19 @@ am__objects_24 = mds/ceph_dencoder-Capability.$(OBJEXT) \
 	mds/ceph_dencoder-MDSAuthCaps.$(OBJEXT) \
 	mds/ceph_dencoder-MDLog.$(OBJEXT) \
 	common/ceph_dencoder-TrackedOp.$(OBJEXT)
- at ENABLE_CLIENT_TRUE@am__objects_25 = $(am__objects_24)
- at ENABLE_CLIENT_TRUE@am__objects_26 =  \
+ at ENABLE_CLIENT_TRUE@am__objects_26 = $(am__objects_25)
+ at ENABLE_CLIENT_TRUE@am__objects_27 =  \
 @ENABLE_CLIENT_TRUE@	rgw/ceph_dencoder-rgw_dencoder.$(OBJEXT) \
 @ENABLE_CLIENT_TRUE@	rgw/ceph_dencoder-rgw_acl.$(OBJEXT) \
 @ENABLE_CLIENT_TRUE@	rgw/ceph_dencoder-rgw_common.$(OBJEXT) \
 @ENABLE_CLIENT_TRUE@	rgw/ceph_dencoder-rgw_env.$(OBJEXT) \
 @ENABLE_CLIENT_TRUE@	rgw/ceph_dencoder-rgw_json_enc.$(OBJEXT)
-am__objects_27 = $(am__objects_25) \
+am__objects_28 = $(am__objects_26) \
 	perfglue/ceph_dencoder-disabled_heap_profiler.$(OBJEXT) \
 	perfglue/ceph_dencoder-disabled_stubs.$(OBJEXT) \
-	$(am__objects_26)
+	$(am__objects_27)
 @ENABLE_CLIENT_TRUE at am_ceph_dencoder_OBJECTS = test/encoding/ceph_dencoder-ceph_dencoder.$(OBJEXT) \
- at ENABLE_CLIENT_TRUE@	$(am__objects_27)
+ at ENABLE_CLIENT_TRUE@	$(am__objects_28)
 ceph_dencoder_OBJECTS = $(am_ceph_dencoder_OBJECTS)
 @ENABLE_CLIENT_TRUE at ceph_dencoder_DEPENDENCIES = $(LIBRBD_TYPES) \
 @ENABLE_CLIENT_TRUE@	$(LIBOSD_TYPES) $(LIBOS_TYPES) \
@@ -2849,7 +2858,8 @@ am__ceph_mds_SOURCES_DIST = ceph_mds.cc
 @ENABLE_SERVER_TRUE@@WITH_MDS_TRUE at am_ceph_mds_OBJECTS =  \
 @ENABLE_SERVER_TRUE@@WITH_MDS_TRUE@	ceph_mds.$(OBJEXT)
 ceph_mds_OBJECTS = $(am_ceph_mds_OBJECTS)
-am__DEPENDENCIES_11 = libperfglue.la $(am__DEPENDENCIES_1)
+am__DEPENDENCIES_11 = libperfglue.la $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1)
 am__DEPENDENCIES_12 = libmds.la $(am__DEPENDENCIES_1) \
 	$(am__DEPENDENCIES_11)
 @ENABLE_SERVER_TRUE@@WITH_MDS_TRUE at ceph_mds_DEPENDENCIES =  \
@@ -3422,7 +3432,8 @@ ceph_test_libcephfs_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
 	$(ceph_test_libcephfs_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
 	$(LDFLAGS) -o $@
-am_ceph_test_librbd_OBJECTS =
+am__ceph_test_librbd_SOURCES_DIST = test/librbd/test_main.cc
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am_ceph_test_librbd_OBJECTS = test/librbd/ceph_test_librbd-test_main.$(OBJEXT)
 ceph_test_librbd_OBJECTS = $(am_ceph_test_librbd_OBJECTS)
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at ceph_test_librbd_DEPENDENCIES = librbd_test.la \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	librbd_api.la \
@@ -3435,21 +3446,40 @@ ceph_test_librbd_OBJECTS = $(am_ceph_test_librbd_OBJECTS)
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(am__DEPENDENCIES_15) \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(am__DEPENDENCIES_10) \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(RADOS_TEST_LDADD) \
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(am__append_158)
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(am__append_162)
 ceph_test_librbd_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
 	$(ceph_test_librbd_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
 	$(LDFLAGS) -o $@
-am__ceph_test_librbd_fsx_SOURCES_DIST = test/librbd/fsx.c \
-	common/dummy.cc
- at ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am_ceph_test_librbd_fsx_OBJECTS = test/librbd/ceph_test_librbd_fsx-fsx.$(OBJEXT) \
- at ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	common/dummy.$(OBJEXT)
+am__ceph_test_librbd_api_SOURCES_DIST = test/librbd/test_support.cc \
+	test/librbd/test_librbd.cc test/librbd/test_main.cc
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am_ceph_test_librbd_api_OBJECTS = test/librbd/ceph_test_librbd_api-test_support.$(OBJEXT) \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	test/librbd/ceph_test_librbd_api-test_librbd.$(OBJEXT) \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	test/librbd/ceph_test_librbd_api-test_main.$(OBJEXT)
+ceph_test_librbd_api_OBJECTS = $(am_ceph_test_librbd_api_OBJECTS)
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at ceph_test_librbd_api_DEPENDENCIES =  \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(LIBRBD) \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(LIBRADOS) \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(am__DEPENDENCIES_15) \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(am__DEPENDENCIES_10) \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(RADOS_TEST_LDADD) \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(am__append_163)
+ceph_test_librbd_api_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+	$(ceph_test_librbd_api_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+am__ceph_test_librbd_fsx_SOURCES_DIST = test/librbd/fsx.cc
+ at ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am_ceph_test_librbd_fsx_OBJECTS = test/librbd/ceph_test_librbd_fsx-fsx.$(OBJEXT)
 ceph_test_librbd_fsx_OBJECTS = $(am_ceph_test_librbd_fsx_OBJECTS)
 @ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at ceph_test_librbd_fsx_DEPENDENCIES = $(LIBKRBD) \
 @ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(LIBRBD) \
 @ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(LIBRADOS) \
 @ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(am__DEPENDENCIES_1) \
 @ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(am__DEPENDENCIES_1)
+ceph_test_librbd_fsx_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+	$(ceph_test_librbd_fsx_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
 am__ceph_test_mon_msg_SOURCES_DIST = test/mon/test-mon-msg.cc
 @ENABLE_SERVER_TRUE at am_ceph_test_mon_msg_OBJECTS = test/mon/ceph_test_mon_msg-test-mon-msg.$(OBJEXT)
 ceph_test_mon_msg_OBJECTS = $(am_ceph_test_mon_msg_OBJECTS)
@@ -4096,13 +4126,13 @@ simple_server_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
 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_28 = osdc/test_build_libcephfs-Objecter.$(OBJEXT) \
+am__objects_29 = 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)
 @ENABLE_CLIENT_TRUE@@WITH_BUILD_TESTS_TRUE@@WITH_CEPHFS_TRUE@@WITH_RADOS_TRUE at am_test_build_libcephfs_OBJECTS = test/test_build_libcephfs-buildtest_skeleton.$(OBJEXT) \
- at ENABLE_CLIENT_TRUE@@WITH_BUILD_TESTS_TRUE@@WITH_CEPHFS_TRUE@@WITH_RADOS_TRUE@	$(am__objects_28)
+ at ENABLE_CLIENT_TRUE@@WITH_BUILD_TESTS_TRUE@@WITH_CEPHFS_TRUE@@WITH_RADOS_TRUE@	$(am__objects_29)
 test_build_libcephfs_OBJECTS = $(am_test_build_libcephfs_OBJECTS)
 @ENABLE_CLIENT_TRUE@@WITH_BUILD_TESTS_TRUE@@WITH_CEPHFS_TRUE@@WITH_RADOS_TRUE at test_build_libcephfs_DEPENDENCIES = $(LIBCEPHFS) \
 @ENABLE_CLIENT_TRUE@@WITH_BUILD_TESTS_TRUE@@WITH_CEPHFS_TRUE@@WITH_RADOS_TRUE@	$(am__DEPENDENCIES_1) \
@@ -4127,10 +4157,10 @@ test_build_libcommon_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
 	$(test_build_libcommon_LDFLAGS) $(LDFLAGS) -o $@
 am__test_build_librados_SOURCES_DIST = test/buildtest_skeleton.cc \
 	common/buffer.cc librados/librados.cc
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__objects_29 = common/test_build_librados-buffer.$(OBJEXT) \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at am__objects_30 = common/test_build_librados-buffer.$(OBJEXT) \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	librados/test_build_librados-librados.$(OBJEXT)
 @ENABLE_CLIENT_TRUE@@WITH_BUILD_TESTS_TRUE@@WITH_RADOS_TRUE at am_test_build_librados_OBJECTS = test/test_build_librados-buildtest_skeleton.$(OBJEXT) \
- at ENABLE_CLIENT_TRUE@@WITH_BUILD_TESTS_TRUE@@WITH_RADOS_TRUE@	$(am__objects_29)
+ at ENABLE_CLIENT_TRUE@@WITH_BUILD_TESTS_TRUE@@WITH_RADOS_TRUE@	$(am__objects_30)
 test_build_librados_OBJECTS = $(am_test_build_librados_OBJECTS)
 @ENABLE_CLIENT_TRUE@@WITH_BUILD_TESTS_TRUE@@WITH_RADOS_TRUE at test_build_librados_DEPENDENCIES = $(am__DEPENDENCIES_8) \
 @ENABLE_CLIENT_TRUE@@WITH_BUILD_TESTS_TRUE@@WITH_RADOS_TRUE@	$(am__DEPENDENCIES_1) \
@@ -4153,7 +4183,7 @@ am__test_build_librgw_SOURCES_DIST = test/buildtest_skeleton.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 \
 	rgw/rgw_dencoder.cc
- at ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE at am__objects_30 = rgw/test_build_librgw-librgw.$(OBJEXT) \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE at am__objects_31 = rgw/test_build_librgw-librgw.$(OBJEXT) \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE@	rgw/test_build_librgw-rgw_acl.$(OBJEXT) \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE@	rgw/test_build_librgw-rgw_acl_s3.$(OBJEXT) \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE@	rgw/test_build_librgw-rgw_acl_swift.$(OBJEXT) \
@@ -4188,7 +4218,7 @@ am__test_build_librgw_SOURCES_DIST = test/buildtest_skeleton.cc \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE@	rgw/test_build_librgw-rgw_quota.$(OBJEXT) \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE@	rgw/test_build_librgw-rgw_dencoder.$(OBJEXT)
 @ENABLE_CLIENT_TRUE@@WITH_BUILD_TESTS_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE at am_test_build_librgw_OBJECTS = test/test_build_librgw-buildtest_skeleton.$(OBJEXT) \
- at ENABLE_CLIENT_TRUE@@WITH_BUILD_TESTS_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE@	$(am__objects_30)
+ at ENABLE_CLIENT_TRUE@@WITH_BUILD_TESTS_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE@	$(am__objects_31)
 test_build_librgw_OBJECTS = $(am_test_build_librgw_OBJECTS)
 @ENABLE_CLIENT_TRUE@@WITH_BUILD_TESTS_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE at test_build_librgw_DEPENDENCIES = $(am__DEPENDENCIES_18) \
 @ENABLE_CLIENT_TRUE@@WITH_BUILD_TESTS_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE@	$(am__DEPENDENCIES_1) \
@@ -4480,7 +4510,7 @@ am__unittest_erasure_code_jerasure_SOURCES_DIST =  \
 	erasure-code/jerasure/gf-complete/src/gf_w8.c \
 	erasure-code/jerasure/ErasureCodePluginJerasure.cc \
 	erasure-code/jerasure/ErasureCodeJerasure.cc
-am__objects_31 = erasure-code/unittest_erasure_code_jerasure-ErasureCode.$(OBJEXT) \
+am__objects_32 = erasure-code/unittest_erasure_code_jerasure-ErasureCode.$(OBJEXT) \
 	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) \
@@ -4500,7 +4530,7 @@ am__objects_31 = erasure-code/unittest_erasure_code_jerasure-ErasureCode.$(OBJEX
 	erasure-code/jerasure/unittest_erasure_code_jerasure-ErasureCodePluginJerasure.$(OBJEXT) \
 	erasure-code/jerasure/unittest_erasure_code_jerasure-ErasureCodeJerasure.$(OBJEXT)
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am_unittest_erasure_code_jerasure_OBJECTS = test/erasure-code/unittest_erasure_code_jerasure-TestErasureCodeJerasure.$(OBJEXT) \
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__objects_31)
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__objects_32)
 unittest_erasure_code_jerasure_OBJECTS =  \
 	$(am_unittest_erasure_code_jerasure_OBJECTS)
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at unittest_erasure_code_jerasure_DEPENDENCIES =  \
@@ -4518,12 +4548,12 @@ am__unittest_erasure_code_lrc_SOURCES_DIST =  \
 	erasure-code/ErasureCode.cc \
 	erasure-code/lrc/ErasureCodePluginLrc.cc \
 	erasure-code/lrc/ErasureCodeLrc.cc
-am__objects_32 =  \
+am__objects_33 =  \
 	erasure-code/unittest_erasure_code_lrc-ErasureCode.$(OBJEXT) \
 	erasure-code/lrc/unittest_erasure_code_lrc-ErasureCodePluginLrc.$(OBJEXT) \
 	erasure-code/lrc/unittest_erasure_code_lrc-ErasureCodeLrc.$(OBJEXT)
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am_unittest_erasure_code_lrc_OBJECTS = test/erasure-code/unittest_erasure_code_lrc-TestErasureCodeLrc.$(OBJEXT) \
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__objects_32)
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__objects_33)
 unittest_erasure_code_lrc_OBJECTS =  \
 	$(am_unittest_erasure_code_lrc_OBJECTS)
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at unittest_erasure_code_lrc_DEPENDENCIES =  \
@@ -4624,7 +4654,7 @@ am__unittest_erasure_code_shec_SOURCES_DIST =  \
 	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
-am__objects_33 =  \
+am__objects_34 =  \
 	erasure-code/unittest_erasure_code_shec-ErasureCode.$(OBJEXT) \
 	erasure-code/shec/unittest_erasure_code_shec-ErasureCodePluginShec.$(OBJEXT) \
 	erasure-code/shec/unittest_erasure_code_shec-ErasureCodeShec.$(OBJEXT) \
@@ -4648,7 +4678,7 @@ am__objects_33 =  \
 	erasure-code/jerasure/gf-complete/src/unittest_erasure_code_shec-gf_rand.$(OBJEXT) \
 	erasure-code/jerasure/gf-complete/src/unittest_erasure_code_shec-gf_w8.$(OBJEXT)
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am_unittest_erasure_code_shec_OBJECTS = test/erasure-code/unittest_erasure_code_shec-TestErasureCodeShec.$(OBJEXT) \
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__objects_33)
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__objects_34)
 unittest_erasure_code_shec_OBJECTS =  \
 	$(am_unittest_erasure_code_shec_OBJECTS)
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at unittest_erasure_code_shec_DEPENDENCIES =  \
@@ -4684,7 +4714,7 @@ am__unittest_erasure_code_shec_all_SOURCES_DIST =  \
 	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
-am__objects_34 = erasure-code/unittest_erasure_code_shec_all-ErasureCode.$(OBJEXT) \
+am__objects_35 = erasure-code/unittest_erasure_code_shec_all-ErasureCode.$(OBJEXT) \
 	erasure-code/shec/unittest_erasure_code_shec_all-ErasureCodePluginShec.$(OBJEXT) \
 	erasure-code/shec/unittest_erasure_code_shec_all-ErasureCodeShec.$(OBJEXT) \
 	erasure-code/shec/unittest_erasure_code_shec_all-ErasureCodeShecTableCache.$(OBJEXT) \
@@ -4707,7 +4737,7 @@ am__objects_34 = erasure-code/unittest_erasure_code_shec_all-ErasureCode.$(OBJEX
 	erasure-code/jerasure/gf-complete/src/unittest_erasure_code_shec_all-gf_rand.$(OBJEXT) \
 	erasure-code/jerasure/gf-complete/src/unittest_erasure_code_shec_all-gf_w8.$(OBJEXT)
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am_unittest_erasure_code_shec_all_OBJECTS = test/erasure-code/unittest_erasure_code_shec_all-TestErasureCodeShec_all.$(OBJEXT) \
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__objects_34)
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__objects_35)
 unittest_erasure_code_shec_all_OBJECTS =  \
 	$(am_unittest_erasure_code_shec_all_OBJECTS)
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at unittest_erasure_code_shec_all_DEPENDENCIES =  \
@@ -4743,7 +4773,7 @@ am__unittest_erasure_code_shec_thread_SOURCES_DIST =  \
 	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
-am__objects_35 = erasure-code/unittest_erasure_code_shec_thread-ErasureCode.$(OBJEXT) \
+am__objects_36 = erasure-code/unittest_erasure_code_shec_thread-ErasureCode.$(OBJEXT) \
 	erasure-code/shec/unittest_erasure_code_shec_thread-ErasureCodePluginShec.$(OBJEXT) \
 	erasure-code/shec/unittest_erasure_code_shec_thread-ErasureCodeShec.$(OBJEXT) \
 	erasure-code/shec/unittest_erasure_code_shec_thread-ErasureCodeShecTableCache.$(OBJEXT) \
@@ -4766,7 +4796,7 @@ am__objects_35 = erasure-code/unittest_erasure_code_shec_thread-ErasureCode.$(OB
 	erasure-code/jerasure/gf-complete/src/unittest_erasure_code_shec_thread-gf_rand.$(OBJEXT) \
 	erasure-code/jerasure/gf-complete/src/unittest_erasure_code_shec_thread-gf_w8.$(OBJEXT)
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at am_unittest_erasure_code_shec_thread_OBJECTS = test/erasure-code/unittest_erasure_code_shec_thread-TestErasureCodeShec_thread.$(OBJEXT) \
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__objects_35)
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__objects_36)
 unittest_erasure_code_shec_thread_OBJECTS =  \
 	$(am_unittest_erasure_code_shec_thread_OBJECTS)
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at unittest_erasure_code_shec_thread_DEPENDENCIES =  \
@@ -4909,7 +4939,8 @@ unittest_librados_config_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
 	$(unittest_librados_config_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
 	$(LDFLAGS) -o $@
-am_unittest_librbd_OBJECTS =
+am__unittest_librbd_SOURCES_DIST = test/librbd/test_main.cc
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at am_unittest_librbd_OBJECTS = test/librbd/unittest_librbd-test_main.$(OBJEXT)
 unittest_librbd_OBJECTS = $(am_unittest_librbd_OBJECTS)
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at unittest_librbd_DEPENDENCIES = librbd_test.la \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	librbd_api.la \
@@ -4923,7 +4954,11 @@ unittest_librbd_OBJECTS = $(am_unittest_librbd_OBJECTS)
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(am__DEPENDENCIES_15) \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(am__DEPENDENCIES_10) \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(RADOS_TEST_LDADD) \
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(am__append_157)
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(am__append_161)
+unittest_librbd_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+	$(unittest_librbd_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
 am_unittest_log_OBJECTS = log/unittest_log-test.$(OBJEXT)
 unittest_log_OBJECTS = $(am_unittest_log_OBJECTS)
 unittest_log_DEPENDENCIES = $(LIBCOMMON) $(am__DEPENDENCIES_15)
@@ -5426,7 +5461,7 @@ SOURCES = $(libcls_log_client_a_SOURCES) \
 	$(ceph_test_keyvaluedb_atomicity_SOURCES) \
 	$(ceph_test_keyvaluedb_iterators_SOURCES) \
 	$(ceph_test_libcephfs_SOURCES) $(ceph_test_librbd_SOURCES) \
-	$(nodist_EXTRA_ceph_test_librbd_SOURCES) \
+	$(ceph_test_librbd_api_SOURCES) \
 	$(ceph_test_librbd_fsx_SOURCES) $(ceph_test_mon_msg_SOURCES) \
 	$(ceph_test_mon_workloadgen_SOURCES) $(ceph_test_msgr_SOURCES) \
 	$(ceph_test_mutate_SOURCES) $(ceph_test_object_map_SOURCES) \
@@ -5507,7 +5542,6 @@ SOURCES = $(libcls_log_client_a_SOURCES) \
 	$(unittest_libcephfs_config_SOURCES) \
 	$(unittest_librados_SOURCES) \
 	$(unittest_librados_config_SOURCES) $(unittest_librbd_SOURCES) \
-	$(nodist_EXTRA_unittest_librbd_SOURCES) \
 	$(unittest_log_SOURCES) $(unittest_lru_SOURCES) \
 	$(unittest_mds_authcap_SOURCES) $(unittest_mds_types_SOURCES) \
 	$(unittest_mime_SOURCES) $(unittest_mon_moncap_SOURCES) \
@@ -5650,7 +5684,8 @@ DIST_SOURCES = $(am__libcls_log_client_a_SOURCES_DIST) \
 	$(am__ceph_test_keyvaluedb_atomicity_SOURCES_DIST) \
 	$(am__ceph_test_keyvaluedb_iterators_SOURCES_DIST) \
 	$(am__ceph_test_libcephfs_SOURCES_DIST) \
-	$(ceph_test_librbd_SOURCES) \
+	$(am__ceph_test_librbd_SOURCES_DIST) \
+	$(am__ceph_test_librbd_api_SOURCES_DIST) \
 	$(am__ceph_test_librbd_fsx_SOURCES_DIST) \
 	$(am__ceph_test_mon_msg_SOURCES_DIST) \
 	$(am__ceph_test_mon_workloadgen_SOURCES_DIST) \
@@ -5747,7 +5782,7 @@ DIST_SOURCES = $(am__libcls_log_client_a_SOURCES_DIST) \
 	$(am__unittest_libcephfs_config_SOURCES_DIST) \
 	$(am__unittest_librados_SOURCES_DIST) \
 	$(am__unittest_librados_config_SOURCES_DIST) \
-	$(unittest_librbd_SOURCES) $(unittest_log_SOURCES) \
+	$(am__unittest_librbd_SOURCES_DIST) $(unittest_log_SOURCES) \
 	$(unittest_lru_SOURCES) \
 	$(am__unittest_mds_authcap_SOURCES_DIST) \
 	$(unittest_mds_types_SOURCES) $(unittest_mime_SOURCES) \
@@ -6037,8 +6072,9 @@ am__noinst_HEADERS_DIST = arch/intel.h arch/arm.h arch/probe.h \
 	include/rados/buffer.h include/radosstriper/libradosstriper.h \
 	include/radosstriper/libradosstriper.hpp \
 	include/rbd/features.h include/rbd/librbd.h \
-	include/rbd/librbd.hpp include/util.h include/stat.h \
-	include/on_exit.h include/memory.h include/rados/memory.h \
+	include/rbd/librbd.hpp include/rbd/object_map_types.h \
+	include/util.h include/stat.h include/on_exit.h \
+	include/memory.h include/rados/memory.h \
 	include/hash_namespace.h include/unordered_set.h \
 	include/unordered_map.h librados/snap_set_diff.h \
 	librados/AioCompletionImpl.h librados/IoCtxImpl.h \
@@ -6121,8 +6157,8 @@ am__noinst_HEADERS_DIST = arch/intel.h arch/arm.h arch/probe.h \
 	test/objectstore/workload_generator.h test/kv_store_bench.h \
 	test/librados/test.h test/librados/TestCase.h \
 	test/libradosstriper/TestCase.h test/librbd/test_fixture.h \
-	test/ObjectMap/KeyValueDBMemory.h test/omap_bench.h \
-	test/osdc/FakeWriteback.h test/osd/Object.h \
+	test/librbd/test_support.h test/ObjectMap/KeyValueDBMemory.h \
+	test/omap_bench.h test/osdc/FakeWriteback.h test/osd/Object.h \
 	test/osd/RadosModel.h test/osd/TestOpStat.h \
 	test/system/cross_process_sem.h \
 	test/system/st_rados_create_pool.h \
@@ -6375,7 +6411,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_67)
+	$(am__append_6) $(am__append_68) $(am__append_71)
 AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
 AR = @AR@
 ARM_FLAGS = @ARM_FLAGS@
@@ -6563,12 +6599,12 @@ top_build_prefix = @top_build_prefix@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 AUTOMAKE_OPTIONS = gnu subdir-objects
-SUBDIRS = ocf java tracing $(am__append_194) $(am__append_195)
+SUBDIRS = ocf java tracing $(am__append_199) $(am__append_200)
 DIST_SUBDIRS = gmock ocf libs3 java tracing
-BUILT_SOURCES = $(am__append_215)
+BUILT_SOURCES = $(am__append_220)
 
 # extra bits
-EXTRA_DIST = $(am__append_20) \
+EXTRA_DIST = $(am__append_21) \
 	$(srcdir)/test/debian-jessie/Dockerfile.in \
 	$(srcdir)/test/debian-jessie/install-deps.sh \
 	$(srcdir)/test/debian-jessie/debian \
@@ -6589,7 +6625,7 @@ EXTRA_DIST = $(am__append_20) \
 	$(srcdir)/test/coverage.sh $(patsubst \
 	%,$(srcdir)/%,$(check_SCRIPTS)) \
 	$(srcdir)/test/container-make-check-ubuntu-14.04.sh \
-	$(am__append_196) $(srcdir)/$(shell_scripts:%=%.in) \
+	$(am__append_201) $(srcdir)/$(shell_scripts:%=%.in) \
 	$(srcdir)/verify-mds-journal.sh $(srcdir)/vstart.sh \
 	$(srcdir)/stop.sh ceph-run $(srcdir)/ceph-osd-prestart.sh \
 	$(srcdir)/ceph_common.sh $(srcdir)/init-radosgw \
@@ -6650,9 +6686,9 @@ noinst_HEADERS = arch/intel.h arch/arm.h arch/probe.h \
 	crush/CrushWrapper.h crush/CrushWrapper.i crush/builder.h \
 	crush/crush.h crush/grammar.h crush/hash.h \
 	crush/crush_ln_table.h crush/mapper.h crush/sample.txt \
-	crush/types.h $(am__append_22) $(am__append_26) \
-	$(am__append_32) $(am__append_34) $(am__append_36) \
-	$(am__append_38) $(am__append_42) $(am__append_46) \
+	crush/types.h $(am__append_23) $(am__append_27) \
+	$(am__append_33) $(am__append_35) $(am__append_37) \
+	$(am__append_39) $(am__append_43) $(am__append_47) \
 	erasure-code/jerasure/gf-complete/include/gf_complete.h \
 	erasure-code/jerasure/gf-complete/include/gf_general.h \
 	erasure-code/jerasure/gf-complete/include/gf_int.h \
@@ -6683,11 +6719,11 @@ noinst_HEADERS = arch/intel.h arch/arm.h arch/probe.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 \
-	$(am__append_57) erasure-code/ErasureCode.h \
+	$(am__append_58) erasure-code/ErasureCode.h \
 	erasure-code/ErasureCodeInterface.h \
 	erasure-code/ErasureCodePlugin.h osdc/Filer.h osdc/Journaler.h \
 	osdc/ObjectCacher.h osdc/Objecter.h osdc/Striper.h \
-	osdc/WritebackHandler.h $(am__append_61) $(am__append_63) \
+	osdc/WritebackHandler.h $(am__append_62) $(am__append_64) \
 	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 \
@@ -6735,7 +6771,7 @@ noinst_HEADERS = arch/intel.h arch/arm.h arch/probe.h \
 	common/linux_version.h common/module.h common/Continuation.h \
 	common/Readahead.h common/Cycles.h common/Initialize.h \
 	common/ContextCompletion.h common/bit_vector.hpp \
-	$(am__append_75) common/secret.h msg/Connection.h \
+	$(am__append_79) common/secret.h msg/Connection.h \
 	msg/Dispatcher.h msg/Message.h msg/Messenger.h \
 	msg/SimplePolicyMessenger.h msg/msg_types.h \
 	msg/simple/Accepter.h msg/simple/DispatchQueue.h \
@@ -6743,7 +6779,7 @@ noinst_HEADERS = arch/intel.h arch/arm.h arch/probe.h \
 	msg/simple/SimpleMessenger.h msg/async/AsyncConnection.h \
 	msg/async/AsyncMessenger.h msg/async/Event.h \
 	msg/async/EventEpoll.h msg/async/EventSelect.h \
-	msg/async/net_handler.h $(am__append_84) messages/MAuth.h \
+	msg/async/net_handler.h $(am__append_88) messages/MAuth.h \
 	messages/MAuthReply.h messages/MCacheExpire.h \
 	messages/MClientCaps.h messages/MClientCapRelease.h \
 	messages/MClientLease.h messages/MClientReconnect.h \
@@ -6823,13 +6859,14 @@ noinst_HEADERS = arch/intel.h arch/arm.h arch/probe.h \
 	include/rados/buffer.h include/radosstriper/libradosstriper.h \
 	include/radosstriper/libradosstriper.hpp \
 	include/rbd/features.h include/rbd/librbd.h \
-	include/rbd/librbd.hpp include/util.h include/stat.h \
-	include/on_exit.h include/memory.h include/rados/memory.h \
+	include/rbd/librbd.hpp include/rbd/object_map_types.h \
+	include/util.h include/stat.h include/on_exit.h \
+	include/memory.h include/rados/memory.h \
 	include/hash_namespace.h include/unordered_set.h \
-	include/unordered_map.h $(am__append_91) $(am__append_94) \
-	$(am__append_99) $(am__append_105) $(am__append_108) \
-	$(am__append_111) $(am__append_113) $(am__append_117) \
-	$(am__append_137) $(am__append_153) test/bench/backend.h \
+	include/unordered_map.h $(am__append_95) $(am__append_98) \
+	$(am__append_103) $(am__append_109) $(am__append_112) \
+	$(am__append_115) $(am__append_117) $(am__append_121) \
+	$(am__append_141) $(am__append_157) 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 \
@@ -6842,8 +6879,8 @@ noinst_HEADERS = arch/intel.h arch/arm.h arch/probe.h \
 	test/objectstore/workload_generator.h test/kv_store_bench.h \
 	test/librados/test.h test/librados/TestCase.h \
 	test/libradosstriper/TestCase.h test/librbd/test_fixture.h \
-	test/ObjectMap/KeyValueDBMemory.h test/omap_bench.h \
-	test/osdc/FakeWriteback.h test/osd/Object.h \
+	test/librbd/test_support.h test/ObjectMap/KeyValueDBMemory.h \
+	test/omap_bench.h test/osdc/FakeWriteback.h test/osd/Object.h \
 	test/osd/RadosModel.h test/osd/TestOpStat.h \
 	test/system/cross_process_sem.h \
 	test/system/st_rados_create_pool.h \
@@ -6861,41 +6898,41 @@ noinst_HEADERS = arch/intel.h arch/arm.h arch/probe.h \
 	bash_completion/ceph bash_completion/rados bash_completion/rbd \
 	bash_completion/radosgw-admin mount/canonicalize.c \
 	mount/mtab.c objclass/objclass.h
-bin_SCRIPTS = $(am__append_19) $(am__append_203) $(am__append_212) \
-	$(am__append_220)
+bin_SCRIPTS = $(am__append_20) $(am__append_208) $(am__append_217) \
+	$(am__append_225)
 sbin_SCRIPTS = 
-su_sbin_SCRIPTS = $(am__append_217)
+su_sbin_SCRIPTS = $(am__append_222)
 dist_bin_SCRIPTS = 
-lib_LTLIBRARIES = $(am__append_90) $(am__append_93) $(am__append_98) \
-	$(am__append_210) $(am__append_211)
+lib_LTLIBRARIES = $(am__append_94) $(am__append_97) $(am__append_102) \
+	$(am__append_215) $(am__append_216)
 noinst_LTLIBRARIES = libarch.la libauth.la libcrush.la libmon_types.la \
-	$(am__append_21) $(am__append_25) libos_types.la \
-	$(am__append_31) $(am__append_33) $(am__append_35) \
-	libosd_types.la $(am__append_45) liberasure_code.la libosdc.la \
-	$(am__append_60) $(am__append_62) libglobal.la \
+	$(am__append_22) $(am__append_26) libos_types.la \
+	$(am__append_32) $(am__append_34) $(am__append_36) \
+	libosd_types.la $(am__append_46) liberasure_code.la libosdc.la \
+	$(am__append_61) $(am__append_63) libglobal.la \
 	libjson_spirit.la liblog.la libperfglue.la \
 	libcommon_internal.la libcommon_api.la libcommon_crc.la \
-	libcommon.la $(am__append_76) libmsg.la $(am__append_85) \
-	librbd_types.la $(am__append_95) $(am__append_101) \
-	$(am__append_106) $(am__append_112) $(am__append_146) \
-	$(am__append_156) $(am__append_160) $(am__append_181) \
-	$(am__append_205)
-noinst_LIBRARIES = $(am__append_37) $(am__append_107)
-radoslib_LTLIBRARIES = $(am__append_109) $(am__append_110)
+	libcommon.la $(am__append_80) libmsg.la $(am__append_89) \
+	librbd_types.la $(am__append_99) $(am__append_105) \
+	$(am__append_110) $(am__append_116) $(am__append_150) \
+	$(am__append_160) $(am__append_165) $(am__append_186) \
+	$(am__append_210)
+noinst_LIBRARIES = $(am__append_38) $(am__append_111)
+radoslib_LTLIBRARIES = $(am__append_113) $(am__append_114)
 
 # like bin_PROGRAMS, but these targets are only built for debug builds
-bin_DEBUGPROGRAMS = $(am__append_64) $(am__append_104) \
-	$(am__append_119) $(am__append_147) $(am__append_148) \
-	$(am__append_149) $(am__append_150) $(am__append_152) \
-	$(am__append_154) $(am__append_159) $(am__append_161) \
-	$(am__append_162) $(am__append_164) $(am__append_165) \
-	$(am__append_166) $(am__append_167) $(am__append_168) \
-	$(am__append_169) $(am__append_170) $(am__append_171) \
-	$(am__append_177) ceph_test_timers ceph_test_signal_handlers \
-	ceph_test_rewrite_latency ceph_test_crypto $(am__append_180) \
+bin_DEBUGPROGRAMS = $(am__append_65) $(am__append_108) \
+	$(am__append_123) $(am__append_151) $(am__append_152) \
+	$(am__append_153) $(am__append_154) $(am__append_156) \
+	$(am__append_158) $(am__append_164) $(am__append_166) \
+	$(am__append_167) $(am__append_169) $(am__append_170) \
+	$(am__append_171) $(am__append_172) $(am__append_173) \
+	$(am__append_174) $(am__append_175) $(am__append_176) \
+	$(am__append_182) ceph_test_timers ceph_test_signal_handlers \
+	ceph_test_rewrite_latency ceph_test_crypto $(am__append_185) \
 	ceph_bench_log ceph_test_objectcacher_stress \
 	ceph_test_cfuse_cache_invalidate ceph_test_get_blkdev_size \
-	$(am__append_184) $(am__append_186) $(am__append_187) \
+	$(am__append_189) $(am__append_191) $(am__append_192) \
 	ceph_psim
 
 # like sbin_SCRIPTS but can be used to install to e.g. /usr/sbin
@@ -6905,7 +6942,7 @@ ceph_sbindir = $(sbindir)
 su_sbindir = /sbin
 
 # tests scripts will be appended to this
-check_SCRIPTS = $(am__append_116) test/ceph_objectstore_tool.py \
+check_SCRIPTS = $(am__append_120) test/ceph_objectstore_tool.py \
 	test/test-ceph-helpers.sh test/cephtool-test-osd.sh \
 	test/cephtool-test-mon.sh test/cephtool-test-mds.sh \
 	unittest_bufferlist.sh test/encoding/check-generated.sh \
@@ -6914,7 +6951,7 @@ check_SCRIPTS = $(am__append_116) test/ceph_objectstore_tool.py \
 	test/mon/mkfs.sh test/osd/osd-scrub-repair.sh \
 	test/osd/osd-config.sh test/osd/osd-bench.sh \
 	test/osd/osd-copy-from.sh test/mon/mon-handle-forward.sh \
-	$(am__append_182) $(am__append_183) \
+	$(am__append_187) $(am__append_188) \
 	test/pybind/test_ceph_argparse.py
 
 ##################################
@@ -6939,7 +6976,8 @@ AM_COMMON_CFLAGS = \
 	-fno-strict-aliasing \
 	-fsigned-char
 
-AM_CFLAGS = $(AM_COMMON_CFLAGS) $(am__append_5) $(am__append_66)
+AM_CFLAGS = $(AM_COMMON_CFLAGS) $(am__append_5) $(am__append_67) \
+	$(am__append_70)
 AM_CPPFLAGS = $(AM_COMMON_CPPFLAGS)
 
 # note: this is position dependant, it affects the -l options that
@@ -6955,12 +6993,12 @@ AM_CCASFLAGS = -f elf64
 
 #####################
 EXTRALIBS = -luuid -lm $(am__append_7) $(am__append_8) $(am__append_9) \
-	$(am__append_18)
+	$(am__append_19)
 LIBGLOBAL = libglobal.la
 LIBCOMMON = libcommon.la
 LIBSECRET = libsecret.la
 LIBARCH = libarch.la
-LIBPERFGLUE = libperfglue.la $(am__append_13)
+LIBPERFGLUE = libperfglue.la $(am__append_13) $(am__append_14)
 LIBAUTH = libauth.la
 LIBMSG = libmsg.la
 LIBCRUSH = libcrush.la
@@ -6973,19 +7011,19 @@ LIBOS = libos.la $(am__append_10) $(am__append_11) $(am__append_12) \
 LIBOS_TYPES = libos_types.la
 
 # Libosd always needs osdc and os
-LIBOSD = libosd.la $(am__append_15) $(LIBOSDC) $(LIBOS) $(LIBPERFGLUE)
+LIBOSD = libosd.la $(am__append_16) $(LIBOSDC) $(LIBOS) $(LIBPERFGLUE)
 LIBOSD_TYPES = libosd_types.la
 LIBOSDC = libosdc.la
 
 # These have references to syms like ceph_using_tcmalloc(), glue libperfglue to them
-LIBMON = libmon.la $(am__append_14) $(LIBPERFGLUE)
+LIBMON = libmon.la $(am__append_15) $(LIBPERFGLUE)
 LIBMON_TYPES = libmon_types.la
-LIBMDS = libmds.la $(am__append_16) $(LIBPERFGLUE)
+LIBMDS = libmds.la $(am__append_17) $(LIBPERFGLUE)
 LIBCLIENT = libclient.la
 LIBCLIENT_FUSE = libclient_fuse.la
 LIBRADOS = librados.la
 LIBRADOSSTRIPER = libradosstriper.la
-LIBRGW = librgw.la $(am__append_17)
+LIBRGW = librgw.la $(am__append_18)
 LIBCIVETWEB = libcivetweb.la
 LIBRBD = librbd.la
 LIBRBD_TYPES = librbd_types.la
@@ -7005,16 +7043,16 @@ CEPH_GLOBAL = $(LIBGLOBAL) $(LIBCOMMON) $(PTHREAD_LIBS) -lm $(CRYPTO_LIBS) $(EXT
 # important; libmsg before libauth!
 LIBCOMMON_DEPS = libcommon_internal.la libcommon_crc.la \
 	$(LIBERASURE_CODE) $(LIBMSG) $(LIBAUTH) $(LIBCRUSH) \
-	$(LIBJSON_SPIRIT) $(LIBLOG) $(LIBARCH) $(am__append_74)
-LIBRADOS_DEPS = $(am__append_86) $(am__append_87)
-LIBRGW_DEPS = $(am__append_102)
+	$(LIBJSON_SPIRIT) $(LIBLOG) $(LIBARCH) $(am__append_78)
+LIBRADOS_DEPS = $(am__append_90) $(am__append_91)
+LIBRGW_DEPS = $(am__append_106)
 
 # This is used by the dencoder test
 
 # Do not use TCMALLOC with dencoder
-DENCODER_SOURCES = $(am__append_23) perfglue/disabled_heap_profiler.cc \
-	perfglue/disabled_stubs.cc $(am__append_100)
-DENCODER_DEPS = $(am__append_24)
+DENCODER_SOURCES = $(am__append_24) perfglue/disabled_heap_profiler.cc \
+	perfglue/disabled_stubs.cc $(am__append_104)
+DENCODER_DEPS = $(am__append_25)
 radoslibdir = $(libdir)/rados-classes
 libarch_la_SOURCES = \
 	arch/intel.c \
@@ -7117,13 +7155,13 @@ libos_types_la_CXXFLAGS = ${AM_CXXFLAGS}
 @ENABLE_SERVER_TRUE@	os/MemStore.cc os/KeyValueDB.cc \
 @ENABLE_SERVER_TRUE@	os/KeyValueStore.cc os/ObjectStore.cc \
 @ENABLE_SERVER_TRUE@	os/WBThrottle.cc os/KeyValueDB.cc \
- at ENABLE_SERVER_TRUE@	common/TrackedOp.cc $(am__append_27) \
- at ENABLE_SERVER_TRUE@	$(am__append_28) $(am__append_29) \
- at ENABLE_SERVER_TRUE@	$(am__append_39)
- at ENABLE_SERVER_TRUE@libos_la_CXXFLAGS = ${AM_CXXFLAGS} \
+ at ENABLE_SERVER_TRUE@	common/TrackedOp.cc $(am__append_28) \
+ at ENABLE_SERVER_TRUE@	$(am__append_29) $(am__append_30) \
 @ENABLE_SERVER_TRUE@	$(am__append_40)
- at ENABLE_SERVER_TRUE@libos_la_LIBADD = $(LIBOS_TYPES) $(am__append_30) \
+ at ENABLE_SERVER_TRUE@libos_la_CXXFLAGS = ${AM_CXXFLAGS} \
 @ENABLE_SERVER_TRUE@	$(am__append_41)
+ at ENABLE_SERVER_TRUE@libos_la_LIBADD = $(LIBOS_TYPES) $(am__append_31) \
+ at ENABLE_SERVER_TRUE@	$(am__append_42)
 @ENABLE_SERVER_TRUE@@WITH_DLIBROCKSDB_TRUE at libos_rocksdb_la_SOURCES = os/RocksDBStore.cc
 @ENABLE_SERVER_TRUE@@WITH_SLIBROCKSDB_TRUE at libos_rocksdb_la_SOURCES = os/RocksDBStore.cc
 @ENABLE_SERVER_TRUE@@WITH_DLIBROCKSDB_TRUE at libos_rocksdb_la_CXXFLAGS = ${AM_CXXFLAGS} ${LIBROCKSDB_CFLAGS} -std=gnu++11
@@ -7159,16 +7197,16 @@ libosd_types_la_CXXFLAGS = ${AM_CXXFLAGS}
 
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at libosd_la_CXXFLAGS =  \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	${AM_CXXFLAGS} \
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_43)
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_44)
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at libosd_la_LIBADD = $(LIBOSDC) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(LIBOS) $(LIBOSD_TYPES) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(LIBOS_TYPES) \
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_44)
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_45)
 erasure_codelibdir = $(pkglibdir)/erasure-code
 erasure_codelib_LTLIBRARIES = libec_jerasure_generic.la \
-	$(am__append_49) $(am__append_51) $(am__append_53) \
-	libec_jerasure.la libec_lrc.la libec_shec.la $(am__append_59) \
-	$(am__append_123)
+	$(am__append_50) $(am__append_52) $(am__append_54) \
+	libec_jerasure.la libec_lrc.la libec_shec.la $(am__append_60) \
+	$(am__append_127)
 jerasure_sources = \
   erasure-code/ErasureCode.cc \
   erasure-code/jerasure/jerasure/src/cauchy.c \
@@ -7201,7 +7239,7 @@ libec_jerasure_generic_la_CXXFLAGS = ${AM_CXXFLAGS} \
 
 libec_jerasure_generic_la_LIBADD = $(LIBCRUSH) $(PTHREAD_LIBS) $(EXTRALIBS)
 libec_jerasure_generic_la_LDFLAGS = ${AM_LDFLAGS} -version-info 2:0:0 \
-	$(am__append_47)
+	$(am__append_48)
 libec_jerasure_neon_la_SOURCES = ${jerasure_sources}                                       \
                                   erasure-code/jerasure/gf-complete/src/neon/gf_w4_neon.c  \
                                   erasure-code/jerasure/gf-complete/src/neon/gf_w8_neon.c  \
@@ -7221,7 +7259,7 @@ libec_jerasure_neon_la_CXXFLAGS = ${AM_CXXFLAGS} \
 
 libec_jerasure_neon_la_LIBADD = $(LIBCRUSH) $(PTHREAD_LIBS) $(EXTRALIBS)
 libec_jerasure_neon_la_LDFLAGS = ${AM_LDFLAGS} -version-info 2:0:0 \
-	$(am__append_48)
+	$(am__append_49)
 libec_jerasure_sse3_la_SOURCES = ${jerasure_sources}
 libec_jerasure_sse3_la_CFLAGS = ${AM_CFLAGS}  \
 	${INTEL_SSE_FLAGS} \
@@ -7241,7 +7279,7 @@ libec_jerasure_sse3_la_CXXFLAGS = ${AM_CXXFLAGS} \
 
 libec_jerasure_sse3_la_LIBADD = $(LIBCRUSH) $(PTHREAD_LIBS) $(EXTRALIBS)
 libec_jerasure_sse3_la_LDFLAGS = ${AM_LDFLAGS} -version-info 2:0:0 \
-	$(am__append_50)
+	$(am__append_51)
 libec_jerasure_sse4_la_SOURCES = ${jerasure_sources}
 libec_jerasure_sse4_la_CFLAGS = ${AM_CFLAGS}  \
 	${INTEL_SSE_FLAGS} \
@@ -7265,7 +7303,7 @@ libec_jerasure_sse4_la_CXXFLAGS = ${AM_CXXFLAGS} \
 
 libec_jerasure_sse4_la_LIBADD = $(LIBCRUSH) $(PTHREAD_LIBS) $(EXTRALIBS)
 libec_jerasure_sse4_la_LDFLAGS = ${AM_LDFLAGS} -version-info 2:0:0 \
-	$(am__append_52)
+	$(am__append_53)
 libec_jerasure_la_SOURCES = \
 	erasure-code/jerasure/ErasureCodePluginSelectJerasure.cc
 
@@ -7273,7 +7311,7 @@ libec_jerasure_la_CFLAGS = ${AM_CFLAGS}
 libec_jerasure_la_CXXFLAGS = ${AM_CXXFLAGS}
 libec_jerasure_la_LIBADD = $(LIBCRUSH) $(PTHREAD_LIBS) $(EXTRALIBS)
 libec_jerasure_la_LDFLAGS = ${AM_LDFLAGS} -version-info 2:0:0 \
-	$(am__append_54)
+	$(am__append_55)
 lrc_sources = \
   erasure-code/ErasureCode.cc \
   erasure-code/lrc/ErasureCodePluginLrc.cc \
@@ -7284,7 +7322,7 @@ libec_lrc_la_CFLAGS = ${AM_CFLAGS}
 libec_lrc_la_CXXFLAGS = ${AM_CXXFLAGS}
 libec_lrc_la_LIBADD = $(LIBCRUSH) $(PTHREAD_LIBS) $(LIBJSON_SPIRIT)
 libec_lrc_la_LDFLAGS = ${AM_LDFLAGS} -version-info 1:0:0 \
-	$(am__append_55)
+	$(am__append_56)
 libec_shec_la_SOURCES = \
 	erasure-code/ErasureCode.cc \
 	erasure-code/shec/ErasureCodePluginShec.cc \
@@ -7325,7 +7363,7 @@ libec_shec_la_LIBADD = $(LIBCRUSH) $(PTHREAD_LIBS) $(EXTRALIBS)
 #libec_shec_la_LIBADD = $(PTHREAD_LIBS) $(EXTRALIBS)
 #libec_shec_la_LDFLAGS = ${AM_LDFLAGS} -version-info 1:0:0 -export-symbols-regex '.*__erasure_code_.*'
 libec_shec_la_LDFLAGS = ${AM_LDFLAGS} -version-info 1:0:0 \
-	$(am__append_56)
+	$(am__append_57)
 @WITH_BETTER_YASM_ELF64_TRUE at isa_sources = \
 @WITH_BETTER_YASM_ELF64_TRUE@	erasure-code/ErasureCode.cc \
 @WITH_BETTER_YASM_ELF64_TRUE@	erasure-code/isa/isa-l/erasure_code/ec_base.c \
@@ -7363,7 +7401,7 @@ libec_shec_la_LDFLAGS = ${AM_LDFLAGS} -version-info 1:0:0 \
 @WITH_BETTER_YASM_ELF64_TRUE at libec_isa_la_LIBADD = $(LIBCRUSH) $(PTHREAD_LIBS) $(EXTRALIBS)
 @WITH_BETTER_YASM_ELF64_TRUE at libec_isa_la_LDFLAGS = ${AM_LDFLAGS} \
 @WITH_BETTER_YASM_ELF64_TRUE@	-version-info 2:10:0 \
- at WITH_BETTER_YASM_ELF64_TRUE@	$(am__append_58)
+ at WITH_BETTER_YASM_ELF64_TRUE@	$(am__append_59)
 @WITH_BETTER_YASM_ELF64_TRUE at libec_isa_la_LIBTOOLFLAGS = --tag=CC
 liberasure_code_la_SOURCES = \
 	erasure-code/ErasureCodePlugin.cc
@@ -7406,8 +7444,9 @@ liblog_la_SOURCES = \
 	log/Log.cc \
 	log/SubsystemMap.cc
 
-libperfglue_la_SOURCES = $(am__append_65) $(am__append_68) \
-	$(am__append_69) $(am__append_70)
+libperfglue_la_SOURCES = $(am__append_66) $(am__append_69) \
+	$(am__append_72) $(am__append_73) $(am__append_74)
+ at WITH_TCMALLOC_FALSE@@WITH_TCMALLOC_MINIMAL_TRUE at libperfglue_la_LIBADD = -ltcmalloc_minimal
 @WITH_TCMALLOC_TRUE at libperfglue_la_LIBADD = -ltcmalloc
 
 # these should go out of libcommon_internal
@@ -7437,7 +7476,7 @@ libcommon_internal_la_SOURCES = ceph_ver.c common/DecayCounter.cc \
 	common/ceph_frag.cc common/addr_parsing.c common/hobject.cc \
 	common/bloom_filter.cc common/linux_version.c common/module.c \
 	common/Readahead.cc common/Cycles.cc \
-	common/ContextCompletion.cc $(am__append_71) $(am__append_72) \
+	common/ContextCompletion.cc $(am__append_75) $(am__append_76) \
 	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 mds/flock.cc
@@ -7449,7 +7488,7 @@ libcommon_api_la_SOURCES = \
 # 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_73)
+	$(am__append_77)
 @WITH_GOOD_YASM_ELF64_TRUE at libcommon_crc_la_LIBTOOLFLAGS = --tag=CC
 libcommon_la_SOURCES = 
 libcommon_la_LIBADD = $(LIBCOMMON_DEPS) libcommon_api.la
@@ -7461,9 +7500,9 @@ libmsg_la_SOURCES = msg/Message.cc msg/Messenger.cc msg/msg_types.cc \
 	msg/simple/SimpleMessenger.cc msg/async/AsyncConnection.cc \
 	msg/async/AsyncMessenger.cc msg/async/Event.cc \
 	msg/async/net_handler.cc msg/async/EventSelect.cc \
-	$(am__append_77) $(am__append_78) $(am__append_79) \
-	$(am__append_80) $(am__append_81) $(am__append_82) \
-	$(am__append_83)
+	$(am__append_81) $(am__append_82) $(am__append_83) \
+	$(am__append_84) $(am__append_85) $(am__append_86) \
+	$(am__append_87)
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at rados_includedir = $(includedir)/rados
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at rados_include_DATA = \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	$(srcdir)/include/rados/librados.h \
@@ -7506,12 +7545,12 @@ libmsg_la_SOURCES = msg/Message.cc msg/Messenger.cc msg/msg_types.cc \
 # We need this to avoid basename conflicts with the librados build tests in test/Makefile.am
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at librados_la_CXXFLAGS =  \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	${AM_CXXFLAGS} \
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	$(am__append_88)
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	$(am__append_92)
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at librados_la_LIBADD = $(LIBRADOS_DEPS) $(PTHREAD_LIBS) $(CRYPTO_LIBS) $(EXTRALIBS)
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at librados_la_LDFLAGS =  \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	${AM_LDFLAGS} \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	-version-info 2:0:0 \
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	$(am__append_89)
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	$(am__append_93)
 @ENABLE_CLIENT_TRUE@@WITH_RADOSSTRIPER_TRUE@@WITH_RADOS_TRUE at libradosstriper_la_SOURCES = \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSSTRIPER_TRUE@@WITH_RADOS_TRUE@	libradosstriper/libradosstriper.cc \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSSTRIPER_TRUE@@WITH_RADOS_TRUE@	libradosstriper/RadosStriperImpl.cc \
@@ -7525,7 +7564,7 @@ libmsg_la_SOURCES = msg/Message.cc msg/Messenger.cc msg/msg_types.cc \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSSTRIPER_TRUE@@WITH_RADOS_TRUE at libradosstriper_la_LDFLAGS = ${AM_LDFLAGS} \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSSTRIPER_TRUE@@WITH_RADOS_TRUE@	-version-info \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSSTRIPER_TRUE@@WITH_RADOS_TRUE@	1:0:0 \
- at ENABLE_CLIENT_TRUE@@WITH_RADOSSTRIPER_TRUE@@WITH_RADOS_TRUE@	$(am__append_92)
+ at ENABLE_CLIENT_TRUE@@WITH_RADOSSTRIPER_TRUE@@WITH_RADOS_TRUE@	$(am__append_96)
 librbd_types_la_SOURCES = \
 	librbd/WatchNotifyTypes.cc
 
@@ -7561,11 +7600,11 @@ librbd_types_la_SOURCES = \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	libcls_lock_client.la \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(PTHREAD_LIBS) \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(EXTRALIBS) \
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(am__append_96)
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(am__append_100)
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at librbd_la_LDFLAGS = ${AM_LDFLAGS} \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	-version-info \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	1:0:0 \
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(am__append_97)
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(am__append_101)
 @ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at librbd_la_CXXFLAGS = -fvisibility=hidden -fvisibility-inlines-hidden
 @ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE at librgw_la_SOURCES = \
 @ENABLE_CLIENT_TRUE@@WITH_RADOSGW_TRUE@@WITH_RADOS_TRUE@	rgw/librgw.cc \
@@ -7761,7 +7800,7 @@ librbd_types_la_SOURCES = \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(LIBOSD) $(LIBCOMMON) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(BOOST_PROGRAM_OPTIONS_LIBS) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(CEPH_GLOBAL) \
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_118)
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_122)
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at ceph_erasure_code_non_regression_SOURCES = \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	test/erasure-code/ceph_erasure_code_non_regression.cc
 
@@ -7769,7 +7808,7 @@ librbd_types_la_SOURCES = \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(LIBOSD) $(LIBCOMMON) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(BOOST_PROGRAM_OPTIONS_LIBS) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(CEPH_GLOBAL) \
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_120)
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_124)
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at ceph_erasure_code_SOURCES = \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	test/erasure-code/ceph_erasure_code.cc
 
@@ -7777,7 +7816,7 @@ librbd_types_la_SOURCES = \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(LIBOSD) $(LIBCOMMON) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(BOOST_PROGRAM_OPTIONS_LIBS) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(CEPH_GLOBAL) \
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_122)
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_126)
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at libec_example_la_SOURCES = test/erasure-code/ErasureCodePluginExample.cc
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at libec_example_la_CFLAGS = ${AM_CFLAGS}
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at libec_example_la_CXXFLAGS = ${AM_CXXFLAGS}
@@ -7837,7 +7876,7 @@ librbd_types_la_SOURCES = \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(LIBOSD) $(LIBCOMMON) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(UNITTEST_LDADD) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(CEPH_GLOBAL) \
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_124)
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_128)
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at unittest_erasure_code_SOURCES = \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	erasure-code/ErasureCode.cc \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	test/erasure-code/TestErasureCode.cc
@@ -7860,7 +7899,7 @@ librbd_types_la_SOURCES = \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(LIBOSD) $(LIBCOMMON) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(UNITTEST_LDADD) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(CEPH_GLOBAL) \
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_126)
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_130)
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at unittest_erasure_code_plugin_jerasure_SOURCES = \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	test/erasure-code/TestErasureCodePluginJerasure.cc
 
@@ -7869,7 +7908,7 @@ librbd_types_la_SOURCES = \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(LIBOSD) $(LIBCOMMON) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(UNITTEST_LDADD) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(CEPH_GLOBAL) \
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_127)
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_131)
 @ENABLE_SERVER_TRUE@@WITH_BETTER_YASM_ELF64_TRUE@@WITH_OSD_TRUE at unittest_erasure_code_isa_SOURCES = \
 @ENABLE_SERVER_TRUE@@WITH_BETTER_YASM_ELF64_TRUE@@WITH_OSD_TRUE@	erasure-code/ErasureCode.cc \
 @ENABLE_SERVER_TRUE@@WITH_BETTER_YASM_ELF64_TRUE@@WITH_OSD_TRUE@	test/erasure-code/TestErasureCodeIsa.cc
@@ -7881,7 +7920,7 @@ librbd_types_la_SOURCES = \
 @ENABLE_SERVER_TRUE@@WITH_BETTER_YASM_ELF64_TRUE@@WITH_OSD_TRUE@	$(CEPH_GLOBAL) \
 @ENABLE_SERVER_TRUE@@WITH_BETTER_YASM_ELF64_TRUE@@WITH_OSD_TRUE@	.libs/libec_isa.la \
 @ENABLE_SERVER_TRUE@@WITH_BETTER_YASM_ELF64_TRUE@@WITH_OSD_TRUE@	$(LIBERASURE_CODE) \
- at ENABLE_SERVER_TRUE@@WITH_BETTER_YASM_ELF64_TRUE@@WITH_OSD_TRUE@	$(am__append_128)
+ at ENABLE_SERVER_TRUE@@WITH_BETTER_YASM_ELF64_TRUE@@WITH_OSD_TRUE@	$(am__append_132)
 @ENABLE_SERVER_TRUE@@WITH_BETTER_YASM_ELF64_TRUE@@WITH_OSD_TRUE at unittest_erasure_code_plugin_isa_SOURCES = \
 @ENABLE_SERVER_TRUE@@WITH_BETTER_YASM_ELF64_TRUE@@WITH_OSD_TRUE@	erasure-code/ErasureCode.cc \
 @ENABLE_SERVER_TRUE@@WITH_BETTER_YASM_ELF64_TRUE@@WITH_OSD_TRUE@	test/erasure-code/TestErasureCodePluginIsa.cc
@@ -7893,7 +7932,7 @@ librbd_types_la_SOURCES = \
 @ENABLE_SERVER_TRUE@@WITH_BETTER_YASM_ELF64_TRUE@@WITH_OSD_TRUE@	$(CEPH_GLOBAL) \
 @ENABLE_SERVER_TRUE@@WITH_BETTER_YASM_ELF64_TRUE@@WITH_OSD_TRUE@	.libs/libec_isa.la \
 @ENABLE_SERVER_TRUE@@WITH_BETTER_YASM_ELF64_TRUE@@WITH_OSD_TRUE@	$(LIBERASURE_CODE) \
- at ENABLE_SERVER_TRUE@@WITH_BETTER_YASM_ELF64_TRUE@@WITH_OSD_TRUE@	$(am__append_130)
+ at ENABLE_SERVER_TRUE@@WITH_BETTER_YASM_ELF64_TRUE@@WITH_OSD_TRUE@	$(am__append_134)
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at unittest_erasure_code_lrc_SOURCES = \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	test/erasure-code/TestErasureCodeLrc.cc \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	${lrc_sources}
@@ -7903,7 +7942,7 @@ librbd_types_la_SOURCES = \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(LIBOSD) $(LIBCOMMON) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(UNITTEST_LDADD) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(CEPH_GLOBAL) \
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_131)
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_135)
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at unittest_erasure_code_plugin_lrc_SOURCES = \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	test/erasure-code/TestErasureCodePluginLrc.cc
 
@@ -7912,7 +7951,7 @@ librbd_types_la_SOURCES = \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(LIBOSD) $(LIBCOMMON) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(UNITTEST_LDADD) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(CEPH_GLOBAL) \
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_133)
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_137)
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at unittest_erasure_code_shec_SOURCES = \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	test/erasure-code/TestErasureCodeShec.cc \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	${libec_shec_la_SOURCES}
@@ -7923,7 +7962,7 @@ librbd_types_la_SOURCES = \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(LIBOSD) $(LIBCOMMON) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(UNITTEST_LDADD) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(CEPH_GLOBAL) \
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_134)
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_138)
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at unittest_erasure_code_shec_all_SOURCES = \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	test/erasure-code/TestErasureCodeShec_all.cc \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	${libec_shec_la_SOURCES}
@@ -7934,7 +7973,7 @@ librbd_types_la_SOURCES = \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(LIBOSD) $(LIBCOMMON) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(UNITTEST_LDADD) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(CEPH_GLOBAL) \
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_135)
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_139)
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at unittest_erasure_code_shec_thread_SOURCES = \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	test/erasure-code/TestErasureCodeShec_thread.cc \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	${libec_shec_la_SOURCES}
@@ -7945,7 +7984,7 @@ librbd_types_la_SOURCES = \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(LIBOSD) $(LIBCOMMON) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(UNITTEST_LDADD) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(CEPH_GLOBAL) \
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_136)
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_140)
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at unittest_erasure_code_example_SOURCES = \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	erasure-code/ErasureCode.cc \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	test/erasure-code/TestErasureCodeExample.cc
@@ -7963,7 +8002,7 @@ librbd_types_la_SOURCES = \
 @ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@	$(CEPH_GLOBAL) \
 @ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@	$(PTHREAD_LIBS) \
 @ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@	$(EXTRALIBS) \
- at ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@	$(am__append_138)
+ at ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@	$(am__append_142)
 @ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE at simple_client_SOURCES = \
 @ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@	test/messenger/simple_client.cc \
 @ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@	test/messenger/simple_dispatcher.cc
@@ -7975,7 +8014,7 @@ librbd_types_la_SOURCES = \
 @ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@	$(CEPH_GLOBAL) \
 @ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@	$(PTHREAD_LIBS) \
 @ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@	$(EXTRALIBS) \
- at ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@	$(am__append_139)
+ at ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@	$(am__append_143)
 @ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE at xio_server_SOURCES = \
 @ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@	test/messenger/xio_server.cc \
 @ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@	test/messenger/xio_dispatcher.cc
@@ -7987,7 +8026,7 @@ librbd_types_la_SOURCES = \
 @ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@	$(LIBCOMMON) \
 @ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@	$(PTHREAD_LIBS) \
 @ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@	$(EXTRALIBS) \
- at ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@	$(am__append_141)
+ at ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@	$(am__append_145)
 @ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE at xio_client_SOURCES = \
 @ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@	test/messenger/xio_client.cc \
 @ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@	test/messenger/xio_dispatcher.cc
@@ -7999,7 +8038,7 @@ librbd_types_la_SOURCES = \
 @ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@	$(LIBCOMMON) \
 @ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@	$(PTHREAD_LIBS) \
 @ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@	$(EXTRALIBS) \
- at ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@	$(am__append_142)
+ at ENABLE_SERVER_TRUE@@ENABLE_XIO_TRUE@	$(am__append_146)
 
 # This should use LIBMDS_TYPES once it exists
 @ENABLE_CLIENT_TRUE at ceph_dencoder_SOURCES = \
@@ -8017,9 +8056,9 @@ librbd_types_la_SOURCES = \
 
 # These should always use explicit _CFLAGS/_CXXFLAGS so avoid basename conflicts
 @ENABLE_CLIENT_TRUE at ceph_dencoder_CFLAGS = ${AM_CFLAGS} \
- at ENABLE_CLIENT_TRUE@	$(am__append_143)
+ at ENABLE_CLIENT_TRUE@	$(am__append_147)
 @ENABLE_CLIENT_TRUE at ceph_dencoder_CXXFLAGS = ${AM_CXXFLAGS} \
- at ENABLE_CLIENT_TRUE@	$(am__append_144)
+ at ENABLE_CLIENT_TRUE@	$(am__append_148)
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE at libradostest_la_SOURCES = \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	test/librados/test.cc \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@	test/librados/TestCase.cc
@@ -8220,14 +8259,17 @@ librbd_types_la_SOURCES = \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at unittest_rbd_replay_CXXFLAGS = $(UNITTEST_CXXFLAGS)
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at librbd_test_la_SOURCES = \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	test/librbd/test_fixture.cc \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	test/librbd/test_support.cc \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	test/librbd/test_librbd.cc \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	test/librbd/test_ImageWatcher.cc \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	test/librbd/test_internal.cc \
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	test/librbd/test_main.cc
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	test/librbd/test_ObjectMap.cc
 
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at librbd_test_la_CXXFLAGS = $(UNITTEST_CXXFLAGS)
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at unittest_librbd_SOURCES = 
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at nodist_EXTRA_unittest_librbd_SOURCES = dummy.cc
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at unittest_librbd_SOURCES = \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@        test/librbd/test_main.cc
+
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at unittest_librbd_CXXFLAGS = $(UNITTEST_CXXFLAGS) -DTEST_LIBRBD_INTERNALS
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at unittest_librbd_LDADD = librbd_test.la \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	librbd_api.la \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	librbd_internal.la \
@@ -8240,9 +8282,11 @@ librbd_types_la_SOURCES = \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(UNITTEST_LDADD) \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(CEPH_GLOBAL) \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(RADOS_TEST_LDADD) \
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(am__append_157)
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at ceph_test_librbd_SOURCES = 
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at nodist_EXTRA_ceph_test_librbd_SOURCES = dummy.cc
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(am__append_161)
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at ceph_test_librbd_SOURCES = \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@        test/librbd/test_main.cc
+
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at ceph_test_librbd_CXXFLAGS = $(UNITTEST_CXXFLAGS) -DTEST_LIBRBD_INTERNALS
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at ceph_test_librbd_LDADD = librbd_test.la \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	librbd_api.la \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	librbd_internal.la \
@@ -8254,16 +8298,26 @@ librbd_types_la_SOURCES = \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(UNITTEST_LDADD) \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(CEPH_GLOBAL) \
 @ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(RADOS_TEST_LDADD) \
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(am__append_158)
- at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at ceph_test_librbd_CXXFLAGS = $(UNITTEST_CXXFLAGS)
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(am__append_162)
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at ceph_test_librbd_api_SOURCES = \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	test/librbd/test_support.cc \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	test/librbd/test_librbd.cc \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	test/librbd/test_main.cc
 
-# Force use of C++ linker with dummy.cc - LIBKRBD is a C++ library
- at ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at ceph_test_librbd_fsx_SOURCES = test/librbd/fsx.c common/dummy.cc
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at ceph_test_librbd_api_CXXFLAGS = $(UNITTEST_CXXFLAGS)
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at ceph_test_librbd_api_LDADD =  \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(LIBRBD) \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(LIBRADOS) \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(UNITTEST_LDADD) \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(CEPH_GLOBAL) \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(RADOS_TEST_LDADD) \
+ at ENABLE_CLIENT_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(am__append_163)
+ at ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at ceph_test_librbd_fsx_SOURCES = test/librbd/fsx.cc
 @ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at ceph_test_librbd_fsx_LDADD = \
 @ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(LIBKRBD) $(LIBRBD) $(LIBRADOS) \
 @ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE@	$(CRYPTO_LIBS) $(PTHREAD_LIBS) -luuid
 
- at ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at ceph_test_librbd_fsx_CFLAGS = ${AM_CFLAGS}
+ at ENABLE_CLIENT_TRUE@@LINUX_TRUE@@WITH_RADOS_TRUE@@WITH_RBD_TRUE at ceph_test_librbd_fsx_CXXFLAGS = $(UNITTEST_CXXFLAGS)
 @ENABLE_CLIENT_TRUE@@WITH_RADOSSTRIPER_TRUE@@WITH_RADOS_TRUE at libradosstripertest_la_SOURCES = test/libradosstriper/TestCase.cc
 @ENABLE_CLIENT_TRUE@@WITH_RADOSSTRIPER_TRUE@@WITH_RADOS_TRUE at libradosstripertest_la_LIBADD = $(RADOS_TEST_LDADD)
 @ENABLE_CLIENT_TRUE@@WITH_RADOSSTRIPER_TRUE@@WITH_RADOS_TRUE at libradosstripertest_la_CXXFLAGS = $(UNITTEST_CXXFLAGS)
@@ -8512,13 +8566,13 @@ librbd_types_la_SOURCES = \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at unittest_osdscrub_LDADD =  \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(LIBOSD) $(UNITTEST_LDADD) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(CEPH_GLOBAL) \
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_175)
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_180)
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at unittest_pglog_SOURCES = test/osd/TestPGLog.cc
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at unittest_pglog_CXXFLAGS = $(UNITTEST_CXXFLAGS)
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at unittest_pglog_LDADD = $(LIBOSD) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(UNITTEST_LDADD) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(CEPH_GLOBAL) \
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_176)
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_181)
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at unittest_hitset_SOURCES = test/osd/hitset.cc
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at unittest_hitset_CXXFLAGS = $(UNITTEST_CXXFLAGS)
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE at unittest_hitset_LDADD = $(LIBOSD) $(UNITTEST_LDADD) $(CEPH_GLOBAL)
@@ -8777,7 +8831,7 @@ ceph_test_get_blkdev_size_LDADD = $(LIBCOMMON)
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(CEPH_GLOBAL) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(BOOST_PROGRAM_OPTIONS_LIBS) \
 @ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(LIBRADOS) \
- at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_188)
+ at ENABLE_SERVER_TRUE@@WITH_OSD_TRUE@	$(am__append_193)
 @ENABLE_CLIENT_TRUE@@ENABLE_SERVER_TRUE@@WITH_MDS_TRUE@@WITH_RADOS_TRUE at cephfs_journal_tool_SOURCES = \
 @ENABLE_CLIENT_TRUE@@ENABLE_SERVER_TRUE@@WITH_MDS_TRUE@@WITH_RADOS_TRUE@	tools/cephfs/cephfs-journal-tool.cc \
 @ENABLE_CLIENT_TRUE@@ENABLE_SERVER_TRUE@@WITH_MDS_TRUE@@WITH_RADOS_TRUE@	tools/cephfs/JournalTool.cc \
@@ -8807,7 +8861,7 @@ ceph_psim_LDADD = $(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_192) $(am__append_193)
+ at WITH_REST_BENCH_TRUE@	$(am__append_197) $(am__append_198)
 @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)
@@ -8827,7 +8881,7 @@ editpaths = sed \
 	-e 's|@@GCOV_PREFIX_STRIP[@][@]|$(GCOV_PREFIX_STRIP)|g'
 
 shell_scripts = ceph-debugpack ceph-post-file ceph-crush-location \
-	$(am__append_214)
+	$(am__append_219)
 doc_DATA = $(srcdir)/sample.ceph.conf sample.fetch_config
 
 # various scripts
@@ -8850,12 +8904,12 @@ TESTS = \
 @WITH_LTTNG_TRUE at TESTS_ENVIRONMENT = LD_PRELOAD=liblttng-ust-fork.so; export LD_PRELOAD; echo "LD_PRELOAD=$${LD_PRELOAD}";
 
 # pybind
-python_PYTHON = $(am__append_197) $(am__append_200) $(am__append_204) \
-	$(am__append_209) $(am__append_213)
+python_PYTHON = $(am__append_202) $(am__append_205) $(am__append_209) \
+	$(am__append_214) $(am__append_218)
 @ENABLE_CLIENT_TRUE at bash_completiondir = $(sysconfdir)/bash_completion.d
 @ENABLE_CLIENT_TRUE at bash_completion_DATA =  \
 @ENABLE_CLIENT_TRUE@	$(srcdir)/bash_completion/ceph \
- at ENABLE_CLIENT_TRUE@	$(am__append_199) $(am__append_202)
+ at ENABLE_CLIENT_TRUE@	$(am__append_204) $(am__append_207)
 @ENABLE_CLIENT_TRUE at ceph_syn_SOURCES = ceph_syn.cc \
 @ENABLE_CLIENT_TRUE@	client/SyntheticClient.cc # uses g_conf.. \
 @ENABLE_CLIENT_TRUE@	needs cleanup
@@ -8891,7 +8945,7 @@ python_PYTHON = $(am__append_197) $(am__append_200) $(am__append_204) \
 @ENABLE_CEPHFS_JAVA_TRUE@@ENABLE_CLIENT_TRUE@@WITH_CEPHFS_TRUE@@WITH_RADOS_TRUE at libcephfs_jni_la_CPPFLAGS = $(JDK_CPPFLAGS) $(AM_CPPFLAGS)
 @ENABLE_CEPHFS_JAVA_TRUE@@ENABLE_CLIENT_TRUE@@WITH_CEPHFS_TRUE@@WITH_RADOS_TRUE at libcephfs_jni_la_LDFLAGS = ${AM_LDFLAGS} -version-info 1:0:0
 @ENABLE_SERVER_TRUE at ceph_sbin_SCRIPTS = ceph-create-keys \
- at ENABLE_SERVER_TRUE@	$(am__append_219)
+ at ENABLE_SERVER_TRUE@	$(am__append_224)
 @ENABLE_SERVER_TRUE at mount_ceph_SOURCES = mount/mount.ceph.c
 @ENABLE_SERVER_TRUE at mount_ceph_LDADD = $(LIBSECRET) $(LIBCOMMON)
 @ENABLE_SERVER_TRUE@@WITH_MON_TRUE at ceph_mon_SOURCES = ceph_mon.cc
@@ -10712,6 +10766,9 @@ test/librbd/$(DEPDIR)/$(am__dirstamp):
 test/librbd/librbd_test_la-test_fixture.lo:  \
 	test/librbd/$(am__dirstamp) \
 	test/librbd/$(DEPDIR)/$(am__dirstamp)
+test/librbd/librbd_test_la-test_support.lo:  \
+	test/librbd/$(am__dirstamp) \
+	test/librbd/$(DEPDIR)/$(am__dirstamp)
 test/librbd/librbd_test_la-test_librbd.lo:  \
 	test/librbd/$(am__dirstamp) \
 	test/librbd/$(DEPDIR)/$(am__dirstamp)
@@ -10721,7 +10778,8 @@ test/librbd/librbd_test_la-test_ImageWatcher.lo:  \
 test/librbd/librbd_test_la-test_internal.lo:  \
 	test/librbd/$(am__dirstamp) \
 	test/librbd/$(DEPDIR)/$(am__dirstamp)
-test/librbd/librbd_test_la-test_main.lo: test/librbd/$(am__dirstamp) \
+test/librbd/librbd_test_la-test_ObjectMap.lo:  \
+	test/librbd/$(am__dirstamp) \
 	test/librbd/$(DEPDIR)/$(am__dirstamp)
 
 librbd_test.la: $(librbd_test_la_OBJECTS) $(librbd_test_la_DEPENDENCIES) $(EXTRA_librbd_test_la_DEPENDENCIES) 
@@ -11590,19 +11648,33 @@ test/libcephfs/ceph_test_libcephfs-multiclient.$(OBJEXT):  \
 ceph_test_libcephfs$(EXEEXT): $(ceph_test_libcephfs_OBJECTS) $(ceph_test_libcephfs_DEPENDENCIES) $(EXTRA_ceph_test_libcephfs_DEPENDENCIES) 
 	@rm -f ceph_test_libcephfs$(EXEEXT)
 	$(AM_V_CXXLD)$(ceph_test_libcephfs_LINK) $(ceph_test_libcephfs_OBJECTS) $(ceph_test_libcephfs_LDADD) $(LIBS)
+test/librbd/ceph_test_librbd-test_main.$(OBJEXT):  \
+	test/librbd/$(am__dirstamp) \
+	test/librbd/$(DEPDIR)/$(am__dirstamp)
 
 ceph_test_librbd$(EXEEXT): $(ceph_test_librbd_OBJECTS) $(ceph_test_librbd_DEPENDENCIES) $(EXTRA_ceph_test_librbd_DEPENDENCIES) 
 	@rm -f ceph_test_librbd$(EXEEXT)
 	$(AM_V_CXXLD)$(ceph_test_librbd_LINK) $(ceph_test_librbd_OBJECTS) $(ceph_test_librbd_LDADD) $(LIBS)
+test/librbd/ceph_test_librbd_api-test_support.$(OBJEXT):  \
+	test/librbd/$(am__dirstamp) \
+	test/librbd/$(DEPDIR)/$(am__dirstamp)
+test/librbd/ceph_test_librbd_api-test_librbd.$(OBJEXT):  \
+	test/librbd/$(am__dirstamp) \
+	test/librbd/$(DEPDIR)/$(am__dirstamp)
+test/librbd/ceph_test_librbd_api-test_main.$(OBJEXT):  \
+	test/librbd/$(am__dirstamp) \
+	test/librbd/$(DEPDIR)/$(am__dirstamp)
+
+ceph_test_librbd_api$(EXEEXT): $(ceph_test_librbd_api_OBJECTS) $(ceph_test_librbd_api_DEPENDENCIES) $(EXTRA_ceph_test_librbd_api_DEPENDENCIES) 
+	@rm -f ceph_test_librbd_api$(EXEEXT)
+	$(AM_V_CXXLD)$(ceph_test_librbd_api_LINK) $(ceph_test_librbd_api_OBJECTS) $(ceph_test_librbd_api_LDADD) $(LIBS)
 test/librbd/ceph_test_librbd_fsx-fsx.$(OBJEXT):  \
 	test/librbd/$(am__dirstamp) \
 	test/librbd/$(DEPDIR)/$(am__dirstamp)
-common/dummy.$(OBJEXT): common/$(am__dirstamp) \
-	common/$(DEPDIR)/$(am__dirstamp)
 
 ceph_test_librbd_fsx$(EXEEXT): $(ceph_test_librbd_fsx_OBJECTS) $(ceph_test_librbd_fsx_DEPENDENCIES) $(EXTRA_ceph_test_librbd_fsx_DEPENDENCIES) 
 	@rm -f ceph_test_librbd_fsx$(EXEEXT)
-	$(AM_V_CXXLD)$(CXXLINK) $(ceph_test_librbd_fsx_OBJECTS) $(ceph_test_librbd_fsx_LDADD) $(LIBS)
+	$(AM_V_CXXLD)$(ceph_test_librbd_fsx_LINK) $(ceph_test_librbd_fsx_OBJECTS) $(ceph_test_librbd_fsx_LDADD) $(LIBS)
 test/mon/$(am__dirstamp):
 	@$(MKDIR_P) test/mon
 	@: > test/mon/$(am__dirstamp)
@@ -12840,10 +12912,13 @@ test/librados/unittest_librados_config-librados_config.$(OBJEXT):  \
 unittest_librados_config$(EXEEXT): $(unittest_librados_config_OBJECTS) $(unittest_librados_config_DEPENDENCIES) $(EXTRA_unittest_librados_config_DEPENDENCIES) 
 	@rm -f unittest_librados_config$(EXEEXT)
 	$(AM_V_CXXLD)$(unittest_librados_config_LINK) $(unittest_librados_config_OBJECTS) $(unittest_librados_config_LDADD) $(LIBS)
+test/librbd/unittest_librbd-test_main.$(OBJEXT):  \
+	test/librbd/$(am__dirstamp) \
+	test/librbd/$(DEPDIR)/$(am__dirstamp)
 
 unittest_librbd$(EXEEXT): $(unittest_librbd_OBJECTS) $(unittest_librbd_DEPENDENCIES) $(EXTRA_unittest_librbd_DEPENDENCIES) 
 	@rm -f unittest_librbd$(EXEEXT)
-	$(AM_V_CXXLD)$(CXXLINK) $(unittest_librbd_OBJECTS) $(unittest_librbd_LDADD) $(LIBS)
+	$(AM_V_CXXLD)$(unittest_librbd_LINK) $(unittest_librbd_OBJECTS) $(unittest_librbd_LDADD) $(LIBS)
 log/unittest_log-test.$(OBJEXT): log/$(am__dirstamp) \
 	log/$(DEPDIR)/$(am__dirstamp)
 
@@ -13489,10 +13564,8 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ceph_mon.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ceph_osd.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ceph_syn.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ceph_test_librbd-dummy.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ceph_ver.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cephfs.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/dummy.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/krbd.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcephfs.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/librados-config.Po at am__quote@
@@ -13604,7 +13677,6 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at common/$(DEPDIR)/common_init.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at common/$(DEPDIR)/config.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at common/$(DEPDIR)/dout.Plo at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at common/$(DEPDIR)/dummy.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at common/$(DEPDIR)/entity_name.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at common/$(DEPDIR)/environment.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at common/$(DEPDIR)/errno.Plo at am__quote@
@@ -14351,12 +14423,18 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at test/libradosstriper/$(DEPDIR)/ceph_test_rados_striper_api_io-io.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test/libradosstriper/$(DEPDIR)/ceph_test_rados_striper_api_striping-striping.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test/libradosstriper/$(DEPDIR)/libradosstripertest_la-TestCase.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at test/librbd/$(DEPDIR)/ceph_test_librbd-test_main.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at test/librbd/$(DEPDIR)/ceph_test_librbd_api-test_librbd.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at test/librbd/$(DEPDIR)/ceph_test_librbd_api-test_main.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at test/librbd/$(DEPDIR)/ceph_test_librbd_api-test_support.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test/librbd/$(DEPDIR)/ceph_test_librbd_fsx-fsx.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test/librbd/$(DEPDIR)/librbd_test_la-test_ImageWatcher.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at test/librbd/$(DEPDIR)/librbd_test_la-test_ObjectMap.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test/librbd/$(DEPDIR)/librbd_test_la-test_fixture.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test/librbd/$(DEPDIR)/librbd_test_la-test_internal.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test/librbd/$(DEPDIR)/librbd_test_la-test_librbd.Plo at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at test/librbd/$(DEPDIR)/librbd_test_la-test_main.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at test/librbd/$(DEPDIR)/librbd_test_la-test_support.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at test/librbd/$(DEPDIR)/unittest_librbd-test_main.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test/mds/$(DEPDIR)/unittest_mds_authcap-TestMDSAuthCaps.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test/messenger/$(DEPDIR)/simple_client-simple_client.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test/messenger/$(DEPDIR)/simple_client-simple_dispatcher.Po at am__quote@
@@ -15175,20 +15253,6 @@ test/ceph_test_c_headers-test_c_headers.obj: test/test_c_headers.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) $(ceph_test_c_headers_CFLAGS) $(CFLAGS) -c -o test/ceph_test_c_headers-test_c_headers.obj `if test -f 'test/test_c_headers.c'; then $(CYGPATH_W) 'test/test_c_headers.c'; else $(CYGPATH_W) '$(srcdir)/test/test_c_headers.c'; fi`
 
-test/librbd/ceph_test_librbd_fsx-fsx.o: test/librbd/fsx.c
- at 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
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) test/librbd/$(DEPDIR)/ceph_test_librbd_fsx-fsx.Tpo test/librbd/$(DEPDIR)/ceph_test_librbd_fsx-fsx.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test/librbd/fsx.c' object='test/librbd/ceph_test_librbd_fsx-fsx.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) $(ceph_test_librbd_fsx_CFLAGS) $(CFLAGS) -c -o test/librbd/ceph_test_librbd_fsx-fsx.o `test -f 'test/librbd/fsx.c' || echo '$(srcdir)/'`test/librbd/fsx.c
-
-test/librbd/ceph_test_librbd_fsx-fsx.obj: test/librbd/fsx.c
- at 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.obj -MD -MP -MF test/librbd/$(DEPDIR)/ceph_test_librbd_fsx-fsx.Tpo -c -o test/librbd/ceph_test_librbd_fsx-fsx.obj `if test -f 'test/librbd/fsx.c'; then $(CYGPATH_W) 'test/librbd/fsx.c'; else $(CYGPATH_W) '$(srcdir)/test/librbd/fsx.c'; fi`
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) test/librbd/$(DEPDIR)/ceph_test_librbd_fsx-fsx.Tpo test/librbd/$(DEPDIR)/ceph_test_librbd_fsx-fsx.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='test/librbd/fsx.c' object='test/librbd/ceph_test_librbd_fsx-fsx.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) $(ceph_test_librbd_fsx_CFLAGS) $(CFLAGS) -c -o test/librbd/ceph_test_librbd_fsx-fsx.obj `if test -f 'test/librbd/fsx.c'; then $(CYGPATH_W) 'test/librbd/fsx.c'; else $(CYGPATH_W) '$(srcdir)/test/librbd/fsx.c'; fi`
-
 erasure-code/jerasure/jerasure/src/unittest_erasure_code_jerasure-cauchy.o: erasure-code/jerasure/jerasure/src/cauchy.c
 @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 [...]
 @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
@@ -16844,6 +16908,13 @@ test/librbd/librbd_test_la-test_fixture.lo: test/librbd/test_fixture.cc
 @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) $(librbd_test_la_CXXFLAGS) $(CXXFLAGS) -c -o test/librbd/librbd_test_la-test_fixture.lo `test -f 'test/librbd/test_fixture.cc' || echo '$(srcdir)/'`test/librbd/test_fixture.cc
 
+test/librbd/librbd_test_la-test_support.lo: test/librbd/test_support.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) $(librbd_test_la_CXXFLAGS) $(CXXFLAGS) -MT test/librbd/librbd_test_la-test_support.lo -MD -MP -MF test/librbd/$(DEPDIR)/librbd_test_la-test_support.Tpo -c -o test/librbd/librbd_test_la-test_support.lo `test -f 'test/librbd/test_support.cc' || echo '$(srcdir)/'`test/librbd/test_support.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) test/librbd/$(DEPDIR)/librbd_test_la-test_support.Tpo test/librbd/$(DEPDIR)/librbd_test_la-test_support.Plo
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='test/librbd/test_support.cc' object='test/librbd/librbd_test_la-test_support.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) $(librbd_test_la_CXXFLAGS) $(CXXFLAGS) -c -o test/librbd/librbd_test_la-test_support.lo `test -f 'test/librbd/test_support.cc' || echo '$(srcdir)/'`test/librbd/test_support.cc
+
 test/librbd/librbd_test_la-test_librbd.lo: test/librbd/test_librbd.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) $(librbd_test_la_CXXFLAGS) $(CXXFLAGS) -MT test/librbd/librbd_test_la-test_librbd.lo -MD -MP -MF test/librbd/$(DEPDIR)/librbd_test_la-test_librbd.Tpo -c -o test/librbd/librbd_test_la-test_librbd.lo `test -f 'test/librbd/test_librbd.cc' || echo '$(srcdir)/'`test/librbd/test_librbd.cc
 @am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) test/librbd/$(DEPDIR)/librbd_test_la-test_librbd.Tpo test/librbd/$(DEPDIR)/librbd_test_la-test_librbd.Plo
@@ -16865,12 +16936,12 @@ test/librbd/librbd_test_la-test_internal.lo: test/librbd/test_internal.cc
 @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) $(librbd_test_la_CXXFLAGS) $(CXXFLAGS) -c -o test/librbd/librbd_test_la-test_internal.lo `test -f 'test/librbd/test_internal.cc' || echo '$(srcdir)/'`test/librbd/test_internal.cc
 
-test/librbd/librbd_test_la-test_main.lo: test/librbd/test_main.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) $(librbd_test_la_CXXFLAGS) $(CXXFLAGS) -MT test/librbd/librbd_test_la-test_main.lo -MD -MP -MF test/librbd/$(DEPDIR)/librbd_test_la-test_main.Tpo -c -o test/librbd/librbd_test_la-test_main.lo `test -f 'test/librbd/test_main.cc' || echo '$(srcdir)/'`test/librbd/test_main.cc
- at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) test/librbd/$(DEPDIR)/librbd_test_la-test_main.Tpo test/librbd/$(DEPDIR)/librbd_test_la-test_main.Plo
- at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='test/librbd/test_main.cc' object='test/librbd/librbd_test_la-test_main.lo' libtool=yes @AMDEPBACKSLASH@
+test/librbd/librbd_test_la-test_ObjectMap.lo: test/librbd/test_ObjectMap.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) $(librbd_test_la_CXXFLAGS) $(CXXFLAGS) -MT test/librbd/librbd_test_la-test_ObjectMap.lo -MD -MP -MF test/librbd/$(DEPDIR)/librbd_test_la-test_ObjectMap.Tpo -c -o test/librbd/librbd_test_la-test_ObjectMap.lo `test -f 'test/librbd/test_ObjectMap.cc' || echo '$(srcdir)/'`test/librbd/test_ObjectMap.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) test/librbd/$(DEPDIR)/librbd_test_la-test_ObjectMap.Tpo test/librbd/$(DEPDIR)/librbd_test_la-test_ObjectMap.Plo
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='test/librbd/test_ObjectMap.cc' object='test/librbd/librbd_test_la-test_ObjectMap.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) $(librbd_test_la_CXXFLAGS) $(CXXFLAGS) -c -o test/librbd/librbd_test_la-test_main.lo `test -f 'test/librbd/test_main.cc' || echo '$(srcdir)/'`test/librbd/test_main.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) $(librbd_test_la_CXXFLAGS) $(CXXFLAGS) -c -o test/librbd/librbd_test_la-test_ObjectMap.lo `test -f 'test/librbd/test_ObjectMap.cc' || echo '$(srcdir)/'`test/librbd/test_ObjectMap.cc
 
 rgw/librgw_la-librgw.lo: rgw/librgw.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) $(librgw_la_CXXFLAGS) $(CXXFLAGS) -MT rgw/librgw_la-librgw.lo -MD -MP -MF rgw/$(DEPDIR)/librgw_la-librgw.Tpo -c -o rgw/librgw_la-librgw.lo `test -f 'rgw/librgw.cc' || echo '$(srcdir)/'`rgw/librgw.cc
@@ -17964,19 +18035,75 @@ test/libcephfs/ceph_test_libcephfs-multiclient.obj: test/libcephfs/multiclient.c
 @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_test_libcephfs_CXXFLAGS) $(CXXFLAGS) -c -o test/libcephfs/ceph_test_libcephfs-multiclient.obj `if test -f 'test/libcephfs/multiclient.cc'; then $(CYGPATH_W) 'test/libcephfs/multiclient.cc'; else $(CYGPATH_W) '$(srcdir)/test/libcephfs/multiclient.cc'; fi`
 
-ceph_test_librbd-dummy.o: dummy.cc
- at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ceph_test_librbd_CXXFLAGS) $(CXXFLAGS) -MT ceph_test_librbd-dummy.o -MD -MP -MF $(DEPDIR)/ceph_test_librbd-dummy.Tpo -c -o ceph_test_librbd-dummy.o `test -f 'dummy.cc' || echo '$(srcdir)/'`dummy.cc
- at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/ceph_test_librbd-dummy.Tpo $(DEPDIR)/ceph_test_librbd-dummy.Po
- at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='dummy.cc' object='ceph_test_librbd-dummy.o' libtool=no @AMDEPBACKSLASH@
+test/librbd/ceph_test_librbd-test_main.o: test/librbd/test_main.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ceph_test_librbd_CXXFLAGS) $(CXXFLAGS) -MT test/librbd/ceph_test_librbd-test_main.o -MD -MP -MF test/librbd/$(DEPDIR)/ceph_test_librbd-test_main.Tpo -c -o test/librbd/ceph_test_librbd-test_main.o `test -f 'test/librbd/test_main.cc' || echo '$(srcdir)/'`test/librbd/test_main.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) test/librbd/$(DEPDIR)/ceph_test_librbd-test_main.Tpo test/librbd/$(DEPDIR)/ceph_test_librbd-test_main.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='test/librbd/test_main.cc' object='test/librbd/ceph_test_librbd-test_main.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) $(ceph_test_librbd_CXXFLAGS) $(CXXFLAGS) -c -o test/librbd/ceph_test_librbd-test_main.o `test -f 'test/librbd/test_main.cc' || echo '$(srcdir)/'`test/librbd/test_main.cc
+
+test/librbd/ceph_test_librbd-test_main.obj: test/librbd/test_main.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ceph_test_librbd_CXXFLAGS) $(CXXFLAGS) -MT test/librbd/ceph_test_librbd-test_main.obj -MD -MP -MF test/librbd/$(DEPDIR)/ceph_test_librbd-test_main.Tpo -c -o test/librbd/ceph_test_librbd-test_main.obj `if test -f 'test/librbd/test_main.cc'; then $(CYGPATH_W) 'test/librbd/test_main.cc'; else $(CYGPATH_W) '$(srcdir)/test/librbd/test_main.cc'; fi`
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) test/librbd/$(DEPDIR)/ceph_test_librbd-test_main.Tpo test/librbd/$(DEPDIR)/ceph_test_librbd-test_main.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='test/librbd/test_main.cc' object='test/librbd/ceph_test_librbd-test_main.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) $(ceph_test_librbd_CXXFLAGS) $(CXXFLAGS) -c -o test/librbd/ceph_test_librbd-test_main.obj `if test -f 'test/librbd/test_main.cc'; then $(CYGPATH_W) 'test/librbd/test_main.cc'; else $(CYGPATH_W) '$(srcdir)/test/librbd/test_main.cc'; fi`
+
+test/librbd/ceph_test_librbd_api-test_support.o: test/librbd/test_support.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ceph_test_librbd_api_CXXFLAGS) $(CXXFLAGS) -MT test/librbd/ceph_test_librbd_api-test_support.o -MD -MP -MF test/librbd/$(DEPDIR)/ceph_test_librbd_api-test_support.Tpo -c -o test/librbd/ceph_test_librbd_api-test_support.o `test -f 'test/librbd/test_support.cc' || echo '$(srcdir)/'`test/librbd/test_support.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) test/librbd/$(DEPDIR)/ceph_test_librbd_api-test_support.Tpo test/librbd/$(DEPDIR)/ceph_test_librbd_api-test_support.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='test/librbd/test_support.cc' object='test/librbd/ceph_test_librbd_api-test_support.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) $(ceph_test_librbd_api_CXXFLAGS) $(CXXFLAGS) -c -o test/librbd/ceph_test_librbd_api-test_support.o `test -f 'test/librbd/test_support.cc' || echo '$(srcdir)/'`test/librbd/test_support.cc
+
+test/librbd/ceph_test_librbd_api-test_support.obj: test/librbd/test_support.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ceph_test_librbd_api_CXXFLAGS) $(CXXFLAGS) -MT test/librbd/ceph_test_librbd_api-test_support.obj -MD -MP -MF test/librbd/$(DEPDIR)/ceph_test_librbd_api-test_support.Tpo -c -o test/librbd/ceph_test_librbd_api-test_support.obj `if test -f 'test/librbd/test_support.cc'; then $(CYGPATH_W) 'test/librbd/test_support.cc'; else $(CYGPATH_W) '$(srcdir)/test/librbd/test_support.cc'; fi`
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) test/librbd/$(DEPDIR)/ceph_test_librbd_api-test_support.Tpo test/librbd/$(DEPDIR)/ceph_test_librbd_api-test_support.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='test/librbd/test_support.cc' object='test/librbd/ceph_test_librbd_api-test_support.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) $(ceph_test_librbd_api_CXXFLAGS) $(CXXFLAGS) -c -o test/librbd/ceph_test_librbd_api-test_support.obj `if test -f 'test/librbd/test_support.cc'; then $(CYGPATH_W) 'test/librbd/test_support.cc'; else $(CYGPATH_W) '$(srcdir)/test/librbd/test_support.cc'; fi`
+
+test/librbd/ceph_test_librbd_api-test_librbd.o: test/librbd/test_librbd.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ceph_test_librbd_api_CXXFLAGS) $(CXXFLAGS) -MT test/librbd/ceph_test_librbd_api-test_librbd.o -MD -MP -MF test/librbd/$(DEPDIR)/ceph_test_librbd_api-test_librbd.Tpo -c -o test/librbd/ceph_test_librbd_api-test_librbd.o `test -f 'test/librbd/test_librbd.cc' || echo '$(srcdir)/'`test/librbd/test_librbd.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) test/librbd/$(DEPDIR)/ceph_test_librbd_api-test_librbd.Tpo test/librbd/$(DEPDIR)/ceph_test_librbd_api-test_librbd.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='test/librbd/test_librbd.cc' object='test/librbd/ceph_test_librbd_api-test_librbd.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_test_librbd_CXXFLAGS) $(CXXFLAGS) -c -o ceph_test_librbd-dummy.o `test -f 'dummy.cc' || echo '$(srcdir)/'`dummy.cc
+ at am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ceph_test_librbd_api_CXXFLAGS) $(CXXFLAGS) -c -o test/librbd/ceph_test_librbd_api-test_librbd.o `test -f 'test/librbd/test_librbd.cc' || echo '$(srcdir)/'`test/librbd/test_librbd.cc
 
-ceph_test_librbd-dummy.obj: dummy.cc
- at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ceph_test_librbd_CXXFLAGS) $(CXXFLAGS) -MT ceph_test_librbd-dummy.obj -MD -MP -MF $(DEPDIR)/ceph_test_librbd-dummy.Tpo -c -o ceph_test_librbd-dummy.obj `if test -f 'dummy.cc'; then $(CYGPATH_W) 'dummy.cc'; else $(CYGPATH_W) '$(srcdir)/dummy.cc'; fi`
- at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/ceph_test_librbd-dummy.Tpo $(DEPDIR)/ceph_test_librbd-dummy.Po
- at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='dummy.cc' object='ceph_test_librbd-dummy.obj' libtool=no @AMDEPBACKSLASH@
+test/librbd/ceph_test_librbd_api-test_librbd.obj: test/librbd/test_librbd.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ceph_test_librbd_api_CXXFLAGS) $(CXXFLAGS) -MT test/librbd/ceph_test_librbd_api-test_librbd.obj -MD -MP -MF test/librbd/$(DEPDIR)/ceph_test_librbd_api-test_librbd.Tpo -c -o test/librbd/ceph_test_librbd_api-test_librbd.obj `if test -f 'test/librbd/test_librbd.cc'; then $(CYGPATH_W) 'test/librbd/test_librbd.cc'; else $(CYGPATH_W) '$(srcdir)/test/librbd/test_librbd.cc'; fi`
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) test/librbd/$(DEPDIR)/ceph_test_librbd_api-test_librbd.Tpo test/librbd/$(DEPDIR)/ceph_test_librbd_api-test_librbd.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='test/librbd/test_librbd.cc' object='test/librbd/ceph_test_librbd_api-test_librbd.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_test_librbd_CXXFLAGS) $(CXXFLAGS) -c -o ceph_test_librbd-dummy.obj `if test -f 'dummy.cc'; then $(CYGPATH_W) 'dummy.cc'; else $(CYGPATH_W) '$(srcdir)/dummy.cc'; fi`
+ at am__fastdepCXX_FALSE@	$(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ceph_test_librbd_api_CXXFLAGS) $(CXXFLAGS) -c -o test/librbd/ceph_test_librbd_api-test_librbd.obj `if test -f 'test/librbd/test_librbd.cc'; then $(CYGPATH_W) 'test/librbd/test_librbd.cc'; else $(CYGPATH_W) '$(srcdir)/test/librbd/test_librbd.cc'; fi`
+
+test/librbd/ceph_test_librbd_api-test_main.o: test/librbd/test_main.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ceph_test_librbd_api_CXXFLAGS) $(CXXFLAGS) -MT test/librbd/ceph_test_librbd_api-test_main.o -MD -MP -MF test/librbd/$(DEPDIR)/ceph_test_librbd_api-test_main.Tpo -c -o test/librbd/ceph_test_librbd_api-test_main.o `test -f 'test/librbd/test_main.cc' || echo '$(srcdir)/'`test/librbd/test_main.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) test/librbd/$(DEPDIR)/ceph_test_librbd_api-test_main.Tpo test/librbd/$(DEPDIR)/ceph_test_librbd_api-test_main.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='test/librbd/test_main.cc' object='test/librbd/ceph_test_librbd_api-test_main.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) $(ceph_test_librbd_api_CXXFLAGS) $(CXXFLAGS) -c -o test/librbd/ceph_test_librbd_api-test_main.o `test -f 'test/librbd/test_main.cc' || echo '$(srcdir)/'`test/librbd/test_main.cc
+
+test/librbd/ceph_test_librbd_api-test_main.obj: test/librbd/test_main.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ceph_test_librbd_api_CXXFLAGS) $(CXXFLAGS) -MT test/librbd/ceph_test_librbd_api-test_main.obj -MD -MP -MF test/librbd/$(DEPDIR)/ceph_test_librbd_api-test_main.Tpo -c -o test/librbd/ceph_test_librbd_api-test_main.obj `if test -f 'test/librbd/test_main.cc'; then $(CYGPATH_W) 'test/librbd/test_main.cc'; else $(CYGPATH_W) '$(srcdir)/test/librbd/test_main.cc'; fi`
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) test/librbd/$(DEPDIR)/ceph_test_librbd_api-test_main.Tpo test/librbd/$(DEPDIR)/ceph_test_librbd_api-test_main.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='test/librbd/test_main.cc' object='test/librbd/ceph_test_librbd_api-test_main.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) $(ceph_test_librbd_api_CXXFLAGS) $(CXXFLAGS) -c -o test/librbd/ceph_test_librbd_api-test_main.obj `if test -f 'test/librbd/test_main.cc'; then $(CYGPATH_W) 'test/librbd/test_main.cc'; else $(CYGPATH_W) '$(srcdir)/test/librbd/test_main.cc'; fi`
+
+test/librbd/ceph_test_librbd_fsx-fsx.o: test/librbd/fsx.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ceph_test_librbd_fsx_CXXFLAGS) $(CXXFLAGS) -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.cc' || echo '$(srcdir)/'`test/librbd/fsx.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) test/librbd/$(DEPDIR)/ceph_test_librbd_fsx-fsx.Tpo test/librbd/$(DEPDIR)/ceph_test_librbd_fsx-fsx.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='test/librbd/fsx.cc' object='test/librbd/ceph_test_librbd_fsx-fsx.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) $(ceph_test_librbd_fsx_CXXFLAGS) $(CXXFLAGS) -c -o test/librbd/ceph_test_librbd_fsx-fsx.o `test -f 'test/librbd/fsx.cc' || echo '$(srcdir)/'`test/librbd/fsx.cc
+
+test/librbd/ceph_test_librbd_fsx-fsx.obj: test/librbd/fsx.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ceph_test_librbd_fsx_CXXFLAGS) $(CXXFLAGS) -MT test/librbd/ceph_test_librbd_fsx-fsx.obj -MD -MP -MF test/librbd/$(DEPDIR)/ceph_test_librbd_fsx-fsx.Tpo -c -o test/librbd/ceph_test_librbd_fsx-fsx.obj `if test -f 'test/librbd/fsx.cc'; then $(CYGPATH_W) 'test/librbd/fsx.cc'; else $(CYGPATH_W) '$(srcdir)/test/librbd/fsx.cc'; fi`
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) test/librbd/$(DEPDIR)/ceph_test_librbd_fsx-fsx.Tpo test/librbd/$(DEPDIR)/ceph_test_librbd_fsx-fsx.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='test/librbd/fsx.cc' object='test/librbd/ceph_test_librbd_fsx-fsx.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) $(ceph_test_librbd_fsx_CXXFLAGS) $(CXXFLAGS) -c -o test/librbd/ceph_test_librbd_fsx-fsx.obj `if test -f 'test/librbd/fsx.cc'; then $(CYGPATH_W) 'test/librbd/fsx.cc'; else $(CYGPATH_W) '$(srcdir)/test/librbd/fsx.cc'; fi`
 
 test/mon/ceph_test_mon_msg-test-mon-msg.o: test/mon/test-mon-msg.cc
 @am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ceph_test_mon_msg_CXXFLAGS) $(CXXFLAGS) -MT test/mon/ceph_test_mon_msg-test-mon-msg.o -MD -MP -MF test/mon/$(DEPDIR)/ceph_test_mon_msg-test-mon-msg.Tpo -c -o test/mon/ceph_test_mon_msg-test-mon-msg.o `test -f 'test/mon/test-mon-msg.cc' || echo '$(srcdir)/'`test/mon/test-mon-msg.cc
@@ -20134,6 +20261,20 @@ test/librados/unittest_librados_config-librados_config.obj: test/librados/librad
 @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_librados_config_CXXFLAGS) $(CXXFLAGS) -c -o test/librados/unittest_librados_config-librados_config.obj `if test -f 'test/librados/librados_config.cc'; then $(CYGPATH_W) 'test/librados/librados_config.cc'; else $(CYGPATH_W) '$(srcdir)/test/librados/librados_config.cc'; fi`
 
+test/librbd/unittest_librbd-test_main.o: test/librbd/test_main.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_librbd_CXXFLAGS) $(CXXFLAGS) -MT test/librbd/unittest_librbd-test_main.o -MD -MP -MF test/librbd/$(DEPDIR)/unittest_librbd-test_main.Tpo -c -o test/librbd/unittest_librbd-test_main.o `test -f 'test/librbd/test_main.cc' || echo '$(srcdir)/'`test/librbd/test_main.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) test/librbd/$(DEPDIR)/unittest_librbd-test_main.Tpo test/librbd/$(DEPDIR)/unittest_librbd-test_main.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='test/librbd/test_main.cc' object='test/librbd/unittest_librbd-test_main.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_librbd_CXXFLAGS) $(CXXFLAGS) -c -o test/librbd/unittest_librbd-test_main.o `test -f 'test/librbd/test_main.cc' || echo '$(srcdir)/'`test/librbd/test_main.cc
+
+test/librbd/unittest_librbd-test_main.obj: test/librbd/test_main.cc
+ at am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_librbd_CXXFLAGS) $(CXXFLAGS) -MT test/librbd/unittest_librbd-test_main.obj -MD -MP -MF test/librbd/$(DEPDIR)/unittest_librbd-test_main.Tpo -c -o test/librbd/unittest_librbd-test_main.obj `if test -f 'test/librbd/test_main.cc'; then $(CYGPATH_W) 'test/librbd/test_main.cc'; else $(CYGPATH_W) '$(srcdir)/test/librbd/test_main.cc'; fi`
+ at am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) test/librbd/$(DEPDIR)/unittest_librbd-test_main.Tpo test/librbd/$(DEPDIR)/unittest_librbd-test_main.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='test/librbd/test_main.cc' object='test/librbd/unittest_librbd-test_main.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_librbd_CXXFLAGS) $(CXXFLAGS) -c -o test/librbd/unittest_librbd-test_main.obj `if test -f 'test/librbd/test_main.cc'; then $(CYGPATH_W) 'test/librbd/test_main.cc'; else $(CYGPATH_W) '$(srcdir)/test/librbd/test_main.cc'; fi`
+
 log/unittest_log-test.o: log/test.cc
 @am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_log_CXXFLAGS) $(CXXFLAGS) -MT log/unittest_log-test.o -MD -MP -MF log/$(DEPDIR)/unittest_log-test.Tpo -c -o log/unittest_log-test.o `test -f 'log/test.cc' || echo '$(srcdir)/'`log/test.cc
 @am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) log/$(DEPDIR)/unittest_log-test.Tpo log/$(DEPDIR)/unittest_log-test.Po
@@ -22388,6 +22529,9 @@ uninstall-am: uninstall-bash_completionDATA uninstall-binPROGRAMS \
 	uninstall-su_sbinPROGRAMS uninstall-su_sbinSCRIPTS
 
 
+# display the output of failed check_SCRIPTS after a failed make check
+export VERBOSE = true
+
 # python unit tests need to know where the scripts are located
 export PYTHONPATH=$(top_srcdir)/src/pybind
 @CLANG_FALSE@	AM_COMMON_CFLAGS += -rdynamic
diff --git a/src/acconfig.h.in b/src/acconfig.h.in
index c99f460..8caa7ef 100644
--- a/src/acconfig.h.in
+++ b/src/acconfig.h.in
@@ -150,6 +150,9 @@
 /* Define if you have tcmalloc */
 #undef HAVE_LIBTCMALLOC
 
+/* Define if you have tcmalloc */
+#undef HAVE_LIBTCMALLOC_MINIMAL
+
 /* Define to 1 if you have libxfs */
 #undef HAVE_LIBXFS
 
diff --git a/src/ceph-disk b/src/ceph-disk
index 1f62399..61a28fd 100755
--- a/src/ceph-disk
+++ b/src/ceph-disk
@@ -2358,6 +2358,13 @@ def get_dev_fs(dev):
         return None
 
 
+def split_dev_base_partnum(dev):
+    if 'loop' in dev or 'cciss' in dev or 'nvme' in dev:
+        return re.match('(.*\d+)p(\d+)', dev).group(1, 2)
+    else:
+        return re.match('(\D+)(\d+)', dev).group(1, 2)
+
+
 def get_partition_type(part):
     """
     Get the GPT partition type UUID.  If we have an old blkid and can't
@@ -2407,7 +2414,7 @@ def get_partition_type(part):
     if 'blkid' not in warned_about:
         LOG.warning('Old blkid does not support ID_PART_ENTRY_* fields, trying sgdisk; may not correctly identify ceph volumes with dmcrypt')
         warned_about['blkid'] = True
-    (base, partnum) = re.match('(\D+)(\d+)', part).group(1, 2)
+    (base, partnum) = split_dev_base_partnum(part)
     sgdisk, _ = command(
         [
             'sgdisk',
@@ -2433,10 +2440,7 @@ def get_partition_type(part):
 
 
 def get_partition_uuid(dev):
-    if 'loop' in dev or 'cciss' in dev:
-        (base, partnum) = re.match('(.*\d+)p(\d+)', dev).group(1, 2)
-    else:
-        (base, partnum) = re.match('(\D+)(\d+)', dev).group(1, 2)
+    (base, partnum) = split_dev_base_partnum(dev)
     out, _ = command(['sgdisk', '-i', partnum, base])
     for line in out.splitlines():
         m = re.match('Partition unique GUID: (\S+)', line)
diff --git a/src/ceph-post-file.in b/src/ceph-post-file.in
index 9b922a6..b278e8a 100755
--- a/src/ceph-post-file.in
+++ b/src/ceph-post-file.in
@@ -1,16 +1,16 @@
 #!/bin/bash -e
 
-# if we start up as ./$0, assume we are running from a source
-# checkout.
-if [ `dirname $0` = "." ] && [ $PWD != "/usr/bin" ]; then
-    known_hosts=../share/known_hosts_drop.ceph.com
-    ssh_key=../share/id_dsa_drop.ceph.com
-else
-    known_hosts=@datadir@/known_hosts_drop.ceph.com
-    ssh_key=@datadir@/id_dsa_drop.ceph.com
+# If these files exist, assume we are a source install.
+if [[ -f ../share/known_hosts_drop.ceph.com && -f ../share/id_dsa_drop.ceph.com ]]
+    then # running from source install
+       known_hosts=../share/known_hosts_drop.ceph.com
+       ssh_key=../share/id_dsa_drop.ceph.com
+    else # running from a pkg install
+       known_hosts=@datadir@/known_hosts_drop.ceph.com
+       ssh_key=@datadir@/id_dsa_drop.ceph.com
 fi
 
-usage() {
+function usage() {
     echo "Usage: $0 [options] file1 [dir2 ...]
 
 Easily upload files or directories to ceph.com for analysis by Ceph
@@ -155,7 +155,7 @@ done
 cp "$ssh_key" "$t4"
 cp "${ssh_key}.pub" "$t4.pub"
 
-sftp -i $t4 \
+sftp -o "IdentityFile=$t4" \
     -C \
     -oCheckHostIP=no \
     -oGlobalKnownHostsFile=$known_hosts \
diff --git a/src/ceph.in b/src/ceph.in
index 53f8087..2b6adf4 100755
--- a/src/ceph.in
+++ b/src/ceph.in
@@ -62,6 +62,7 @@ import argparse
 import errno
 import json
 import rados
+import shlex
 import signal
 import socket
 import string
@@ -384,6 +385,25 @@ def ceph_conf(parsed_args, field, name):
 
 PROMPT = 'ceph> '
 
+if sys.stdin.isatty():
+    def read_input():
+        while True:
+            line = raw_input(PROMPT).rstrip()
+            if line in ['q', 'quit', 'Q']:
+                return None
+            if line:
+                return line
+else:
+    def read_input():
+        while True:
+            line = sys.stdin.readline()
+            if not line:
+                return None
+            line = line.rstrip()
+            if line:
+                return line
+
+
 def new_style_command(parsed_args, cmdargs, target, sigdict, inbuf, verbose):
     """
     Do new-style command dance.
@@ -411,26 +431,22 @@ def new_style_command(parsed_args, cmdargs, target, sigdict, inbuf, verbose):
             else:
                 return -errno.EINVAL, '', 'invalid command'
         else:
-            # do the command-interpreter looping
-            # for raw_input to do readline cmd editing
-            import readline
-
             if sys.stdin.isatty():
-                prompt = PROMPT
-            else:
-                prompt = ''
+                # do the command-interpreter looping
+                # for raw_input to do readline cmd editing
+                import readline
 
             while True:
-                interactive_input = raw_input(prompt)
-                if interactive_input in ['q', 'quit', 'Q']:
+                interactive_input = read_input()
+                if interactive_input is None:
                     return 0, '', ''
-                cmdargs = parse_cmdargs(interactive_input.split())[2]
+                cmdargs = parse_cmdargs(shlex.split(interactive_input))[2]
                 try:
                     target = find_cmd_target(cmdargs)
                 except Exception as e:
                     print >> sys.stderr, \
                             'error handling command target: {0}'.format(e)
-                    return 1
+                    return 1, '', ''
                 valid_dict = validate_command(sigdict, cmdargs, verbose)
                 if valid_dict:
                     if parsed_args.output_format:
diff --git a/src/client/Client.cc b/src/client/Client.cc
index 63a9faa..446f0d1 100644
--- a/src/client/Client.cc
+++ b/src/client/Client.cc
@@ -254,8 +254,7 @@ void Client::tear_down_cache()
        ++it) {
     Fh *fh = it->second;
     ldout(cct, 1) << "tear_down_cache forcing close of fh " << it->first << " ino " << fh->inode->ino << dendl;
-    put_inode(fh->inode);
-    delete fh;
+    _release_fh(fh);
   }
   fd_map.clear();
 
@@ -6697,12 +6696,20 @@ int Client::_release_fh(Fh *f)
     ldout(cct, 10) << "_release_fh " << f << " on inode " << *in << " no async_err state" << dendl;
   }
 
-  put_inode(in);
-  delete f;
+  _put_fh(f);
 
   return err;
 }
 
+void Client::_put_fh(Fh *f)
+{
+  int left = f->put();
+  if (!left) {
+    put_inode(f->inode);
+    delete f;
+  }
+}
+
 int Client::_open(Inode *in, int flags, mode_t mode, Fh **fhp, int uid, int gid)
 {
   int cmode = ceph_flags_to_mode(flags);
@@ -7042,6 +7049,15 @@ done:
   return r < 0 ? r : bl->length();
 }
 
+Client::C_Readahead::C_Readahead(Client *c, Fh *f) :
+  client(c), f(f) {
+    f->get();
+}
+
+Client::C_Readahead::~C_Readahead() {
+  client->_put_fh(f);
+}
+
 void Client::C_Readahead::finish(int r) {
   lgeneric_subdout(client->cct, client, 20) << "client." << client->get_nodeid() << " " << "C_Readahead on " << f->inode << dendl;
   client->put_cap_ref(f->inode, CEPH_CAP_FILE_RD | CEPH_CAP_FILE_CACHE);
diff --git a/src/client/Client.h b/src/client/Client.h
index 074887d..b476f5e 100644
--- a/src/client/Client.h
+++ b/src/client/Client.h
@@ -628,14 +628,14 @@ private:
 
   Fh *_create_fh(Inode *in, int flags, int cmode);
   int _release_fh(Fh *fh);
+  void _put_fh(Fh *fh);
 
 
   struct C_Readahead : public Context {
     Client *client;
     Fh *f;
-    C_Readahead(Client *c, Fh *f)
-      : client(c),
-	f(f) { }
+    C_Readahead(Client *c, Fh *f);
+    ~C_Readahead();
     void finish(int r);
   };
 
diff --git a/src/client/Fh.h b/src/client/Fh.h
index 6f0aebd..dcf70cd 100644
--- a/src/client/Fh.h
+++ b/src/client/Fh.h
@@ -11,7 +11,8 @@ class ceph_lock_state_t;
 // file handle for any open file state
 
 struct Fh {
-  Inode    *inode;
+  int	    _ref;
+  Inode     *inode;
   loff_t    pos;
   int       mds;        // have to talk to mds we opened with (for now)
   int       mode;       // the mode i opened the file with
@@ -26,8 +27,10 @@ struct Fh {
   ceph_lock_state_t *fcntl_locks;
   ceph_lock_state_t *flock_locks;
 
-  Fh() : inode(0), pos(0), mds(0), mode(0), flags(0), pos_locked(false),
+  Fh() : _ref(1), inode(0), pos(0), mds(0), mode(0), flags(0), pos_locked(false),
       readahead(), fcntl_locks(NULL), flock_locks(NULL) {}
+  void get() { ++_ref; }
+  int put() { return --_ref; }
 };
 
 
diff --git a/src/common/Throttle.cc b/src/common/Throttle.cc
index 026d731..5c68a1f 100644
--- a/src/common/Throttle.cc
+++ b/src/common/Throttle.cc
@@ -267,6 +267,12 @@ void SimpleThrottle::end_op(int r)
   m_cond.Signal();
 }
 
+bool SimpleThrottle::pending_error() const
+{
+  Mutex::Locker l(m_lock);
+  return (m_ret < 0);
+}
+
 int SimpleThrottle::wait_for_ret()
 {
   Mutex::Locker l(m_lock);
diff --git a/src/common/Throttle.h b/src/common/Throttle.h
index 6d03988..b171e27 100644
--- a/src/common/Throttle.h
+++ b/src/common/Throttle.h
@@ -76,9 +76,10 @@ public:
   ~SimpleThrottle();
   void start_op();
   void end_op(int r);
+  bool pending_error() const;
   int wait_for_ret();
 private:
-  Mutex m_lock;
+  mutable Mutex m_lock;
   Cond m_cond;
   uint64_t m_max;
   uint64_t m_current;
diff --git a/src/common/WorkQueue.h b/src/common/WorkQueue.h
index 0373d73..d1b11b6 100644
--- a/src/common/WorkQueue.h
+++ b/src/common/WorkQueue.h
@@ -330,7 +330,7 @@ private:
 
 public:
   ThreadPool(CephContext *cct_, string nm, int n, const char *option = NULL);
-  ~ThreadPool();
+  virtual ~ThreadPool();
 
   /// return number of threads currently running
   int get_num_threads() {
@@ -433,6 +433,37 @@ public:
   }
 };
 
+class ContextWQ : public ThreadPool::WorkQueueVal<Context *> {
+public:
+  ContextWQ(const string &name, time_t ti, ThreadPool *tp)
+    : ThreadPool::WorkQueueVal<Context *>(name, ti, 0, tp) {}
+
+  void queue(Context *ctx) {
+    ThreadPool::WorkQueueVal<Context *>::queue(ctx);
+  }
+
+protected:
+  virtual void _enqueue(Context *item) {
+    _queue.push_back(item);
+  }
+  virtual void _enqueue_front(Context *item) {
+    _queue.push_front(item);
+  }
+  virtual bool _empty() {
+    return _queue.empty();
+  }
+  virtual Context *_dequeue() {
+    Context *item = _queue.front();
+    _queue.pop_front();
+    return item;
+  }
+  virtual void _process(Context *item) {
+    item->complete(0);
+  }
+private:
+  list<Context *> _queue;
+};
+
 class ShardedThreadPool {
 
   CephContext *cct;
diff --git a/src/common/admin_socket.cc b/src/common/admin_socket.cc
index 3220e70..95a48b3 100644
--- a/src/common/admin_socket.cc
+++ b/src/common/admin_socket.cc
@@ -149,6 +149,33 @@ std::string AdminSocket::create_shutdown_pipe(int *pipe_rd, int *pipe_wr)
   return "";
 }
 
+std::string AdminSocket::destroy_shutdown_pipe()
+{
+  // 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));
+
+  // Close write end
+  VOID_TEMP_FAILURE_RETRY(close(m_shutdown_wr_fd));
+  m_shutdown_wr_fd = -1;
+
+  if (ret != 0) {
+    ostringstream oss;
+    oss << "AdminSocket::destroy_shutdown_pipe error: failed to write"
+      "to thread shutdown pipe: error " << ret;
+    return oss.str();
+  }
+
+  join();
+
+  // Close read end. Doing this before join() blocks the listenter and prevents
+  // joining.
+  VOID_TEMP_FAILURE_RETRY(close(m_shutdown_rd_fd));
+  m_shutdown_rd_fd = -1;
+
+  return "";
+}
+
 std::string AdminSocket::bind_and_listen(const std::string &sock_path, int *fd)
 {
   ldout(m_cct, 5) << "bind_and_listen " << sock_path << dendl;
@@ -536,30 +563,31 @@ bool AdminSocket::init(const std::string &path)
 
 void AdminSocket::shutdown()
 {
+  std::string err;
+
+  // Under normal operation this is unlikely to occur.  However for some unit
+  // tests, some object members are not initialized and so cannot be deleted
+  // without fault.
   if (m_shutdown_wr_fd < 0)
     return;
 
   ldout(m_cct, 5) << "shutdown" << dendl;
 
-  // 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));
-  VOID_TEMP_FAILURE_RETRY(close(m_shutdown_wr_fd));
-  m_shutdown_wr_fd = -1;
-
-  if (ret == 0) {
-    join();
-  } else {
-    lderr(m_cct) << "AdminSocket::shutdown: failed to write "
-      "to thread shutdown pipe: error " << ret << dendl;
+  err = destroy_shutdown_pipe();
+  if (!err.empty()) {
+    lderr(m_cct) << "AdminSocket::shutdown: error: " << err << dendl;
   }
 
+  VOID_TEMP_FAILURE_RETRY(close(m_sock_fd));
+
   unregister_command("version");
   unregister_command("git_version");
   unregister_command("0");
   delete m_version_hook;
+
   unregister_command("help");
   delete m_help_hook;
+
   unregister_command("get_command_descriptions");
   delete m_getdescs_hook;
 
diff --git a/src/common/admin_socket.h b/src/common/admin_socket.h
index 20e3f9b..bbbaa29 100644
--- a/src/common/admin_socket.h
+++ b/src/common/admin_socket.h
@@ -79,6 +79,7 @@ private:
   void shutdown();
 
   std::string create_shutdown_pipe(int *pipe_rd, int *pipe_wr);
+  std::string destroy_shutdown_pipe();
   std::string bind_and_listen(const std::string &sock_path, int *fd);
 
   void *entry();
diff --git a/src/common/config.cc b/src/common/config.cc
index 88f443d..5e923e6 100644
--- a/src/common/config.cc
+++ b/src/common/config.cc
@@ -877,7 +877,7 @@ int md_config_t::set_val_raw(const char *val, const config_option *opt)
   switch (opt->type) {
     case OPT_INT: {
       std::string err;
-      int f = strict_sistrtoll(val, &err);
+      int f = strict_si_cast<int>(val, &err);
       if (!err.empty())
 	return -EINVAL;
       *(int*)opt->conf_ptr(this) = f;
@@ -885,7 +885,7 @@ int md_config_t::set_val_raw(const char *val, const config_option *opt)
     }
     case OPT_LONGLONG: {
       std::string err;
-      long long f = strict_sistrtoll(val, &err);
+      long long f = strict_si_cast<long long>(val, &err);
       if (!err.empty())
 	return -EINVAL;
       *(long long*)opt->conf_ptr(this) = f;
@@ -894,12 +894,22 @@ int md_config_t::set_val_raw(const char *val, const config_option *opt)
     case OPT_STR:
       *(std::string*)opt->conf_ptr(this) = val ? val : "";
       return 0;
-    case OPT_FLOAT:
-      *(float*)opt->conf_ptr(this) = atof(val);
+    case OPT_FLOAT: {
+      std::string err;
+      float f = strict_strtof(val, &err);
+      if (!err.empty())
+	return -EINVAL;
+      *(float*)opt->conf_ptr(this) = f;
       return 0;
-    case OPT_DOUBLE:
-      *(double*)opt->conf_ptr(this) = atof(val);
+    }
+    case OPT_DOUBLE: {
+      std::string err;
+      double f = strict_strtod(val, &err);
+      if (!err.empty())
+	return -EINVAL;
+      *(double*)opt->conf_ptr(this) = f;
       return 0;
+    }
     case OPT_BOOL:
       if (strcasecmp(val, "false") == 0)
 	*(bool*)opt->conf_ptr(this) = false;
@@ -915,7 +925,7 @@ int md_config_t::set_val_raw(const char *val, const config_option *opt)
       return 0;
     case OPT_U32: {
       std::string err;
-      int f = strict_sistrtoll(val, &err);
+      int f = strict_si_cast<int>(val, &err);
       if (!err.empty())
 	return -EINVAL;
       *(uint32_t*)opt->conf_ptr(this) = f;
@@ -923,7 +933,7 @@ int md_config_t::set_val_raw(const char *val, const config_option *opt)
     }
     case OPT_U64: {
       std::string err;
-      long long f = strict_sistrtoll(val, &err);
+      uint64_t f = strict_si_cast<uint64_t>(val, &err);
       if (!err.empty())
 	return -EINVAL;
       *(uint64_t*)opt->conf_ptr(this) = f;
diff --git a/src/common/config_opts.h b/src/common/config_opts.h
index 9c00432..f2c34fe 100644
--- a/src/common/config_opts.h
+++ b/src/common/config_opts.h
@@ -263,6 +263,10 @@ OPTION(mon_sync_provider_kill_at, OPT_INT, 0)  // kill the sync provider at a sp
 OPTION(mon_sync_requester_kill_at, OPT_INT, 0) // kill the sync requester at a specific point in the work flow
 OPTION(mon_force_quorum_join, OPT_BOOL, false) // force monitor to join quorum even if it has been previously removed from the map
 OPTION(mon_keyvaluedb, OPT_STR, "leveldb")   // type of keyvaluedb backend
+
+// UNSAFE -- TESTING ONLY! Allows addition of a cache tier with preexisting snaps
+OPTION(mon_debug_unsafe_allow_tier_with_nonempty_snaps, OPT_BOOL, false)
+
 OPTION(paxos_stash_full_interval, OPT_INT, 25)   // how often (in commits) to stash a full copy of the PaxosService state
 OPTION(paxos_max_join_drift, OPT_INT, 10) // max paxos iterations before we must first sync the monitor stores
 OPTION(paxos_propose_interval, OPT_DOUBLE, 1.0)  // gather updates for this long before proposing a map update
@@ -564,16 +568,22 @@ OPTION(osd_recover_clone_overlap_limit, OPT_INT, 10)
 OPTION(osd_backfill_scan_min, OPT_INT, 64)
 OPTION(osd_backfill_scan_max, OPT_INT, 512)
 OPTION(osd_op_thread_timeout, OPT_INT, 15)
+OPTION(osd_op_thread_suicide_timeout, OPT_INT, 150)
 OPTION(osd_recovery_thread_timeout, OPT_INT, 30)
+OPTION(osd_recovery_thread_suicide_timeout, OPT_INT, 300)
 OPTION(osd_snap_trim_thread_timeout, OPT_INT, 60*60*1)
+OPTION(osd_snap_trim_thread_suicide_timeout, OPT_INT, 60*60*10)
 OPTION(osd_snap_trim_sleep, OPT_FLOAT, 0)
 OPTION(osd_scrub_thread_timeout, OPT_INT, 60)
+OPTION(osd_scrub_thread_suicide_timeout, OPT_INT, 60)
 OPTION(osd_scrub_finalize_thread_timeout, OPT_INT, 60*10)
 OPTION(osd_scrub_invalid_stats, OPT_BOOL, true)
 OPTION(osd_remove_thread_timeout, OPT_INT, 60*60)
+OPTION(osd_remove_thread_suicide_timeout, OPT_INT, 10*60*60)
 OPTION(osd_command_thread_timeout, OPT_INT, 10*60)
 OPTION(osd_age, OPT_FLOAT, .8)
 OPTION(osd_age_time, OPT_INT, 0)
+OPTION(osd_command_thread_suicide_timeout, OPT_INT, 15*60)
 OPTION(osd_heartbeat_addr, OPT_ADDR, entity_addr_t())
 OPTION(osd_heartbeat_interval, OPT_INT, 6)       // (seconds) how often we ping peers
 OPTION(osd_heartbeat_grace, OPT_INT, 20)         // (seconds) how long before we decide a peer has failed
@@ -858,6 +868,9 @@ OPTION(journal_discard, OPT_BOOL, false) //using ssd disk as journal, whether su
 OPTION(rados_mon_op_timeout, OPT_DOUBLE, 0) // how many seconds to wait for a response from the monitor before returning an error from a rados operation. 0 means on limit.
 OPTION(rados_osd_op_timeout, OPT_DOUBLE, 0) // how many seconds to wait for a response from osds before returning an error from a rados operation. 0 means no limit.
 
+OPTION(rbd_op_threads, OPT_INT, 1)
+OPTION(rbd_op_thread_timeout, OPT_INT, 60)
+OPTION(rbd_non_blocking_aio, OPT_BOOL, true) // process AIO ops from a worker thread to prevent blocking
 OPTION(rbd_cache, OPT_BOOL, true) // whether to enable caching (writeback unless rbd_cache_max_dirty is 0)
 OPTION(rbd_cache_writethrough_until_flush, OPT_BOOL, true) // whether to make writeback caching writethrough until flush is called, to be sure the user of librbd will send flushs so that writeback is safe
 OPTION(rbd_cache_size, OPT_LONGLONG, 32<<20)         // cache size in bytes
@@ -938,6 +951,7 @@ OPTION(rgw_socket_path, OPT_STR, "")   // path to unix domain socket, if not spe
 OPTION(rgw_host, OPT_STR, "")  // host for radosgw, can be an IP, default is 0.0.0.0
 OPTION(rgw_port, OPT_STR, "")  // port to listen, format as "8080" "5000", if not specified, rgw will not run external fcgi
 OPTION(rgw_dns_name, OPT_STR, "")
+OPTION(rgw_content_length_compat, OPT_BOOL, false) // Check both HTTP_CONTENT_LENGTH and CONTENT_LENGTH in fcgi env
 OPTION(rgw_script_uri, OPT_STR, "") // alternative value for SCRIPT_URI if not set in request
 OPTION(rgw_request_uri, OPT_STR,  "") // alternative value for REQUEST_URI if not set in request
 OPTION(rgw_swift_url, OPT_STR, "")             // the swift url, being published by the internal swift auth
diff --git a/src/common/dummy.cc b/src/common/dummy.cc
deleted file mode 100644
index 2626714..0000000
--- a/src/common/dummy.cc
+++ /dev/null
@@ -1,20 +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 Inktank, Inc
- *
- * 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.
- *
- */
-
-/*
- * A dummy file with a .cc extension to make autotools link
- * ceph_test_librbd_fsx with a C++ linker.  An approach w/o a physical
- * dummy.cc recommended in 8.3.5 Libtool Convenience Libraries works,
- * but breaks 'make tags' and friends.
- */
diff --git a/src/common/strtol.cc b/src/common/strtol.cc
index 840b3d9..8a43eb5 100644
--- a/src/common/strtol.cc
+++ b/src/common/strtol.cc
@@ -12,14 +12,12 @@
  *
  */
 
+#include "strtol.h"
+
 #include <errno.h>
 #include <limits.h>
 #include <sstream>
 #include <stdlib.h>
-#include <string>
-extern "C" {
-#include <stdint.h>
-}
 
 using std::ostringstream;
 
@@ -131,10 +129,8 @@ float strict_strtof(const char *str, std::string *err)
 uint64_t strict_sistrtoll(const char *str, std::string *err)
 {
   std::string s(str);
-  if (s.size() == 0) {
-    ostringstream oss;
-    oss << "strict_sistrtoll: value not specified";
-    *err = oss.str();
+  if (s.empty()) {
+    *err = "strict_sistrtoll: value not specified";
     return 0;
   }
   const char &u = s.at(s.size()-1); //str[std::strlen(str)-1];
@@ -161,9 +157,25 @@ uint64_t strict_sistrtoll(const char *str, std::string *err)
     s = std::string(str, s.size()-1);
   v = s.c_str();
 
-  uint64_t r = strict_strtoll(v, 10, err);
+  long long r_ll = strict_strtoll(v, 10, err);
+
+  if (r_ll < 0) {
+    *err = "strict_sistrtoll: value should not be negative";
+    return 0;
+  }
+
+  uint64_t r = r_ll;
   if (err->empty() && m > 0) {
-    r = (r << m);
+    if (r > (std::numeric_limits<uint64_t>::max() >> m)) {
+      *err = "strict_sistrtoll: value seems to be too large";
+      return 0;
+    }
+    r <<= m;
   }
   return r;
 }
+
+template <>
+uint64_t strict_si_cast(const char *str, std::string *err) {
+  return strict_sistrtoll(str, err);
+}
diff --git a/src/common/strtol.h b/src/common/strtol.h
index ea0a469..5575ed7 100644
--- a/src/common/strtol.h
+++ b/src/common/strtol.h
@@ -16,6 +16,7 @@
 #define CEPH_COMMON_STRTOL_H
 
 #include <string>
+#include <limits>
 extern "C" {
 #include <stdint.h>
 }
@@ -30,4 +31,21 @@ float strict_strtof(const char *str, std::string *err);
 
 uint64_t strict_sistrtoll(const char *str, std::string *err);
 
+template <typename Target>
+Target strict_si_cast(const char *str, std::string *err) {
+  uint64_t ret = strict_sistrtoll(str, err);
+  if (!err->empty())
+    return ret;
+  if (ret > (uint64_t)std::numeric_limits<Target>::max()) {
+    err->append("The option value '");
+    err->append(str);
+    err->append("' seems to be too large");
+    return 0;
+  }
+  return ret;
+}
+
+template <>
+uint64_t strict_si_cast(const char *str, std::string *err);
+
 #endif
diff --git a/src/crush/CrushTester.cc b/src/crush/CrushTester.cc
index 5ca4978..9aada7b 100644
--- a/src/crush/CrushTester.cc
+++ b/src/crush/CrushTester.cc
@@ -1,6 +1,7 @@
 
 #include "include/stringify.h"
 #include "CrushTester.h"
+#include "CrushTreeDumper.h"
 
 #include <algorithm>
 #include <stdlib.h>
@@ -357,9 +358,11 @@ void CrushTester::write_integer_indexed_scalar_data_string(vector<string> &dst,
 }
 
 int CrushTester::test_with_crushtool(const string& crushtool,
+                                     int max_id,
                                      int timeout)
 {
   string timeout_string = stringify(timeout);
+  string opt_max_id = stringify(max_id);
   vector<const char *> cmd_args;
   cmd_args.push_back("timeout");
   cmd_args.push_back(timeout_string.c_str());
@@ -367,6 +370,8 @@ int CrushTester::test_with_crushtool(const string& crushtool,
   cmd_args.push_back("-i");
   cmd_args.push_back("-");
   cmd_args.push_back("--test");
+  cmd_args.push_back("--check");
+  cmd_args.push_back(opt_max_id.c_str());
   cmd_args.push_back(NULL);
 
   int pipefds[2];
@@ -430,7 +435,59 @@ int CrushTester::test_with_crushtool(const string& crushtool,
   // something else entirely happened
   // log it and consider an invalid crush map
   err << "error running crushmap through crushtool: " << cpp_strerror(r);
-  return -r;
+  return -EINVAL;
+}
+
+namespace {
+  class BadCrushMap : public std::runtime_error {
+  public:
+    int item;
+    BadCrushMap(const char* msg, int id)
+      : std::runtime_error(msg), item(id) {}
+  };
+  // throws if any node in the crush fail to print
+  class CrushWalker : public CrushTreeDumper::Dumper<void> {
+    typedef void DumbFormatter;
+    typedef CrushTreeDumper::Dumper<DumbFormatter> Parent;
+    unsigned max_id;
+  public:
+    CrushWalker(const CrushWrapper *crush, unsigned max_id)
+      : Parent(crush), max_id(max_id) {}
+    void dump_item(const CrushTreeDumper::Item &qi, DumbFormatter *) {
+      int type = -1;
+      if (qi.is_bucket()) {
+	if (!crush->get_item_name(qi.id)) {
+	  throw BadCrushMap("unknown item name", qi.id);
+	}
+	type = crush->get_bucket_type(qi.id);
+      } else {
+	if (max_id > 0 && qi.id >= (int)max_id) {
+	  throw BadCrushMap("item id too large", qi.id);
+	}
+	type = 0;
+      }
+      if (!crush->get_type_name(type)) {
+	throw BadCrushMap("unknown type name", qi.id);
+      }
+    }
+  };
+}
+
+bool CrushTester::check_name_maps(unsigned max_id) const
+{
+  CrushWalker crush_walker(&crush, max_id);
+  try {
+    // walk through the crush, to see if its self-contained
+    crush_walker.dump(NULL);
+    // and see if the maps is also able to handle straying OSDs, whose id >= 0.
+    // "ceph osd tree" will try to print them, even they are not listed in the
+    // crush map.
+    crush_walker.dump_item(CrushTreeDumper::Item(0, 0, 0), NULL);
+  } catch (const BadCrushMap& e) {
+    err << e.what() << ": item#" << e.item << std::endl;
+    return false;
+  }
+  return true;
 }
 
 int CrushTester::test()
diff --git a/src/crush/CrushTester.h b/src/crush/CrushTester.h
index 09936ce..4f90aae 100644
--- a/src/crush/CrushTester.h
+++ b/src/crush/CrushTester.h
@@ -333,9 +333,18 @@ public:
     min_rule = max_rule = rule;
   }
 
+  /**
+   * check if any bucket/nodes is referencing an unknown name or type
+   * @param max_id rejects any non-bucket items with id less than this number,
+   *               pass 0 to disable this check
+   * @return false if an dangling name/type is referenced or an item id is too
+   *         large, true otherwise
+   */
+  bool check_name_maps(unsigned max_id = 0) const;
   int test();
   int test_with_crushtool(const string& crushtool,
-			  int timeout);
+			  int max_id = -1,
+			  int timeout = 0);
 };
 
 #endif
diff --git a/src/crush/CrushWrapper.cc b/src/crush/CrushWrapper.cc
index 497c219..4dcf6b8 100644
--- a/src/crush/CrushWrapper.cc
+++ b/src/crush/CrushWrapper.cc
@@ -192,6 +192,9 @@ bool CrushWrapper::_maybe_remove_last_instance(CephContext *cct, int item, bool
   if (_search_item_exists(item)) {
     return false;
   }
+  if (item < 0 && _bucket_is_in_use(cct, item)) {
+    return false;
+  }
 
   if (item < 0 && !unlink_only) {
     crush_bucket *t = get_bucket(item);
@@ -219,6 +222,9 @@ int CrushWrapper::remove_item(CephContext *cct, int item, bool unlink_only)
 		    << " items, not empty" << dendl;
       return -ENOTEMPTY;
     }
+    if (_bucket_is_in_use(cct, item)) {
+      return -EBUSY;
+    }
   }
 
   for (int i = 0; i < crush->max_buckets; i++) {
@@ -258,6 +264,22 @@ bool CrushWrapper::_search_item_exists(int item) const
   return false;
 }
 
+bool CrushWrapper::_bucket_is_in_use(CephContext *cct, int item)
+{
+  for (unsigned i = 0; i < crush->max_rules; ++i) {
+    crush_rule *r = crush->rules[i];
+    if (!r)
+      continue;
+    for (unsigned j = 0; j < r->len; ++j) {
+      if (r->steps[j].op == CRUSH_RULE_TAKE &&
+	  r->steps[j].arg1 == item) {
+	return true;
+      }
+    }
+  }
+  return false;
+}
+
 int CrushWrapper::_remove_item_under(CephContext *cct, int item, int ancestor, bool unlink_only)
 {
   ldout(cct, 5) << "_remove_item_under " << item << " under " << ancestor
@@ -293,6 +315,11 @@ int CrushWrapper::remove_item_under(CephContext *cct, int item, int ancestor, bo
 {
   ldout(cct, 5) << "remove_item_under " << item << " under " << ancestor
 		<< (unlink_only ? " unlink_only":"") << dendl;
+
+  if (!unlink_only && _bucket_is_in_use(cct, item)) {
+    return -EBUSY;
+  }
+
   int ret = _remove_item_under(cct, item, ancestor, unlink_only);
   if (ret < 0)
     return ret;
@@ -1409,6 +1436,56 @@ void CrushWrapper::dump(Formatter *f) const
   f->close_section();
 }
 
+namespace {
+  // depth first walker
+  class TreeDumper {
+    typedef CrushTreeDumper::Item Item;
+    const CrushWrapper *crush;
+  public:
+    TreeDumper(const CrushWrapper *crush)
+      : crush(crush) {}
+
+    void dump(Formatter *f) {
+      set<int> roots;
+      crush->find_roots(roots);
+      for (set<int>::iterator root = roots.begin(); root != roots.end(); ++root) {
+	dump_item(Item(*root, 0, crush->get_bucket_weightf(*root)), f);
+      }
+    }
+
+  private:
+    void dump_item(const Item& qi, Formatter* f) {
+      if (qi.is_bucket()) {
+	f->open_object_section("bucket");
+	CrushTreeDumper::dump_item_fields(crush, qi, f);
+	dump_bucket_children(qi, f);
+	f->close_section();
+      } else {
+	f->open_object_section("device");
+	CrushTreeDumper::dump_item_fields(crush, qi, f);
+	f->close_section();
+      }
+    }
+
+    void dump_bucket_children(const Item& parent, Formatter* f) {
+      f->open_array_section("items");
+      const int max_pos = crush->get_bucket_size(parent.id);
+      for (int pos = 0; pos < max_pos; pos++) {
+	int id = crush->get_bucket_item(parent.id, pos);
+	float weight = crush->get_bucket_item_weightf(parent.id, pos);
+	dump_item(Item(id, parent.depth + 1, weight), f);
+      }
+      f->close_section();
+    }
+  };
+}
+
+void CrushWrapper::dump_tree(Formatter *f) const
+{
+  assert(f);
+  TreeDumper(this).dump(f);
+}
+
 void CrushWrapper::dump_tunables(Formatter *f) const
 {
   f->dump_int("choose_local_tries", get_choose_local_tries());
diff --git a/src/crush/CrushWrapper.h b/src/crush/CrushWrapper.h
index cfafab0..c76fac3 100644
--- a/src/crush/CrushWrapper.h
+++ b/src/crush/CrushWrapper.h
@@ -587,6 +587,7 @@ public:
 private:
   bool _maybe_remove_last_instance(CephContext *cct, int id, bool unlink_only);
   int _remove_item_under(CephContext *cct, int id, int ancestor, bool unlink_only);
+  bool _bucket_is_in_use(CephContext *cct, int id);
 public:
   int remove_item_under(CephContext *cct, int id, int ancestor, bool unlink_only);
 
@@ -1054,6 +1055,7 @@ public:
   void dump_tunables(Formatter *f) const;
   void list_rules(Formatter *f) const;
   void dump_tree(ostream *out, Formatter *f) const;
+  void dump_tree(Formatter *f) const;
   static void generate_test_instances(list<CrushWrapper*>& o);
 
   int get_osd_pool_default_crush_replicated_ruleset(CephContext *cct);
diff --git a/src/crush/mapper.c b/src/crush/mapper.c
index 251ab4a..916790d 100644
--- a/src/crush/mapper.c
+++ b/src/crush/mapper.c
@@ -839,8 +839,15 @@ int crush_do_rule(const struct crush_map *map,
 
 		switch (curstep->op) {
 		case CRUSH_RULE_TAKE:
-			w[0] = curstep->arg1;
-			wsize = 1;
+			if ((curstep->arg1 >= 0 &&
+			     curstep->arg1 < map->max_devices) ||
+			    (-1-curstep->arg1 < map->max_buckets &&
+			     map->buckets[-1-curstep->arg1])) {
+				w[0] = curstep->arg1;
+				wsize = 1;
+			} else {
+				dprintk(" bad take value %d\n", curstep->arg1);
+			}
 			break;
 
 		case CRUSH_RULE_SET_CHOOSE_TRIES:
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
index 5f57ee0..ef2e0ae 100644
--- a/src/include/Makefile.am
+++ b/src/include/Makefile.am
@@ -103,6 +103,7 @@ noinst_HEADERS += \
 	include/rbd/features.h \
 	include/rbd/librbd.h \
 	include/rbd/librbd.hpp\
+	include/rbd/object_map_types.h \
 	include/util.h\
 	include/stat.h \
 	include/on_exit.h \
diff --git a/src/include/interval_set.h b/src/include/interval_set.h
index 7affb87..9a7d2f2 100644
--- a/src/include/interval_set.h
+++ b/src/include/interval_set.h
@@ -371,6 +371,7 @@ class interval_set {
   
   void erase(iterator &i) {
     _size -= i.get_len();
+    assert(_size >= 0);
     m.erase(i._iter);
   }
 
diff --git a/src/include/krbd.h b/src/include/krbd.h
index 702a76d..d7e868c 100644
--- a/src/include/krbd.h
+++ b/src/include/krbd.h
@@ -13,14 +13,15 @@
 #ifndef CEPH_KRBD_H
 #define CEPH_KRBD_H
 
+#include "rados/librados.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 struct krbd_ctx;
-struct CephContext;
 
-int krbd_create_from_context(struct CephContext *cct, struct krbd_ctx **pctx);
+int krbd_create_from_context(rados_config_t cct, struct krbd_ctx **pctx);
 void krbd_destroy(struct krbd_ctx *ctx);
 
 int krbd_map(struct krbd_ctx *ctx, const char *pool, const char *image,
@@ -38,7 +39,7 @@ namespace ceph {
   class Formatter;
 }
 
-int krbd_showmapped(struct krbd_ctx *ctx, Formatter *f);
+int krbd_showmapped(struct krbd_ctx *ctx, ceph::Formatter *f);
 
 #endif /* __cplusplus */
 
diff --git a/src/include/rados/librados.h b/src/include/rados/librados.h
index d9ad19e..5c56191 100644
--- a/src/include/rados/librados.h
+++ b/src/include/rados/librados.h
@@ -81,6 +81,7 @@ enum {
   // indicate read/write data will not accessed again (by *this* client)
   LIBRADOS_OP_FLAG_FADVISE_NOCACHE    = 0x40,
 };
+/** @endcond */
 
 #if __GNUC__ >= 4
   #define CEPH_RADOS_API  __attribute__ ((visibility ("default")))
diff --git a/src/include/rbd/object_map_types.h b/src/include/rbd/object_map_types.h
new file mode 100644
index 0000000..7776232
--- /dev/null
+++ b/src/include/rbd/object_map_types.h
@@ -0,0 +1,12 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+#ifndef CEPH_RBD_OBJECT_MAP_TYPES_H
+#define CEPH_RBD_OBJECT_MAP_TYPES_H
+
+#include "include/int_types.h"
+
+static const uint8_t OBJECT_NONEXISTENT  = 0;
+static const uint8_t OBJECT_EXISTS       = 1;
+static const uint8_t OBJECT_PENDING      = 2;
+
+#endif // CEPH_RBD_OBJECT_MAP_TYPES_H
diff --git a/src/json_spirit/json_spirit_reader_template.h b/src/json_spirit/json_spirit_reader_template.h
index f87b593..c50f885 100644
--- a/src/json_spirit/json_spirit_reader_template.h
+++ b/src/json_spirit/json_spirit_reader_template.h
@@ -13,6 +13,8 @@
 #include "json_spirit_value.h"
 #include "json_spirit_error_position.h"
 
+#include "common/utf8.h"
+
 #define BOOST_SPIRIT_THREADSAFE  // uncomment for multithreaded use, requires linking to boost.thread
 
 #include <boost/bind.hpp>
@@ -71,18 +73,30 @@ namespace json_spirit
         return ( hex_to_num( c1 ) << 4 ) + hex_to_num( c2 );
     }       
 
-    template< class Char_type, class Iter_type >
-    Char_type unicode_str_to_char( Iter_type& begin )
+    template< class String_type, class Iter_type >
+    String_type unicode_str_to_utf8( Iter_type& begin );
+
+    template<>
+    std::string unicode_str_to_utf8( std::string::const_iterator & begin )
     {
+        typedef std::string::value_type Char_type;
+
         const Char_type c1( *( ++begin ) );
         const Char_type c2( *( ++begin ) );
         const Char_type c3( *( ++begin ) );
         const Char_type c4( *( ++begin ) );
 
-        return ( hex_to_num( c1 ) << 12 ) + 
-               ( hex_to_num( c2 ) <<  8 ) + 
-               ( hex_to_num( c3 ) <<  4 ) + 
-               hex_to_num( c4 );
+        unsigned long uc = ( hex_to_num( c1 ) << 12 ) + 
+                           ( hex_to_num( c2 ) <<  8 ) + 
+                           ( hex_to_num( c3 ) <<  4 ) + 
+                           hex_to_num( c4 );
+
+        unsigned char buf[7];  // MAX_UTF8_SZ is 6 (see src/common/utf8.c)
+        int r = encode_utf8(uc, buf);
+        if (r >= 0) {
+            return std::string(reinterpret_cast<char *>(buf), r);
+        }
+        return std::string("_");
     }
 
     template< class String_type >
@@ -116,7 +130,7 @@ namespace json_spirit
             {
                 if( end - begin >= 5 )  //  expecting "uHHHH..."
                 {
-                    s += unicode_str_to_char< Char_type >( begin );  
+                    s += unicode_str_to_utf8< String_type >( begin );
                 }
                 break;
             }
@@ -178,11 +192,15 @@ namespace json_spirit
         return get_str_< std::string >( begin, end );
     }
 
+// Need this guard else it tries to instantiate unicode_str_to_utf8 with a
+// std::wstring, which isn't presently implemented
+#if defined( JSON_SPIRIT_WMVALUE_ENABLED ) && !defined( BOOST_NO_STD_WSTRING )
     inline std::wstring get_str( std::wstring::const_iterator begin, std::wstring::const_iterator end )
     {
         return get_str_< std::wstring >( begin, end );
     }
-    
+#endif
+
     template< class String_type, class Iter_type >
     String_type get_str( Iter_type begin, Iter_type end )
     {
diff --git a/src/krbd.cc b/src/krbd.cc
index 04f4004..3fb64fd 100644
--- a/src/krbd.cc
+++ b/src/krbd.cc
@@ -34,6 +34,7 @@
 #include "common/TextTable.h"
 #include "include/assert.h"
 #include "include/stringify.h"
+#include "include/krbd.h"
 #include "mon/MonMap.h"
 
 #include <blkid/blkid.h>
@@ -582,12 +583,12 @@ int dump_images(struct krbd_ctx *ctx, Formatter *f)
   return r;
 }
 
-extern "C" int krbd_create_from_context(struct CephContext *cct,
+extern "C" int krbd_create_from_context(rados_config_t cct,
                                         struct krbd_ctx **pctx)
 {
   struct krbd_ctx *ctx = new struct krbd_ctx();
 
-  ctx->cct = cct;
+  ctx->cct = reinterpret_cast<CephContext *>(cct);
   ctx->udev = udev_new();
   if (!ctx->udev) {
     delete ctx;
diff --git a/src/librbd/AioCompletion.cc b/src/librbd/AioCompletion.cc
index 8c38e1c..2663e74 100644
--- a/src/librbd/AioCompletion.cc
+++ b/src/librbd/AioCompletion.cc
@@ -5,6 +5,7 @@
 
 #include "common/ceph_context.h"
 #include "common/dout.h"
+#include "common/errno.h"
 
 #include "librbd/AioRequest.h"
 #include "librbd/internal.h"
@@ -63,11 +64,11 @@ namespace librbd {
     }
   }
 
-  void AioCompletion::complete() {
+  void AioCompletion::complete(CephContext *cct) {
     tracepoint(librbd, aio_complete_enter, this, rval);
     utime_t elapsed;
     assert(lock.is_locked());
-    elapsed = ceph_clock_now(ictx->cct) - start_time;
+    elapsed = ceph_clock_now(cct) - start_time;
     switch (aio_type) {
     case AIO_TYPE_READ:
       ictx->perfcounter->tinc(l_librbd_aio_rd_latency, elapsed); break;
@@ -78,12 +79,14 @@ namespace librbd {
     case AIO_TYPE_FLUSH:
       ictx->perfcounter->tinc(l_librbd_aio_flush_latency, elapsed); break;
     default:
-      lderr(ictx->cct) << "completed invalid aio_type: " << aio_type << dendl;
+      lderr(cct) << "completed invalid aio_type: " << aio_type << dendl;
       break;
     }
 
     // note: possible for image to be closed after op marked finished
-    async_op.finish_op();
+    if (async_op.started()) {
+      async_op.finish_op();
+    }
 
     if (complete_cb) {
       complete_cb(rbd_comp, complete_arg);
@@ -93,6 +96,17 @@ namespace librbd {
     tracepoint(librbd, aio_complete_exit);
   }
 
+  void AioCompletion::fail(CephContext *cct, int r)
+  {
+    lderr(cct) << "AioCompletion::fail() " << this << ": " << cpp_strerror(r)
+               << dendl;
+    lock.Lock();
+    assert(pending_count == 0);
+    rval = r;
+    complete(cct);
+    put_unlock();
+  }
+
   void AioCompletion::complete_request(CephContext *cct, ssize_t r)
   {
     ldout(cct, 20) << "AioCompletion::complete_request() "
@@ -109,7 +123,7 @@ namespace librbd {
     int count = --pending_count;
     if (!count && blockers == 0) {
       finalize(cct, rval);
-      complete();
+      complete(cct);
     }
     put_unlock();
   }
diff --git a/src/librbd/AioCompletion.h b/src/librbd/AioCompletion.h
index cef8388..bd527b1 100644
--- a/src/librbd/AioCompletion.h
+++ b/src/librbd/AioCompletion.h
@@ -98,7 +98,9 @@ namespace librbd {
       }
     }
 
-    void complete();
+    void fail(CephContext *cct, int r);
+
+    void complete(CephContext *cct);
 
     void set_complete_cb(void *cb_arg, callback_t cb) {
       complete_cb = cb;
@@ -145,7 +147,7 @@ namespace librbd {
       --blockers;
       if (pending_count == 0 && blockers == 0) {
         finalize(cct, rval);
-        complete();
+        complete(cct);
       }
     }
   };
diff --git a/src/librbd/AioRequest.cc b/src/librbd/AioRequest.cc
index 3bbbab9..d52cd5d 100644
--- a/src/librbd/AioRequest.cc
+++ b/src/librbd/AioRequest.cc
@@ -76,15 +76,8 @@ namespace librbd {
 			   << " parent completion " << m_parent_completion
 			   << " extents " << image_extents
 			   << dendl;
-    int r = aio_read(m_ictx->parent, image_extents, NULL, &m_read_data,
-	             m_parent_completion, 0);
-    if (r < 0) {
-      lderr(m_ictx->cct) << "read_from_parent " << this
-                         << ": error reading from parent: "
-                         << cpp_strerror(r) << dendl;
-      m_parent_completion->release();
-      complete(r);
-    }
+    aio_read(m_ictx->parent, image_extents, NULL, &m_read_data,
+             m_parent_completion, 0);
   }
 
   static inline bool is_copy_on_read(ImageCtx *ictx, librados::snap_t snap_id) {
@@ -238,13 +231,14 @@ namespace librbd {
     return finished;
   }
 
-  int AioRead::send() {
-    ldout(m_ictx->cct, 20) << "send " << this << " " << m_oid << " " << m_object_off << "~" << m_object_len << dendl;
+  void AioRead::send() {
+    ldout(m_ictx->cct, 20) << "send " << this << " " << m_oid << " "
+                           << m_object_off << "~" << m_object_len << dendl;
 
     // send read request to parent if the object doesn't exist locally
     if (!m_ictx->object_map.object_may_exist(m_object_no)) {
       complete(-ENOENT);
-      return 0;
+      return;
     }
 
     librados::AioCompletion *rados_completion =
@@ -261,8 +255,9 @@ namespace librbd {
     op.set_op_flags2(m_op_flags);
 
     r = m_ictx->data_ctx.aio_operate(m_oid, rados_completion, &op, flags, NULL);
+    assert(r == 0);
+
     rados_completion->release();
-    return r;
   }
 
   /** write **/
@@ -441,16 +436,13 @@ namespace librbd {
     return finished;
   }
 
-  int AbstractWrite::send() {
+  void AbstractWrite::send() {
     ldout(m_ictx->cct, 20) << "send " << this << " " << m_oid << " "
 			   << m_object_off << "~" << m_object_len << dendl;
 
-    if (send_pre()) {
-      return 0;
-    } else {
+    if (!send_pre()) {
       send_write();
     }
-    return 0;
   }
 
   bool AbstractWrite::send_pre() {
diff --git a/src/librbd/AioRequest.h b/src/librbd/AioRequest.h
index 60be8fc..bac3b47 100644
--- a/src/librbd/AioRequest.h
+++ b/src/librbd/AioRequest.h
@@ -37,7 +37,7 @@ namespace librbd {
     void complete(int r);
 
     virtual bool should_complete(int r) = 0;
-    virtual int send() = 0;
+    virtual void send() = 0;
 
   protected:
     void read_from_parent(vector<pair<uint64_t,uint64_t> >& image_extents,
@@ -63,7 +63,7 @@ namespace librbd {
 	    Context *completion, int op_flags);
     virtual ~AioRead() {}
     virtual bool should_complete(int r);
-    virtual int send();
+    virtual void send();
     void guard_read();
 
     ceph::bufferlist &data() {
@@ -118,7 +118,7 @@ namespace librbd {
 		  bool hide_enoent);
     virtual ~AbstractWrite() {}
     virtual bool should_complete(int r);
-    virtual int send();
+    virtual void send();
 
     bool has_parent() const {
       return !m_object_image_extents.empty();
diff --git a/src/librbd/AsyncFlattenRequest.cc b/src/librbd/AsyncFlattenRequest.cc
index 87c2655..ebaf511 100644
--- a/src/librbd/AsyncFlattenRequest.cc
+++ b/src/librbd/AsyncFlattenRequest.cc
@@ -71,8 +71,7 @@ public:
     AioWrite *req = new AioWrite(&m_image_ctx, oid, m_object_no, 0, objectx,
                                  object_overlap, bl, m_snapc, CEPH_NOSNAP,
                                  this);
-    int r = req->send();
-    assert(r == 0);
+    req->send();
     return 0;
   }
 
diff --git a/src/librbd/AsyncOperation.h b/src/librbd/AsyncOperation.h
index 2ca2aec..e6c8849 100644
--- a/src/librbd/AsyncOperation.h
+++ b/src/librbd/AsyncOperation.h
@@ -26,6 +26,10 @@ public:
     assert(!m_xlist_item.is_on_list());
   }
 
+  inline bool started() const {
+    return m_xlist_item.is_on_list();
+  }
+
   void start_op(ImageCtx &image_ctx);
   void finish_op();
 
diff --git a/src/librbd/AsyncTrimRequest.cc b/src/librbd/AsyncTrimRequest.cc
index d3dcd81..cb4764a 100644
--- a/src/librbd/AsyncTrimRequest.cc
+++ b/src/librbd/AsyncTrimRequest.cc
@@ -289,12 +289,7 @@ bool AsyncTrimRequest::send_clean_boundary() {
                                 objectx, object_overlap, snapc, CEPH_NOSNAP,
                                 req_comp);
         }
-        int r = req->send();
-        if (r < 0) {
-          req_comp->complete(r);
-          delete req;
-          break;
-        }
+        req->send();
       }
     }
 
diff --git a/src/librbd/CopyupRequest.cc b/src/librbd/CopyupRequest.cc
index a58ec84..3d780c6 100644
--- a/src/librbd/CopyupRequest.cc
+++ b/src/librbd/CopyupRequest.cc
@@ -91,15 +91,7 @@ namespace librbd {
 			   << ", oid " << m_oid
                            << ", extents " << m_image_extents
                            << dendl;
-    int r = aio_read(m_ictx->parent, m_image_extents, NULL, &m_copyup_data,
-		     comp, 0);
-    if (r < 0) {
-      lderr(m_ictx->cct) << __func__ << " " << this
-                         << ": error reading from parent: "
-                         << cpp_strerror(r) << dendl;
-      comp->release();
-      complete(r);
-    }
+    aio_read(m_ictx->parent, m_image_extents, NULL, &m_copyup_data, comp, 0);
   }
 
   void CopyupRequest::queue_send()
diff --git a/src/librbd/ImageCtx.cc b/src/librbd/ImageCtx.cc
index 2b1dd0a..a68a906 100644
--- a/src/librbd/ImageCtx.cc
+++ b/src/librbd/ImageCtx.cc
@@ -6,6 +6,7 @@
 #include "common/dout.h"
 #include "common/errno.h"
 #include "common/perf_counters.h"
+#include "common/WorkQueue.h"
 
 #include "librbd/AsyncOperation.h"
 #include "librbd/AsyncRequest.h"
@@ -32,6 +33,23 @@ using librados::snap_t;
 using librados::IoCtx;
 
 namespace librbd {
+
+namespace {
+
+class ThreadPoolSingleton : public ThreadPool {
+public:
+  ThreadPoolSingleton(CephContext *cct)
+    : ThreadPool(cct, "librbd::thread_pool", cct->_conf->rbd_op_threads,
+                 "rbd_op_threads") {
+    start();
+  }
+  virtual ~ThreadPoolSingleton() {
+    stop();
+  }
+};
+
+} // anonymous namespace
+
   ImageCtx::ImageCtx(const string &image_name, const string &image_id,
 		     const char *snap, IoCtx& p, bool ro)
     : cct((CephContext*)p.cct()),
@@ -63,7 +81,7 @@ namespace librbd {
       object_cacher(NULL), writeback_handler(NULL), object_set(NULL),
       readahead(),
       total_bytes_read(0), copyup_finisher(NULL),
-      object_map(*this)
+      object_map(*this), aio_work_queue(NULL)
   {
     md_ctx.dup(p);
     data_ctx.dup(p);
@@ -113,6 +131,13 @@ namespace librbd {
       copyup_finisher = new Finisher(cct);
       copyup_finisher->start();
     }
+
+    ThreadPoolSingleton *thread_pool_singleton;
+    cct->lookup_or_create_singleton_object<ThreadPoolSingleton>(
+      thread_pool_singleton, "librbd::thread_pool");
+    aio_work_queue = new ContextWQ("librbd::aio_work_queue",
+                                   cct->_conf->rbd_op_thread_timeout,
+                                   thread_pool_singleton);
   }
 
   ImageCtx::~ImageCtx() {
@@ -134,6 +159,8 @@ namespace librbd {
       copyup_finisher = NULL;
     }
     delete[] format_string;
+
+    delete aio_work_queue;
   }
 
   int ImageCtx::init() {
diff --git a/src/librbd/ImageCtx.h b/src/librbd/ImageCtx.h
index 22f3b80..47134e2 100644
--- a/src/librbd/ImageCtx.h
+++ b/src/librbd/ImageCtx.h
@@ -31,6 +31,7 @@
 #include "librbd/parent_types.h"
 
 class CephContext;
+class ContextWQ;
 class Finisher;
 class PerfCounters;
 
@@ -130,6 +131,8 @@ namespace librbd {
 
     xlist<AsyncResizeRequest*> async_resize_reqs;
 
+    ContextWQ *aio_work_queue;
+
     /**
      * Either image_name or image_id must be set.
      * If id is not known, pass the empty std::string,
diff --git a/src/librbd/ImageWatcher.cc b/src/librbd/ImageWatcher.cc
index c335176..9962f48 100644
--- a/src/librbd/ImageWatcher.cc
+++ b/src/librbd/ImageWatcher.cc
@@ -56,8 +56,13 @@ ImageWatcher::~ImageWatcher()
 }
 
 bool ImageWatcher::is_lock_supported() const {
-  assert(m_image_ctx.owner_lock.is_locked());
   RWLock::RLocker l(m_image_ctx.snap_lock);
+  return is_lock_supported(m_image_ctx.snap_lock);
+}
+
+bool ImageWatcher::is_lock_supported(const RWLock &) const {
+  assert(m_image_ctx.owner_lock.is_locked());
+  assert(m_image_ctx.snap_lock.is_locked());
   uint64_t snap_features;
   m_image_ctx.get_features(m_image_ctx.snap_id, &snap_features);
   return ((snap_features & RBD_FEATURE_EXCLUSIVE_LOCK) != 0 &&
@@ -178,8 +183,8 @@ int ImageWatcher::try_lock() {
   return 0;
 }
 
-int ImageWatcher::request_lock(
-    const boost::function<int(AioCompletion*)>& restart_op, AioCompletion* c) {
+void ImageWatcher::request_lock(
+    const boost::function<void(AioCompletion*)>& restart_op, AioCompletion* c) {
   assert(m_image_ctx.owner_lock.is_locked());
   assert(m_lock_owner_state == LOCK_OWNER_STATE_NOT_LOCKED);
 
@@ -192,7 +197,7 @@ int ImageWatcher::request_lock(
     c->get();
     m_aio_requests.push_back(std::make_pair(restart_op, c));
     if (request_pending) {
-      return 0;
+      return;
     }
   }
 
@@ -205,7 +210,6 @@ int ImageWatcher::request_lock(
       boost::bind(&ImageWatcher::notify_request_lock, this));
     m_task_finisher->queue(TASK_CODE_REQUEST_LOCK, ctx);
   }
-  return 0;
 }
 
 bool ImageWatcher::try_request_lock() {
diff --git a/src/librbd/ImageWatcher.h b/src/librbd/ImageWatcher.h
index ba126ac..19155ae 100644
--- a/src/librbd/ImageWatcher.h
+++ b/src/librbd/ImageWatcher.h
@@ -31,14 +31,15 @@ namespace librbd {
     ~ImageWatcher();
 
     bool is_lock_supported() const;
+    bool is_lock_supported(const RWLock &snap_lock) const;
     bool is_lock_owner() const;
 
     int register_watch();
     int unregister_watch();
 
     int try_lock();
-    int request_lock(const boost::function<int(AioCompletion*)>& restart_op,
-		     AioCompletion* c);
+    void request_lock(const boost::function<void(AioCompletion*)>& restart_op,
+		      AioCompletion* c);
     void prepare_unlock();
     void cancel_unlock();
     int unlock();
@@ -80,7 +81,7 @@ namespace librbd {
     };
 
     typedef std::pair<Context *, ProgressContext *> AsyncRequest;
-    typedef std::pair<boost::function<int(AioCompletion *)>,
+    typedef std::pair<boost::function<void(AioCompletion *)>,
 		      AioCompletion *> AioRequest;
 
     class Task {
diff --git a/src/librbd/ObjectMap.cc b/src/librbd/ObjectMap.cc
index 8099a91..c2ca798 100644
--- a/src/librbd/ObjectMap.cc
+++ b/src/librbd/ObjectMap.cc
@@ -274,6 +274,7 @@ void ObjectMap::aio_resize(uint64_t new_size, uint8_t default_object_state,
 			   Context *on_finish) {
   assert(m_image_ctx.test_features(RBD_FEATURE_OBJECT_MAP));
   assert(m_image_ctx.owner_lock.is_locked());
+  assert(m_image_ctx.image_watcher != NULL);
   assert(m_image_ctx.image_watcher->is_lock_owner());
 
   ResizeRequest *req = new ResizeRequest(
@@ -296,7 +297,9 @@ bool ObjectMap::aio_update(uint64_t start_object_no, uint64_t end_object_no,
 {
   assert(m_image_ctx.test_features(RBD_FEATURE_OBJECT_MAP));
   assert(m_image_ctx.owner_lock.is_locked());
+  assert(m_image_ctx.image_watcher != NULL);
   assert(m_image_ctx.image_watcher->is_lock_owner());
+  assert(start_object_no < end_object_no);
 
   RWLock::WLocker l(m_image_ctx.object_map_lock);
   assert(start_object_no < end_object_no);
@@ -338,13 +341,26 @@ void ObjectMap::invalidate() {
   m_image_ctx.update_flags(m_image_ctx.snap_id, RBD_FLAG_OBJECT_MAP_INVALID,
                            true);
 
+  // do not update on-disk flags if not image owner
+  if (m_image_ctx.image_watcher == NULL ||
+      (m_image_ctx.image_watcher->is_lock_supported(m_image_ctx.snap_lock) &&
+       !m_image_ctx.image_watcher->is_lock_owner())) {
+    return;
+  }
+
   librados::ObjectWriteOperation op;
+  if (m_image_ctx.snap_id == CEPH_NOSNAP) {
+    m_image_ctx.image_watcher->assert_header_locked(&op);
+  }
   cls_client::set_flags(&op, m_image_ctx.snap_id, m_image_ctx.flags,
                         RBD_FLAG_OBJECT_MAP_INVALID);
 
   int r = m_image_ctx.md_ctx.operate(m_image_ctx.header_oid, &op);
-  if (r < 0) {
-    lderr(cct) << "failed to invalidate object map: " << cpp_strerror(r)
+  if (r == -EBUSY) {
+    ldout(cct, 5) << "skipping on-disk object map invalidation: "
+                  << "image not locked by client" << dendl;
+  } else if (r < 0) {
+    lderr(cct) << "failed to invalidate on-disk object map: " << cpp_strerror(r)
 	       << dendl;
   }
 }
@@ -403,6 +419,7 @@ bool ObjectMap::Request::invalidate() {
   m_image_ctx.flags |= RBD_FLAG_OBJECT_MAP_INVALID;
 
   librados::ObjectWriteOperation op;
+  m_image_ctx.image_watcher->assert_header_locked(&op);
   cls_client::set_flags(&op, CEPH_NOSNAP, m_image_ctx.flags,
                         RBD_FLAG_OBJECT_MAP_INVALID);
 
diff --git a/src/librbd/ObjectMap.h b/src/librbd/ObjectMap.h
index 596f5cf..44709b8 100644
--- a/src/librbd/ObjectMap.h
+++ b/src/librbd/ObjectMap.h
@@ -5,6 +5,7 @@
 
 #include "include/int_types.h"
 #include "include/rados/librados.hpp"
+#include "include/rbd/object_map_types.h"
 #include "common/bit_vector.hpp"
 #include "librbd/AsyncRequest.h"
 #include <boost/optional.hpp>
@@ -13,10 +14,6 @@ class Context;
 
 namespace librbd {
 
-static const uint8_t OBJECT_NONEXISTENT = 0;
-static const uint8_t OBJECT_EXISTS = 1;
-static const uint8_t OBJECT_PENDING = 2;
-
 class ImageCtx;
 
 class ObjectMap {
@@ -58,6 +55,10 @@ private:
     }
 
   protected:
+
+    virtual bool safely_cancel(int r) {
+      return false;
+    }
     virtual bool should_complete(int r);
     virtual int filter_return_code(int r) {
       // never propagate an error back to the caller
diff --git a/src/librbd/TaskFinisher.h b/src/librbd/TaskFinisher.h
index 14dcd30..4942a38 100644
--- a/src/librbd/TaskFinisher.h
+++ b/src/librbd/TaskFinisher.h
@@ -35,6 +35,7 @@ public:
       delete m_safe_timer;
     }
 
+    m_finisher->wait_for_empty();
     m_finisher->stop();
     delete m_finisher;
   }
diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc
index ba6722d..15ea416 100644
--- a/src/librbd/internal.cc
+++ b/src/librbd/internal.cc
@@ -10,6 +10,7 @@
 #include "common/errno.h"
 #include "common/ContextCompletion.h"
 #include "common/Throttle.h"
+#include "common/WorkQueue.h"
 #include "cls/lock/cls_lock_client.h"
 #include "include/stringify.h"
 
@@ -1619,7 +1620,6 @@ reprotect_and_return_err:
         close_image(ictx);
         return -EBUSY;
       }
-      assert(watchers.size() == 1);
 
       ictx->md_lock.get_read();
       trim_image(ictx, 0, prog_ctx);
@@ -2293,13 +2293,7 @@ reprotect_and_return_err:
 
       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, 0);
-      if (r < 0) {
-	ctx->complete(r);
-	comp->release();
-	lderr(m_dest->cct) << "error writing to destination image at offset "
-			   << m_offset << ": " << cpp_strerror(r) << dendl;
-      }
+      aio_write(m_dest, m_offset, m_bl->length(), m_bl->c_str(), comp, 0);
     }
   private:
     SimpleThrottle *m_throttle;
@@ -2328,20 +2322,15 @@ reprotect_and_return_err:
     SimpleThrottle throttle(cct->_conf->rbd_concurrent_management_ops, false);
     uint64_t period = src->get_stripe_period();
     for (uint64_t offset = 0; offset < src_size; offset += period) {
+      if (throttle.pending_error()) {
+        return throttle.wait_for_ret();
+      }
+
       uint64_t len = min(period, src_size - offset);
       bufferlist *bl = new bufferlist();
       Context *ctx = new C_CopyRead(&throttle, dest, offset, bl);
       AioCompletion *comp = aio_create_completion_internal(ctx, rbd_ctx_cb);
-      r = aio_read(src, offset, len, NULL, bl, comp, 0);
-      if (r < 0) {
-	ctx->complete(r);
-	comp->release();
-	throttle.wait_for_ret();
-	lderr(cct) << "could not read from source image from "
-		   << offset << " to " << offset + len << ": "
-		   << cpp_strerror(r) << dendl;
-	return r;
-      }
+      aio_read(src, offset, len, NULL, bl, comp, 0);
       prog_ctx.update_progress(offset, src_size);
     }
 
@@ -2472,6 +2461,8 @@ reprotect_and_return_err:
       }
     }
 
+    ictx->aio_work_queue->drain();
+
     ictx->cancel_async_requests();
     ictx->readahead.wait_for_pending();
     if (ictx->object_cacher) {
@@ -2790,12 +2781,7 @@ reprotect_and_return_err:
 
       Context *ctx = new C_SafeCond(&mylock, &cond, &done, &ret);
       AioCompletion *c = aio_create_completion_internal(ctx, rbd_ctx_cb);
-      r = aio_read(ictx, off, read_len, NULL, &bl, c, 0);
-      if (r < 0) {
-	c->release();
-	delete ctx;
-	return r;
-      }
+      aio_read(ictx, off, read_len, NULL, &bl, c, 0);
 
       mylock.Lock();
       while (!done)
@@ -3028,12 +3014,7 @@ reprotect_and_return_err:
 
     Context *ctx = new C_SafeCond(&mylock, &cond, &done, &ret);
     AioCompletion *c = aio_create_completion_internal(ctx, rbd_ctx_cb);
-    int r = aio_read(ictx, image_extents, buf, pbl, c, op_flags);
-    if (r < 0) {
-      c->release();
-      delete ctx;
-      return r;
-    }
+    aio_read(ictx, image_extents, buf, pbl, c, op_flags);
 
     mylock.Lock();
     while (!done)
@@ -3065,12 +3046,7 @@ reprotect_and_return_err:
 
     Context *ctx = new C_SafeCond(&mylock, &cond, &done, &ret);
     AioCompletion *c = aio_create_completion_internal(ctx, rbd_ctx_cb);
-    r = aio_write(ictx, off, mylen, buf, c, op_flags);
-    if (r < 0) {
-      c->release();
-      delete ctx;
-      return r;
-    }
+    aio_write(ictx, off, mylen, buf, c, op_flags);
 
     mylock.Lock();
     while (!done)
@@ -3102,12 +3078,7 @@ reprotect_and_return_err:
 
     Context *ctx = new C_SafeCond(&mylock, &cond, &done, &ret);
     AioCompletion *c = aio_create_completion_internal(ctx, rbd_ctx_cb);
-    int r = aio_discard(ictx, off, len, c);
-    if (r < 0) {
-      c->release();
-      delete ctx;
-      return r;
-    }
+    aio_discard(ictx, off, len, c);
 
     mylock.Lock();
     while (!done)
@@ -3223,20 +3194,20 @@ reprotect_and_return_err:
     return 0;
   }
 
-  int aio_flush(ImageCtx *ictx, AioCompletion *c)
+  void aio_flush(ImageCtx *ictx, AioCompletion *c)
   {
     CephContext *cct = ictx->cct;
     ldout(cct, 20) << "aio_flush " << ictx << " completion " << c <<  dendl;
 
+    c->get();
     int r = ictx_check(ictx);
     if (r < 0) {
-      return r;
+      c->fail(cct, r);
+      return;
     }
 
     ictx->user_flushed();
 
-    c->get();
-
     C_AioWrite *flush_ctx = new C_AioWrite(cct, c);
     c->add_request();
     ictx->flush_async_operations(flush_ctx);
@@ -3255,8 +3226,6 @@ reprotect_and_return_err:
     c->finish_adding_requests(cct);
     c->put();
     ictx->perfcounter->inc(l_librbd_aio_flush);
-
-    return 0;
   }
 
   int flush(ImageCtx *ictx)
@@ -3310,16 +3279,18 @@ reprotect_and_return_err:
     return r;
   }
 
-  int aio_write(ImageCtx *ictx, uint64_t off, size_t len, const char *buf,
-		AioCompletion *c, int op_flags)
+  void aio_write(ImageCtx *ictx, uint64_t off, size_t len, const char *buf,
+		 AioCompletion *c, int op_flags)
   {
     CephContext *cct = ictx->cct;
     ldout(cct, 20) << "aio_write " << ictx << " off = " << off << " len = "
 		   << len << " buf = " << (void*)buf << dendl;
 
+    c->get();
     int r = ictx_check(ictx);
     if (r < 0) {
-      return r;
+      c->fail(cct, r);
+      return;
     }
 
     RWLock::RLocker owner_locker(ictx->owner_lock);
@@ -3335,7 +3306,8 @@ reprotect_and_return_err:
       RWLock::RLocker snap_locker(ictx->snap_lock);
       r = clip_io(ictx, off, &clip_len);
       if (r < 0) {
-        return r;
+        c->fail(cct, r);
+        return;
       }
 
       snap_id = ictx->snap_id;
@@ -3345,20 +3317,21 @@ reprotect_and_return_err:
       ictx->parent_lock.put_read();
 
       if (snap_id != CEPH_NOSNAP || ictx->read_only) {
-        return -EROFS;
+        c->fail(cct, -EROFS);
+        return;
       }
 
       ldout(cct, 20) << "  parent overlap " << overlap << dendl;
 
-      c->get();
       c->init_time(ictx, AIO_TYPE_WRITE);
     }
 
     if (ictx->image_watcher->is_lock_supported() &&
 	!ictx->image_watcher->is_lock_owner()) {
       c->put();
-      return ictx->image_watcher->request_lock(
+      ictx->image_watcher->request_lock(
 	boost::bind(&librbd::aio_write, ictx, off, len, buf, _1, op_flags), c);
+      return;
     }
 
     // map
@@ -3397,31 +3370,28 @@ reprotect_and_return_err:
 	c->add_request();
 
 	req->set_op_flags(op_flags);
-	r = req->send();
-	if (r < 0) {
-	  req->complete(r);
-	  goto done;
-	}
+	req->send();
       }
     }
-  done:
+
     c->finish_adding_requests(ictx->cct);
     c->put();
 
     ictx->perfcounter->inc(l_librbd_aio_wr);
     ictx->perfcounter->inc(l_librbd_aio_wr_bytes, clip_len);
-    return r;
   }
 
-  int aio_discard(ImageCtx *ictx, uint64_t off, uint64_t len, AioCompletion *c)
+  void aio_discard(ImageCtx *ictx, uint64_t off, uint64_t len, AioCompletion *c)
   {
     CephContext *cct = ictx->cct;
     ldout(cct, 20) << "aio_discard " << ictx << " off = " << off << " len = "
 		   << len << dendl;
 
+    c->get();
     int r = ictx_check(ictx);
     if (r < 0) {
-      return r;
+      c->fail(cct, r);
+      return;
     }
 
     RWLock::RLocker owner_locker(ictx->owner_lock);
@@ -3437,7 +3407,8 @@ reprotect_and_return_err:
       RWLock::RLocker snap_locker(ictx->snap_lock);
       r = clip_io(ictx, off, &clip_len);
       if (r < 0) {
-        return r;
+        c->fail(cct, r);
+        return;
       }
 
       // TODO: check for snap
@@ -3448,18 +3419,19 @@ reprotect_and_return_err:
       ictx->parent_lock.put_read();
 
       if (snap_id != CEPH_NOSNAP || ictx->read_only) {
-        return -EROFS;
+        c->fail(cct, -EROFS);
+        return;
       }
 
-      c->get();
       c->init_time(ictx, AIO_TYPE_DISCARD);
     }
 
     if (ictx->image_watcher->is_lock_supported() &&
 	!ictx->image_watcher->is_lock_owner()) {
       c->put();
-      return ictx->image_watcher->request_lock(
+      ictx->image_watcher->request_lock(
 	boost::bind(&librbd::aio_discard, ictx, off, len, _1), c);
+      return;
     }
 
     // map
@@ -3498,14 +3470,9 @@ reprotect_and_return_err:
 			  snapc, snap_id, req_comp);
       }
 
-      r = req->send();
-      if (r < 0) {
-	req->complete(r);
-	goto done;
-      }
+      req->send();
     }
-    r = 0;
-  done:
+
     if (ictx->object_cacher) {
       Mutex::Locker l(ictx->cache_lock);
       ictx->object_cacher->discard_set(ictx->object_set, extents);
@@ -3516,7 +3483,6 @@ reprotect_and_return_err:
 
     ictx->perfcounter->inc(l_librbd_aio_discard);
     ictx->perfcounter->inc(l_librbd_aio_discard_bytes, clip_len);
-    return r;
   }
 
   void rbd_req_cb(completion_t cb, void *arg)
@@ -3526,13 +3492,13 @@ reprotect_and_return_err:
     req->complete(comp->get_return_value());
   }
 
-  int aio_read(ImageCtx *ictx, uint64_t off, size_t len,
+  void aio_read(ImageCtx *ictx, uint64_t off, size_t len,
 	       char *buf, bufferlist *bl,
 	       AioCompletion *c, int op_flags)
   {
     vector<pair<uint64_t,uint64_t> > image_extents(1);
     image_extents[0] = make_pair(off, len);
-    return aio_read(ictx, image_extents, buf, bl, c, op_flags);
+    aio_read(ictx, image_extents, buf, bl, c, op_flags);
   }
 
   struct C_RBD_Readahead : public Context {
@@ -3594,14 +3560,17 @@ reprotect_and_return_err:
     }
   }
 
-  int aio_read(ImageCtx *ictx, const vector<pair<uint64_t,uint64_t> >& image_extents,
-	       char *buf, bufferlist *pbl, AioCompletion *c, int op_flags)
+  void aio_read(ImageCtx *ictx, const vector<pair<uint64_t,uint64_t> >& image_extents,
+	        char *buf, bufferlist *pbl, AioCompletion *c, int op_flags)
   {
-    ldout(ictx->cct, 20) << "aio_read " << ictx << " completion " << c << " " << image_extents << dendl;
+    CephContext *cct = ictx->cct;
+    ldout(cct, 20) << "aio_read " << ictx << " completion " << c << " " << image_extents << dendl;
 
+    c->get();
     int r = ictx_check(ictx);
     if (r < 0) {
-      return r;
+      c->fail(cct, r);
+      return;
     }
 
     // readahead
@@ -3629,22 +3598,21 @@ reprotect_and_return_err:
         uint64_t len = p->second;
         r = clip_io(ictx, p->first, &len);
         if (r < 0) {
-	  return r;
+          c->fail(cct, r);
+	  return;
         }
         if (len == 0) {
 	  continue;
         }
 
-        Striper::file_to_extents(ictx->cct, ictx->format_string, &ictx->layout,
+        Striper::file_to_extents(cct, ictx->format_string, &ictx->layout,
 			         p->first, len, 0, object_extents, buffer_ofs);
         buffer_ofs += len;
       }
 
-      c->get();
       c->init_time(ictx, AIO_TYPE_READ);
     }
 
-    int64_t ret;
     c->read_buf = buf;
     c->read_buf_len = buffer_ofs;
     c->read_bl = pbl;
@@ -3668,25 +3636,16 @@ reprotect_and_return_err:
 				    q->length, q->offset,
 				    cache_comp, op_flags);
 	} else {
-	  r = req->send();
-	  if (r == -ENOENT)
-	    r = 0;
-	  if (r < 0) {
-	    ret = r;
-	    goto done;
-	  }
+	  req->send();
 	}
       }
     }
-    ret = buffer_ofs;
-  done:
-    c->finish_adding_requests(ictx->cct);
+
+    c->finish_adding_requests(cct);
     c->put();
 
     ictx->perfcounter->inc(l_librbd_aio_rd);
     ictx->perfcounter->inc(l_librbd_aio_rd_bytes, buffer_ofs);
-
-    return ret;
   }
 
   AioCompletion *aio_create_completion() {
diff --git a/src/librbd/internal.h b/src/librbd/internal.h
index eda119e..419f929 100644
--- a/src/librbd/internal.h
+++ b/src/librbd/internal.h
@@ -197,14 +197,14 @@ namespace librbd {
   void async_resize_helper(ImageCtx *ictx, Context *ctx, uint64_t new_size,
                            ProgressContext& prog_ctx);
 
-  int aio_write(ImageCtx *ictx, uint64_t off, size_t len, const char *buf,
-		AioCompletion *c, int op_flags);
-  int aio_discard(ImageCtx *ictx, uint64_t off, uint64_t len, AioCompletion *c);
-  int aio_read(ImageCtx *ictx, uint64_t off, size_t len,
-	       char *buf, bufferlist *pbl, AioCompletion *c, int op_flags);
-  int aio_read(ImageCtx *ictx, const vector<pair<uint64_t,uint64_t> >& image_extents,
-	       char *buf, bufferlist *pbl, AioCompletion *c, int op_flags);
-  int aio_flush(ImageCtx *ictx, AioCompletion *c);
+  void aio_write(ImageCtx *ictx, uint64_t off, size_t len, const char *buf,
+		 AioCompletion *c, int op_flags);
+  void aio_discard(ImageCtx *ictx, uint64_t off, uint64_t len, AioCompletion *c);
+  void aio_read(ImageCtx *ictx, uint64_t off, size_t len,
+	        char *buf, bufferlist *pbl, AioCompletion *c, int op_flags);
+  void aio_read(ImageCtx *ictx, const vector<pair<uint64_t,uint64_t> >& image_extents,
+	        char *buf, bufferlist *pbl, AioCompletion *c, int op_flags);
+  void aio_flush(ImageCtx *ictx, AioCompletion *c);
   int flush(ImageCtx *ictx);
   int _flush(ImageCtx *ictx);
   int invalidate_cache(ImageCtx *ictx);
diff --git a/src/librbd/librbd.cc b/src/librbd/librbd.cc
index ce0d313..a99f7d4 100644
--- a/src/librbd/librbd.cc
+++ b/src/librbd/librbd.cc
@@ -20,6 +20,7 @@
 #include "common/errno.h"
 #include "common/snap_types.h"
 #include "common/perf_counters.h"
+#include "common/WorkQueue.h"
 #include "include/Context.h"
 #include "include/rbd/librbd.hpp"
 #include "osdc/ObjectCacher.h"
@@ -51,6 +52,125 @@ using ceph::bufferlist;
 using librados::snap_t;
 using librados::IoCtx;
 
+namespace {
+
+class C_AioReadWQ : public Context {
+public:
+  C_AioReadWQ(librbd::ImageCtx *ictx, uint64_t off, size_t len,
+              char *buf, bufferlist *pbl, librbd::AioCompletion *c,
+              int op_flags)
+    : m_ictx(ictx), m_off(off), m_len(len), m_buf(buf), m_pbl(pbl), m_comp(c),
+      m_op_flags(op_flags) {
+  }
+protected:
+  virtual void finish(int r) {
+    librbd::aio_read(m_ictx, m_off, m_len, m_buf, m_pbl, m_comp, m_op_flags);
+  }
+private:
+  librbd::ImageCtx *m_ictx;
+  uint64_t m_off;
+  uint64_t m_len;
+  char *m_buf;
+  bufferlist *m_pbl;
+  librbd::AioCompletion *m_comp;
+  int m_op_flags;
+};
+
+class C_AioWriteWQ : public Context {
+public:
+  C_AioWriteWQ(librbd::ImageCtx *ictx, uint64_t off, size_t len,
+               const char *buf, librbd::AioCompletion *c, int op_flags)
+    : m_ictx(ictx), m_off(off), m_len(len), m_buf(buf), m_comp(c),
+      m_op_flags(op_flags) {
+  }
+protected:
+  virtual void finish(int r) {
+    librbd::aio_write(m_ictx, m_off, m_len, m_buf, m_comp, m_op_flags);
+  }
+private:
+  librbd::ImageCtx *m_ictx;
+  uint64_t m_off;
+  uint64_t m_len;
+  const char *m_buf;
+  librbd::AioCompletion *m_comp;
+  int m_op_flags;
+};
+
+class C_AioDiscardWQ : public Context {
+public:
+  C_AioDiscardWQ(librbd::ImageCtx *ictx, uint64_t off, uint64_t len,
+                 librbd::AioCompletion *c)
+    : m_ictx(ictx), m_off(off), m_len(len), m_comp(c) {
+  }
+protected:
+  virtual void finish(int r) {
+    librbd::aio_discard(m_ictx, m_off, m_len, m_comp);
+  }
+private:
+  librbd::ImageCtx *m_ictx;
+  uint64_t m_off;
+  uint64_t m_len;
+  librbd::AioCompletion *m_comp;
+};
+
+class C_AioFlushWQ : public Context {
+public:
+  C_AioFlushWQ(librbd::ImageCtx *ictx, librbd::AioCompletion *c)
+    : m_ictx(ictx), m_comp(c) {
+  }
+protected:
+  virtual void finish(int r) {
+    librbd::aio_flush(m_ictx, m_comp);
+  }
+private:
+  librbd::ImageCtx *m_ictx;
+  librbd::AioCompletion *m_comp;
+};
+
+void submit_aio_read(librbd::ImageCtx *ictx, uint64_t off, size_t len,
+                     char *buf, bufferlist *pbl, librbd::AioCompletion *c,
+                     int op_flags) {
+  if (ictx->cct->_conf->rbd_non_blocking_aio) {
+    ictx->aio_work_queue->queue(new C_AioReadWQ(ictx, off, len, buf, pbl, c,
+                                                op_flags));
+  } else {
+    librbd::aio_read(ictx, off, len, buf, pbl, c, op_flags);
+  }
+}
+
+void submit_aio_write(librbd::ImageCtx *ictx, uint64_t off, size_t len,
+                      const char *buf, librbd::AioCompletion *c, int op_flags) {
+  if (ictx->cct->_conf->rbd_non_blocking_aio) {
+    ictx->aio_work_queue->queue(new C_AioWriteWQ(ictx, off, len, buf, c,
+                                                 op_flags));
+  } else {
+    librbd::aio_write(ictx, off, len, buf, c, op_flags);
+  }
+}
+
+void submit_aio_discard(librbd::ImageCtx *ictx, uint64_t off, uint64_t len,
+                        librbd::AioCompletion *c) {
+  if (ictx->cct->_conf->rbd_non_blocking_aio) {
+    ictx->aio_work_queue->queue(new C_AioDiscardWQ(ictx, off, len, c));
+  } else {
+    librbd::aio_discard(ictx, off, len, c);
+  }
+}
+
+void submit_aio_flush(librbd::ImageCtx *ictx, librbd::AioCompletion *c) {
+  if (ictx->cct->_conf->rbd_non_blocking_aio) {
+    ictx->aio_work_queue->queue(new C_AioFlushWQ(ictx, c));
+  } else {
+    librbd::aio_flush(ictx, c);
+  }
+}
+
+librbd::AioCompletion* get_aio_completion(librbd::RBD::AioCompletion *comp) {
+  return reinterpret_cast<librbd::AioCompletion *>(comp->pc);
+}
+
+} // anonymous namespace
+
 namespace librbd {
   ProgressContext::~ProgressContext()
   {
@@ -709,10 +829,9 @@ namespace librbd {
       tracepoint(librbd, aio_write_exit, -EINVAL);
       return -EINVAL;
     }
-    int r = librbd::aio_write(ictx, off, len, bl.c_str(),
-			     (librbd::AioCompletion *)c->pc, 0);
-    tracepoint(librbd, aio_write_exit, r);
-    return r;
+    submit_aio_write(ictx, off, len, bl.c_str(), get_aio_completion(c), 0);
+    tracepoint(librbd, aio_write_exit, 0);
+    return 0;
   }
 
   int Image::aio_write2(uint64_t off, size_t len, bufferlist& bl,
@@ -725,19 +844,19 @@ namespace librbd {
       tracepoint(librbd, aio_write_exit, -EINVAL);
       return -EINVAL;
     }
-    int r = librbd::aio_write(ictx, off, len, bl.c_str(),
-			     (librbd::AioCompletion *)c->pc, op_flags);
-    tracepoint(librbd, aio_write_exit, r);
-    return r;
+    submit_aio_write(ictx, off, len, bl.c_str(), get_aio_completion(c),
+                     op_flags);
+    tracepoint(librbd, aio_write_exit, 0);
+    return 0;
   }
 
   int Image::aio_discard(uint64_t off, uint64_t len, RBD::AioCompletion *c)
   {
     ImageCtx *ictx = (ImageCtx *)ctx;
     tracepoint(librbd, aio_discard_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, c->pc);
-    int r = librbd::aio_discard(ictx, off, len, (librbd::AioCompletion *)c->pc);
-    tracepoint(librbd, aio_discard_exit, r);
-    return r;
+    submit_aio_discard(ictx, off, len, get_aio_completion(c));
+    tracepoint(librbd, aio_discard_exit, 0);
+    return 0;
   }
 
   int Image::aio_read(uint64_t off, size_t len, bufferlist& bl,
@@ -747,9 +866,9 @@ namespace librbd {
     tracepoint(librbd, aio_read_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, bl.c_str(), c->pc);
     ldout(ictx->cct, 10) << "Image::aio_read() buf=" << (void *)bl.c_str() << "~"
 			 << (void *)(bl.c_str() + len - 1) << dendl;
-    int r = librbd::aio_read(ictx, off, len, NULL, &bl, (librbd::AioCompletion *)c->pc, 0);
-    tracepoint(librbd, aio_read_exit, r);
-    return r;
+    submit_aio_read(ictx, off, len, NULL, &bl, get_aio_completion(c), 0);
+    tracepoint(librbd, aio_read_exit, 0);
+    return 0;
   }
 
   int Image::aio_read2(uint64_t off, size_t len, bufferlist& bl,
@@ -760,9 +879,9 @@ namespace librbd {
 		ictx->read_only, off, len, bl.c_str(), c->pc, op_flags);
     ldout(ictx->cct, 10) << "Image::aio_read() buf=" << (void *)bl.c_str() << "~"
 			 << (void *)(bl.c_str() + len - 1) << dendl;
-    int r = librbd::aio_read(ictx, off, len, NULL, &bl, (librbd::AioCompletion *)c->pc, op_flags);
-    tracepoint(librbd, aio_read_exit, r);
-    return r;
+    submit_aio_read(ictx, off, len, NULL, &bl, get_aio_completion(c), op_flags);
+    tracepoint(librbd, aio_read_exit, 0);
+    return 0;
   }
 
   int Image::flush()
@@ -778,9 +897,9 @@ namespace librbd {
   {
     ImageCtx *ictx = (ImageCtx *)ctx;
     tracepoint(librbd, aio_flush_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, c->pc);
-    int r = librbd::aio_flush(ictx, (librbd::AioCompletion *)c->pc);
-    tracepoint(librbd, aio_flush_exit, r);
-    return r;
+    submit_aio_flush(ictx, get_aio_completion(c));
+    tracepoint(librbd, aio_flush_exit, 0);
+    return 0;
   }
 
   int Image::invalidate_cache()
@@ -1612,10 +1731,9 @@ extern "C" int rbd_aio_write(rbd_image_t image, uint64_t off, size_t len,
   librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
   librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
   tracepoint(librbd, aio_write_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, buf, comp->pc);
-  int r = librbd::aio_write(ictx, off, len, buf,
-			   (librbd::AioCompletion *)comp->pc, 0);
-  tracepoint(librbd, aio_write_exit, r);
-  return r;
+  submit_aio_write(ictx, off, len, buf, get_aio_completion(comp), 0);
+  tracepoint(librbd, aio_write_exit, 0);
+  return 0;
 }
 
 extern "C" int rbd_aio_write2(rbd_image_t image, uint64_t off, size_t len,
@@ -1625,10 +1743,9 @@ extern "C" int rbd_aio_write2(rbd_image_t image, uint64_t off, size_t len,
   librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
   tracepoint(librbd, aio_write2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
 	      ictx->read_only, off, len, buf, comp->pc, op_flags);
-  int r = librbd::aio_write(ictx, off, len, buf,
-			   (librbd::AioCompletion *)comp->pc, op_flags);
-  tracepoint(librbd, aio_write_exit, r);
-  return r;
+  submit_aio_write(ictx, off, len, buf, get_aio_completion(comp), op_flags);
+  tracepoint(librbd, aio_write_exit, 0);
+  return 0;
 }
 
 
@@ -1638,9 +1755,9 @@ extern "C" int rbd_aio_discard(rbd_image_t image, uint64_t off, uint64_t len,
   librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
   librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
   tracepoint(librbd, aio_discard_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, comp->pc);
-  int r = librbd::aio_discard(ictx, off, len, (librbd::AioCompletion *)comp->pc);
-  tracepoint(librbd, aio_discard_exit, r);
-  return r;
+  submit_aio_discard(ictx, off, len, get_aio_completion(comp));
+  tracepoint(librbd, aio_discard_exit, 0);
+  return 0;
 }
 
 extern "C" int rbd_aio_read(rbd_image_t image, uint64_t off, size_t len,
@@ -1649,10 +1766,9 @@ extern "C" int rbd_aio_read(rbd_image_t image, uint64_t off, size_t len,
   librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
   librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
   tracepoint(librbd, aio_read_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, off, len, buf, comp->pc);
-  int r = librbd::aio_read(ictx, off, len, buf, NULL,
-			  (librbd::AioCompletion *)comp->pc, 0);
-  tracepoint(librbd, aio_read_exit, r);
-  return r;
+  submit_aio_read(ictx, off, len, buf, NULL, get_aio_completion(comp), 0);
+  tracepoint(librbd, aio_read_exit, 0);
+  return 0;
 }
 
 extern "C" int rbd_aio_read2(rbd_image_t image, uint64_t off, size_t len,
@@ -1662,10 +1778,10 @@ extern "C" int rbd_aio_read2(rbd_image_t image, uint64_t off, size_t len,
   librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
   tracepoint(librbd, aio_read2_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(),
 	      ictx->read_only, off, len, buf, comp->pc, op_flags);
-  int r = librbd::aio_read(ictx, off, len, buf, NULL,
-			  (librbd::AioCompletion *)comp->pc, op_flags);
-  tracepoint(librbd, aio_read_exit, r);
-  return r;
+  submit_aio_read(ictx, off, len, buf, NULL, get_aio_completion(comp),
+                  op_flags);
+  tracepoint(librbd, aio_read_exit, 0);
+  return 0;
 }
 
 extern "C" int rbd_flush(rbd_image_t image)
@@ -1682,9 +1798,9 @@ extern "C" int rbd_aio_flush(rbd_image_t image, rbd_completion_t c)
   librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
   librbd::RBD::AioCompletion *comp = (librbd::RBD::AioCompletion *)c;
   tracepoint(librbd, aio_flush_enter, ictx, ictx->name.c_str(), ictx->snap_name.c_str(), ictx->read_only, comp->pc);
-  int r = librbd::aio_flush(ictx, (librbd::AioCompletion *)comp->pc);
-  tracepoint(librbd, aio_flush_exit, r);
-  return r;
+  submit_aio_flush(ictx, get_aio_completion(comp));
+  tracepoint(librbd, aio_flush_exit, 0);
+  return 0;
 }
 
 extern "C" int rbd_invalidate_cache(rbd_image_t image)
diff --git a/src/log/Log.cc b/src/log/Log.cc
index 046774d..ce97494 100644
--- a/src/log/Log.cc
+++ b/src/log/Log.cc
@@ -116,6 +116,8 @@ void Log::set_log_file(string fn)
 
 void Log::reopen_log_file()
 {
+  pthread_mutex_lock(&m_flush_mutex);
+  m_flush_mutex_holder = pthread_self();
   if (m_fd >= 0)
     VOID_TEMP_FAILURE_RETRY(::close(m_fd));
   if (m_log_file.length()) {
@@ -123,6 +125,8 @@ void Log::reopen_log_file()
   } else {
     m_fd = -1;
   }
+  m_flush_mutex_holder = 0;
+  pthread_mutex_unlock(&m_flush_mutex);
 }
 
 void Log::set_syslog_level(int log, int crash)
diff --git a/src/mds/CDir.cc b/src/mds/CDir.cc
index 235b0dd..5b72d51 100644
--- a/src/mds/CDir.cc
+++ b/src/mds/CDir.cc
@@ -1402,9 +1402,17 @@ void CDir::fetch(MDSInternalContextBase *c, const string& want_dn, bool ignore_a
   // unlinked directory inode shouldn't have any entry
   if (inode->inode.nlink == 0 && !inode->snaprealm) {
     dout(7) << "fetch dirfrag for unlinked directory, mark complete" << dendl;
-    if (get_version() == 0)
+    if (get_version() == 0) {
       set_version(1);
+
+      if (state_test(STATE_REJOINUNDEF)) {
+	assert(cache->mds->is_rejoin());
+	state_clear(STATE_REJOINUNDEF);
+	cache->opened_undef_dirfrag(this);
+      }
+    }
     mark_complete();
+
     if (c)
       cache->mds->queue_waiter(c);
     return;
diff --git a/src/mon/MDSMonitor.cc b/src/mon/MDSMonitor.cc
index a9044ae..4cf26cd 100644
--- a/src/mon/MDSMonitor.cc
+++ b/src/mon/MDSMonitor.cc
@@ -246,17 +246,16 @@ bool MDSMonitor::preprocess_beacon(MMDSBeacon *m)
 
   // check privileges, ignore if fails
   MonSession *session = m->get_session();
-  if (!session)
-    goto out;
+  assert(session);
   if (!session->is_capable("mds", MON_CAP_X)) {
     dout(0) << "preprocess_beacon got MMDSBeacon from entity with insufficient privileges "
 	    << session->caps << dendl;
-    goto out;
+    goto ignore;
   }
 
   if (m->get_fsid() != mon->monmap->fsid) {
     dout(0) << "preprocess_beacon on fsid " << m->get_fsid() << " != " << mon->monmap->fsid << dendl;
-    goto out;
+    goto ignore;
   }
 
   dout(12) << "preprocess_beacon " << *m
@@ -267,13 +266,13 @@ bool MDSMonitor::preprocess_beacon(MMDSBeacon *m)
   // make sure the address has a port
   if (m->get_orig_source_addr().get_port() == 0) {
     dout(1) << " ignoring boot message without a port" << dendl;
-    goto out;
+    goto ignore;
   }
 
   // check compat
   if (!m->get_compat().writeable(mdsmap.compat)) {
     dout(1) << " mds " << m->get_source_inst() << " can't write to mdsmap " << mdsmap.compat << dendl;
-    goto out;
+    goto ignore;
   }
 
   // fw to leader?
@@ -282,7 +281,7 @@ bool MDSMonitor::preprocess_beacon(MMDSBeacon *m)
 
   if (pending_mdsmap.test_flag(CEPH_MDSMAP_DOWN)) {
     dout(7) << " mdsmap DOWN flag set, ignoring mds " << m->get_source_inst() << " beacon" << dendl;
-    goto out;
+    goto ignore;
   }
 
   // booted, but not in map?
@@ -290,7 +289,8 @@ bool MDSMonitor::preprocess_beacon(MMDSBeacon *m)
     if (state != MDSMap::STATE_BOOT) {
       dout(7) << "mds_beacon " << *m << " is not in mdsmap" << dendl;
       mon->send_reply(m, new MMDSMap(mon->monmap->fsid, &mdsmap));
-      goto out;
+      m->put();
+      return true;
     } else {
       return false;  // not booted yet.
     }
@@ -300,13 +300,13 @@ bool MDSMonitor::preprocess_beacon(MMDSBeacon *m)
   // old seq?
   if (info.state_seq > seq) {
     dout(7) << "mds_beacon " << *m << " has old seq, ignoring" << dendl;
-    goto out;
+    goto ignore;
   }
 
   if (mdsmap.get_epoch() != m->get_last_epoch_seen()) {
     dout(10) << "mds_beacon " << *m
 	     << " ignoring requested state, because mds hasn't seen latest map" << dendl;
-    goto ignore;
+    goto reply;
   }
 
   if (info.laggy()) {
@@ -315,17 +315,17 @@ bool MDSMonitor::preprocess_beacon(MMDSBeacon *m)
   }
   if (state == MDSMap::STATE_BOOT) {
     // ignore, already booted.
-    goto out;
+    goto ignore;
   }
   // is there a state change here?
-  if (info.state != state) {    
+  if (info.state != state) {
     // legal state change?
     if ((info.state == MDSMap::STATE_STANDBY ||
 	 info.state == MDSMap::STATE_STANDBY_REPLAY ||
 	 info.state == MDSMap::STATE_ONESHOT_REPLAY) && state > 0) {
       dout(10) << "mds_beacon mds can't activate itself (" << ceph_mds_state_name(info.state)
 	       << " -> " << ceph_mds_state_name(state) << ")" << dendl;
-      goto ignore;
+      goto reply;
     }
     
     if (info.state == MDSMap::STATE_STANDBY &&
@@ -337,7 +337,7 @@ bool MDSMonitor::preprocess_beacon(MMDSBeacon *m)
       dout(10) << "mds_beacon can't standby-replay mds." << m->get_standby_for_rank() << " at this time (cluster degraded, or mds not active)" << dendl;
       dout(10) << "pending_mdsmap.is_degraded()==" << pending_mdsmap.is_degraded()
           << " rank state: " << ceph_mds_state_name(pending_mdsmap.get_state(m->get_standby_for_rank())) << dendl;
-      goto ignore;
+      goto reply;
     }
     _note_beacon(m);
     return false;  // need to update map
@@ -351,15 +351,18 @@ bool MDSMonitor::preprocess_beacon(MMDSBeacon *m)
     return false;
   }
 
- ignore:
+ reply:
   // note time and reply
   _note_beacon(m);
   mon->send_reply(m,
 		  new MMDSBeacon(mon->monmap->fsid, m->get_global_id(), m->get_name(),
 				 mdsmap.get_epoch(), state, seq));
-  
-  // done
- out:
+  m->put();
+  return true;
+
+ ignore:
+  // I won't reply this beacon, drop it.
+  mon->no_reply(m);
   m->put();
   return true;
 }
@@ -589,8 +592,14 @@ void MDSMonitor::_updated(MMDSBeacon *m)
   if (m->get_state() == MDSMap::STATE_STOPPED) {
     // send the map manually (they're out of the map, so they won't get it automatic)
     mon->send_reply(m, new MMDSMap(mon->monmap->fsid, &mdsmap));
+  } else {
+    mon->send_reply(m, new MMDSBeacon(mon->monmap->fsid,
+				      m->get_global_id(),
+				      m->get_name(),
+				      mdsmap.get_epoch(),
+				      m->get_state(),
+				      m->get_seq()));
   }
-
   m->put();
 }
 
diff --git a/src/mon/MDSMonitor.h b/src/mon/MDSMonitor.h
index 9a0dcda..5b858ee 100644
--- a/src/mon/MDSMonitor.h
+++ b/src/mon/MDSMonitor.h
@@ -58,10 +58,12 @@ class MDSMonitor : public PaxosService {
     void finish(int r) {
       if (r >= 0)
 	mm->_updated(m);   // success
-      else if (r == -ECANCELED)
+      else if (r == -ECANCELED) {
+	mm->mon->no_reply(m);
 	m->put();
-      else
+      } else {
 	mm->dispatch((PaxosServiceMessage*)m);        // try again
+      }
     }
   };
 
diff --git a/src/mon/MonCommands.h b/src/mon/MonCommands.h
index a72aa4b..a75b067 100644
--- a/src/mon/MonCommands.h
+++ b/src/mon/MonCommands.h
@@ -133,21 +133,21 @@ COMMAND("pg dump_stuck " \
 	"pg", "r", "cli,rest")
 COMMAND("pg ls-by-pool " \
         "name=poolstr,type=CephString " \
-	"name=states,type=CephChoices,strings=active|clean|down|replay|splitting|scrubbing|scrubq|degraded|inconsistent|peering|repair|recovery|backfill_wait|incomplete|stale|remapped|deep_scrub|backfill|backfill_toofull|recovery_wait|undersized,n=N,req=false ", \
+	"name=states,type=CephChoices,strings=active|clean|down|replay|splitting|scrubbing|scrubq|degraded|inconsistent|peering|repair|recovering|backfill_wait|incomplete|stale|remapped|deep_scrub|backfill|backfill_toofull|recovery_wait|undersized,n=N,req=false ", \
 	"list pg with pool = [poolname | poolid]", "pg", "r", "cli,rest")
 COMMAND("pg ls-by-primary " \
         "name=osd,type=CephOsdName " \
         "name=pool,type=CephInt,req=false " \
-	"name=states,type=CephChoices,strings=active|clean|down|replay|splitting|scrubbing|scrubq|degraded|inconsistent|peering|repair|recovery|backfill_wait|incomplete|stale|remapped|deep_scrub|backfill|backfill_toofull|recovery_wait|undersized,n=N,req=false ", \
+	"name=states,type=CephChoices,strings=active|clean|down|replay|splitting|scrubbing|scrubq|degraded|inconsistent|peering|repair|recovering|backfill_wait|incomplete|stale|remapped|deep_scrub|backfill|backfill_toofull|recovery_wait|undersized,n=N,req=false ", \
 	"list pg with primary = [osd]", "pg", "r", "cli,rest")
 COMMAND("pg ls-by-osd " \
         "name=osd,type=CephOsdName " \
         "name=pool,type=CephInt,req=false " \
-	"name=states,type=CephChoices,strings=active|clean|down|replay|splitting|scrubbing|scrubq|degraded|inconsistent|peering|repair|recovery|backfill_wait|incomplete|stale|remapped|deep_scrub|backfill|backfill_toofull|recovery_wait|undersized,n=N,req=false ", \
+	"name=states,type=CephChoices,strings=active|clean|down|replay|splitting|scrubbing|scrubq|degraded|inconsistent|peering|repair|recovering|backfill_wait|incomplete|stale|remapped|deep_scrub|backfill|backfill_toofull|recovery_wait|undersized,n=N,req=false ", \
 	"list pg on osd [osd]", "pg", "r", "cli,rest")
 COMMAND("pg ls " \
         "name=pool,type=CephInt,req=false " \
-	"name=states,type=CephChoices,strings=active|clean|down|replay|splitting|scrubbing|scrubq|degraded|inconsistent|peering|repair|recovery|backfill_wait|incomplete|stale|remapped|deep_scrub|backfill|backfill_toofull|recovery_wait|undersized,n=N,req=false ", \
+	"name=states,type=CephChoices,strings=active|clean|down|replay|splitting|scrubbing|scrubq|degraded|inconsistent|peering|repair|recovering|backfill_wait|incomplete|stale|remapped|deep_scrub|backfill|backfill_toofull|recovery_wait|undersized,n=N,req=false ", \
 	"list pg with specific pool, osd, state", "pg", "r", "cli,rest")
 COMMAND("pg map name=pgid,type=CephPgid", "show mapping of pg to osds", \
 	"pg", "r", "cli,rest")
@@ -521,6 +521,9 @@ COMMAND("osd crush rule create-erasure " \
 COMMAND("osd crush rule rm " \
 	"name=name,type=CephString,goodchars=[A-Za-z0-9-_.] ",	\
 	"remove crush rule <name>", "osd", "rw", "cli,rest")
+COMMAND("osd crush tree",
+	"dump crush buckets and items in a tree view",
+	"osd", "r", "cli,rest")
 COMMAND("osd setmaxosd " \
 	"name=newmax,type=CephInt,range=0", \
 	"set new maximum osd value", "osd", "rw", "cli,rest")
diff --git a/src/mon/Monitor.cc b/src/mon/Monitor.cc
index 70cb798..83098f0 100644
--- a/src/mon/Monitor.cc
+++ b/src/mon/Monitor.cc
@@ -2253,26 +2253,6 @@ health_status_t Monitor::get_health(list<string>& status,
 
   health_monitor->get_health(f, summary, (detailbl ? &detail : NULL));
 
-  if (f)
-    f->open_array_section("summary");
-  health_status_t overall = HEALTH_OK;
-  if (!summary.empty()) {
-    while (!summary.empty()) {
-      if (overall > summary.front().first)
-	overall = summary.front().first;
-      status.push_back(summary.front().second);
-      if (f) {
-        f->open_object_section("item");
-        f->dump_stream("severity") <<  summary.front().first;
-        f->dump_string("summary", summary.front().second);
-        f->close_section();
-      }
-      summary.pop_front();
-    }
-  }
-  if (f)
-    f->close_section();
-
   if (f) {
     f->open_object_section("timechecks");
     f->dump_unsigned("epoch", get_epoch());
@@ -2281,6 +2261,7 @@ health_status_t Monitor::get_health(list<string>& status,
       << ((timecheck_round%2) ? "on-going" : "finished");
   }
 
+  health_status_t overall = HEALTH_OK;
   if (!timecheck_skews.empty()) {
     list<string> warns;
     if (f)
@@ -2327,6 +2308,7 @@ health_status_t Monitor::get_health(list<string>& status,
           ss << ",";
       }
       status.push_back(ss.str());
+      summary.push_back(make_pair(HEALTH_WARN, "Monitor clock skew detected "));
     }
     if (f)
       f->close_section();
@@ -2334,6 +2316,25 @@ health_status_t Monitor::get_health(list<string>& status,
   if (f)
     f->close_section();
 
+  if (f)
+    f->open_array_section("summary");
+  if (!summary.empty()) {
+    while (!summary.empty()) {
+      if (overall > summary.front().first)
+	overall = summary.front().first;
+      status.push_back(summary.front().second);
+      if (f) {
+        f->open_object_section("item");
+        f->dump_stream("severity") <<  summary.front().first;
+        f->dump_string("summary", summary.front().second);
+        f->close_section();
+      }
+      summary.pop_front();
+    }
+  }
+  if (f)
+    f->close_section();
+
   stringstream fss;
   fss << overall;
   status.push_front(fss.str());
@@ -3361,12 +3362,11 @@ void Monitor::_ms_dispatch(Message *m)
     dout(20) << "ms_dispatch existing session " << s << " for " << s->inst << dendl;
   }
 
-  if (s) {
-    if (s->auth_handler) {
-      s->entity_name = s->auth_handler->get_entity_name();
-    }
-    dout(20) << " caps " << s->caps.get_str() << dendl;
+  assert(s);
+  if (s->auth_handler) {
+    s->entity_name = s->auth_handler->get_entity_name();
   }
+  dout(20) << " caps " << s->caps.get_str() << dendl;
 
   if (is_synchronizing() && !src_is_mon) {
     waitlist_or_zap_client(m);
@@ -3374,11 +3374,7 @@ void Monitor::_ms_dispatch(Message *m)
   }
 
   dispatch(s, m, src_is_mon);
-
-  if (s) {
-    s->put();
-  }
-
+  s->put();
   return;
 }
 
diff --git a/src/mon/OSDMonitor.cc b/src/mon/OSDMonitor.cc
index 58a70ef..730702e 100644
--- a/src/mon/OSDMonitor.cc
+++ b/src/mon/OSDMonitor.cc
@@ -2998,8 +2998,6 @@ bool OSDMonitor::preprocess_command(MMonCommand *m)
   } else if (prefix == "osd crush get-tunable") {
     string tunable;
     cmd_getval(g_ceph_context, cmdmap, "tunable", tunable);
-    int value;
-    cmd_getval(g_ceph_context, cmdmap, "value", value);
     ostringstream rss;
     if (f)
       f->open_object_section("tunable");
@@ -3369,6 +3367,12 @@ stats_out:
     f->flush(rs);
     rs << "\n";
     rdata.append(rs.str());
+  } else if (prefix == "osd crush tree") {
+    boost::scoped_ptr<Formatter> f(Formatter::create(format, "json-pretty", "json-pretty"));
+    f->open_array_section("crush_map_roots");
+    osdmap.crush->dump_tree(f.get());
+    f->close_section();
+    f->flush(rdata);
   } else if (prefix == "osd erasure-code-profile ls") {
     const map<string,map<string,string> > &profiles =
       osdmap.get_erasure_code_profiles();
@@ -4525,8 +4529,13 @@ bool OSDMonitor::prepare_command_impl(MMonCommand *m,
     // sanity check: test some inputs to make sure this map isn't totally broken
     dout(10) << " testing map" << dendl;
     stringstream ess;
+    // XXX: Use mon_lease as a timeout value for crushtool.
+    // If the crushtool consistently takes longer than 'mon_lease' seconds,
+    // then we would consistently trigger an election before the command
+    // finishes, having a flapping monitor unable to hold quorum.
     CrushTester tester(crush, ess);
     int r = tester.test_with_crushtool(g_conf->crushtool,
+				       osdmap.get_max_osd(),
 				       g_conf->mon_lease);
     if (r < 0) {
       if (r == -EINTR) {
@@ -6112,6 +6121,19 @@ done:
       err = -ENOTEMPTY;
       goto reply;
     }
+    if (tp->ec_pool()) {
+      ss << "tier pool '" << tierpoolstr
+	 << "' is an ec pool, which cannot be a tier";
+      err = -ENOTSUP;
+      goto reply;
+    }
+    if ((!tp->removed_snaps.empty() || !tp->snaps.empty()) &&
+	((force_nonempty != "--force-nonempty") ||
+	 (!g_conf->mon_debug_unsafe_allow_tier_with_nonempty_snaps))) {
+      ss << "tier pool '" << tierpoolstr << "' has snapshot state; it cannot be added as a tier without breaking the pool";
+      err = -ENOTEMPTY;
+      goto reply;
+    }
     // go
     pg_pool_t *np = pending_inc.get_new_pool(pool_id, p);
     pg_pool_t *ntp = pending_inc.get_new_pool(tierpool_id, tp);
diff --git a/src/mon/PGMap.cc b/src/mon/PGMap.cc
index 4c90d9a..e60ed6a 100644
--- a/src/mon/PGMap.cc
+++ b/src/mon/PGMap.cc
@@ -1426,7 +1426,7 @@ void PGMap::generate_test_instances(list<PGMap*>& o)
   }
 }
 
-void PGMap::get_filtered_pg_stats(string& state, int64_t poolid, int64_t osdid,
+void PGMap::get_filtered_pg_stats(const string& state, int64_t poolid, int64_t osdid,
                                   bool primary, set<pg_t>& pgs)
 {
   int type = 0;
diff --git a/src/mon/PGMap.h b/src/mon/PGMap.h
index f151bf6..1cdff4a 100644
--- a/src/mon/PGMap.h
+++ b/src/mon/PGMap.h
@@ -290,7 +290,7 @@ public:
   void dump_osd_blocked_by_stats(Formatter *f) const;
   void print_osd_blocked_by_stats(std::ostream *ss) const;
 
-  void get_filtered_pg_stats(string& state, int64_t poolid, int64_t osdid,
+  void get_filtered_pg_stats(const string& state, int64_t poolid, int64_t osdid,
                              bool primary, set<pg_t>& pgs);
   void recovery_summary(Formatter *f, list<string> *psl,
                         const pool_stat_t& delta_sum) const;
diff --git a/src/osd/OSD.cc b/src/osd/OSD.cc
index c126c3b..7dbcfc5 100644
--- a/src/osd/OSD.cc
+++ b/src/osd/OSD.cc
@@ -1543,9 +1543,17 @@ OSD::OSD(CephContext *cct_, ObjectStore *store_,
   op_tracker(cct, cct->_conf->osd_enable_op_tracker, 
                   cct->_conf->osd_num_op_tracker_shard),
   test_ops_hook(NULL),
-  op_shardedwq(cct->_conf->osd_op_num_shards, this, 
-    cct->_conf->osd_op_thread_timeout, &osd_op_tp),
-  peering_wq(this, cct->_conf->osd_op_thread_timeout, &osd_tp),
+  op_shardedwq(
+    cct->_conf->osd_op_num_shards,
+    this,
+    cct->_conf->osd_op_thread_timeout,
+    cct->_conf->osd_op_thread_suicide_timeout,
+    &osd_op_tp),
+  peering_wq(
+    this,
+    cct->_conf->osd_op_thread_timeout,
+    cct->_conf->osd_op_thread_suicide_timeout,
+    &osd_tp),
   map_lock("OSD::map_lock"),
   pg_map_lock("OSD::pg_map_lock"),
   debug_drop_pg_create_probability(cct->_conf->osd_debug_drop_pg_create_probability),
@@ -1557,14 +1565,38 @@ OSD::OSD(CephContext *cct_, ObjectStore *store_,
   pg_stat_queue_lock("OSD::pg_stat_queue_lock"),
   osd_stat_updated(false),
   pg_stat_tid(0), pg_stat_tid_flushed(0),
-  command_wq(this, cct->_conf->osd_command_thread_timeout, &command_tp),
+  command_wq(
+    this,
+    cct->_conf->osd_command_thread_timeout,
+    cct->_conf->osd_command_thread_suicide_timeout,
+    &command_tp),
   recovery_ops_active(0),
-  recovery_wq(this, cct->_conf->osd_recovery_thread_timeout, &recovery_tp),
+  recovery_wq(
+    this,
+    cct->_conf->osd_recovery_thread_timeout,
+    cct->_conf->osd_recovery_thread_suicide_timeout,
+    &recovery_tp),
   replay_queue_lock("OSD::replay_queue_lock"),
-  snap_trim_wq(this, cct->_conf->osd_snap_trim_thread_timeout, &disk_tp),
-  scrub_wq(this, cct->_conf->osd_scrub_thread_timeout, &disk_tp),
-  rep_scrub_wq(this, cct->_conf->osd_scrub_thread_timeout, &disk_tp),
-  remove_wq(store, cct->_conf->osd_remove_thread_timeout, &disk_tp),
+  snap_trim_wq(
+    this,
+    cct->_conf->osd_snap_trim_thread_timeout,
+    cct->_conf->osd_snap_trim_thread_suicide_timeout,
+    &disk_tp),
+  scrub_wq(
+    this,
+    cct->_conf->osd_scrub_thread_timeout,
+    cct->_conf->osd_scrub_thread_suicide_timeout,
+    &disk_tp),
+  rep_scrub_wq(
+    this,
+    cct->_conf->osd_scrub_thread_timeout,
+    cct->_conf->osd_scrub_thread_suicide_timeout,
+    &disk_tp),
+  remove_wq(
+    store,
+    cct->_conf->osd_remove_thread_timeout,
+    cct->_conf->osd_remove_thread_suicide_timeout,
+    &disk_tp),
   service(this)
 {
   monc->set_messenger(client_messenger);
diff --git a/src/osd/OSD.h b/src/osd/OSD.h
index c8e5b8f..f5021ef 100644
--- a/src/osd/OSD.h
+++ b/src/osd/OSD.h
@@ -1452,8 +1452,8 @@ private:
     uint32_t num_shards;
 
     public:
-      ShardedOpWQ(uint32_t pnum_shards, OSD *o, time_t ti, ShardedThreadPool* tp):
-        ShardedThreadPool::ShardedWQ < pair <PGRef, OpRequestRef> >(ti, ti*10, tp),
+      ShardedOpWQ(uint32_t pnum_shards, OSD *o, time_t ti, time_t si, ShardedThreadPool* tp):
+        ShardedThreadPool::ShardedWQ < pair <PGRef, OpRequestRef> >(ti, si, tp),
         osd(o), num_shards(pnum_shards) {
         for(uint32_t i = 0; i < num_shards; i++) {
           char lock_name[32] = {0};
@@ -1563,9 +1563,9 @@ private:
     list<PG*> peering_queue;
     OSD *osd;
     set<PG*> in_use;
-    PeeringWQ(OSD *o, time_t ti, ThreadPool *tp)
+    PeeringWQ(OSD *o, time_t ti, time_t si, ThreadPool *tp)
       : ThreadPool::BatchWorkQueue<PG>(
-	"OSD::PeeringWQ", ti, ti*10, tp), osd(o) {}
+	"OSD::PeeringWQ", ti, si, tp), osd(o) {}
 
     void _dequeue(PG *pg) {
       for (list<PG*>::iterator i = peering_queue.begin();
@@ -1944,8 +1944,8 @@ protected:
   list<Command*> command_queue;
   struct CommandWQ : public ThreadPool::WorkQueue<Command> {
     OSD *osd;
-    CommandWQ(OSD *o, time_t ti, ThreadPool *tp)
-      : ThreadPool::WorkQueue<Command>("OSD::CommandWQ", ti, 0, tp), osd(o) {}
+    CommandWQ(OSD *o, time_t ti, time_t si, ThreadPool *tp)
+      : ThreadPool::WorkQueue<Command>("OSD::CommandWQ", ti, si, tp), osd(o) {}
 
     bool _empty() {
       return osd->command_queue.empty();
@@ -1998,8 +1998,8 @@ protected:
 
   struct RecoveryWQ : public ThreadPool::WorkQueue<PG> {
     OSD *osd;
-    RecoveryWQ(OSD *o, time_t ti, ThreadPool *tp)
-      : ThreadPool::WorkQueue<PG>("OSD::RecoveryWQ", ti, ti*10, tp), osd(o) {}
+    RecoveryWQ(OSD *o, time_t ti, time_t si, ThreadPool *tp)
+      : ThreadPool::WorkQueue<PG>("OSD::RecoveryWQ", ti, si, tp), osd(o) {}
 
     bool _empty() {
       return osd->recovery_queue.empty();
@@ -2056,8 +2056,8 @@ protected:
   
   struct SnapTrimWQ : public ThreadPool::WorkQueue<PG> {
     OSD *osd;
-    SnapTrimWQ(OSD *o, time_t ti, ThreadPool *tp)
-      : ThreadPool::WorkQueue<PG>("OSD::SnapTrimWQ", ti, 0, tp), osd(o) {}
+    SnapTrimWQ(OSD *o, time_t ti, time_t si, ThreadPool *tp)
+      : ThreadPool::WorkQueue<PG>("OSD::SnapTrimWQ", ti, si, tp), osd(o) {}
 
     bool _empty() {
       return osd->snap_trim_queue.empty();
@@ -2102,8 +2102,8 @@ protected:
 
   struct ScrubWQ : public ThreadPool::WorkQueue<PG> {
     OSD *osd;
-    ScrubWQ(OSD *o, time_t ti, ThreadPool *tp)
-      : ThreadPool::WorkQueue<PG>("OSD::ScrubWQ", ti, 0, tp), osd(o) {}
+    ScrubWQ(OSD *o, time_t ti, time_t si, ThreadPool *tp)
+      : ThreadPool::WorkQueue<PG>("OSD::ScrubWQ", ti, si, tp), osd(o) {}
 
     bool _empty() {
       return osd->scrub_queue.empty();
@@ -2149,8 +2149,8 @@ protected:
     list<MOSDRepScrub*> rep_scrub_queue;
 
   public:
-    RepScrubWQ(OSD *o, time_t ti, ThreadPool *tp)
-      : ThreadPool::WorkQueue<MOSDRepScrub>("OSD::RepScrubWQ", ti, 0, tp), osd(o) {}
+    RepScrubWQ(OSD *o, time_t ti, time_t si, ThreadPool *tp)
+      : ThreadPool::WorkQueue<MOSDRepScrub>("OSD::RepScrubWQ", ti, si, tp), osd(o) {}
 
     bool _empty() {
       return rep_scrub_queue.empty();
@@ -2202,9 +2202,9 @@ protected:
     public ThreadPool::WorkQueueVal<pair<PGRef, DeletingStateRef> > {
     ObjectStore *&store;
     list<pair<PGRef, DeletingStateRef> > remove_queue;
-    RemoveWQ(ObjectStore *&o, time_t ti, ThreadPool *tp)
+    RemoveWQ(ObjectStore *&o, time_t ti, time_t si, ThreadPool *tp)
       : ThreadPool::WorkQueueVal<pair<PGRef, DeletingStateRef> >(
-	"OSD::RemoveWQ", ti, 0, tp),
+	"OSD::RemoveWQ", ti, si, tp),
 	store(o) {}
 
     bool _empty() {
diff --git a/src/osd/PG.cc b/src/osd/PG.cc
index 7301094..bfe59b7 100644
--- a/src/osd/PG.cc
+++ b/src/osd/PG.cc
@@ -892,6 +892,9 @@ void PG::clear_primary_state()
 map<pg_shard_t, pg_info_t>::const_iterator PG::find_best_info(
   const map<pg_shard_t, pg_info_t> &infos) const
 {
+  /* See doc/dev/osd_internals/last_epoch_started.rst before attempting
+   * to make changes to this process.  Also, make sure to update it
+   * when you find bugs! */
   eversion_t min_last_update_acceptable = eversion_t::max();
   epoch_t max_last_epoch_started_found = 0;
   for (map<pg_shard_t, pg_info_t>::const_iterator i = infos.begin();
@@ -902,11 +905,16 @@ map<pg_shard_t, pg_info_t>::const_iterator PG::find_best_info(
       min_last_update_acceptable = eversion_t::max();
       max_last_epoch_started_found = i->second.history.last_epoch_started;
     }
-    if (max_last_epoch_started_found < i->second.last_epoch_started) {
+    if (!i->second.is_incomplete() &&
+	max_last_epoch_started_found < i->second.last_epoch_started) {
       min_last_update_acceptable = eversion_t::max();
       max_last_epoch_started_found = i->second.last_epoch_started;
     }
-    if (max_last_epoch_started_found == i->second.last_epoch_started) {
+  }
+  for (map<pg_shard_t, pg_info_t>::const_iterator i = infos.begin();
+       i != infos.end();
+       ++i) {
+    if (max_last_epoch_started_found <= i->second.last_epoch_started) {
       if (min_last_update_acceptable > i->second.last_update)
 	min_last_update_acceptable = i->second.last_update;
     }
diff --git a/src/osd/ReplicatedPG.cc b/src/osd/ReplicatedPG.cc
index 37b2f51..66fd948 100644
--- a/src/osd/ReplicatedPG.cc
+++ b/src/osd/ReplicatedPG.cc
@@ -2835,7 +2835,10 @@ ReplicatedPG::RepGather *ReplicatedPG::trim_object(const hobject_t &coid)
       ctx->log.back().mod_desc.mark_unrollbackable();
     }
   } else {
-    dout(10) << coid << " updating snapset on " << snapoid << dendl;
+    dout(10) << coid << " filtering snapset on " << snapoid << dendl;
+    snapset.filter(pool.info);
+    dout(10) << coid << " writing updated snapset on " << snapoid
+	     << ", snapset is " << snapset << dendl;
     ctx->log.push_back(
       pg_log_entry_t(
 	pg_log_entry_t::MODIFY,
@@ -5711,7 +5714,13 @@ void ReplicatedPG::finish_ctx(OpContext *ctx, int log_op_type, bool maintain_ssc
 
       if (!ctx->snapset_obc)
 	ctx->snapset_obc = get_object_context(snapoid, true);
-      bool got = ctx->snapset_obc->get_write_greedy(ctx->op);
+      bool got = false;
+      if (ctx->lock_to_release == OpContext::W_LOCK) {
+	got = ctx->snapset_obc->get_write_greedy(ctx->op);
+      } else {
+	assert(ctx->lock_to_release == OpContext::E_LOCK);
+	got = ctx->snapset_obc->get_excl(ctx->op);
+      }
       assert(got);
       dout(20) << " got greedy write on snapset_obc " << *ctx->snapset_obc << dendl;
       ctx->release_snapset_obc = true;
@@ -6520,6 +6529,35 @@ void ReplicatedPG::finish_promote(int r, CopyResults *results,
     return;
   }
 
+  if (r != -ENOENT && soid.is_snap()) {
+    if (results->snaps.empty()) {
+      // we must have read "snap" content from the head object in
+      // the base pool.  use snap_seq to construct what snaps should
+      // be for this clone (what is was before we evicted the clean
+      // clone from this pool, and what it will be when we flush and
+      // the clone eventually happens in the base pool).
+      SnapSet& snapset = obc->ssc->snapset;
+      vector<snapid_t>::iterator p = snapset.snaps.begin();
+      while (p != snapset.snaps.end() && *p > soid.snap)
+	++p;
+      while (p != snapset.snaps.end() && *p > results->snap_seq) {
+	results->snaps.push_back(*p);
+	++p;
+      }
+    }
+
+    dout(20) << __func__ << " snaps " << results->snaps << dendl;
+    filter_snapc(results->snaps);
+
+    dout(20) << __func__ << " filtered snaps " << results->snaps << dendl;
+    if (results->snaps.empty()) {
+      dout(20) << __func__
+	       << " snaps are empty, clone is invalid,"
+	       << " setting r to ENOENT" << dendl;
+      r = -ENOENT;
+    }
+  }
+
   if (r == -ENOENT && results->started_temp_obj) {
     dout(10) << __func__ << " abort; will clean up partial work" << dendl;
     ObjectContextRef tempobc = get_object_context(results->temp_oid, true);
@@ -6624,25 +6662,7 @@ void ReplicatedPG::finish_promote(int r, CopyResults *results,
     tctx->new_obs.oi.user_version = results->user_version;
 
     if (soid.snap != CEPH_NOSNAP) {
-      if (!results->snaps.empty()) {
-	tctx->new_obs.oi.snaps = results->snaps;
-      } else {
-	// we must have read "snap" content from the head object in
-	// the base pool.  use snap_seq to construct what snaps should
-	// be for this clone (what is was before we evicted the clean
-	// clone from this pool, and what it will be when we flush and
-	// the clone eventually happens in the base pool).
-	SnapSet& snapset = obc->ssc->snapset;
-	vector<snapid_t>::iterator p = snapset.snaps.begin();
-	while (p != snapset.snaps.end() && *p > soid.snap)
-	  ++p;
-	assert(p != snapset.snaps.end());
-	do {
-	  tctx->new_obs.oi.snaps.push_back(*p);
-	  ++p;
-	} while (p != snapset.snaps.end() && *p > results->snap_seq);
-      }
-      dout(20) << __func__ << " snaps " << tctx->new_obs.oi.snaps << dendl;
+      tctx->new_obs.oi.snaps = results->snaps;
       assert(!tctx->new_obs.oi.snaps.empty());
       assert(obc->ssc->snapset.clone_size.count(soid.snap));
       assert(obc->ssc->snapset.clone_size[soid.snap] ==
@@ -6779,8 +6799,10 @@ int ReplicatedPG::start_flush(
 	   << " " << (blocking ? "blocking" : "non-blocking/best-effort")
 	   << dendl;
 
+  // get a filtered snapset, need to remove removed snaps
+  SnapSet snapset = obc->ssc->snapset.get_filtered(pool.info);
+
   // verify there are no (older) check for dirty clones
-  SnapSet& snapset = obc->ssc->snapset;
   {
     dout(20) << " snapset " << snapset << dendl;
     vector<snapid_t>::reverse_iterator p = snapset.clones.rbegin();
diff --git a/src/osd/ReplicatedPG.h b/src/osd/ReplicatedPG.h
index da0c75b..5b5bc23 100644
--- a/src/osd/ReplicatedPG.h
+++ b/src/osd/ReplicatedPG.h
@@ -852,7 +852,20 @@ protected:
 	requeue_snaptrimmer_clone ||
 	requeue_snaptrimmer_snapset)
       queue_snap_trim();
-    requeue_ops(to_req);
+
+    if (!to_req.empty()) {
+      assert(ctx->obc);
+      // requeue at front of scrub blocking queue if we are blocked by scrub
+      if (scrubber.write_blocked_by_scrub(ctx->obc->obs.oi.soid.get_head())) {
+	waiting_for_active.splice(
+	  waiting_for_active.begin(),
+	  to_req,
+	  to_req.begin(),
+	  to_req.end());
+      } else {
+	requeue_ops(to_req);
+      }
+    }
   }
 
   // replica ops
diff --git a/src/osd/osd_types.cc b/src/osd/osd_types.cc
index e5954c0..3774452 100644
--- a/src/osd/osd_types.cc
+++ b/src/osd/osd_types.cc
@@ -770,7 +770,7 @@ std::string pg_state_string(int state)
   return ret;
 }
 
-int pg_string_state(std::string state)
+int pg_string_state(const std::string& state)
 {
   int type;
   if (state == "active")
@@ -793,16 +793,18 @@ int pg_string_state(std::string state)
     type = PG_STATE_INCONSISTENT;
   else if (state == "peering")
     type = PG_STATE_PEERING;
-  else if (state == "recoverying")
+  else if (state == "repair")
+    type = PG_STATE_REPAIR;
+  else if (state == "recovering")
     type = PG_STATE_RECOVERING;
   else if (state == "backfill_wait")
     type = PG_STATE_BACKFILL_WAIT;
   else if (state == "incomplete")
     type = PG_STATE_INCOMPLETE;
-  else if (state == "remapped")
-    type = PG_STATE_REMAPPED;
   else if (state == "stale")
     type = PG_STATE_STALE;
+  else if (state == "remapped")
+    type = PG_STATE_REMAPPED;
   else if (state == "deep_scrub")
     type = PG_STATE_DEEP_SCRUB;
   else if (state == "backfill")
@@ -4084,6 +4086,25 @@ uint64_t SnapSet::get_clone_bytes(snapid_t clone) const
   return size;
 }
 
+void SnapSet::filter(const pg_pool_t &pinfo)
+{
+  vector<snapid_t> oldsnaps;
+  oldsnaps.swap(snaps);
+  for (vector<snapid_t>::const_iterator i = oldsnaps.begin();
+       i != oldsnaps.end();
+       ++i) {
+    if (!pinfo.is_removed_snap(*i))
+      snaps.push_back(*i);
+  }
+}
+
+SnapSet SnapSet::get_filtered(const pg_pool_t &pinfo) const
+{
+  SnapSet ss = *this;
+  ss.filter(pinfo);
+  return ss;
+}
+
 // -- watch_info_t --
 
 void watch_info_t::encode(bufferlist& bl) const
diff --git a/src/osd/osd_types.h b/src/osd/osd_types.h
index 531f163..6525a0c 100644
--- a/src/osd/osd_types.h
+++ b/src/osd/osd_types.h
@@ -772,7 +772,7 @@ inline ostream& operator<<(ostream& out, const osd_stat_t& s) {
 
 std::string pg_state_string(int state);
 std::string pg_vector_string(const vector<int32_t> &a);
-int pg_string_state(std::string state);
+int pg_string_state(const std::string& state);
 
 
 /*
@@ -2766,6 +2766,9 @@ struct SnapSet {
     }
     return max;
   }
+
+  SnapSet get_filtered(const pg_pool_t &pinfo) const;
+  void filter(const pg_pool_t &pinfo);
 };
 WRITE_CLASS_ENCODER(SnapSet)
 
diff --git a/src/osdc/ObjectCacher.cc b/src/osdc/ObjectCacher.cc
index 75174a6..95f4b8f 100644
--- a/src/osdc/ObjectCacher.cc
+++ b/src/osdc/ObjectCacher.cc
@@ -1144,6 +1144,7 @@ int ObjectCacher::_readx(OSDRead *rd, ObjectSet *oset, Context *onfinish,
            ++bh_it) {
 	uint64_t rx_bytes = static_cast<uint64_t>(
 	  stat_rx + bh_it->second->length());
+        bytes_not_in_cache += bh_it->second->length();
 	if (!waitfor_read.empty() || rx_bytes > max_size) {
 	  // cache is full with concurrent reads -- wait for rx's to complete
 	  // to constrain memory growth (especially during copy-ups)
@@ -1165,7 +1166,6 @@ int ObjectCacher::_readx(OSDRead *rd, ObjectSet *oset, Context *onfinish,
 	    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/perfglue/Makefile.am b/src/perfglue/Makefile.am
index 9228b21..77c3085 100644
--- a/src/perfglue/Makefile.am
+++ b/src/perfglue/Makefile.am
@@ -6,7 +6,14 @@ libperfglue_la_LIBADD = -ltcmalloc
 AM_CFLAGS += -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free
 AM_CXXFLAGS += -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free
 else
+if WITH_TCMALLOC_MINIMAL
+libperfglue_la_SOURCES += perfglue/heap_profiler.cc
+libperfglue_la_LIBADD = -ltcmalloc_minimal
+AM_CFLAGS += -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free
+AM_CXXFLAGS += -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free
+else
 libperfglue_la_SOURCES += perfglue/disabled_heap_profiler.cc
+endif # WITH_TCMALLOC_MINIMAL
 endif # WITH_TCMALLOC
 
 if WITH_PROFILER
diff --git a/src/perfglue/heap_profiler.cc b/src/perfglue/heap_profiler.cc
index 0fe1f9a..a0307ca 100644
--- a/src/perfglue/heap_profiler.cc
+++ b/src/perfglue/heap_profiler.cc
@@ -61,7 +61,11 @@ void ceph_heap_release_free_memory()
 
 bool ceph_heap_profiler_running()
 {
+#ifdef HAVE_LIBTCMALLOC
   return IsHeapProfilerRunning();
+#else
+  return false;
+#endif
 }
 
 static void get_profile_name(char *profile_name, int profile_name_len)
@@ -83,21 +87,27 @@ static void get_profile_name(char *profile_name, int profile_name_len)
 
 void ceph_heap_profiler_start()
 {
+#ifdef HAVE_LIBTCMALLOC
   char profile_name[PATH_MAX];
   get_profile_name(profile_name, sizeof(profile_name)); 
   generic_dout(0) << "turning on heap profiler with prefix "
 		  << profile_name << dendl;
   HeapProfilerStart(profile_name);
+#endif
 }
 
 void ceph_heap_profiler_stop()
 {
+#ifdef HAVE_LIBTCMALLOC
   HeapProfilerStop();
+#endif
 }
 
 void ceph_heap_profiler_dump(const char *reason)
 {
+#ifdef HAVE_LIBTCMALLOC
   HeapProfilerDump(reason);
+#endif
 }
 
 #define HEAP_PROFILER_STATS_SIZE 2048
@@ -105,6 +115,7 @@ void ceph_heap_profiler_dump(const char *reason)
 void ceph_heap_profiler_handle_command(const std::vector<std::string>& cmd,
                                        ostream& out)
 {
+#ifdef HAVE_LIBTCMALLOC
   if (cmd.size() == 1 && cmd[0] == "dump") {
     if (!ceph_heap_profiler_running()) {
       out << "heap profiler not running; can't dump";
@@ -124,7 +135,9 @@ void ceph_heap_profiler_handle_command(const std::vector<std::string>& cmd,
   } else if (cmd.size() == 1 && cmd[0] == "release") {
     ceph_heap_release_free_memory();
     out << g_conf->name << " releasing free RAM back to system.";
-  } else if (cmd.size() == 1 && cmd[0] == "stats") {
+  } else
+#endif
+  if (cmd.size() == 1 && cmd[0] == "stats") {
     char heap_stats[HEAP_PROFILER_STATS_SIZE];
     ceph_heap_profiler_stats(heap_stats, sizeof(heap_stats));
     out << g_conf->name << " tcmalloc heap stats:"
diff --git a/src/pybind/rbd.py b/src/pybind/rbd.py
index 334e4c7..35bf5c7 100644
--- a/src/pybind/rbd.py
+++ b/src/pybind/rbd.py
@@ -466,8 +466,12 @@ class Image(object):
             pool = create_string_buffer(size)
             name = create_string_buffer(size)
             snapname = create_string_buffer(size)
-            ret = self.librbd.rbd_get_parent_info(self.image, pool, len(pool),
-                name, len(name), snapname, len(snapname))
+            ret = self.librbd.rbd_get_parent_info(self.image, byref(pool),
+                                                  c_size_t(size),
+                                                  byref(name),
+                                                  c_size_t(size),
+                                                  byref(snapname),
+                                                  c_size_t(size))
             if ret == -errno.ERANGE:
                 size *= 2
 
diff --git a/src/rgw/logrotate.conf b/src/rgw/logrotate.conf
index ec47f00..7e527e8 100644
--- a/src/rgw/logrotate.conf
+++ b/src/rgw/logrotate.conf
@@ -7,7 +7,7 @@
         if which invoke-rc.d > /dev/null 2>&1 && [ -x `which invoke-rc.d` ]; then
             invoke-rc.d radosgw reload >/dev/null
         elif which service > /dev/null 2>&1 && [ -x `which service` ]; then
-            service radosgw reload >/dev/null
+            service ceph-radosgw reload >/dev/null
         fi
         # Possibly reload twice, but depending on ceph.conf the reload above may be a no-op
         if which initctl > /dev/null 2>&1 && [ -x `which initctl` ]; then
diff --git a/src/rgw/rgw_admin.cc b/src/rgw/rgw_admin.cc
index a7a0039..5debefb 100644
--- a/src/rgw/rgw_admin.cc
+++ b/src/rgw/rgw_admin.cc
@@ -908,9 +908,10 @@ int check_min_obj_stripe_size(RGWRados *store, RGWBucketInfo& bucket_info, rgw_o
 }
 
 
-int check_obj_locator_underscore(RGWBucketInfo& bucket_info, rgw_obj& obj, rgw_obj_key& key, bool fix, Formatter *f) {
+int check_obj_locator_underscore(RGWBucketInfo& bucket_info, rgw_obj& obj, rgw_obj_key& key, bool fix, bool remove_bad, Formatter *f) {
   f->open_object_section("object");
   f->open_object_section("key");
+  f->dump_string("type", "head");
   f->dump_string("name", key.name);
   f->dump_string("instance", key.instance);
   f->close_section();
@@ -936,8 +937,8 @@ int check_obj_locator_underscore(RGWBucketInfo& bucket_info, rgw_obj& obj, rgw_o
 
   string status = (needs_fixing ? "needs_fixing" : "ok");
 
-  if (needs_fixing && fix) {
-    ret = store->fix_head_obj_locator(obj.bucket, key);
+  if ((needs_fixing || remove_bad) && fix) {
+    ret = store->fix_head_obj_locator(obj.bucket, needs_fixing, remove_bad, key);
     if (ret < 0) {
       cerr << "ERROR: fix_head_object_locator() returned ret=" << ret << std::endl;
       goto done;
@@ -953,8 +954,43 @@ done:
   return 0;
 }
 
-int do_check_object_locator(const string& bucket_name, bool fix, Formatter *f)
+int check_obj_tail_locator_underscore(RGWBucketInfo& bucket_info, rgw_obj& obj, rgw_obj_key& key, bool fix, Formatter *f) {
+  f->open_object_section("object");
+  f->open_object_section("key");
+  f->dump_string("type", "tail");
+  f->dump_string("name", key.name);
+  f->dump_string("instance", key.instance);
+  f->close_section();
+
+  string oid;
+  string locator;
+
+  bool needs_fixing;
+  string status;
+
+  int ret = store->fix_tail_obj_locator(obj.bucket, key, fix, &needs_fixing);
+  if (ret < 0) {
+    cerr << "ERROR: fix_tail_object_locator_underscore() returned ret=" << ret << std::endl;
+    status = "failed";
+  } else {
+    status = (needs_fixing && !fix ? "needs_fixing" : "ok");
+  }
+
+  f->dump_bool("needs_fixing", needs_fixing);
+  f->dump_string("status", status);
+
+  f->close_section();
+
+  return 0;
+}
+
+int do_check_object_locator(const string& bucket_name, bool fix, bool remove_bad, Formatter *f)
 {
+  if (remove_bad && !fix) {
+    cerr << "ERROR: can't have remove_bad specified without fix" << std::endl;
+    return -EINVAL;
+  }
+
   RGWBucketInfo bucket_info;
   rgw_bucket bucket;
   string bucket_id;
@@ -986,7 +1022,7 @@ int do_check_object_locator(const string& bucket_name, bool fix, Formatter *f)
   list_op.params.delim = delim;
   list_op.params.marker = rgw_obj_key(marker);
   list_op.params.ns = ns;
-  list_op.params.enforce_ns = false;
+  list_op.params.enforce_ns = true;
   list_op.params.list_versions = true;
   
   f->open_array_section("check_objects");
@@ -1005,8 +1041,12 @@ int do_check_object_locator(const string& bucket_name, bool fix, Formatter *f)
       rgw_obj obj(bucket, key);
 
       if (key.name[0] == '_') {
-        ret = check_obj_locator_underscore(bucket_info, obj, key, fix, f);
+        ret = check_obj_locator_underscore(bucket_info, obj, key, fix, remove_bad, f);
         /* ignore return code, move to the next one */
+	
+	if (ret >= 0) {
+          ret = check_obj_tail_locator_underscore(bucket_info, obj, key, fix, f);
+	}
       }
     }
     f->flush(cout);
@@ -1056,6 +1096,7 @@ int main(int argc, char **argv)
   int yes_i_really_mean_it = false;
   int delete_child_objects = false;
   int fix = false;
+  int remove_bad = false;
   int check_head_obj_locator = false;
   int max_buckets = -1;
   map<string, bool> categories;
@@ -1241,6 +1282,8 @@ int main(int argc, char **argv)
       // do nothing
     } else if (ceph_argparse_binary_flag(args, i, &fix, NULL, "--fix", (char*)NULL)) {
       // do nothing
+    } else if (ceph_argparse_binary_flag(args, i, &remove_bad, NULL, "--remove-bad", (char*)NULL)) {
+      // do nothing
     } else if (ceph_argparse_binary_flag(args, i, &check_head_obj_locator, NULL, "--check-head-obj-locator", (char*)NULL)) {
       // do nothing
     } else if (ceph_argparse_binary_flag(args, i, &check_objects, NULL, "--check-objects", (char*)NULL)) {
@@ -1706,14 +1749,6 @@ int main(int argc, char **argv)
       return -ret;
     }
 
-    ret = user.info(info, &err_msg);
-    if (ret < 0) {
-      cerr << "could not fetch user info: " << err_msg << std::endl;
-      return -ret;
-    }
-
-    show_user_info(info, formatter);
-
     break;
   case OPT_SUBUSER_RM:
     ret = user.subusers.remove(user_op, &err_msg);
@@ -2468,7 +2503,7 @@ next:
         cerr << "ERROR: need to specify bucket name" << std::endl;
         return EINVAL;
       }
-      do_check_object_locator(bucket_name, fix, formatter);
+      do_check_object_locator(bucket_name, fix, remove_bad, formatter);
     } else {
       RGWBucketAdminOp::check_index(store, bucket_op, f);
     }
diff --git a/src/rgw/rgw_civetweb.cc b/src/rgw/rgw_civetweb.cc
index 901b2de..eea3b14 100644
--- a/src/rgw/rgw_civetweb.cc
+++ b/src/rgw/rgw_civetweb.cc
@@ -13,17 +13,22 @@ int RGWMongoose::write_data(const char *buf, int len)
 {
   if (!header_done) {
     header_data.append(buf, len);
-    return 0;
+    return len;
   }
   if (!sent_header) {
     data.append(buf, len);
-    return 0;
+    return len;
+  }
+  int r = mg_write(conn, buf, len);
+  if (r == 0) {
+    /* didn't send anything, error out */
+    return -EIO;
   }
-  return mg_write(conn, buf, len);
+  return r;
 }
 
 RGWMongoose::RGWMongoose(mg_connection *_conn, int _port) : conn(_conn), port(_port), header_done(false), sent_header(false), has_content_length(false),
-                                                 explicit_keepalive(false)
+                                                 explicit_keepalive(false), explicit_conn_close(false)
 {
 }
 
@@ -88,6 +93,7 @@ void RGWMongoose::init_env(CephContext *cct)
 
     if (strcasecmp(header->name, "connection") == 0) {
       explicit_keepalive = (strcasecmp(header->value, "keep-alive") == 0);
+      explicit_conn_close = (strcasecmp(header->value, "close") == 0);
     }
 
     int len = strlen(header->name) + 5; /* HTTP_ prepended */
@@ -147,6 +153,20 @@ int RGWMongoose::send_100_continue()
   return mg_write(conn, buf, sizeof(buf) - 1);
 }
 
+static void dump_date_header(bufferlist &out)
+{
+  char timestr[TIME_BUF_SIZE];
+  const time_t gtime = time(NULL);
+  struct tm result;
+  struct tm const * const tmp = gmtime_r(&gtime, &result);
+
+  if (tmp == NULL)
+    return;
+
+  if (strftime(timestr, sizeof(timestr), "Date: %a, %d %b %Y %H:%M:%S %Z\r\n", tmp))
+    out.append(timestr);
+}
+
 int RGWMongoose::complete_header()
 {
   header_done = true;
@@ -155,8 +175,12 @@ int RGWMongoose::complete_header()
     return 0;
   }
 
+  dump_date_header(header_data);
+
   if (explicit_keepalive)
     header_data.append("Connection: Keep-Alive\r\n");
+  else if (explicit_conn_close)
+    header_data.append("Connection: close\r\n");
 
   header_data.append("\r\n");
 
diff --git a/src/rgw/rgw_civetweb.h b/src/rgw/rgw_civetweb.h
index 9a7594f..1cee5c8 100644
--- a/src/rgw/rgw_civetweb.h
+++ b/src/rgw/rgw_civetweb.h
@@ -3,6 +3,7 @@
 
 #ifndef CEPH_RGW_MONGOOSE_H
 #define CEPH_RGW_MONGOOSE_H
+#define TIME_BUF_SIZE 128
 
 #include "rgw_client_io.h"
 
@@ -23,6 +24,7 @@ class RGWMongoose : public RGWClientIO
   bool sent_header;
   bool has_content_length;
   bool explicit_keepalive;
+  bool explicit_conn_close;
 
 public:
   void init_env(CephContext *cct);
diff --git a/src/rgw/rgw_client_io.cc b/src/rgw/rgw_client_io.cc
index 5e8edbf..1f8b803 100644
--- a/src/rgw/rgw_client_io.cc
+++ b/src/rgw/rgw_client_io.cc
@@ -56,7 +56,12 @@ int RGWClientIO::write(const char *buf, int len)
     return ret;
 
   if (account)
-    bytes_sent += len;
+    bytes_sent += ret;
+
+  if (ret < len) {
+    /* sent less than tried to send, error out */
+    return -EIO;
+  }
 
   return 0;
 }
diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h
index e1688ee..6c7912b 100644
--- a/src/rgw/rgw_common.h
+++ b/src/rgw/rgw_common.h
@@ -1230,7 +1230,7 @@ public:
      * having object locator at all for most objects but the ones that started with underscore as
      * these were escaped.
      */
-    if (orig_obj[0] == '_') {
+    if (orig_obj[0] == '_' && ns.empty()) {
       loc = orig_obj;
     }
   }
diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc
index a1732da..bf6c3e7 100644
--- a/src/rgw/rgw_op.cc
+++ b/src/rgw/rgw_op.cc
@@ -1399,10 +1399,11 @@ void RGWCreateBucket::execute()
     /* bucket already existed, might have raced with another bucket creation, or
      * might be partial bucket creation that never completed. Read existing bucket
      * info, verify that the reported bucket owner is the current user.
-     * If all is ok then update the user's list of buckets
+     * If all is ok then update the user's list of buckets.
+     * Otherwise inform client about a name conflict.
      */
     if (info.owner.compare(s->user.user_id) != 0) {
-      ret = -ERR_BUCKET_EXISTS;
+      ret = -EEXIST;
       return;
     }
     s->bucket = info.bucket;
@@ -1414,10 +1415,9 @@ void RGWCreateBucket::execute()
     if (ret < 0) {
       ldout(s->cct, 0) << "WARNING: failed to unlink bucket: ret=" << ret << dendl;
     }
-  }
-
-  if (ret == -EEXIST)
+  } else if (ret == -EEXIST || (ret == 0 && existed)) {
     ret = -ERR_BUCKET_EXISTS;
+  }
 }
 
 int RGWDeleteBucket::verify_permission()
@@ -2303,6 +2303,7 @@ int RGWCopyObj::verify_permission()
 
   if (src_bucket_name.compare(dest_bucket_name) == 0) { /* will only happen if s->local_source */
     dest_bucket_info = src_bucket_info;
+    dest_attrs = src_attrs;
   } else {
     ret = store->get_bucket_info(obj_ctx, dest_bucket_name, dest_bucket_info, NULL, &dest_attrs);
     if (ret < 0)
diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc
index 38718b4..6717c54 100644
--- a/src/rgw/rgw_rados.cc
+++ b/src/rgw/rgw_rados.cc
@@ -915,11 +915,36 @@ RGWPutObjProcessor_Aio::~RGWPutObjProcessor_Aio()
     return;
 
   list<rgw_obj>::iterator iter;
+  bool is_multipart_obj = false;
+  rgw_obj multipart_obj;
+
+  /** 
+   * We should delete the object in the "multipart" namespace to avoid race condition. 
+   * Such race condition is caused by the fact that the multipart object is the gatekeeper of a multipart 
+   * upload, when it is deleted, a second upload would start with the same suffix("2/"), therefore, objects
+   * written by the second upload may be deleted by the first upload.
+   * details is describled on #11749
+   */ 
   for (iter = written_objs.begin(); iter != written_objs.end(); ++iter) {
-    rgw_obj& obj = *iter;
+    rgw_obj &obj = *iter;
+    if (RGW_OBJ_NS_MULTIPART == obj.ns) {
+      ldout(store->ctx(), 5) << "NOTE: we should not process the multipart object (" << obj << ") here" << dendl;
+      multipart_obj = *iter;
+      is_multipart_obj = true;
+      continue;
+    }
+
     int r = store->delete_obj(obj_ctx, bucket_info, obj, 0, 0);
     if (r < 0 && r != -ENOENT) {
-      ldout(store->ctx(), 0) << "WARNING: failed to remove obj (" << obj << "), leaked" << dendl;
+      ldout(store->ctx(), 5) << "WARNING: failed to remove obj (" << obj << "), leaked" << dendl;
+    }
+  }
+
+  if (true == is_multipart_obj) {
+    ldout(store->ctx(), 5) << "NOTE: we are going to process the multipart obj (" << multipart_obj << dendl;
+    int r = store->delete_obj(obj_ctx, bucket_info, multipart_obj, 0, 0);
+    if (r < 0 && r != -ENOENT) {
+      ldout(store->ctx(), 0) << "WARNING: failed to remove obj (" << multipart_obj << "), leaked" << dendl;
     }
   }
 }
@@ -2966,7 +2991,7 @@ int RGWRados::get_obj_ref(const rgw_obj& obj, rgw_rados_ref *ref, rgw_bucket *bu
  * fixes an issue where head objects were supposed to have a locator created, but ended
  * up without one
  */
-int RGWRados::fix_head_obj_locator(rgw_bucket& bucket, rgw_obj_key& key)
+int RGWRados::fix_head_obj_locator(rgw_bucket& bucket, bool copy_obj, bool remove_bad, rgw_obj_key& key)
 {
   string oid;
   string locator;
@@ -3016,19 +3041,174 @@ int RGWRados::fix_head_obj_locator(rgw_bucket& bucket, rgw_obj_key& key)
     return -EIO;
   }
 
-  librados::ObjectWriteOperation wop;
+  if (copy_obj) {
+    librados::ObjectWriteOperation wop;
 
-  wop.mtime(&mtime);
+    wop.mtime(&mtime);
 
-  map<string, bufferlist>::iterator iter;
-  for (iter = attrs.begin(); iter != attrs.end(); ++iter) {
-    wop.setxattr(iter->first.c_str(), iter->second);
+    map<string, bufferlist>::iterator iter;
+    for (iter = attrs.begin(); iter != attrs.end(); ++iter) {
+      wop.setxattr(iter->first.c_str(), iter->second);
+    }
+
+    wop.write(0, data);
+
+    ioctx.locator_set_key(locator);
+    ioctx.operate(oid, &wop);
+  }
+
+  if (remove_bad) {
+    ioctx.locator_set_key(string());
+
+    ret = ioctx.remove(oid);
+    if (ret < 0) {
+      lderr(cct) << "ERROR: failed to remove original bad object" << dendl;
+      return ret;
+    }
+  }
+
+  return 0;
+}
+
+int RGWRados::move_rados_obj(librados::IoCtx& src_ioctx,
+			     const string& src_oid, const string& src_locator,
+		             librados::IoCtx& dst_ioctx,
+			     const string& dst_oid, const string& dst_locator)
+{
+
+#define COPY_BUF_SIZE (4 * 1024 * 1024)
+  bool done = false;
+  uint64_t chunk_size = COPY_BUF_SIZE;
+  uint64_t ofs = 0;
+  int ret = 0;
+  time_t mtime = 0;
+  uint64_t size;
+
+  if (src_oid == dst_oid && src_locator == dst_locator) {
+    return 0;
+  }
+
+  src_ioctx.locator_set_key(src_locator);
+  dst_ioctx.locator_set_key(dst_locator);
+
+  do {
+    bufferlist data;
+    ObjectReadOperation rop;
+    ObjectWriteOperation wop;
+
+    if (ofs == 0) {
+      rop.stat(&size, &mtime, NULL);
+    }
+    rop.read(ofs, chunk_size, &data, NULL);
+    ret = src_ioctx.operate(src_oid, &rop, NULL);
+    if (ret < 0) {
+      goto done_err;
+    }
+
+    if (data.length() == 0) {
+      break;
+    }
+
+    if (ofs == 0) {
+      wop.create(true); /* make it exclusive */
+      wop.mtime(&mtime);
+    }
+    wop.write(ofs, data);
+    ret = dst_ioctx.operate(dst_oid, &wop);
+    ofs += data.length();
+    done = data.length() != chunk_size;
+  } while (!done);
+
+  if (ofs != size) {
+    lderr(cct) << "ERROR: " << __func__ << ": copying " << src_oid << " -> " << dst_oid
+               << ": expected " << size << " bytes to copy, ended up with " << ofs << dendl;
+    ret = -EIO;
+    goto done_err;
   }
 
-  wop.write(0, data);
+  src_ioctx.remove(src_oid);
 
-  ioctx.locator_set_key(locator);
-  ioctx.operate(oid, &wop);
+  return 0;
+
+done_err:
+  lderr(cct) << "ERROR: failed to copy " << src_oid << " -> " << dst_oid << dendl;
+  return ret;
+}
+
+/*
+ * fixes an issue where head objects were supposed to have a locator created, but ended
+ * up without one
+ */
+int RGWRados::fix_tail_obj_locator(rgw_bucket& bucket, rgw_obj_key& key, bool fix, bool *need_fix)
+{
+  string locator;
+
+  rgw_obj obj(bucket, key);
+
+  if (need_fix) {
+    *need_fix = false;
+  }
+
+  rgw_rados_ref ref;
+  int r = get_obj_ref(obj, &ref, &bucket);
+  if (r < 0) {
+    return r;
+  }
+
+  RGWObjState *astate = NULL;
+  RGWObjectCtx rctx(this);
+  r = get_obj_state(&rctx, obj, &astate, NULL);
+  if (r < 0)
+    return r;
+
+  if (astate->has_manifest) {
+    RGWObjManifest::obj_iterator miter;
+    RGWObjManifest& manifest = astate->manifest;
+    for (miter = manifest.obj_begin(); miter != manifest.obj_end(); ++miter) {
+      rgw_obj loc = miter.get_location();
+      string oid;
+      string locator;
+
+      if (loc.ns.empty()) {
+	/* continue, we're only interested in tail objects */
+	continue;
+      }
+
+      get_obj_bucket_and_oid_loc(loc, bucket, oid, locator);
+      ref.ioctx.locator_set_key(locator);
+
+      ldout(cct, 20) << __func__ << ": key=" << key << " oid=" << oid << " locator=" << locator << dendl;
+
+      r = ref.ioctx.stat(oid, NULL, NULL);
+      if (r != -ENOENT) {
+	continue;
+      }
+
+      string bad_loc;
+      prepend_bucket_marker(bucket, loc.get_orig_obj(), bad_loc);
+
+      /* create a new ioctx with the bad locator */
+      librados::IoCtx src_ioctx;
+      src_ioctx.dup(ref.ioctx);
+      src_ioctx.locator_set_key(bad_loc);
+
+      r = src_ioctx.stat(oid, NULL, NULL);
+      if (r != 0) {
+	/* cannot find a broken part */
+	continue;
+      }
+      ldout(cct, 20) << __func__ << ": found bad object part: " << loc << dendl;
+      if (need_fix) {
+        *need_fix = true;
+      }
+      if (fix) {
+        r = move_rados_obj(src_ioctx, oid, bad_loc, ref.ioctx, oid, locator);
+        if (r < 0) {
+          lderr(cct) << "ERROR: copy_rados_obj() on oid=" << oid << " returned r=" << r << dendl;
+        }
+      }
+    }
+  }
 
   return 0;
 }
diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h
index b1cfac8..18213cf 100644
--- a/src/rgw/rgw_rados.h
+++ b/src/rgw/rgw_rados.h
@@ -2031,7 +2031,12 @@ public:
                          map<RGWObjCategory, RGWStorageStats> *calculated_stats);
   int bucket_rebuild_index(rgw_bucket& bucket);
   int remove_objs_from_index(rgw_bucket& bucket, list<rgw_obj_key>& oid_list);
-  int fix_head_obj_locator(rgw_bucket& bucket, rgw_obj_key& key);
+  int move_rados_obj(librados::IoCtx& src_ioctx,
+		     const string& src_oid, const string& src_locator,
+	             librados::IoCtx& dst_ioctx,
+		     const string& dst_oid, const string& dst_locator);
+  int fix_head_obj_locator(rgw_bucket& bucket, bool copy_obj, bool remove_bad, rgw_obj_key& key);
+  int fix_tail_obj_locator(rgw_bucket& bucket, rgw_obj_key& key, bool fix, bool *need_fix);
 
   int cls_user_get_header(const string& user_id, cls_user_header *header);
   int cls_user_get_header_async(const string& user_id, RGWGetUserHeader_CB *ctx);
diff --git a/src/rgw/rgw_rest.cc b/src/rgw/rgw_rest.cc
index 1ac46e9..d385d62 100644
--- a/src/rgw/rgw_rest.cc
+++ b/src/rgw/rgw_rest.cc
@@ -360,7 +360,7 @@ void dump_bucket_from_state(struct req_state *s)
   int expose_bucket = g_conf->rgw_expose_bucket;
   if (expose_bucket) {
     if (!s->bucket_name_str.empty())
-      s->cio->print("Bucket: \"%s\"\r\n", s->bucket_name_str.c_str());
+      s->cio->print("Bucket: %s\r\n", s->bucket_name_str.c_str());
   }
 }
 
@@ -1301,6 +1301,22 @@ RGWRESTMgr::~RGWRESTMgr()
   delete default_mgr;
 }
 
+static int64_t parse_content_length(const char *content_length)
+{
+  int64_t len = -1;
+
+  if (*content_length == '\0') {
+    len = 0;
+  } else {
+    string err;
+    len = strict_strtoll(content_length, 10, &err);
+    if (!err.empty()) {
+      len = -1;
+    }
+  }
+
+  return len;
+}
 int RGWREST::preprocess(struct req_state *s, RGWClientIO *cio)
 {
   req_info& info = s->info;
@@ -1348,7 +1364,58 @@ int RGWREST::preprocess(struct req_state *s, RGWClientIO *cio)
   }
 
   url_decode(s->info.request_uri, s->decoded_uri);
-  s->length = info.env->get("CONTENT_LENGTH");
+
+  /* FastCGI specification, section 6.3
+   * http://www.fastcgi.com/devkit/doc/fcgi-spec.html#S6.3
+   * ===
+   * The Authorizer application receives HTTP request information from the Web
+   * server on the FCGI_PARAMS stream, in the same format as a Responder. The
+   * Web server does not send CONTENT_LENGTH, PATH_INFO, PATH_TRANSLATED, and
+   * SCRIPT_NAME headers.
+   * ===
+   * Ergo if we are in Authorizer role, we MUST look at HTTP_CONTENT_LENGTH
+   * instead of CONTENT_LENGTH for the Content-Length.
+   *
+   * There is one slight wrinkle in this, and that's older versions of 
+   * nginx/lighttpd/apache setting BOTH headers. As a result, we have to check
+   * both headers and can't always simply pick A or B.
+   */
+  const char* content_length = info.env->get("CONTENT_LENGTH");
+  const char* http_content_length = info.env->get("HTTP_CONTENT_LENGTH");
+  if (!http_content_length != !content_length) {
+    /* Easy case: one or the other is missing */
+    s->length = (content_length ? content_length : http_content_length);
+  } else if (s->cct->_conf->rgw_content_length_compat && content_length && http_content_length) {
+    /* Hard case: Both are set, we have to disambiguate */
+    int64_t content_length_i, http_content_length_i;
+
+    content_length_i = parse_content_length(content_length);
+    http_content_length_i = parse_content_length(http_content_length);
+
+    // Now check them:
+    if (http_content_length_i < 0) {
+      // HTTP_CONTENT_LENGTH is invalid, ignore it
+    } else if (content_length_i < 0) {
+      // CONTENT_LENGTH is invalid, and HTTP_CONTENT_LENGTH is valid
+      // Swap entries
+      content_length = http_content_length;
+    } else {
+      // both CONTENT_LENGTH and HTTP_CONTENT_LENGTH are valid
+      // Let's pick the larger size
+      if (content_length_i < http_content_length_i) {
+	// prefer the larger value
+	content_length = http_content_length;
+      }
+    }
+    s->length = content_length;
+    // End of: else if (s->cct->_conf->rgw_content_length_compat && content_length &&
+    // http_content_length)
+  } else {
+    /* no content length was defined */
+    s->length = NULL;
+  }
+
+
   if (s->length) {
     if (*s->length == '\0') {
       s->content_length = 0;
diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc
index bca4533..768766f 100644
--- a/src/rgw/rgw_rest_s3.cc
+++ b/src/rgw/rgw_rest_s3.cc
@@ -1737,7 +1737,7 @@ void RGWListMultipart_ObjStore_S3::send_response()
 
   if (ret == 0) { 
     dump_start(s);
-    s->formatter->open_object_section_in_ns("ListMultipartUploadResult",
+    s->formatter->open_object_section_in_ns("ListPartsResult",
 		    "http://s3.amazonaws.com/doc/2006-03-01/");
     map<uint32_t, RGWUploadPartInfo>::iterator iter;
     map<uint32_t, RGWUploadPartInfo>::reverse_iterator test_iter;
diff --git a/src/rgw/rgw_rest_swift.cc b/src/rgw/rgw_rest_swift.cc
index 427ee5b..9513cd6 100644
--- a/src/rgw/rgw_rest_swift.cc
+++ b/src/rgw/rgw_rest_swift.cc
@@ -58,7 +58,8 @@ void RGWListBuckets_ObjStore_SWIFT::send_response_begin(bool has_buckets)
 
   if (!ret) {
     dump_start(s);
-    s->formatter->open_array_section("account");
+    s->formatter->open_array_section_with_attrs("account",
+            FormatterAttrs("name", s->user.display_name.c_str(), NULL));
 
     sent_data = true;
   }
diff --git a/src/rgw/rgw_rest_user.cc b/src/rgw/rgw_rest_user.cc
index 8d8485f..fc46ff6 100644
--- a/src/rgw/rgw_rest_user.cc
+++ b/src/rgw/rgw_rest_user.cc
@@ -693,6 +693,7 @@ void RGWOp_Quota_Info::execute()
   if (http_ret < 0)
     return;
 
+  flusher.start(0);
   if (show_all) {
     UserQuotas quotas(info);
     encode_json("quota", quotas, s->formatter);
diff --git a/src/rgw/rgw_swift.cc b/src/rgw/rgw_swift.cc
index 586821e..09fb9b7 100644
--- a/src/rgw/rgw_swift.cc
+++ b/src/rgw/rgw_swift.cc
@@ -269,6 +269,7 @@ int	RGWSwift::get_keystone_admin_token(std::string& token)
     std::stringstream ss;
     jf.flush(ss);
     token_req.set_post_data(ss.str());
+    token_req.set_send_length(ss.str().length());
     int ret = token_req.process("POST", token_url.c_str());
     if (ret < 0)
       return ret;
@@ -296,6 +297,7 @@ int RGWSwift::check_revoked()
     return -EINVAL;
   url.append("v2.0/tokens/revoked");
   req.append_header("X-Auth-Token", token);
+  req.set_send_length(0);
   int ret = req.process(url.c_str());
   if (ret < 0)
     return ret;
@@ -523,6 +525,11 @@ int RGWSwift::validate_keystone_token(RGWRados *store, const string& token, stru
   if (ret < 0)
     return ret;
 
+  if (t.expired()) {
+    ldout(cct, 0) << "got expired token: " << t.token.tenant.name << ":" << t.user.name << " expired: " << t.token.expires << dendl;
+    return -EPERM;
+  }
+
   keystone_token_cache->add(token_id, t);
 
   ret = update_user_info(store, info, rgw_user);
diff --git a/src/test/Makefile-client.am b/src/test/Makefile-client.am
index e83a131..bc4a86a 100644
--- a/src/test/Makefile-client.am
+++ b/src/test/Makefile-client.am
@@ -300,15 +300,17 @@ check_PROGRAMS += unittest_rbd_replay
 
 librbd_test_la_SOURCES = \
 	test/librbd/test_fixture.cc \
+	test/librbd/test_support.cc \
 	test/librbd/test_librbd.cc \
 	test/librbd/test_ImageWatcher.cc \
 	test/librbd/test_internal.cc \
-	test/librbd/test_main.cc
+	test/librbd/test_ObjectMap.cc
 librbd_test_la_CXXFLAGS = $(UNITTEST_CXXFLAGS)
 noinst_LTLIBRARIES += librbd_test.la
 
-unittest_librbd_SOURCES =
-nodist_EXTRA_unittest_librbd_SOURCES = dummy.cc
+unittest_librbd_SOURCES = \
+        test/librbd/test_main.cc
+unittest_librbd_CXXFLAGS = $(UNITTEST_CXXFLAGS) -DTEST_LIBRBD_INTERNALS
 unittest_librbd_LDADD = \
 	librbd_test.la librbd_api.la librbd_internal.la $(LIBRBD_TYPES) \
 	libcls_rbd_client.la libcls_lock_client.la \
@@ -317,28 +319,38 @@ unittest_librbd_LDADD = \
 	$(CEPH_GLOBAL) $(RADOS_TEST_LDADD)
 check_PROGRAMS += unittest_librbd
 
-ceph_test_librbd_SOURCES =
-nodist_EXTRA_ceph_test_librbd_SOURCES = dummy.cc
+ceph_test_librbd_SOURCES = \
+        test/librbd/test_main.cc
+ceph_test_librbd_CXXFLAGS = $(UNITTEST_CXXFLAGS) -DTEST_LIBRBD_INTERNALS
 ceph_test_librbd_LDADD = \
 	librbd_test.la librbd_api.la librbd_internal.la $(LIBRBD_TYPES) \
 	libcls_rbd_client.la libcls_lock_client.la \
 	librados_api.la $(LIBRADOS_DEPS) $(UNITTEST_LDADD) \
 	$(CEPH_GLOBAL) $(RADOS_TEST_LDADD)
-ceph_test_librbd_CXXFLAGS = $(UNITTEST_CXXFLAGS)
 bin_DEBUGPROGRAMS += ceph_test_librbd
 
+ceph_test_librbd_api_SOURCES = \
+	test/librbd/test_support.cc \
+	test/librbd/test_librbd.cc \
+	test/librbd/test_main.cc
+ceph_test_librbd_api_CXXFLAGS = $(UNITTEST_CXXFLAGS)
+ceph_test_librbd_api_LDADD = \
+	$(LIBRBD) $(LIBRADOS) $(UNITTEST_LDADD) \
+	$(CEPH_GLOBAL) $(RADOS_TEST_LDADD)
+bin_DEBUGPROGRAMS += ceph_test_librbd_api
+
 if WITH_LTTNG
 unittest_librbd_LDADD += $(LIBRBD_TP)
 ceph_test_librbd_LDADD += $(LIBRBD_TP)
+ceph_test_librbd_api_LDADD += $(LIBRBD_TP)
 endif
 
 if LINUX
-# Force use of C++ linker with dummy.cc - LIBKRBD is a C++ library
-ceph_test_librbd_fsx_SOURCES = test/librbd/fsx.c common/dummy.cc
+ceph_test_librbd_fsx_SOURCES = test/librbd/fsx.cc
 ceph_test_librbd_fsx_LDADD = \
 	$(LIBKRBD) $(LIBRBD) $(LIBRADOS) \
 	$(CRYPTO_LIBS) $(PTHREAD_LIBS) -luuid
-ceph_test_librbd_fsx_CFLAGS = ${AM_CFLAGS}
+ceph_test_librbd_fsx_CXXFLAGS = $(UNITTEST_CXXFLAGS)
 bin_DEBUGPROGRAMS += ceph_test_librbd_fsx
 endif
 endif # WITH_RBD
diff --git a/src/test/Makefile.am b/src/test/Makefile.am
index 15f051d..ab77ba7 100644
--- a/src/test/Makefile.am
+++ b/src/test/Makefile.am
@@ -425,6 +425,7 @@ noinst_HEADERS += \
 	test/librados/TestCase.h \
 	test/libradosstriper/TestCase.h \
 	test/librbd/test_fixture.h \
+	test/librbd/test_support.h \
 	test/ObjectMap/KeyValueDBMemory.h \
 	test/omap_bench.h \
 	test/osdc/FakeWriteback.h \
diff --git a/src/test/centos-6/ceph.spec.in b/src/test/centos-6/ceph.spec.in
index f3cfaf0..b36a0b9 100644
--- a/src/test/centos-6/ceph.spec.in
+++ b/src/test/centos-6/ceph.spec.in
@@ -39,7 +39,9 @@ Requires:	cryptsetup
 Requires(post):	binutils
 BuildRequires:	gcc-c++
 BuildRequires:	boost-devel
+%if ! 0%{defined suse_version}
 BuildRequires:  bzip2-devel
+%endif
 BuildRequires:	cryptsetup
 BuildRequires:	gdbm
 BuildRequires:	hdparm
@@ -66,9 +68,12 @@ BuildRequires:	xfsprogs
 BuildRequires:	xfsprogs-devel
 BuildRequires:	xmlstarlet
 BuildRequires:	yasm
-%if 0%{?rhel} || 0%{?centos} || 0%{?fedora}
+%if 0%{?rhel} || 0%{?centos} || 0%{?fedora} || 0%{?suse_version}
 BuildRequires:	snappy-devel
 %endif
+%if 0%{?suse_version}
+BuildRequires:	net-tools
+%endif
 
 #################################################################################
 # specific
@@ -121,7 +126,12 @@ Requires:	python-rados = %{epoch}:%{version}-%{release}
 Requires:	python-rbd = %{epoch}:%{version}-%{release}
 Requires:	python-cephfs = %{epoch}:%{version}-%{release}
 Requires:	python-requests
-Requires:	redhat-lsb-core
+%if 0%{defined suse_version}
+Requires:  python-argparse
+%endif
+%if 0%{?rhel} || 0%{?fedora}
+Requires:  redhat-lsb-core
+%endif
 %description -n ceph-common
 Common utilities to mount and interact with a ceph storage cluster.
 
@@ -480,6 +490,12 @@ install -m 0644 -D src/rgw/logrotate.conf $RPM_BUILD_ROOT%{_sysconfdir}/logrotat
 chmod 0644 $RPM_BUILD_ROOT%{_docdir}/ceph/sample.ceph.conf
 chmod 0644 $RPM_BUILD_ROOT%{_docdir}/ceph/sample.fetch_config
 
+# firewall templates
+%if 0%{?suse_version}
+install -m 0644 -D etc/sysconfig/SuSEfirewall2.d/services/ceph-mon %{buildroot}%{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/ceph-mon
+install -m 0644 -D etc/sysconfig/SuSEfirewall2.d/services/ceph-osd-mds %{buildroot}%{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/ceph-osd-mds
+%endif
+
 # udev rules
 %if 0%{?rhel} >= 7 || 0%{?fedora}
 install -m 0644 -D udev/50-rbd.rules $RPM_BUILD_ROOT/usr/lib/udev/rules.d/50-rbd.rules
@@ -495,7 +511,7 @@ install -m 0644 -D udev/95-ceph-osd-alt.rules $RPM_BUILD_ROOT/lib/udev/rules.d/9
 install -m 0644 -D udev/95-ceph-osd.rules $RPM_BUILD_ROOT/lib/udev/rules.d/95-ceph-osd.rules
 %endif
 
-%if 0%{?rhel} >= 7 || 0%{?fedora}
+%if 0%{?rhel} >= 7 || 0%{?fedora} || 0%{?suse_version}
 mv $RPM_BUILD_ROOT/lib/udev/rules.d/95-ceph-osd.rules $RPM_BUILD_ROOT/usr/lib/udev/rules.d/95-ceph-osd.rules
 mv $RPM_BUILD_ROOT/sbin/mount.ceph $RPM_BUILD_ROOT/usr/sbin/mount.ceph
 mv $RPM_BUILD_ROOT/sbin/mount.fuse.ceph $RPM_BUILD_ROOT/usr/sbin/mount.fuse.ceph
@@ -577,7 +593,7 @@ fi
 %{_sbindir}/ceph-disk-udev
 %{_sbindir}/ceph-create-keys
 %{_sbindir}/rcceph
-%if 0%{?rhel} >= 7 || 0%{?fedora}
+%if 0%{?rhel} >= 7 || 0%{?fedora} || 0%{?suse_version}
 %{_sbindir}/mount.ceph
 %else
 /sbin/mount.ceph
@@ -608,8 +624,13 @@ fi
 %endif
 %config %{_sysconfdir}/bash_completion.d/ceph
 %config(noreplace) %{_sysconfdir}/logrotate.d/ceph
+%if 0%{?suse_version}
+%config %{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/ceph-mon
+%config %{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/ceph-osd-mds
+%endif
 %{_mandir}/man8/ceph-deploy.8*
 %{_mandir}/man8/ceph-disk.8*
+%{_mandir}/man8/ceph-create-keys.8*
 %{_mandir}/man8/ceph-mon.8*
 %{_mandir}/man8/ceph-mds.8*
 %{_mandir}/man8/ceph-osd.8*
@@ -684,7 +705,7 @@ fi
 %defattr(-,root,root,-)
 %{_bindir}/ceph-fuse
 %{_mandir}/man8/ceph-fuse.8*
-%if 0%{?rhel} >= 7 || 0%{?fedora}
+%if 0%{?rhel} >= 7 || 0%{?fedora} || 0%{?suse_version}
 %{_sbindir}/mount.fuse.ceph
 %else
 /sbin/mount.fuse.ceph
diff --git a/src/test/centos-7/ceph.spec.in b/src/test/centos-7/ceph.spec.in
index f3cfaf0..b36a0b9 100644
--- a/src/test/centos-7/ceph.spec.in
+++ b/src/test/centos-7/ceph.spec.in
@@ -39,7 +39,9 @@ Requires:	cryptsetup
 Requires(post):	binutils
 BuildRequires:	gcc-c++
 BuildRequires:	boost-devel
+%if ! 0%{defined suse_version}
 BuildRequires:  bzip2-devel
+%endif
 BuildRequires:	cryptsetup
 BuildRequires:	gdbm
 BuildRequires:	hdparm
@@ -66,9 +68,12 @@ BuildRequires:	xfsprogs
 BuildRequires:	xfsprogs-devel
 BuildRequires:	xmlstarlet
 BuildRequires:	yasm
-%if 0%{?rhel} || 0%{?centos} || 0%{?fedora}
+%if 0%{?rhel} || 0%{?centos} || 0%{?fedora} || 0%{?suse_version}
 BuildRequires:	snappy-devel
 %endif
+%if 0%{?suse_version}
+BuildRequires:	net-tools
+%endif
 
 #################################################################################
 # specific
@@ -121,7 +126,12 @@ Requires:	python-rados = %{epoch}:%{version}-%{release}
 Requires:	python-rbd = %{epoch}:%{version}-%{release}
 Requires:	python-cephfs = %{epoch}:%{version}-%{release}
 Requires:	python-requests
-Requires:	redhat-lsb-core
+%if 0%{defined suse_version}
+Requires:  python-argparse
+%endif
+%if 0%{?rhel} || 0%{?fedora}
+Requires:  redhat-lsb-core
+%endif
 %description -n ceph-common
 Common utilities to mount and interact with a ceph storage cluster.
 
@@ -480,6 +490,12 @@ install -m 0644 -D src/rgw/logrotate.conf $RPM_BUILD_ROOT%{_sysconfdir}/logrotat
 chmod 0644 $RPM_BUILD_ROOT%{_docdir}/ceph/sample.ceph.conf
 chmod 0644 $RPM_BUILD_ROOT%{_docdir}/ceph/sample.fetch_config
 
+# firewall templates
+%if 0%{?suse_version}
+install -m 0644 -D etc/sysconfig/SuSEfirewall2.d/services/ceph-mon %{buildroot}%{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/ceph-mon
+install -m 0644 -D etc/sysconfig/SuSEfirewall2.d/services/ceph-osd-mds %{buildroot}%{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/ceph-osd-mds
+%endif
+
 # udev rules
 %if 0%{?rhel} >= 7 || 0%{?fedora}
 install -m 0644 -D udev/50-rbd.rules $RPM_BUILD_ROOT/usr/lib/udev/rules.d/50-rbd.rules
@@ -495,7 +511,7 @@ install -m 0644 -D udev/95-ceph-osd-alt.rules $RPM_BUILD_ROOT/lib/udev/rules.d/9
 install -m 0644 -D udev/95-ceph-osd.rules $RPM_BUILD_ROOT/lib/udev/rules.d/95-ceph-osd.rules
 %endif
 
-%if 0%{?rhel} >= 7 || 0%{?fedora}
+%if 0%{?rhel} >= 7 || 0%{?fedora} || 0%{?suse_version}
 mv $RPM_BUILD_ROOT/lib/udev/rules.d/95-ceph-osd.rules $RPM_BUILD_ROOT/usr/lib/udev/rules.d/95-ceph-osd.rules
 mv $RPM_BUILD_ROOT/sbin/mount.ceph $RPM_BUILD_ROOT/usr/sbin/mount.ceph
 mv $RPM_BUILD_ROOT/sbin/mount.fuse.ceph $RPM_BUILD_ROOT/usr/sbin/mount.fuse.ceph
@@ -577,7 +593,7 @@ fi
 %{_sbindir}/ceph-disk-udev
 %{_sbindir}/ceph-create-keys
 %{_sbindir}/rcceph
-%if 0%{?rhel} >= 7 || 0%{?fedora}
+%if 0%{?rhel} >= 7 || 0%{?fedora} || 0%{?suse_version}
 %{_sbindir}/mount.ceph
 %else
 /sbin/mount.ceph
@@ -608,8 +624,13 @@ fi
 %endif
 %config %{_sysconfdir}/bash_completion.d/ceph
 %config(noreplace) %{_sysconfdir}/logrotate.d/ceph
+%if 0%{?suse_version}
+%config %{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/ceph-mon
+%config %{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/ceph-osd-mds
+%endif
 %{_mandir}/man8/ceph-deploy.8*
 %{_mandir}/man8/ceph-disk.8*
+%{_mandir}/man8/ceph-create-keys.8*
 %{_mandir}/man8/ceph-mon.8*
 %{_mandir}/man8/ceph-mds.8*
 %{_mandir}/man8/ceph-osd.8*
@@ -684,7 +705,7 @@ fi
 %defattr(-,root,root,-)
 %{_bindir}/ceph-fuse
 %{_mandir}/man8/ceph-fuse.8*
-%if 0%{?rhel} >= 7 || 0%{?fedora}
+%if 0%{?rhel} >= 7 || 0%{?fedora} || 0%{?suse_version}
 %{_sbindir}/mount.fuse.ceph
 %else
 /sbin/mount.fuse.ceph
diff --git a/src/test/cli/crushtool/check-names.empty.crushmap.txt b/src/test/cli/crushtool/check-names.empty.crushmap.txt
new file mode 100644
index 0000000..6ba00cd
--- /dev/null
+++ b/src/test/cli/crushtool/check-names.empty.crushmap.txt
@@ -0,0 +1,11 @@
+# begin crush map
+
+# devices
+
+# types
+
+# buckets
+
+# rules
+
+# end crush map
diff --git a/src/test/cli/crushtool/check-names.empty.t b/src/test/cli/crushtool/check-names.empty.t
new file mode 100644
index 0000000..755e931
--- /dev/null
+++ b/src/test/cli/crushtool/check-names.empty.t
@@ -0,0 +1,5 @@
+  $ crushtool -c "$TESTDIR/check-names.empty.crushmap.txt" -o "$TESTDIR/check-names.empty.crushmap"
+  $ crushtool -i "$TESTDIR/check-names.empty.crushmap" --check 0
+  unknown type name: item#0
+  [1]
+  $ rm -f "$TESTDIR/check-names.empty.crushmap"
diff --git a/src/test/cli/crushtool/check-names.max-id.t b/src/test/cli/crushtool/check-names.max-id.t
new file mode 100644
index 0000000..dab2d31
--- /dev/null
+++ b/src/test/cli/crushtool/check-names.max-id.t
@@ -0,0 +1,7 @@
+  $ crushtool -i "$TESTDIR/simple.template" --add-item 0 1.0 device0 --loc host host0 --loc cluster cluster0 -o check-names.crushmap > /dev/null
+  $ crushtool -i check-names.crushmap       --add-item 1 1.0 device1 --loc host host0 --loc cluster cluster0 -o check-names.crushmap > /dev/null
+  $ crushtool -i check-names.crushmap --check 2
+  $ crushtool -i check-names.crushmap       --add-item 2 1.0 device2 --loc host host0 --loc cluster cluster0 -o check-names.crushmap > /dev/null
+  $ crushtool -i check-names.crushmap --check 2
+  item id too large: item#2
+  [1]
diff --git a/src/test/cli/crushtool/help.t b/src/test/cli/crushtool/help.t
index 7d54919..9c81b7c 100644
--- a/src/test/cli/crushtool/help.t
+++ b/src/test/cli/crushtool/help.t
@@ -30,6 +30,10 @@
                            reweight a given item (and adjust ancestor
                            weights as needed)
      -i mapfn --reweight   recalculate all bucket weights
+  
+  Options for the display/test stage
+  
+     --check max_id        check if any item is referencing an unknown name/type
      -i mapfn --show-location id
                            show location for given device id
      --show-utilization    show OSD usage
diff --git a/src/test/daemon_config.cc b/src/test/daemon_config.cc
index 1361ddc..6d32e15 100644
--- a/src/test/daemon_config.cc
+++ b/src/test/daemon_config.cc
@@ -23,6 +23,9 @@
 #include <string>
 #include <string.h>
 
+#include <boost/lexical_cast.hpp>
+
+
 using std::string;
 
 TEST(DaemonConfig, SimpleSet) {
@@ -333,6 +336,49 @@ TEST(DaemonConfig, ThreadSafety1) {
 				       "false"));
   ASSERT_EQ(ret, 0);
 }
+
+TEST(DaemonConfig, InvalidIntegers) {
+  {
+    int ret = g_ceph_context->_conf->set_val("num_client", "-1");
+    ASSERT_EQ(ret, -EINVAL);
+  }
+  {
+    int ret = g_ceph_context->_conf->set_val("num_client", "-1K");
+    ASSERT_EQ(ret, -EINVAL);
+  }
+  {
+    long long bad_value = (long long)std::numeric_limits<int>::max() + 1;
+    string str = boost::lexical_cast<string>(bad_value);
+    int ret = g_ceph_context->_conf->set_val("num_client", str);
+    ASSERT_EQ(ret, -EINVAL);
+  }
+  {
+    // 4G must be greater than INT_MAX
+    ASSERT_GT(4LL * 1024 * 1024 * 1024, (long long)std::numeric_limits<int>::max());
+    int ret = g_ceph_context->_conf->set_val("num_client", "4G");
+    ASSERT_EQ(ret, -EINVAL);
+  }
+}
+
+TEST(DaemonConfig, InvalidFloats) {
+  {
+    double bad_value = 2 * (double)std::numeric_limits<float>::max();
+    string str = boost::lexical_cast<string>(-bad_value);
+    int ret = g_ceph_context->_conf->set_val("log_stop_at_utilization", str);
+    ASSERT_EQ(ret, -EINVAL);
+  }
+  {
+    double bad_value = 2 * (double)std::numeric_limits<float>::max();
+    string str = boost::lexical_cast<string>(bad_value);
+    int ret = g_ceph_context->_conf->set_val("log_stop_at_utilization", str);
+    ASSERT_EQ(ret, -EINVAL);
+  }
+  {
+    int ret = g_ceph_context->_conf->set_val("log_stop_at_utilization", "not a float");
+    ASSERT_EQ(ret, -EINVAL);
+  }
+}
+
 /*
  * Local Variables:
  * compile-command: "cd .. ; make unittest_daemon_config && ./unittest_daemon_config"
diff --git a/src/test/librados/snapshots.cc b/src/test/librados/snapshots.cc
index 880b84d..3eb4e72 100644
--- a/src/test/librados/snapshots.cc
+++ b/src/test/librados/snapshots.cc
@@ -485,6 +485,40 @@ TEST_F(LibRadosSnapshotsSelfManagedPP, SnapOverlapPP) {
   readioctx.close();
 }
 
+TEST_F(LibRadosSnapshotsSelfManagedPP, Bug11677) {
+  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 = 1<<20;
+  char *buf = (char *)new char[bsize];
+  memset(buf, 0xcc, bsize);
+  bufferlist bl1;
+  bl1.append(buf, bsize);
+  ASSERT_EQ(0, 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());
+
+  librados::ObjectWriteOperation *op = new librados::ObjectWriteOperation();
+  op->assert_exists();
+  op->remove();
+  ASSERT_EQ(0, ioctx.operate("foo", op));
+
+  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);
+  delete[] buf;
+}
+
 // EC testing
 TEST_F(LibRadosSnapshotsEC, SnapList) {
   char buf[bufsize];
@@ -816,3 +850,37 @@ TEST_F(LibRadosSnapshotsSelfManagedECPP, RollbackPP) {
   delete[] buf2;
 }
 
+TEST_F(LibRadosSnapshotsSelfManagedECPP, Bug11677) {
+  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, bsize);
+  bufferlist bl1;
+  bl1.append(buf, bsize);
+  ASSERT_EQ(0, 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());
+
+  librados::ObjectWriteOperation *op = new librados::ObjectWriteOperation();
+  op->assert_exists();
+  op->remove();
+  ASSERT_EQ(0, ioctx.operate("foo", op));
+
+  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);
+  delete[] buf;
+}
+
diff --git a/src/test/librados/tier.cc b/src/test/librados/tier.cc
index 208380b..1e94bdd 100644
--- a/src/test/librados/tier.cc
+++ b/src/test/librados/tier.cc
@@ -76,16 +76,15 @@ protected:
   static void SetUpTestCase() {
     pool_name = get_temp_pool_name();
     ASSERT_EQ("", create_one_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_pool_pp(pool_name, s_cluster));
   }
   static std::string cache_pool_name;
 
   virtual void SetUp() {
+    cache_pool_name = get_temp_pool_name();
+    ASSERT_EQ(0, s_cluster.pool_create(cache_pool_name.c_str()));
     RadosTestPP::SetUp();
     ASSERT_EQ(0, cluster.ioctx_create(cache_pool_name.c_str(), cache_ioctx));
     cache_ioctx.set_namespace(nspace);
@@ -114,6 +113,7 @@ protected:
     cleanup_namespace(cache_ioctx, nspace);
 
     cache_ioctx.close();
+    ASSERT_EQ(0, s_cluster.pool_delete(cache_pool_name.c_str()));
   }
   librados::IoCtx cache_ioctx;
 };
@@ -2399,16 +2399,15 @@ 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() {
+    cache_pool_name = get_temp_pool_name();
+    ASSERT_EQ(0, s_cluster.pool_create(cache_pool_name.c_str()));
     RadosTestECPP::SetUp();
     ASSERT_EQ(0, cluster.ioctx_create(cache_pool_name.c_str(), cache_ioctx));
     cache_ioctx.set_namespace(nspace);
@@ -2437,6 +2436,7 @@ protected:
     cleanup_namespace(cache_ioctx, nspace);
 
     cache_ioctx.close();
+    ASSERT_EQ(0, s_cluster.pool_delete(cache_pool_name.c_str()));
   }
 
   librados::IoCtx cache_ioctx;
diff --git a/src/test/librados_test_stub/LibradosTestStub.cc b/src/test/librados_test_stub/LibradosTestStub.cc
index f9cf32b..f7f597c 100644
--- a/src/test/librados_test_stub/LibradosTestStub.cc
+++ b/src/test/librados_test_stub/LibradosTestStub.cc
@@ -15,6 +15,7 @@
 #include "test/librados_test_stub/TestMemRadosClient.h"
 #include "objclass/objclass.h"
 #include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
 #include <deque>
 #include <list>
 #include <vector>
@@ -22,29 +23,39 @@
 
 #define dout_subsys ceph_subsys_rados
 
+namespace {
+
+static void DeallocateRadosClient(librados::TestRadosClient* client)
+{
+  client->put();
+}
+
+} // anonymous namespace
+
+
 static librados::TestClassHandler *get_class_handler() {
-  static librados::TestClassHandler *s_class_handler = NULL;
-  if (s_class_handler == NULL) {
-    s_class_handler = new librados::TestClassHandler();
+  static boost::shared_ptr<librados::TestClassHandler> s_class_handler;
+  if (!s_class_handler) {
+    s_class_handler.reset(new librados::TestClassHandler());
     s_class_handler->open_all_classes();
   }
-  return s_class_handler;
+  return s_class_handler.get();
 }
 
 static librados::TestRadosClient *get_rados_client() {
   // TODO: use factory to allow tests to swap out impl
-  static librados::TestRadosClient *s_rados_client = NULL;
-  if (s_rados_client == NULL) {
+  static boost::shared_ptr<librados::TestRadosClient> s_rados_client;
+  if (!s_rados_client) {
     CephInitParameters iparams(CEPH_ENTITY_TYPE_CLIENT);
     CephContext *cct = common_preinit(iparams, CODE_ENVIRONMENT_LIBRARY, 0);
     cct->_conf->parse_env();
     cct->_conf->apply_changes(NULL);
-    g_ceph_context = cct;
-    s_rados_client = new librados::TestMemRadosClient(cct);
+    s_rados_client.reset(new librados::TestMemRadosClient(cct),
+                         &DeallocateRadosClient);
     cct->put();
   }
   s_rados_client->get();
-  return s_rados_client;
+  return s_rados_client.get();
 }
 
 static void do_out_buffer(bufferlist& outbl, char **outbuf, size_t *outbuflen) {
diff --git a/src/test/librados_test_stub/TestMemIoCtxImpl.cc b/src/test/librados_test_stub/TestMemIoCtxImpl.cc
index 2e6518a..7116c46 100644
--- a/src/test/librados_test_stub/TestMemIoCtxImpl.cc
+++ b/src/test/librados_test_stub/TestMemIoCtxImpl.cc
@@ -241,7 +241,7 @@ int TestMemIoCtxImpl::read(const std::string& oid, size_t len, uint64_t off,
     bit.substr_of(file->data, off, len);
     append_clone(bit, bl);
   }
-  return 0;
+  return len;
 }
 
 int TestMemIoCtxImpl::remove(const std::string& oid) {
diff --git a/src/test/librados_test_stub/TestWatchNotify.cc b/src/test/librados_test_stub/TestWatchNotify.cc
index 0a68c3c..6fd7748 100644
--- a/src/test/librados_test_stub/TestWatchNotify.cc
+++ b/src/test/librados_test_stub/TestWatchNotify.cc
@@ -12,12 +12,14 @@ namespace librados {
 TestWatchNotify::TestWatchNotify(CephContext *cct)
   : m_cct(cct), m_finisher(new Finisher(cct)), m_handle(), m_notify_id(),
     m_file_watcher_lock("librados::TestWatchNotify::m_file_watcher_lock") {
+  m_cct->get();
   m_finisher->start();
 }
 
 TestWatchNotify::~TestWatchNotify() {
   m_finisher->stop();
   delete m_finisher;
+  m_cct->put();
 }
 
 TestWatchNotify::NotifyHandle::NotifyHandle()
diff --git a/src/test/librbd/fsx.c b/src/test/librbd/fsx.cc
similarity index 98%
rename from src/test/librbd/fsx.c
rename to src/test/librbd/fsx.cc
index e2ad45c..c5ed1e6 100644
--- a/src/test/librbd/fsx.c
+++ b/src/test/librbd/fsx.cc
@@ -42,6 +42,7 @@
 #include "include/krbd.h"
 #include "include/rados/librados.h"
 #include "include/rbd/librbd.h"
+#include "common/ceph_crypto.h"
 
 #define NUMPRINTCOLUMNS 32	/* # columns of data to print on each line */
 
@@ -196,7 +197,7 @@ warn(const char * fmt, ...)  {
 #define BUF_SIZE 1024
 
 void
-prt(char *fmt, ...)
+prt(const char *fmt, ...)
 {
 	va_list args;
 	char buffer[BUF_SIZE];
@@ -210,13 +211,13 @@ prt(char *fmt, ...)
 }
 
 void
-prterr(char *prefix)
+prterr(const char *prefix)
 {
 	prt("%s%s%s\n", prefix, prefix ? ": " : "", strerror(errno));
 }
 
 void
-prterrcode(char *prefix, int code)
+prterrcode(const char *prefix, int code)
 {
 	prt("%s%s%s\n", prefix, prefix ? ": " : "", strerror(-code));
 }
@@ -264,8 +265,8 @@ struct rbd_ctx {
 struct rbd_operations {
 	int (*open)(const char *name, struct rbd_ctx *ctx);
 	int (*close)(struct rbd_ctx *ctx);
-	ssize_t (*read)(struct rbd_ctx *ctx, uint64_t off, size_t len, void *buf);
-	ssize_t (*write)(struct rbd_ctx *ctx, uint64_t off, size_t len, void *buf);
+	ssize_t (*read)(struct rbd_ctx *ctx, uint64_t off, size_t len, char *buf);
+	ssize_t (*write)(struct rbd_ctx *ctx, uint64_t off, size_t len, const char *buf);
 	int (*flush)(struct rbd_ctx *ctx);
 	int (*discard)(struct rbd_ctx *ctx, uint64_t off, uint64_t len);
 	int (*get_size)(struct rbd_ctx *ctx, uint64_t *size);
@@ -362,7 +363,7 @@ librbd_verify_object_map(struct rbd_ctx *ctx)
 }
 
 ssize_t
-librbd_read(struct rbd_ctx *ctx, uint64_t off, size_t len, void *buf)
+librbd_read(struct rbd_ctx *ctx, uint64_t off, size_t len, char *buf)
 {
 	ssize_t n;
 
@@ -374,7 +375,7 @@ librbd_read(struct rbd_ctx *ctx, uint64_t off, size_t len, void *buf)
 }
 
 ssize_t
-librbd_write(struct rbd_ctx *ctx, uint64_t off, size_t len, void *buf)
+librbd_write(struct rbd_ctx *ctx, uint64_t off, size_t len, const char *buf)
 {
 	ssize_t n;
 	int ret;
@@ -525,16 +526,16 @@ librbd_flatten(struct rbd_ctx *ctx)
 }
 
 const struct rbd_operations librbd_operations = {
-	.open	= librbd_open,
-	.close	= librbd_close,
-	.read	= librbd_read,
-	.write	= librbd_write,
-	.flush	= librbd_flush,
-	.discard = librbd_discard,
-	.get_size = librbd_get_size,
-	.resize	= librbd_resize,
-	.clone	= librbd_clone,
-	.flatten = librbd_flatten,
+	librbd_open,
+	librbd_close,
+	librbd_read,
+	librbd_write,
+	librbd_flush,
+	librbd_discard,
+	librbd_get_size,
+	librbd_resize,
+	librbd_clone,
+	librbd_flatten
 };
 
 int
@@ -595,7 +596,7 @@ krbd_close(struct rbd_ctx *ctx)
 }
 
 ssize_t
-krbd_read(struct rbd_ctx *ctx, uint64_t off, size_t len, void *buf)
+krbd_read(struct rbd_ctx *ctx, uint64_t off, size_t len, char *buf)
 {
 	ssize_t n;
 
@@ -610,7 +611,7 @@ krbd_read(struct rbd_ctx *ctx, uint64_t off, size_t len, void *buf)
 }
 
 ssize_t
-krbd_write(struct rbd_ctx *ctx, uint64_t off, size_t len, void *buf)
+krbd_write(struct rbd_ctx *ctx, uint64_t off, size_t len, const char *buf)
 {
 	ssize_t n;
 
@@ -738,16 +739,16 @@ krbd_flatten(struct rbd_ctx *ctx)
 }
 
 const struct rbd_operations krbd_operations = {
-	.open	= krbd_open,
-	.close	= krbd_close,
-	.read	= krbd_read,
-	.write	= krbd_write,
-	.flush	= krbd_flush,
-	.discard = krbd_discard,
-	.get_size = krbd_get_size,
-	.resize	= krbd_resize,
-	.clone	= krbd_clone,
-	.flatten = krbd_flatten,
+	krbd_open,
+	krbd_close,
+	krbd_read,
+	krbd_write,
+	krbd_flush,
+	krbd_discard,
+	krbd_get_size,
+	krbd_resize,
+	krbd_clone,
+	krbd_flatten,
 };
 
 struct rbd_ctx ctx = RBD_CTX_INIT;
@@ -793,7 +794,7 @@ logdump(void)
 {
 	int	i, count, down;
 	struct log_entry	*lp;
-	char *falloc_type[3] = {"PAST_EOF", "EXTENDING", "INTERIOR"};
+	const char *falloc_type[3] = {"PAST_EOF", "EXTENDING", "INTERIOR"};
 
 	prt("LOG DUMP (%d total operations):\n", logcount);
 	if (logcount < LOGSIZE) {
@@ -1744,8 +1745,7 @@ out:
 
 
 void
-cleanup(sig)
-	int	sig;
+cleanup(int sig)
 {
 	if (sig)
 		prt("signal %d\n", sig);
@@ -2312,6 +2312,7 @@ main(int argc, char **argv)
 	krbd_destroy(krbd);
 	rados_shutdown(cluster);
 
+        ceph::crypto::shutdown();
 	free(original_buf);
 	free(good_buf);
 	free(temp_buf);
diff --git a/src/test/librbd/test_ImageWatcher.cc b/src/test/librbd/test_ImageWatcher.cc
index b73bc7b..99a1002 100644
--- a/src/test/librbd/test_ImageWatcher.cc
+++ b/src/test/librbd/test_ImageWatcher.cc
@@ -1,6 +1,7 @@
 // -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
 // vim: ts=8 sw=2 smarttab
 #include "test/librbd/test_fixture.h"
+#include "test/librbd/test_support.h"
 #include "include/int_types.h"
 #include "include/stringify.h"
 #include "include/rados/librados.h"
@@ -170,13 +171,13 @@ public:
     if (!ictx->image_watcher->is_lock_owner() &&
         (m_expected_aio_restarts == 0 ||
 	 m_aio_completion_restarts < m_expected_aio_restarts)) {
-      EXPECT_EQ(0, ictx->image_watcher->request_lock(
+      ictx->image_watcher->request_lock(
         boost::bind(&TestImageWatcher::handle_restart_aio, this, ictx, _1),
-	aio_completion));
+	aio_completion);
     } else {
       {
 	Mutex::Locker l2(aio_completion->lock);
-	aio_completion->complete();
+	aio_completion->complete(ictx->cct);
       }
 
       m_aio_completions.erase(aio_completion);
@@ -531,12 +532,12 @@ TEST_F(TestImageWatcher, RequestLock) {
 
   {
     RWLock::WLocker l(ictx->owner_lock);
-    ASSERT_EQ(0, ictx->image_watcher->request_lock(
+    ictx->image_watcher->request_lock(
       boost::bind(&TestImageWatcher::handle_restart_aio, this, ictx, _1),
-      create_aio_completion(*ictx)));
-    ASSERT_EQ(0, ictx->image_watcher->request_lock(
+      create_aio_completion(*ictx));
+    ictx->image_watcher->request_lock(
       boost::bind(&TestImageWatcher::handle_restart_aio, this, ictx, _1),
-      create_aio_completion(*ictx)));
+      create_aio_completion(*ictx));
   }
 
   ASSERT_TRUE(wait_for_notifies(*ictx));
@@ -581,9 +582,9 @@ TEST_F(TestImageWatcher, RequestLockTimedOut) {
 
   {
     RWLock::WLocker l(ictx->owner_lock);
-    ASSERT_EQ(0, ictx->image_watcher->request_lock(
+    ictx->image_watcher->request_lock(
       boost::bind(&TestImageWatcher::handle_restart_aio, this, ictx, _1),
-      create_aio_completion(*ictx)));
+      create_aio_completion(*ictx));
   }
 
   ASSERT_TRUE(wait_for_notifies(*ictx));
@@ -608,9 +609,9 @@ TEST_F(TestImageWatcher, RequestLockTryLockRace) {
 
   {
     RWLock::WLocker l(ictx->owner_lock);
-    ASSERT_EQ(0, ictx->image_watcher->request_lock(
+    ictx->image_watcher->request_lock(
       boost::bind(&TestImageWatcher::handle_restart_aio, this, ictx, _1),
-      create_aio_completion(*ictx)));
+      create_aio_completion(*ictx));
   }
 
   ASSERT_TRUE(wait_for_notifies(*ictx));
@@ -643,9 +644,9 @@ TEST_F(TestImageWatcher, RequestLockPreTryLockFailed) {
 
   {
     RWLock::WLocker l(ictx->owner_lock);
-    ASSERT_EQ(0, ictx->image_watcher->request_lock(
+    ictx->image_watcher->request_lock(
       boost::bind(&TestImageWatcher::handle_restart_aio, this, ictx, _1),
-      create_aio_completion(*ictx)));
+      create_aio_completion(*ictx));
   }
   ASSERT_TRUE(wait_for_aio_completions(*ictx));
 }
@@ -665,9 +666,9 @@ TEST_F(TestImageWatcher, RequestLockPostTryLockFailed) {
   m_expected_aio_restarts = 1;
   {
     RWLock::WLocker l(ictx->owner_lock);
-    ASSERT_EQ(0, ictx->image_watcher->request_lock(
+    ictx->image_watcher->request_lock(
       boost::bind(&TestImageWatcher::handle_restart_aio, this, ictx, _1),
-      create_aio_completion(*ictx)));
+      create_aio_completion(*ictx));
   }
 
   ASSERT_TRUE(wait_for_notifies(*ictx));
diff --git a/src/test/librbd/test_ObjectMap.cc b/src/test/librbd/test_ObjectMap.cc
new file mode 100644
index 0000000..5457b99
--- /dev/null
+++ b/src/test/librbd/test_ObjectMap.cc
@@ -0,0 +1,124 @@
+// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+#include "test/librbd/test_fixture.h"
+#include "test/librbd/test_support.h"
+#include "librbd/ImageCtx.h"
+#include "librbd/ImageWatcher.h"
+#include "librbd/internal.h"
+#include "librbd/ObjectMap.h"
+#include "cls/rbd/cls_rbd_client.h"
+#include <list>
+
+void register_test_object_map() {
+}
+
+class TestObjectMap : public TestFixture {
+public:
+};
+
+TEST_F(TestObjectMap, RefreshInvalidatesWhenCorrupt) {
+  REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
+
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+  ASSERT_FALSE(ictx->test_flags(RBD_FLAG_OBJECT_MAP_INVALID));
+
+  {
+    RWLock::WLocker owner_locker(ictx->owner_lock);
+    ASSERT_EQ(0, ictx->image_watcher->try_lock());
+  }
+
+  std::string oid = librbd::ObjectMap::object_map_name(ictx->id, CEPH_NOSNAP);
+  bufferlist bl;
+  bl.append("corrupt");
+  ASSERT_EQ(0, ictx->data_ctx.write_full(oid, bl));
+
+  {
+    RWLock::RLocker owner_locker(ictx->owner_lock);
+    RWLock::WLocker snap_locker(ictx->snap_lock);
+    ictx->object_map.refresh(CEPH_NOSNAP);
+  }
+  ASSERT_TRUE(ictx->test_flags(RBD_FLAG_OBJECT_MAP_INVALID));
+}
+
+TEST_F(TestObjectMap, RefreshInvalidatesWhenTooSmall) {
+  REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
+
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+  ASSERT_FALSE(ictx->test_flags(RBD_FLAG_OBJECT_MAP_INVALID));
+
+  {
+    RWLock::WLocker owner_locker(ictx->owner_lock);
+    ASSERT_EQ(0, ictx->image_watcher->try_lock());
+  }
+
+  librados::ObjectWriteOperation op;
+  librbd::cls_client::object_map_resize(&op, 0, OBJECT_NONEXISTENT);
+
+  std::string oid = librbd::ObjectMap::object_map_name(ictx->id, CEPH_NOSNAP);
+  ASSERT_EQ(0, ictx->data_ctx.operate(oid, &op));
+
+  {
+    RWLock::RLocker owner_locker(ictx->owner_lock);
+    RWLock::WLocker snap_locker(ictx->snap_lock);
+    ictx->object_map.refresh(CEPH_NOSNAP);
+  }
+  ASSERT_TRUE(ictx->test_flags(RBD_FLAG_OBJECT_MAP_INVALID));
+}
+
+TEST_F(TestObjectMap, InvalidateFlagOnDisk) {
+  REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
+
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+  ASSERT_FALSE(ictx->test_flags(RBD_FLAG_OBJECT_MAP_INVALID));
+
+  {
+    RWLock::WLocker owner_locker(ictx->owner_lock);
+    ASSERT_EQ(0, ictx->image_watcher->try_lock());
+  }
+
+  std::string oid = librbd::ObjectMap::object_map_name(ictx->id, CEPH_NOSNAP);
+  bufferlist bl;
+  bl.append("corrupt");
+  ASSERT_EQ(0, ictx->data_ctx.write_full(oid, bl));
+
+  {
+    RWLock::RLocker owner_locker(ictx->owner_lock);
+    RWLock::WLocker snap_locker(ictx->snap_lock);
+    ictx->object_map.refresh(CEPH_NOSNAP);
+  }
+  ASSERT_TRUE(ictx->test_flags(RBD_FLAG_OBJECT_MAP_INVALID));
+
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+  ASSERT_TRUE(ictx->test_flags(RBD_FLAG_OBJECT_MAP_INVALID));
+}
+
+TEST_F(TestObjectMap, InvalidateFlagInMemoryOnly) {
+  REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
+
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+  ASSERT_FALSE(ictx->test_flags(RBD_FLAG_OBJECT_MAP_INVALID));
+
+  std::string oid = librbd::ObjectMap::object_map_name(ictx->id, CEPH_NOSNAP);
+  bufferlist valid_bl;
+  ASSERT_LT(0, ictx->data_ctx.read(oid, valid_bl, 0, 0));
+
+  bufferlist corrupt_bl;
+  corrupt_bl.append("corrupt");
+  ASSERT_EQ(0, ictx->data_ctx.write_full(oid, corrupt_bl));
+
+  {
+    RWLock::RLocker owner_locker(ictx->owner_lock);
+    RWLock::WLocker snap_locker(ictx->snap_lock);
+    ictx->object_map.refresh(CEPH_NOSNAP);
+  }
+  ASSERT_TRUE(ictx->test_flags(RBD_FLAG_OBJECT_MAP_INVALID));
+
+  ASSERT_EQ(0, ictx->data_ctx.write_full(oid, valid_bl));
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+  ASSERT_FALSE(ictx->test_flags(RBD_FLAG_OBJECT_MAP_INVALID));
+}
+
diff --git a/src/test/librbd/test_fixture.cc b/src/test/librbd/test_fixture.cc
index 9e47125..e3db5c9 100644
--- a/src/test/librbd/test_fixture.cc
+++ b/src/test/librbd/test_fixture.cc
@@ -1,6 +1,7 @@
 // -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
 // vim: ts=8 sw=2 smarttab
 #include "test/librbd/test_fixture.h"
+#include "test/librbd/test_support.h"
 #include "include/stringify.h"
 #include "cls/lock/cls_lock_client.h"
 #include "cls/lock/cls_lock_types.h"
@@ -10,32 +11,6 @@
 #include <sstream>
 #include <stdlib.h>
 
-bool get_features(uint64_t *features) {
-  const char *c = getenv("RBD_FEATURES");
-  if (c == NULL) {
-    return false;
-  }
-
-  std::stringstream ss(c);
-  if (!(ss >> *features)) {
-    return false;
-  }
-  return true;
-}
-
-bool is_feature_enabled(uint64_t feature) {
-  uint64_t features;
-  return (get_features(&features) && (features & feature) == feature);
-}
-
-int create_image_pp(librbd::RBD &rbd, librados::IoCtx &ioctx,
-                    const std::string &name, uint64_t size) {
-  uint64_t features = 0;
-  get_features(&features);
-  int order = 0;
-  return rbd.create2(ioctx, name.c_str(), size, features, &order);
-}
-
 std::string TestFixture::_pool_name;
 librados::Rados TestFixture::_rados;
 uint64_t TestFixture::_image_number = 0;
diff --git a/src/test/librbd/test_fixture.h b/src/test/librbd/test_fixture.h
index d3246a7..7e3fff8 100644
--- a/src/test/librbd/test_fixture.h
+++ b/src/test/librbd/test_fixture.h
@@ -10,18 +10,6 @@
 
 using namespace ceph;
 
-bool get_features(uint64_t *features);
-bool is_feature_enabled(uint64_t feature);
-int create_image_pp(librbd::RBD &rbd, librados::IoCtx &ioctx,
-                    const std::string &name, uint64_t size);
-
-#define REQUIRE_FEATURE(feature) { 	  \
-  if (!is_feature_enabled(feature)) { 	  \
-    std::cout << "SKIPPING" << std::endl; \
-    return SUCCEED(); 			  \
-  } 					  \
-}
-
 class TestFixture : public ::testing::Test {
 public:
 
diff --git a/src/test/librbd/test_internal.cc b/src/test/librbd/test_internal.cc
index aac4d4d..2df917d 100644
--- a/src/test/librbd/test_internal.cc
+++ b/src/test/librbd/test_internal.cc
@@ -1,6 +1,7 @@
 // -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
 // vim: ts=8 sw=2 smarttab
 #include "test/librbd/test_fixture.h"
+#include "test/librbd/test_support.h"
 #include "librbd/AioCompletion.h"
 #include "librbd/ImageWatcher.h"
 #include "librbd/internal.h"
@@ -249,12 +250,17 @@ TEST_F(TestInternal, AioWriteRequestsLock) {
   DummyContext *ctx = new DummyContext();
   librbd::AioCompletion *c =
     librbd::aio_create_completion_internal(ctx, librbd::rbd_ctx_cb);
-  ASSERT_EQ(0, aio_write(ictx, 0, buffer.size(), buffer.c_str(), c, 0));
+  c->get();
+  aio_write(ictx, 0, buffer.size(), buffer.c_str(), c, 0);
 
   bool is_owner;
   ASSERT_EQ(0, librbd::is_exclusive_lock_owner(ictx, &is_owner));
   ASSERT_FALSE(is_owner);
   ASSERT_FALSE(c->is_complete());
+
+  unlock_image();
+  ASSERT_EQ(0, c->wait_for_complete());
+  c->put();
 }
 
 TEST_F(TestInternal, AioDiscardRequestsLock) {
@@ -267,12 +273,17 @@ TEST_F(TestInternal, AioDiscardRequestsLock) {
   DummyContext *ctx = new DummyContext();
   librbd::AioCompletion *c =
     librbd::aio_create_completion_internal(ctx, librbd::rbd_ctx_cb);
-  ASSERT_EQ(0, aio_discard(ictx, 0, 256, c));
+  c->get();
+  aio_discard(ictx, 0, 256, c);
 
   bool is_owner;
   ASSERT_EQ(0, librbd::is_exclusive_lock_owner(ictx, &is_owner));
   ASSERT_FALSE(is_owner);
   ASSERT_FALSE(c->is_complete());
+
+  unlock_image();
+  ASSERT_EQ(0, c->wait_for_complete());
+  c->put();
 }
 
 TEST_F(TestInternal, CancelAsyncResize) {
diff --git a/src/test/librbd/test_librbd.cc b/src/test/librbd/test_librbd.cc
index cf76c67..b3c53c1 100644
--- a/src/test/librbd/test_librbd.cc
+++ b/src/test/librbd/test_librbd.cc
@@ -22,6 +22,7 @@
 #include "global/global_init.h"
 #include "common/ceph_argparse.h"
 #include "common/config.h"
+#include "common/Thread.h"
 
 #include "gtest/gtest.h"
 
@@ -39,7 +40,7 @@
 #include <vector>
 
 #include "test/librados/test.h"
-#include "test/librbd/test_fixture.h"
+#include "test/librbd/test_support.h"
 #include "common/errno.h"
 #include "include/interval_set.h"
 #include "include/stringify.h"
@@ -137,10 +138,12 @@ public:
     _unique_pool_names.clear();
     _image_number = 0;
     ASSERT_EQ("", connect_cluster(&_cluster));
+    ASSERT_EQ("", connect_cluster_pp(_rados));
   }
 
   static void TearDownTestCase() {
     rados_shutdown(_cluster);
+    _rados.wait_for_latest_osdmap();
     _pool_names.insert(_pool_names.end(), _unique_pool_names.begin(),
 		       _unique_pool_names.end());
     for (size_t i = 1; i < _pool_names.size(); ++i) {
@@ -173,16 +176,17 @@ public:
   }
 
   std::string create_pool(bool unique = false) {
+    librados::Rados rados;
     std::string pool_name;
     if (unique) {
       pool_name = get_temp_pool_name();
-      EXPECT_EQ("", create_one_pool_pp(pool_name, _rados));
+      EXPECT_EQ("", create_one_pool_pp(pool_name, rados));
       _unique_pool_names.push_back(pool_name);
     } else if (m_pool_number < _pool_names.size()) {
       pool_name = _pool_names[m_pool_number];
     } else {
       pool_name = get_temp_pool_name();
-      EXPECT_EQ("", create_one_pool_pp(pool_name, _rados));
+      EXPECT_EQ("", create_one_pool_pp(pool_name, rados));
       _pool_names.push_back(pool_name);
     }
     ++m_pool_number;
@@ -827,8 +831,16 @@ TEST_F(TestLibRBD, TestIO)
   ASSERT_EQ(10, rbd_write(image, info.size - 10, 100, test_data));
 
   rbd_aio_create_completion(NULL, (rbd_callback_t) simple_read_cb, &comp);
-  ASSERT_EQ(-EINVAL, rbd_aio_write(image, info.size, 1, test_data, comp));
-  ASSERT_EQ(-EINVAL, rbd_aio_read(image, info.size, 1, test_data, comp));
+  ASSERT_EQ(0, rbd_aio_write(image, info.size, 1, test_data, comp));
+  ASSERT_EQ(0, rbd_aio_wait_for_complete(comp));
+  ASSERT_EQ(-EINVAL, rbd_aio_get_return_value(comp));
+  rbd_aio_release(comp);
+
+  rbd_aio_create_completion(NULL, (rbd_callback_t) simple_read_cb, &comp);
+  ASSERT_EQ(0, rbd_aio_read(image, info.size, 1, test_data, comp));
+  ASSERT_EQ(0, rbd_aio_wait_for_complete(comp));
+  ASSERT_EQ(-EINVAL, rbd_aio_get_return_value(comp));
+  rbd_aio_release(comp);
 
   ASSERT_PASSED(validate_object_map, image);
   ASSERT_EQ(0, rbd_close(image));
@@ -903,15 +915,16 @@ TEST_F(TestLibRBD, TestIOWithIOHint)
 			    LIBRADOS_OP_FLAG_FADVISE_DONTNEED));
 
   rbd_aio_create_completion(NULL, (rbd_callback_t) simple_read_cb, &comp);
-  ASSERT_EQ(-EINVAL, rbd_aio_write(image, info.size, 1, test_data, comp));
-  ASSERT_EQ(-EINVAL, rbd_aio_read2(image, info.size, 1, test_data, comp,
-				    LIBRADOS_OP_FLAG_FADVISE_DONTNEED));
+  ASSERT_EQ(0, rbd_aio_read2(image, info.size, 1, test_data, comp,
+			     LIBRADOS_OP_FLAG_FADVISE_DONTNEED));
+  ASSERT_EQ(0, rbd_aio_wait_for_complete(comp));
+  ASSERT_EQ(-EINVAL, rbd_aio_get_return_value(comp));
+  rbd_aio_release(comp);
 
   ASSERT_PASSED(validate_object_map, image);
   ASSERT_EQ(0, rbd_close(image));
 
   rados_ioctx_destroy(ioctx);
-
 }
 
 TEST_F(TestLibRBD, TestEmptyDiscard)
@@ -1113,6 +1126,7 @@ TEST_F(TestLibRBD, TestIOPPWithIOHint)
     ASSERT_EQ(0, rbd.open(ioctx, image, name.c_str(), NULL));
 
     char test_data[TEST_IO_SIZE + 1];
+    test_data[TEST_IO_SIZE] = '\0';
     int i;
 
     for (i = 0; i < TEST_IO_SIZE; ++i) {
@@ -1945,14 +1959,15 @@ TEST_F(TestLibRBD, FlushAioPP)
     for (i = 0; i < TEST_IO_SIZE; ++i) {
       test_data[i] = (char) (rand() % (126 - 33) + 33);
     }
+    test_data[TEST_IO_SIZE] = '\0';
 
     librbd::RBD::AioCompletion *write_comps[num_aios];
+    ceph::bufferlist bls[num_aios];
     for (i = 0; i < num_aios; ++i) {
-      ceph::bufferlist bl;
-      bl.append(test_data, strlen(test_data));
+      bls[i].append(test_data, strlen(test_data));
       write_comps[i] = new librbd::RBD::AioCompletion(NULL, NULL);
       uint64_t offset = rand() % (size - TEST_IO_SIZE);
-      ASSERT_EQ(0, image.aio_write(offset, TEST_IO_SIZE, bl,
+      ASSERT_EQ(0, image.aio_write(offset, TEST_IO_SIZE, bls[i],
 				   write_comps[i]));
     }
 
@@ -1961,12 +1976,12 @@ TEST_F(TestLibRBD, FlushAioPP)
     ASSERT_EQ(0, image.aio_flush(flush_comp));
     ASSERT_EQ(0, flush_comp->wait_for_complete());
     ASSERT_EQ(1, flush_comp->is_complete());
-    delete flush_comp;
+    flush_comp->release();
 
     for (i = 0; i < num_aios; ++i) {
       librbd::RBD::AioCompletion *comp = write_comps[i];
       ASSERT_EQ(1, comp->is_complete());
-      delete comp;
+      comp->release();
     }
     ASSERT_PASSED(validate_object_map, image);
   }
@@ -2595,3 +2610,58 @@ TEST_F(TestLibRBD, ObjectMapConsistentSnap)
   ASSERT_EQ(0, image1.snap_set(NULL));
   ASSERT_PASSED(validate_object_map, image1);
 }
+
+TEST_F(TestLibRBD, BlockingAIO)
+{
+  librados::IoCtx ioctx;
+  ASSERT_EQ(0, _rados.ioctx_create(m_pool_name.c_str(), ioctx));
+
+  librbd::RBD rbd;
+  std::string name = get_temp_image_name();
+  uint64_t size = 1 << 20;
+  int order = 18;
+  ASSERT_EQ(0, create_image_pp(rbd, ioctx, name.c_str(), size, &order));
+
+  CephContext *cct = reinterpret_cast<CephContext*>(ioctx.cct());
+  cct->_conf->set_val_or_die("rbd_non_blocking_aio", "0");
+
+  librbd::Image image;
+  ASSERT_EQ(0, rbd.open(ioctx, image, name.c_str(), NULL));
+
+  bufferlist bl;
+  bl.append(std::string(256, '1'));
+
+  librbd::RBD::AioCompletion *write_comp =
+    new librbd::RBD::AioCompletion(NULL, NULL);
+  ASSERT_EQ(0, image.aio_write(0, bl.length(), bl, write_comp));
+
+  librbd::RBD::AioCompletion *flush_comp =
+    new librbd::RBD::AioCompletion(NULL, NULL);
+  ASSERT_EQ(0, image.aio_flush(flush_comp));
+  ASSERT_EQ(0, flush_comp->wait_for_complete());
+  ASSERT_EQ(0, flush_comp->get_return_value());
+  flush_comp->release();
+
+  ASSERT_EQ(1, write_comp->is_complete());
+  ASSERT_EQ(0, write_comp->get_return_value());
+  write_comp->release();
+
+  librbd::RBD::AioCompletion *discard_comp =
+    new librbd::RBD::AioCompletion(NULL, NULL);
+  ASSERT_EQ(0, image.aio_discard(128, 128, discard_comp));
+  ASSERT_EQ(0, discard_comp->wait_for_complete());
+  discard_comp->release();
+
+  librbd::RBD::AioCompletion *read_comp =
+    new librbd::RBD::AioCompletion(NULL, NULL);
+  bufferlist read_bl;
+  image.aio_read(0, bl.length(), read_bl, read_comp);
+  ASSERT_EQ(0, read_comp->wait_for_complete());
+  ASSERT_EQ(bl.length(), read_comp->get_return_value());
+  read_comp->release();
+
+  bufferlist expected_bl;
+  expected_bl.append(std::string(128, '1'));
+  expected_bl.append(std::string(128, '\0'));
+  ASSERT_TRUE(expected_bl.contents_equal(read_bl));
+}
diff --git a/src/test/librbd/test_main.cc b/src/test/librbd/test_main.cc
index 4b72eb4..4c80fba 100644
--- a/src/test/librbd/test_main.cc
+++ b/src/test/librbd/test_main.cc
@@ -3,19 +3,26 @@
 
 #include "gtest/gtest.h"
 #include "common/ceph_argparse.h"
+#include "common/ceph_crypto.h"
 #include "global/global_context.h"
 #include "global/global_init.h"
 #include <vector>
 
+extern void register_test_librbd();
+#ifdef TEST_LIBRBD_INTERNALS
 extern void register_test_image_watcher();
 extern void register_test_internal();
-extern void register_test_librbd();
+extern void register_test_object_map();
+#endif // TEST_LIBRBD_INTERNALS
 
 int main(int argc, char **argv)
 {
+  register_test_librbd();
+#ifdef TEST_LIBRBD_INTERNALS
   register_test_image_watcher();
   register_test_internal();
-  register_test_librbd();
+  register_test_object_map();
+#endif // TEST_LIBRBD_INTERNALS
 
   ::testing::InitGoogleTest(&argc, argv);
 
@@ -25,5 +32,8 @@ int main(int argc, char **argv)
   global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0);
   common_init_finish(g_ceph_context);
 
-  return RUN_ALL_TESTS();
+  int r = RUN_ALL_TESTS();
+  g_ceph_context->put();
+  ceph::crypto::shutdown();
+  return r;
 }
diff --git a/src/test/librbd/test_support.cc b/src/test/librbd/test_support.cc
new file mode 100644
index 0000000..318b5be
--- /dev/null
+++ b/src/test/librbd/test_support.cc
@@ -0,0 +1,30 @@
+// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+#include "test/librbd/test_support.h"
+#include <sstream>
+
+bool get_features(uint64_t *features) {
+  const char *c = getenv("RBD_FEATURES");
+  if (c == NULL) {
+    return false;
+  }
+
+  std::stringstream ss(c);
+  if (!(ss >> *features)) {
+    return false;
+  }
+  return true;
+}
+
+bool is_feature_enabled(uint64_t feature) {
+  uint64_t features;
+  return (get_features(&features) && (features & feature) == feature);
+}
+
+int create_image_pp(librbd::RBD &rbd, librados::IoCtx &ioctx,
+                    const std::string &name, uint64_t size) {
+  uint64_t features = 0;
+  get_features(&features);
+  int order = 0;
+  return rbd.create2(ioctx, name.c_str(), size, features, &order);
+}
diff --git a/src/test/librbd/test_support.h b/src/test/librbd/test_support.h
new file mode 100644
index 0000000..5bdd958
--- /dev/null
+++ b/src/test/librbd/test_support.h
@@ -0,0 +1,19 @@
+// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+#include "include/int_types.h"
+#include "include/rados/librados.h"
+#include "include/rbd/librbd.hpp"
+#include <string>
+
+bool get_features(uint64_t *features);
+bool is_feature_enabled(uint64_t feature);
+int create_image_pp(librbd::RBD &rbd, librados::IoCtx &ioctx,
+                    const std::string &name, uint64_t size);
+
+#define REQUIRE_FEATURE(feature) { 	  \
+  if (!is_feature_enabled(feature)) { 	  \
+    std::cout << "SKIPPING" << std::endl; \
+    return SUCCEED(); 			  \
+  } 					  \
+}
+
diff --git a/src/test/mon/osd-crush.sh b/src/test/mon/osd-crush.sh
index 4b1c601..2242e9c 100755
--- a/src/test/mon/osd-crush.sh
+++ b/src/test/mon/osd-crush.sh
@@ -15,7 +15,7 @@
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU Library Public License for more details.
 #
-source test/mon/mon-test-helpers.sh
+source test/ceph-helpers.sh
 
 function run() {
     local dir=$1
@@ -30,7 +30,7 @@ function run() {
 	setup $dir || return 1
 	run_mon $dir a --public-addr $CEPH_MON
 	if ! $TEST_function $dir ; then
-	  cat $dir/a/log
+	  cat $dir/mon.a.log
 	  return 1
 	fi
 	teardown $dir || return 1
@@ -103,8 +103,8 @@ function TEST_crush_rule_create_erasure() {
     ./ceph osd erasure-code-profile rm default || return 1
     ! ./ceph osd erasure-code-profile ls | grep default || return 1
     ./ceph osd crush rule create-erasure $ruleset || return 1
-    CEPH_ARGS='' ./ceph --admin-daemon $dir/a/ceph-mon.a.asok log flush || return 1
-    grep 'profile default set' $dir/a/log || return 1
+    CEPH_ARGS='' ./ceph --admin-daemon $dir/ceph-mon.a.asok log flush || return 1
+    grep 'profile default set' $dir/mon.a.log || return 1
     ./ceph osd erasure-code-profile ls | grep default || return 1
     ./ceph osd crush rule rm $ruleset || return 1
     ! ./ceph osd crush rule ls | grep $ruleset || return 1
@@ -188,7 +188,24 @@ function TEST_crush_rename_bucket() {
     ./ceph osd crush rename-bucket nonexistent something 2>&1 | grep "Error ENOENT" || return 1
 }
 
-main osd-crush
+function TEST_crush_reject_empty() {
+    local dir=$1
+    # should have at least one OSD
+    run_osd $dir 0 || return 1
+
+    local empty_map=$dir/empty_map
+    :> $empty_map.txt
+    ./crushtool -c $empty_map.txt -o $empty_map.map || return 1
+    expect_failure $dir "Error EINVAL" \
+        ./ceph osd setcrushmap -i $empty_map.map || return 1
+}
+
+function TEST_crush_tree() {
+    ./ceph osd crush tree --format=xml | \
+        $XMLSTARLET val -e -r test/mon/osd-crush-tree.rng - || return 1
+}
+
+main osd-crush 
 
 # Local Variables:
 # compile-command: "cd ../.. ; make -j4 && test/mon/osd-crush.sh"
diff --git a/src/test/mon/osd-pool-create.sh b/src/test/mon/osd-pool-create.sh
index 428bfe0..8a57856 100755
--- a/src/test/mon/osd-pool-create.sh
+++ b/src/test/mon/osd-pool-create.sh
@@ -236,6 +236,21 @@ function TEST_no_pool_delete() {
     ./ceph osd pool delete foo foo --yes-i-really-really-mean-it
 }
 
+function TEST_utf8_cli() {
+    local dir=$1
+    run_mon $dir a --public-addr $CEPH_MON
+    # Hopefully it's safe to include literal UTF-8 characters to test
+    # the fix for http://tracker.ceph.com/issues/7387.  If it turns out
+    # to not be OK (when is the default encoding *not* UTF-8?), maybe
+    # the character '黄' can be replaced with the escape $'\xe9\xbb\x84'
+    ./ceph osd pool create 黄 1024 2>&1 | \
+        grep "pool '黄' created" || return 1
+    ./ceph osd lspools 2>&1 | \
+        grep "黄" || return 1
+    ./ceph -f json-pretty osd dump | \
+        python -c "import json; import sys; json.load(sys.stdin)" || return 1
+    ./ceph osd pool delete 黄 黄 --yes-i-really-really-mean-it
+}
 
 main osd-pool-create
 
diff --git a/src/test/osd/RadosModel.h b/src/test/osd/RadosModel.h
index f9c0f9b..8d6889e 100644
--- a/src/test/osd/RadosModel.h
+++ b/src/test/osd/RadosModel.h
@@ -47,6 +47,7 @@ typename T::iterator rand_choose(T &cont) {
 enum TestOpType {
   TEST_OP_READ,
   TEST_OP_WRITE,
+  TEST_OP_WRITE_EXCL,
   TEST_OP_DELETE,
   TEST_OP_SNAP_CREATE,
   TEST_OP_SNAP_REMOVE,
@@ -61,7 +62,8 @@ enum TestOpType {
   TEST_OP_CACHE_FLUSH,
   TEST_OP_CACHE_TRY_FLUSH,
   TEST_OP_CACHE_EVICT,
-  TEST_OP_APPEND
+  TEST_OP_APPEND,
+  TEST_OP_APPEND_EXCL
 };
 
 class TestWatchContext : public librados::WatchCtx2 {
@@ -716,14 +718,17 @@ public:
   bufferlist rbuffer;
 
   bool do_append;
+  bool do_excl;
 
   WriteOp(int n,
 	  RadosTestContext *context,
 	  const string &oid,
 	  bool do_append,
+	  bool do_excl,
 	  TestOpStat *stat = 0)
     : TestOp(n, context, stat),
-      oid(oid), waiting_on(0), last_acked_tid(0), do_append(do_append)
+      oid(oid), waiting_on(0), last_acked_tid(0), do_append(do_append),
+      do_excl(do_excl)
   {}
 		
   void _begin()
@@ -795,6 +800,8 @@ public:
       } else {
 	op.write(i->first, to_write);
       }
+      if (do_excl && tid == 1)
+	op.assert_exists();
       context->io_ctx.aio_operate(
 	context->prefix+oid, completion,
 	&op);
@@ -937,7 +944,15 @@ public:
     interval_set<uint64_t> ranges;
     context->state_lock.Unlock();
 
-    int r = context->io_ctx.remove(context->prefix+oid);
+    int r = 0;
+    if (rand() % 2) {
+      librados::ObjectWriteOperation op;
+      op.assert_exists();
+      op.remove();
+      r = context->io_ctx.operate(context->prefix+oid, &op);
+    } else {
+      r = context->io_ctx.remove(context->prefix+oid);
+    }
     if (r && !(r == -ENOENT && !present)) {
       cerr << "r is " << r << " while deleting " << oid << " and present is " << present << std::endl;
       assert(0);
diff --git a/src/test/osd/TestRados.cc b/src/test/osd/TestRados.cc
index 4d8b45c..e8eb0db 100644
--- a/src/test/osd/TestRados.cc
+++ b/src/test/osd/TestRados.cc
@@ -55,9 +55,9 @@ public:
       cout << m_op << ": write initial oid " << oid.str() << std::endl;
       context.oid_not_flushing.insert(oid.str());
       if (m_ec_pool) {
-	return new WriteOp(m_op, &context, oid.str(), true);
+	return new WriteOp(m_op, &context, oid.str(), true, true);
       } else {
-	return new WriteOp(m_op, &context, oid.str(), false);
+	return new WriteOp(m_op, &context, oid.str(), false, true);
       }
     } else if (m_op >= m_ops) {
       return NULL;
@@ -105,7 +105,14 @@ private:
       oid = *(rand_choose(context.oid_not_in_use));
       cout << m_op << ": " << "write oid " << oid << " current snap is "
 	   << context.current_snap << std::endl;
-      return new WriteOp(m_op, &context, oid, false, m_stats);
+      return new WriteOp(m_op, &context, oid, false, false, m_stats);
+
+    case TEST_OP_WRITE_EXCL:
+      oid = *(rand_choose(context.oid_not_in_use));
+      cout << m_op << ": " << "write (excl) oid "
+	   << oid << " current snap is "
+	   << context.current_snap << std::endl;
+      return new WriteOp(m_op, &context, oid, false, true, m_stats);
 
     case TEST_OP_DELETE:
       oid = *(rand_choose(context.oid_not_in_use));
@@ -206,7 +213,13 @@ private:
       oid = *(rand_choose(context.oid_not_in_use));
       cout << "append oid " << oid << " current snap is "
 	   << context.current_snap << std::endl;
-      return new WriteOp(m_op, &context, oid, true, m_stats);
+      return new WriteOp(m_op, &context, oid, true, false, m_stats);
+
+    case TEST_OP_APPEND_EXCL:
+      oid = *(rand_choose(context.oid_not_in_use));
+      cout << "append oid (excl) " << oid << " current snap is "
+	   << context.current_snap << std::endl;
+      return new WriteOp(m_op, &context, oid, true, true, m_stats);
 
     default:
       cerr << m_op << ": Invalid op type " << type << std::endl;
@@ -244,6 +257,7 @@ int main(int argc, char **argv)
   } op_types[] = {
     { TEST_OP_READ, "read", true },
     { TEST_OP_WRITE, "write", false },
+    { TEST_OP_WRITE_EXCL, "write_excl", false },
     { TEST_OP_DELETE, "delete", true },
     { TEST_OP_SNAP_CREATE, "snap_create", true },
     { TEST_OP_SNAP_REMOVE, "snap_remove", true },
@@ -259,6 +273,7 @@ int main(int argc, char **argv)
     { TEST_OP_CACHE_TRY_FLUSH, "cache_try_flush", true },
     { TEST_OP_CACHE_EVICT, "cache_evict", true },
     { TEST_OP_APPEND, "append", true },
+    { TEST_OP_APPEND_EXCL, "append_excl", true },
     { TEST_OP_READ /* grr */, NULL },
   };
 
diff --git a/src/test/strtol.cc b/src/test/strtol.cc
index 08ba081..93d6e68 100644
--- a/src/test/strtol.cc
+++ b/src/test/strtol.cc
@@ -174,7 +174,8 @@ TEST(SIStrToLL, WithUnits) {
 
   for (std::map<char,int>::iterator p = units.begin();
        p != units.end(); ++p) {
-    test_strict_sistrtoll_units("1024", p->first, p->second);
+    // the upper bound of uint64_t is 2^64 = 4E
+    test_strict_sistrtoll_units("4", p->first, p->second);
     test_strict_sistrtoll_units("1", p->first, p->second);
     test_strict_sistrtoll_units("0", p->first, p->second);
   }
@@ -208,4 +209,14 @@ TEST(SIStrToLL, Error) {
   test_strict_sistrtoll_err("BM");
   test_strict_sistrtoll_err("B0wef");
   test_strict_sistrtoll_err("0m");
+  test_strict_sistrtoll_err("-1"); // it returns uint64_t
+  test_strict_sistrtoll_err("-1K");
+  // the upper bound of uint64_t is 2^64 = 4E, so 1024E overflows
+  test_strict_sistrtoll_err("1024E"); // overflows after adding the suffix
 }
+
+/*
+ * Local Variables:
+ * compile-command: "cd .. ; make unittest_strtol && ./unittest_strtol"
+ * End:
+ */
diff --git a/src/tools/cephfs/Dumper.cc b/src/tools/cephfs/Dumper.cc
index 2075c7c..0603661 100644
--- a/src/tools/cephfs/Dumper.cc
+++ b/src/tools/cephfs/Dumper.cc
@@ -83,19 +83,9 @@ int Dumper::dump(const char *dump_file)
   uint64_t end = journaler.get_write_pos();
   uint64_t len = end-start;
 
-  cout << "journal is " << start << "~" << len << std::endl;
-
   Filer filer(objecter, &finisher);
-  bufferlist bl;
-
-  C_SaferCond cond;
-  lock.Lock();
-  filer.read(ino, &journaler.get_layout(), CEPH_NOSNAP,
-             start, len, &bl, 0, &cond);
-  lock.Unlock();
-  r = cond.wait();
 
-  cout << "read " << bl.length() << " bytes at offset " << start << std::endl;
+  cout << "journal is " << start << "~" << len << std::endl;
 
   int fd = ::open(dump_file, O_WRONLY|O_CREAT|O_TRUNC, 0644);
   if (fd >= 0) {
@@ -105,7 +95,7 @@ int Dumper::dump(const char *dump_file)
     sprintf(buf, "Ceph mds%d journal dump\n start offset %llu (0x%llx)\n       length %llu (0x%llx)\n    write_pos %llu (0x%llx)\n    format %llu\n    trimmed_pos %llu (0x%llx)\n%c",
 	    rank, 
 	    (unsigned long long)start, (unsigned long long)start,
-	    (unsigned long long)bl.length(), (unsigned long long)bl.length(),
+	    (unsigned long long)len, (unsigned long long)len,
 	    (unsigned long long)journaler.last_committed.write_pos, (unsigned long long)journaler.last_committed.write_pos,
 	    (unsigned long long)journaler.last_committed.stream_format,
 	    (unsigned long long)journaler.last_committed.trimmed_pos, (unsigned long long)journaler.last_committed.trimmed_pos,
@@ -125,11 +115,39 @@ int Dumper::dump(const char *dump_file)
       ::close(fd);
       return r;
     }
-    r = bl.write_fd(fd);
-    if (r) {
-      derr << "Error " << r << " (" << cpp_strerror(r) << ") writing journal file" << dendl;
-      ::close(fd);
-      return r;
+
+
+    // Read and write 32MB chunks.  Slower than it could be because we're not
+    // streaming, but that's okay because this is just a debug/disaster tool.
+    const uint32_t chunk_size = 32 * 1024 * 1024;
+
+    for (uint64_t pos = start; pos < start + len; pos += chunk_size) {
+      bufferlist bl;
+      dout(10) << "Reading at pos=0x" << std::hex << pos << std::dec << dendl;
+
+      const uint32_t read_size = MIN(chunk_size, end - pos);
+
+      C_SaferCond cond;
+      lock.Lock();
+      filer.read(ino, &journaler.get_layout(), CEPH_NOSNAP,
+                 pos, read_size, &bl, 0, &cond);
+      lock.Unlock();
+      r = cond.wait();
+      if (r < 0) {
+        derr << "Error " << r << " (" << cpp_strerror(r) << ") reading "
+                "journal at offset 0x" << std::hex << pos << std::dec << dendl;
+        ::close(fd);
+        return r;
+      }
+      dout(10) << "Got 0x" << std::hex << bl.length() << std::dec
+               << " bytes" << dendl;
+
+      r = bl.write_fd(fd);
+      if (r) {
+        derr << "Error " << r << " (" << cpp_strerror(r) << ") writing journal file" << dendl;
+        ::close(fd);
+        return r;
+      }
     }
 
     r = ::close(fd);
@@ -139,7 +157,7 @@ int Dumper::dump(const char *dump_file)
       return r;
     }
 
-    cout << "wrote " << bl.length() << " bytes at offset " << start << " to " << dump_file << "\n"
+    cout << "wrote " << len << " bytes at offset " << start << " to " << dump_file << "\n"
 	 << "NOTE: this is a _sparse_ file; you can\n"
 	 << "\t$ tar cSzf " << dump_file << ".tgz " << dump_file << "\n"
 	 << "      to efficiently compress it while preserving sparseness." << std::endl;
diff --git a/src/tools/crushtool.cc b/src/tools/crushtool.cc
index f332186..3e36ac9 100644
--- a/src/tools/crushtool.cc
+++ b/src/tools/crushtool.cc
@@ -135,6 +135,10 @@ void usage()
   cout << "                         reweight a given item (and adjust ancestor\n"
        << "                         weights as needed)\n";
   cout << "   -i mapfn --reweight   recalculate all bucket weights\n";
+  cout << "\n";
+  cout << "Options for the display/test stage\n";
+  cout << "\n";
+  cout << "   --check max_id        check if any item is referencing an unknown name/type\n";
   cout << "   -i mapfn --show-location id\n";
   cout << "                         show location for given device id\n";
   cout << "   --show-utilization    show OSD usage\n";
@@ -191,6 +195,8 @@ int main(int argc, const char **argv)
   std::string infn, srcfn, outfn, add_name, remove_name, reweight_name;
   bool compile = false;
   bool decompile = false;
+  bool check = false;
+  int max_id = -1;
   bool test = false;
   bool display = false;
   bool tree = false;
@@ -276,6 +282,8 @@ int main(int argc, const char **argv)
     } else if (ceph_argparse_witharg(args, i, &val, "-c", "--compile", (char*)NULL)) {
       srcfn = val;
       compile = true;
+    } else if (ceph_argparse_withint(args, i, &max_id, &err, "--check", (char*)NULL)) {
+      check = true;
     } else if (ceph_argparse_flag(args, i, "-t", "--test", (char*)NULL)) {
       test = true;
     } else if (ceph_argparse_withint(args, i, &full_location, &err, "--show-location", (char*)NULL)) {
@@ -462,7 +470,7 @@ int main(int argc, const char **argv)
     }
   }
 
-  if (test && !display && !write_to_file) {
+  if (test && !check && !display && !write_to_file) {
     cerr << "WARNING: no output selected; use --output-csv or --show-X" << std::endl;
   }
 
@@ -470,7 +478,7 @@ int main(int argc, const char **argv)
     cerr << "cannot specify more than one of compile, decompile, and build" << std::endl;
     exit(EXIT_FAILURE);
   }
-  if (!compile && !decompile && !build && !test && !reweight && !adjust && !tree &&
+  if (!check && !compile && !decompile && !build && !test && !reweight && !adjust && !tree &&
       add_item < 0 && full_location < 0 &&
       remove_name.empty() && reweight_name.empty()) {
     cerr << "no action specified; -h for help" << std::endl;
@@ -785,8 +793,9 @@ int main(int argc, const char **argv)
     crush.set_allowed_bucket_algs(allowed_bucket_algs);
     modified = true;
   }
-  if (modified) {
-    crush.finalize();
+
+ if (modified) {
+   crush.finalize();
 
     if (outfn.empty()) {
       cout << me << " successfully built or modified map.  Use '-o <file>' to write it out." << std::endl;
@@ -803,6 +812,12 @@ int main(int argc, const char **argv)
     }
   }
 
+  if (check) {
+    if (!tester.check_name_maps(max_id)) {
+      exit(1);
+    }
+  }
+
   if (test) {
     if (tester.get_output_utilization_all() ||
 	tester.get_output_utilization())

-- 
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