]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: helper methods to query and break lock 12922/head
authorMykola Golub <mgolub@mirantis.com>
Fri, 13 Jan 2017 14:13:22 +0000 (15:13 +0100)
committerMykola Golub <mgolub@mirantis.com>
Mon, 16 Jan 2017 22:12:29 +0000 (23:12 +0100)
Signed-off-by: Mykola Golub <mgolub@mirantis.com>
src/librbd/ManagedLock.cc
src/librbd/ManagedLock.h
src/librbd/internal.cc
src/test/librbd/test_mock_ManagedLock.cc

index ee1303cbea0495b138d56940566b9a5e3358d624..0a5074e28b0548314071a9920e1072ffbdc882ae 100644 (file)
@@ -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 <typename I>
 bool ManagedLock<I>::is_lock_owner() const {
   Mutex::Locker locker(m_lock);
 
+  return is_lock_owner(m_lock);
+}
+
+template <typename I>
+bool ManagedLock<I>::is_lock_owner(Mutex &lock) const {
+
+  assert(m_lock.is_locked());
+
   bool lock_owner;
 
   switch (m_state) {
@@ -182,6 +193,33 @@ void ManagedLock<I>::reacquire_lock(Context *on_reacquired) {
   }
 }
 
+template <typename I>
+void ManagedLock<I>::get_locker(managed_lock::Locker *locker,
+                                Context *on_finish) {
+  ldout(m_cct, 10) << dendl;
+
+  auto req = managed_lock::GetLockerRequest<I>::create(
+    m_ioctx, m_oid, locker, on_finish);
+  req->send();
+}
+
+template <typename I>
+void ManagedLock<I>::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<I>::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 <typename I>
 void ManagedLock<I>::shutdown_handler(int r, Context *on_finish) {
   on_finish->complete(r);
index 41b439d9d60d9c1507d36fdb6098d2b0255664bd..0b4893926df5b58d95df7dd9ba8e4ddff664c181 100644 (file)
@@ -20,6 +20,8 @@ namespace librbd {
 
 struct ImageCtx;
 
+namespace managed_lock { struct Locker; }
+
 template <typename ImageCtxT = librbd::ImageCtx>
 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);
index 0f9912843f559e8717d5b7b6062c70d34e9f4e75..7690f8bb3fd0ca31575e9eb69e03df0beffb5382 100644 (file)
@@ -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;
index 6b7b5228e61729d9f2b0c2f436b938aa54a69b5f..f546003b9cdef3904485620ce078bee0b7f7a60c 100644 (file)
@@ -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<MockManagedLockImageCtx> : public BaseRequest<ReleaseReque
   MOCK_METHOD0(send, void());
 };
 
+template <>
+struct GetLockerRequest<MockManagedLockImageCtx> {
+  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<MockManagedLockImageCtx> {
+  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