Merge pull request #13110 from dillaman/wip-18666

librbd: prevent self-blacklisting during break lock

Reviewed-by: Mykola Golub <mgolub@mirantis.com>
This commit is contained in:
Mykola Golub 2017-01-26 23:44:01 +02:00 committed by GitHub
commit c720e348d4
3 changed files with 42 additions and 1 deletions

View 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>;

View 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));

View 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);