]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: prevent self-blacklisting during break lock 17412/head
authorJason Dillaman <dillaman@redhat.com>
Fri, 1 Sep 2017 01:30:47 +0000 (21:30 -0400)
committerJason Dillaman <dillaman@redhat.com>
Fri, 1 Sep 2017 01:30:47 +0000 (21:30 -0400)
(derived from commit 5c590acaec4dd66a9a8c3aa0ec8ab904dd350216)

Fixes: http://tracker.ceph.com/issues/18704
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/librbd/exclusive_lock/BreakRequest.cc
src/test/librados_test_stub/MockTestMemIoCtxImpl.h
src/test/librbd/exclusive_lock/test_mock_BreakRequest.cc

index 8b889e704da847bad78cf88e308bdb46bf352abe..c4315200ebdfac467961b4999d048a0412384751 100644 (file)
@@ -112,7 +112,16 @@ void BreakRequest<I>::send_blacklist() {
   }
 
   CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << dendl;
+  entity_name_t entity_name = entity_name_t::CLIENT(
+    m_image_ctx.md_ctx.get_instance_id());
+  ldout(cct, 10) << "local entity=" << entity_name << ", "
+                 << "locker entity=" << m_locker.entity << dendl;
+
+  if (m_locker.entity == entity_name) {
+    lderr(cct) << "attempting to self-blacklist" << dendl;
+    finish(-EINVAL);
+    return;
+  }
 
   // TODO: need async version of RadosClient::blacklist_add
   using klass = BreakRequest<I>;
index adfe6f8d0a0e5212e8f6307e2517efef1cb9c32b..99c2ee2c8fba5cfa877e39f38650e5fa5ac1b237 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);
@@ -143,6 +148,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 27bb8e12725527591c8791b31d423f8c8c9cf952..802a4e97fcf312f757fc630e46895fb00deb656b 100644 (file)
@@ -72,6 +72,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(TestMockExclusiveLockBreakRequest, DeadLockOwner) {
@@ -179,6 +184,27 @@ TEST_F(TestMockExclusiveLockBreakRequest, BlacklistDisabled) {
   ASSERT_EQ(0, ctx.wait());
 }
 
+TEST_F(TestMockExclusiveLockBreakRequest, 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, locker,
+                                                   true, false, &ctx);
+  req->send();
+  ASSERT_EQ(-EINVAL, ctx.wait());
+}
+
 TEST_F(TestMockExclusiveLockBreakRequest, BlacklistError) {
   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);