From: Jason Dillaman Date: Fri, 1 Sep 2017 01:30:47 +0000 (-0400) Subject: librbd: prevent self-blacklisting during break lock X-Git-Tag: v10.2.10~37^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=f9acf56dce26bb031cddb6676b2834b6bd426ae2;p=ceph.git librbd: prevent self-blacklisting during break lock (derived from commit 5c590acaec4dd66a9a8c3aa0ec8ab904dd350216) Fixes: http://tracker.ceph.com/issues/18704 Signed-off-by: Jason Dillaman --- diff --git a/src/librbd/exclusive_lock/BreakRequest.cc b/src/librbd/exclusive_lock/BreakRequest.cc index 8b889e704da8..c4315200ebdf 100644 --- a/src/librbd/exclusive_lock/BreakRequest.cc +++ b/src/librbd/exclusive_lock/BreakRequest.cc @@ -112,7 +112,16 @@ void BreakRequest::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; diff --git a/src/test/librados_test_stub/MockTestMemIoCtxImpl.h b/src/test/librados_test_stub/MockTestMemIoCtxImpl.h index adfe6f8d0a0e..99c2ee2c8fba 100644 --- a/src/test/librados_test_stub/MockTestMemIoCtxImpl.h +++ b/src/test/librados_test_stub/MockTestMemIoCtxImpl.h @@ -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)); diff --git a/src/test/librbd/exclusive_lock/test_mock_BreakRequest.cc b/src/test/librbd/exclusive_lock/test_mock_BreakRequest.cc index 27bb8e127255..802a4e97fcf3 100644 --- a/src/test/librbd/exclusive_lock/test_mock_BreakRequest.cc +++ b/src/test/librbd/exclusive_lock/test_mock_BreakRequest.cc @@ -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);