From: Mykola Golub Date: Fri, 13 Jan 2017 14:13:22 +0000 (+0100) Subject: librbd: helper methods to query and break lock X-Git-Tag: v12.0.0~159^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=refs%2Fpull%2F12922%2Fhead;p=ceph.git librbd: helper methods to query and break lock Signed-off-by: Mykola Golub --- diff --git a/src/librbd/ManagedLock.cc b/src/librbd/ManagedLock.cc index ee1303cbea04..0a5074e28b05 100644 --- a/src/librbd/ManagedLock.cc +++ b/src/librbd/ManagedLock.cc @@ -3,8 +3,11 @@ #include "librbd/ManagedLock.h" #include "librbd/managed_lock/AcquireRequest.h" +#include "librbd/managed_lock/BreakRequest.h" +#include "librbd/managed_lock/GetLockerRequest.h" #include "librbd/managed_lock/ReleaseRequest.h" #include "librbd/managed_lock/ReacquireRequest.h" +#include "librbd/managed_lock/Types.h" #include "librbd/Watcher.h" #include "librbd/ImageCtx.h" #include "cls/lock/cls_lock_client.h" @@ -67,6 +70,14 @@ template bool ManagedLock::is_lock_owner() const { Mutex::Locker locker(m_lock); + return is_lock_owner(m_lock); +} + +template +bool ManagedLock::is_lock_owner(Mutex &lock) const { + + assert(m_lock.is_locked()); + bool lock_owner; switch (m_state) { @@ -182,6 +193,33 @@ void ManagedLock::reacquire_lock(Context *on_reacquired) { } } +template +void ManagedLock::get_locker(managed_lock::Locker *locker, + Context *on_finish) { + ldout(m_cct, 10) << dendl; + + auto req = managed_lock::GetLockerRequest::create( + m_ioctx, m_oid, locker, on_finish); + req->send(); +} + +template +void ManagedLock::break_lock(const managed_lock::Locker &locker, + bool force_break_lock, Context *on_finish) { + { + Mutex::Locker l(m_lock); + if (!is_lock_owner(m_lock)) { + auto req = managed_lock::BreakRequest::create( + m_ioctx, m_work_queue, m_oid, locker, m_blacklist_on_break_lock, + m_blacklist_expire_seconds, force_break_lock, on_finish); + req->send(); + return; + } + } + + on_finish->complete(-EBUSY); +} + template void ManagedLock::shutdown_handler(int r, Context *on_finish) { on_finish->complete(r); diff --git a/src/librbd/ManagedLock.h b/src/librbd/ManagedLock.h index 41b439d9d60d..0b4893926df5 100644 --- a/src/librbd/ManagedLock.h +++ b/src/librbd/ManagedLock.h @@ -20,6 +20,8 @@ namespace librbd { struct ImageCtx; +namespace managed_lock { struct Locker; } + template class ManagedLock { private: @@ -50,6 +52,9 @@ public: void try_acquire_lock(Context *on_acquired); void release_lock(Context *on_released); void reacquire_lock(Context *on_reacquired = nullptr); + void get_locker(managed_lock::Locker *locker, Context *on_finish); + void break_lock(const managed_lock::Locker &locker, bool force_break_lock, + Context *on_finish); bool is_shutdown() const { Mutex::Locker l(m_lock); @@ -168,6 +173,7 @@ private: static std::string encode_lock_cookie(uint64_t watch_handle); + bool is_lock_owner(Mutex &lock) const; bool is_transition_state() const; void append_context(Action action, Context *ctx); diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc index 0f9912843f55..7690f8bb3fd0 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -33,8 +33,6 @@ #include "librbd/internal.h" #include "librbd/Journal.h" #include "librbd/journal/Types.h" -#include "librbd/managed_lock/BreakRequest.h" -#include "librbd/managed_lock/GetLockerRequest.h" #include "librbd/managed_lock/Types.h" #include "librbd/mirror/DisableRequest.h" #include "librbd/mirror/EnableRequest.h" @@ -1568,12 +1566,14 @@ void filter_out_mirror_watchers(ImageCtx *ictx, CephContext *cct = ictx->cct; ldout(cct, 20) << __func__ << ": ictx=" << ictx << dendl; + if (!ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) { + lderr(cct) << "exclusive-lock feature is not enabled" << dendl; + return -EINVAL; + } + managed_lock::Locker locker; C_SaferCond get_owner_ctx; - auto get_owner_req = managed_lock::GetLockerRequest<>::create( - ictx->md_ctx, ictx->header_oid, &locker, &get_owner_ctx); - get_owner_req->send(); - + ExclusiveLock<>(*ictx).get_locker(&locker, &get_owner_ctx); int r = get_owner_ctx.wait(); if (r == -ENOENT) { return r; @@ -1601,12 +1601,22 @@ void filter_out_mirror_watchers(ImageCtx *ictx, return -EOPNOTSUPP; } + if (ictx->read_only) { + return -EROFS; + } + managed_lock::Locker locker; C_SaferCond get_owner_ctx; - auto get_owner_req = managed_lock::GetLockerRequest<>::create( - ictx->md_ctx, ictx->header_oid, &locker, &get_owner_ctx); - get_owner_req->send(); + { + RWLock::RLocker l(ictx->owner_lock); + if (ictx->exclusive_lock == nullptr) { + lderr(cct) << "exclusive-lock feature is not enabled" << dendl; + return -EINVAL; + } + + ictx->exclusive_lock->get_locker(&locker, &get_owner_ctx); + } int r = get_owner_ctx.wait(); if (r == -ENOENT) { return r; @@ -1621,12 +1631,16 @@ void filter_out_mirror_watchers(ImageCtx *ictx, } C_SaferCond break_ctx; - auto break_req = managed_lock::BreakRequest<>::create( - ictx->md_ctx, ictx->op_work_queue, ictx->header_oid, locker, - ictx->blacklist_on_break_lock, ictx->blacklist_expire_seconds, true, - &break_ctx); - break_req->send(); + { + RWLock::RLocker l(ictx->owner_lock); + if (ictx->exclusive_lock == nullptr) { + lderr(cct) << "exclusive-lock feature is not enabled" << dendl; + return -EINVAL; + } + + ictx->exclusive_lock->break_lock(locker, true, &break_ctx); + } r = break_ctx.wait(); if (r == -ENOENT) { return r; diff --git a/src/test/librbd/test_mock_ManagedLock.cc b/src/test/librbd/test_mock_ManagedLock.cc index 6b7b5228e617..f546003b9cde 100644 --- a/src/test/librbd/test_mock_ManagedLock.cc +++ b/src/test/librbd/test_mock_ManagedLock.cc @@ -5,6 +5,8 @@ #include "test/librbd/test_support.h" #include "librbd/ManagedLock.h" #include "librbd/managed_lock/AcquireRequest.h" +#include "librbd/managed_lock/BreakRequest.h" +#include "librbd/managed_lock/GetLockerRequest.h" #include "librbd/managed_lock/ReacquireRequest.h" #include "librbd/managed_lock/ReleaseRequest.h" #include "gmock/gmock.h" @@ -80,6 +82,34 @@ struct ReleaseRequest : public BaseRequest +struct GetLockerRequest { + static GetLockerRequest* create(librados::IoCtx& ioctx, + const std::string& oid, + Locker *locker, Context *on_finish) { + assert(0 == "unexpected call"); + } + + void send() { + assert(0 == "unexpected call"); + } +}; + +template <> +struct BreakRequest { + static BreakRequest* create(librados::IoCtx& ioctx, ContextWQ *work_queue, + const std::string& oid, const Locker &locker, + bool blacklist_locker, + uint32_t blacklist_expire_seconds, + bool force_break_lock, Context *on_finish) { + assert(0 == "unexpected call"); + } + + void send() { + assert(0 == "unexpected call"); + } +}; + } // namespace managed_lock } // namespace librbd