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_metadata(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("metadata_list"), _
, _
, _
));
162 expect
.WillOnce(Return(r
));
164 expect
.WillOnce(DoDefault());
168 void expect_get_flags(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"), StrEq("get_flags"), _
, _
, _
));
172 expect
.WillOnce(Return(r
));
174 expect
.WillOnce(DoDefault());
178 void expect_get_group(MockRefreshImageCtx
&mock_image_ctx
, int r
) {
179 auto &expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
180 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"),
181 StrEq("image_get_group"), _
, _
, _
));
183 expect
.WillOnce(Return(r
));
185 expect
.WillOnce(DoDefault());
190 void expect_get_snapshots(MockRefreshImageCtx
&mock_image_ctx
, int r
) {
191 auto &expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
192 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_snapshot_name"), _
, _
, _
));
194 expect
.WillOnce(Return(r
));
196 expect
.WillOnce(DoDefault());
197 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
198 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_size"), _
, _
, _
))
199 .WillOnce(DoDefault());
200 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
201 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_parent"), _
, _
, _
))
202 .WillOnce(DoDefault());
203 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
204 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_protection_status"), _
, _
, _
))
205 .WillOnce(DoDefault());
209 void expect_snap_timestamp_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_timestamp"), _
, _
, _
));
213 expect
.WillOnce(Return(r
));
215 expect
.WillOnce(DoDefault());
219 void expect_snap_namespace_list(MockRefreshImageCtx
&mock_image_ctx
, int r
) {
220 auto &expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
221 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_snapshot_namespace"), _
, _
, _
));
223 expect
.WillOnce(Return(r
));
225 expect
.WillOnce(DoDefault());
229 void expect_apply_metadata(MockRefreshImageCtx
&mock_image_ctx
,
231 EXPECT_CALL(mock_image_ctx
, apply_metadata(_
, false))
232 .WillOnce(Return(r
));
235 void expect_add_snap(MockRefreshImageCtx
&mock_image_ctx
,
236 const std::string
&snap_name
, uint64_t snap_id
) {
237 EXPECT_CALL(mock_image_ctx
, add_snap(_
, snap_name
, snap_id
, _
, _
, _
, _
, _
));
240 void expect_init_exclusive_lock(MockRefreshImageCtx
&mock_image_ctx
,
241 MockExclusiveLock
&mock_exclusive_lock
,
243 EXPECT_CALL(mock_image_ctx
, create_exclusive_lock())
244 .WillOnce(Return(&mock_exclusive_lock
));
245 EXPECT_CALL(mock_exclusive_lock
, init(mock_image_ctx
.features
, _
))
246 .WillOnce(WithArg
<1>(CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
)));
249 void expect_shut_down_exclusive_lock(MockRefreshImageCtx
&mock_image_ctx
,
250 MockExclusiveLock
&mock_exclusive_lock
,
252 EXPECT_CALL(mock_exclusive_lock
, shut_down(_
))
253 .WillOnce(DoAll(ShutDownExclusiveLock(&mock_image_ctx
),
254 CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
)));
257 void expect_init_layout(MockRefreshImageCtx
&mock_image_ctx
) {
258 EXPECT_CALL(mock_image_ctx
, init_layout());
261 void expect_test_features(MockRefreshImageCtx
&mock_image_ctx
) {
262 EXPECT_CALL(mock_image_ctx
, test_features(_
, _
))
263 .WillRepeatedly(TestFeatures(&mock_image_ctx
));
266 void expect_refresh_parent_is_required(MockRefreshParentRequest
&mock_refresh_parent_request
,
268 EXPECT_CALL(mock_refresh_parent_request
, is_refresh_required())
269 .WillRepeatedly(Return(required
));
272 void expect_refresh_parent_send(MockRefreshImageCtx
&mock_image_ctx
,
273 MockRefreshParentRequest
&mock_refresh_parent_request
,
275 EXPECT_CALL(mock_refresh_parent_request
, send())
276 .WillOnce(FinishRequest(&mock_refresh_parent_request
, r
,
280 void expect_refresh_parent_apply(MockRefreshParentRequest
&mock_refresh_parent_request
) {
281 EXPECT_CALL(mock_refresh_parent_request
, apply());
284 void expect_refresh_parent_finalize(MockRefreshImageCtx
&mock_image_ctx
,
285 MockRefreshParentRequest
&mock_refresh_parent_request
,
287 EXPECT_CALL(mock_refresh_parent_request
, finalize(_
))
288 .WillOnce(CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
));
291 void expect_is_exclusive_lock_owner(MockExclusiveLock
&mock_exclusive_lock
,
293 EXPECT_CALL(mock_exclusive_lock
, is_lock_owner()).WillOnce(Return(is_owner
));
296 void expect_get_journal_policy(MockImageCtx
&mock_image_ctx
,
297 MockJournalPolicy
&mock_journal_policy
) {
298 EXPECT_CALL(mock_image_ctx
, get_journal_policy())
299 .WillOnce(Return(&mock_journal_policy
));
302 void expect_journal_disabled(MockJournalPolicy
&mock_journal_policy
,
304 EXPECT_CALL(mock_journal_policy
, journal_disabled())
305 .WillOnce(Return(disabled
));
308 void expect_open_journal(MockRefreshImageCtx
&mock_image_ctx
,
309 MockJournal
&mock_journal
, int r
) {
310 EXPECT_CALL(mock_image_ctx
, create_journal())
311 .WillOnce(Return(&mock_journal
));
312 EXPECT_CALL(mock_journal
, open(_
))
313 .WillOnce(CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
));
316 void expect_close_journal(MockRefreshImageCtx
&mock_image_ctx
,
317 MockJournal
&mock_journal
, int r
) {
318 EXPECT_CALL(mock_journal
, close(_
))
319 .WillOnce(CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
));
322 void expect_open_object_map(MockRefreshImageCtx
&mock_image_ctx
,
323 MockObjectMap
*mock_object_map
, int r
) {
324 EXPECT_CALL(mock_image_ctx
, create_object_map(_
))
325 .WillOnce(Return(mock_object_map
));
326 EXPECT_CALL(*mock_object_map
, open(_
))
327 .WillOnce(CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
));
330 void expect_close_object_map(MockRefreshImageCtx
&mock_image_ctx
,
331 MockObjectMap
&mock_object_map
, int r
) {
332 EXPECT_CALL(mock_object_map
, close(_
))
333 .WillOnce(CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
));
336 void expect_get_snap_id(MockRefreshImageCtx
&mock_image_ctx
,
337 const std::string
&snap_name
,
339 EXPECT_CALL(mock_image_ctx
,
340 get_snap_id(_
, snap_name
)).WillOnce(Return(snap_id
));
343 void expect_block_writes(MockImageCtx
&mock_image_ctx
, int r
) {
344 EXPECT_CALL(*mock_image_ctx
.io_work_queue
, block_writes(_
))
345 .WillOnce(CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
));
348 void expect_unblock_writes(MockImageCtx
&mock_image_ctx
) {
349 EXPECT_CALL(*mock_image_ctx
.io_work_queue
, unblock_writes())
355 TEST_F(TestMockImageRefreshRequest
, SuccessV1
) {
358 librbd::ImageCtx
*ictx
;
359 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
361 MockRefreshImageCtx
mock_image_ctx(*ictx
);
362 expect_op_work_queue(mock_image_ctx
);
363 expect_test_features(mock_image_ctx
);
366 expect_v1_read_header(mock_image_ctx
, 0);
367 expect_v1_get_snapshots(mock_image_ctx
, 0);
368 expect_v1_get_locks(mock_image_ctx
, 0);
369 expect_init_layout(mock_image_ctx
);
372 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
375 ASSERT_EQ(0, ctx
.wait());
378 TEST_F(TestMockImageRefreshRequest
, SuccessSnapshotV1
) {
380 librbd::ImageCtx
*ictx
;
381 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
382 ASSERT_EQ(0, snap_create(*ictx
, "snap"));
383 ASSERT_EQ(0, ictx
->state
->refresh());
385 MockRefreshImageCtx
mock_image_ctx(*ictx
);
386 expect_op_work_queue(mock_image_ctx
);
387 expect_test_features(mock_image_ctx
);
390 expect_v1_read_header(mock_image_ctx
, 0);
391 expect_v1_get_snapshots(mock_image_ctx
, 0);
392 expect_v1_get_locks(mock_image_ctx
, 0);
393 expect_init_layout(mock_image_ctx
);
394 expect_add_snap(mock_image_ctx
, "snap", ictx
->snap_ids
.begin()->second
);
397 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
400 ASSERT_EQ(0, ctx
.wait());
403 TEST_F(TestMockImageRefreshRequest
, SuccessV2
) {
406 librbd::ImageCtx
*ictx
;
407 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
409 MockRefreshImageCtx
mock_image_ctx(*ictx
);
410 MockRefreshParentRequest mock_refresh_parent_request
;
411 MockExclusiveLock mock_exclusive_lock
;
412 expect_op_work_queue(mock_image_ctx
);
413 expect_test_features(mock_image_ctx
);
416 expect_get_mutable_metadata(mock_image_ctx
, 0);
417 expect_get_metadata(mock_image_ctx
, 0);
418 expect_apply_metadata(mock_image_ctx
, 0);
419 expect_get_flags(mock_image_ctx
, 0);
420 expect_get_group(mock_image_ctx
, 0);
421 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
422 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
423 expect_init_exclusive_lock(mock_image_ctx
, mock_exclusive_lock
, 0);
427 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
430 ASSERT_EQ(0, ctx
.wait());
433 TEST_F(TestMockImageRefreshRequest
, SuccessSnapshotV2
) {
436 librbd::ImageCtx
*ictx
;
437 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
438 ASSERT_EQ(0, snap_create(*ictx
, "snap"));
440 MockRefreshImageCtx
mock_image_ctx(*ictx
);
441 MockRefreshParentRequest mock_refresh_parent_request
;
442 MockExclusiveLock mock_exclusive_lock
;
443 expect_op_work_queue(mock_image_ctx
);
444 expect_test_features(mock_image_ctx
);
447 expect_get_mutable_metadata(mock_image_ctx
, 0);
448 expect_get_metadata(mock_image_ctx
, 0);
449 expect_apply_metadata(mock_image_ctx
, 0);
450 expect_get_flags(mock_image_ctx
, 0);
451 expect_get_flags(mock_image_ctx
, 0);
452 expect_get_group(mock_image_ctx
, 0);
453 expect_get_snapshots(mock_image_ctx
, 0);
454 expect_snap_timestamp_list(mock_image_ctx
, 0);
455 expect_snap_namespace_list(mock_image_ctx
, 0);
456 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
457 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
458 expect_init_exclusive_lock(mock_image_ctx
, mock_exclusive_lock
, 0);
460 expect_add_snap(mock_image_ctx
, "snap", ictx
->snap_ids
.begin()->second
);
463 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
466 ASSERT_EQ(0, ctx
.wait());
469 TEST_F(TestMockImageRefreshRequest
, SuccessSetSnapshotV2
) {
472 librbd::ImageCtx
*ictx
;
473 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
474 ASSERT_EQ(0, snap_create(*ictx
, "snap"));
475 ASSERT_EQ(0, librbd::snap_set(ictx
, cls::rbd::UserSnapshotNamespace(), "snap"));
477 MockRefreshImageCtx
mock_image_ctx(*ictx
);
478 MockRefreshParentRequest mock_refresh_parent_request
;
479 MockObjectMap mock_object_map
;
480 expect_op_work_queue(mock_image_ctx
);
481 expect_test_features(mock_image_ctx
);
484 expect_get_mutable_metadata(mock_image_ctx
, 0);
485 expect_get_metadata(mock_image_ctx
, 0);
486 expect_apply_metadata(mock_image_ctx
, 0);
487 expect_get_flags(mock_image_ctx
, 0);
488 expect_get_flags(mock_image_ctx
, 0);
489 expect_get_group(mock_image_ctx
, 0);
490 expect_get_snapshots(mock_image_ctx
, 0);
491 expect_snap_timestamp_list(mock_image_ctx
, 0);
492 expect_snap_namespace_list(mock_image_ctx
, 0);
493 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
494 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
495 expect_open_object_map(mock_image_ctx
, &mock_object_map
, 0);
497 expect_add_snap(mock_image_ctx
, "snap", ictx
->snap_ids
.begin()->second
);
498 expect_get_snap_id(mock_image_ctx
, "snap", ictx
->snap_ids
.begin()->second
);
501 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
504 ASSERT_EQ(0, ctx
.wait());
507 TEST_F(TestMockImageRefreshRequest
, SuccessChild
) {
508 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
510 librbd::ImageCtx
*ictx
;
511 librbd::ImageCtx
*ictx2
= nullptr;
512 std::string clone_name
= get_temp_image_name();
514 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
515 ASSERT_EQ(0, snap_create(*ictx
, "snap"));
516 ASSERT_EQ(0, snap_protect(*ictx
, "snap"));
517 BOOST_SCOPE_EXIT_ALL((&)) {
518 if (ictx2
!= nullptr) {
522 librbd::NoOpProgressContext no_op
;
523 ASSERT_EQ(0, librbd::remove(m_ioctx
, clone_name
, "", no_op
));
524 ASSERT_EQ(0, ictx
->operations
->snap_unprotect(cls::rbd::UserSnapshotNamespace(), "snap"));
527 int order
= ictx
->order
;
528 ASSERT_EQ(0, librbd::clone(m_ioctx
, m_image_name
.c_str(), "snap", m_ioctx
,
529 clone_name
.c_str(), ictx
->features
, &order
, 0, 0));
531 ASSERT_EQ(0, open_image(clone_name
, &ictx2
));
533 MockRefreshImageCtx
mock_image_ctx(*ictx2
);
534 MockRefreshParentRequest
*mock_refresh_parent_request
= new MockRefreshParentRequest();
535 MockExclusiveLock mock_exclusive_lock
;
536 expect_op_work_queue(mock_image_ctx
);
537 expect_test_features(mock_image_ctx
);
540 expect_get_mutable_metadata(mock_image_ctx
, 0);
541 expect_get_metadata(mock_image_ctx
, 0);
542 expect_apply_metadata(mock_image_ctx
, 0);
543 expect_get_flags(mock_image_ctx
, 0);
544 expect_get_group(mock_image_ctx
, 0);
545 expect_refresh_parent_is_required(*mock_refresh_parent_request
, true);
546 expect_refresh_parent_send(mock_image_ctx
, *mock_refresh_parent_request
, 0);
547 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
548 expect_init_exclusive_lock(mock_image_ctx
, mock_exclusive_lock
, 0);
550 expect_refresh_parent_apply(*mock_refresh_parent_request
);
551 expect_refresh_parent_finalize(mock_image_ctx
, *mock_refresh_parent_request
, 0);
554 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
557 ASSERT_EQ(0, ctx
.wait());
560 TEST_F(TestMockImageRefreshRequest
, SuccessChildDontOpenParent
) {
561 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
563 librbd::ImageCtx
*ictx
;
564 librbd::ImageCtx
*ictx2
= nullptr;
565 std::string clone_name
= get_temp_image_name();
567 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
568 ASSERT_EQ(0, snap_create(*ictx
, "snap"));
569 ASSERT_EQ(0, snap_protect(*ictx
, "snap"));
570 BOOST_SCOPE_EXIT_ALL((&)) {
571 if (ictx2
!= nullptr) {
575 librbd::NoOpProgressContext no_op
;
576 ASSERT_EQ(0, librbd::remove(m_ioctx
, clone_name
, "", no_op
));
577 ASSERT_EQ(0, ictx
->operations
->snap_unprotect(cls::rbd::UserSnapshotNamespace(), "snap"));
580 int order
= ictx
->order
;
581 ASSERT_EQ(0, librbd::clone(m_ioctx
, m_image_name
.c_str(), "snap", m_ioctx
,
582 clone_name
.c_str(), ictx
->features
, &order
, 0, 0));
584 ASSERT_EQ(0, open_image(clone_name
, &ictx2
));
586 MockRefreshImageCtx
mock_image_ctx(*ictx2
);
587 MockExclusiveLock mock_exclusive_lock
;
588 expect_op_work_queue(mock_image_ctx
);
589 expect_test_features(mock_image_ctx
);
592 expect_get_mutable_metadata(mock_image_ctx
, 0);
593 expect_get_metadata(mock_image_ctx
, 0);
594 expect_apply_metadata(mock_image_ctx
, 0);
595 expect_get_flags(mock_image_ctx
, 0);
596 expect_get_group(mock_image_ctx
, 0);
597 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
598 expect_init_exclusive_lock(mock_image_ctx
, mock_exclusive_lock
, 0);
602 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, true, &ctx
);
605 ASSERT_EQ(0, ctx
.wait());
608 TEST_F(TestMockImageRefreshRequest
, DisableExclusiveLock
) {
609 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
611 librbd::ImageCtx
*ictx
;
612 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
614 MockRefreshImageCtx
mock_image_ctx(*ictx
);
615 MockRefreshParentRequest mock_refresh_parent_request
;
617 MockExclusiveLock
*mock_exclusive_lock
= new MockExclusiveLock();
618 mock_image_ctx
.exclusive_lock
= mock_exclusive_lock
;
620 MockObjectMap mock_object_map
;
621 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
622 mock_image_ctx
.object_map
= &mock_object_map
;
625 MockJournal mock_journal
;
626 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
627 mock_image_ctx
.journal
= &mock_journal
;
630 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
631 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_JOURNALING
,
635 if (ictx
->test_features(RBD_FEATURE_FAST_DIFF
)) {
636 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_FAST_DIFF
,
640 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
641 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_OBJECT_MAP
,
645 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
646 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_EXCLUSIVE_LOCK
,
650 expect_op_work_queue(mock_image_ctx
);
651 expect_test_features(mock_image_ctx
);
653 // verify that exclusive lock is properly handled when object map
654 // and journaling were never enabled (or active)
656 expect_get_mutable_metadata(mock_image_ctx
, 0);
657 expect_get_metadata(mock_image_ctx
, 0);
658 expect_apply_metadata(mock_image_ctx
, 0);
659 expect_get_flags(mock_image_ctx
, 0);
660 expect_get_group(mock_image_ctx
, 0);
661 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
662 expect_shut_down_exclusive_lock(mock_image_ctx
, *mock_exclusive_lock
, 0);
665 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
668 ASSERT_EQ(0, ctx
.wait());
671 TEST_F(TestMockImageRefreshRequest
, DisableExclusiveLockWhileAcquiringLock
) {
672 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
674 librbd::ImageCtx
*ictx
;
675 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
677 MockRefreshImageCtx
mock_image_ctx(*ictx
);
678 MockRefreshParentRequest mock_refresh_parent_request
;
680 MockExclusiveLock mock_exclusive_lock
;
681 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
683 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
684 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_JOURNALING
,
688 if (ictx
->test_features(RBD_FEATURE_FAST_DIFF
)) {
689 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_FAST_DIFF
,
693 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
694 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_OBJECT_MAP
,
698 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
699 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_EXCLUSIVE_LOCK
,
703 expect_op_work_queue(mock_image_ctx
);
704 expect_test_features(mock_image_ctx
);
706 // verify that exclusive lock is properly handled when object map
707 // and journaling were never enabled (or active)
709 expect_get_mutable_metadata(mock_image_ctx
, 0);
710 expect_get_metadata(mock_image_ctx
, 0);
711 expect_apply_metadata(mock_image_ctx
, 0);
712 expect_get_flags(mock_image_ctx
, 0);
713 expect_get_group(mock_image_ctx
, 0);
714 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
717 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, true, false, &ctx
);
720 ASSERT_EQ(-ERESTART
, ctx
.wait());
723 TEST_F(TestMockImageRefreshRequest
, JournalDisabledByPolicy
) {
724 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
726 librbd::ImageCtx
*ictx
;
727 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
729 if (ictx
->test_features(RBD_FEATURE_FAST_DIFF
)) {
730 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_FAST_DIFF
,
734 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
735 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_OBJECT_MAP
,
739 MockRefreshImageCtx
mock_image_ctx(*ictx
);
740 MockRefreshParentRequest mock_refresh_parent_request
;
742 MockExclusiveLock mock_exclusive_lock
;
743 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
745 MockJournal mock_journal
;
747 expect_op_work_queue(mock_image_ctx
);
748 expect_test_features(mock_image_ctx
);
749 expect_is_exclusive_lock_owner(mock_exclusive_lock
, true);
752 expect_get_mutable_metadata(mock_image_ctx
, 0);
753 expect_get_metadata(mock_image_ctx
, 0);
754 expect_apply_metadata(mock_image_ctx
, 0);
755 expect_get_flags(mock_image_ctx
, 0);
756 expect_get_group(mock_image_ctx
, 0);
757 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
759 MockJournalPolicy mock_journal_policy
;
760 expect_get_journal_policy(mock_image_ctx
, mock_journal_policy
);
761 expect_journal_disabled(mock_journal_policy
, true);
764 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
767 ASSERT_EQ(0, ctx
.wait());
770 TEST_F(TestMockImageRefreshRequest
, EnableJournalWithExclusiveLock
) {
771 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
773 librbd::ImageCtx
*ictx
;
774 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
776 if (ictx
->test_features(RBD_FEATURE_FAST_DIFF
)) {
777 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_FAST_DIFF
,
781 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
782 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_OBJECT_MAP
,
786 MockRefreshImageCtx
mock_image_ctx(*ictx
);
787 MockRefreshParentRequest mock_refresh_parent_request
;
789 MockExclusiveLock mock_exclusive_lock
;
790 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
792 MockJournal mock_journal
;
794 expect_op_work_queue(mock_image_ctx
);
795 expect_test_features(mock_image_ctx
);
796 expect_is_exclusive_lock_owner(mock_exclusive_lock
, true);
798 // journal should be immediately opened if exclusive lock owned
800 expect_get_mutable_metadata(mock_image_ctx
, 0);
801 expect_get_metadata(mock_image_ctx
, 0);
802 expect_apply_metadata(mock_image_ctx
, 0);
803 expect_get_flags(mock_image_ctx
, 0);
804 expect_get_group(mock_image_ctx
, 0);
805 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
807 MockJournalPolicy mock_journal_policy
;
808 expect_get_journal_policy(mock_image_ctx
, mock_journal_policy
);
809 expect_journal_disabled(mock_journal_policy
, false);
810 expect_open_journal(mock_image_ctx
, mock_journal
, 0);
813 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
816 ASSERT_EQ(0, ctx
.wait());
819 TEST_F(TestMockImageRefreshRequest
, EnableJournalWithoutExclusiveLock
) {
820 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
822 librbd::ImageCtx
*ictx
;
823 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
825 if (ictx
->test_features(RBD_FEATURE_FAST_DIFF
)) {
826 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_FAST_DIFF
,
830 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
831 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_OBJECT_MAP
,
835 MockRefreshImageCtx
mock_image_ctx(*ictx
);
836 MockRefreshParentRequest mock_refresh_parent_request
;
838 MockExclusiveLock mock_exclusive_lock
;
839 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
841 expect_op_work_queue(mock_image_ctx
);
842 expect_test_features(mock_image_ctx
);
843 expect_is_exclusive_lock_owner(mock_exclusive_lock
, false);
845 // do not open the journal if exclusive lock is not owned
847 expect_get_mutable_metadata(mock_image_ctx
, 0);
848 expect_get_metadata(mock_image_ctx
, 0);
849 expect_apply_metadata(mock_image_ctx
, 0);
850 expect_get_flags(mock_image_ctx
, 0);
851 expect_get_group(mock_image_ctx
, 0);
852 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
853 expect_set_require_lock(mock_image_ctx
, librbd::io::DIRECTION_BOTH
, true);
856 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
859 ASSERT_EQ(0, ctx
.wait());
862 TEST_F(TestMockImageRefreshRequest
, DisableJournal
) {
863 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
865 librbd::ImageCtx
*ictx
;
866 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
868 MockRefreshImageCtx
mock_image_ctx(*ictx
);
869 MockRefreshParentRequest mock_refresh_parent_request
;
871 MockExclusiveLock mock_exclusive_lock
;
872 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
874 MockObjectMap mock_object_map
;
875 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
876 mock_image_ctx
.object_map
= &mock_object_map
;
879 MockJournal
*mock_journal
= new MockJournal();
880 mock_image_ctx
.journal
= mock_journal
;
882 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
883 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_JOURNALING
,
887 expect_op_work_queue(mock_image_ctx
);
888 expect_test_features(mock_image_ctx
);
890 // verify journal is closed if feature disabled
892 expect_get_mutable_metadata(mock_image_ctx
, 0);
893 expect_get_metadata(mock_image_ctx
, 0);
894 expect_apply_metadata(mock_image_ctx
, 0);
895 expect_get_flags(mock_image_ctx
, 0);
896 expect_get_group(mock_image_ctx
, 0);
897 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
898 expect_block_writes(mock_image_ctx
, 0);
899 if (!mock_image_ctx
.clone_copy_on_read
) {
900 expect_set_require_lock(mock_image_ctx
, librbd::io::DIRECTION_READ
, false);
902 expect_close_journal(mock_image_ctx
, *mock_journal
, 0);
903 expect_unblock_writes(mock_image_ctx
);
906 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
909 ASSERT_EQ(0, ctx
.wait());
912 TEST_F(TestMockImageRefreshRequest
, EnableObjectMapWithExclusiveLock
) {
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 MockObjectMap mock_object_map
;
931 expect_op_work_queue(mock_image_ctx
);
932 expect_test_features(mock_image_ctx
);
933 expect_is_exclusive_lock_owner(mock_exclusive_lock
, true);
935 // object map should be immediately opened if exclusive lock owned
937 expect_get_mutable_metadata(mock_image_ctx
, 0);
938 expect_get_metadata(mock_image_ctx
, 0);
939 expect_apply_metadata(mock_image_ctx
, 0);
940 expect_get_flags(mock_image_ctx
, 0);
941 expect_get_group(mock_image_ctx
, 0);
942 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
943 expect_open_object_map(mock_image_ctx
, &mock_object_map
, 0);
946 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
949 ASSERT_EQ(0, ctx
.wait());
952 TEST_F(TestMockImageRefreshRequest
, EnableObjectMapWithoutExclusiveLock
) {
953 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP
);
955 librbd::ImageCtx
*ictx
;
956 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
958 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
959 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_JOURNALING
,
963 MockRefreshImageCtx
mock_image_ctx(*ictx
);
964 MockRefreshParentRequest mock_refresh_parent_request
;
966 MockExclusiveLock mock_exclusive_lock
;
967 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
969 expect_op_work_queue(mock_image_ctx
);
970 expect_test_features(mock_image_ctx
);
971 expect_is_exclusive_lock_owner(mock_exclusive_lock
, false);
973 // do not open the object map if exclusive lock is not owned
975 expect_get_mutable_metadata(mock_image_ctx
, 0);
976 expect_get_metadata(mock_image_ctx
, 0);
977 expect_apply_metadata(mock_image_ctx
, 0);
978 expect_get_flags(mock_image_ctx
, 0);
979 expect_get_group(mock_image_ctx
, 0);
980 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
983 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
986 ASSERT_EQ(0, ctx
.wait());
989 TEST_F(TestMockImageRefreshRequest
, DisableObjectMap
) {
990 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP
);
992 librbd::ImageCtx
*ictx
;
993 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
995 MockRefreshImageCtx
mock_image_ctx(*ictx
);
996 MockRefreshParentRequest mock_refresh_parent_request
;
998 MockExclusiveLock mock_exclusive_lock
;
999 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
1001 MockObjectMap
*mock_object_map
= new MockObjectMap();
1002 mock_image_ctx
.object_map
= mock_object_map
;
1004 MockJournal mock_journal
;
1005 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
1006 mock_image_ctx
.journal
= &mock_journal
;
1009 if (ictx
->test_features(RBD_FEATURE_FAST_DIFF
)) {
1010 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_FAST_DIFF
,
1014 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
1015 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_OBJECT_MAP
,
1019 expect_op_work_queue(mock_image_ctx
);
1020 expect_test_features(mock_image_ctx
);
1022 // verify object map is closed if feature disabled
1024 expect_get_mutable_metadata(mock_image_ctx
, 0);
1025 expect_get_metadata(mock_image_ctx
, 0);
1026 expect_apply_metadata(mock_image_ctx
, 0);
1027 expect_get_flags(mock_image_ctx
, 0);
1028 expect_get_group(mock_image_ctx
, 0);
1029 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
1030 expect_close_object_map(mock_image_ctx
, *mock_object_map
, 0);
1033 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
1036 ASSERT_EQ(0, ctx
.wait());
1039 TEST_F(TestMockImageRefreshRequest
, OpenObjectMapError
) {
1040 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP
);
1042 librbd::ImageCtx
*ictx
;
1043 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1045 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
1046 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_JOURNALING
,
1050 MockRefreshImageCtx
mock_image_ctx(*ictx
);
1051 MockRefreshParentRequest mock_refresh_parent_request
;
1053 MockExclusiveLock mock_exclusive_lock
;
1054 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
1056 MockObjectMap
*mock_object_map
= new MockObjectMap();
1058 expect_op_work_queue(mock_image_ctx
);
1059 expect_test_features(mock_image_ctx
);
1060 expect_is_exclusive_lock_owner(mock_exclusive_lock
, true);
1062 // object map should be immediately opened if exclusive lock owned
1064 expect_get_mutable_metadata(mock_image_ctx
, 0);
1065 expect_get_metadata(mock_image_ctx
, 0);
1066 expect_apply_metadata(mock_image_ctx
, 0);
1067 expect_get_flags(mock_image_ctx
, 0);
1068 expect_get_group(mock_image_ctx
, 0);
1069 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
1070 expect_open_object_map(mock_image_ctx
, mock_object_map
, -EFBIG
);
1073 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
1076 ASSERT_EQ(0, ctx
.wait());
1077 ASSERT_EQ(nullptr, mock_image_ctx
.object_map
);
1080 TEST_F(TestMockImageRefreshRequest
, ApplyMetadataError
) {
1081 REQUIRE_FORMAT_V2();
1083 librbd::ImageCtx
*ictx
;
1084 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1086 MockRefreshImageCtx
mock_image_ctx(*ictx
);
1087 MockRefreshParentRequest mock_refresh_parent_request
;
1088 MockExclusiveLock mock_exclusive_lock
;
1089 expect_op_work_queue(mock_image_ctx
);
1090 expect_test_features(mock_image_ctx
);
1093 expect_get_mutable_metadata(mock_image_ctx
, 0);
1094 expect_get_metadata(mock_image_ctx
, 0);
1095 expect_apply_metadata(mock_image_ctx
, -EINVAL
);
1096 expect_get_flags(mock_image_ctx
, 0);
1097 expect_get_group(mock_image_ctx
, 0);
1098 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
1099 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
1100 expect_init_exclusive_lock(mock_image_ctx
, mock_exclusive_lock
, 0);
1104 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
1107 ASSERT_EQ(0, ctx
.wait());
1110 } // namespace image
1111 } // namespace librbd