From: Jason Dillaman Date: Wed, 25 Jan 2017 19:45:56 +0000 (-0500) Subject: librbd: prevent self-blacklisting during break lock X-Git-Tag: v12.0.0~82^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=refs%2Fpull%2F13110%2Fhead;p=ceph.git librbd: prevent self-blacklisting during break lock Fixes: http://tracker.ceph.com/issues/18666 Signed-off-by: Jason Dillaman --- diff --git a/src/librbd/managed_lock/BreakRequest.cc b/src/librbd/managed_lock/BreakRequest.cc index d7f65a889306..bf66d932c4b3 100644 --- a/src/librbd/managed_lock/BreakRequest.cc +++ b/src/librbd/managed_lock/BreakRequest.cc @@ -119,7 +119,15 @@ void BreakRequest::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; diff --git a/src/test/librados_test_stub/MockTestMemIoCtxImpl.h b/src/test/librados_test_stub/MockTestMemIoCtxImpl.h index 3547e453f211..7d3bca3dac67 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); @@ -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)); diff --git a/src/test/librbd/managed_lock/test_mock_BreakRequest.cc b/src/test/librbd/managed_lock/test_mock_BreakRequest.cc index 947ea1f731df..3ebc233024fd 100644 --- a/src/test/librbd/managed_lock/test_mock_BreakRequest.cc +++ b/src/test/librbd/managed_lock/test_mock_BreakRequest.cc @@ -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);