From: Jason Dillaman Date: Tue, 21 Apr 2015 14:17:17 +0000 (-0400) Subject: librbd: copyup now optionally updates the snapshot object maps X-Git-Tag: v9.0.2~225^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=refs%2Fpull%2F4422%2Fhead;p=ceph.git librbd: copyup now optionally updates the snapshot object maps Signed-off-by: Jason Dillaman --- diff --git a/src/librbd/CopyupRequest.cc b/src/librbd/CopyupRequest.cc index 83e432210cb..1b8ff2529df 100644 --- a/src/librbd/CopyupRequest.cc +++ b/src/librbd/CopyupRequest.cc @@ -8,12 +8,15 @@ #include "librbd/AioCompletion.h" #include "librbd/AioRequest.h" +#include "librbd/AsyncObjectThrottle.h" #include "librbd/CopyupRequest.h" #include "librbd/ImageCtx.h" #include "librbd/ImageWatcher.h" #include "librbd/ObjectMap.h" #include +#include +#include #define dout_subsys ceph_subsys_rbd #undef dout_prefix @@ -21,6 +24,52 @@ namespace librbd { +namespace { + +class UpdateObjectMap : public C_AsyncObjectThrottle { +public: + UpdateObjectMap(AsyncObjectThrottle &throttle, ImageCtx *image_ctx, + uint64_t object_no, const std::vector *snap_ids, + size_t snap_id_idx) + : C_AsyncObjectThrottle(throttle), m_image_ctx(*image_ctx), + m_object_no(object_no), m_snap_ids(*snap_ids), m_snap_id_idx(snap_id_idx) + { + } + + virtual int send() { + uint64_t snap_id = m_snap_ids[m_snap_id_idx]; + if (snap_id == CEPH_NOSNAP) { + RWLock::RLocker owner_locker(m_image_ctx.owner_lock); + RWLock::WLocker object_map_locker(m_image_ctx.object_map_lock); + assert(m_image_ctx.image_watcher->is_lock_owner()); + bool sent = m_image_ctx.object_map.aio_update(m_object_no, OBJECT_EXISTS, + boost::optional(), + this); + return (sent ? 0 : 1); + } + + uint8_t state = OBJECT_EXISTS; + if (m_image_ctx.test_features(RBD_FEATURE_DEEP_FLATTEN) && + m_snap_id_idx + 1 < m_snap_ids.size()) { + state = OBJECT_EXISTS_CLEAN; + } + + RWLock::RLocker object_map_locker(m_image_ctx.object_map_lock); + m_image_ctx.object_map.aio_update(snap_id, m_object_no, m_object_no + 1, + state, boost::optional(), this); + return 0; + } + +private: + ImageCtx &m_image_ctx; + uint64_t m_object_no; + const std::vector &m_snap_ids; + size_t m_snap_id_idx; +}; + +} // anonymous namespace + + CopyupRequest::CopyupRequest(ImageCtx *ictx, const std::string &oid, uint64_t objectno, vector >& image_extents) @@ -162,6 +211,7 @@ namespace librbd { void CopyupRequest::complete(int r) { if (should_complete(r)) { + complete_requests(r); delete this; } } @@ -188,33 +238,25 @@ namespace librbd { case STATE_OBJECT_MAP: ldout(cct, 20) << "OBJECT_MAP" << dendl; - if (r == 0) { - return send_copyup(); - } - break; + assert(r == 0); + return send_copyup(); case STATE_COPYUP: // invoked via a finisher in librados, so thread safe pending_copyups = m_pending_copyups.dec(); ldout(cct, 20) << "COPYUP (" << pending_copyups << " pending)" << dendl; - if (pending_copyups == 0 || r < 0) { + if (r < 0) { complete_requests(r); - return (pending_copyups == 0); } - break; + return (pending_copyups == 0); default: lderr(cct) << "invalid state: " << m_state << dendl; assert(false); break; } - - if (r < 0) { - complete_requests(r); - return true; - } - return false; + return (r < 0); } void CopyupRequest::remove_from_list() @@ -228,40 +270,46 @@ namespace librbd { } bool CopyupRequest::send_object_map() { - bool copyup = false; { RWLock::RLocker l(m_ictx->owner_lock); - if (!m_ictx->object_map.enabled()) { - copyup = true; - } else if (!m_ictx->image_watcher->is_lock_owner()) { - ldout(m_ictx->cct, 20) << "exclusive lock not held for copyup request" - << dendl; - assert(m_pending_requests.empty()); - return true; - } else { + if (m_ictx->object_map.enabled()) { + if (!m_ictx->image_watcher->is_lock_owner()) { + ldout(m_ictx->cct, 20) << "exclusive lock not held for copyup request" + << dendl; + assert(m_pending_requests.empty()); + return true; + } + + RWLock::RLocker snap_locker(m_ictx->snap_lock); RWLock::WLocker object_map_locker(m_ictx->object_map_lock); - if (m_ictx->object_map[m_object_no] != OBJECT_EXISTS) { - ldout(m_ictx->cct, 20) << __func__ << " " << this - << ": oid " << m_oid - << ", extents " << m_image_extents - << dendl; - m_state = STATE_OBJECT_MAP; - - Context *ctx = create_callback_context(); - bool sent = m_ictx->object_map.aio_update(m_object_no, OBJECT_EXISTS, - boost::optional(), - ctx); - assert(sent); - } else { - copyup = true; + if (m_ictx->object_map[m_object_no] != OBJECT_EXISTS || + !m_ictx->snaps.empty()) { + m_snap_ids.push_back(CEPH_NOSNAP); + m_snap_ids.insert(m_snap_ids.end(), m_ictx->snaps.begin(), + m_ictx->snaps.end()); } } } // avoid possible recursive lock attempts - if (copyup) { + if (m_snap_ids.empty()) { // no object map update required return send_copyup(); + } else { + // update object maps for HEAD and all existing snapshots + ldout(m_ictx->cct, 20) << __func__ << " " << this + << ": oid " << m_oid + << dendl; + m_state = STATE_OBJECT_MAP; + + AsyncObjectThrottle::ContextFactory context_factory( + boost::lambda::bind(boost::lambda::new_ptr(), + boost::lambda::_1, m_ictx, m_object_no, &m_snap_ids, + boost::lambda::_2)); + AsyncObjectThrottle *throttle = new AsyncObjectThrottle( + NULL, context_factory, create_callback_context(), NULL, 0, + m_snap_ids.size()); + throttle->start_ops(m_ictx->concurrent_management_ops); } return false; } diff --git a/src/librbd/CopyupRequest.h b/src/librbd/CopyupRequest.h index aa07471be1e..fd1fd87b241 100644 --- a/src/librbd/CopyupRequest.h +++ b/src/librbd/CopyupRequest.h @@ -36,13 +36,16 @@ namespace librbd { * * | * v - * STATE_READ_FROM_PARENT ----> STATE_OBJECT_MAP . . . - * . . | . - * . . v . - * . . . . . > STATE_COPYUP . - * . | . - * . v . - * . . . . . . . . . . . . > < . . . . . . + * STATE_READ_FROM_PARENT + * . . | + * . . v + * . . STATE_OBJECT_MAP . . + * . . | . + * . . v . + * . . . > STATE_COPYUP . + * . | . + * . v . + * . . . . > < . . . . . * * @endverbatim * @@ -67,6 +70,8 @@ namespace librbd { AsyncOperation m_async_op; + std::vector m_snap_ids; + void complete_requests(int r); void complete(int r);