m_image_ctx->set_journal_policy(new journal::DisabledPolicy());
}
- if (m_force) {
- auto ctx = create_context_callback<
- PreRemoveRequest<I>,
- &PreRemoveRequest<I>::handle_exclusive_lock_force>(this);
-
- m_exclusive_lock = m_image_ctx->exclusive_lock;
- m_exclusive_lock->shut_down(ctx);
- } else {
- auto ctx = create_context_callback<
- PreRemoveRequest<I>, &PreRemoveRequest<I>::handle_exclusive_lock>(this);
-
- m_image_ctx->exclusive_lock->try_acquire_lock(ctx);
- }
+ auto ctx = create_context_callback<
+ PreRemoveRequest<I>, &PreRemoveRequest<I>::handle_exclusive_lock>(this);
+
+ m_image_ctx->exclusive_lock->try_acquire_lock(ctx);
}
template <typename I>
ldout(cct, 5) << "r=" << r << dendl;
if (r < 0 || !m_image_ctx->exclusive_lock->is_lock_owner()) {
- lderr(cct) << "cannot obtain exclusive lock - not removing" << dendl;
- finish(-EBUSY);
+ if (!m_force) {
+ lderr(cct) << "cannot obtain exclusive lock - not removing" << dendl;
+ finish(-EBUSY);
+ } else {
+ ldout(cct, 5) << "cannot obtain exclusive lock - "
+ << "proceeding due to force flag set" << dendl;
+ shut_down_exclusive_lock();
+ }
return;
}
}
template <typename I>
-void PreRemoveRequest<I>::handle_exclusive_lock_force(int r) {
+void PreRemoveRequest<I>::shut_down_exclusive_lock() {
+ std::shared_lock owner_lock{m_image_ctx->owner_lock};
+ if (m_image_ctx->exclusive_lock == nullptr) {
+ validate_image_removal();
+ return;
+ }
+
+ auto cct = m_image_ctx->cct;
+ ldout(cct, 5) << dendl;
+
+ auto ctx = create_context_callback<
+ PreRemoveRequest<I>,
+ &PreRemoveRequest<I>::handle_shut_down_exclusive_lock>(this);
+
+ m_exclusive_lock = m_image_ctx->exclusive_lock;
+ m_exclusive_lock->shut_down(ctx);
+}
+
+template <typename I>
+void PreRemoveRequest<I>::handle_shut_down_exclusive_lock(int r) {
auto cct = m_image_ctx->cct;
ldout(cct, 5) << "r=" << r << dendl;
};
TEST_F(TestMockImagePreRemoveRequest, Success) {
- MockExclusiveLock *mock_exclusive_lock = new MockExclusiveLock();
+ MockExclusiveLock mock_exclusive_lock;
if (m_test_imctx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
- m_mock_imctx->exclusive_lock = mock_exclusive_lock;
+ m_mock_imctx->exclusive_lock = &mock_exclusive_lock;
}
expect_op_work_queue(*m_mock_imctx);
InSequence seq;
expect_set_journal_policy(*m_mock_imctx);
- expect_shut_down_exclusive_lock(*m_mock_imctx, *mock_exclusive_lock, 0);
+ expect_try_acquire_exclusive_lock(*m_mock_imctx, mock_exclusive_lock, 0);
+ expect_is_exclusive_lock_owner(*m_mock_imctx, mock_exclusive_lock, true);
MockListWatchersRequest mock_list_watchers_request;
expect_list_image_watchers(*m_mock_imctx, mock_list_watchers_request, 0);
expect_get_group(*m_mock_imctx, 0);
C_SaferCond ctx;
- auto req = MockPreRemoveRequest::create(m_mock_imctx, true, &ctx);
+ auto req = MockPreRemoveRequest::create(m_mock_imctx, false, &ctx);
req->send();
ASSERT_EQ(0, ctx.wait());
ASSERT_EQ(-EROFS, ctx.wait());
}
-TEST_F(TestMockImagePreRemoveRequest, ExclusiveLockShutDownFailed) {
+TEST_F(TestMockImagePreRemoveRequest, ExclusiveLockTryAcquireFailed) {
REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
- MockExclusiveLock *mock_exclusive_lock = new MockExclusiveLock();
- if (m_test_imctx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
- m_mock_imctx->exclusive_lock = mock_exclusive_lock;
- }
+ MockExclusiveLock mock_exclusive_lock;
+ m_mock_imctx->exclusive_lock = &mock_exclusive_lock;
expect_op_work_queue(*m_mock_imctx);
expect_test_features(*m_mock_imctx);
InSequence seq;
expect_set_journal_policy(*m_mock_imctx);
- expect_shut_down_exclusive_lock(*m_mock_imctx, *mock_exclusive_lock, -EINVAL);
+ expect_try_acquire_exclusive_lock(*m_mock_imctx, mock_exclusive_lock,
+ -EINVAL);
C_SaferCond ctx;
- auto req = MockPreRemoveRequest::create(m_mock_imctx, true, &ctx);
+ auto req = MockPreRemoveRequest::create(m_mock_imctx, false, &ctx);
req->send();
- ASSERT_EQ(-EINVAL, ctx.wait());
+ ASSERT_EQ(-EBUSY, ctx.wait());
}
-TEST_F(TestMockImagePreRemoveRequest, ExclusiveLockTryAcquireFailed) {
+TEST_F(TestMockImagePreRemoveRequest, ExclusiveLockTryAcquireNotLockOwner) {
REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
MockExclusiveLock mock_exclusive_lock;
- if (m_test_imctx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
- m_mock_imctx->exclusive_lock = &mock_exclusive_lock;
- }
+ m_mock_imctx->exclusive_lock = &mock_exclusive_lock;
expect_op_work_queue(*m_mock_imctx);
expect_test_features(*m_mock_imctx);
InSequence seq;
expect_set_journal_policy(*m_mock_imctx);
- expect_try_acquire_exclusive_lock(*m_mock_imctx, mock_exclusive_lock,
- -EINVAL);
+ expect_try_acquire_exclusive_lock(*m_mock_imctx, mock_exclusive_lock, 0);
+ expect_is_exclusive_lock_owner(*m_mock_imctx, mock_exclusive_lock, false);
C_SaferCond ctx;
auto req = MockPreRemoveRequest::create(m_mock_imctx, false, &ctx);
ASSERT_EQ(-EBUSY, ctx.wait());
}
+TEST_F(TestMockImagePreRemoveRequest, Force) {
+ REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
+
+ MockExclusiveLock *mock_exclusive_lock = new MockExclusiveLock();
+ m_mock_imctx->exclusive_lock = mock_exclusive_lock;
+
+ expect_op_work_queue(*m_mock_imctx);
+ expect_test_features(*m_mock_imctx);
+
+ InSequence seq;
+ expect_set_journal_policy(*m_mock_imctx);
+ expect_try_acquire_exclusive_lock(*m_mock_imctx, *mock_exclusive_lock,
+ -EINVAL);
+ expect_shut_down_exclusive_lock(*m_mock_imctx, *mock_exclusive_lock, 0);
+
+ MockListWatchersRequest mock_list_watchers_request;
+ expect_list_image_watchers(*m_mock_imctx, mock_list_watchers_request, 0);
+
+ expect_get_group(*m_mock_imctx, 0);
+
+ C_SaferCond ctx;
+ auto req = MockPreRemoveRequest::create(m_mock_imctx, true, &ctx);
+ req->send();
+
+ ASSERT_EQ(0, ctx.wait());
+}
+
+TEST_F(TestMockImagePreRemoveRequest, ExclusiveLockShutDownFailed) {
+ REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
+
+ MockExclusiveLock *mock_exclusive_lock = new MockExclusiveLock();
+ m_mock_imctx->exclusive_lock = mock_exclusive_lock;
+
+ expect_op_work_queue(*m_mock_imctx);
+ expect_test_features(*m_mock_imctx);
+
+ InSequence seq;
+ expect_set_journal_policy(*m_mock_imctx);
+ expect_try_acquire_exclusive_lock(*m_mock_imctx, *mock_exclusive_lock, -EINVAL);
+ expect_shut_down_exclusive_lock(*m_mock_imctx, *mock_exclusive_lock, -EINVAL);
+
+ C_SaferCond ctx;
+ auto req = MockPreRemoveRequest::create(m_mock_imctx, true, &ctx);
+ req->send();
+
+ ASSERT_EQ(-EINVAL, ctx.wait());
+}
+
TEST_F(TestMockImagePreRemoveRequest, Migration) {
m_mock_imctx->features |= RBD_FEATURE_MIGRATING;