diff options
author | Ilya Dryomov <idryomov@gmail.com> | 2021-02-07 13:46:15 +0100 |
---|---|---|
committer | Ilya Dryomov <idryomov@gmail.com> | 2021-02-09 14:29:35 +0100 |
commit | 707907ea3f6ff39968666af4ba718ceef8cd8953 (patch) | |
tree | afeda05d712a5576488b3c20c4c7469a78f72e02 /src/test/librbd/image | |
parent | librbd: templatize exclusive_lock::StandardPolicy (diff) | |
download | ceph-707907ea3f6ff39968666af4ba718ceef8cd8953.tar.xz ceph-707907ea3f6ff39968666af4ba718ceef8cd8953.zip |
librbd: refuse to release exclusive lock when removing
Commit 25c2ffe145be ("librbd: acquire exclusive lock from peer when
removing") changed PreRemoveRequest to request exclusive lock from the
peer instead of giving up and proceeding without exclusive lock. This
caused one of the test cases that sometimes runs concurrent "rbd rm"
against the same image to fail intermittently, most often on assert
ceph_assert(image_ctx.exclusive_lock == nullptr ||
image_ctx.exclusive_lock->is_lock_owner());
because exclusive lock is now automatically transitioned to another
"rbd rm" on its request.
The root cause is older and probably goes back to when synchronous
librbd::remove() which held owner_lock across all operations including
trim_image() was converted to a set of state machines. Since then, any
peer that requests exclusive lock (instead of trying once and backing
off) is able to mess with image removal.
Install StandardPolicy to disable automatic exclusive lock transitions
during image removal.
Fixes: https://tracker.ceph.com/issues/49226
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Diffstat (limited to 'src/test/librbd/image')
-rw-r--r-- | src/test/librbd/image/test_mock_PreRemoveRequest.cc | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/src/test/librbd/image/test_mock_PreRemoveRequest.cc b/src/test/librbd/image/test_mock_PreRemoveRequest.cc index a451104f882..faae4f2017f 100644 --- a/src/test/librbd/image/test_mock_PreRemoveRequest.cc +++ b/src/test/librbd/image/test_mock_PreRemoveRequest.cc @@ -85,6 +85,7 @@ ListWatchersRequest<MockTestImageCtx> *ListWatchersRequest<MockTestImageCtx>::s_ } // namespace librbd // template definitions +#include "librbd/exclusive_lock/StandardPolicy.cc" #include "librbd/image/PreRemoveRequest.cc" ACTION_P(TestFeatures, image_ctx) { @@ -132,6 +133,16 @@ public: .WillRepeatedly(TestFeatures(&mock_image_ctx)); } + void expect_set_exclusive_lock_policy(MockTestImageCtx& mock_image_ctx) { + if (m_mock_imctx->exclusive_lock != nullptr) { + EXPECT_CALL(mock_image_ctx, set_exclusive_lock_policy(_)) + .WillOnce(Invoke([](exclusive_lock::Policy* policy) { + ASSERT_FALSE(policy->may_auto_request_lock()); + delete policy; + })); + } + } + void expect_set_journal_policy(MockTestImageCtx &mock_image_ctx) { if (m_test_imctx->test_features(RBD_FEATURE_JOURNALING)) { EXPECT_CALL(mock_image_ctx, set_journal_policy(_)) @@ -212,6 +223,7 @@ TEST_F(TestMockImagePreRemoveRequest, Success) { expect_test_features(*m_mock_imctx); InSequence seq; + expect_set_exclusive_lock_policy(*m_mock_imctx); expect_set_journal_policy(*m_mock_imctx); expect_acquire_exclusive_lock(*m_mock_imctx, mock_exclusive_lock, 0); expect_is_exclusive_lock_owner(*m_mock_imctx, mock_exclusive_lock, true); @@ -250,6 +262,7 @@ TEST_F(TestMockImagePreRemoveRequest, ExclusiveLockTryAcquireFailed) { expect_test_features(*m_mock_imctx); InSequence seq; + expect_set_exclusive_lock_policy(*m_mock_imctx); expect_set_journal_policy(*m_mock_imctx); expect_acquire_exclusive_lock(*m_mock_imctx, mock_exclusive_lock, -EINVAL); @@ -271,6 +284,7 @@ TEST_F(TestMockImagePreRemoveRequest, ExclusiveLockTryAcquireNotLockOwner) { expect_test_features(*m_mock_imctx); InSequence seq; + expect_set_exclusive_lock_policy(*m_mock_imctx); expect_set_journal_policy(*m_mock_imctx); expect_acquire_exclusive_lock(*m_mock_imctx, mock_exclusive_lock, 0); expect_is_exclusive_lock_owner(*m_mock_imctx, mock_exclusive_lock, false); @@ -292,6 +306,7 @@ TEST_F(TestMockImagePreRemoveRequest, Force) { expect_test_features(*m_mock_imctx); InSequence seq; + expect_set_exclusive_lock_policy(*m_mock_imctx); expect_set_journal_policy(*m_mock_imctx); expect_acquire_exclusive_lock(*m_mock_imctx, mock_exclusive_lock, -EINVAL); @@ -319,6 +334,7 @@ TEST_F(TestMockImagePreRemoveRequest, ExclusiveLockShutDownFailed) { expect_test_features(*m_mock_imctx); InSequence seq; + expect_set_exclusive_lock_policy(*m_mock_imctx); expect_set_journal_policy(*m_mock_imctx); expect_acquire_exclusive_lock(*m_mock_imctx, mock_exclusive_lock, -EINVAL); expect_shut_down_exclusive_lock(*m_mock_imctx, mock_exclusive_lock, -EINVAL); @@ -365,6 +381,7 @@ TEST_F(TestMockImagePreRemoveRequest, Watchers) { expect_test_features(*m_mock_imctx); InSequence seq; + expect_set_exclusive_lock_policy(*m_mock_imctx); expect_set_journal_policy(*m_mock_imctx); expect_acquire_exclusive_lock(*m_mock_imctx, mock_exclusive_lock, 0); expect_is_exclusive_lock_owner(*m_mock_imctx, mock_exclusive_lock, true); @@ -392,6 +409,7 @@ TEST_F(TestMockImagePreRemoveRequest, GroupError) { expect_test_features(*m_mock_imctx); InSequence seq; + expect_set_exclusive_lock_policy(*m_mock_imctx); expect_set_journal_policy(*m_mock_imctx); expect_acquire_exclusive_lock(*m_mock_imctx, mock_exclusive_lock, 0); expect_is_exclusive_lock_owner(*m_mock_imctx, mock_exclusive_lock, true); @@ -423,6 +441,7 @@ TEST_F(TestMockImagePreRemoveRequest, AutoDeleteSnapshots) { {123, {"snap1", {cls::rbd::TrashSnapshotNamespace{}}, {}, {}, {}, {}, {}}}}; InSequence seq; + expect_set_exclusive_lock_policy(*m_mock_imctx); expect_set_journal_policy(*m_mock_imctx); expect_acquire_exclusive_lock(*m_mock_imctx, mock_exclusive_lock, 0); expect_is_exclusive_lock_owner(*m_mock_imctx, mock_exclusive_lock, true); |