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 "test/librbd/mock/MockJournal.h"
8 #include "test/librbd/mock/MockJournalPolicy.h"
9 #include "test/librbd/mock/MockObjectMap.h"
10 #include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
11 #include "test/librados_test_stub/MockTestMemRadosClient.h"
12 #include "librbd/ImageState.h"
13 #include "librbd/internal.h"
14 #include "librbd/Operations.h"
15 #include "librbd/image/RefreshRequest.h"
16 #include "librbd/image/RefreshParentRequest.h"
17 #include "gmock/gmock.h"
18 #include "gtest/gtest.h"
19 #include <arpa/inet.h>
21 #include <boost/scope_exit.hpp>
27 struct MockRefreshImageCtx : public MockImageCtx {
28 MockRefreshImageCtx(ImageCtx &image_ctx) : MockImageCtx(image_ctx) {
32 } // anonymous namespace
37 struct RefreshParentRequest<MockRefreshImageCtx> {
38 static RefreshParentRequest* s_instance;
39 static RefreshParentRequest* create(MockRefreshImageCtx &mock_image_ctx,
40 const ParentInfo& parent_md,
42 assert(s_instance != nullptr);
43 s_instance->on_finish = on_finish;
46 static bool is_refresh_required(MockRefreshImageCtx &mock_image_ctx,
47 const ParentInfo& parent_md) {
48 assert(s_instance != nullptr);
49 return s_instance->is_refresh_required();
52 Context *on_finish = nullptr;
54 RefreshParentRequest() {
58 MOCK_CONST_METHOD0(is_refresh_required, bool());
59 MOCK_METHOD0(send, void());
60 MOCK_METHOD0(apply, void());
61 MOCK_METHOD1(finalize, void(Context *));
64 RefreshParentRequest<MockRefreshImageCtx>* RefreshParentRequest<MockRefreshImageCtx>::s_instance = nullptr;
69 // template definitions
70 #include "librbd/image/RefreshRequest.cc"
71 template class librbd::image::RefreshRequest<librbd::MockRefreshImageCtx>;
73 ACTION_P(TestFeatures, image_ctx) {
74 return ((image_ctx->features & arg0) != 0);
77 ACTION_P(ShutDownExclusiveLock, image_ctx) {
78 // shutting down exclusive lock will close object map and journal
79 image_ctx->exclusive_lock = nullptr;
80 image_ctx->object_map = nullptr;
81 image_ctx->journal = nullptr;
88 using ::testing::DoAll;
89 using ::testing::DoDefault;
90 using ::testing::InSequence;
91 using ::testing::Return;
92 using ::testing::WithArg;
93 using ::testing::StrEq;
95 class TestMockImageRefreshRequest : public TestMockFixture {
97 typedef RefreshRequest<MockRefreshImageCtx> MockRefreshRequest;
98 typedef RefreshParentRequest<MockRefreshImageCtx> MockRefreshParentRequest;
100 void expect_set_require_lock(MockRefreshImageCtx &mock_image_ctx,
101 librbd::io::Direction direction, bool enabled) {
102 EXPECT_CALL(*mock_image_ctx.io_work_queue, set_require_lock(direction,
106 void expect_v1_read_header(MockRefreshImageCtx &mock_image_ctx, int r) {
107 auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
108 read(mock_image_ctx.header_oid, _, _, _));
110 expect.WillOnce(Return(r));
112 expect.WillOnce(DoDefault());
116 void expect_v1_get_snapshots(MockRefreshImageCtx &mock_image_ctx, int r) {
117 auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
118 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("snap_list"), _, _, _));
120 expect.WillOnce(Return(r));
122 expect.WillOnce(DoDefault());
126 void expect_v1_get_locks(MockRefreshImageCtx &mock_image_ctx, int r) {
127 auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
128 exec(mock_image_ctx.header_oid, _, StrEq("lock"), StrEq("get_info"), _, _, _));
130 expect.WillOnce(Return(r));
132 expect.WillOnce(DoDefault());
136 void expect_get_mutable_metadata(MockRefreshImageCtx &mock_image_ctx, int r) {
137 auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
138 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_size"), _, _, _));
140 expect.WillOnce(Return(r));
142 expect.WillOnce(DoDefault());
143 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
144 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_features"), _, _, _))
145 .WillOnce(DoDefault());
146 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
147 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_snapcontext"), _, _, _))
148 .WillOnce(DoDefault());
149 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
150 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_parent"), _, _, _))
151 .WillOnce(DoDefault());
152 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
153 exec(mock_image_ctx.header_oid, _, StrEq("lock"), StrEq("get_info"), _, _, _))
154 .WillOnce(DoDefault());
158 void expect_get_flags(MockRefreshImageCtx &mock_image_ctx, int r) {
159 auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
160 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_flags"), _, _, _));
162 expect.WillOnce(Return(r));
164 expect.WillOnce(DoDefault());
168 void expect_get_group(MockRefreshImageCtx &mock_image_ctx, int r) {
169 auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
170 exec(mock_image_ctx.header_oid, _, StrEq("rbd"),
171 StrEq("image_get_group"), _, _, _));
173 expect.WillOnce(Return(r));
175 expect.WillOnce(DoDefault());
180 void expect_get_snapshots(MockRefreshImageCtx &mock_image_ctx, int r) {
181 auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
182 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_snapshot_name"), _, _, _));
184 expect.WillOnce(Return(r));
186 expect.WillOnce(DoDefault());
187 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
188 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_size"), _, _, _))
189 .WillOnce(DoDefault());
190 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
191 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_parent"), _, _, _))
192 .WillOnce(DoDefault());
193 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
194 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_protection_status"), _, _, _))
195 .WillOnce(DoDefault());
199 void expect_snap_timestamp_list(MockRefreshImageCtx &mock_image_ctx, int r) {
200 auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
201 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_snapshot_timestamp"), _, _, _));
203 expect.WillOnce(Return(r));
205 expect.WillOnce(DoDefault());
209 void expect_snap_namespace_list(MockRefreshImageCtx &mock_image_ctx, int r) {
210 auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
211 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_snapshot_namespace"), _, _, _));
213 expect.WillOnce(Return(r));
215 expect.WillOnce(DoDefault());
219 void expect_add_snap(MockRefreshImageCtx &mock_image_ctx,
220 const std::string &snap_name, uint64_t snap_id) {
221 EXPECT_CALL(mock_image_ctx, add_snap(_, snap_name, snap_id, _, _, _, _, _));
224 void expect_init_exclusive_lock(MockRefreshImageCtx &mock_image_ctx,
225 MockExclusiveLock &mock_exclusive_lock,
227 EXPECT_CALL(mock_image_ctx, create_exclusive_lock())
228 .WillOnce(Return(&mock_exclusive_lock));
229 EXPECT_CALL(mock_exclusive_lock, init(mock_image_ctx.features, _))
230 .WillOnce(WithArg<1>(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue)));
233 void expect_shut_down_exclusive_lock(MockRefreshImageCtx &mock_image_ctx,
234 MockExclusiveLock &mock_exclusive_lock,
236 EXPECT_CALL(mock_exclusive_lock, shut_down(_))
237 .WillOnce(DoAll(ShutDownExclusiveLock(&mock_image_ctx),
238 CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue)));
241 void expect_init_layout(MockRefreshImageCtx &mock_image_ctx) {
242 EXPECT_CALL(mock_image_ctx, init_layout());
245 void expect_test_features(MockRefreshImageCtx &mock_image_ctx) {
246 EXPECT_CALL(mock_image_ctx, test_features(_, _))
247 .WillRepeatedly(TestFeatures(&mock_image_ctx));
250 void expect_refresh_parent_is_required(MockRefreshParentRequest &mock_refresh_parent_request,
252 EXPECT_CALL(mock_refresh_parent_request, is_refresh_required())
253 .WillRepeatedly(Return(required));
256 void expect_refresh_parent_send(MockRefreshImageCtx &mock_image_ctx,
257 MockRefreshParentRequest &mock_refresh_parent_request,
259 EXPECT_CALL(mock_refresh_parent_request, send())
260 .WillOnce(FinishRequest(&mock_refresh_parent_request, r,
264 void expect_refresh_parent_apply(MockRefreshParentRequest &mock_refresh_parent_request) {
265 EXPECT_CALL(mock_refresh_parent_request, apply());
268 void expect_refresh_parent_finalize(MockRefreshImageCtx &mock_image_ctx,
269 MockRefreshParentRequest &mock_refresh_parent_request,
271 EXPECT_CALL(mock_refresh_parent_request, finalize(_))
272 .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
275 void expect_is_exclusive_lock_owner(MockExclusiveLock &mock_exclusive_lock,
277 EXPECT_CALL(mock_exclusive_lock, is_lock_owner()).WillOnce(Return(is_owner));
280 void expect_get_journal_policy(MockImageCtx &mock_image_ctx,
281 MockJournalPolicy &mock_journal_policy) {
282 EXPECT_CALL(mock_image_ctx, get_journal_policy())
283 .WillOnce(Return(&mock_journal_policy));
286 void expect_journal_disabled(MockJournalPolicy &mock_journal_policy,
288 EXPECT_CALL(mock_journal_policy, journal_disabled())
289 .WillOnce(Return(disabled));
292 void expect_open_journal(MockRefreshImageCtx &mock_image_ctx,
293 MockJournal &mock_journal, int r) {
294 EXPECT_CALL(mock_image_ctx, create_journal())
295 .WillOnce(Return(&mock_journal));
296 EXPECT_CALL(mock_journal, open(_))
297 .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
300 void expect_close_journal(MockRefreshImageCtx &mock_image_ctx,
301 MockJournal &mock_journal, int r) {
302 EXPECT_CALL(mock_journal, close(_))
303 .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
306 void expect_open_object_map(MockRefreshImageCtx &mock_image_ctx,
307 MockObjectMap *mock_object_map, int r) {
308 EXPECT_CALL(mock_image_ctx, create_object_map(_))
309 .WillOnce(Return(mock_object_map));
310 EXPECT_CALL(*mock_object_map, open(_))
311 .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
314 void expect_close_object_map(MockRefreshImageCtx &mock_image_ctx,
315 MockObjectMap &mock_object_map, int r) {
316 EXPECT_CALL(mock_object_map, close(_))
317 .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
320 void expect_get_snap_id(MockRefreshImageCtx &mock_image_ctx,
321 const std::string &snap_name,
323 EXPECT_CALL(mock_image_ctx,
324 get_snap_id(_, snap_name)).WillOnce(Return(snap_id));
327 void expect_block_writes(MockImageCtx &mock_image_ctx, int r) {
328 EXPECT_CALL(*mock_image_ctx.io_work_queue, block_writes(_))
329 .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
332 void expect_unblock_writes(MockImageCtx &mock_image_ctx) {
333 EXPECT_CALL(*mock_image_ctx.io_work_queue, unblock_writes())
339 TEST_F(TestMockImageRefreshRequest, SuccessV1) {
342 librbd::ImageCtx *ictx;
343 ASSERT_EQ(0, open_image(m_image_name, &ictx));
345 MockRefreshImageCtx mock_image_ctx(*ictx);
346 expect_op_work_queue(mock_image_ctx);
347 expect_test_features(mock_image_ctx);
350 expect_v1_read_header(mock_image_ctx, 0);
351 expect_v1_get_snapshots(mock_image_ctx, 0);
352 expect_v1_get_locks(mock_image_ctx, 0);
353 expect_init_layout(mock_image_ctx);
356 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
359 ASSERT_EQ(0, ctx.wait());
362 TEST_F(TestMockImageRefreshRequest, SuccessSnapshotV1) {
364 librbd::ImageCtx *ictx;
365 ASSERT_EQ(0, open_image(m_image_name, &ictx));
366 ASSERT_EQ(0, snap_create(*ictx, "snap"));
367 ASSERT_EQ(0, ictx->state->refresh());
369 MockRefreshImageCtx mock_image_ctx(*ictx);
370 expect_op_work_queue(mock_image_ctx);
371 expect_test_features(mock_image_ctx);
374 expect_v1_read_header(mock_image_ctx, 0);
375 expect_v1_get_snapshots(mock_image_ctx, 0);
376 expect_v1_get_locks(mock_image_ctx, 0);
377 expect_init_layout(mock_image_ctx);
378 expect_add_snap(mock_image_ctx, "snap", ictx->snap_ids.begin()->second);
381 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
384 ASSERT_EQ(0, ctx.wait());
387 TEST_F(TestMockImageRefreshRequest, SuccessV2) {
390 librbd::ImageCtx *ictx;
391 ASSERT_EQ(0, open_image(m_image_name, &ictx));
393 MockRefreshImageCtx mock_image_ctx(*ictx);
394 MockRefreshParentRequest mock_refresh_parent_request;
395 MockExclusiveLock mock_exclusive_lock;
396 expect_op_work_queue(mock_image_ctx);
397 expect_test_features(mock_image_ctx);
400 expect_get_mutable_metadata(mock_image_ctx, 0);
401 expect_get_flags(mock_image_ctx, 0);
402 expect_get_group(mock_image_ctx, 0);
403 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
404 if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
405 expect_init_exclusive_lock(mock_image_ctx, mock_exclusive_lock, 0);
409 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
412 ASSERT_EQ(0, ctx.wait());
415 TEST_F(TestMockImageRefreshRequest, SuccessSnapshotV2) {
418 librbd::ImageCtx *ictx;
419 ASSERT_EQ(0, open_image(m_image_name, &ictx));
420 ASSERT_EQ(0, snap_create(*ictx, "snap"));
422 MockRefreshImageCtx mock_image_ctx(*ictx);
423 MockRefreshParentRequest mock_refresh_parent_request;
424 MockExclusiveLock mock_exclusive_lock;
425 expect_op_work_queue(mock_image_ctx);
426 expect_test_features(mock_image_ctx);
429 expect_get_mutable_metadata(mock_image_ctx, 0);
430 expect_get_flags(mock_image_ctx, 0);
431 expect_get_flags(mock_image_ctx, 0);
432 expect_get_group(mock_image_ctx, 0);
433 expect_get_snapshots(mock_image_ctx, 0);
434 expect_snap_timestamp_list(mock_image_ctx, 0);
435 expect_snap_namespace_list(mock_image_ctx, 0);
436 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
437 if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
438 expect_init_exclusive_lock(mock_image_ctx, mock_exclusive_lock, 0);
440 expect_add_snap(mock_image_ctx, "snap", ictx->snap_ids.begin()->second);
443 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
446 ASSERT_EQ(0, ctx.wait());
449 TEST_F(TestMockImageRefreshRequest, SuccessSetSnapshotV2) {
452 librbd::ImageCtx *ictx;
453 ASSERT_EQ(0, open_image(m_image_name, &ictx));
454 ASSERT_EQ(0, snap_create(*ictx, "snap"));
455 ASSERT_EQ(0, librbd::snap_set(ictx, cls::rbd::UserSnapshotNamespace(), "snap"));
457 MockRefreshImageCtx mock_image_ctx(*ictx);
458 MockRefreshParentRequest mock_refresh_parent_request;
459 MockObjectMap mock_object_map;
460 expect_op_work_queue(mock_image_ctx);
461 expect_test_features(mock_image_ctx);
464 expect_get_mutable_metadata(mock_image_ctx, 0);
465 expect_get_flags(mock_image_ctx, 0);
466 expect_get_flags(mock_image_ctx, 0);
467 expect_get_group(mock_image_ctx, 0);
468 expect_get_snapshots(mock_image_ctx, 0);
469 expect_snap_timestamp_list(mock_image_ctx, 0);
470 expect_snap_namespace_list(mock_image_ctx, 0);
471 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
472 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
473 expect_open_object_map(mock_image_ctx, &mock_object_map, 0);
475 expect_add_snap(mock_image_ctx, "snap", ictx->snap_ids.begin()->second);
476 expect_get_snap_id(mock_image_ctx, "snap", ictx->snap_ids.begin()->second);
479 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
482 ASSERT_EQ(0, ctx.wait());
485 TEST_F(TestMockImageRefreshRequest, SuccessChild) {
486 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
488 librbd::ImageCtx *ictx;
489 librbd::ImageCtx *ictx2 = nullptr;
490 std::string clone_name = get_temp_image_name();
492 ASSERT_EQ(0, open_image(m_image_name, &ictx));
493 ASSERT_EQ(0, snap_create(*ictx, "snap"));
494 ASSERT_EQ(0, snap_protect(*ictx, "snap"));
495 BOOST_SCOPE_EXIT_ALL((&)) {
496 if (ictx2 != nullptr) {
500 librbd::NoOpProgressContext no_op;
501 ASSERT_EQ(0, librbd::remove(m_ioctx, clone_name, "", no_op));
502 ASSERT_EQ(0, ictx->operations->snap_unprotect(cls::rbd::UserSnapshotNamespace(), "snap"));
505 int order = ictx->order;
506 ASSERT_EQ(0, librbd::clone(m_ioctx, m_image_name.c_str(), "snap", m_ioctx,
507 clone_name.c_str(), ictx->features, &order, 0, 0));
509 ASSERT_EQ(0, open_image(clone_name, &ictx2));
511 MockRefreshImageCtx mock_image_ctx(*ictx2);
512 MockRefreshParentRequest *mock_refresh_parent_request = new MockRefreshParentRequest();
513 MockExclusiveLock mock_exclusive_lock;
514 expect_op_work_queue(mock_image_ctx);
515 expect_test_features(mock_image_ctx);
518 expect_get_mutable_metadata(mock_image_ctx, 0);
519 expect_get_flags(mock_image_ctx, 0);
520 expect_get_group(mock_image_ctx, 0);
521 expect_refresh_parent_is_required(*mock_refresh_parent_request, true);
522 expect_refresh_parent_send(mock_image_ctx, *mock_refresh_parent_request, 0);
523 if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
524 expect_init_exclusive_lock(mock_image_ctx, mock_exclusive_lock, 0);
526 expect_refresh_parent_apply(*mock_refresh_parent_request);
527 expect_refresh_parent_finalize(mock_image_ctx, *mock_refresh_parent_request, 0);
530 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
533 ASSERT_EQ(0, ctx.wait());
536 TEST_F(TestMockImageRefreshRequest, SuccessChildDontOpenParent) {
537 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
539 librbd::ImageCtx *ictx;
540 librbd::ImageCtx *ictx2 = nullptr;
541 std::string clone_name = get_temp_image_name();
543 ASSERT_EQ(0, open_image(m_image_name, &ictx));
544 ASSERT_EQ(0, snap_create(*ictx, "snap"));
545 ASSERT_EQ(0, snap_protect(*ictx, "snap"));
546 BOOST_SCOPE_EXIT_ALL((&)) {
547 if (ictx2 != nullptr) {
551 librbd::NoOpProgressContext no_op;
552 ASSERT_EQ(0, librbd::remove(m_ioctx, clone_name, "", no_op));
553 ASSERT_EQ(0, ictx->operations->snap_unprotect(cls::rbd::UserSnapshotNamespace(), "snap"));
556 int order = ictx->order;
557 ASSERT_EQ(0, librbd::clone(m_ioctx, m_image_name.c_str(), "snap", m_ioctx,
558 clone_name.c_str(), ictx->features, &order, 0, 0));
560 ASSERT_EQ(0, open_image(clone_name, &ictx2));
562 MockRefreshImageCtx mock_image_ctx(*ictx2);
563 MockExclusiveLock mock_exclusive_lock;
564 expect_op_work_queue(mock_image_ctx);
565 expect_test_features(mock_image_ctx);
568 expect_get_mutable_metadata(mock_image_ctx, 0);
569 expect_get_flags(mock_image_ctx, 0);
570 expect_get_group(mock_image_ctx, 0);
571 if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
572 expect_init_exclusive_lock(mock_image_ctx, mock_exclusive_lock, 0);
576 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, true, &ctx);
579 ASSERT_EQ(0, ctx.wait());
582 TEST_F(TestMockImageRefreshRequest, DisableExclusiveLock) {
583 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
585 librbd::ImageCtx *ictx;
586 ASSERT_EQ(0, open_image(m_image_name, &ictx));
588 MockRefreshImageCtx mock_image_ctx(*ictx);
589 MockRefreshParentRequest mock_refresh_parent_request;
591 MockExclusiveLock *mock_exclusive_lock = new MockExclusiveLock();
592 mock_image_ctx.exclusive_lock = mock_exclusive_lock;
594 MockObjectMap mock_object_map;
595 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
596 mock_image_ctx.object_map = &mock_object_map;
599 MockJournal mock_journal;
600 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
601 mock_image_ctx.journal = &mock_journal;
604 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
605 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
609 if (ictx->test_features(RBD_FEATURE_FAST_DIFF)) {
610 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_FAST_DIFF,
614 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
615 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_OBJECT_MAP,
619 if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
620 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_EXCLUSIVE_LOCK,
624 expect_op_work_queue(mock_image_ctx);
625 expect_test_features(mock_image_ctx);
627 // verify that exclusive lock is properly handled when object map
628 // and journaling were never enabled (or active)
630 expect_get_mutable_metadata(mock_image_ctx, 0);
631 expect_get_flags(mock_image_ctx, 0);
632 expect_get_group(mock_image_ctx, 0);
633 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
634 expect_shut_down_exclusive_lock(mock_image_ctx, *mock_exclusive_lock, 0);
637 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
640 ASSERT_EQ(0, ctx.wait());
643 TEST_F(TestMockImageRefreshRequest, DisableExclusiveLockWhileAcquiringLock) {
644 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
646 librbd::ImageCtx *ictx;
647 ASSERT_EQ(0, open_image(m_image_name, &ictx));
649 MockRefreshImageCtx mock_image_ctx(*ictx);
650 MockRefreshParentRequest mock_refresh_parent_request;
652 MockExclusiveLock mock_exclusive_lock;
653 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
655 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
656 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
660 if (ictx->test_features(RBD_FEATURE_FAST_DIFF)) {
661 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_FAST_DIFF,
665 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
666 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_OBJECT_MAP,
670 if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
671 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_EXCLUSIVE_LOCK,
675 expect_op_work_queue(mock_image_ctx);
676 expect_test_features(mock_image_ctx);
678 // verify that exclusive lock is properly handled when object map
679 // and journaling were never enabled (or active)
681 expect_get_mutable_metadata(mock_image_ctx, 0);
682 expect_get_flags(mock_image_ctx, 0);
683 expect_get_group(mock_image_ctx, 0);
684 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
687 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, true, false, &ctx);
690 ASSERT_EQ(-ERESTART, ctx.wait());
693 TEST_F(TestMockImageRefreshRequest, JournalDisabledByPolicy) {
694 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
696 librbd::ImageCtx *ictx;
697 ASSERT_EQ(0, open_image(m_image_name, &ictx));
699 if (ictx->test_features(RBD_FEATURE_FAST_DIFF)) {
700 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_FAST_DIFF,
704 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
705 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_OBJECT_MAP,
709 MockRefreshImageCtx mock_image_ctx(*ictx);
710 MockRefreshParentRequest mock_refresh_parent_request;
712 MockExclusiveLock mock_exclusive_lock;
713 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
715 MockJournal mock_journal;
717 expect_op_work_queue(mock_image_ctx);
718 expect_test_features(mock_image_ctx);
719 expect_is_exclusive_lock_owner(mock_exclusive_lock, true);
722 expect_get_mutable_metadata(mock_image_ctx, 0);
723 expect_get_flags(mock_image_ctx, 0);
724 expect_get_group(mock_image_ctx, 0);
725 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
727 MockJournalPolicy mock_journal_policy;
728 expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
729 expect_journal_disabled(mock_journal_policy, true);
732 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
735 ASSERT_EQ(0, ctx.wait());
738 TEST_F(TestMockImageRefreshRequest, EnableJournalWithExclusiveLock) {
739 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
741 librbd::ImageCtx *ictx;
742 ASSERT_EQ(0, open_image(m_image_name, &ictx));
744 if (ictx->test_features(RBD_FEATURE_FAST_DIFF)) {
745 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_FAST_DIFF,
749 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
750 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_OBJECT_MAP,
754 MockRefreshImageCtx mock_image_ctx(*ictx);
755 MockRefreshParentRequest mock_refresh_parent_request;
757 MockExclusiveLock mock_exclusive_lock;
758 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
760 MockJournal mock_journal;
762 expect_op_work_queue(mock_image_ctx);
763 expect_test_features(mock_image_ctx);
764 expect_is_exclusive_lock_owner(mock_exclusive_lock, true);
766 // journal should be immediately opened if exclusive lock owned
768 expect_get_mutable_metadata(mock_image_ctx, 0);
769 expect_get_flags(mock_image_ctx, 0);
770 expect_get_group(mock_image_ctx, 0);
771 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
773 MockJournalPolicy mock_journal_policy;
774 expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
775 expect_journal_disabled(mock_journal_policy, false);
776 expect_open_journal(mock_image_ctx, mock_journal, 0);
779 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
782 ASSERT_EQ(0, ctx.wait());
785 TEST_F(TestMockImageRefreshRequest, EnableJournalWithoutExclusiveLock) {
786 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
788 librbd::ImageCtx *ictx;
789 ASSERT_EQ(0, open_image(m_image_name, &ictx));
791 if (ictx->test_features(RBD_FEATURE_FAST_DIFF)) {
792 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_FAST_DIFF,
796 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
797 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_OBJECT_MAP,
801 MockRefreshImageCtx mock_image_ctx(*ictx);
802 MockRefreshParentRequest mock_refresh_parent_request;
804 MockExclusiveLock mock_exclusive_lock;
805 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
807 expect_op_work_queue(mock_image_ctx);
808 expect_test_features(mock_image_ctx);
809 expect_is_exclusive_lock_owner(mock_exclusive_lock, false);
811 // do not open the journal if exclusive lock is not owned
813 expect_get_mutable_metadata(mock_image_ctx, 0);
814 expect_get_flags(mock_image_ctx, 0);
815 expect_get_group(mock_image_ctx, 0);
816 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
817 expect_set_require_lock(mock_image_ctx, librbd::io::DIRECTION_BOTH, true);
820 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
823 ASSERT_EQ(0, ctx.wait());
826 TEST_F(TestMockImageRefreshRequest, DisableJournal) {
827 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
829 librbd::ImageCtx *ictx;
830 ASSERT_EQ(0, open_image(m_image_name, &ictx));
832 MockRefreshImageCtx mock_image_ctx(*ictx);
833 MockRefreshParentRequest mock_refresh_parent_request;
835 MockExclusiveLock mock_exclusive_lock;
836 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
838 MockObjectMap mock_object_map;
839 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
840 mock_image_ctx.object_map = &mock_object_map;
843 MockJournal *mock_journal = new MockJournal();
844 mock_image_ctx.journal = mock_journal;
846 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
847 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
851 expect_op_work_queue(mock_image_ctx);
852 expect_test_features(mock_image_ctx);
854 // verify journal is closed if feature disabled
856 expect_get_mutable_metadata(mock_image_ctx, 0);
857 expect_get_flags(mock_image_ctx, 0);
858 expect_get_group(mock_image_ctx, 0);
859 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
860 expect_block_writes(mock_image_ctx, 0);
861 if (!mock_image_ctx.clone_copy_on_read) {
862 expect_set_require_lock(mock_image_ctx, librbd::io::DIRECTION_READ, false);
864 expect_close_journal(mock_image_ctx, *mock_journal, 0);
865 expect_unblock_writes(mock_image_ctx);
868 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
871 ASSERT_EQ(0, ctx.wait());
874 TEST_F(TestMockImageRefreshRequest, EnableObjectMapWithExclusiveLock) {
875 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
877 librbd::ImageCtx *ictx;
878 ASSERT_EQ(0, open_image(m_image_name, &ictx));
880 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
881 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
885 MockRefreshImageCtx mock_image_ctx(*ictx);
886 MockRefreshParentRequest mock_refresh_parent_request;
888 MockExclusiveLock mock_exclusive_lock;
889 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
891 MockObjectMap mock_object_map;
893 expect_op_work_queue(mock_image_ctx);
894 expect_test_features(mock_image_ctx);
895 expect_is_exclusive_lock_owner(mock_exclusive_lock, true);
897 // object map should be immediately opened if exclusive lock owned
899 expect_get_mutable_metadata(mock_image_ctx, 0);
900 expect_get_flags(mock_image_ctx, 0);
901 expect_get_group(mock_image_ctx, 0);
902 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
903 expect_open_object_map(mock_image_ctx, &mock_object_map, 0);
906 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
909 ASSERT_EQ(0, ctx.wait());
912 TEST_F(TestMockImageRefreshRequest, EnableObjectMapWithoutExclusiveLock) {
913 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
915 librbd::ImageCtx *ictx;
916 ASSERT_EQ(0, open_image(m_image_name, &ictx));
918 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
919 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
923 MockRefreshImageCtx mock_image_ctx(*ictx);
924 MockRefreshParentRequest mock_refresh_parent_request;
926 MockExclusiveLock mock_exclusive_lock;
927 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
929 expect_op_work_queue(mock_image_ctx);
930 expect_test_features(mock_image_ctx);
931 expect_is_exclusive_lock_owner(mock_exclusive_lock, false);
933 // do not open the object map if exclusive lock is not owned
935 expect_get_mutable_metadata(mock_image_ctx, 0);
936 expect_get_flags(mock_image_ctx, 0);
937 expect_get_group(mock_image_ctx, 0);
938 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
941 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
944 ASSERT_EQ(0, ctx.wait());
947 TEST_F(TestMockImageRefreshRequest, DisableObjectMap) {
948 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
950 librbd::ImageCtx *ictx;
951 ASSERT_EQ(0, open_image(m_image_name, &ictx));
953 MockRefreshImageCtx mock_image_ctx(*ictx);
954 MockRefreshParentRequest mock_refresh_parent_request;
956 MockExclusiveLock mock_exclusive_lock;
957 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
959 MockObjectMap *mock_object_map = new MockObjectMap();
960 mock_image_ctx.object_map = mock_object_map;
962 MockJournal mock_journal;
963 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
964 mock_image_ctx.journal = &mock_journal;
967 if (ictx->test_features(RBD_FEATURE_FAST_DIFF)) {
968 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_FAST_DIFF,
972 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
973 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_OBJECT_MAP,
977 expect_op_work_queue(mock_image_ctx);
978 expect_test_features(mock_image_ctx);
980 // verify object map is closed if feature disabled
982 expect_get_mutable_metadata(mock_image_ctx, 0);
983 expect_get_flags(mock_image_ctx, 0);
984 expect_get_group(mock_image_ctx, 0);
985 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
986 expect_close_object_map(mock_image_ctx, *mock_object_map, 0);
989 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
992 ASSERT_EQ(0, ctx.wait());
995 TEST_F(TestMockImageRefreshRequest, OpenObjectMapError) {
996 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
998 librbd::ImageCtx *ictx;
999 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1001 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
1002 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
1006 MockRefreshImageCtx mock_image_ctx(*ictx);
1007 MockRefreshParentRequest mock_refresh_parent_request;
1009 MockExclusiveLock mock_exclusive_lock;
1010 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
1012 MockObjectMap *mock_object_map = new MockObjectMap();
1014 expect_op_work_queue(mock_image_ctx);
1015 expect_test_features(mock_image_ctx);
1016 expect_is_exclusive_lock_owner(mock_exclusive_lock, true);
1018 // object map should be immediately opened if exclusive lock owned
1020 expect_get_mutable_metadata(mock_image_ctx, 0);
1021 expect_get_flags(mock_image_ctx, 0);
1022 expect_get_group(mock_image_ctx, 0);
1023 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
1024 expect_open_object_map(mock_image_ctx, mock_object_map, -EFBIG);
1027 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
1030 ASSERT_EQ(0, ctx.wait());
1031 ASSERT_EQ(nullptr, mock_image_ctx.object_map);
1034 } // namespace image
1035 } // namespace librbd