]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: recheck current lock owner before blacklist
authorJason Dillaman <dillaman@redhat.com>
Thu, 18 May 2017 16:38:44 +0000 (12:38 -0400)
committerJason Dillaman <dillaman@redhat.com>
Fri, 19 May 2017 12:43:37 +0000 (08:43 -0400)
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
qa/workunits/rbd/rbd_mirror.sh
src/librbd/ManagedLock.cc
src/librbd/managed_lock/AcquireRequest.cc
src/librbd/managed_lock/AcquireRequest.h
src/librbd/managed_lock/BreakRequest.cc
src/librbd/managed_lock/BreakRequest.h
src/test/librbd/managed_lock/test_mock_AcquireRequest.cc
src/test/librbd/managed_lock/test_mock_BreakRequest.cc
src/test/librbd/test_mock_ManagedLock.cc

index f49359412059b67bb6f14e3c83552c61fdcfa79f..f000b66271c1d40c6947acfd06b11c6b4d395be1 100755 (executable)
@@ -387,4 +387,8 @@ wait_for_status_in_pool_dir ${CLUSTER1} ${POOL} ${image} 'up+error' 'split-brain
 request_resync_image ${CLUSTER1} ${POOL} ${image} image_id
 wait_for_status_in_pool_dir ${CLUSTER1} ${POOL} ${image} 'up+replaying' 'master_position'
 
+testlog "TEST: no blacklists"
+ceph --cluster ${CLUSTER1} osd blacklist ls 2>&1 | grep -q "listed 0 entries"
+ceph --cluster ${CLUSTER2} osd blacklist ls 2>&1 | grep -q "listed 0 entries"
+
 echo OK
index ee321bf93adea28662eaf0e749f4cfacd55b894d..f584d6af5fb5e9518388c087cd9a43be12be83e2 100644 (file)
@@ -256,8 +256,9 @@ void ManagedLock<I>::break_lock(const managed_lock::Locker &locker,
     } else {
       on_finish = new C_Tracked(m_async_op_tracker, on_finish);
       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);
+        m_ioctx, m_work_queue, m_oid, locker, m_mode == EXCLUSIVE,
+        m_blacklist_on_break_lock, m_blacklist_expire_seconds, force_break_lock,
+        on_finish);
       req->send();
       return;
     }
index 0249be2a14ea7d96726fe3a0d8fbf6c875de3126..83f5dbac1a8bbe55e467391632b6325dbf2443f5 100644 (file)
@@ -146,8 +146,8 @@ void AcquireRequest<I>::send_break_lock() {
   Context *ctx = create_context_callback<
     AcquireRequest<I>, &AcquireRequest<I>::handle_break_lock>(this);
   auto req = BreakRequest<I>::create(
-    m_ioctx, m_work_queue, m_oid, m_locker, m_blacklist_on_break_lock,
-    m_blacklist_expire_seconds, false, ctx);
+    m_ioctx, m_work_queue, m_oid, m_locker, m_exclusive,
+    m_blacklist_on_break_lock, m_blacklist_expire_seconds, false, ctx);
   req->send();
 }
 
@@ -165,7 +165,8 @@ void AcquireRequest<I>::handle_break_lock(int r) {
     return;
   }
 
-  send_get_locker();
+  m_locker = {};
+  send_lock();
 }
 
 template <typename I>
index 16a5be36c787981300b4fed51e73b1d86940b704..20af0693349432bbfaa0b22d3f69e3d7691bec63 100644 (file)
@@ -47,15 +47,17 @@ private:
    * <start>
    *    |
    *    v
-   * GET_LOCKER <---------------------------------------\
-   *    |     ^                                         |
-   *    |     . (EBUSY && no cached locker)             |
-   *    |     .                                         |
-   *    |     .          (EBUSY && cached locker)       |
-   *    \--> LOCK_IMAGE * * * * * * * * > BREAK_LOCK ---/
-   *              |
-   *              v
-   *          <finish>
+   * GET_LOCKER
+   *    |     ^
+   *    |     . (EBUSY && no cached locker)
+   *    |     .
+   *    |     .          (EBUSY && cached locker)
+   *    \--> LOCK_IMAGE * * * * * * * * > BREAK_LOCK . . . . .
+   *            |   ^                         |              .
+   *            |   |                         | (success)    .
+   *            |   \-------------------------/              .
+   *            v                                            .
+   *         <finish>  < . . . . . . . . . . . . . . . . . . .
    *
    * @endverbatim
    */
index 6c4d4d208fe8435e39439819d14a2c25faf3453d..9a7fe10f35a4fde33b8ce96878d3ccffee10bee0 100644 (file)
@@ -10,6 +10,7 @@
 #include "cls/lock/cls_lock_types.h"
 #include "librbd/ImageCtx.h"
 #include "librbd/Utils.h"
+#include "librbd/managed_lock/GetLockerRequest.h"
 
 #define dout_subsys ceph_subsys_rbd
 #undef dout_prefix
@@ -48,12 +49,12 @@ struct C_BlacklistClient : public Context {
 template <typename I>
 BreakRequest<I>::BreakRequest(librados::IoCtx& ioctx, ContextWQ *work_queue,
                               const std::string& oid, const Locker &locker,
-                              bool blacklist_locker,
+                              bool exclusive, bool blacklist_locker,
                               uint32_t blacklist_expire_seconds,
                               bool force_break_lock, Context *on_finish)
   : m_ioctx(ioctx), m_cct(reinterpret_cast<CephContext *>(m_ioctx.cct())),
     m_work_queue(work_queue), m_oid(oid), m_locker(locker),
-    m_blacklist_locker(blacklist_locker),
+    m_exclusive(exclusive), m_blacklist_locker(blacklist_locker),
     m_blacklist_expire_seconds(blacklist_expire_seconds),
     m_force_break_lock(force_break_lock), m_on_finish(on_finish) {
 }
@@ -112,6 +113,43 @@ void BreakRequest<I>::handle_get_watchers(int r) {
     return;
   }
 
+  send_get_locker();
+}
+
+template <typename I>
+void BreakRequest<I>::send_get_locker() {
+  ldout(m_cct, 10) << dendl;
+
+  using klass = BreakRequest<I>;
+  Context *ctx = create_context_callback<klass, &klass::handle_get_locker>(
+    this);
+  auto req = GetLockerRequest<I>::create(m_ioctx, m_oid, m_exclusive,
+                                         &m_refreshed_locker, ctx);
+  req->send();
+}
+
+template <typename I>
+void BreakRequest<I>::handle_get_locker(int r) {
+  ldout(m_cct, 10) << "r=" << r << dendl;
+
+  if (r == -ENOENT) {
+    ldout(m_cct, 5) << "no lock owner" << dendl;
+    finish(0);
+    return;
+  } else if (r < 0 && r != -EBUSY) {
+    lderr(m_cct) << "failed to retrieve lockers: " << cpp_strerror(r) << dendl;
+    finish(r);
+    return;
+  } else if (r < 0) {
+    m_refreshed_locker = {};
+  }
+
+  if (m_refreshed_locker != m_locker || m_refreshed_locker == Locker{}) {
+    ldout(m_cct, 5) << "no longer lock owner" << dendl;
+    finish(-EAGAIN);
+    return;
+  }
+
   send_blacklist();
 }
 
index 045f629de291e71d1e31a623efb0f80e3bf24b48..6f4f4acab0454492ad707612513ccc35400b194b 100644 (file)
@@ -30,12 +30,12 @@ class BreakRequest {
 public:
   static BreakRequest* create(librados::IoCtx& ioctx, ContextWQ *work_queue,
                               const std::string& oid, const Locker &locker,
-                              bool blacklist_locker,
+                              bool exclusive, bool blacklist_locker,
                               uint32_t blacklist_expire_seconds,
                               bool force_break_lock, Context *on_finish) {
-    return new BreakRequest(ioctx, work_queue, oid, locker, blacklist_locker,
-                            blacklist_expire_seconds, force_break_lock,
-                            on_finish);
+    return new BreakRequest(ioctx, work_queue, oid, locker, exclusive,
+                            blacklist_locker, blacklist_expire_seconds,
+                            force_break_lock, on_finish);
   }
 
   void send();
@@ -50,6 +50,9 @@ private:
    * GET_WATCHERS
    *    |
    *    v
+   * GET_LOCKER
+   *    |
+   *    v
    * BLACKLIST (skip if disabled)
    *    |
    *    v
@@ -66,6 +69,7 @@ private:
   ContextWQ *m_work_queue;
   std::string m_oid;
   Locker m_locker;
+  bool m_exclusive;
   bool m_blacklist_locker;
   uint32_t m_blacklist_expire_seconds;
   bool m_force_break_lock;
@@ -76,14 +80,20 @@ private:
   std::list<obj_watch_t> m_watchers;
   int m_watchers_ret_val;
 
+  Locker m_refreshed_locker;
+
   BreakRequest(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);
+               bool exclusive, bool blacklist_locker,
+               uint32_t blacklist_expire_seconds, bool force_break_lock,
+               Context *on_finish);
 
   void send_get_watchers();
   void handle_get_watchers(int r);
 
+  void send_get_locker();
+  void handle_get_locker(int r);
+
   void send_blacklist();
   void handle_blacklist(int r);
 
index 4860b0385cb9ece0cca80027287dfac80c597eef..174e97be49bf8e8a88c71d33ee3d9ffc1e6ef48a 100644 (file)
@@ -30,7 +30,7 @@ struct BreakRequest<librbd::MockImageCtx> {
   static BreakRequest *s_instance;
   static BreakRequest* create(librados::IoCtx& ioctx, ContextWQ *work_queue,
                               const std::string& oid, const Locker &locker,
-                              bool blacklist_locker,
+                              bool exclusive, bool blacklist_locker,
                               uint32_t blacklist_expire_seconds,
                               bool force_break_lock, Context *on_finish) {
     CephContext *cct = reinterpret_cast<CephContext *>(ioctx.cct());
@@ -195,7 +195,6 @@ TEST_F(TestMockManagedLockAcquireRequest, LockBusy) {
                     0);
   expect_lock(mock_image_ctx, -EBUSY);
   expect_break_lock(mock_image_ctx, mock_break_request, 0);
-  expect_get_locker(mock_image_ctx, mock_get_locker_request, {}, 0);
   expect_lock(mock_image_ctx, -ENOENT);
 
   C_SaferCond ctx;
index c1dff856a0df318bcfa537cc64bf7e81f3142035..faeb090d505bcf9069bb0b6d3a9ccac127b4e10c 100644 (file)
@@ -8,6 +8,7 @@
 #include "test/librados_test_stub/MockTestMemRadosClient.h"
 #include "cls/lock/cls_lock_ops.h"
 #include "librbd/managed_lock/BreakRequest.h"
+#include "librbd/managed_lock/GetLockerRequest.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include <arpa/inet.h>
@@ -23,6 +24,33 @@ struct MockTestImageCtx : public librbd::MockImageCtx {
 };
 
 } // anonymous namespace
+
+namespace managed_lock {
+
+template <>
+struct GetLockerRequest<librbd::MockTestImageCtx> {
+  Locker *locker;
+  Context *on_finish = nullptr;
+  static GetLockerRequest *s_instance;
+  static GetLockerRequest* create(librados::IoCtx& ioctx,
+                                  const std::string& oid, bool exclusive,
+                                  Locker *locker, Context *on_finish) {
+    assert(s_instance != nullptr);
+    s_instance->locker = locker;
+    s_instance->on_finish = on_finish;
+    return s_instance;
+  }
+
+
+  GetLockerRequest() {
+    s_instance = this;
+  }
+  MOCK_METHOD0(send, void());
+};
+
+GetLockerRequest<librbd::MockTestImageCtx> *GetLockerRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
+
+} // namespace managed_lock
 } // namespace librbd
 
 // template definitions
@@ -34,6 +62,7 @@ namespace managed_lock {
 using ::testing::_;
 using ::testing::DoAll;
 using ::testing::InSequence;
+using ::testing::Invoke;
 using ::testing::Return;
 using ::testing::SetArgPointee;
 using ::testing::StrEq;
@@ -42,6 +71,7 @@ using ::testing::WithArg;
 class TestMockManagedLockBreakRequest : public TestMockFixture {
 public:
   typedef BreakRequest<MockTestImageCtx> MockBreakRequest;
+  typedef GetLockerRequest<MockTestImageCtx> MockGetLockerRequest;
 
   void expect_list_watchers(MockTestImageCtx &mock_image_ctx, int r,
                             const std::string &address, uint64_t watch_handle) {
@@ -61,6 +91,18 @@ public:
     }
   }
 
+  void expect_get_locker(MockImageCtx &mock_image_ctx,
+                         MockGetLockerRequest &mock_get_locker_request,
+                         const Locker &locker, int r) {
+    EXPECT_CALL(mock_get_locker_request, send())
+      .WillOnce(Invoke([&mock_image_ctx, &mock_get_locker_request, locker, r]() {
+          *mock_get_locker_request.locker = locker;
+          mock_image_ctx.image_ctx->op_work_queue->queue(
+            mock_get_locker_request.on_finish, r);
+        }));
+  }
+
+
   void expect_blacklist_add(MockTestImageCtx &mock_image_ctx, int r) {
     EXPECT_CALL(*get_mock_io_ctx(mock_image_ctx.md_ctx).get_mock_rados_client(),
                 blacklist_add(_, _))
@@ -90,6 +132,12 @@ TEST_F(TestMockManagedLockBreakRequest, DeadLockOwner) {
 
   InSequence seq;
   expect_list_watchers(mock_image_ctx, 0, "dead client", 123);
+
+  MockGetLockerRequest mock_get_locker_request;
+  expect_get_locker(mock_image_ctx, mock_get_locker_request,
+                    {entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123},
+                    0);
+
   expect_blacklist_add(mock_image_ctx, 0);
   expect_break_lock(mock_image_ctx, 0);
 
@@ -97,7 +145,7 @@ TEST_F(TestMockManagedLockBreakRequest, DeadLockOwner) {
   Locker locker{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
   MockBreakRequest *req = MockBreakRequest::create(
       mock_image_ctx.md_ctx, ictx->op_work_queue, mock_image_ctx.header_oid,
-      locker, true, 0, false, &ctx);
+      locker, true, true, 0, false, &ctx);
   req->send();
   ASSERT_EQ(0, ctx.wait());
 }
@@ -113,6 +161,12 @@ TEST_F(TestMockManagedLockBreakRequest, ForceBreak) {
 
   InSequence seq;
   expect_list_watchers(mock_image_ctx, 0, "1.2.3.4", 123);
+
+  MockGetLockerRequest mock_get_locker_request;
+  expect_get_locker(mock_image_ctx, mock_get_locker_request,
+                    {entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123},
+                    0);
+
   expect_blacklist_add(mock_image_ctx, 0);
   expect_break_lock(mock_image_ctx, 0);
 
@@ -120,7 +174,7 @@ TEST_F(TestMockManagedLockBreakRequest, ForceBreak) {
   Locker locker{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
   MockBreakRequest *req = MockBreakRequest::create(
       mock_image_ctx.md_ctx, ictx->op_work_queue, mock_image_ctx.header_oid,
-      locker, true, 0, true, &ctx);
+      locker, true, true, 0, true, &ctx);
   req->send();
   ASSERT_EQ(0, ctx.wait());
 }
@@ -141,7 +195,7 @@ TEST_F(TestMockManagedLockBreakRequest, GetWatchersError) {
   Locker locker{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
   MockBreakRequest *req = MockBreakRequest::create(
       mock_image_ctx.md_ctx, ictx->op_work_queue, mock_image_ctx.header_oid,
-      locker, true, 0, false, &ctx);
+      locker, true, true, 0, false, &ctx);
   req->send();
   ASSERT_EQ(-EINVAL, ctx.wait());
 }
@@ -162,11 +216,113 @@ TEST_F(TestMockManagedLockBreakRequest, GetWatchersAlive) {
   Locker locker{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
   MockBreakRequest *req = MockBreakRequest::create(
       mock_image_ctx.md_ctx, ictx->op_work_queue, mock_image_ctx.header_oid,
-      locker, true, 0, false, &ctx);
+      locker, true, true, 0, false, &ctx);
+  req->send();
+  ASSERT_EQ(-EAGAIN, ctx.wait());
+}
+
+TEST_F(TestMockManagedLockBreakRequest, GetLockerUpdated) {
+  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
+
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+  MockTestImageCtx mock_image_ctx(*ictx);
+  expect_op_work_queue(mock_image_ctx);
+
+  InSequence seq;
+  expect_list_watchers(mock_image_ctx, 0, "dead client", 123);
+
+  MockGetLockerRequest mock_get_locker_request;
+  expect_get_locker(mock_image_ctx, mock_get_locker_request,
+                    {entity_name_t::CLIENT(2), "auto 123", "1.2.3.4:0/0", 123},
+                    0);
+
+  C_SaferCond ctx;
+  Locker locker{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
+  MockBreakRequest *req = MockBreakRequest::create(
+      mock_image_ctx.md_ctx, ictx->op_work_queue, mock_image_ctx.header_oid,
+      locker, true, false, 0, false, &ctx);
+  req->send();
+  ASSERT_EQ(-EAGAIN, ctx.wait());
+}
+
+TEST_F(TestMockManagedLockBreakRequest, GetLockerBusy) {
+  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
+
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+  MockTestImageCtx mock_image_ctx(*ictx);
+  expect_op_work_queue(mock_image_ctx);
+
+  InSequence seq;
+  expect_list_watchers(mock_image_ctx, 0, "dead client", 123);
+
+  MockGetLockerRequest mock_get_locker_request;
+  expect_get_locker(mock_image_ctx, mock_get_locker_request,
+                    {entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123},
+                    -EBUSY);
+
+  C_SaferCond ctx;
+  Locker locker{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
+  MockBreakRequest *req = MockBreakRequest::create(
+      mock_image_ctx.md_ctx, ictx->op_work_queue, mock_image_ctx.header_oid,
+      locker, true, false, 0, false, &ctx);
   req->send();
   ASSERT_EQ(-EAGAIN, ctx.wait());
 }
 
+TEST_F(TestMockManagedLockBreakRequest, GetLockerMissing) {
+  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
+
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+  MockTestImageCtx mock_image_ctx(*ictx);
+  expect_op_work_queue(mock_image_ctx);
+
+  InSequence seq;
+  expect_list_watchers(mock_image_ctx, 0, "dead client", 123);
+
+  MockGetLockerRequest mock_get_locker_request;
+  expect_get_locker(mock_image_ctx, mock_get_locker_request,
+                    {entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123},
+                    -ENOENT);
+
+  C_SaferCond ctx;
+  Locker locker{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
+  MockBreakRequest *req = MockBreakRequest::create(
+      mock_image_ctx.md_ctx, ictx->op_work_queue, mock_image_ctx.header_oid,
+      locker, true, false, 0, false, &ctx);
+  req->send();
+  ASSERT_EQ(0, ctx.wait());
+}
+
+TEST_F(TestMockManagedLockBreakRequest, GetLockerError) {
+  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
+
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+  MockTestImageCtx mock_image_ctx(*ictx);
+  expect_op_work_queue(mock_image_ctx);
+
+  InSequence seq;
+  expect_list_watchers(mock_image_ctx, 0, "dead client", 123);
+
+  MockGetLockerRequest mock_get_locker_request;
+  expect_get_locker(mock_image_ctx, mock_get_locker_request, {}, -EINVAL);
+
+  C_SaferCond ctx;
+  Locker locker{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
+  MockBreakRequest *req = MockBreakRequest::create(
+      mock_image_ctx.md_ctx, ictx->op_work_queue, mock_image_ctx.header_oid,
+      locker, true, false, 0, false, &ctx);
+  req->send();
+  ASSERT_EQ(-EINVAL, ctx.wait());
+}
+
 TEST_F(TestMockManagedLockBreakRequest, BlacklistDisabled) {
   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
 
@@ -178,13 +334,19 @@ TEST_F(TestMockManagedLockBreakRequest, BlacklistDisabled) {
 
   InSequence seq;
   expect_list_watchers(mock_image_ctx, 0, "dead client", 123);
+
+  MockGetLockerRequest mock_get_locker_request;
+  expect_get_locker(mock_image_ctx, mock_get_locker_request,
+                    {entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123},
+                    0);
+
   expect_break_lock(mock_image_ctx, 0);
 
   C_SaferCond ctx;
   Locker locker{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
   MockBreakRequest *req = MockBreakRequest::create(
       mock_image_ctx.md_ctx, ictx->op_work_queue, mock_image_ctx.header_oid,
-      locker, false, 0, false, &ctx);
+      locker, true, false, 0, false, &ctx);
   req->send();
   ASSERT_EQ(0, ctx.wait());
 }
@@ -200,13 +362,19 @@ TEST_F(TestMockManagedLockBreakRequest, BlacklistSelf) {
 
   InSequence seq;
   expect_list_watchers(mock_image_ctx, 0, "dead client", 456);
+
+  MockGetLockerRequest mock_get_locker_request;
+  expect_get_locker(mock_image_ctx, mock_get_locker_request,
+                    {entity_name_t::CLIENT(456), "auto 123", "1.2.3.4:0/0",
+                     123}, 0);
+
   expect_get_instance_id(mock_image_ctx, 456);
 
   C_SaferCond ctx;
   Locker locker{entity_name_t::CLIENT(456), "auto 123", "1.2.3.4:0/0", 123};
   MockBreakRequest *req = MockBreakRequest::create(
       mock_image_ctx.md_ctx, ictx->op_work_queue, mock_image_ctx.header_oid,
-      locker, true, 0, false, &ctx);
+      locker, true, true, 0, false, &ctx);
   req->send();
   ASSERT_EQ(-EINVAL, ctx.wait());
 }
@@ -222,13 +390,19 @@ TEST_F(TestMockManagedLockBreakRequest, BlacklistError) {
 
   InSequence seq;
   expect_list_watchers(mock_image_ctx, 0, "dead client", 123);
+
+  MockGetLockerRequest mock_get_locker_request;
+  expect_get_locker(mock_image_ctx, mock_get_locker_request,
+                    {entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123},
+                    0);
+
   expect_blacklist_add(mock_image_ctx, -EINVAL);
 
   C_SaferCond ctx;
   Locker locker{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
   MockBreakRequest *req = MockBreakRequest::create(
       mock_image_ctx.md_ctx, ictx->op_work_queue, mock_image_ctx.header_oid,
-      locker, true, 0, false, &ctx);
+      locker, true, true, 0, false, &ctx);
   req->send();
   ASSERT_EQ(-EINVAL, ctx.wait());
 }
@@ -244,6 +418,12 @@ TEST_F(TestMockManagedLockBreakRequest, BreakLockMissing) {
 
   InSequence seq;
   expect_list_watchers(mock_image_ctx, 0, "dead client", 123);
+
+  MockGetLockerRequest mock_get_locker_request;
+  expect_get_locker(mock_image_ctx, mock_get_locker_request,
+                    {entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123},
+                    0);
+
   expect_blacklist_add(mock_image_ctx, 0);
   expect_break_lock(mock_image_ctx, -ENOENT);
 
@@ -251,7 +431,7 @@ TEST_F(TestMockManagedLockBreakRequest, BreakLockMissing) {
   Locker locker{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
   MockBreakRequest *req = MockBreakRequest::create(
       mock_image_ctx.md_ctx, ictx->op_work_queue, mock_image_ctx.header_oid,
-      locker, true, 0, false, &ctx);
+      locker, true, true, 0, false, &ctx);
   req->send();
   ASSERT_EQ(0, ctx.wait());
 }
@@ -267,6 +447,12 @@ TEST_F(TestMockManagedLockBreakRequest, BreakLockError) {
 
   InSequence seq;
   expect_list_watchers(mock_image_ctx, 0, "dead client", 123);
+
+  MockGetLockerRequest mock_get_locker_request;
+  expect_get_locker(mock_image_ctx, mock_get_locker_request,
+                    {entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123},
+                    0);
+
   expect_blacklist_add(mock_image_ctx, 0);
   expect_break_lock(mock_image_ctx, -EINVAL);
 
@@ -274,7 +460,7 @@ TEST_F(TestMockManagedLockBreakRequest, BreakLockError) {
   Locker locker{entity_name_t::CLIENT(1), "auto 123", "1.2.3.4:0/0", 123};
   MockBreakRequest *req = MockBreakRequest::create(
       mock_image_ctx.md_ctx, ictx->op_work_queue, mock_image_ctx.header_oid,
-      locker, true, 0, false, &ctx);
+      locker, true, true, 0, false, &ctx);
   req->send();
   ASSERT_EQ(-EINVAL, ctx.wait());
 }
index 7e79aa241251b311a8c7bc37fa056eaa886e8e2a..a808523fc204ba3f49d619598a134d60374c1c9f 100644 (file)
@@ -106,7 +106,7 @@ template <>
 struct BreakRequest<MockManagedLockImageCtx> {
   static BreakRequest* create(librados::IoCtx& ioctx, ContextWQ *work_queue,
                               const std::string& oid, const Locker &locker,
-                              bool blacklist_locker,
+                              bool exclusive, bool blacklist_locker,
                               uint32_t blacklist_expire_seconds,
                               bool force_break_lock, Context *on_finish) {
     assert(0 == "unexpected call");