]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: prevent self-blacklisting during break lock 13110/head
authorJason Dillaman <dillaman@redhat.com>
Wed, 25 Jan 2017 19:45:56 +0000 (14:45 -0500)
committerJason Dillaman <dillaman@redhat.com>
Wed, 25 Jan 2017 19:45:56 +0000 (14:45 -0500)
Fixes: http://tracker.ceph.com/issues/18666
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/librbd/managed_lock/BreakRequest.cc
src/test/librados_test_stub/MockTestMemIoCtxImpl.h
src/test/librbd/managed_lock/test_mock_BreakRequest.cc

index d7f65a889306912a0908646639f25c1837fb8d9f..bf66d932c4b35ae83be65e48e80115c01d55172d 100644 (file)
@@ -119,7 +119,15 @@ void BreakRequest<I>::send_blacklist() {
     return;
   }
 
-  ldout(m_cct, 10) << dendl;
+  entity_name_t entity_name = entity_name_t::CLIENT(m_ioctx.get_instance_id());
+  ldout(m_cct, 10) << "local entity=" << entity_name << ", "
+                   << "locker entity=" << m_locker.entity << dendl;
+
+  if (m_locker.entity == entity_name) {
+    lderr(m_cct) << "attempting to self-blacklist" << dendl;
+    finish(-EINVAL);
+    return;
+  }
 
   // TODO: need async version of RadosClient::blacklist_add
   using klass = BreakRequest<I>;
index 3547e453f2119aaca6579a5aba3e22573e1b6882..7d3bca3dac671e87f69830d3ff003fe5c5d0b5a8 100644 (file)
@@ -60,6 +60,11 @@ public:
                                   snapc);
   }
 
+  MOCK_CONST_METHOD0(get_instance_id, uint64_t());
+  uint64_t do_get_instance_id() const {
+    return TestMemIoCtxImpl::get_instance_id();
+  }
+
   MOCK_METHOD2(list_snaps, int(const std::string& o, snap_set_t *out_snaps));
   int do_list_snaps(const std::string& o, snap_set_t *out_snaps) {
     return TestMemIoCtxImpl::list_snaps(o, out_snaps);
@@ -148,6 +153,7 @@ public:
     ON_CALL(*this, aio_watch(_, _, _, _)).WillByDefault(Invoke(this, &MockTestMemIoCtxImpl::do_aio_watch));
     ON_CALL(*this, aio_unwatch(_, _)).WillByDefault(Invoke(this, &MockTestMemIoCtxImpl::do_aio_unwatch));
     ON_CALL(*this, exec(_, _, _, _, _, _, _)).WillByDefault(Invoke(this, &MockTestMemIoCtxImpl::do_exec));
+    ON_CALL(*this, get_instance_id()).WillByDefault(Invoke(this, &MockTestMemIoCtxImpl::do_get_instance_id));
     ON_CALL(*this, list_snaps(_, _)).WillByDefault(Invoke(this, &MockTestMemIoCtxImpl::do_list_snaps));
     ON_CALL(*this, list_watchers(_, _)).WillByDefault(Invoke(this, &MockTestMemIoCtxImpl::do_list_watchers));
     ON_CALL(*this, notify(_, _, _, _)).WillByDefault(Invoke(this, &MockTestMemIoCtxImpl::do_notify));
index 947ea1f731df58ca42c46b847c65d72546cc6f93..3ebc233024fdb45e9f28f6ff74900a1cc6530d55 100644 (file)
@@ -71,6 +71,11 @@ public:
                 exec(mock_image_ctx.header_oid, _, StrEq("lock"), StrEq("break_lock"), _, _, _))
                   .WillOnce(Return(r));
   }
+
+  void expect_get_instance_id(MockTestImageCtx &mock_image_ctx, uint64_t id) {
+    EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx), get_instance_id())
+      .WillOnce(Return(id));
+  }
 };
 
 TEST_F(TestMockManagedLockBreakRequest, DeadLockOwner) {
@@ -183,6 +188,28 @@ TEST_F(TestMockManagedLockBreakRequest, BlacklistDisabled) {
   ASSERT_EQ(0, ctx.wait());
 }
 
+TEST_F(TestMockManagedLockBreakRequest, BlacklistSelf) {
+  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", 456);
+  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);
+  req->send();
+  ASSERT_EQ(-EINVAL, ctx.wait());
+}
+
 TEST_F(TestMockManagedLockBreakRequest, BlacklistError) {
   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);