X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Ftest%2Flibrbd%2Fjournal%2Ftest_mock_Replay.cc;fp=src%2Fceph%2Fsrc%2Ftest%2Flibrbd%2Fjournal%2Ftest_mock_Replay.cc;h=0000000000000000000000000000000000000000;hb=7da45d65be36d36b880cc55c5036e96c24b53f00;hp=8c39576905d7f19dfb98fd45ebdfc4451ff402c9;hpb=691462d09d0987b47e112d6ee8740375df3c51b2;p=stor4nfv.git diff --git a/src/ceph/src/test/librbd/journal/test_mock_Replay.cc b/src/ceph/src/test/librbd/journal/test_mock_Replay.cc deleted file mode 100644 index 8c39576..0000000 --- a/src/ceph/src/test/librbd/journal/test_mock_Replay.cc +++ /dev/null @@ -1,2013 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab - -#include "test/librbd/test_mock_fixture.h" -#include "test/librbd/test_support.h" -#include "test/librbd/mock/MockImageCtx.h" -#include "librbd/io/ImageRequest.h" -#include "librbd/journal/Replay.h" -#include "librbd/journal/Types.h" -#include "gmock/gmock.h" -#include "gtest/gtest.h" -#include - -namespace librbd { - -namespace { - -struct MockReplayImageCtx : public MockImageCtx { - MockReplayImageCtx(ImageCtx &image_ctx) : MockImageCtx(image_ctx) { - } -}; - -} // anonymous namespace - -namespace io { - -template <> -struct ImageRequest { - static ImageRequest *s_instance; - - MOCK_METHOD4(aio_write, void(AioCompletion *c, const Extents &image_extents, - const bufferlist &bl, int op_flags)); - static void aio_write(MockReplayImageCtx *ictx, AioCompletion *c, - Extents &&image_extents, bufferlist &&bl, - int op_flags, const ZTracer::Trace &parent_trace) { - assert(s_instance != nullptr); - s_instance->aio_write(c, image_extents, bl, op_flags); - } - - MOCK_METHOD4(aio_discard, void(AioCompletion *c, uint64_t off, uint64_t len, - bool skip_partial_discard)); - static void aio_discard(MockReplayImageCtx *ictx, AioCompletion *c, - uint64_t off, uint64_t len, - bool skip_partial_discard, - const ZTracer::Trace &parent_trace) { - assert(s_instance != nullptr); - s_instance->aio_discard(c, off, len, skip_partial_discard); - } - - MOCK_METHOD1(aio_flush, void(AioCompletion *c)); - static void aio_flush(MockReplayImageCtx *ictx, AioCompletion *c, - const ZTracer::Trace &parent_trace) { - assert(s_instance != nullptr); - s_instance->aio_flush(c); - } - - MOCK_METHOD5(aio_writesame, void(AioCompletion *c, uint64_t off, uint64_t len, - const bufferlist &bl, int op_flags)); - static void aio_writesame(MockReplayImageCtx *ictx, AioCompletion *c, - uint64_t off, uint64_t len, bufferlist &&bl, - int op_flags, const ZTracer::Trace &parent_trace) { - assert(s_instance != nullptr); - s_instance->aio_writesame(c, off, len, bl, op_flags); - } - - MOCK_METHOD6(aio_compare_and_write, void(AioCompletion *c, const Extents &image_extents, - const bufferlist &cmp_bl, const bufferlist &bl, - uint64_t *mismatch_offset, int op_flags)); - static void aio_compare_and_write(MockReplayImageCtx *ictx, AioCompletion *c, - Extents &&image_extents, bufferlist &&cmp_bl, - bufferlist &&bl, uint64_t *mismatch_offset, - int op_flags, const ZTracer::Trace &parent_trace) { - assert(s_instance != nullptr); - s_instance->aio_compare_and_write(c, image_extents, cmp_bl, bl, - mismatch_offset, op_flags); - } - - ImageRequest() { - s_instance = this; - } -}; - -ImageRequest *ImageRequest::s_instance = nullptr; - -} // namespace io - -namespace util { - -inline ImageCtx *get_image_ctx(librbd::MockReplayImageCtx *image_ctx) { - return image_ctx->image_ctx; -} - -} // namespace util - -} // namespace librbd - -// template definitions -#include "librbd/journal/Replay.cc" -template class librbd::journal::Replay; - -using ::testing::_; -using ::testing::DoAll; -using ::testing::InSequence; -using ::testing::Return; -using ::testing::SaveArg; -using ::testing::StrEq; -using ::testing::WithArgs; - -MATCHER_P(BufferlistEqual, str, "") { - bufferlist bl(arg); - return (strncmp(bl.c_str(), str, strlen(str)) == 0); -} - -MATCHER_P(CStrEq, str, "") { - return (strncmp(arg, str, strlen(str)) == 0); -} - -ACTION_P2(NotifyInvoke, lock, cond) { - Mutex::Locker locker(*lock); - cond->Signal(); -} - -ACTION_P2(CompleteAioCompletion, r, image_ctx) { - image_ctx->op_work_queue->queue(new FunctionContext([this, arg0](int r) { - arg0->get(); - arg0->init_time(image_ctx, librbd::io::AIO_TYPE_NONE); - arg0->set_request_count(1); - arg0->complete_request(r); - }), r); -} - -namespace librbd { -namespace journal { - -class TestMockJournalReplay : public TestMockFixture { -public: - typedef io::ImageRequest MockIoImageRequest; - typedef Replay MockJournalReplay; - - TestMockJournalReplay() : m_invoke_lock("m_invoke_lock") { - } - - void expect_accept_ops(MockExclusiveLock &mock_exclusive_lock, bool accept) { - EXPECT_CALL(mock_exclusive_lock, accept_ops()).WillRepeatedly( - Return(accept)); - } - - void expect_aio_discard(MockIoImageRequest &mock_io_image_request, - io::AioCompletion **aio_comp, uint64_t off, - uint64_t len, bool skip_partial_discard) { - EXPECT_CALL(mock_io_image_request, aio_discard(_, off, len, skip_partial_discard)) - .WillOnce(SaveArg<0>(aio_comp)); - } - - void expect_aio_flush(MockIoImageRequest &mock_io_image_request, - io::AioCompletion **aio_comp) { - EXPECT_CALL(mock_io_image_request, aio_flush(_)) - .WillOnce(SaveArg<0>(aio_comp)); - } - - void expect_aio_flush(MockReplayImageCtx &mock_image_ctx, - MockIoImageRequest &mock_io_image_request, int r) { - EXPECT_CALL(mock_io_image_request, aio_flush(_)) - .WillOnce(CompleteAioCompletion(r, mock_image_ctx.image_ctx)); - } - - void expect_aio_write(MockIoImageRequest &mock_io_image_request, - io::AioCompletion **aio_comp, uint64_t off, - uint64_t len, const char *data) { - EXPECT_CALL(mock_io_image_request, - aio_write(_, io::Extents{{off, len}}, BufferlistEqual(data), _)) - .WillOnce(SaveArg<0>(aio_comp)); - } - - void expect_aio_writesame(MockIoImageRequest &mock_io_image_request, - io::AioCompletion **aio_comp, uint64_t off, - uint64_t len, const char *data) { - EXPECT_CALL(mock_io_image_request, - aio_writesame(_, off, len, BufferlistEqual(data), _)) - .WillOnce(SaveArg<0>(aio_comp)); - } - - void expect_aio_compare_and_write(MockIoImageRequest &mock_io_image_request, - io::AioCompletion **aio_comp, uint64_t off, - uint64_t len, const char *cmp_data, const char *data, - uint64_t *mismatch_offset) { - EXPECT_CALL(mock_io_image_request, - aio_compare_and_write(_, io::Extents{{off, len}}, - BufferlistEqual(cmp_data), BufferlistEqual(data), mismatch_offset, _)) - .WillOnce(SaveArg<0>(aio_comp)); - } - - void expect_flatten(MockReplayImageCtx &mock_image_ctx, Context **on_finish) { - EXPECT_CALL(*mock_image_ctx.operations, execute_flatten(_, _)) - .WillOnce(DoAll(SaveArg<1>(on_finish), - NotifyInvoke(&m_invoke_lock, &m_invoke_cond))); - } - - void expect_rename(MockReplayImageCtx &mock_image_ctx, Context **on_finish, - const char *image_name) { - EXPECT_CALL(*mock_image_ctx.operations, execute_rename(StrEq(image_name), _)) - .WillOnce(DoAll(SaveArg<1>(on_finish), - NotifyInvoke(&m_invoke_lock, &m_invoke_cond))); - } - - void expect_resize(MockReplayImageCtx &mock_image_ctx, Context **on_finish, - uint64_t size, uint64_t op_tid) { - EXPECT_CALL(*mock_image_ctx.operations, execute_resize(size, _, _, _, op_tid)) - .WillOnce(DoAll(SaveArg<3>(on_finish), - NotifyInvoke(&m_invoke_lock, &m_invoke_cond))); - } - - void expect_snap_create(MockReplayImageCtx &mock_image_ctx, - Context **on_finish, const char *snap_name, - uint64_t op_tid) { - EXPECT_CALL(*mock_image_ctx.operations, execute_snap_create(_, StrEq(snap_name), _, - op_tid, false)) - .WillOnce(DoAll(SaveArg<2>(on_finish), - NotifyInvoke(&m_invoke_lock, &m_invoke_cond))); - } - - void expect_snap_remove(MockReplayImageCtx &mock_image_ctx, - Context **on_finish, const char *snap_name) { - EXPECT_CALL(*mock_image_ctx.operations, execute_snap_remove(_, StrEq(snap_name), _)) - .WillOnce(DoAll(SaveArg<2>(on_finish), - NotifyInvoke(&m_invoke_lock, &m_invoke_cond))); - } - - void expect_snap_rename(MockReplayImageCtx &mock_image_ctx, - Context **on_finish, uint64_t snap_id, - const char *snap_name) { - EXPECT_CALL(*mock_image_ctx.operations, execute_snap_rename(snap_id, StrEq(snap_name), _)) - .WillOnce(DoAll(SaveArg<2>(on_finish), - NotifyInvoke(&m_invoke_lock, &m_invoke_cond))); - } - - void expect_snap_protect(MockReplayImageCtx &mock_image_ctx, - Context **on_finish, const char *snap_name) { - EXPECT_CALL(*mock_image_ctx.operations, execute_snap_protect(_, StrEq(snap_name), _)) - .WillOnce(DoAll(SaveArg<2>(on_finish), - NotifyInvoke(&m_invoke_lock, &m_invoke_cond))); - } - - void expect_snap_unprotect(MockReplayImageCtx &mock_image_ctx, - Context **on_finish, const char *snap_name) { - EXPECT_CALL(*mock_image_ctx.operations, execute_snap_unprotect(_, StrEq(snap_name), _)) - .WillOnce(DoAll(SaveArg<2>(on_finish), - NotifyInvoke(&m_invoke_lock, &m_invoke_cond))); - } - - void expect_snap_rollback(MockReplayImageCtx &mock_image_ctx, - Context **on_finish, const char *snap_name) { - EXPECT_CALL(*mock_image_ctx.operations, execute_snap_rollback(_, StrEq(snap_name), _, _)) - .WillOnce(DoAll(SaveArg<3>(on_finish), - NotifyInvoke(&m_invoke_lock, &m_invoke_cond))); - } - - void expect_update_features(MockReplayImageCtx &mock_image_ctx, Context **on_finish, - uint64_t features, bool enabled, uint64_t op_tid) { - EXPECT_CALL(*mock_image_ctx.operations, execute_update_features(features, enabled, _, op_tid)) - .WillOnce(DoAll(SaveArg<2>(on_finish), - NotifyInvoke(&m_invoke_lock, &m_invoke_cond))); - } - - void expect_metadata_set(MockReplayImageCtx &mock_image_ctx, - Context **on_finish, const char *key, - const char *value) { - EXPECT_CALL(*mock_image_ctx.operations, execute_metadata_set(StrEq(key), - StrEq(value), _)) - .WillOnce(DoAll(SaveArg<2>(on_finish), - NotifyInvoke(&m_invoke_lock, &m_invoke_cond))); - } - - void expect_metadata_remove(MockReplayImageCtx &mock_image_ctx, - Context **on_finish, const char *key) { - EXPECT_CALL(*mock_image_ctx.operations, execute_metadata_remove(StrEq(key), _)) - .WillOnce(DoAll(SaveArg<1>(on_finish), - NotifyInvoke(&m_invoke_lock, &m_invoke_cond))); - } - - void expect_refresh_image(MockReplayImageCtx &mock_image_ctx, bool required, - int r) { - EXPECT_CALL(*mock_image_ctx.state, is_refresh_required()) - .WillOnce(Return(required)); - if (required) { - EXPECT_CALL(*mock_image_ctx.state, refresh(_)) - .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue)); - } - } - - void when_process(MockJournalReplay &mock_journal_replay, - EventEntry &&event_entry, Context *on_ready, - Context *on_safe) { - bufferlist bl; - ::encode(event_entry, bl); - - bufferlist::iterator it = bl.begin(); - when_process(mock_journal_replay, &it, on_ready, on_safe); - } - - void when_process(MockJournalReplay &mock_journal_replay, - bufferlist::iterator *it, Context *on_ready, - Context *on_safe) { - EventEntry event_entry; - int r = mock_journal_replay.decode(it, &event_entry); - ASSERT_EQ(0, r); - - mock_journal_replay.process(event_entry, on_ready, on_safe); - } - - void when_complete(MockReplayImageCtx &mock_image_ctx, - io::AioCompletion *aio_comp, int r) { - aio_comp->get(); - aio_comp->init_time(mock_image_ctx.image_ctx, librbd::io::AIO_TYPE_NONE); - aio_comp->set_request_count(1); - aio_comp->complete_request(r); - } - - int when_flush(MockJournalReplay &mock_journal_replay) { - C_SaferCond ctx; - mock_journal_replay.flush(&ctx); - return ctx.wait(); - } - - int when_shut_down(MockJournalReplay &mock_journal_replay, bool cancel_ops) { - C_SaferCond ctx; - mock_journal_replay.shut_down(cancel_ops, &ctx); - return ctx.wait(); - } - - void when_replay_op_ready(MockJournalReplay &mock_journal_replay, - uint64_t op_tid, Context *on_resume) { - mock_journal_replay.replay_op_ready(op_tid, on_resume); - } - - void wait_for_op_invoked(Context **on_finish, int r) { - { - Mutex::Locker locker(m_invoke_lock); - while (*on_finish == nullptr) { - m_invoke_cond.Wait(m_invoke_lock); - } - } - (*on_finish)->complete(r); - } - - bufferlist to_bl(const std::string &str) { - bufferlist bl; - bl.append(str); - return bl; - } - - Mutex m_invoke_lock; - Cond m_invoke_cond; -}; - -TEST_F(TestMockJournalReplay, AioDiscard) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - MockIoImageRequest mock_io_image_request; - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - io::AioCompletion *aio_comp; - C_SaferCond on_ready; - C_SaferCond on_safe; - expect_aio_discard(mock_io_image_request, &aio_comp, 123, 456, ictx->skip_partial_discard); - when_process(mock_journal_replay, - EventEntry{AioDiscardEvent(123, 456, ictx->skip_partial_discard)}, - &on_ready, &on_safe); - - when_complete(mock_image_ctx, aio_comp, 0); - ASSERT_EQ(0, on_ready.wait()); - - expect_aio_flush(mock_image_ctx, mock_io_image_request, 0); - ASSERT_EQ(0, when_shut_down(mock_journal_replay, false)); - ASSERT_EQ(0, on_safe.wait()); -} - -TEST_F(TestMockJournalReplay, AioWrite) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - MockIoImageRequest mock_io_image_request; - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - io::AioCompletion *aio_comp; - C_SaferCond on_ready; - C_SaferCond on_safe; - expect_aio_write(mock_io_image_request, &aio_comp, 123, 456, "test"); - when_process(mock_journal_replay, - EventEntry{AioWriteEvent(123, 456, to_bl("test"))}, - &on_ready, &on_safe); - - when_complete(mock_image_ctx, aio_comp, 0); - ASSERT_EQ(0, on_ready.wait()); - - expect_aio_flush(mock_image_ctx, mock_io_image_request, 0); - ASSERT_EQ(0, when_shut_down(mock_journal_replay, false)); - ASSERT_EQ(0, on_safe.wait()); -} - -TEST_F(TestMockJournalReplay, AioFlush) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - MockIoImageRequest mock_io_image_request; - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - io::AioCompletion *aio_comp; - C_SaferCond on_ready; - C_SaferCond on_safe; - expect_aio_flush(mock_io_image_request, &aio_comp); - when_process(mock_journal_replay, EventEntry{AioFlushEvent()}, - &on_ready, &on_safe); - - when_complete(mock_image_ctx, aio_comp, 0); - ASSERT_EQ(0, on_safe.wait()); - - ASSERT_EQ(0, when_shut_down(mock_journal_replay, false)); - ASSERT_EQ(0, on_ready.wait()); -} - -TEST_F(TestMockJournalReplay, AioWriteSame) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - MockIoImageRequest mock_io_image_request; - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - io::AioCompletion *aio_comp; - C_SaferCond on_ready; - C_SaferCond on_safe; - expect_aio_writesame(mock_io_image_request, &aio_comp, 123, 456, "333"); - when_process(mock_journal_replay, - EventEntry{AioWriteSameEvent(123, 456, to_bl("333"))}, - &on_ready, &on_safe); - - when_complete(mock_image_ctx, aio_comp, 0); - ASSERT_EQ(0, on_ready.wait()); - - expect_aio_flush(mock_image_ctx, mock_io_image_request, 0); - ASSERT_EQ(0, when_shut_down(mock_journal_replay, false)); - ASSERT_EQ(0, on_safe.wait()); -} - - -TEST_F(TestMockJournalReplay, AioCompareAndWrite) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_write_journal_replay(mock_image_ctx); - MockJournalReplay mock_compare_and_write_journal_replay(mock_image_ctx); - MockJournalReplay mock_mis_compare_and_write_journal_replay(mock_image_ctx); - MockIoImageRequest mock_io_image_request; - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - io::AioCompletion *aio_comp; - C_SaferCond on_ready; - C_SaferCond on_safe; - expect_aio_write(mock_io_image_request, &aio_comp, 512, 512, "test"); - when_process(mock_write_journal_replay, - EventEntry{AioWriteEvent(512, 512, to_bl("test"))}, - &on_ready, &on_safe); - - when_complete(mock_image_ctx, aio_comp, 0); - ASSERT_EQ(0, on_ready.wait()); - - expect_aio_flush(mock_image_ctx, mock_io_image_request, 0); - ASSERT_EQ(0, when_shut_down(mock_write_journal_replay, false)); - ASSERT_EQ(0, on_safe.wait()); - - expect_aio_compare_and_write(mock_io_image_request, &aio_comp, - 512, 512, "test", "test", nullptr); - when_process(mock_compare_and_write_journal_replay, - EventEntry{AioCompareAndWriteEvent(512, 512, to_bl("test"), - to_bl("test"))}, &on_ready, &on_safe); - - when_complete(mock_image_ctx, aio_comp, 0); - ASSERT_EQ(0, on_ready.wait()); - - expect_aio_flush(mock_image_ctx, mock_io_image_request, 0); - ASSERT_EQ(0, when_shut_down(mock_compare_and_write_journal_replay, false)); - ASSERT_EQ(0, on_safe.wait()); - - expect_aio_compare_and_write(mock_io_image_request, &aio_comp, - 512, 512, "111", "test", nullptr); - when_process(mock_mis_compare_and_write_journal_replay, - EventEntry{AioCompareAndWriteEvent(512, 512, to_bl("111"), - to_bl("test"))}, &on_ready, &on_safe); - - when_complete(mock_image_ctx, aio_comp, 0); - ASSERT_EQ(0, on_ready.wait()); - - expect_aio_flush(mock_image_ctx, mock_io_image_request, 0); - ASSERT_EQ(0, when_shut_down(mock_mis_compare_and_write_journal_replay, false)); - ASSERT_EQ(0, on_safe.wait()); - -} - -TEST_F(TestMockJournalReplay, IOError) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - MockIoImageRequest mock_io_image_request; - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - io::AioCompletion *aio_comp; - C_SaferCond on_ready; - C_SaferCond on_safe; - expect_aio_discard(mock_io_image_request, &aio_comp, 123, 456, ictx->skip_partial_discard); - when_process(mock_journal_replay, - EventEntry{AioDiscardEvent(123, 456, ictx->skip_partial_discard)}, - &on_ready, &on_safe); - - when_complete(mock_image_ctx, aio_comp, -EINVAL); - ASSERT_EQ(-EINVAL, on_safe.wait()); - - expect_aio_flush(mock_image_ctx, mock_io_image_request, 0); - ASSERT_EQ(0, when_shut_down(mock_journal_replay, false)); - ASSERT_EQ(0, on_ready.wait()); -} - -TEST_F(TestMockJournalReplay, SoftFlushIO) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - MockIoImageRequest mock_io_image_request; - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - const size_t io_count = 32; - C_SaferCond on_safes[io_count]; - for (size_t i = 0; i < io_count; ++i) { - io::AioCompletion *aio_comp; - io::AioCompletion *flush_comp = nullptr; - C_SaferCond on_ready; - expect_aio_discard(mock_io_image_request, &aio_comp, 123, 456, ictx->skip_partial_discard); - if (i == io_count - 1) { - expect_aio_flush(mock_io_image_request, &flush_comp); - } - when_process(mock_journal_replay, - EventEntry{AioDiscardEvent(123, 456, ictx->skip_partial_discard)}, - &on_ready, &on_safes[i]); - when_complete(mock_image_ctx, aio_comp, 0); - ASSERT_EQ(0, on_ready.wait()); - - if (flush_comp != nullptr) { - when_complete(mock_image_ctx, flush_comp, 0); - } - } - for (auto &on_safe : on_safes) { - ASSERT_EQ(0, on_safe.wait()); - } - - ASSERT_EQ(0, when_shut_down(mock_journal_replay, false)); -} - -TEST_F(TestMockJournalReplay, PauseIO) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - MockIoImageRequest mock_io_image_request; - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - const size_t io_count = 64; - std::list flush_comps; - C_SaferCond on_safes[io_count]; - for (size_t i = 0; i < io_count; ++i) { - io::AioCompletion *aio_comp; - C_SaferCond on_ready; - expect_aio_write(mock_io_image_request, &aio_comp, 123, 456, "test"); - if ((i + 1) % 32 == 0) { - flush_comps.push_back(nullptr); - expect_aio_flush(mock_io_image_request, &flush_comps.back()); - } - when_process(mock_journal_replay, - EventEntry{AioWriteEvent(123, 456, to_bl("test"))}, - &on_ready, &on_safes[i]); - when_complete(mock_image_ctx, aio_comp, 0); - if (i < io_count - 1) { - ASSERT_EQ(0, on_ready.wait()); - } else { - for (auto flush_comp : flush_comps) { - when_complete(mock_image_ctx, flush_comp, 0); - } - ASSERT_EQ(0, on_ready.wait()); - } - } - for (auto &on_safe : on_safes) { - ASSERT_EQ(0, on_safe.wait()); - } - - ASSERT_EQ(0, when_shut_down(mock_journal_replay, false)); -} - -TEST_F(TestMockJournalReplay, Flush) { - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - MockIoImageRequest mock_io_image_request; - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - io::AioCompletion *aio_comp = nullptr; - C_SaferCond on_ready; - C_SaferCond on_safe; - expect_aio_discard(mock_io_image_request, &aio_comp, 123, 456, ictx->skip_partial_discard); - when_process(mock_journal_replay, - EventEntry{AioDiscardEvent(123, 456, ictx->skip_partial_discard)}, - &on_ready, &on_safe); - - when_complete(mock_image_ctx, aio_comp, 0); - ASSERT_EQ(0, on_ready.wait()); - - expect_aio_flush(mock_image_ctx, mock_io_image_request, 0); - ASSERT_EQ(0, when_flush(mock_journal_replay)); - ASSERT_EQ(0, on_safe.wait()); -} - -TEST_F(TestMockJournalReplay, OpFinishError) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - C_SaferCond on_start_ready; - C_SaferCond on_start_safe; - when_process(mock_journal_replay, - EventEntry{SnapRemoveEvent(123, - cls::rbd::UserSnapshotNamespace(), - "snap")}, - &on_start_ready, - &on_start_safe); - ASSERT_EQ(0, on_start_ready.wait()); - - C_SaferCond on_finish_ready; - C_SaferCond on_finish_safe; - when_process(mock_journal_replay, EventEntry{OpFinishEvent(123, -EIO)}, - &on_finish_ready, &on_finish_safe); - - ASSERT_EQ(-EIO, on_start_safe.wait()); - ASSERT_EQ(-EIO, on_finish_safe.wait()); - ASSERT_EQ(0, on_finish_ready.wait()); -} - -TEST_F(TestMockJournalReplay, BlockedOpFinishError) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - Context *on_finish = nullptr; - expect_refresh_image(mock_image_ctx, false, 0); - expect_snap_create(mock_image_ctx, &on_finish, "snap", 123); - - C_SaferCond on_start_ready; - C_SaferCond on_start_safe; - when_process(mock_journal_replay, - EventEntry{SnapCreateEvent(123, - cls::rbd::UserSnapshotNamespace(), - "snap")}, - &on_start_ready, - &on_start_safe); - - C_SaferCond on_resume; - when_replay_op_ready(mock_journal_replay, 123, &on_resume); - ASSERT_EQ(0, on_start_ready.wait()); - - C_SaferCond on_finish_ready; - C_SaferCond on_finish_safe; - when_process(mock_journal_replay, EventEntry{OpFinishEvent(123, -EBADMSG)}, - &on_finish_ready, &on_finish_safe); - - ASSERT_EQ(-EBADMSG, on_resume.wait()); - wait_for_op_invoked(&on_finish, -ESTALE); - - ASSERT_EQ(-ESTALE, on_start_safe.wait()); - ASSERT_EQ(-ESTALE, on_finish_safe.wait()); - ASSERT_EQ(0, on_finish_ready.wait()); -} - -TEST_F(TestMockJournalReplay, MissingOpFinishEvent) { - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - expect_op_work_queue(mock_image_ctx); - - EXPECT_CALL(*mock_image_ctx.state, is_refresh_required()) - .WillRepeatedly(Return(false)); - - InSequence seq; - Context *on_snap_create_finish = nullptr; - expect_snap_create(mock_image_ctx, &on_snap_create_finish, "snap", 123); - - Context *on_snap_remove_finish = nullptr; - expect_snap_remove(mock_image_ctx, &on_snap_remove_finish, "snap"); - - C_SaferCond on_snap_remove_ready; - C_SaferCond on_snap_remove_safe; - when_process(mock_journal_replay, - EventEntry{SnapRemoveEvent(122, - cls::rbd::UserSnapshotNamespace(), - "snap")}, - &on_snap_remove_ready, - &on_snap_remove_safe); - ASSERT_EQ(0, on_snap_remove_ready.wait()); - - C_SaferCond on_snap_create_ready; - C_SaferCond on_snap_create_safe; - when_process(mock_journal_replay, - EventEntry{SnapCreateEvent(123, - cls::rbd::UserSnapshotNamespace(), - "snap")}, - &on_snap_create_ready, - &on_snap_create_safe); - - C_SaferCond on_shut_down; - mock_journal_replay.shut_down(false, &on_shut_down); - - wait_for_op_invoked(&on_snap_remove_finish, 0); - ASSERT_EQ(0, on_snap_remove_safe.wait()); - - C_SaferCond on_snap_create_resume; - when_replay_op_ready(mock_journal_replay, 123, &on_snap_create_resume); - ASSERT_EQ(0, on_snap_create_resume.wait()); - - wait_for_op_invoked(&on_snap_create_finish, 0); - ASSERT_EQ(0, on_snap_create_ready.wait()); - ASSERT_EQ(0, on_snap_create_safe.wait()); - - ASSERT_EQ(0, on_shut_down.wait()); -} - -TEST_F(TestMockJournalReplay, MissingOpFinishEventCancelOps) { - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - Context *on_snap_create_finish = nullptr; - expect_refresh_image(mock_image_ctx, false, 0); - expect_snap_create(mock_image_ctx, &on_snap_create_finish, "snap", 123); - - C_SaferCond on_snap_remove_ready; - C_SaferCond on_snap_remove_safe; - when_process(mock_journal_replay, - EventEntry{SnapRemoveEvent(122, - cls::rbd::UserSnapshotNamespace(), - "snap")}, - &on_snap_remove_ready, - &on_snap_remove_safe); - ASSERT_EQ(0, on_snap_remove_ready.wait()); - - C_SaferCond on_snap_create_ready; - C_SaferCond on_snap_create_safe; - when_process(mock_journal_replay, - EventEntry{SnapCreateEvent(123, - cls::rbd::UserSnapshotNamespace(), - "snap")}, - &on_snap_create_ready, - &on_snap_create_safe); - - C_SaferCond on_resume; - when_replay_op_ready(mock_journal_replay, 123, &on_resume); - ASSERT_EQ(0, on_snap_create_ready.wait()); - - C_SaferCond on_shut_down; - mock_journal_replay.shut_down(true, &on_shut_down); - - ASSERT_EQ(-ERESTART, on_resume.wait()); - on_snap_create_finish->complete(-ERESTART); - ASSERT_EQ(-ERESTART, on_snap_create_safe.wait()); - - ASSERT_EQ(-ERESTART, on_snap_remove_safe.wait()); - ASSERT_EQ(0, on_shut_down.wait()); -} - -TEST_F(TestMockJournalReplay, UnknownOpFinishEvent) { - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - C_SaferCond on_ready; - C_SaferCond on_safe; - when_process(mock_journal_replay, EventEntry{OpFinishEvent(123, 0)}, - &on_ready, &on_safe); - - ASSERT_EQ(0, on_safe.wait()); - ASSERT_EQ(0, on_ready.wait()); -} - -TEST_F(TestMockJournalReplay, OpEventError) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - Context *on_finish = nullptr; - expect_refresh_image(mock_image_ctx, false, 0); - expect_snap_remove(mock_image_ctx, &on_finish, "snap"); - - C_SaferCond on_start_ready; - C_SaferCond on_start_safe; - when_process(mock_journal_replay, - EventEntry{SnapRemoveEvent(123, - cls::rbd::UserSnapshotNamespace(), - "snap")}, - &on_start_ready, - &on_start_safe); - ASSERT_EQ(0, on_start_ready.wait()); - - C_SaferCond on_finish_ready; - C_SaferCond on_finish_safe; - when_process(mock_journal_replay, EventEntry{OpFinishEvent(123, 0)}, - &on_finish_ready, &on_finish_safe); - - wait_for_op_invoked(&on_finish, -EINVAL); - ASSERT_EQ(-EINVAL, on_start_safe.wait()); - ASSERT_EQ(0, on_finish_ready.wait()); - ASSERT_EQ(-EINVAL, on_finish_safe.wait()); -} - -TEST_F(TestMockJournalReplay, SnapCreateEvent) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - Context *on_finish = nullptr; - expect_refresh_image(mock_image_ctx, false, 0); - expect_snap_create(mock_image_ctx, &on_finish, "snap", 123); - - C_SaferCond on_start_ready; - C_SaferCond on_start_safe; - when_process(mock_journal_replay, - EventEntry{SnapCreateEvent(123, - cls::rbd::UserSnapshotNamespace(), - "snap")}, - &on_start_ready, - &on_start_safe); - - C_SaferCond on_resume; - when_replay_op_ready(mock_journal_replay, 123, &on_resume); - ASSERT_EQ(0, on_start_ready.wait()); - - C_SaferCond on_finish_ready; - C_SaferCond on_finish_safe; - when_process(mock_journal_replay, EventEntry{OpFinishEvent(123, 0)}, - &on_finish_ready, &on_finish_safe); - - ASSERT_EQ(0, on_resume.wait()); - wait_for_op_invoked(&on_finish, 0); - - ASSERT_EQ(0, on_start_safe.wait()); - ASSERT_EQ(0, on_finish_ready.wait()); - ASSERT_EQ(0, on_finish_safe.wait()); -} - -TEST_F(TestMockJournalReplay, SnapCreateEventExists) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - Context *on_finish = nullptr; - expect_refresh_image(mock_image_ctx, false, 0); - expect_snap_create(mock_image_ctx, &on_finish, "snap", 123); - - C_SaferCond on_start_ready; - C_SaferCond on_start_safe; - when_process(mock_journal_replay, - EventEntry{SnapCreateEvent(123, - cls::rbd::UserSnapshotNamespace(), - "snap")}, - &on_start_ready, - &on_start_safe); - - wait_for_op_invoked(&on_finish, -EEXIST); - ASSERT_EQ(0, on_start_ready.wait()); - - C_SaferCond on_finish_ready; - C_SaferCond on_finish_safe; - when_process(mock_journal_replay, EventEntry{OpFinishEvent(123, 0)}, - &on_finish_ready, &on_finish_safe); - - ASSERT_EQ(0, on_start_safe.wait()); - ASSERT_EQ(0, on_finish_ready.wait()); - ASSERT_EQ(0, on_finish_safe.wait()); -} - -TEST_F(TestMockJournalReplay, SnapRemoveEvent) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - Context *on_finish = nullptr; - expect_refresh_image(mock_image_ctx, false, 0); - expect_snap_remove(mock_image_ctx, &on_finish, "snap"); - - C_SaferCond on_start_ready; - C_SaferCond on_start_safe; - when_process(mock_journal_replay, - EventEntry{SnapRemoveEvent(123, - cls::rbd::UserSnapshotNamespace(), - "snap")}, - &on_start_ready, - &on_start_safe); - ASSERT_EQ(0, on_start_ready.wait()); - - C_SaferCond on_finish_ready; - C_SaferCond on_finish_safe; - when_process(mock_journal_replay, EventEntry{OpFinishEvent(123, 0)}, - &on_finish_ready, &on_finish_safe); - - wait_for_op_invoked(&on_finish, 0); - ASSERT_EQ(0, on_start_safe.wait()); - ASSERT_EQ(0, on_finish_ready.wait()); - ASSERT_EQ(0, on_finish_safe.wait()); -} - -TEST_F(TestMockJournalReplay, SnapRemoveEventDNE) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - Context *on_finish = nullptr; - expect_refresh_image(mock_image_ctx, false, 0); - expect_snap_remove(mock_image_ctx, &on_finish, "snap"); - - C_SaferCond on_start_ready; - C_SaferCond on_start_safe; - when_process(mock_journal_replay, - EventEntry{SnapRemoveEvent(123, - cls::rbd::UserSnapshotNamespace(), - "snap")}, - &on_start_ready, - &on_start_safe); - ASSERT_EQ(0, on_start_ready.wait()); - - C_SaferCond on_finish_ready; - C_SaferCond on_finish_safe; - when_process(mock_journal_replay, EventEntry{OpFinishEvent(123, 0)}, - &on_finish_ready, &on_finish_safe); - - wait_for_op_invoked(&on_finish, -ENOENT); - ASSERT_EQ(0, on_start_safe.wait()); - ASSERT_EQ(0, on_finish_ready.wait()); - ASSERT_EQ(0, on_finish_safe.wait()); -} - -TEST_F(TestMockJournalReplay, SnapRenameEvent) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - Context *on_finish = nullptr; - expect_refresh_image(mock_image_ctx, false, 0); - expect_snap_rename(mock_image_ctx, &on_finish, 234, "snap"); - - C_SaferCond on_start_ready; - C_SaferCond on_start_safe; - when_process(mock_journal_replay, - EventEntry{SnapRenameEvent(123, 234, "snap1", "snap")}, - &on_start_ready, &on_start_safe); - ASSERT_EQ(0, on_start_ready.wait()); - - C_SaferCond on_finish_ready; - C_SaferCond on_finish_safe; - when_process(mock_journal_replay, EventEntry{OpFinishEvent(123, 0)}, - &on_finish_ready, &on_finish_safe); - - wait_for_op_invoked(&on_finish, 0); - ASSERT_EQ(0, on_start_safe.wait()); - ASSERT_EQ(0, on_finish_ready.wait()); - ASSERT_EQ(0, on_finish_safe.wait()); -} - -TEST_F(TestMockJournalReplay, SnapRenameEventExists) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - Context *on_finish = nullptr; - expect_refresh_image(mock_image_ctx, false, 0); - expect_snap_rename(mock_image_ctx, &on_finish, 234, "snap"); - - C_SaferCond on_start_ready; - C_SaferCond on_start_safe; - when_process(mock_journal_replay, - EventEntry{SnapRenameEvent(123, 234, "snap1", "snap")}, - &on_start_ready, &on_start_safe); - ASSERT_EQ(0, on_start_ready.wait()); - - C_SaferCond on_finish_ready; - C_SaferCond on_finish_safe; - when_process(mock_journal_replay, EventEntry{OpFinishEvent(123, 0)}, - &on_finish_ready, &on_finish_safe); - - wait_for_op_invoked(&on_finish, -EEXIST); - ASSERT_EQ(0, on_start_safe.wait()); - ASSERT_EQ(0, on_finish_ready.wait()); - ASSERT_EQ(0, on_finish_safe.wait()); -} - -TEST_F(TestMockJournalReplay, SnapProtectEvent) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - Context *on_finish = nullptr; - expect_refresh_image(mock_image_ctx, false, 0); - expect_snap_protect(mock_image_ctx, &on_finish, "snap"); - - C_SaferCond on_start_ready; - C_SaferCond on_start_safe; - when_process(mock_journal_replay, - EventEntry{SnapProtectEvent(123, - cls::rbd::UserSnapshotNamespace(), - "snap")}, - &on_start_ready, - &on_start_safe); - ASSERT_EQ(0, on_start_ready.wait()); - - C_SaferCond on_finish_ready; - C_SaferCond on_finish_safe; - when_process(mock_journal_replay, EventEntry{OpFinishEvent(123, 0)}, - &on_finish_ready, &on_finish_safe); - - wait_for_op_invoked(&on_finish, 0); - ASSERT_EQ(0, on_start_safe.wait()); - ASSERT_EQ(0, on_finish_ready.wait()); - ASSERT_EQ(0, on_finish_safe.wait()); -} - -TEST_F(TestMockJournalReplay, SnapProtectEventBusy) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - Context *on_finish = nullptr; - expect_refresh_image(mock_image_ctx, false, 0); - expect_snap_protect(mock_image_ctx, &on_finish, "snap"); - - C_SaferCond on_start_ready; - C_SaferCond on_start_safe; - when_process(mock_journal_replay, - EventEntry{SnapProtectEvent(123, - cls::rbd::UserSnapshotNamespace(), - "snap")}, - &on_start_ready, - &on_start_safe); - ASSERT_EQ(0, on_start_ready.wait()); - - C_SaferCond on_finish_ready; - C_SaferCond on_finish_safe; - when_process(mock_journal_replay, EventEntry{OpFinishEvent(123, 0)}, - &on_finish_ready, &on_finish_safe); - - wait_for_op_invoked(&on_finish, -EBUSY); - ASSERT_EQ(0, on_start_safe.wait()); - ASSERT_EQ(0, on_finish_ready.wait()); - ASSERT_EQ(0, on_finish_safe.wait()); -} - -TEST_F(TestMockJournalReplay, SnapUnprotectEvent) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - Context *on_finish = nullptr; - expect_refresh_image(mock_image_ctx, false, 0); - expect_snap_unprotect(mock_image_ctx, &on_finish, "snap"); - - C_SaferCond on_start_ready; - C_SaferCond on_start_safe; - when_process(mock_journal_replay, - EventEntry{SnapUnprotectEvent(123, - cls::rbd::UserSnapshotNamespace(), - "snap")}, - &on_start_ready, - &on_start_safe); - ASSERT_EQ(0, on_start_ready.wait()); - - C_SaferCond on_finish_ready; - C_SaferCond on_finish_safe; - when_process(mock_journal_replay, EventEntry{OpFinishEvent(123, 0)}, - &on_finish_ready, &on_finish_safe); - - wait_for_op_invoked(&on_finish, 0); - ASSERT_EQ(0, on_start_safe.wait()); - ASSERT_EQ(0, on_finish_ready.wait()); - ASSERT_EQ(0, on_finish_safe.wait()); -} - -TEST_F(TestMockJournalReplay, SnapUnprotectOpFinishBusy) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - C_SaferCond on_start_ready; - C_SaferCond on_start_safe; - when_process(mock_journal_replay, - EventEntry{SnapUnprotectEvent(123, - cls::rbd::UserSnapshotNamespace(), - "snap")}, - &on_start_ready, - &on_start_safe); - ASSERT_EQ(0, on_start_ready.wait()); - - // aborts the snap unprotect op if image had children - C_SaferCond on_finish_ready; - C_SaferCond on_finish_safe; - when_process(mock_journal_replay, EventEntry{OpFinishEvent(123, -EBUSY)}, - &on_finish_ready, &on_finish_safe); - - ASSERT_EQ(0, on_start_safe.wait()); - ASSERT_EQ(0, on_finish_safe.wait()); - ASSERT_EQ(0, on_finish_ready.wait()); -} - -TEST_F(TestMockJournalReplay, SnapUnprotectEventInvalid) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - Context *on_finish = nullptr; - expect_refresh_image(mock_image_ctx, false, 0); - expect_snap_unprotect(mock_image_ctx, &on_finish, "snap"); - - C_SaferCond on_start_ready; - C_SaferCond on_start_safe; - when_process(mock_journal_replay, - EventEntry{SnapUnprotectEvent(123, - cls::rbd::UserSnapshotNamespace(), - "snap")}, - &on_start_ready, - &on_start_safe); - ASSERT_EQ(0, on_start_ready.wait()); - - C_SaferCond on_finish_ready; - C_SaferCond on_finish_safe; - when_process(mock_journal_replay, EventEntry{OpFinishEvent(123, 0)}, - &on_finish_ready, &on_finish_safe); - - wait_for_op_invoked(&on_finish, -EINVAL); - ASSERT_EQ(0, on_start_safe.wait()); - ASSERT_EQ(0, on_finish_ready.wait()); - ASSERT_EQ(0, on_finish_safe.wait()); -} - -TEST_F(TestMockJournalReplay, SnapRollbackEvent) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - Context *on_finish = nullptr; - expect_refresh_image(mock_image_ctx, false, 0); - expect_snap_rollback(mock_image_ctx, &on_finish, "snap"); - - C_SaferCond on_start_ready; - C_SaferCond on_start_safe; - when_process(mock_journal_replay, - EventEntry{SnapRollbackEvent(123, - cls::rbd::UserSnapshotNamespace(), - "snap")}, - &on_start_ready, - &on_start_safe); - ASSERT_EQ(0, on_start_ready.wait()); - - C_SaferCond on_finish_ready; - C_SaferCond on_finish_safe; - when_process(mock_journal_replay, EventEntry{OpFinishEvent(123, 0)}, - &on_finish_ready, &on_finish_safe); - - wait_for_op_invoked(&on_finish, 0); - ASSERT_EQ(0, on_start_safe.wait()); - ASSERT_EQ(0, on_finish_ready.wait()); - ASSERT_EQ(0, on_finish_safe.wait()); -} - -TEST_F(TestMockJournalReplay, RenameEvent) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - Context *on_finish = nullptr; - expect_refresh_image(mock_image_ctx, false, 0); - expect_rename(mock_image_ctx, &on_finish, "image"); - - C_SaferCond on_start_ready; - C_SaferCond on_start_safe; - when_process(mock_journal_replay, EventEntry{RenameEvent(123, "image")}, - &on_start_ready, &on_start_safe); - ASSERT_EQ(0, on_start_ready.wait()); - - C_SaferCond on_finish_ready; - C_SaferCond on_finish_safe; - when_process(mock_journal_replay, EventEntry{OpFinishEvent(123, 0)}, - &on_finish_ready, &on_finish_safe); - - wait_for_op_invoked(&on_finish, 0); - ASSERT_EQ(0, on_start_safe.wait()); - ASSERT_EQ(0, on_finish_ready.wait()); - ASSERT_EQ(0, on_finish_safe.wait()); -} - -TEST_F(TestMockJournalReplay, RenameEventExists) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - Context *on_finish = nullptr; - expect_refresh_image(mock_image_ctx, false, 0); - expect_rename(mock_image_ctx, &on_finish, "image"); - - C_SaferCond on_start_ready; - C_SaferCond on_start_safe; - when_process(mock_journal_replay, EventEntry{RenameEvent(123, "image")}, - &on_start_ready, &on_start_safe); - ASSERT_EQ(0, on_start_ready.wait()); - - C_SaferCond on_finish_ready; - C_SaferCond on_finish_safe; - when_process(mock_journal_replay, EventEntry{OpFinishEvent(123, 0)}, - &on_finish_ready, &on_finish_safe); - - wait_for_op_invoked(&on_finish, -EEXIST); - ASSERT_EQ(0, on_start_safe.wait()); - ASSERT_EQ(0, on_finish_ready.wait()); - ASSERT_EQ(0, on_finish_safe.wait()); -} - -TEST_F(TestMockJournalReplay, ResizeEvent) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - Context *on_finish = nullptr; - expect_refresh_image(mock_image_ctx, false, 0); - expect_resize(mock_image_ctx, &on_finish, 234, 123); - - C_SaferCond on_start_ready; - C_SaferCond on_start_safe; - when_process(mock_journal_replay, EventEntry{ResizeEvent(123, 234)}, - &on_start_ready, &on_start_safe); - - C_SaferCond on_resume; - when_replay_op_ready(mock_journal_replay, 123, &on_resume); - ASSERT_EQ(0, on_start_ready.wait()); - - C_SaferCond on_finish_ready; - C_SaferCond on_finish_safe; - when_process(mock_journal_replay, EventEntry{OpFinishEvent(123, 0)}, - &on_finish_ready, &on_finish_safe); - - ASSERT_EQ(0, on_resume.wait()); - wait_for_op_invoked(&on_finish, 0); - - ASSERT_EQ(0, on_start_safe.wait()); - ASSERT_EQ(0, on_finish_ready.wait()); - ASSERT_EQ(0, on_finish_safe.wait()); -} - -TEST_F(TestMockJournalReplay, FlattenEvent) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - Context *on_finish = nullptr; - expect_refresh_image(mock_image_ctx, false, 0); - expect_flatten(mock_image_ctx, &on_finish); - - C_SaferCond on_start_ready; - C_SaferCond on_start_safe; - when_process(mock_journal_replay, EventEntry{FlattenEvent(123)}, - &on_start_ready, &on_start_safe); - ASSERT_EQ(0, on_start_ready.wait()); - - C_SaferCond on_finish_ready; - C_SaferCond on_finish_safe; - when_process(mock_journal_replay, EventEntry{OpFinishEvent(123, 0)}, - &on_finish_ready, &on_finish_safe); - - wait_for_op_invoked(&on_finish, 0); - ASSERT_EQ(0, on_start_safe.wait()); - ASSERT_EQ(0, on_finish_ready.wait()); - ASSERT_EQ(0, on_finish_safe.wait()); -} - -TEST_F(TestMockJournalReplay, FlattenEventInvalid) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - Context *on_finish = nullptr; - expect_refresh_image(mock_image_ctx, false, 0); - expect_flatten(mock_image_ctx, &on_finish); - - C_SaferCond on_start_ready; - C_SaferCond on_start_safe; - when_process(mock_journal_replay, EventEntry{FlattenEvent(123)}, - &on_start_ready, &on_start_safe); - ASSERT_EQ(0, on_start_ready.wait()); - - C_SaferCond on_finish_ready; - C_SaferCond on_finish_safe; - when_process(mock_journal_replay, EventEntry{OpFinishEvent(123, 0)}, - &on_finish_ready, &on_finish_safe); - - wait_for_op_invoked(&on_finish, -EINVAL); - ASSERT_EQ(0, on_start_safe.wait()); - ASSERT_EQ(0, on_finish_ready.wait()); - ASSERT_EQ(0, on_finish_safe.wait()); -} - -TEST_F(TestMockJournalReplay, UpdateFeaturesEvent) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - uint64_t features = RBD_FEATURE_OBJECT_MAP | RBD_FEATURE_FAST_DIFF; - bool enabled = !ictx->test_features(features); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - Context *on_finish = nullptr; - expect_refresh_image(mock_image_ctx, false, 0); - expect_update_features(mock_image_ctx, &on_finish, features, enabled, 123); - - C_SaferCond on_start_ready; - C_SaferCond on_start_safe; - when_process(mock_journal_replay, - EventEntry{UpdateFeaturesEvent(123, features, enabled)}, - &on_start_ready, &on_start_safe); - - C_SaferCond on_resume; - when_replay_op_ready(mock_journal_replay, 123, &on_resume); - ASSERT_EQ(0, on_start_ready.wait()); - - C_SaferCond on_finish_ready; - C_SaferCond on_finish_safe; - when_process(mock_journal_replay, EventEntry{OpFinishEvent(123, 0)}, - &on_finish_ready, &on_finish_safe); - - ASSERT_EQ(0, on_resume.wait()); - wait_for_op_invoked(&on_finish, 0); - - ASSERT_EQ(0, on_start_safe.wait()); - ASSERT_EQ(0, on_finish_ready.wait()); - ASSERT_EQ(0, on_finish_safe.wait()); -} - -TEST_F(TestMockJournalReplay, MetadataSetEvent) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - Context *on_finish = nullptr; - expect_refresh_image(mock_image_ctx, false, 0); - expect_metadata_set(mock_image_ctx, &on_finish, "key", "value"); - - C_SaferCond on_start_ready; - C_SaferCond on_start_safe; - when_process(mock_journal_replay, EventEntry{MetadataSetEvent(123, "key", "value")}, - &on_start_ready, &on_start_safe); - ASSERT_EQ(0, on_start_ready.wait()); - - C_SaferCond on_finish_ready; - C_SaferCond on_finish_safe; - when_process(mock_journal_replay, EventEntry{OpFinishEvent(123, 0)}, - &on_finish_ready, &on_finish_safe); - - wait_for_op_invoked(&on_finish, 0); - ASSERT_EQ(0, on_start_safe.wait()); - ASSERT_EQ(0, on_finish_ready.wait()); - ASSERT_EQ(0, on_finish_safe.wait()); -} - -TEST_F(TestMockJournalReplay, MetadataRemoveEvent) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - Context *on_finish = nullptr; - expect_refresh_image(mock_image_ctx, false, 0); - expect_metadata_remove(mock_image_ctx, &on_finish, "key"); - - C_SaferCond on_start_ready; - C_SaferCond on_start_safe; - when_process(mock_journal_replay, EventEntry{MetadataRemoveEvent(123, "key")}, - &on_start_ready, &on_start_safe); - ASSERT_EQ(0, on_start_ready.wait()); - - C_SaferCond on_finish_ready; - C_SaferCond on_finish_safe; - when_process(mock_journal_replay, EventEntry{OpFinishEvent(123, 0)}, - &on_finish_ready, &on_finish_safe); - - wait_for_op_invoked(&on_finish, 0); - ASSERT_EQ(0, on_start_safe.wait()); - ASSERT_EQ(0, on_finish_ready.wait()); - ASSERT_EQ(0, on_finish_safe.wait()); -} - -TEST_F(TestMockJournalReplay, MetadataRemoveEventDNE) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - Context *on_finish = nullptr; - expect_refresh_image(mock_image_ctx, false, 0); - expect_metadata_remove(mock_image_ctx, &on_finish, "key"); - - C_SaferCond on_start_ready; - C_SaferCond on_start_safe; - when_process(mock_journal_replay, EventEntry{MetadataRemoveEvent(123, "key")}, - &on_start_ready, &on_start_safe); - ASSERT_EQ(0, on_start_ready.wait()); - - C_SaferCond on_finish_ready; - C_SaferCond on_finish_safe; - when_process(mock_journal_replay, EventEntry{OpFinishEvent(123, 0)}, - &on_finish_ready, &on_finish_safe); - - wait_for_op_invoked(&on_finish, -ENOENT); - ASSERT_EQ(0, on_start_safe.wait()); - ASSERT_EQ(0, on_finish_ready.wait()); - ASSERT_EQ(0, on_finish_safe.wait()); -} - -TEST_F(TestMockJournalReplay, UnknownEvent) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - - bufferlist bl; - ENCODE_START(1, 1, bl); - ::encode(static_cast(-1), bl); - ENCODE_FINISH(bl); - - bufferlist::iterator it = bl.begin(); - C_SaferCond on_ready; - C_SaferCond on_safe; - when_process(mock_journal_replay, &it, &on_ready, &on_safe); - - ASSERT_EQ(0, on_safe.wait()); - ASSERT_EQ(0, on_ready.wait()); -} - -TEST_F(TestMockJournalReplay, RefreshImageBeforeOpStart) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - Context *on_finish = nullptr; - expect_refresh_image(mock_image_ctx, true, 0); - expect_resize(mock_image_ctx, &on_finish, 234, 123); - - C_SaferCond on_start_ready; - C_SaferCond on_start_safe; - when_process(mock_journal_replay, EventEntry{ResizeEvent(123, 234)}, - &on_start_ready, &on_start_safe); - - C_SaferCond on_resume; - when_replay_op_ready(mock_journal_replay, 123, &on_resume); - ASSERT_EQ(0, on_start_ready.wait()); - - C_SaferCond on_finish_ready; - C_SaferCond on_finish_safe; - when_process(mock_journal_replay, EventEntry{OpFinishEvent(123, 0)}, - &on_finish_ready, &on_finish_safe); - - ASSERT_EQ(0, on_resume.wait()); - wait_for_op_invoked(&on_finish, 0); - - ASSERT_EQ(0, on_start_safe.wait()); - ASSERT_EQ(0, on_finish_ready.wait()); - ASSERT_EQ(0, on_finish_safe.wait()); -} - -TEST_F(TestMockJournalReplay, FlushEventAfterShutDown) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - MockIoImageRequest mock_io_image_request; - expect_op_work_queue(mock_image_ctx); - - ASSERT_EQ(0, when_shut_down(mock_journal_replay, false)); - - C_SaferCond on_ready; - C_SaferCond on_safe; - when_process(mock_journal_replay, EventEntry{AioFlushEvent()}, - &on_ready, &on_safe); - ASSERT_EQ(0, on_ready.wait()); - ASSERT_EQ(-ESHUTDOWN, on_safe.wait()); -} - -TEST_F(TestMockJournalReplay, ModifyEventAfterShutDown) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - MockIoImageRequest mock_io_image_request; - expect_op_work_queue(mock_image_ctx); - - ASSERT_EQ(0, when_shut_down(mock_journal_replay, false)); - - C_SaferCond on_ready; - C_SaferCond on_safe; - when_process(mock_journal_replay, - EventEntry{AioWriteEvent(123, 456, to_bl("test"))}, - &on_ready, &on_safe); - ASSERT_EQ(0, on_ready.wait()); - ASSERT_EQ(-ESHUTDOWN, on_safe.wait()); -} - -TEST_F(TestMockJournalReplay, OpEventAfterShutDown) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, true); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - MockIoImageRequest mock_io_image_request; - expect_op_work_queue(mock_image_ctx); - - ASSERT_EQ(0, when_shut_down(mock_journal_replay, false)); - - C_SaferCond on_ready; - C_SaferCond on_safe; - when_process(mock_journal_replay, EventEntry{RenameEvent(123, "image")}, - &on_ready, &on_safe); - ASSERT_EQ(0, on_ready.wait()); - ASSERT_EQ(-ESHUTDOWN, on_safe.wait()); -} - -TEST_F(TestMockJournalReplay, LockLostBeforeProcess) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, false); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - MockIoImageRequest mock_io_image_request; - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - C_SaferCond on_ready; - C_SaferCond on_safe; - when_process(mock_journal_replay, EventEntry{AioFlushEvent()}, - &on_ready, &on_safe); - ASSERT_EQ(0, on_ready.wait()); - ASSERT_EQ(-ECANCELED, on_safe.wait()); - - ASSERT_EQ(0, when_shut_down(mock_journal_replay, false)); -} - -TEST_F(TestMockJournalReplay, LockLostBeforeExecuteOp) { - REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); - - librbd::ImageCtx *ictx; - ASSERT_EQ(0, open_image(m_image_name, &ictx)); - - MockReplayImageCtx mock_image_ctx(*ictx); - - MockExclusiveLock mock_exclusive_lock; - mock_image_ctx.exclusive_lock = &mock_exclusive_lock; - expect_accept_ops(mock_exclusive_lock, false); - - MockJournalReplay mock_journal_replay(mock_image_ctx); - expect_op_work_queue(mock_image_ctx); - - InSequence seq; - EXPECT_CALL(mock_exclusive_lock, accept_ops()).WillOnce(Return(true)); - EXPECT_CALL(mock_exclusive_lock, accept_ops()).WillOnce(Return(true)); - expect_refresh_image(mock_image_ctx, false, 0); - - C_SaferCond on_start_ready; - C_SaferCond on_start_safe; - when_process(mock_journal_replay, EventEntry{RenameEvent(123, "image")}, - &on_start_ready, &on_start_safe); - ASSERT_EQ(0, on_start_ready.wait()); - - C_SaferCond on_finish_ready; - C_SaferCond on_finish_safe; - when_process(mock_journal_replay, EventEntry{OpFinishEvent(123, 0)}, - &on_finish_ready, &on_finish_safe); - - ASSERT_EQ(-ECANCELED, on_start_safe.wait()); - ASSERT_EQ(0, on_finish_ready.wait()); - ASSERT_EQ(-ECANCELED, on_finish_safe.wait()); -} - -} // namespace journal -} // namespace librbd