#include "cls/rbd/cls_rbd_types.h"
#include "librbd/ExclusiveLock.h"
#include "librbd/Utils.h"
+#include "librbd/exclusive_lock/StandardPolicy.h"
#include "librbd/image/ListWatchersRequest.h"
#include "librbd/journal/DisabledPolicy.h"
#include "librbd/operation/SnapshotRemoveRequest.h"
template <typename I>
void PreRemoveRequest<I>::acquire_exclusive_lock() {
- std::shared_lock owner_lock{m_image_ctx->owner_lock};
+ // lock for write for set_exclusive_lock_policy()
+ std::unique_lock owner_locker{m_image_ctx->owner_lock};
if (m_image_ctx->exclusive_lock == nullptr) {
+ owner_locker.unlock();
validate_image_removal();
return;
}
auto cct = m_image_ctx->cct;
ldout(cct, 5) << dendl;
+ // refuse to release exclusive lock when (in the midst of) removing
+ // the image
+ m_image_ctx->set_exclusive_lock_policy(
+ new exclusive_lock::StandardPolicy<I>(m_image_ctx));
+
// do not attempt to open the journal when removing the image in case
// it's corrupt
if (m_image_ctx->test_features(RBD_FEATURE_JOURNALING)) {
} // namespace librbd
// template definitions
+#include "librbd/exclusive_lock/StandardPolicy.cc"
#include "librbd/image/PreRemoveRequest.cc"
ACTION_P(TestFeatures, image_ctx) {
.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(_))
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);
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_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);
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_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);
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);
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);
{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);