]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/librbd/journal/test_mock_Replay.cc
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / test / librbd / journal / test_mock_Replay.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
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>
13
14 namespace librbd {
15
16 namespace {
17
18 struct MockReplayImageCtx : public MockImageCtx {
19 MockReplayImageCtx(ImageCtx &image_ctx) : MockImageCtx(image_ctx) {
20 }
21 };
22
23 } // anonymous namespace
24
25 namespace io {
26
27 template <>
28 struct ImageRequest<MockReplayImageCtx> {
29 static ImageRequest *s_instance;
30
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,
35 int op_flags) {
36 assert(s_instance != nullptr);
37 s_instance->aio_write(c, image_extents, bl, op_flags);
38 }
39
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);
46 }
47
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);
52 }
53
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,
58 int op_flags) {
59 assert(s_instance != nullptr);
60 s_instance->aio_writesame(c, off, len, bl, op_flags);
61 }
62
63 ImageRequest() {
64 s_instance = this;
65 }
66 };
67
68 ImageRequest<MockReplayImageCtx> *ImageRequest<MockReplayImageCtx>::s_instance = nullptr;
69
70 } // namespace io
71
72 namespace util {
73
74 inline ImageCtx *get_image_ctx(librbd::MockReplayImageCtx *image_ctx) {
75 return image_ctx->image_ctx;
76 }
77
78 } // namespace util
79
80 } // namespace librbd
81
82 // template definitions
83 #include "librbd/journal/Replay.cc"
84 template class librbd::journal::Replay<librbd::MockReplayImageCtx>;
85
86 using ::testing::_;
87 using ::testing::DoAll;
88 using ::testing::InSequence;
89 using ::testing::Return;
90 using ::testing::SaveArg;
91 using ::testing::StrEq;
92 using ::testing::WithArgs;
93
94 MATCHER_P(BufferlistEqual, str, "") {
95 bufferlist bl(arg);
96 return (strncmp(bl.c_str(), str, strlen(str)) == 0);
97 }
98
99 MATCHER_P(CStrEq, str, "") {
100 return (strncmp(arg, str, strlen(str)) == 0);
101 }
102
103 ACTION_P2(NotifyInvoke, lock, cond) {
104 Mutex::Locker locker(*lock);
105 cond->Signal();
106 }
107
108 ACTION_P2(CompleteAioCompletion, r, image_ctx) {
109 image_ctx->op_work_queue->queue(new FunctionContext([this, arg0](int r) {
110 arg0->get();
111 arg0->init_time(image_ctx, librbd::io::AIO_TYPE_NONE);
112 arg0->set_request_count(1);
113 arg0->complete_request(r);
114 }), r);
115 }
116
117 namespace librbd {
118 namespace journal {
119
120 class TestMockJournalReplay : public TestMockFixture {
121 public:
122 typedef io::ImageRequest<MockReplayImageCtx> MockIoImageRequest;
123 typedef Replay<MockReplayImageCtx> MockJournalReplay;
124
125 TestMockJournalReplay() : m_invoke_lock("m_invoke_lock") {
126 }
127
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));
133 }
134
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));
139 }
140
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));
145 }
146
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));
153 }
154
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));
161 }
162
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)));
167 }
168
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)));
174 }
175
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)));
181 }
182
183 void expect_snap_create(MockReplayImageCtx &mock_image_ctx,
184 Context **on_finish, const char *snap_name,
185 uint64_t op_tid) {
186 EXPECT_CALL(*mock_image_ctx.operations, execute_snap_create(_, StrEq(snap_name), _,
187 op_tid, false))
188 .WillOnce(DoAll(SaveArg<2>(on_finish),
189 NotifyInvoke(&m_invoke_lock, &m_invoke_cond)));
190 }
191
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)));
197 }
198
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)));
205 }
206
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)));
212 }
213
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)));
219 }
220
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)));
226 }
227
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)));
233 }
234
235 void expect_metadata_set(MockReplayImageCtx &mock_image_ctx,
236 Context **on_finish, const char *key,
237 const char *value) {
238 EXPECT_CALL(*mock_image_ctx.operations, execute_metadata_set(StrEq(key),
239 StrEq(value), _))
240 .WillOnce(DoAll(SaveArg<2>(on_finish),
241 NotifyInvoke(&m_invoke_lock, &m_invoke_cond)));
242 }
243
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)));
249 }
250
251 void expect_refresh_image(MockReplayImageCtx &mock_image_ctx, bool required,
252 int r) {
253 EXPECT_CALL(*mock_image_ctx.state, is_refresh_required())
254 .WillOnce(Return(required));
255 if (required) {
256 EXPECT_CALL(*mock_image_ctx.state, refresh(_))
257 .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
258 }
259 }
260
261 void when_process(MockJournalReplay &mock_journal_replay,
262 EventEntry &&event_entry, Context *on_ready,
263 Context *on_safe) {
264 bufferlist bl;
265 ::encode(event_entry, bl);
266
267 bufferlist::iterator it = bl.begin();
268 when_process(mock_journal_replay, &it, on_ready, on_safe);
269 }
270
271 void when_process(MockJournalReplay &mock_journal_replay,
272 bufferlist::iterator *it, Context *on_ready,
273 Context *on_safe) {
274 EventEntry event_entry;
275 int r = mock_journal_replay.decode(it, &event_entry);
276 ASSERT_EQ(0, r);
277
278 mock_journal_replay.process(event_entry, on_ready, on_safe);
279 }
280
281 void when_complete(MockReplayImageCtx &mock_image_ctx,
282 io::AioCompletion *aio_comp, int r) {
283 aio_comp->get();
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);
287 }
288
289 int when_flush(MockJournalReplay &mock_journal_replay) {
290 C_SaferCond ctx;
291 mock_journal_replay.flush(&ctx);
292 return ctx.wait();
293 }
294
295 int when_shut_down(MockJournalReplay &mock_journal_replay, bool cancel_ops) {
296 C_SaferCond ctx;
297 mock_journal_replay.shut_down(cancel_ops, &ctx);
298 return ctx.wait();
299 }
300
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);
304 }
305
306 void wait_for_op_invoked(Context **on_finish, int r) {
307 {
308 Mutex::Locker locker(m_invoke_lock);
309 while (*on_finish == nullptr) {
310 m_invoke_cond.Wait(m_invoke_lock);
311 }
312 }
313 (*on_finish)->complete(r);
314 }
315
316 bufferlist to_bl(const std::string &str) {
317 bufferlist bl;
318 bl.append(str);
319 return bl;
320 }
321
322 Mutex m_invoke_lock;
323 Cond m_invoke_cond;
324 };
325
326 TEST_F(TestMockJournalReplay, AioDiscard) {
327 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
328
329 librbd::ImageCtx *ictx;
330 ASSERT_EQ(0, open_image(m_image_name, &ictx));
331
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);
336
337 InSequence seq;
338 io::AioCompletion *aio_comp;
339 C_SaferCond on_ready;
340 C_SaferCond on_safe;
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);
345
346 when_complete(mock_image_ctx, aio_comp, 0);
347 ASSERT_EQ(0, on_ready.wait());
348
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());
352 }
353
354 TEST_F(TestMockJournalReplay, AioWrite) {
355 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
356
357 librbd::ImageCtx *ictx;
358 ASSERT_EQ(0, open_image(m_image_name, &ictx));
359
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);
364
365 InSequence seq;
366 io::AioCompletion *aio_comp;
367 C_SaferCond on_ready;
368 C_SaferCond on_safe;
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);
373
374 when_complete(mock_image_ctx, aio_comp, 0);
375 ASSERT_EQ(0, on_ready.wait());
376
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());
380 }
381
382 TEST_F(TestMockJournalReplay, AioFlush) {
383 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
384
385 librbd::ImageCtx *ictx;
386 ASSERT_EQ(0, open_image(m_image_name, &ictx));
387
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);
392
393 InSequence seq;
394 io::AioCompletion *aio_comp;
395 C_SaferCond on_ready;
396 C_SaferCond on_safe;
397 expect_aio_flush(mock_io_image_request, &aio_comp);
398 when_process(mock_journal_replay, EventEntry{AioFlushEvent()},
399 &on_ready, &on_safe);
400
401 when_complete(mock_image_ctx, aio_comp, 0);
402 ASSERT_EQ(0, on_safe.wait());
403
404 ASSERT_EQ(0, when_shut_down(mock_journal_replay, false));
405 ASSERT_EQ(0, on_ready.wait());
406 }
407
408 TEST_F(TestMockJournalReplay, AioWriteSame) {
409 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
410
411 librbd::ImageCtx *ictx;
412 ASSERT_EQ(0, open_image(m_image_name, &ictx));
413
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);
418
419 InSequence seq;
420 io::AioCompletion *aio_comp;
421 C_SaferCond on_ready;
422 C_SaferCond on_safe;
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);
427
428 when_complete(mock_image_ctx, aio_comp, 0);
429 ASSERT_EQ(0, on_ready.wait());
430
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());
434 }
435
436 TEST_F(TestMockJournalReplay, IOError) {
437 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
438
439 librbd::ImageCtx *ictx;
440 ASSERT_EQ(0, open_image(m_image_name, &ictx));
441
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);
446
447 InSequence seq;
448 io::AioCompletion *aio_comp;
449 C_SaferCond on_ready;
450 C_SaferCond on_safe;
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);
455
456 when_complete(mock_image_ctx, aio_comp, -EINVAL);
457 ASSERT_EQ(-EINVAL, on_safe.wait());
458
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());
462 }
463
464 TEST_F(TestMockJournalReplay, SoftFlushIO) {
465 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
466
467 librbd::ImageCtx *ictx;
468 ASSERT_EQ(0, open_image(m_image_name, &ictx));
469
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);
474
475 InSequence seq;
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);
485 }
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());
491
492 if (flush_comp != nullptr) {
493 when_complete(mock_image_ctx, flush_comp, 0);
494 }
495 }
496 for (auto &on_safe : on_safes) {
497 ASSERT_EQ(0, on_safe.wait());
498 }
499
500 ASSERT_EQ(0, when_shut_down(mock_journal_replay, false));
501 }
502
503 TEST_F(TestMockJournalReplay, PauseIO) {
504 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
505
506 librbd::ImageCtx *ictx;
507 ASSERT_EQ(0, open_image(m_image_name, &ictx));
508
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);
513
514 InSequence seq;
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());
525 }
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());
532 } else {
533 for (auto flush_comp : flush_comps) {
534 when_complete(mock_image_ctx, flush_comp, 0);
535 }
536 ASSERT_EQ(0, on_ready.wait());
537 }
538 }
539 for (auto &on_safe : on_safes) {
540 ASSERT_EQ(0, on_safe.wait());
541 }
542
543 ASSERT_EQ(0, when_shut_down(mock_journal_replay, false));
544 }
545
546 TEST_F(TestMockJournalReplay, Flush) {
547 librbd::ImageCtx *ictx;
548 ASSERT_EQ(0, open_image(m_image_name, &ictx));
549
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);
554
555 InSequence seq;
556 io::AioCompletion *aio_comp = nullptr;
557 C_SaferCond on_ready;
558 C_SaferCond on_safe;
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);
563
564 when_complete(mock_image_ctx, aio_comp, 0);
565 ASSERT_EQ(0, on_ready.wait());
566
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());
570 }
571
572 TEST_F(TestMockJournalReplay, OpFinishError) {
573 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
574
575 librbd::ImageCtx *ictx;
576 ASSERT_EQ(0, open_image(m_image_name, &ictx));
577
578 MockReplayImageCtx mock_image_ctx(*ictx);
579 MockJournalReplay mock_journal_replay(mock_image_ctx);
580 expect_op_work_queue(mock_image_ctx);
581
582 InSequence seq;
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(),
588 "snap")},
589 &on_start_ready,
590 &on_start_safe);
591 ASSERT_EQ(0, on_start_ready.wait());
592
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);
597
598 ASSERT_EQ(-EIO, on_start_safe.wait());
599 ASSERT_EQ(-EIO, on_finish_safe.wait());
600 ASSERT_EQ(0, on_finish_ready.wait());
601 }
602
603 TEST_F(TestMockJournalReplay, BlockedOpFinishError) {
604 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
605
606 librbd::ImageCtx *ictx;
607 ASSERT_EQ(0, open_image(m_image_name, &ictx));
608
609 MockReplayImageCtx mock_image_ctx(*ictx);
610 MockJournalReplay mock_journal_replay(mock_image_ctx);
611 expect_op_work_queue(mock_image_ctx);
612
613 InSequence seq;
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);
617
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(),
623 "snap")},
624 &on_start_ready,
625 &on_start_safe);
626
627 C_SaferCond on_resume;
628 when_replay_op_ready(mock_journal_replay, 123, &on_resume);
629 ASSERT_EQ(0, on_start_ready.wait());
630
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);
635
636 ASSERT_EQ(-EBADMSG, on_resume.wait());
637 wait_for_op_invoked(&on_finish, -ESTALE);
638
639 ASSERT_EQ(-ESTALE, on_start_safe.wait());
640 ASSERT_EQ(-ESTALE, on_finish_safe.wait());
641 ASSERT_EQ(0, on_finish_ready.wait());
642 }
643
644 TEST_F(TestMockJournalReplay, MissingOpFinishEvent) {
645 librbd::ImageCtx *ictx;
646 ASSERT_EQ(0, open_image(m_image_name, &ictx));
647
648 MockReplayImageCtx mock_image_ctx(*ictx);
649 MockJournalReplay mock_journal_replay(mock_image_ctx);
650 expect_op_work_queue(mock_image_ctx);
651
652 EXPECT_CALL(*mock_image_ctx.state, is_refresh_required())
653 .WillRepeatedly(Return(false));
654
655 InSequence seq;
656 Context *on_snap_create_finish = nullptr;
657 expect_snap_create(mock_image_ctx, &on_snap_create_finish, "snap", 123);
658
659 Context *on_snap_remove_finish = nullptr;
660 expect_snap_remove(mock_image_ctx, &on_snap_remove_finish, "snap");
661
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(),
667 "snap")},
668 &on_snap_remove_ready,
669 &on_snap_remove_safe);
670 ASSERT_EQ(0, on_snap_remove_ready.wait());
671
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(),
677 "snap")},
678 &on_snap_create_ready,
679 &on_snap_create_safe);
680
681 C_SaferCond on_shut_down;
682 mock_journal_replay.shut_down(false, &on_shut_down);
683
684 wait_for_op_invoked(&on_snap_remove_finish, 0);
685 ASSERT_EQ(0, on_snap_remove_safe.wait());
686
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());
690
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());
694
695 ASSERT_EQ(0, on_shut_down.wait());
696 }
697
698 TEST_F(TestMockJournalReplay, MissingOpFinishEventCancelOps) {
699 librbd::ImageCtx *ictx;
700 ASSERT_EQ(0, open_image(m_image_name, &ictx));
701
702 MockReplayImageCtx mock_image_ctx(*ictx);
703 MockJournalReplay mock_journal_replay(mock_image_ctx);
704 expect_op_work_queue(mock_image_ctx);
705
706 InSequence seq;
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);
710
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(),
716 "snap")},
717 &on_snap_remove_ready,
718 &on_snap_remove_safe);
719 ASSERT_EQ(0, on_snap_remove_ready.wait());
720
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(),
726 "snap")},
727 &on_snap_create_ready,
728 &on_snap_create_safe);
729
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());
733
734 C_SaferCond on_shut_down;
735 mock_journal_replay.shut_down(true, &on_shut_down);
736
737 ASSERT_EQ(-ERESTART, on_resume.wait());
738 on_snap_create_finish->complete(-ERESTART);
739 ASSERT_EQ(-ERESTART, on_snap_create_safe.wait());
740
741 ASSERT_EQ(-ERESTART, on_snap_remove_safe.wait());
742 ASSERT_EQ(0, on_shut_down.wait());
743 }
744
745 TEST_F(TestMockJournalReplay, UnknownOpFinishEvent) {
746 librbd::ImageCtx *ictx;
747 ASSERT_EQ(0, open_image(m_image_name, &ictx));
748
749 MockReplayImageCtx mock_image_ctx(*ictx);
750 MockJournalReplay mock_journal_replay(mock_image_ctx);
751 expect_op_work_queue(mock_image_ctx);
752
753 InSequence seq;
754 C_SaferCond on_ready;
755 C_SaferCond on_safe;
756 when_process(mock_journal_replay, EventEntry{OpFinishEvent(123, 0)},
757 &on_ready, &on_safe);
758
759 ASSERT_EQ(0, on_safe.wait());
760 ASSERT_EQ(0, on_ready.wait());
761 }
762
763 TEST_F(TestMockJournalReplay, OpEventError) {
764 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
765
766 librbd::ImageCtx *ictx;
767 ASSERT_EQ(0, open_image(m_image_name, &ictx));
768
769 MockReplayImageCtx mock_image_ctx(*ictx);
770 MockJournalReplay mock_journal_replay(mock_image_ctx);
771 expect_op_work_queue(mock_image_ctx);
772
773 InSequence seq;
774 Context *on_finish = nullptr;
775 expect_refresh_image(mock_image_ctx, false, 0);
776 expect_snap_remove(mock_image_ctx, &on_finish, "snap");
777
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(),
783 "snap")},
784 &on_start_ready,
785 &on_start_safe);
786 ASSERT_EQ(0, on_start_ready.wait());
787
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);
792
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());
797 }
798
799 TEST_F(TestMockJournalReplay, SnapCreateEvent) {
800 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
801
802 librbd::ImageCtx *ictx;
803 ASSERT_EQ(0, open_image(m_image_name, &ictx));
804
805 MockReplayImageCtx mock_image_ctx(*ictx);
806 MockJournalReplay mock_journal_replay(mock_image_ctx);
807 expect_op_work_queue(mock_image_ctx);
808
809 InSequence seq;
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);
813
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(),
819 "snap")},
820 &on_start_ready,
821 &on_start_safe);
822
823 C_SaferCond on_resume;
824 when_replay_op_ready(mock_journal_replay, 123, &on_resume);
825 ASSERT_EQ(0, on_start_ready.wait());
826
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);
831
832 ASSERT_EQ(0, on_resume.wait());
833 wait_for_op_invoked(&on_finish, 0);
834
835 ASSERT_EQ(0, on_start_safe.wait());
836 ASSERT_EQ(0, on_finish_ready.wait());
837 ASSERT_EQ(0, on_finish_safe.wait());
838 }
839
840 TEST_F(TestMockJournalReplay, SnapCreateEventExists) {
841 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
842
843 librbd::ImageCtx *ictx;
844 ASSERT_EQ(0, open_image(m_image_name, &ictx));
845
846 MockReplayImageCtx mock_image_ctx(*ictx);
847 MockJournalReplay mock_journal_replay(mock_image_ctx);
848 expect_op_work_queue(mock_image_ctx);
849
850 InSequence seq;
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);
854
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(),
860 "snap")},
861 &on_start_ready,
862 &on_start_safe);
863
864 wait_for_op_invoked(&on_finish, -EEXIST);
865 ASSERT_EQ(0, on_start_ready.wait());
866
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);
871
872 ASSERT_EQ(0, on_start_safe.wait());
873 ASSERT_EQ(0, on_finish_ready.wait());
874 ASSERT_EQ(0, on_finish_safe.wait());
875 }
876
877 TEST_F(TestMockJournalReplay, SnapRemoveEvent) {
878 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
879
880 librbd::ImageCtx *ictx;
881 ASSERT_EQ(0, open_image(m_image_name, &ictx));
882
883 MockReplayImageCtx mock_image_ctx(*ictx);
884 MockJournalReplay mock_journal_replay(mock_image_ctx);
885 expect_op_work_queue(mock_image_ctx);
886
887 InSequence seq;
888 Context *on_finish = nullptr;
889 expect_refresh_image(mock_image_ctx, false, 0);
890 expect_snap_remove(mock_image_ctx, &on_finish, "snap");
891
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(),
897 "snap")},
898 &on_start_ready,
899 &on_start_safe);
900 ASSERT_EQ(0, on_start_ready.wait());
901
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);
906
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());
911 }
912
913 TEST_F(TestMockJournalReplay, SnapRemoveEventDNE) {
914 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
915
916 librbd::ImageCtx *ictx;
917 ASSERT_EQ(0, open_image(m_image_name, &ictx));
918
919 MockReplayImageCtx mock_image_ctx(*ictx);
920 MockJournalReplay mock_journal_replay(mock_image_ctx);
921 expect_op_work_queue(mock_image_ctx);
922
923 InSequence seq;
924 Context *on_finish = nullptr;
925 expect_refresh_image(mock_image_ctx, false, 0);
926 expect_snap_remove(mock_image_ctx, &on_finish, "snap");
927
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(),
933 "snap")},
934 &on_start_ready,
935 &on_start_safe);
936 ASSERT_EQ(0, on_start_ready.wait());
937
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);
942
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());
947 }
948
949 TEST_F(TestMockJournalReplay, SnapRenameEvent) {
950 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
951
952 librbd::ImageCtx *ictx;
953 ASSERT_EQ(0, open_image(m_image_name, &ictx));
954
955 MockReplayImageCtx mock_image_ctx(*ictx);
956 MockJournalReplay mock_journal_replay(mock_image_ctx);
957 expect_op_work_queue(mock_image_ctx);
958
959 InSequence seq;
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");
963
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());
970
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);
975
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());
980 }
981
982 TEST_F(TestMockJournalReplay, SnapRenameEventExists) {
983 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
984
985 librbd::ImageCtx *ictx;
986 ASSERT_EQ(0, open_image(m_image_name, &ictx));
987
988 MockReplayImageCtx mock_image_ctx(*ictx);
989 MockJournalReplay mock_journal_replay(mock_image_ctx);
990 expect_op_work_queue(mock_image_ctx);
991
992 InSequence seq;
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");
996
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());
1003
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);
1008
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());
1013 }
1014
1015 TEST_F(TestMockJournalReplay, SnapProtectEvent) {
1016 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
1017
1018 librbd::ImageCtx *ictx;
1019 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1020
1021 MockReplayImageCtx mock_image_ctx(*ictx);
1022 MockJournalReplay mock_journal_replay(mock_image_ctx);
1023 expect_op_work_queue(mock_image_ctx);
1024
1025 InSequence seq;
1026 Context *on_finish = nullptr;
1027 expect_refresh_image(mock_image_ctx, false, 0);
1028 expect_snap_protect(mock_image_ctx, &on_finish, "snap");
1029
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(),
1035 "snap")},
1036 &on_start_ready,
1037 &on_start_safe);
1038 ASSERT_EQ(0, on_start_ready.wait());
1039
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);
1044
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());
1049 }
1050
1051 TEST_F(TestMockJournalReplay, SnapProtectEventBusy) {
1052 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
1053
1054 librbd::ImageCtx *ictx;
1055 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1056
1057 MockReplayImageCtx mock_image_ctx(*ictx);
1058 MockJournalReplay mock_journal_replay(mock_image_ctx);
1059 expect_op_work_queue(mock_image_ctx);
1060
1061 InSequence seq;
1062 Context *on_finish = nullptr;
1063 expect_refresh_image(mock_image_ctx, false, 0);
1064 expect_snap_protect(mock_image_ctx, &on_finish, "snap");
1065
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(),
1071 "snap")},
1072 &on_start_ready,
1073 &on_start_safe);
1074 ASSERT_EQ(0, on_start_ready.wait());
1075
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);
1080
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());
1085 }
1086
1087 TEST_F(TestMockJournalReplay, SnapUnprotectEvent) {
1088 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
1089
1090 librbd::ImageCtx *ictx;
1091 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1092
1093 MockReplayImageCtx mock_image_ctx(*ictx);
1094 MockJournalReplay mock_journal_replay(mock_image_ctx);
1095 expect_op_work_queue(mock_image_ctx);
1096
1097 InSequence seq;
1098 Context *on_finish = nullptr;
1099 expect_refresh_image(mock_image_ctx, false, 0);
1100 expect_snap_unprotect(mock_image_ctx, &on_finish, "snap");
1101
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(),
1107 "snap")},
1108 &on_start_ready,
1109 &on_start_safe);
1110 ASSERT_EQ(0, on_start_ready.wait());
1111
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);
1116
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());
1121 }
1122
1123 TEST_F(TestMockJournalReplay, SnapUnprotectOpFinishBusy) {
1124 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
1125
1126 librbd::ImageCtx *ictx;
1127 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1128
1129 MockReplayImageCtx mock_image_ctx(*ictx);
1130 MockJournalReplay mock_journal_replay(mock_image_ctx);
1131 expect_op_work_queue(mock_image_ctx);
1132
1133 InSequence seq;
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(),
1139 "snap")},
1140 &on_start_ready,
1141 &on_start_safe);
1142 ASSERT_EQ(0, on_start_ready.wait());
1143
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);
1149
1150 ASSERT_EQ(0, on_start_safe.wait());
1151 ASSERT_EQ(0, on_finish_safe.wait());
1152 ASSERT_EQ(0, on_finish_ready.wait());
1153 }
1154
1155 TEST_F(TestMockJournalReplay, SnapUnprotectEventInvalid) {
1156 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
1157
1158 librbd::ImageCtx *ictx;
1159 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1160
1161 MockReplayImageCtx mock_image_ctx(*ictx);
1162 MockJournalReplay mock_journal_replay(mock_image_ctx);
1163 expect_op_work_queue(mock_image_ctx);
1164
1165 InSequence seq;
1166 Context *on_finish = nullptr;
1167 expect_refresh_image(mock_image_ctx, false, 0);
1168 expect_snap_unprotect(mock_image_ctx, &on_finish, "snap");
1169
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(),
1175 "snap")},
1176 &on_start_ready,
1177 &on_start_safe);
1178 ASSERT_EQ(0, on_start_ready.wait());
1179
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);
1184
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());
1189 }
1190
1191 TEST_F(TestMockJournalReplay, SnapRollbackEvent) {
1192 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
1193
1194 librbd::ImageCtx *ictx;
1195 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1196
1197 MockReplayImageCtx mock_image_ctx(*ictx);
1198 MockJournalReplay mock_journal_replay(mock_image_ctx);
1199 expect_op_work_queue(mock_image_ctx);
1200
1201 InSequence seq;
1202 Context *on_finish = nullptr;
1203 expect_refresh_image(mock_image_ctx, false, 0);
1204 expect_snap_rollback(mock_image_ctx, &on_finish, "snap");
1205
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(),
1211 "snap")},
1212 &on_start_ready,
1213 &on_start_safe);
1214 ASSERT_EQ(0, on_start_ready.wait());
1215
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);
1220
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());
1225 }
1226
1227 TEST_F(TestMockJournalReplay, RenameEvent) {
1228 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
1229
1230 librbd::ImageCtx *ictx;
1231 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1232
1233 MockReplayImageCtx mock_image_ctx(*ictx);
1234 MockJournalReplay mock_journal_replay(mock_image_ctx);
1235 expect_op_work_queue(mock_image_ctx);
1236
1237 InSequence seq;
1238 Context *on_finish = nullptr;
1239 expect_refresh_image(mock_image_ctx, false, 0);
1240 expect_rename(mock_image_ctx, &on_finish, "image");
1241
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());
1247
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);
1252
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());
1257 }
1258
1259 TEST_F(TestMockJournalReplay, RenameEventExists) {
1260 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
1261
1262 librbd::ImageCtx *ictx;
1263 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1264
1265 MockReplayImageCtx mock_image_ctx(*ictx);
1266 MockJournalReplay mock_journal_replay(mock_image_ctx);
1267 expect_op_work_queue(mock_image_ctx);
1268
1269 InSequence seq;
1270 Context *on_finish = nullptr;
1271 expect_refresh_image(mock_image_ctx, false, 0);
1272 expect_rename(mock_image_ctx, &on_finish, "image");
1273
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());
1279
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);
1284
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());
1289 }
1290
1291 TEST_F(TestMockJournalReplay, ResizeEvent) {
1292 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
1293
1294 librbd::ImageCtx *ictx;
1295 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1296
1297 MockReplayImageCtx mock_image_ctx(*ictx);
1298 MockJournalReplay mock_journal_replay(mock_image_ctx);
1299 expect_op_work_queue(mock_image_ctx);
1300
1301 InSequence seq;
1302 Context *on_finish = nullptr;
1303 expect_refresh_image(mock_image_ctx, false, 0);
1304 expect_resize(mock_image_ctx, &on_finish, 234, 123);
1305
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);
1310
1311 C_SaferCond on_resume;
1312 when_replay_op_ready(mock_journal_replay, 123, &on_resume);
1313 ASSERT_EQ(0, on_start_ready.wait());
1314
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);
1319
1320 ASSERT_EQ(0, on_resume.wait());
1321 wait_for_op_invoked(&on_finish, 0);
1322
1323 ASSERT_EQ(0, on_start_safe.wait());
1324 ASSERT_EQ(0, on_finish_ready.wait());
1325 ASSERT_EQ(0, on_finish_safe.wait());
1326 }
1327
1328 TEST_F(TestMockJournalReplay, FlattenEvent) {
1329 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
1330
1331 librbd::ImageCtx *ictx;
1332 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1333
1334 MockReplayImageCtx mock_image_ctx(*ictx);
1335 MockJournalReplay mock_journal_replay(mock_image_ctx);
1336 expect_op_work_queue(mock_image_ctx);
1337
1338 InSequence seq;
1339 Context *on_finish = nullptr;
1340 expect_refresh_image(mock_image_ctx, false, 0);
1341 expect_flatten(mock_image_ctx, &on_finish);
1342
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());
1348
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);
1353
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());
1358 }
1359
1360 TEST_F(TestMockJournalReplay, FlattenEventInvalid) {
1361 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
1362
1363 librbd::ImageCtx *ictx;
1364 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1365
1366 MockReplayImageCtx mock_image_ctx(*ictx);
1367 MockJournalReplay mock_journal_replay(mock_image_ctx);
1368 expect_op_work_queue(mock_image_ctx);
1369
1370 InSequence seq;
1371 Context *on_finish = nullptr;
1372 expect_refresh_image(mock_image_ctx, false, 0);
1373 expect_flatten(mock_image_ctx, &on_finish);
1374
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());
1380
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);
1385
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());
1390 }
1391
1392 TEST_F(TestMockJournalReplay, UpdateFeaturesEvent) {
1393 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
1394
1395 librbd::ImageCtx *ictx;
1396 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1397
1398 uint64_t features = RBD_FEATURE_OBJECT_MAP | RBD_FEATURE_FAST_DIFF;
1399 bool enabled = !ictx->test_features(features);
1400
1401 MockReplayImageCtx mock_image_ctx(*ictx);
1402 MockJournalReplay mock_journal_replay(mock_image_ctx);
1403 expect_op_work_queue(mock_image_ctx);
1404
1405 InSequence seq;
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);
1409
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);
1415
1416 C_SaferCond on_resume;
1417 when_replay_op_ready(mock_journal_replay, 123, &on_resume);
1418 ASSERT_EQ(0, on_start_ready.wait());
1419
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);
1424
1425 ASSERT_EQ(0, on_resume.wait());
1426 wait_for_op_invoked(&on_finish, 0);
1427
1428 ASSERT_EQ(0, on_start_safe.wait());
1429 ASSERT_EQ(0, on_finish_ready.wait());
1430 ASSERT_EQ(0, on_finish_safe.wait());
1431 }
1432
1433 TEST_F(TestMockJournalReplay, MetadataSetEvent) {
1434 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
1435
1436 librbd::ImageCtx *ictx;
1437 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1438
1439 MockReplayImageCtx mock_image_ctx(*ictx);
1440 MockJournalReplay mock_journal_replay(mock_image_ctx);
1441 expect_op_work_queue(mock_image_ctx);
1442
1443 InSequence seq;
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");
1447
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());
1453
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);
1458
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());
1463 }
1464
1465 TEST_F(TestMockJournalReplay, MetadataRemoveEvent) {
1466 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
1467
1468 librbd::ImageCtx *ictx;
1469 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1470
1471 MockReplayImageCtx mock_image_ctx(*ictx);
1472 MockJournalReplay mock_journal_replay(mock_image_ctx);
1473 expect_op_work_queue(mock_image_ctx);
1474
1475 InSequence seq;
1476 Context *on_finish = nullptr;
1477 expect_refresh_image(mock_image_ctx, false, 0);
1478 expect_metadata_remove(mock_image_ctx, &on_finish, "key");
1479
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());
1485
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);
1490
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());
1495 }
1496
1497 TEST_F(TestMockJournalReplay, MetadataRemoveEventDNE) {
1498 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
1499
1500 librbd::ImageCtx *ictx;
1501 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1502
1503 MockReplayImageCtx mock_image_ctx(*ictx);
1504 MockJournalReplay mock_journal_replay(mock_image_ctx);
1505 expect_op_work_queue(mock_image_ctx);
1506
1507 InSequence seq;
1508 Context *on_finish = nullptr;
1509 expect_refresh_image(mock_image_ctx, false, 0);
1510 expect_metadata_remove(mock_image_ctx, &on_finish, "key");
1511
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());
1517
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);
1522
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());
1527 }
1528
1529 TEST_F(TestMockJournalReplay, UnknownEvent) {
1530 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
1531
1532 librbd::ImageCtx *ictx;
1533 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1534
1535 MockReplayImageCtx mock_image_ctx(*ictx);
1536 MockJournalReplay mock_journal_replay(mock_image_ctx);
1537 expect_op_work_queue(mock_image_ctx);
1538
1539 InSequence seq;
1540
1541 bufferlist bl;
1542 ENCODE_START(1, 1, bl);
1543 ::encode(static_cast<uint32_t>(-1), bl);
1544 ENCODE_FINISH(bl);
1545
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);
1550
1551 ASSERT_EQ(0, on_safe.wait());
1552 ASSERT_EQ(0, on_ready.wait());
1553 }
1554
1555 TEST_F(TestMockJournalReplay, RefreshImageBeforeOpStart) {
1556 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
1557
1558 librbd::ImageCtx *ictx;
1559 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1560
1561 MockReplayImageCtx mock_image_ctx(*ictx);
1562 MockJournalReplay mock_journal_replay(mock_image_ctx);
1563 expect_op_work_queue(mock_image_ctx);
1564
1565 InSequence seq;
1566 Context *on_finish = nullptr;
1567 expect_refresh_image(mock_image_ctx, true, 0);
1568 expect_resize(mock_image_ctx, &on_finish, 234, 123);
1569
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);
1574
1575 C_SaferCond on_resume;
1576 when_replay_op_ready(mock_journal_replay, 123, &on_resume);
1577 ASSERT_EQ(0, on_start_ready.wait());
1578
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);
1583
1584 ASSERT_EQ(0, on_resume.wait());
1585 wait_for_op_invoked(&on_finish, 0);
1586
1587 ASSERT_EQ(0, on_start_safe.wait());
1588 ASSERT_EQ(0, on_finish_ready.wait());
1589 ASSERT_EQ(0, on_finish_safe.wait());
1590 }
1591
1592 } // namespace journal
1593 } // namespace librbd