1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "test/librbd/test_mock_fixture.h"
5 #include "test/librbd/test_support.h"
6 #include "test/librbd/mock/MockImageCtx.h"
7 #include "librbd/io/ImageRequest.h"
8 #include "librbd/journal/Replay.h"
9 #include "librbd/journal/Types.h"
10 #include "gmock/gmock.h"
11 #include "gtest/gtest.h"
12 #include <boost/scope_exit.hpp>
18 struct MockReplayImageCtx
: public MockImageCtx
{
19 MockReplayImageCtx(ImageCtx
&image_ctx
) : MockImageCtx(image_ctx
) {
23 } // anonymous namespace
28 struct ImageRequest
<MockReplayImageCtx
> {
29 static ImageRequest
*s_instance
;
31 MOCK_METHOD4(aio_write
, void(AioCompletion
*c
, const Extents
&image_extents
,
32 const bufferlist
&bl
, int op_flags
));
33 static void aio_write(MockReplayImageCtx
*ictx
, AioCompletion
*c
,
34 Extents
&&image_extents
, bufferlist
&&bl
,
36 assert(s_instance
!= nullptr);
37 s_instance
->aio_write(c
, image_extents
, bl
, op_flags
);
40 MOCK_METHOD4(aio_discard
, void(AioCompletion
*c
, uint64_t off
, uint64_t len
,
41 bool skip_partial_discard
));
42 static void aio_discard(MockReplayImageCtx
*ictx
, AioCompletion
*c
,
43 uint64_t off
, uint64_t len
, bool skip_partial_discard
) {
44 assert(s_instance
!= nullptr);
45 s_instance
->aio_discard(c
, off
, len
, skip_partial_discard
);
48 MOCK_METHOD1(aio_flush
, void(AioCompletion
*c
));
49 static void aio_flush(MockReplayImageCtx
*ictx
, AioCompletion
*c
) {
50 assert(s_instance
!= nullptr);
51 s_instance
->aio_flush(c
);
54 MOCK_METHOD5(aio_writesame
, void(AioCompletion
*c
, uint64_t off
, uint64_t len
,
55 const bufferlist
&bl
, int op_flags
));
56 static void aio_writesame(MockReplayImageCtx
*ictx
, AioCompletion
*c
,
57 uint64_t off
, uint64_t len
, bufferlist
&&bl
,
59 assert(s_instance
!= nullptr);
60 s_instance
->aio_writesame(c
, off
, len
, bl
, op_flags
);
68 ImageRequest
<MockReplayImageCtx
> *ImageRequest
<MockReplayImageCtx
>::s_instance
= nullptr;
74 inline ImageCtx
*get_image_ctx(librbd::MockReplayImageCtx
*image_ctx
) {
75 return image_ctx
->image_ctx
;
82 // template definitions
83 #include "librbd/journal/Replay.cc"
84 template class librbd::journal::Replay
<librbd::MockReplayImageCtx
>;
87 using ::testing::DoAll
;
88 using ::testing::InSequence
;
89 using ::testing::Return
;
90 using ::testing::SaveArg
;
91 using ::testing::StrEq
;
92 using ::testing::WithArgs
;
94 MATCHER_P(BufferlistEqual
, str
, "") {
96 return (strncmp(bl
.c_str(), str
, strlen(str
)) == 0);
99 MATCHER_P(CStrEq
, str
, "") {
100 return (strncmp(arg
, str
, strlen(str
)) == 0);
103 ACTION_P2(NotifyInvoke
, lock
, cond
) {
104 Mutex::Locker
locker(*lock
);
108 ACTION_P2(CompleteAioCompletion
, r
, image_ctx
) {
109 image_ctx
->op_work_queue
->queue(new FunctionContext([this, arg0
](int r
) {
111 arg0
->init_time(image_ctx
, librbd::io::AIO_TYPE_NONE
);
112 arg0
->set_request_count(1);
113 arg0
->complete_request(r
);
120 class TestMockJournalReplay
: public TestMockFixture
{
122 typedef io::ImageRequest
<MockReplayImageCtx
> MockIoImageRequest
;
123 typedef Replay
<MockReplayImageCtx
> MockJournalReplay
;
125 TestMockJournalReplay() : m_invoke_lock("m_invoke_lock") {
128 void expect_aio_discard(MockIoImageRequest
&mock_io_image_request
,
129 io::AioCompletion
**aio_comp
, uint64_t off
,
130 uint64_t len
, bool skip_partial_discard
) {
131 EXPECT_CALL(mock_io_image_request
, aio_discard(_
, off
, len
, skip_partial_discard
))
132 .WillOnce(SaveArg
<0>(aio_comp
));
135 void expect_aio_flush(MockIoImageRequest
&mock_io_image_request
,
136 io::AioCompletion
**aio_comp
) {
137 EXPECT_CALL(mock_io_image_request
, aio_flush(_
))
138 .WillOnce(SaveArg
<0>(aio_comp
));
141 void expect_aio_flush(MockReplayImageCtx
&mock_image_ctx
,
142 MockIoImageRequest
&mock_io_image_request
, int r
) {
143 EXPECT_CALL(mock_io_image_request
, aio_flush(_
))
144 .WillOnce(CompleteAioCompletion(r
, mock_image_ctx
.image_ctx
));
147 void expect_aio_write(MockIoImageRequest
&mock_io_image_request
,
148 io::AioCompletion
**aio_comp
, uint64_t off
,
149 uint64_t len
, const char *data
) {
150 EXPECT_CALL(mock_io_image_request
,
151 aio_write(_
, io::Extents
{{off
, len
}}, BufferlistEqual(data
), _
))
152 .WillOnce(SaveArg
<0>(aio_comp
));
155 void expect_aio_writesame(MockIoImageRequest
&mock_io_image_request
,
156 io::AioCompletion
**aio_comp
, uint64_t off
,
157 uint64_t len
, const char *data
) {
158 EXPECT_CALL(mock_io_image_request
,
159 aio_writesame(_
, off
, len
, BufferlistEqual(data
), _
))
160 .WillOnce(SaveArg
<0>(aio_comp
));
163 void expect_flatten(MockReplayImageCtx
&mock_image_ctx
, Context
**on_finish
) {
164 EXPECT_CALL(*mock_image_ctx
.operations
, execute_flatten(_
, _
))
165 .WillOnce(DoAll(SaveArg
<1>(on_finish
),
166 NotifyInvoke(&m_invoke_lock
, &m_invoke_cond
)));
169 void expect_rename(MockReplayImageCtx
&mock_image_ctx
, Context
**on_finish
,
170 const char *image_name
) {
171 EXPECT_CALL(*mock_image_ctx
.operations
, execute_rename(StrEq(image_name
), _
))
172 .WillOnce(DoAll(SaveArg
<1>(on_finish
),
173 NotifyInvoke(&m_invoke_lock
, &m_invoke_cond
)));
176 void expect_resize(MockReplayImageCtx
&mock_image_ctx
, Context
**on_finish
,
177 uint64_t size
, uint64_t op_tid
) {
178 EXPECT_CALL(*mock_image_ctx
.operations
, execute_resize(size
, _
, _
, _
, op_tid
))
179 .WillOnce(DoAll(SaveArg
<3>(on_finish
),
180 NotifyInvoke(&m_invoke_lock
, &m_invoke_cond
)));
183 void expect_snap_create(MockReplayImageCtx
&mock_image_ctx
,
184 Context
**on_finish
, const char *snap_name
,
186 EXPECT_CALL(*mock_image_ctx
.operations
, execute_snap_create(_
, StrEq(snap_name
), _
,
188 .WillOnce(DoAll(SaveArg
<2>(on_finish
),
189 NotifyInvoke(&m_invoke_lock
, &m_invoke_cond
)));
192 void expect_snap_remove(MockReplayImageCtx
&mock_image_ctx
,
193 Context
**on_finish
, const char *snap_name
) {
194 EXPECT_CALL(*mock_image_ctx
.operations
, execute_snap_remove(_
, StrEq(snap_name
), _
))
195 .WillOnce(DoAll(SaveArg
<2>(on_finish
),
196 NotifyInvoke(&m_invoke_lock
, &m_invoke_cond
)));
199 void expect_snap_rename(MockReplayImageCtx
&mock_image_ctx
,
200 Context
**on_finish
, uint64_t snap_id
,
201 const char *snap_name
) {
202 EXPECT_CALL(*mock_image_ctx
.operations
, execute_snap_rename(snap_id
, StrEq(snap_name
), _
))
203 .WillOnce(DoAll(SaveArg
<2>(on_finish
),
204 NotifyInvoke(&m_invoke_lock
, &m_invoke_cond
)));
207 void expect_snap_protect(MockReplayImageCtx
&mock_image_ctx
,
208 Context
**on_finish
, const char *snap_name
) {
209 EXPECT_CALL(*mock_image_ctx
.operations
, execute_snap_protect(_
, StrEq(snap_name
), _
))
210 .WillOnce(DoAll(SaveArg
<2>(on_finish
),
211 NotifyInvoke(&m_invoke_lock
, &m_invoke_cond
)));
214 void expect_snap_unprotect(MockReplayImageCtx
&mock_image_ctx
,
215 Context
**on_finish
, const char *snap_name
) {
216 EXPECT_CALL(*mock_image_ctx
.operations
, execute_snap_unprotect(_
, StrEq(snap_name
), _
))
217 .WillOnce(DoAll(SaveArg
<2>(on_finish
),
218 NotifyInvoke(&m_invoke_lock
, &m_invoke_cond
)));
221 void expect_snap_rollback(MockReplayImageCtx
&mock_image_ctx
,
222 Context
**on_finish
, const char *snap_name
) {
223 EXPECT_CALL(*mock_image_ctx
.operations
, execute_snap_rollback(_
, StrEq(snap_name
), _
, _
))
224 .WillOnce(DoAll(SaveArg
<3>(on_finish
),
225 NotifyInvoke(&m_invoke_lock
, &m_invoke_cond
)));
228 void expect_update_features(MockReplayImageCtx
&mock_image_ctx
, Context
**on_finish
,
229 uint64_t features
, bool enabled
, uint64_t op_tid
) {
230 EXPECT_CALL(*mock_image_ctx
.operations
, execute_update_features(features
, enabled
, _
, op_tid
))
231 .WillOnce(DoAll(SaveArg
<2>(on_finish
),
232 NotifyInvoke(&m_invoke_lock
, &m_invoke_cond
)));
235 void expect_metadata_set(MockReplayImageCtx
&mock_image_ctx
,
236 Context
**on_finish
, const char *key
,
238 EXPECT_CALL(*mock_image_ctx
.operations
, execute_metadata_set(StrEq(key
),
240 .WillOnce(DoAll(SaveArg
<2>(on_finish
),
241 NotifyInvoke(&m_invoke_lock
, &m_invoke_cond
)));
244 void expect_metadata_remove(MockReplayImageCtx
&mock_image_ctx
,
245 Context
**on_finish
, const char *key
) {
246 EXPECT_CALL(*mock_image_ctx
.operations
, execute_metadata_remove(StrEq(key
), _
))
247 .WillOnce(DoAll(SaveArg
<1>(on_finish
),
248 NotifyInvoke(&m_invoke_lock
, &m_invoke_cond
)));
251 void expect_refresh_image(MockReplayImageCtx
&mock_image_ctx
, bool required
,
253 EXPECT_CALL(*mock_image_ctx
.state
, is_refresh_required())
254 .WillOnce(Return(required
));
256 EXPECT_CALL(*mock_image_ctx
.state
, refresh(_
))
257 .WillOnce(CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
));
261 void when_process(MockJournalReplay
&mock_journal_replay
,
262 EventEntry
&&event_entry
, Context
*on_ready
,
265 ::encode(event_entry
, bl
);
267 bufferlist::iterator it
= bl
.begin();
268 when_process(mock_journal_replay
, &it
, on_ready
, on_safe
);
271 void when_process(MockJournalReplay
&mock_journal_replay
,
272 bufferlist::iterator
*it
, Context
*on_ready
,
274 EventEntry event_entry
;
275 int r
= mock_journal_replay
.decode(it
, &event_entry
);
278 mock_journal_replay
.process(event_entry
, on_ready
, on_safe
);
281 void when_complete(MockReplayImageCtx
&mock_image_ctx
,
282 io::AioCompletion
*aio_comp
, int r
) {
284 aio_comp
->init_time(mock_image_ctx
.image_ctx
, librbd::io::AIO_TYPE_NONE
);
285 aio_comp
->set_request_count(1);
286 aio_comp
->complete_request(r
);
289 int when_flush(MockJournalReplay
&mock_journal_replay
) {
291 mock_journal_replay
.flush(&ctx
);
295 int when_shut_down(MockJournalReplay
&mock_journal_replay
, bool cancel_ops
) {
297 mock_journal_replay
.shut_down(cancel_ops
, &ctx
);
301 void when_replay_op_ready(MockJournalReplay
&mock_journal_replay
,
302 uint64_t op_tid
, Context
*on_resume
) {
303 mock_journal_replay
.replay_op_ready(op_tid
, on_resume
);
306 void wait_for_op_invoked(Context
**on_finish
, int r
) {
308 Mutex::Locker
locker(m_invoke_lock
);
309 while (*on_finish
== nullptr) {
310 m_invoke_cond
.Wait(m_invoke_lock
);
313 (*on_finish
)->complete(r
);
316 bufferlist
to_bl(const std::string
&str
) {
326 TEST_F(TestMockJournalReplay
, AioDiscard
) {
327 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
329 librbd::ImageCtx
*ictx
;
330 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
332 MockReplayImageCtx
mock_image_ctx(*ictx
);
333 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
334 MockIoImageRequest mock_io_image_request
;
335 expect_op_work_queue(mock_image_ctx
);
338 io::AioCompletion
*aio_comp
;
339 C_SaferCond on_ready
;
341 expect_aio_discard(mock_io_image_request
, &aio_comp
, 123, 456, ictx
->skip_partial_discard
);
342 when_process(mock_journal_replay
,
343 EventEntry
{AioDiscardEvent(123, 456, ictx
->skip_partial_discard
)},
344 &on_ready
, &on_safe
);
346 when_complete(mock_image_ctx
, aio_comp
, 0);
347 ASSERT_EQ(0, on_ready
.wait());
349 expect_aio_flush(mock_image_ctx
, mock_io_image_request
, 0);
350 ASSERT_EQ(0, when_shut_down(mock_journal_replay
, false));
351 ASSERT_EQ(0, on_safe
.wait());
354 TEST_F(TestMockJournalReplay
, AioWrite
) {
355 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
357 librbd::ImageCtx
*ictx
;
358 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
360 MockReplayImageCtx
mock_image_ctx(*ictx
);
361 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
362 MockIoImageRequest mock_io_image_request
;
363 expect_op_work_queue(mock_image_ctx
);
366 io::AioCompletion
*aio_comp
;
367 C_SaferCond on_ready
;
369 expect_aio_write(mock_io_image_request
, &aio_comp
, 123, 456, "test");
370 when_process(mock_journal_replay
,
371 EventEntry
{AioWriteEvent(123, 456, to_bl("test"))},
372 &on_ready
, &on_safe
);
374 when_complete(mock_image_ctx
, aio_comp
, 0);
375 ASSERT_EQ(0, on_ready
.wait());
377 expect_aio_flush(mock_image_ctx
, mock_io_image_request
, 0);
378 ASSERT_EQ(0, when_shut_down(mock_journal_replay
, false));
379 ASSERT_EQ(0, on_safe
.wait());
382 TEST_F(TestMockJournalReplay
, AioFlush
) {
383 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
385 librbd::ImageCtx
*ictx
;
386 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
388 MockReplayImageCtx
mock_image_ctx(*ictx
);
389 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
390 MockIoImageRequest mock_io_image_request
;
391 expect_op_work_queue(mock_image_ctx
);
394 io::AioCompletion
*aio_comp
;
395 C_SaferCond on_ready
;
397 expect_aio_flush(mock_io_image_request
, &aio_comp
);
398 when_process(mock_journal_replay
, EventEntry
{AioFlushEvent()},
399 &on_ready
, &on_safe
);
401 when_complete(mock_image_ctx
, aio_comp
, 0);
402 ASSERT_EQ(0, on_safe
.wait());
404 ASSERT_EQ(0, when_shut_down(mock_journal_replay
, false));
405 ASSERT_EQ(0, on_ready
.wait());
408 TEST_F(TestMockJournalReplay
, AioWriteSame
) {
409 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
411 librbd::ImageCtx
*ictx
;
412 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
414 MockReplayImageCtx
mock_image_ctx(*ictx
);
415 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
416 MockIoImageRequest mock_io_image_request
;
417 expect_op_work_queue(mock_image_ctx
);
420 io::AioCompletion
*aio_comp
;
421 C_SaferCond on_ready
;
423 expect_aio_writesame(mock_io_image_request
, &aio_comp
, 123, 456, "333");
424 when_process(mock_journal_replay
,
425 EventEntry
{AioWriteSameEvent(123, 456, to_bl("333"))},
426 &on_ready
, &on_safe
);
428 when_complete(mock_image_ctx
, aio_comp
, 0);
429 ASSERT_EQ(0, on_ready
.wait());
431 expect_aio_flush(mock_image_ctx
, mock_io_image_request
, 0);
432 ASSERT_EQ(0, when_shut_down(mock_journal_replay
, false));
433 ASSERT_EQ(0, on_safe
.wait());
436 TEST_F(TestMockJournalReplay
, IOError
) {
437 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
439 librbd::ImageCtx
*ictx
;
440 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
442 MockReplayImageCtx
mock_image_ctx(*ictx
);
443 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
444 MockIoImageRequest mock_io_image_request
;
445 expect_op_work_queue(mock_image_ctx
);
448 io::AioCompletion
*aio_comp
;
449 C_SaferCond on_ready
;
451 expect_aio_discard(mock_io_image_request
, &aio_comp
, 123, 456, ictx
->skip_partial_discard
);
452 when_process(mock_journal_replay
,
453 EventEntry
{AioDiscardEvent(123, 456, ictx
->skip_partial_discard
)},
454 &on_ready
, &on_safe
);
456 when_complete(mock_image_ctx
, aio_comp
, -EINVAL
);
457 ASSERT_EQ(-EINVAL
, on_safe
.wait());
459 expect_aio_flush(mock_image_ctx
, mock_io_image_request
, 0);
460 ASSERT_EQ(0, when_shut_down(mock_journal_replay
, false));
461 ASSERT_EQ(0, on_ready
.wait());
464 TEST_F(TestMockJournalReplay
, SoftFlushIO
) {
465 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
467 librbd::ImageCtx
*ictx
;
468 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
470 MockReplayImageCtx
mock_image_ctx(*ictx
);
471 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
472 MockIoImageRequest mock_io_image_request
;
473 expect_op_work_queue(mock_image_ctx
);
476 const size_t io_count
= 32;
477 C_SaferCond on_safes
[io_count
];
478 for (size_t i
= 0; i
< io_count
; ++i
) {
479 io::AioCompletion
*aio_comp
;
480 io::AioCompletion
*flush_comp
= nullptr;
481 C_SaferCond on_ready
;
482 expect_aio_discard(mock_io_image_request
, &aio_comp
, 123, 456, ictx
->skip_partial_discard
);
483 if (i
== io_count
- 1) {
484 expect_aio_flush(mock_io_image_request
, &flush_comp
);
486 when_process(mock_journal_replay
,
487 EventEntry
{AioDiscardEvent(123, 456, ictx
->skip_partial_discard
)},
488 &on_ready
, &on_safes
[i
]);
489 when_complete(mock_image_ctx
, aio_comp
, 0);
490 ASSERT_EQ(0, on_ready
.wait());
492 if (flush_comp
!= nullptr) {
493 when_complete(mock_image_ctx
, flush_comp
, 0);
496 for (auto &on_safe
: on_safes
) {
497 ASSERT_EQ(0, on_safe
.wait());
500 ASSERT_EQ(0, when_shut_down(mock_journal_replay
, false));
503 TEST_F(TestMockJournalReplay
, PauseIO
) {
504 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
506 librbd::ImageCtx
*ictx
;
507 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
509 MockReplayImageCtx
mock_image_ctx(*ictx
);
510 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
511 MockIoImageRequest mock_io_image_request
;
512 expect_op_work_queue(mock_image_ctx
);
515 const size_t io_count
= 64;
516 std::list
<io::AioCompletion
*> flush_comps
;
517 C_SaferCond on_safes
[io_count
];
518 for (size_t i
= 0; i
< io_count
; ++i
) {
519 io::AioCompletion
*aio_comp
;
520 C_SaferCond on_ready
;
521 expect_aio_write(mock_io_image_request
, &aio_comp
, 123, 456, "test");
522 if ((i
+ 1) % 32 == 0) {
523 flush_comps
.push_back(nullptr);
524 expect_aio_flush(mock_io_image_request
, &flush_comps
.back());
526 when_process(mock_journal_replay
,
527 EventEntry
{AioWriteEvent(123, 456, to_bl("test"))},
528 &on_ready
, &on_safes
[i
]);
529 when_complete(mock_image_ctx
, aio_comp
, 0);
530 if (i
< io_count
- 1) {
531 ASSERT_EQ(0, on_ready
.wait());
533 for (auto flush_comp
: flush_comps
) {
534 when_complete(mock_image_ctx
, flush_comp
, 0);
536 ASSERT_EQ(0, on_ready
.wait());
539 for (auto &on_safe
: on_safes
) {
540 ASSERT_EQ(0, on_safe
.wait());
543 ASSERT_EQ(0, when_shut_down(mock_journal_replay
, false));
546 TEST_F(TestMockJournalReplay
, Flush
) {
547 librbd::ImageCtx
*ictx
;
548 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
550 MockReplayImageCtx
mock_image_ctx(*ictx
);
551 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
552 MockIoImageRequest mock_io_image_request
;
553 expect_op_work_queue(mock_image_ctx
);
556 io::AioCompletion
*aio_comp
= nullptr;
557 C_SaferCond on_ready
;
559 expect_aio_discard(mock_io_image_request
, &aio_comp
, 123, 456, ictx
->skip_partial_discard
);
560 when_process(mock_journal_replay
,
561 EventEntry
{AioDiscardEvent(123, 456, ictx
->skip_partial_discard
)},
562 &on_ready
, &on_safe
);
564 when_complete(mock_image_ctx
, aio_comp
, 0);
565 ASSERT_EQ(0, on_ready
.wait());
567 expect_aio_flush(mock_image_ctx
, mock_io_image_request
, 0);
568 ASSERT_EQ(0, when_flush(mock_journal_replay
));
569 ASSERT_EQ(0, on_safe
.wait());
572 TEST_F(TestMockJournalReplay
, OpFinishError
) {
573 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
575 librbd::ImageCtx
*ictx
;
576 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
578 MockReplayImageCtx
mock_image_ctx(*ictx
);
579 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
580 expect_op_work_queue(mock_image_ctx
);
583 C_SaferCond on_start_ready
;
584 C_SaferCond on_start_safe
;
585 when_process(mock_journal_replay
,
586 EventEntry
{SnapRemoveEvent(123,
587 cls::rbd::UserSnapshotNamespace(),
591 ASSERT_EQ(0, on_start_ready
.wait());
593 C_SaferCond on_finish_ready
;
594 C_SaferCond on_finish_safe
;
595 when_process(mock_journal_replay
, EventEntry
{OpFinishEvent(123, -EIO
)},
596 &on_finish_ready
, &on_finish_safe
);
598 ASSERT_EQ(-EIO
, on_start_safe
.wait());
599 ASSERT_EQ(-EIO
, on_finish_safe
.wait());
600 ASSERT_EQ(0, on_finish_ready
.wait());
603 TEST_F(TestMockJournalReplay
, BlockedOpFinishError
) {
604 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
606 librbd::ImageCtx
*ictx
;
607 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
609 MockReplayImageCtx
mock_image_ctx(*ictx
);
610 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
611 expect_op_work_queue(mock_image_ctx
);
614 Context
*on_finish
= nullptr;
615 expect_refresh_image(mock_image_ctx
, false, 0);
616 expect_snap_create(mock_image_ctx
, &on_finish
, "snap", 123);
618 C_SaferCond on_start_ready
;
619 C_SaferCond on_start_safe
;
620 when_process(mock_journal_replay
,
621 EventEntry
{SnapCreateEvent(123,
622 cls::rbd::UserSnapshotNamespace(),
627 C_SaferCond on_resume
;
628 when_replay_op_ready(mock_journal_replay
, 123, &on_resume
);
629 ASSERT_EQ(0, on_start_ready
.wait());
631 C_SaferCond on_finish_ready
;
632 C_SaferCond on_finish_safe
;
633 when_process(mock_journal_replay
, EventEntry
{OpFinishEvent(123, -EBADMSG
)},
634 &on_finish_ready
, &on_finish_safe
);
636 ASSERT_EQ(-EBADMSG
, on_resume
.wait());
637 wait_for_op_invoked(&on_finish
, -ESTALE
);
639 ASSERT_EQ(-ESTALE
, on_start_safe
.wait());
640 ASSERT_EQ(-ESTALE
, on_finish_safe
.wait());
641 ASSERT_EQ(0, on_finish_ready
.wait());
644 TEST_F(TestMockJournalReplay
, MissingOpFinishEvent
) {
645 librbd::ImageCtx
*ictx
;
646 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
648 MockReplayImageCtx
mock_image_ctx(*ictx
);
649 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
650 expect_op_work_queue(mock_image_ctx
);
652 EXPECT_CALL(*mock_image_ctx
.state
, is_refresh_required())
653 .WillRepeatedly(Return(false));
656 Context
*on_snap_create_finish
= nullptr;
657 expect_snap_create(mock_image_ctx
, &on_snap_create_finish
, "snap", 123);
659 Context
*on_snap_remove_finish
= nullptr;
660 expect_snap_remove(mock_image_ctx
, &on_snap_remove_finish
, "snap");
662 C_SaferCond on_snap_remove_ready
;
663 C_SaferCond on_snap_remove_safe
;
664 when_process(mock_journal_replay
,
665 EventEntry
{SnapRemoveEvent(122,
666 cls::rbd::UserSnapshotNamespace(),
668 &on_snap_remove_ready
,
669 &on_snap_remove_safe
);
670 ASSERT_EQ(0, on_snap_remove_ready
.wait());
672 C_SaferCond on_snap_create_ready
;
673 C_SaferCond on_snap_create_safe
;
674 when_process(mock_journal_replay
,
675 EventEntry
{SnapCreateEvent(123,
676 cls::rbd::UserSnapshotNamespace(),
678 &on_snap_create_ready
,
679 &on_snap_create_safe
);
681 C_SaferCond on_shut_down
;
682 mock_journal_replay
.shut_down(false, &on_shut_down
);
684 wait_for_op_invoked(&on_snap_remove_finish
, 0);
685 ASSERT_EQ(0, on_snap_remove_safe
.wait());
687 C_SaferCond on_snap_create_resume
;
688 when_replay_op_ready(mock_journal_replay
, 123, &on_snap_create_resume
);
689 ASSERT_EQ(0, on_snap_create_resume
.wait());
691 wait_for_op_invoked(&on_snap_create_finish
, 0);
692 ASSERT_EQ(0, on_snap_create_ready
.wait());
693 ASSERT_EQ(0, on_snap_create_safe
.wait());
695 ASSERT_EQ(0, on_shut_down
.wait());
698 TEST_F(TestMockJournalReplay
, MissingOpFinishEventCancelOps
) {
699 librbd::ImageCtx
*ictx
;
700 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
702 MockReplayImageCtx
mock_image_ctx(*ictx
);
703 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
704 expect_op_work_queue(mock_image_ctx
);
707 Context
*on_snap_create_finish
= nullptr;
708 expect_refresh_image(mock_image_ctx
, false, 0);
709 expect_snap_create(mock_image_ctx
, &on_snap_create_finish
, "snap", 123);
711 C_SaferCond on_snap_remove_ready
;
712 C_SaferCond on_snap_remove_safe
;
713 when_process(mock_journal_replay
,
714 EventEntry
{SnapRemoveEvent(122,
715 cls::rbd::UserSnapshotNamespace(),
717 &on_snap_remove_ready
,
718 &on_snap_remove_safe
);
719 ASSERT_EQ(0, on_snap_remove_ready
.wait());
721 C_SaferCond on_snap_create_ready
;
722 C_SaferCond on_snap_create_safe
;
723 when_process(mock_journal_replay
,
724 EventEntry
{SnapCreateEvent(123,
725 cls::rbd::UserSnapshotNamespace(),
727 &on_snap_create_ready
,
728 &on_snap_create_safe
);
730 C_SaferCond on_resume
;
731 when_replay_op_ready(mock_journal_replay
, 123, &on_resume
);
732 ASSERT_EQ(0, on_snap_create_ready
.wait());
734 C_SaferCond on_shut_down
;
735 mock_journal_replay
.shut_down(true, &on_shut_down
);
737 ASSERT_EQ(-ERESTART
, on_resume
.wait());
738 on_snap_create_finish
->complete(-ERESTART
);
739 ASSERT_EQ(-ERESTART
, on_snap_create_safe
.wait());
741 ASSERT_EQ(-ERESTART
, on_snap_remove_safe
.wait());
742 ASSERT_EQ(0, on_shut_down
.wait());
745 TEST_F(TestMockJournalReplay
, UnknownOpFinishEvent
) {
746 librbd::ImageCtx
*ictx
;
747 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
749 MockReplayImageCtx
mock_image_ctx(*ictx
);
750 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
751 expect_op_work_queue(mock_image_ctx
);
754 C_SaferCond on_ready
;
756 when_process(mock_journal_replay
, EventEntry
{OpFinishEvent(123, 0)},
757 &on_ready
, &on_safe
);
759 ASSERT_EQ(0, on_safe
.wait());
760 ASSERT_EQ(0, on_ready
.wait());
763 TEST_F(TestMockJournalReplay
, OpEventError
) {
764 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
766 librbd::ImageCtx
*ictx
;
767 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
769 MockReplayImageCtx
mock_image_ctx(*ictx
);
770 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
771 expect_op_work_queue(mock_image_ctx
);
774 Context
*on_finish
= nullptr;
775 expect_refresh_image(mock_image_ctx
, false, 0);
776 expect_snap_remove(mock_image_ctx
, &on_finish
, "snap");
778 C_SaferCond on_start_ready
;
779 C_SaferCond on_start_safe
;
780 when_process(mock_journal_replay
,
781 EventEntry
{SnapRemoveEvent(123,
782 cls::rbd::UserSnapshotNamespace(),
786 ASSERT_EQ(0, on_start_ready
.wait());
788 C_SaferCond on_finish_ready
;
789 C_SaferCond on_finish_safe
;
790 when_process(mock_journal_replay
, EventEntry
{OpFinishEvent(123, 0)},
791 &on_finish_ready
, &on_finish_safe
);
793 wait_for_op_invoked(&on_finish
, -EINVAL
);
794 ASSERT_EQ(-EINVAL
, on_start_safe
.wait());
795 ASSERT_EQ(0, on_finish_ready
.wait());
796 ASSERT_EQ(-EINVAL
, on_finish_safe
.wait());
799 TEST_F(TestMockJournalReplay
, SnapCreateEvent
) {
800 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
802 librbd::ImageCtx
*ictx
;
803 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
805 MockReplayImageCtx
mock_image_ctx(*ictx
);
806 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
807 expect_op_work_queue(mock_image_ctx
);
810 Context
*on_finish
= nullptr;
811 expect_refresh_image(mock_image_ctx
, false, 0);
812 expect_snap_create(mock_image_ctx
, &on_finish
, "snap", 123);
814 C_SaferCond on_start_ready
;
815 C_SaferCond on_start_safe
;
816 when_process(mock_journal_replay
,
817 EventEntry
{SnapCreateEvent(123,
818 cls::rbd::UserSnapshotNamespace(),
823 C_SaferCond on_resume
;
824 when_replay_op_ready(mock_journal_replay
, 123, &on_resume
);
825 ASSERT_EQ(0, on_start_ready
.wait());
827 C_SaferCond on_finish_ready
;
828 C_SaferCond on_finish_safe
;
829 when_process(mock_journal_replay
, EventEntry
{OpFinishEvent(123, 0)},
830 &on_finish_ready
, &on_finish_safe
);
832 ASSERT_EQ(0, on_resume
.wait());
833 wait_for_op_invoked(&on_finish
, 0);
835 ASSERT_EQ(0, on_start_safe
.wait());
836 ASSERT_EQ(0, on_finish_ready
.wait());
837 ASSERT_EQ(0, on_finish_safe
.wait());
840 TEST_F(TestMockJournalReplay
, SnapCreateEventExists
) {
841 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
843 librbd::ImageCtx
*ictx
;
844 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
846 MockReplayImageCtx
mock_image_ctx(*ictx
);
847 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
848 expect_op_work_queue(mock_image_ctx
);
851 Context
*on_finish
= nullptr;
852 expect_refresh_image(mock_image_ctx
, false, 0);
853 expect_snap_create(mock_image_ctx
, &on_finish
, "snap", 123);
855 C_SaferCond on_start_ready
;
856 C_SaferCond on_start_safe
;
857 when_process(mock_journal_replay
,
858 EventEntry
{SnapCreateEvent(123,
859 cls::rbd::UserSnapshotNamespace(),
864 wait_for_op_invoked(&on_finish
, -EEXIST
);
865 ASSERT_EQ(0, on_start_ready
.wait());
867 C_SaferCond on_finish_ready
;
868 C_SaferCond on_finish_safe
;
869 when_process(mock_journal_replay
, EventEntry
{OpFinishEvent(123, 0)},
870 &on_finish_ready
, &on_finish_safe
);
872 ASSERT_EQ(0, on_start_safe
.wait());
873 ASSERT_EQ(0, on_finish_ready
.wait());
874 ASSERT_EQ(0, on_finish_safe
.wait());
877 TEST_F(TestMockJournalReplay
, SnapRemoveEvent
) {
878 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
880 librbd::ImageCtx
*ictx
;
881 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
883 MockReplayImageCtx
mock_image_ctx(*ictx
);
884 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
885 expect_op_work_queue(mock_image_ctx
);
888 Context
*on_finish
= nullptr;
889 expect_refresh_image(mock_image_ctx
, false, 0);
890 expect_snap_remove(mock_image_ctx
, &on_finish
, "snap");
892 C_SaferCond on_start_ready
;
893 C_SaferCond on_start_safe
;
894 when_process(mock_journal_replay
,
895 EventEntry
{SnapRemoveEvent(123,
896 cls::rbd::UserSnapshotNamespace(),
900 ASSERT_EQ(0, on_start_ready
.wait());
902 C_SaferCond on_finish_ready
;
903 C_SaferCond on_finish_safe
;
904 when_process(mock_journal_replay
, EventEntry
{OpFinishEvent(123, 0)},
905 &on_finish_ready
, &on_finish_safe
);
907 wait_for_op_invoked(&on_finish
, 0);
908 ASSERT_EQ(0, on_start_safe
.wait());
909 ASSERT_EQ(0, on_finish_ready
.wait());
910 ASSERT_EQ(0, on_finish_safe
.wait());
913 TEST_F(TestMockJournalReplay
, SnapRemoveEventDNE
) {
914 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
916 librbd::ImageCtx
*ictx
;
917 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
919 MockReplayImageCtx
mock_image_ctx(*ictx
);
920 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
921 expect_op_work_queue(mock_image_ctx
);
924 Context
*on_finish
= nullptr;
925 expect_refresh_image(mock_image_ctx
, false, 0);
926 expect_snap_remove(mock_image_ctx
, &on_finish
, "snap");
928 C_SaferCond on_start_ready
;
929 C_SaferCond on_start_safe
;
930 when_process(mock_journal_replay
,
931 EventEntry
{SnapRemoveEvent(123,
932 cls::rbd::UserSnapshotNamespace(),
936 ASSERT_EQ(0, on_start_ready
.wait());
938 C_SaferCond on_finish_ready
;
939 C_SaferCond on_finish_safe
;
940 when_process(mock_journal_replay
, EventEntry
{OpFinishEvent(123, 0)},
941 &on_finish_ready
, &on_finish_safe
);
943 wait_for_op_invoked(&on_finish
, -ENOENT
);
944 ASSERT_EQ(0, on_start_safe
.wait());
945 ASSERT_EQ(0, on_finish_ready
.wait());
946 ASSERT_EQ(0, on_finish_safe
.wait());
949 TEST_F(TestMockJournalReplay
, SnapRenameEvent
) {
950 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
952 librbd::ImageCtx
*ictx
;
953 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
955 MockReplayImageCtx
mock_image_ctx(*ictx
);
956 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
957 expect_op_work_queue(mock_image_ctx
);
960 Context
*on_finish
= nullptr;
961 expect_refresh_image(mock_image_ctx
, false, 0);
962 expect_snap_rename(mock_image_ctx
, &on_finish
, 234, "snap");
964 C_SaferCond on_start_ready
;
965 C_SaferCond on_start_safe
;
966 when_process(mock_journal_replay
,
967 EventEntry
{SnapRenameEvent(123, 234, "snap1", "snap")},
968 &on_start_ready
, &on_start_safe
);
969 ASSERT_EQ(0, on_start_ready
.wait());
971 C_SaferCond on_finish_ready
;
972 C_SaferCond on_finish_safe
;
973 when_process(mock_journal_replay
, EventEntry
{OpFinishEvent(123, 0)},
974 &on_finish_ready
, &on_finish_safe
);
976 wait_for_op_invoked(&on_finish
, 0);
977 ASSERT_EQ(0, on_start_safe
.wait());
978 ASSERT_EQ(0, on_finish_ready
.wait());
979 ASSERT_EQ(0, on_finish_safe
.wait());
982 TEST_F(TestMockJournalReplay
, SnapRenameEventExists
) {
983 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
985 librbd::ImageCtx
*ictx
;
986 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
988 MockReplayImageCtx
mock_image_ctx(*ictx
);
989 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
990 expect_op_work_queue(mock_image_ctx
);
993 Context
*on_finish
= nullptr;
994 expect_refresh_image(mock_image_ctx
, false, 0);
995 expect_snap_rename(mock_image_ctx
, &on_finish
, 234, "snap");
997 C_SaferCond on_start_ready
;
998 C_SaferCond on_start_safe
;
999 when_process(mock_journal_replay
,
1000 EventEntry
{SnapRenameEvent(123, 234, "snap1", "snap")},
1001 &on_start_ready
, &on_start_safe
);
1002 ASSERT_EQ(0, on_start_ready
.wait());
1004 C_SaferCond on_finish_ready
;
1005 C_SaferCond on_finish_safe
;
1006 when_process(mock_journal_replay
, EventEntry
{OpFinishEvent(123, 0)},
1007 &on_finish_ready
, &on_finish_safe
);
1009 wait_for_op_invoked(&on_finish
, -EEXIST
);
1010 ASSERT_EQ(0, on_start_safe
.wait());
1011 ASSERT_EQ(0, on_finish_ready
.wait());
1012 ASSERT_EQ(0, on_finish_safe
.wait());
1015 TEST_F(TestMockJournalReplay
, SnapProtectEvent
) {
1016 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
1018 librbd::ImageCtx
*ictx
;
1019 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1021 MockReplayImageCtx
mock_image_ctx(*ictx
);
1022 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
1023 expect_op_work_queue(mock_image_ctx
);
1026 Context
*on_finish
= nullptr;
1027 expect_refresh_image(mock_image_ctx
, false, 0);
1028 expect_snap_protect(mock_image_ctx
, &on_finish
, "snap");
1030 C_SaferCond on_start_ready
;
1031 C_SaferCond on_start_safe
;
1032 when_process(mock_journal_replay
,
1033 EventEntry
{SnapProtectEvent(123,
1034 cls::rbd::UserSnapshotNamespace(),
1038 ASSERT_EQ(0, on_start_ready
.wait());
1040 C_SaferCond on_finish_ready
;
1041 C_SaferCond on_finish_safe
;
1042 when_process(mock_journal_replay
, EventEntry
{OpFinishEvent(123, 0)},
1043 &on_finish_ready
, &on_finish_safe
);
1045 wait_for_op_invoked(&on_finish
, 0);
1046 ASSERT_EQ(0, on_start_safe
.wait());
1047 ASSERT_EQ(0, on_finish_ready
.wait());
1048 ASSERT_EQ(0, on_finish_safe
.wait());
1051 TEST_F(TestMockJournalReplay
, SnapProtectEventBusy
) {
1052 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
1054 librbd::ImageCtx
*ictx
;
1055 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1057 MockReplayImageCtx
mock_image_ctx(*ictx
);
1058 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
1059 expect_op_work_queue(mock_image_ctx
);
1062 Context
*on_finish
= nullptr;
1063 expect_refresh_image(mock_image_ctx
, false, 0);
1064 expect_snap_protect(mock_image_ctx
, &on_finish
, "snap");
1066 C_SaferCond on_start_ready
;
1067 C_SaferCond on_start_safe
;
1068 when_process(mock_journal_replay
,
1069 EventEntry
{SnapProtectEvent(123,
1070 cls::rbd::UserSnapshotNamespace(),
1074 ASSERT_EQ(0, on_start_ready
.wait());
1076 C_SaferCond on_finish_ready
;
1077 C_SaferCond on_finish_safe
;
1078 when_process(mock_journal_replay
, EventEntry
{OpFinishEvent(123, 0)},
1079 &on_finish_ready
, &on_finish_safe
);
1081 wait_for_op_invoked(&on_finish
, -EBUSY
);
1082 ASSERT_EQ(0, on_start_safe
.wait());
1083 ASSERT_EQ(0, on_finish_ready
.wait());
1084 ASSERT_EQ(0, on_finish_safe
.wait());
1087 TEST_F(TestMockJournalReplay
, SnapUnprotectEvent
) {
1088 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
1090 librbd::ImageCtx
*ictx
;
1091 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1093 MockReplayImageCtx
mock_image_ctx(*ictx
);
1094 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
1095 expect_op_work_queue(mock_image_ctx
);
1098 Context
*on_finish
= nullptr;
1099 expect_refresh_image(mock_image_ctx
, false, 0);
1100 expect_snap_unprotect(mock_image_ctx
, &on_finish
, "snap");
1102 C_SaferCond on_start_ready
;
1103 C_SaferCond on_start_safe
;
1104 when_process(mock_journal_replay
,
1105 EventEntry
{SnapUnprotectEvent(123,
1106 cls::rbd::UserSnapshotNamespace(),
1110 ASSERT_EQ(0, on_start_ready
.wait());
1112 C_SaferCond on_finish_ready
;
1113 C_SaferCond on_finish_safe
;
1114 when_process(mock_journal_replay
, EventEntry
{OpFinishEvent(123, 0)},
1115 &on_finish_ready
, &on_finish_safe
);
1117 wait_for_op_invoked(&on_finish
, 0);
1118 ASSERT_EQ(0, on_start_safe
.wait());
1119 ASSERT_EQ(0, on_finish_ready
.wait());
1120 ASSERT_EQ(0, on_finish_safe
.wait());
1123 TEST_F(TestMockJournalReplay
, SnapUnprotectOpFinishBusy
) {
1124 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
1126 librbd::ImageCtx
*ictx
;
1127 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1129 MockReplayImageCtx
mock_image_ctx(*ictx
);
1130 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
1131 expect_op_work_queue(mock_image_ctx
);
1134 C_SaferCond on_start_ready
;
1135 C_SaferCond on_start_safe
;
1136 when_process(mock_journal_replay
,
1137 EventEntry
{SnapUnprotectEvent(123,
1138 cls::rbd::UserSnapshotNamespace(),
1142 ASSERT_EQ(0, on_start_ready
.wait());
1144 // aborts the snap unprotect op if image had children
1145 C_SaferCond on_finish_ready
;
1146 C_SaferCond on_finish_safe
;
1147 when_process(mock_journal_replay
, EventEntry
{OpFinishEvent(123, -EBUSY
)},
1148 &on_finish_ready
, &on_finish_safe
);
1150 ASSERT_EQ(0, on_start_safe
.wait());
1151 ASSERT_EQ(0, on_finish_safe
.wait());
1152 ASSERT_EQ(0, on_finish_ready
.wait());
1155 TEST_F(TestMockJournalReplay
, SnapUnprotectEventInvalid
) {
1156 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
1158 librbd::ImageCtx
*ictx
;
1159 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1161 MockReplayImageCtx
mock_image_ctx(*ictx
);
1162 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
1163 expect_op_work_queue(mock_image_ctx
);
1166 Context
*on_finish
= nullptr;
1167 expect_refresh_image(mock_image_ctx
, false, 0);
1168 expect_snap_unprotect(mock_image_ctx
, &on_finish
, "snap");
1170 C_SaferCond on_start_ready
;
1171 C_SaferCond on_start_safe
;
1172 when_process(mock_journal_replay
,
1173 EventEntry
{SnapUnprotectEvent(123,
1174 cls::rbd::UserSnapshotNamespace(),
1178 ASSERT_EQ(0, on_start_ready
.wait());
1180 C_SaferCond on_finish_ready
;
1181 C_SaferCond on_finish_safe
;
1182 when_process(mock_journal_replay
, EventEntry
{OpFinishEvent(123, 0)},
1183 &on_finish_ready
, &on_finish_safe
);
1185 wait_for_op_invoked(&on_finish
, -EINVAL
);
1186 ASSERT_EQ(0, on_start_safe
.wait());
1187 ASSERT_EQ(0, on_finish_ready
.wait());
1188 ASSERT_EQ(0, on_finish_safe
.wait());
1191 TEST_F(TestMockJournalReplay
, SnapRollbackEvent
) {
1192 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
1194 librbd::ImageCtx
*ictx
;
1195 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1197 MockReplayImageCtx
mock_image_ctx(*ictx
);
1198 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
1199 expect_op_work_queue(mock_image_ctx
);
1202 Context
*on_finish
= nullptr;
1203 expect_refresh_image(mock_image_ctx
, false, 0);
1204 expect_snap_rollback(mock_image_ctx
, &on_finish
, "snap");
1206 C_SaferCond on_start_ready
;
1207 C_SaferCond on_start_safe
;
1208 when_process(mock_journal_replay
,
1209 EventEntry
{SnapRollbackEvent(123,
1210 cls::rbd::UserSnapshotNamespace(),
1214 ASSERT_EQ(0, on_start_ready
.wait());
1216 C_SaferCond on_finish_ready
;
1217 C_SaferCond on_finish_safe
;
1218 when_process(mock_journal_replay
, EventEntry
{OpFinishEvent(123, 0)},
1219 &on_finish_ready
, &on_finish_safe
);
1221 wait_for_op_invoked(&on_finish
, 0);
1222 ASSERT_EQ(0, on_start_safe
.wait());
1223 ASSERT_EQ(0, on_finish_ready
.wait());
1224 ASSERT_EQ(0, on_finish_safe
.wait());
1227 TEST_F(TestMockJournalReplay
, RenameEvent
) {
1228 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
1230 librbd::ImageCtx
*ictx
;
1231 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1233 MockReplayImageCtx
mock_image_ctx(*ictx
);
1234 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
1235 expect_op_work_queue(mock_image_ctx
);
1238 Context
*on_finish
= nullptr;
1239 expect_refresh_image(mock_image_ctx
, false, 0);
1240 expect_rename(mock_image_ctx
, &on_finish
, "image");
1242 C_SaferCond on_start_ready
;
1243 C_SaferCond on_start_safe
;
1244 when_process(mock_journal_replay
, EventEntry
{RenameEvent(123, "image")},
1245 &on_start_ready
, &on_start_safe
);
1246 ASSERT_EQ(0, on_start_ready
.wait());
1248 C_SaferCond on_finish_ready
;
1249 C_SaferCond on_finish_safe
;
1250 when_process(mock_journal_replay
, EventEntry
{OpFinishEvent(123, 0)},
1251 &on_finish_ready
, &on_finish_safe
);
1253 wait_for_op_invoked(&on_finish
, 0);
1254 ASSERT_EQ(0, on_start_safe
.wait());
1255 ASSERT_EQ(0, on_finish_ready
.wait());
1256 ASSERT_EQ(0, on_finish_safe
.wait());
1259 TEST_F(TestMockJournalReplay
, RenameEventExists
) {
1260 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
1262 librbd::ImageCtx
*ictx
;
1263 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1265 MockReplayImageCtx
mock_image_ctx(*ictx
);
1266 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
1267 expect_op_work_queue(mock_image_ctx
);
1270 Context
*on_finish
= nullptr;
1271 expect_refresh_image(mock_image_ctx
, false, 0);
1272 expect_rename(mock_image_ctx
, &on_finish
, "image");
1274 C_SaferCond on_start_ready
;
1275 C_SaferCond on_start_safe
;
1276 when_process(mock_journal_replay
, EventEntry
{RenameEvent(123, "image")},
1277 &on_start_ready
, &on_start_safe
);
1278 ASSERT_EQ(0, on_start_ready
.wait());
1280 C_SaferCond on_finish_ready
;
1281 C_SaferCond on_finish_safe
;
1282 when_process(mock_journal_replay
, EventEntry
{OpFinishEvent(123, 0)},
1283 &on_finish_ready
, &on_finish_safe
);
1285 wait_for_op_invoked(&on_finish
, -EEXIST
);
1286 ASSERT_EQ(0, on_start_safe
.wait());
1287 ASSERT_EQ(0, on_finish_ready
.wait());
1288 ASSERT_EQ(0, on_finish_safe
.wait());
1291 TEST_F(TestMockJournalReplay
, ResizeEvent
) {
1292 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
1294 librbd::ImageCtx
*ictx
;
1295 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1297 MockReplayImageCtx
mock_image_ctx(*ictx
);
1298 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
1299 expect_op_work_queue(mock_image_ctx
);
1302 Context
*on_finish
= nullptr;
1303 expect_refresh_image(mock_image_ctx
, false, 0);
1304 expect_resize(mock_image_ctx
, &on_finish
, 234, 123);
1306 C_SaferCond on_start_ready
;
1307 C_SaferCond on_start_safe
;
1308 when_process(mock_journal_replay
, EventEntry
{ResizeEvent(123, 234)},
1309 &on_start_ready
, &on_start_safe
);
1311 C_SaferCond on_resume
;
1312 when_replay_op_ready(mock_journal_replay
, 123, &on_resume
);
1313 ASSERT_EQ(0, on_start_ready
.wait());
1315 C_SaferCond on_finish_ready
;
1316 C_SaferCond on_finish_safe
;
1317 when_process(mock_journal_replay
, EventEntry
{OpFinishEvent(123, 0)},
1318 &on_finish_ready
, &on_finish_safe
);
1320 ASSERT_EQ(0, on_resume
.wait());
1321 wait_for_op_invoked(&on_finish
, 0);
1323 ASSERT_EQ(0, on_start_safe
.wait());
1324 ASSERT_EQ(0, on_finish_ready
.wait());
1325 ASSERT_EQ(0, on_finish_safe
.wait());
1328 TEST_F(TestMockJournalReplay
, FlattenEvent
) {
1329 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
1331 librbd::ImageCtx
*ictx
;
1332 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1334 MockReplayImageCtx
mock_image_ctx(*ictx
);
1335 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
1336 expect_op_work_queue(mock_image_ctx
);
1339 Context
*on_finish
= nullptr;
1340 expect_refresh_image(mock_image_ctx
, false, 0);
1341 expect_flatten(mock_image_ctx
, &on_finish
);
1343 C_SaferCond on_start_ready
;
1344 C_SaferCond on_start_safe
;
1345 when_process(mock_journal_replay
, EventEntry
{FlattenEvent(123)},
1346 &on_start_ready
, &on_start_safe
);
1347 ASSERT_EQ(0, on_start_ready
.wait());
1349 C_SaferCond on_finish_ready
;
1350 C_SaferCond on_finish_safe
;
1351 when_process(mock_journal_replay
, EventEntry
{OpFinishEvent(123, 0)},
1352 &on_finish_ready
, &on_finish_safe
);
1354 wait_for_op_invoked(&on_finish
, 0);
1355 ASSERT_EQ(0, on_start_safe
.wait());
1356 ASSERT_EQ(0, on_finish_ready
.wait());
1357 ASSERT_EQ(0, on_finish_safe
.wait());
1360 TEST_F(TestMockJournalReplay
, FlattenEventInvalid
) {
1361 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
1363 librbd::ImageCtx
*ictx
;
1364 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1366 MockReplayImageCtx
mock_image_ctx(*ictx
);
1367 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
1368 expect_op_work_queue(mock_image_ctx
);
1371 Context
*on_finish
= nullptr;
1372 expect_refresh_image(mock_image_ctx
, false, 0);
1373 expect_flatten(mock_image_ctx
, &on_finish
);
1375 C_SaferCond on_start_ready
;
1376 C_SaferCond on_start_safe
;
1377 when_process(mock_journal_replay
, EventEntry
{FlattenEvent(123)},
1378 &on_start_ready
, &on_start_safe
);
1379 ASSERT_EQ(0, on_start_ready
.wait());
1381 C_SaferCond on_finish_ready
;
1382 C_SaferCond on_finish_safe
;
1383 when_process(mock_journal_replay
, EventEntry
{OpFinishEvent(123, 0)},
1384 &on_finish_ready
, &on_finish_safe
);
1386 wait_for_op_invoked(&on_finish
, -EINVAL
);
1387 ASSERT_EQ(0, on_start_safe
.wait());
1388 ASSERT_EQ(0, on_finish_ready
.wait());
1389 ASSERT_EQ(0, on_finish_safe
.wait());
1392 TEST_F(TestMockJournalReplay
, UpdateFeaturesEvent
) {
1393 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
1395 librbd::ImageCtx
*ictx
;
1396 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1398 uint64_t features
= RBD_FEATURE_OBJECT_MAP
| RBD_FEATURE_FAST_DIFF
;
1399 bool enabled
= !ictx
->test_features(features
);
1401 MockReplayImageCtx
mock_image_ctx(*ictx
);
1402 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
1403 expect_op_work_queue(mock_image_ctx
);
1406 Context
*on_finish
= nullptr;
1407 expect_refresh_image(mock_image_ctx
, false, 0);
1408 expect_update_features(mock_image_ctx
, &on_finish
, features
, enabled
, 123);
1410 C_SaferCond on_start_ready
;
1411 C_SaferCond on_start_safe
;
1412 when_process(mock_journal_replay
,
1413 EventEntry
{UpdateFeaturesEvent(123, features
, enabled
)},
1414 &on_start_ready
, &on_start_safe
);
1416 C_SaferCond on_resume
;
1417 when_replay_op_ready(mock_journal_replay
, 123, &on_resume
);
1418 ASSERT_EQ(0, on_start_ready
.wait());
1420 C_SaferCond on_finish_ready
;
1421 C_SaferCond on_finish_safe
;
1422 when_process(mock_journal_replay
, EventEntry
{OpFinishEvent(123, 0)},
1423 &on_finish_ready
, &on_finish_safe
);
1425 ASSERT_EQ(0, on_resume
.wait());
1426 wait_for_op_invoked(&on_finish
, 0);
1428 ASSERT_EQ(0, on_start_safe
.wait());
1429 ASSERT_EQ(0, on_finish_ready
.wait());
1430 ASSERT_EQ(0, on_finish_safe
.wait());
1433 TEST_F(TestMockJournalReplay
, MetadataSetEvent
) {
1434 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
1436 librbd::ImageCtx
*ictx
;
1437 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1439 MockReplayImageCtx
mock_image_ctx(*ictx
);
1440 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
1441 expect_op_work_queue(mock_image_ctx
);
1444 Context
*on_finish
= nullptr;
1445 expect_refresh_image(mock_image_ctx
, false, 0);
1446 expect_metadata_set(mock_image_ctx
, &on_finish
, "key", "value");
1448 C_SaferCond on_start_ready
;
1449 C_SaferCond on_start_safe
;
1450 when_process(mock_journal_replay
, EventEntry
{MetadataSetEvent(123, "key", "value")},
1451 &on_start_ready
, &on_start_safe
);
1452 ASSERT_EQ(0, on_start_ready
.wait());
1454 C_SaferCond on_finish_ready
;
1455 C_SaferCond on_finish_safe
;
1456 when_process(mock_journal_replay
, EventEntry
{OpFinishEvent(123, 0)},
1457 &on_finish_ready
, &on_finish_safe
);
1459 wait_for_op_invoked(&on_finish
, 0);
1460 ASSERT_EQ(0, on_start_safe
.wait());
1461 ASSERT_EQ(0, on_finish_ready
.wait());
1462 ASSERT_EQ(0, on_finish_safe
.wait());
1465 TEST_F(TestMockJournalReplay
, MetadataRemoveEvent
) {
1466 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
1468 librbd::ImageCtx
*ictx
;
1469 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1471 MockReplayImageCtx
mock_image_ctx(*ictx
);
1472 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
1473 expect_op_work_queue(mock_image_ctx
);
1476 Context
*on_finish
= nullptr;
1477 expect_refresh_image(mock_image_ctx
, false, 0);
1478 expect_metadata_remove(mock_image_ctx
, &on_finish
, "key");
1480 C_SaferCond on_start_ready
;
1481 C_SaferCond on_start_safe
;
1482 when_process(mock_journal_replay
, EventEntry
{MetadataRemoveEvent(123, "key")},
1483 &on_start_ready
, &on_start_safe
);
1484 ASSERT_EQ(0, on_start_ready
.wait());
1486 C_SaferCond on_finish_ready
;
1487 C_SaferCond on_finish_safe
;
1488 when_process(mock_journal_replay
, EventEntry
{OpFinishEvent(123, 0)},
1489 &on_finish_ready
, &on_finish_safe
);
1491 wait_for_op_invoked(&on_finish
, 0);
1492 ASSERT_EQ(0, on_start_safe
.wait());
1493 ASSERT_EQ(0, on_finish_ready
.wait());
1494 ASSERT_EQ(0, on_finish_safe
.wait());
1497 TEST_F(TestMockJournalReplay
, MetadataRemoveEventDNE
) {
1498 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
1500 librbd::ImageCtx
*ictx
;
1501 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1503 MockReplayImageCtx
mock_image_ctx(*ictx
);
1504 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
1505 expect_op_work_queue(mock_image_ctx
);
1508 Context
*on_finish
= nullptr;
1509 expect_refresh_image(mock_image_ctx
, false, 0);
1510 expect_metadata_remove(mock_image_ctx
, &on_finish
, "key");
1512 C_SaferCond on_start_ready
;
1513 C_SaferCond on_start_safe
;
1514 when_process(mock_journal_replay
, EventEntry
{MetadataRemoveEvent(123, "key")},
1515 &on_start_ready
, &on_start_safe
);
1516 ASSERT_EQ(0, on_start_ready
.wait());
1518 C_SaferCond on_finish_ready
;
1519 C_SaferCond on_finish_safe
;
1520 when_process(mock_journal_replay
, EventEntry
{OpFinishEvent(123, 0)},
1521 &on_finish_ready
, &on_finish_safe
);
1523 wait_for_op_invoked(&on_finish
, -ENOENT
);
1524 ASSERT_EQ(0, on_start_safe
.wait());
1525 ASSERT_EQ(0, on_finish_ready
.wait());
1526 ASSERT_EQ(0, on_finish_safe
.wait());
1529 TEST_F(TestMockJournalReplay
, UnknownEvent
) {
1530 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
1532 librbd::ImageCtx
*ictx
;
1533 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1535 MockReplayImageCtx
mock_image_ctx(*ictx
);
1536 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
1537 expect_op_work_queue(mock_image_ctx
);
1542 ENCODE_START(1, 1, bl
);
1543 ::encode(static_cast<uint32_t>(-1), bl
);
1546 bufferlist::iterator it
= bl
.begin();
1547 C_SaferCond on_ready
;
1548 C_SaferCond on_safe
;
1549 when_process(mock_journal_replay
, &it
, &on_ready
, &on_safe
);
1551 ASSERT_EQ(0, on_safe
.wait());
1552 ASSERT_EQ(0, on_ready
.wait());
1555 TEST_F(TestMockJournalReplay
, RefreshImageBeforeOpStart
) {
1556 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
1558 librbd::ImageCtx
*ictx
;
1559 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1561 MockReplayImageCtx
mock_image_ctx(*ictx
);
1562 MockJournalReplay
mock_journal_replay(mock_image_ctx
);
1563 expect_op_work_queue(mock_image_ctx
);
1566 Context
*on_finish
= nullptr;
1567 expect_refresh_image(mock_image_ctx
, true, 0);
1568 expect_resize(mock_image_ctx
, &on_finish
, 234, 123);
1570 C_SaferCond on_start_ready
;
1571 C_SaferCond on_start_safe
;
1572 when_process(mock_journal_replay
, EventEntry
{ResizeEvent(123, 234)},
1573 &on_start_ready
, &on_start_safe
);
1575 C_SaferCond on_resume
;
1576 when_replay_op_ready(mock_journal_replay
, 123, &on_resume
);
1577 ASSERT_EQ(0, on_start_ready
.wait());
1579 C_SaferCond on_finish_ready
;
1580 C_SaferCond on_finish_safe
;
1581 when_process(mock_journal_replay
, EventEntry
{OpFinishEvent(123, 0)},
1582 &on_finish_ready
, &on_finish_safe
);
1584 ASSERT_EQ(0, on_resume
.wait());
1585 wait_for_op_invoked(&on_finish
, 0);
1587 ASSERT_EQ(0, on_start_safe
.wait());
1588 ASSERT_EQ(0, on_finish_ready
.wait());
1589 ASSERT_EQ(0, on_finish_safe
.wait());
1592 } // namespace journal
1593 } // namespace librbd