using ::testing::InSequence;
using ::testing::Invoke;
using ::testing::Return;
+using ::testing::ReturnNew;
using ::testing::WithArg;
using ::testing::InvokeWithoutArgs;
ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &m_local_image_ctx));
}
+ void expect_start_op(librbd::MockExclusiveLock &mock_exclusive_lock) {
+ EXPECT_CALL(mock_exclusive_lock, start_op()).WillOnce(
+ ReturnNew<FunctionContext>([](int) {}));
+ }
+
void expect_get_snap_id(librbd::MockTestImageCtx &mock_image_ctx) {
EXPECT_CALL(mock_image_ctx, get_snap_id(_, _))
.WillRepeatedly(Invoke([&mock_image_ctx](cls::rbd::SnapshotNamespace snap_namespace,
journal::MockJournaler mock_journaler;
MockObjectCopyRequest mock_object_copy_request;
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
expect_get_snap_id(mock_remote_image_ctx);
InSequence seq;
expect_get_object_count(mock_remote_image_ctx, 1);
expect_get_object_count(mock_remote_image_ctx, 0);
expect_update_client(mock_journaler, 0);
+ expect_start_op(mock_exclusive_lock);
expect_object_copy_send(mock_object_copy_request);
expect_update_client(mock_journaler, 0);
journal::MockJournaler mock_journaler;
MockObjectCopyRequest mock_object_copy_request;
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
expect_get_snap_id(mock_remote_image_ctx);
expect_get_object_count(mock_remote_image_ctx, object_count);
expect_get_object_count(mock_remote_image_ctx, 0);
+ EXPECT_CALL(mock_exclusive_lock, start_op())
+ .Times(object_count).WillRepeatedly(ReturnNew<FunctionContext>([](int) {}));
EXPECT_CALL(mock_object_copy_request, send()).Times(object_count);
boost::optional<uint64_t> expected_object_number(boost::none);
journal::MockJournaler mock_journaler;
MockObjectCopyRequest mock_object_copy_request;
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
expect_get_snap_id(mock_remote_image_ctx);
InSequence seq;
expect_get_object_count(mock_remote_image_ctx, 1);
expect_get_object_count(mock_remote_image_ctx, 1);
expect_update_client(mock_journaler, 0);
+ expect_start_op(mock_exclusive_lock);
expect_object_copy_send(mock_object_copy_request);
expect_update_client(mock_journaler, 0);
journal::MockJournaler mock_journaler;
MockObjectCopyRequest mock_object_copy_request;
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
expect_get_snap_id(mock_remote_image_ctx);
InSequence seq;
expect_get_object_count(mock_remote_image_ctx, 0);
expect_get_object_count(mock_remote_image_ctx, 0);
expect_update_client(mock_journaler, 0);
+ expect_start_op(mock_exclusive_lock);
expect_object_copy_send(mock_object_copy_request);
expect_update_client(mock_journaler, 0);
journal::MockJournaler mock_journaler;
MockObjectCopyRequest mock_object_copy_request;
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
expect_get_snap_id(mock_remote_image_ctx);
InSequence seq;
expect_get_object_count(mock_remote_image_ctx, 1);
expect_get_object_count(mock_remote_image_ctx, 2);
expect_update_client(mock_journaler, 0);
+ expect_start_op(mock_exclusive_lock);
expect_object_copy_send(mock_object_copy_request);
expect_update_client(mock_journaler, 0);
journal::MockJournaler mock_journaler;
MockObjectCopyRequest mock_object_copy_request;
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
expect_get_snap_id(mock_remote_image_ctx);
InSequence seq;
expect_get_object_count(mock_remote_image_ctx, 2);
expect_get_object_count(mock_remote_image_ctx, 2);
expect_update_client(mock_journaler, 0);
+ expect_start_op(mock_exclusive_lock);
expect_object_copy_send(mock_object_copy_request);
C_SaferCond ctx;
journal::MockJournaler mock_journaler;
MockObjectCopyRequest mock_object_copy_request;
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
expect_get_snap_id(mock_remote_image_ctx);
expect_get_object_count(mock_remote_image_ctx, 10);
expect_get_object_count(mock_remote_image_ctx, 0);
+ EXPECT_CALL(mock_exclusive_lock, start_op())
+ .Times(6).WillRepeatedly(ReturnNew<FunctionContext>([](int) {}));
EXPECT_CALL(mock_object_copy_request, send()).Times(6);
EXPECT_CALL(mock_journaler, update_client(_, _))
journal::MockJournaler mock_journaler;
MockObjectCopyRequest mock_object_copy_request;
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
C_SaferCond ctx;
MockImageCopyRequest *request = create_request(mock_remote_image_ctx,
mock_local_image_ctx,
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
journal::MockJournaler mock_journaler;
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
expect_get_snap_id(mock_remote_image_ctx);
C_SaferCond ctx;
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
journal::MockJournaler mock_journaler;
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
expect_get_snap_id(mock_remote_image_ctx);
C_SaferCond ctx;
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
journal::MockJournaler mock_journaler;
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
expect_get_snap_id(mock_remote_image_ctx);
C_SaferCond ctx;
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
journal::MockJournaler mock_journaler;
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
expect_get_snap_id(mock_remote_image_ctx);
C_SaferCond ctx;
using ::testing::Invoke;
using ::testing::InvokeWithoutArgs;
using ::testing::Return;
+using ::testing::ReturnNew;
using ::testing::SetArgPointee;
using ::testing::StrEq;
using ::testing::WithArg;
ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &m_local_image_ctx));
}
+ void expect_start_op(librbd::MockExclusiveLock &mock_exclusive_lock) {
+ EXPECT_CALL(mock_exclusive_lock, start_op()).WillOnce(
+ ReturnNew<FunctionContext>([](int) {}));
+ }
+
void expect_get_snap_namespace(librbd::MockTestImageCtx &mock_image_ctx,
uint64_t snap_id) {
EXPECT_CALL(mock_image_ctx, get_snap_namespace(snap_id, _))
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
journal::MockJournaler mock_journaler;
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
InSequence seq;
expect_update_client(mock_journaler, 0);
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
journal::MockJournaler mock_journaler;
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
InSequence seq;
expect_update_client(mock_journaler, -EINVAL);
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
journal::MockJournaler mock_journaler;
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
C_SaferCond ctx;
MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
mock_local_image_ctx,
ASSERT_EQ(0, create_snap(m_remote_image_ctx, "snap1"));
ASSERT_EQ(0, create_snap(m_remote_image_ctx, "snap2"));
- uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[{cls::rbd::UserSnapshotNamespace(),
- "snap1"}];
- uint64_t remote_snap_id2 = m_remote_image_ctx->snap_ids[{cls::rbd::UserSnapshotNamespace(),
- "snap2"}];
+ uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[
+ {cls::rbd::UserSnapshotNamespace(), "snap1"}];
+ uint64_t remote_snap_id2 = m_remote_image_ctx->snap_ids[
+ {cls::rbd::UserSnapshotNamespace(), "snap2"}];
librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
MockSnapshotCreateRequest mock_snapshot_create_request;
journal::MockJournaler mock_journaler;
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
InSequence seq;
expect_get_snap_namespace(mock_remote_image_ctx, remote_snap_id1);
+ expect_start_op(mock_exclusive_lock);
expect_snap_create(mock_local_image_ctx, mock_snapshot_create_request, "snap1", 12, 0);
expect_get_snap_namespace(mock_remote_image_ctx, remote_snap_id2);
+ expect_start_op(mock_exclusive_lock);
expect_snap_create(mock_local_image_ctx, mock_snapshot_create_request, "snap2", 14, 0);
expect_snap_is_protected(mock_remote_image_ctx, remote_snap_id1, false, 0);
expect_snap_is_protected(mock_remote_image_ctx, remote_snap_id2, false, 0);
MockSnapshotCreateRequest mock_snapshot_create_request;
journal::MockJournaler mock_journaler;
- uint64_t remote_snap_id1 = mock_remote_image_ctx.snap_ids[{cls::rbd::UserSnapshotNamespace(),
- "snap1"}];
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
+ uint64_t remote_snap_id1 = mock_remote_image_ctx.snap_ids[
+ {cls::rbd::UserSnapshotNamespace(), "snap1"}];
InSequence seq;
expect_get_snap_namespace(mock_remote_image_ctx, remote_snap_id1);
+ expect_start_op(mock_exclusive_lock);
expect_snap_create(mock_local_image_ctx, mock_snapshot_create_request, "snap1", 12, -EINVAL);
C_SaferCond ctx;
MockSnapshotCreateRequest mock_snapshot_create_request;
journal::MockJournaler mock_journaler;
- uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[{cls::rbd::UserSnapshotNamespace(),
- "snap1"}];
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
+ uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[
+ {cls::rbd::UserSnapshotNamespace(), "snap1"}];
expect_get_snap_namespace(mock_remote_image_ctx, remote_snap_id1);
C_SaferCond ctx;
mock_local_image_ctx,
mock_journaler, &ctx);
InSequence seq;
+ expect_start_op(mock_exclusive_lock);
EXPECT_CALL(mock_snapshot_create_request, send())
.WillOnce(DoAll(InvokeWithoutArgs([request]() {
request->cancel();
ASSERT_EQ(0, create_snap(m_remote_image_ctx, "snap1"));
ASSERT_EQ(0, create_snap(m_local_image_ctx, "snap1"));
- uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[{cls::rbd::UserSnapshotNamespace(),
- "snap1"}];
- uint64_t local_snap_id1 = m_local_image_ctx->snap_ids[{cls::rbd::UserSnapshotNamespace(),
- "snap1"}];
+ uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[
+ {cls::rbd::UserSnapshotNamespace(), "snap1"}];
+ uint64_t local_snap_id1 = m_local_image_ctx->snap_ids[
+ {cls::rbd::UserSnapshotNamespace(), "snap1"}];
librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
MockSnapshotCreateRequest mock_snapshot_create_request;
journal::MockJournaler mock_journaler;
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
InSequence seq;
expect_snap_is_unprotected(mock_local_image_ctx,
- m_local_image_ctx->snap_ids[{cls::rbd::UserSnapshotNamespace(),
- "snap1"}], true, 0);
+ m_local_image_ctx->snap_ids[
+ {cls::rbd::UserSnapshotNamespace(), "snap1"}],
+ true, 0);
expect_get_snap_namespace(mock_local_image_ctx, local_snap_id1);
+ expect_start_op(mock_exclusive_lock);
expect_snap_remove(mock_local_image_ctx, "snap1", 0);
expect_get_snap_namespace(mock_remote_image_ctx, remote_snap_id1);
+ expect_start_op(mock_exclusive_lock);
expect_snap_create(mock_local_image_ctx, mock_snapshot_create_request, "snap1", 12, 0);
expect_snap_is_protected(mock_remote_image_ctx, remote_snap_id1, false, 0);
expect_update_client(mock_journaler, 0);
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
journal::MockJournaler mock_journaler;
- uint64_t local_snap_id1 = m_local_image_ctx->snap_ids[{cls::rbd::UserSnapshotNamespace(),
- "snap1"}];
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
+ uint64_t local_snap_id1 = m_local_image_ctx->snap_ids[
+ {cls::rbd::UserSnapshotNamespace(), "snap1"}];
InSequence seq;
expect_snap_is_unprotected(mock_local_image_ctx,
- m_local_image_ctx->snap_ids[{cls::rbd::UserSnapshotNamespace(),
- "snap1"}], true, 0);
+ m_local_image_ctx->snap_ids[
+ {cls::rbd::UserSnapshotNamespace(), "snap1"}],
+ true, 0);
expect_get_snap_namespace(mock_local_image_ctx, local_snap_id1);
+ expect_start_op(mock_exclusive_lock);
expect_snap_remove(mock_local_image_ctx, "snap1", -EINVAL);
C_SaferCond ctx;
ASSERT_EQ(0, create_snap(m_remote_image_ctx, "snap1", true));
ASSERT_EQ(0, create_snap(m_local_image_ctx, "snap1", true));
- uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[{cls::rbd::UserSnapshotNamespace(),
- "snap1"}];
- uint64_t local_snap_id1 = m_local_image_ctx->snap_ids[{cls::rbd::UserSnapshotNamespace(),
- "snap1"}];
+ uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[
+ {cls::rbd::UserSnapshotNamespace(), "snap1"}];
+ uint64_t local_snap_id1 = m_local_image_ctx->snap_ids[
+ {cls::rbd::UserSnapshotNamespace(), "snap1"}];
m_client_meta.snap_seqs[remote_snap_id1] = local_snap_id1;
librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
journal::MockJournaler mock_journaler;
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
InSequence seq;
expect_snap_is_unprotected(mock_local_image_ctx, local_snap_id1, false, 0);
expect_snap_is_unprotected(mock_remote_image_ctx, remote_snap_id1, true, 0);
+ expect_start_op(mock_exclusive_lock);
expect_snap_unprotect(mock_local_image_ctx, "snap1", 0);
expect_get_snap_namespace(mock_local_image_ctx, local_snap_id1);
expect_get_snap_namespace(mock_remote_image_ctx, remote_snap_id1);
ASSERT_EQ(0, create_snap(m_remote_image_ctx, "snap1", true));
ASSERT_EQ(0, create_snap(m_local_image_ctx, "snap1", true));
- uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[{cls::rbd::UserSnapshotNamespace(),
- "snap1"}];
- uint64_t local_snap_id1 = m_local_image_ctx->snap_ids[{cls::rbd::UserSnapshotNamespace(),
- "snap1"}];
+ uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[
+ {cls::rbd::UserSnapshotNamespace(), "snap1"}];
+ uint64_t local_snap_id1 = m_local_image_ctx->snap_ids[
+ {cls::rbd::UserSnapshotNamespace(), "snap1"}];
m_client_meta.snap_seqs[remote_snap_id1] = local_snap_id1;
librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
journal::MockJournaler mock_journaler;
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
InSequence seq;
expect_snap_is_unprotected(mock_local_image_ctx, local_snap_id1, false, 0);
expect_snap_is_unprotected(mock_remote_image_ctx, remote_snap_id1, true, 0);
+ expect_start_op(mock_exclusive_lock);
expect_snap_unprotect(mock_local_image_ctx, "snap1", -EBUSY);
C_SaferCond ctx;
ASSERT_EQ(0, create_snap(m_remote_image_ctx, "snap1", true));
ASSERT_EQ(0, create_snap(m_local_image_ctx, "snap1", true));
- uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[{cls::rbd::UserSnapshotNamespace(),
- "snap1"}];
- uint64_t local_snap_id1 = m_local_image_ctx->snap_ids[{cls::rbd::UserSnapshotNamespace(),
- "snap1"}];
+ uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[
+ {cls::rbd::UserSnapshotNamespace(), "snap1"}];
+ uint64_t local_snap_id1 = m_local_image_ctx->snap_ids[
+ {cls::rbd::UserSnapshotNamespace(), "snap1"}];
m_client_meta.snap_seqs[remote_snap_id1] = local_snap_id1;
librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
journal::MockJournaler mock_journaler;
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
C_SaferCond ctx;
MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
mock_local_image_ctx,
InSequence seq;
expect_snap_is_unprotected(mock_local_image_ctx, local_snap_id1, false, 0);
expect_snap_is_unprotected(mock_remote_image_ctx, remote_snap_id1, true, 0);
+ expect_start_op(mock_exclusive_lock);
EXPECT_CALL(*mock_local_image_ctx.operations,
execute_snap_unprotect(_, StrEq("snap1"), _))
.WillOnce(DoAll(InvokeWithoutArgs([request]() {
ASSERT_EQ(0, create_snap(m_remote_image_ctx, "snap1", true));
ASSERT_EQ(0, create_snap(m_local_image_ctx, "snap1", true));
- uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[{cls::rbd::UserSnapshotNamespace(),
- "snap1"}];
- uint64_t local_snap_id1 = m_local_image_ctx->snap_ids[{cls::rbd::UserSnapshotNamespace(),
- "snap1"}];
+ uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[
+ {cls::rbd::UserSnapshotNamespace(), "snap1"}];
+ uint64_t local_snap_id1 = m_local_image_ctx->snap_ids[
+ {cls::rbd::UserSnapshotNamespace(), "snap1"}];
librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
MockSnapshotCreateRequest mock_snapshot_create_request;
journal::MockJournaler mock_journaler;
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
InSequence seq;
expect_snap_is_unprotected(mock_local_image_ctx,
- m_local_image_ctx->snap_ids[{cls::rbd::UserSnapshotNamespace(),
- "snap1"}], false, 0);
+ m_local_image_ctx->snap_ids[
+ {cls::rbd::UserSnapshotNamespace(), "snap1"}],
+ false, 0);
+ expect_start_op(mock_exclusive_lock);
expect_snap_unprotect(mock_local_image_ctx, "snap1", 0);
expect_get_snap_namespace(mock_local_image_ctx, local_snap_id1);
+ expect_start_op(mock_exclusive_lock);
expect_snap_remove(mock_local_image_ctx, "snap1", 0);
expect_get_snap_namespace(mock_remote_image_ctx, remote_snap_id1);
+ expect_start_op(mock_exclusive_lock);
expect_snap_create(mock_local_image_ctx, mock_snapshot_create_request, "snap1", 12, 0);
expect_snap_is_protected(mock_remote_image_ctx, remote_snap_id1, false, 0);
expect_update_client(mock_journaler, 0);
TEST_F(TestMockImageSyncSnapshotCopyRequest, SnapCreateProtect) {
ASSERT_EQ(0, create_snap(m_remote_image_ctx, "snap1", true));
- uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[{cls::rbd::UserSnapshotNamespace(),
- "snap1"}];
+ uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[
+ {cls::rbd::UserSnapshotNamespace(), "snap1"}];
librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
MockSnapshotCreateRequest mock_snapshot_create_request;
journal::MockJournaler mock_journaler;
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
InSequence seq;
expect_get_snap_namespace(mock_remote_image_ctx, remote_snap_id1);
+ expect_start_op(mock_exclusive_lock);
expect_snap_create(mock_local_image_ctx, mock_snapshot_create_request, "snap1", 12, 0);
expect_snap_is_protected(mock_remote_image_ctx, remote_snap_id1, true, 0);
expect_snap_is_protected(mock_local_image_ctx, 12, false, 0);
+ expect_start_op(mock_exclusive_lock);
expect_snap_protect(mock_local_image_ctx, "snap1", 0);
expect_update_client(mock_journaler, 0);
ASSERT_EQ(0, create_snap(m_remote_image_ctx, "snap1", true));
ASSERT_EQ(0, create_snap(m_local_image_ctx, "snap1", true));
- uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[{cls::rbd::UserSnapshotNamespace(),
- "snap1"}];
- uint64_t local_snap_id1 = m_local_image_ctx->snap_ids[{cls::rbd::UserSnapshotNamespace(),
- "snap1"}];
+ uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[
+ {cls::rbd::UserSnapshotNamespace(), "snap1"}];
+ uint64_t local_snap_id1 = m_local_image_ctx->snap_ids[
+ {cls::rbd::UserSnapshotNamespace(), "snap1"}];
m_client_meta.snap_seqs[remote_snap_id1] = local_snap_id1;
librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
journal::MockJournaler mock_journaler;
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
InSequence seq;
expect_snap_is_unprotected(mock_local_image_ctx, local_snap_id1, true, 0);
expect_get_snap_namespace(mock_local_image_ctx, local_snap_id1);
expect_get_snap_namespace(mock_remote_image_ctx, remote_snap_id1);
expect_snap_is_protected(mock_remote_image_ctx, remote_snap_id1, true, 0);
expect_snap_is_protected(mock_local_image_ctx, local_snap_id1, false, 0);
+ expect_start_op(mock_exclusive_lock);
expect_snap_protect(mock_local_image_ctx, "snap1", 0);
expect_update_client(mock_journaler, 0);
ASSERT_EQ(0, create_snap(m_remote_image_ctx, "snap1", true));
ASSERT_EQ(0, create_snap(m_local_image_ctx, "snap1", true));
- uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[{cls::rbd::UserSnapshotNamespace(),
- "snap1"}];
- uint64_t local_snap_id1 = m_local_image_ctx->snap_ids[{cls::rbd::UserSnapshotNamespace(),
- "snap1"}];
+ uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[
+ {cls::rbd::UserSnapshotNamespace(), "snap1"}];
+ uint64_t local_snap_id1 = m_local_image_ctx->snap_ids[
+ {cls::rbd::UserSnapshotNamespace(), "snap1"}];
m_client_meta.snap_seqs[remote_snap_id1] = local_snap_id1;
librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
journal::MockJournaler mock_journaler;
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
InSequence seq;
expect_snap_is_unprotected(mock_local_image_ctx, local_snap_id1, true, 0);
expect_get_snap_namespace(mock_local_image_ctx, local_snap_id1);
expect_get_snap_namespace(mock_remote_image_ctx, remote_snap_id1);
expect_snap_is_protected(mock_remote_image_ctx, remote_snap_id1, true, 0);
expect_snap_is_protected(mock_local_image_ctx, local_snap_id1, false, 0);
+ expect_start_op(mock_exclusive_lock);
expect_snap_protect(mock_local_image_ctx, "snap1", -EINVAL);
C_SaferCond ctx;
ASSERT_EQ(0, create_snap(m_remote_image_ctx, "snap1", true));
ASSERT_EQ(0, create_snap(m_local_image_ctx, "snap1", true));
- uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[{cls::rbd::UserSnapshotNamespace(),
- "snap1"}];
- uint64_t local_snap_id1 = m_local_image_ctx->snap_ids[{cls::rbd::UserSnapshotNamespace(),
- "snap1"}];
+ uint64_t remote_snap_id1 = m_remote_image_ctx->snap_ids[
+ {cls::rbd::UserSnapshotNamespace(), "snap1"}];
+ uint64_t local_snap_id1 = m_local_image_ctx->snap_ids[
+ {cls::rbd::UserSnapshotNamespace(), "snap1"}];
m_client_meta.snap_seqs[remote_snap_id1] = local_snap_id1;
librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
journal::MockJournaler mock_journaler;
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
C_SaferCond ctx;
MockSnapshotCopyRequest *request = create_request(mock_remote_image_ctx,
mock_local_image_ctx,
expect_get_snap_namespace(mock_remote_image_ctx, remote_snap_id1);
expect_snap_is_protected(mock_remote_image_ctx, remote_snap_id1, true, 0);
expect_snap_is_protected(mock_local_image_ctx, local_snap_id1, false, 0);
+ expect_start_op(mock_exclusive_lock);
EXPECT_CALL(*mock_local_image_ctx.operations,
execute_snap_protect(_, StrEq("snap1"), _))
.WillOnce(DoAll(InvokeWithoutArgs([request]() {
using ::testing::Invoke;
using ::testing::InvokeWithoutArgs;
using ::testing::Return;
+using ::testing::ReturnNew;
using ::testing::StrEq;
using ::testing::WithArg;
ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &m_local_image_ctx));
}
+ void expect_start_op(librbd::MockExclusiveLock &mock_exclusive_lock) {
+ EXPECT_CALL(mock_exclusive_lock, start_op()).WillOnce(
+ ReturnNew<FunctionContext>([](int) {}));
+ }
+
void expect_test_features(librbd::MockTestImageCtx &mock_image_ctx,
uint64_t features, bool enabled) {
EXPECT_CALL(mock_image_ctx, test_features(features))
TEST_F(TestMockImageSyncSnapshotCreateRequest, Resize) {
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
InSequence seq;
+ expect_start_op(mock_exclusive_lock);
expect_set_size(mock_local_image_ctx, 0);
+ expect_start_op(mock_exclusive_lock);
expect_snap_create(mock_local_image_ctx, "snap1", 10, 0);
expect_test_features(mock_local_image_ctx, RBD_FEATURE_OBJECT_MAP, false);
TEST_F(TestMockImageSyncSnapshotCreateRequest, ResizeError) {
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
InSequence seq;
+ expect_start_op(mock_exclusive_lock);
expect_set_size(mock_local_image_ctx, -EINVAL);
C_SaferCond ctx;
TEST_F(TestMockImageSyncSnapshotCreateRequest, RemoveParent) {
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
mock_local_image_ctx.parent_md.spec.pool_id = 213;
InSequence seq;
+ expect_start_op(mock_exclusive_lock);
expect_remove_parent(mock_local_image_ctx, 0);
+ expect_start_op(mock_exclusive_lock);
expect_snap_create(mock_local_image_ctx, "snap1", 10, 0);
expect_test_features(mock_local_image_ctx, RBD_FEATURE_OBJECT_MAP, false);
TEST_F(TestMockImageSyncSnapshotCreateRequest, RemoveParentError) {
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
mock_local_image_ctx.parent_md.spec.pool_id = 213;
InSequence seq;
+ expect_start_op(mock_exclusive_lock);
expect_remove_parent(mock_local_image_ctx, -EINVAL);
C_SaferCond ctx;
TEST_F(TestMockImageSyncSnapshotCreateRequest, RemoveSetParent) {
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
mock_local_image_ctx.parent_md.spec.pool_id = 213;
InSequence seq;
+ expect_start_op(mock_exclusive_lock);
expect_remove_parent(mock_local_image_ctx, 0);
+ expect_start_op(mock_exclusive_lock);
expect_set_parent(mock_local_image_ctx, 0);
+ expect_start_op(mock_exclusive_lock);
expect_snap_create(mock_local_image_ctx, "snap1", 10, 0);
expect_test_features(mock_local_image_ctx, RBD_FEATURE_OBJECT_MAP, false);
TEST_F(TestMockImageSyncSnapshotCreateRequest, SetParentSpec) {
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
InSequence seq;
+ expect_start_op(mock_exclusive_lock);
expect_set_parent(mock_local_image_ctx, 0);
+ expect_start_op(mock_exclusive_lock);
expect_snap_create(mock_local_image_ctx, "snap1", 10, 0);
expect_test_features(mock_local_image_ctx, RBD_FEATURE_OBJECT_MAP, false);
TEST_F(TestMockImageSyncSnapshotCreateRequest, SetParentOverlap) {
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
mock_local_image_ctx.parent_md.spec = {123, "test", 0};
InSequence seq;
+ expect_start_op(mock_exclusive_lock);
expect_set_parent(mock_local_image_ctx, 0);
+ expect_start_op(mock_exclusive_lock);
expect_snap_create(mock_local_image_ctx, "snap1", 10, 0);
expect_test_features(mock_local_image_ctx, RBD_FEATURE_OBJECT_MAP, false);
TEST_F(TestMockImageSyncSnapshotCreateRequest, SetParentError) {
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
InSequence seq;
+ expect_start_op(mock_exclusive_lock);
expect_set_parent(mock_local_image_ctx, -ESTALE);
C_SaferCond ctx;
TEST_F(TestMockImageSyncSnapshotCreateRequest, SnapCreate) {
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
InSequence seq;
+ expect_start_op(mock_exclusive_lock);
expect_snap_create(mock_local_image_ctx, "snap1", 10, 0);
expect_test_features(mock_local_image_ctx, RBD_FEATURE_OBJECT_MAP, false);
TEST_F(TestMockImageSyncSnapshotCreateRequest, SnapCreateError) {
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
InSequence seq;
+ expect_start_op(mock_exclusive_lock);
expect_snap_create(mock_local_image_ctx, "snap1", 10, -EINVAL);
C_SaferCond ctx;
TEST_F(TestMockImageSyncSnapshotCreateRequest, ResizeObjectMap) {
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
InSequence seq;
+ expect_start_op(mock_exclusive_lock);
expect_snap_create(mock_local_image_ctx, "snap1", 10, 0);
expect_test_features(mock_local_image_ctx, RBD_FEATURE_OBJECT_MAP, true);
+ expect_start_op(mock_exclusive_lock);
expect_object_map_resize(mock_local_image_ctx, 10, 0);
C_SaferCond ctx;
TEST_F(TestMockImageSyncSnapshotCreateRequest, ResizeObjectMapError) {
librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
InSequence seq;
+ expect_start_op(mock_exclusive_lock);
expect_snap_create(mock_local_image_ctx, "snap1", 10, 0);
expect_test_features(mock_local_image_ctx, RBD_FEATURE_OBJECT_MAP, true);
+ expect_start_op(mock_exclusive_lock);
expect_object_map_resize(mock_local_image_ctx, 10, -EINVAL);
C_SaferCond ctx;
using ::testing::InSequence;
using ::testing::Invoke;
using ::testing::Return;
+using ::testing::ReturnNew;
using ::testing::WithArg;
using ::testing::InvokeWithoutArgs;
ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &m_local_image_ctx));
}
+ void expect_start_op(librbd::MockExclusiveLock &mock_exclusive_lock) {
+ EXPECT_CALL(mock_exclusive_lock, start_op()).WillOnce(
+ ReturnNew<FunctionContext>([](int) {}));
+ }
+
void expect_create_sync_point(librbd::MockTestImageCtx &mock_local_image_ctx,
MockSyncPointCreateRequest &mock_sync_point_create_request,
int r) {
MockSyncPointCreateRequest mock_sync_point_create_request;
MockSyncPointPruneRequest mock_sync_point_prune_request;
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
librbd::MockObjectMap *mock_object_map = new librbd::MockObjectMap();
mock_local_image_ctx.object_map = mock_object_map;
expect_test_features(mock_local_image_ctx);
expect_create_sync_point(mock_local_image_ctx, mock_sync_point_create_request, 0);
expect_copy_snapshots(mock_snapshot_copy_request, 0);
expect_copy_image(mock_image_copy_request, 0);
+ expect_start_op(mock_exclusive_lock);
expect_rollback_object_map(*mock_object_map, 0);
expect_create_object_map(mock_local_image_ctx, mock_object_map);
expect_open_object_map(mock_local_image_ctx, *mock_object_map);
mock_local_image_ctx.snap_ids[{cls::rbd::UserSnapshotNamespace(), "snap1"}] = 123;
mock_local_image_ctx.snap_ids[{cls::rbd::UserSnapshotNamespace(), "snap2"}] = 234;
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
librbd::MockObjectMap *mock_object_map = new librbd::MockObjectMap();
mock_local_image_ctx.object_map = mock_object_map;
expect_test_features(mock_local_image_ctx);
expect_prune_sync_point(mock_sync_point_prune_request, false, 0);
expect_copy_snapshots(mock_snapshot_copy_request, 0);
expect_copy_image(mock_image_copy_request, 0);
+ expect_start_op(mock_exclusive_lock);
expect_rollback_object_map(*mock_object_map, 0);
expect_create_object_map(mock_local_image_ctx, mock_object_map);
expect_open_object_map(mock_local_image_ctx, *mock_object_map);
MockSyncPointCreateRequest mock_sync_point_create_request;
MockSyncPointPruneRequest mock_sync_point_prune_request;
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
m_client_meta.sync_points = {{cls::rbd::UserSnapshotNamespace(), "snap1", boost::none}};
InSequence seq;
MockSnapshotCopyRequest mock_snapshot_copy_request;
MockSyncPointCreateRequest mock_sync_point_create_request;
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
librbd::MockObjectMap *mock_object_map = new librbd::MockObjectMap();
mock_local_image_ctx.object_map = mock_object_map;
expect_test_features(mock_local_image_ctx);
MockSyncPointCreateRequest mock_sync_point_create_request;
MockSyncPointPruneRequest mock_sync_point_prune_request;
+ librbd::MockExclusiveLock mock_exclusive_lock;
+ mock_local_image_ctx.exclusive_lock = &mock_exclusive_lock;
+
librbd::MockObjectMap *mock_object_map = new librbd::MockObjectMap();
mock_local_image_ctx.object_map = mock_object_map;
expect_test_features(mock_local_image_ctx);
#include "ProgressContext.h"
#include "common/errno.h"
#include "journal/Journaler.h"
+#include "librbd/ExclusiveLock.h"
#include "librbd/ImageCtx.h"
#include "librbd/ObjectMap.h"
#include "librbd/Utils.h"
void ImageSync<I>::send_copy_object_map() {
update_progress("COPY_OBJECT_MAP");
+ m_local_image_ctx->owner_lock.get_read();
m_local_image_ctx->snap_lock.get_read();
if (!m_local_image_ctx->test_features(RBD_FEATURE_OBJECT_MAP,
m_local_image_ctx->snap_lock)) {
m_local_image_ctx->snap_lock.put_read();
+ m_local_image_ctx->owner_lock.put_read();
send_prune_sync_points();
return;
}
assert(!m_client_meta->sync_points.empty());
librbd::journal::MirrorPeerSyncPoint &sync_point =
m_client_meta->sync_points.front();
- auto snap_id_it = m_local_image_ctx->snap_ids.find({cls::rbd::UserSnapshotNamespace(),
- sync_point.snap_name});
+ auto snap_id_it = m_local_image_ctx->snap_ids.find(
+ {cls::rbd::UserSnapshotNamespace(), sync_point.snap_name});
assert(snap_id_it != m_local_image_ctx->snap_ids.end());
librados::snap_t snap_id = snap_id_it->second;
dout(20) << ": snap_id=" << snap_id << ", "
<< "snap_name=" << sync_point.snap_name << dendl;
+ Context *finish_op_ctx = nullptr;
+ if (m_local_image_ctx->exclusive_lock != nullptr) {
+ finish_op_ctx = m_local_image_ctx->exclusive_lock->start_op();
+ }
+ if (finish_op_ctx == nullptr) {
+ derr << ": lost exclusive lock" << dendl;
+ m_local_image_ctx->snap_lock.put_read();
+ m_local_image_ctx->owner_lock.put_read();
+ finish(-EROFS);
+ return;
+ }
+
// rollback the object map (copy snapshot object map to HEAD)
RWLock::WLocker object_map_locker(m_local_image_ctx->object_map_lock);
- Context *ctx = create_context_callback<
- ImageSync<I>, &ImageSync<I>::handle_copy_object_map>(this);
+ auto ctx = new FunctionContext([this, finish_op_ctx](int r) {
+ handle_copy_object_map(r);
+ finish_op_ctx->complete(0);
+ });
m_local_image_ctx->object_map->rollback(snap_id, ctx);
m_local_image_ctx->snap_lock.put_read();
+ m_local_image_ctx->owner_lock.put_read();
}
template <typename I>
#include "common/errno.h"
#include "common/Timer.h"
#include "journal/Journaler.h"
+#include "librbd/ExclusiveLock.h"
#include "librbd/Utils.h"
#include "tools/rbd_mirror/ProgressContext.h"
bool complete;
{
+ RWLock::RLocker owner_locker(m_local_image_ctx->owner_lock);
Mutex::Locker locker(m_lock);
for (int i = 0; i < cct->_conf->rbd_concurrent_management_ops; ++i) {
send_next_object_copy();
template <typename I>
void ImageCopyRequest<I>::send_next_object_copy() {
+ assert(m_local_image_ctx->owner_lock.is_locked());
assert(m_lock.is_locked());
if (m_canceled && m_ret_val == 0) {
++m_current_ops;
- Context *ctx = create_context_callback<
- ImageCopyRequest<I>, &ImageCopyRequest<I>::handle_object_copy>(this);
+ Context *finish_op_ctx = nullptr;
+ if (m_local_image_ctx->exclusive_lock != nullptr) {
+ finish_op_ctx = m_local_image_ctx->exclusive_lock->start_op();
+ }
+ if (finish_op_ctx == nullptr) {
+ derr << ": lost exclusive lock" << dendl;
+ finish(-EROFS);
+ return;
+ }
+
+ auto ctx = new FunctionContext([this, finish_op_ctx](int r) {
+ handle_object_copy(r);
+ finish_op_ctx->complete(0);
+ });
ObjectCopyRequest<I> *req = ObjectCopyRequest<I>::create(
m_local_image_ctx, m_remote_image_ctx, &m_snap_map, ono, ctx);
req->send();
int percent;
bool complete;
{
+ RWLock::RLocker owner_locker(m_local_image_ctx->owner_lock);
Mutex::Locker locker(m_lock);
assert(m_current_ops > 0);
--m_current_ops;
#include "common/errno.h"
#include "common/WorkQueue.h"
#include "journal/Journaler.h"
+#include "librbd/ExclusiveLock.h"
#include "librbd/Operations.h"
#include "librbd/Utils.h"
#include "librbd/journal/Types.h"
<< "snap_name=" << m_snap_name << ", "
<< "snap_id=" << m_prev_snap_id << dendl;
- Context *ctx = create_context_callback<
- SnapshotCopyRequest<I>, &SnapshotCopyRequest<I>::handle_snap_unprotect>(
- this);
+ auto finish_op_ctx = start_local_op();
+ if (finish_op_ctx == nullptr) {
+ derr << ": lost exclusive lock" << dendl;
+ finish(-EROFS);
+ return;
+ }
+
+ auto ctx = new FunctionContext([this, finish_op_ctx](int r) {
+ handle_snap_unprotect(r);
+ finish_op_ctx->complete(0);
+ });
RWLock::RLocker owner_locker(m_local_image_ctx->owner_lock);
- m_local_image_ctx->operations->execute_snap_unprotect(cls::rbd::UserSnapshotNamespace(),
- m_snap_name.c_str(),
- ctx);
+ m_local_image_ctx->operations->execute_snap_unprotect(
+ cls::rbd::UserSnapshotNamespace(), m_snap_name.c_str(), ctx);
}
template <typename I>
cls::rbd::SnapshotNamespace snap_namespace;
m_local_image_ctx->snap_lock.get_read();
- int r = m_local_image_ctx->get_snap_namespace(local_snap_id, &snap_namespace);
+ int r = m_local_image_ctx->get_snap_namespace(local_snap_id,
+ &snap_namespace);
m_local_image_ctx->snap_lock.put_read();
if (r < 0) {
derr << ": failed to retrieve local snap namespace: " << m_snap_name
return;
}
- if (boost::get<cls::rbd::UserSnapshotNamespace>(&snap_namespace) == nullptr) {
+ if (boost::get<cls::rbd::UserSnapshotNamespace>(&snap_namespace) ==
+ nullptr) {
continue;
}
<< "snap_name=" << m_snap_name << ", "
<< "snap_id=" << m_prev_snap_id << dendl;
- Context *ctx = create_context_callback<
- SnapshotCopyRequest<I>, &SnapshotCopyRequest<I>::handle_snap_remove>(
- this);
+ auto finish_op_ctx = start_local_op();
+ if (finish_op_ctx == nullptr) {
+ derr << ": lost exclusive lock" << dendl;
+ finish(-EROFS);
+ return;
+ }
+
+ auto ctx = new FunctionContext([this, finish_op_ctx](int r) {
+ handle_snap_remove(r);
+ finish_op_ctx->complete(0);
+ });
RWLock::RLocker owner_locker(m_local_image_ctx->owner_lock);
- m_local_image_ctx->operations->execute_snap_remove(cls::rbd::UserSnapshotNamespace(),
- m_snap_name.c_str(),
- ctx);
+ m_local_image_ctx->operations->execute_snap_remove(
+ cls::rbd::UserSnapshotNamespace(), m_snap_name.c_str(), ctx);
}
template <typename I>
<< "snap_id=" << parent_spec.snap_id << ", "
<< "overlap=" << parent_overlap << "]" << dendl;
- Context *ctx = create_context_callback<
- SnapshotCopyRequest<I>, &SnapshotCopyRequest<I>::handle_snap_create>(
- this);
+ Context *finish_op_ctx = start_local_op();
+ if (finish_op_ctx == nullptr) {
+ derr << ": lost exclusive lock" << dendl;
+ finish(-EROFS);
+ return;
+ }
+
+ auto ctx = new FunctionContext([this, finish_op_ctx](int r) {
+ handle_snap_create(r);
+ finish_op_ctx->complete(0);
+ });
SnapshotCreateRequest<I> *req = SnapshotCreateRequest<I>::create(
- m_local_image_ctx, m_snap_name, m_snap_namespace, size, parent_spec, parent_overlap, ctx);
+ m_local_image_ctx, m_snap_name, m_snap_namespace, size, parent_spec,
+ parent_overlap, ctx);
req->send();
}
<< "snap_name=" << m_snap_name << ", "
<< "snap_id=" << m_prev_snap_id << dendl;
- Context *ctx = create_context_callback<
- SnapshotCopyRequest<I>, &SnapshotCopyRequest<I>::handle_snap_protect>(
- this);
+ auto finish_op_ctx = start_local_op();
+ if (finish_op_ctx == nullptr) {
+ derr << ": lost exclusive lock" << dendl;
+ finish(-EROFS);
+ return;
+ }
+
+ auto ctx = new FunctionContext([this, finish_op_ctx](int r) {
+ handle_snap_protect(r);
+ finish_op_ctx->complete(0);
+ });
RWLock::RLocker owner_locker(m_local_image_ctx->owner_lock);
- m_local_image_ctx->operations->execute_snap_protect(cls::rbd::UserSnapshotNamespace(),
- m_snap_name.c_str(),
- ctx);
+ m_local_image_ctx->operations->execute_snap_protect(
+ cls::rbd::UserSnapshotNamespace(), m_snap_name.c_str(), ctx);
}
template <typename I>
return 0;
}
+template <typename I>
+Context *SnapshotCopyRequest<I>::start_local_op() {
+ RWLock::RLocker owner_locker(m_local_image_ctx->owner_lock);
+ if (m_local_image_ctx->exclusive_lock == nullptr) {
+ return nullptr;
+ }
+ return m_local_image_ctx->exclusive_lock->start_op();
+}
+
} // namespace image_sync
} // namespace mirror
} // namespace rbd
int validate_parent(ImageCtxT *image_ctx, librbd::ParentSpec *spec);
+ Context *start_local_op();
+
};
} // namespace image_sync
#include "common/errno.h"
#include "cls/rbd/cls_rbd_client.h"
#include "cls/rbd/cls_rbd_types.h"
+#include "librbd/ExclusiveLock.h"
#include "librbd/ObjectMap.h"
#include "librbd/Operations.h"
#include "librbd/Utils.h"
librados::ObjectWriteOperation op;
librbd::cls_client::set_size(&op, m_size);
- librados::AioCompletion *comp = create_rados_callback<
- SnapshotCreateRequest<I>, &SnapshotCreateRequest<I>::handle_set_size>(this);
+ auto finish_op_ctx = start_local_op();
+ if (finish_op_ctx == nullptr) {
+ derr << ": lost exclusive lock" << dendl;
+ finish(-EROFS);
+ return;
+ }
+
+ auto ctx = new FunctionContext([this, finish_op_ctx](int r) {
+ handle_set_size(r);
+ finish_op_ctx->complete(0);
+ });
+ librados::AioCompletion *comp = create_rados_callback(ctx);
int r = m_local_image_ctx->md_ctx.aio_operate(m_local_image_ctx->header_oid,
comp, &op);
assert(r == 0);
librados::ObjectWriteOperation op;
librbd::cls_client::remove_parent(&op);
- librados::AioCompletion *comp = create_rados_callback<
- SnapshotCreateRequest<I>,
- &SnapshotCreateRequest<I>::handle_remove_parent>(this);
+ auto finish_op_ctx = start_local_op();
+ if (finish_op_ctx == nullptr) {
+ derr << ": lost exclusive lock" << dendl;
+ finish(-EROFS);
+ return;
+ }
+
+ auto ctx = new FunctionContext([this, finish_op_ctx](int r) {
+ handle_remove_parent(r);
+ finish_op_ctx->complete(0);
+ });
+ librados::AioCompletion *comp = create_rados_callback(ctx);
int r = m_local_image_ctx->md_ctx.aio_operate(m_local_image_ctx->header_oid,
comp, &op);
assert(r == 0);
librados::ObjectWriteOperation op;
librbd::cls_client::set_parent(&op, m_parent_spec, m_parent_overlap);
- librados::AioCompletion *comp = create_rados_callback<
- SnapshotCreateRequest<I>,
- &SnapshotCreateRequest<I>::handle_set_parent>(this);
+ auto finish_op_ctx = start_local_op();
+ if (finish_op_ctx == nullptr) {
+ derr << ": lost exclusive lock" << dendl;
+ finish(-EROFS);
+ return;
+ }
+
+ auto ctx = new FunctionContext([this, finish_op_ctx](int r) {
+ handle_set_parent(r);
+ finish_op_ctx->complete(0);
+ });
+ librados::AioCompletion *comp = create_rados_callback(ctx);
int r = m_local_image_ctx->md_ctx.aio_operate(m_local_image_ctx->header_oid,
comp, &op);
assert(r == 0);
void SnapshotCreateRequest<I>::send_snap_create() {
dout(20) << ": snap_name=" << m_snap_name << dendl;
- Context *ctx = create_context_callback<
- SnapshotCreateRequest<I>, &SnapshotCreateRequest<I>::handle_snap_create>(
- this);
+ auto finish_op_ctx = start_local_op();
+ if (finish_op_ctx == nullptr) {
+ derr << ": lost exclusive lock" << dendl;
+ finish(-EROFS);
+ return;
+ }
+
+ auto ctx = new FunctionContext([this, finish_op_ctx](int r) {
+ handle_snap_create(r);
+ finish_op_ctx->complete(0);
+ });
RWLock::RLocker owner_locker(m_local_image_ctx->owner_lock);
m_local_image_ctx->operations->execute_snap_create(m_snap_namespace,
m_snap_name.c_str(),
}
m_local_image_ctx->snap_lock.get_read();
- auto snap_it = m_local_image_ctx->snap_ids.find({cls::rbd::UserSnapshotNamespace(),
- m_snap_name});
+ auto snap_it = m_local_image_ctx->snap_ids.find(
+ {cls::rbd::UserSnapshotNamespace(), m_snap_name});
if (snap_it == m_local_image_ctx->snap_ids.end()) {
derr << ": failed to locate snap: " << m_snap_name << dendl;
m_local_image_ctx->snap_lock.put_read();
librados::ObjectWriteOperation op;
librbd::cls_client::object_map_resize(&op, object_count, OBJECT_NONEXISTENT);
- librados::AioCompletion *comp = create_rados_callback<
- SnapshotCreateRequest<I>,
- &SnapshotCreateRequest<I>::handle_create_object_map>(this);
+ auto finish_op_ctx = start_local_op();
+ if (finish_op_ctx == nullptr) {
+ derr << ": lost exclusive lock" << dendl;
+ finish(-EROFS);
+ return;
+ }
+
+ auto ctx = new FunctionContext([this, finish_op_ctx](int r) {
+ handle_create_object_map(r);
+ finish_op_ctx->complete(0);
+ });
+ librados::AioCompletion *comp = create_rados_callback(ctx);
int r = m_local_image_ctx->md_ctx.aio_operate(object_map_oid, comp, &op);
assert(r == 0);
comp->release();
finish(0);
}
+template <typename I>
+Context *SnapshotCreateRequest<I>::start_local_op() {
+ RWLock::RLocker owner_locker(m_local_image_ctx->owner_lock);
+ if (m_local_image_ctx->exclusive_lock == nullptr) {
+ return nullptr;
+ }
+ return m_local_image_ctx->exclusive_lock->start_op();
+}
+
template <typename I>
void SnapshotCreateRequest<I>::finish(int r) {
dout(20) << ": r=" << r << dendl;
void send_create_object_map();
void handle_create_object_map(int r);
+ Context *start_local_op();
+
void finish(int r);
};