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_is_lock_required(MockRefreshImageCtx
&mock_image_ctx
, bool require_lock
) {
101 EXPECT_CALL(*mock_image_ctx
.io_work_queue
, is_lock_required()).WillOnce(Return(require_lock
));
104 void expect_set_require_lock_on_read(MockRefreshImageCtx
&mock_image_ctx
) {
105 EXPECT_CALL(*mock_image_ctx
.io_work_queue
, set_require_lock_on_read());
108 void expect_clear_require_lock_on_read(MockRefreshImageCtx
&mock_image_ctx
) {
109 EXPECT_CALL(*mock_image_ctx
.io_work_queue
, clear_require_lock_on_read());
112 void expect_v1_read_header(MockRefreshImageCtx
&mock_image_ctx
, int r
) {
113 auto &expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
114 read(mock_image_ctx
.header_oid
, _
, _
, _
));
116 expect
.WillOnce(Return(r
));
118 expect
.WillOnce(DoDefault());
122 void expect_v1_get_snapshots(MockRefreshImageCtx
&mock_image_ctx
, int r
) {
123 auto &expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
124 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("snap_list"), _
, _
, _
));
126 expect
.WillOnce(Return(r
));
128 expect
.WillOnce(DoDefault());
132 void expect_v1_get_locks(MockRefreshImageCtx
&mock_image_ctx
, int r
) {
133 auto &expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
134 exec(mock_image_ctx
.header_oid
, _
, StrEq("lock"), StrEq("get_info"), _
, _
, _
));
136 expect
.WillOnce(Return(r
));
138 expect
.WillOnce(DoDefault());
142 void expect_get_mutable_metadata(MockRefreshImageCtx
&mock_image_ctx
, int r
) {
143 auto &expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
144 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_size"), _
, _
, _
));
146 expect
.WillOnce(Return(r
));
148 expect
.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_features"), _
, _
, _
))
151 .WillOnce(DoDefault());
152 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
153 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_snapcontext"), _
, _
, _
))
154 .WillOnce(DoDefault());
155 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
156 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_parent"), _
, _
, _
))
157 .WillOnce(DoDefault());
158 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
159 exec(mock_image_ctx
.header_oid
, _
, StrEq("lock"), StrEq("get_info"), _
, _
, _
))
160 .WillOnce(DoDefault());
164 void expect_get_flags(MockRefreshImageCtx
&mock_image_ctx
, int r
) {
165 auto &expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
166 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_flags"), _
, _
, _
));
168 expect
.WillOnce(Return(r
));
170 expect
.WillOnce(DoDefault());
174 void expect_get_group(MockRefreshImageCtx
&mock_image_ctx
, int r
) {
175 auto &expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
176 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"),
177 StrEq("image_get_group"), _
, _
, _
));
179 expect
.WillOnce(Return(r
));
181 expect
.WillOnce(DoDefault());
186 void expect_get_snapshots(MockRefreshImageCtx
&mock_image_ctx
, int r
) {
187 auto &expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
188 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_snapshot_name"), _
, _
, _
));
190 expect
.WillOnce(Return(r
));
192 expect
.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_size"), _
, _
, _
))
195 .WillOnce(DoDefault());
196 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
197 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_parent"), _
, _
, _
))
198 .WillOnce(DoDefault());
199 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
200 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_protection_status"), _
, _
, _
))
201 .WillOnce(DoDefault());
205 void expect_snap_timestamp_list(MockRefreshImageCtx
&mock_image_ctx
, int r
) {
206 auto &expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
207 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_snapshot_timestamp"), _
, _
, _
));
209 expect
.WillOnce(Return(r
));
211 expect
.WillOnce(DoDefault());
215 void expect_snap_namespace_list(MockRefreshImageCtx
&mock_image_ctx
, int r
) {
216 auto &expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
217 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_snapshot_namespace"), _
, _
, _
));
219 expect
.WillOnce(Return(r
));
221 expect
.WillOnce(DoDefault());
225 void expect_add_snap(MockRefreshImageCtx
&mock_image_ctx
,
226 const std::string
&snap_name
, uint64_t snap_id
) {
227 EXPECT_CALL(mock_image_ctx
, add_snap(_
, snap_name
, snap_id
, _
, _
, _
, _
, _
));
230 void expect_init_exclusive_lock(MockRefreshImageCtx
&mock_image_ctx
,
231 MockExclusiveLock
&mock_exclusive_lock
,
233 EXPECT_CALL(mock_image_ctx
, create_exclusive_lock())
234 .WillOnce(Return(&mock_exclusive_lock
));
235 EXPECT_CALL(mock_exclusive_lock
, init(mock_image_ctx
.features
, _
))
236 .WillOnce(WithArg
<1>(CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
)));
239 void expect_shut_down_exclusive_lock(MockRefreshImageCtx
&mock_image_ctx
,
240 MockExclusiveLock
&mock_exclusive_lock
,
242 EXPECT_CALL(mock_exclusive_lock
, shut_down(_
))
243 .WillOnce(DoAll(ShutDownExclusiveLock(&mock_image_ctx
),
244 CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
)));
247 void expect_init_layout(MockRefreshImageCtx
&mock_image_ctx
) {
248 EXPECT_CALL(mock_image_ctx
, init_layout());
251 void expect_test_features(MockRefreshImageCtx
&mock_image_ctx
) {
252 EXPECT_CALL(mock_image_ctx
, test_features(_
, _
))
253 .WillRepeatedly(TestFeatures(&mock_image_ctx
));
256 void expect_refresh_parent_is_required(MockRefreshParentRequest
&mock_refresh_parent_request
,
258 EXPECT_CALL(mock_refresh_parent_request
, is_refresh_required())
259 .WillRepeatedly(Return(required
));
262 void expect_refresh_parent_send(MockRefreshImageCtx
&mock_image_ctx
,
263 MockRefreshParentRequest
&mock_refresh_parent_request
,
265 EXPECT_CALL(mock_refresh_parent_request
, send())
266 .WillOnce(FinishRequest(&mock_refresh_parent_request
, r
,
270 void expect_refresh_parent_apply(MockRefreshParentRequest
&mock_refresh_parent_request
) {
271 EXPECT_CALL(mock_refresh_parent_request
, apply());
274 void expect_refresh_parent_finalize(MockRefreshImageCtx
&mock_image_ctx
,
275 MockRefreshParentRequest
&mock_refresh_parent_request
,
277 EXPECT_CALL(mock_refresh_parent_request
, finalize(_
))
278 .WillOnce(CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
));
281 void expect_is_exclusive_lock_owner(MockExclusiveLock
&mock_exclusive_lock
,
283 EXPECT_CALL(mock_exclusive_lock
, is_lock_owner()).WillOnce(Return(is_owner
));
286 void expect_get_journal_policy(MockImageCtx
&mock_image_ctx
,
287 MockJournalPolicy
&mock_journal_policy
) {
288 EXPECT_CALL(mock_image_ctx
, get_journal_policy())
289 .WillOnce(Return(&mock_journal_policy
));
292 void expect_journal_disabled(MockJournalPolicy
&mock_journal_policy
,
294 EXPECT_CALL(mock_journal_policy
, journal_disabled())
295 .WillOnce(Return(disabled
));
298 void expect_open_journal(MockRefreshImageCtx
&mock_image_ctx
,
299 MockJournal
&mock_journal
, int r
) {
300 EXPECT_CALL(mock_image_ctx
, create_journal())
301 .WillOnce(Return(&mock_journal
));
302 EXPECT_CALL(mock_journal
, open(_
))
303 .WillOnce(CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
));
306 void expect_close_journal(MockRefreshImageCtx
&mock_image_ctx
,
307 MockJournal
&mock_journal
, int r
) {
308 EXPECT_CALL(mock_journal
, close(_
))
309 .WillOnce(CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
));
312 void expect_open_object_map(MockRefreshImageCtx
&mock_image_ctx
,
313 MockObjectMap
*mock_object_map
, int r
) {
314 EXPECT_CALL(mock_image_ctx
, create_object_map(_
))
315 .WillOnce(Return(mock_object_map
));
316 EXPECT_CALL(*mock_object_map
, open(_
))
317 .WillOnce(CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
));
320 void expect_close_object_map(MockRefreshImageCtx
&mock_image_ctx
,
321 MockObjectMap
&mock_object_map
, int r
) {
322 EXPECT_CALL(mock_object_map
, close(_
))
323 .WillOnce(CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
));
326 void expect_get_snap_id(MockRefreshImageCtx
&mock_image_ctx
,
327 const std::string
&snap_name
,
329 EXPECT_CALL(mock_image_ctx
,
330 get_snap_id(_
, snap_name
)).WillOnce(Return(snap_id
));
333 void expect_block_writes(MockImageCtx
&mock_image_ctx
, int r
) {
334 EXPECT_CALL(*mock_image_ctx
.io_work_queue
, block_writes(_
))
335 .WillOnce(CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
));
338 void expect_unblock_writes(MockImageCtx
&mock_image_ctx
) {
339 EXPECT_CALL(*mock_image_ctx
.io_work_queue
, unblock_writes())
345 TEST_F(TestMockImageRefreshRequest
, SuccessV1
) {
348 librbd::ImageCtx
*ictx
;
349 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
351 MockRefreshImageCtx
mock_image_ctx(*ictx
);
352 expect_op_work_queue(mock_image_ctx
);
353 expect_test_features(mock_image_ctx
);
356 expect_v1_read_header(mock_image_ctx
, 0);
357 expect_v1_get_snapshots(mock_image_ctx
, 0);
358 expect_v1_get_locks(mock_image_ctx
, 0);
359 expect_init_layout(mock_image_ctx
);
362 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
365 ASSERT_EQ(0, ctx
.wait());
368 TEST_F(TestMockImageRefreshRequest
, SuccessSnapshotV1
) {
370 librbd::ImageCtx
*ictx
;
371 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
372 ASSERT_EQ(0, snap_create(*ictx
, "snap"));
373 ASSERT_EQ(0, ictx
->state
->refresh());
375 MockRefreshImageCtx
mock_image_ctx(*ictx
);
376 expect_op_work_queue(mock_image_ctx
);
377 expect_test_features(mock_image_ctx
);
380 expect_v1_read_header(mock_image_ctx
, 0);
381 expect_v1_get_snapshots(mock_image_ctx
, 0);
382 expect_v1_get_locks(mock_image_ctx
, 0);
383 expect_init_layout(mock_image_ctx
);
384 expect_add_snap(mock_image_ctx
, "snap", ictx
->snap_ids
.begin()->second
);
387 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
390 ASSERT_EQ(0, ctx
.wait());
393 TEST_F(TestMockImageRefreshRequest
, SuccessV2
) {
396 librbd::ImageCtx
*ictx
;
397 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
399 MockRefreshImageCtx
mock_image_ctx(*ictx
);
400 MockRefreshParentRequest mock_refresh_parent_request
;
401 MockExclusiveLock mock_exclusive_lock
;
402 expect_op_work_queue(mock_image_ctx
);
403 expect_test_features(mock_image_ctx
);
406 expect_get_mutable_metadata(mock_image_ctx
, 0);
407 expect_get_flags(mock_image_ctx
, 0);
408 expect_get_group(mock_image_ctx
, 0);
409 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
410 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
411 expect_init_exclusive_lock(mock_image_ctx
, mock_exclusive_lock
, 0);
415 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
418 ASSERT_EQ(0, ctx
.wait());
421 TEST_F(TestMockImageRefreshRequest
, SuccessSnapshotV2
) {
424 librbd::ImageCtx
*ictx
;
425 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
426 ASSERT_EQ(0, snap_create(*ictx
, "snap"));
428 MockRefreshImageCtx
mock_image_ctx(*ictx
);
429 MockRefreshParentRequest mock_refresh_parent_request
;
430 MockExclusiveLock mock_exclusive_lock
;
431 expect_op_work_queue(mock_image_ctx
);
432 expect_test_features(mock_image_ctx
);
435 expect_get_mutable_metadata(mock_image_ctx
, 0);
436 expect_get_flags(mock_image_ctx
, 0);
437 expect_get_flags(mock_image_ctx
, 0);
438 expect_get_group(mock_image_ctx
, 0);
439 expect_get_snapshots(mock_image_ctx
, 0);
440 expect_snap_timestamp_list(mock_image_ctx
, 0);
441 expect_snap_namespace_list(mock_image_ctx
, 0);
442 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
443 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
444 expect_init_exclusive_lock(mock_image_ctx
, mock_exclusive_lock
, 0);
446 expect_add_snap(mock_image_ctx
, "snap", ictx
->snap_ids
.begin()->second
);
449 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
452 ASSERT_EQ(0, ctx
.wait());
455 TEST_F(TestMockImageRefreshRequest
, SuccessSetSnapshotV2
) {
458 librbd::ImageCtx
*ictx
;
459 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
460 ASSERT_EQ(0, snap_create(*ictx
, "snap"));
461 ASSERT_EQ(0, librbd::snap_set(ictx
, cls::rbd::UserSnapshotNamespace(), "snap"));
463 MockRefreshImageCtx
mock_image_ctx(*ictx
);
464 MockRefreshParentRequest mock_refresh_parent_request
;
465 MockObjectMap mock_object_map
;
466 expect_op_work_queue(mock_image_ctx
);
467 expect_test_features(mock_image_ctx
);
470 expect_get_mutable_metadata(mock_image_ctx
, 0);
471 expect_get_flags(mock_image_ctx
, 0);
472 expect_get_flags(mock_image_ctx
, 0);
473 expect_get_group(mock_image_ctx
, 0);
474 expect_get_snapshots(mock_image_ctx
, 0);
475 expect_snap_timestamp_list(mock_image_ctx
, 0);
476 expect_snap_namespace_list(mock_image_ctx
, 0);
477 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
478 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
479 expect_open_object_map(mock_image_ctx
, &mock_object_map
, 0);
481 expect_add_snap(mock_image_ctx
, "snap", ictx
->snap_ids
.begin()->second
);
482 expect_get_snap_id(mock_image_ctx
, "snap", ictx
->snap_ids
.begin()->second
);
485 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
488 ASSERT_EQ(0, ctx
.wait());
491 TEST_F(TestMockImageRefreshRequest
, SuccessChild
) {
492 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
494 librbd::ImageCtx
*ictx
;
495 librbd::ImageCtx
*ictx2
= nullptr;
496 std::string clone_name
= get_temp_image_name();
498 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
499 ASSERT_EQ(0, snap_create(*ictx
, "snap"));
500 ASSERT_EQ(0, snap_protect(*ictx
, "snap"));
501 BOOST_SCOPE_EXIT_ALL((&)) {
502 if (ictx2
!= nullptr) {
506 librbd::NoOpProgressContext no_op
;
507 ASSERT_EQ(0, librbd::remove(m_ioctx
, clone_name
, "", no_op
));
508 ASSERT_EQ(0, ictx
->operations
->snap_unprotect(cls::rbd::UserSnapshotNamespace(), "snap"));
511 int order
= ictx
->order
;
512 ASSERT_EQ(0, librbd::clone(m_ioctx
, m_image_name
.c_str(), "snap", m_ioctx
,
513 clone_name
.c_str(), ictx
->features
, &order
, 0, 0));
515 ASSERT_EQ(0, open_image(clone_name
, &ictx2
));
517 MockRefreshImageCtx
mock_image_ctx(*ictx2
);
518 MockRefreshParentRequest
*mock_refresh_parent_request
= new MockRefreshParentRequest();
519 MockExclusiveLock mock_exclusive_lock
;
520 expect_op_work_queue(mock_image_ctx
);
521 expect_test_features(mock_image_ctx
);
524 expect_get_mutable_metadata(mock_image_ctx
, 0);
525 expect_get_flags(mock_image_ctx
, 0);
526 expect_get_group(mock_image_ctx
, 0);
527 expect_refresh_parent_is_required(*mock_refresh_parent_request
, true);
528 expect_refresh_parent_send(mock_image_ctx
, *mock_refresh_parent_request
, 0);
529 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
530 expect_init_exclusive_lock(mock_image_ctx
, mock_exclusive_lock
, 0);
532 expect_refresh_parent_apply(*mock_refresh_parent_request
);
533 expect_refresh_parent_finalize(mock_image_ctx
, *mock_refresh_parent_request
, 0);
536 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
539 ASSERT_EQ(0, ctx
.wait());
542 TEST_F(TestMockImageRefreshRequest
, SuccessChildDontOpenParent
) {
543 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
545 librbd::ImageCtx
*ictx
;
546 librbd::ImageCtx
*ictx2
= nullptr;
547 std::string clone_name
= get_temp_image_name();
549 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
550 ASSERT_EQ(0, snap_create(*ictx
, "snap"));
551 ASSERT_EQ(0, snap_protect(*ictx
, "snap"));
552 BOOST_SCOPE_EXIT_ALL((&)) {
553 if (ictx2
!= nullptr) {
557 librbd::NoOpProgressContext no_op
;
558 ASSERT_EQ(0, librbd::remove(m_ioctx
, clone_name
, "", no_op
));
559 ASSERT_EQ(0, ictx
->operations
->snap_unprotect(cls::rbd::UserSnapshotNamespace(), "snap"));
562 int order
= ictx
->order
;
563 ASSERT_EQ(0, librbd::clone(m_ioctx
, m_image_name
.c_str(), "snap", m_ioctx
,
564 clone_name
.c_str(), ictx
->features
, &order
, 0, 0));
566 ASSERT_EQ(0, open_image(clone_name
, &ictx2
));
568 MockRefreshImageCtx
mock_image_ctx(*ictx2
);
569 MockExclusiveLock mock_exclusive_lock
;
570 expect_op_work_queue(mock_image_ctx
);
571 expect_test_features(mock_image_ctx
);
574 expect_get_mutable_metadata(mock_image_ctx
, 0);
575 expect_get_flags(mock_image_ctx
, 0);
576 expect_get_group(mock_image_ctx
, 0);
577 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
578 expect_init_exclusive_lock(mock_image_ctx
, mock_exclusive_lock
, 0);
582 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, true, &ctx
);
585 ASSERT_EQ(0, ctx
.wait());
588 TEST_F(TestMockImageRefreshRequest
, DisableExclusiveLock
) {
589 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
591 librbd::ImageCtx
*ictx
;
592 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
594 MockRefreshImageCtx
mock_image_ctx(*ictx
);
595 MockRefreshParentRequest mock_refresh_parent_request
;
597 MockExclusiveLock
*mock_exclusive_lock
= new MockExclusiveLock();
598 mock_image_ctx
.exclusive_lock
= mock_exclusive_lock
;
600 MockObjectMap mock_object_map
;
601 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
602 mock_image_ctx
.object_map
= &mock_object_map
;
605 MockJournal mock_journal
;
606 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
607 mock_image_ctx
.journal
= &mock_journal
;
610 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
611 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_JOURNALING
,
615 if (ictx
->test_features(RBD_FEATURE_FAST_DIFF
)) {
616 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_FAST_DIFF
,
620 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
621 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_OBJECT_MAP
,
625 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
626 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_EXCLUSIVE_LOCK
,
630 expect_op_work_queue(mock_image_ctx
);
631 expect_test_features(mock_image_ctx
);
633 // verify that exclusive lock is properly handled when object map
634 // and journaling were never enabled (or active)
636 expect_get_mutable_metadata(mock_image_ctx
, 0);
637 expect_get_flags(mock_image_ctx
, 0);
638 expect_get_group(mock_image_ctx
, 0);
639 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
640 expect_clear_require_lock_on_read(mock_image_ctx
);
641 expect_shut_down_exclusive_lock(mock_image_ctx
, *mock_exclusive_lock
, 0);
644 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
647 ASSERT_EQ(0, ctx
.wait());
650 TEST_F(TestMockImageRefreshRequest
, DisableExclusiveLockWhileAcquiringLock
) {
651 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
653 librbd::ImageCtx
*ictx
;
654 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
656 MockRefreshImageCtx
mock_image_ctx(*ictx
);
657 MockRefreshParentRequest mock_refresh_parent_request
;
659 MockExclusiveLock mock_exclusive_lock
;
660 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
662 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
663 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_JOURNALING
,
667 if (ictx
->test_features(RBD_FEATURE_FAST_DIFF
)) {
668 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_FAST_DIFF
,
672 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
673 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_OBJECT_MAP
,
677 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
678 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_EXCLUSIVE_LOCK
,
682 expect_op_work_queue(mock_image_ctx
);
683 expect_test_features(mock_image_ctx
);
685 // verify that exclusive lock is properly handled when object map
686 // and journaling were never enabled (or active)
688 expect_get_mutable_metadata(mock_image_ctx
, 0);
689 expect_get_flags(mock_image_ctx
, 0);
690 expect_get_group(mock_image_ctx
, 0);
691 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
694 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, true, false, &ctx
);
697 ASSERT_EQ(-ERESTART
, ctx
.wait());
700 TEST_F(TestMockImageRefreshRequest
, JournalDisabledByPolicy
) {
701 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
703 librbd::ImageCtx
*ictx
;
704 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
706 if (ictx
->test_features(RBD_FEATURE_FAST_DIFF
)) {
707 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_FAST_DIFF
,
711 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
712 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_OBJECT_MAP
,
716 MockRefreshImageCtx
mock_image_ctx(*ictx
);
717 MockRefreshParentRequest mock_refresh_parent_request
;
719 MockExclusiveLock mock_exclusive_lock
;
720 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
722 MockJournal mock_journal
;
724 expect_op_work_queue(mock_image_ctx
);
725 expect_test_features(mock_image_ctx
);
726 expect_is_exclusive_lock_owner(mock_exclusive_lock
, true);
729 expect_get_mutable_metadata(mock_image_ctx
, 0);
730 expect_get_flags(mock_image_ctx
, 0);
731 expect_get_group(mock_image_ctx
, 0);
732 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
734 MockJournalPolicy mock_journal_policy
;
735 expect_get_journal_policy(mock_image_ctx
, mock_journal_policy
);
736 expect_journal_disabled(mock_journal_policy
, true);
739 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
742 ASSERT_EQ(0, ctx
.wait());
745 TEST_F(TestMockImageRefreshRequest
, ExclusiveLockWithCoR
) {
746 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
749 ASSERT_EQ(0, _rados
.conf_get("rbd_clone_copy_on_read", val
));
750 if (val
== "false") {
751 std::cout
<< "SKIPPING due to disabled rbd_copy_on_read" << std::endl
;
755 librbd::ImageCtx
*ictx
;
756 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
758 MockRefreshImageCtx
mock_image_ctx(*ictx
);
759 MockRefreshParentRequest mock_refresh_parent_request
;
761 MockExclusiveLock mock_exclusive_lock
;
762 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
764 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
765 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_JOURNALING
,
769 if (ictx
->test_features(RBD_FEATURE_FAST_DIFF
)) {
770 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_FAST_DIFF
,
774 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
775 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_OBJECT_MAP
,
779 expect_op_work_queue(mock_image_ctx
);
780 expect_test_features(mock_image_ctx
);
783 expect_get_mutable_metadata(mock_image_ctx
, 0);
784 expect_get_flags(mock_image_ctx
, 0);
785 expect_get_group(mock_image_ctx
, 0);
786 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
787 expect_is_lock_required(mock_image_ctx
, true);
788 expect_set_require_lock_on_read(mock_image_ctx
);
791 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
794 ASSERT_EQ(0, ctx
.wait());
797 TEST_F(TestMockImageRefreshRequest
, EnableJournalWithExclusiveLock
) {
798 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
800 librbd::ImageCtx
*ictx
;
801 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
803 if (ictx
->test_features(RBD_FEATURE_FAST_DIFF
)) {
804 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_FAST_DIFF
,
808 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
809 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_OBJECT_MAP
,
813 MockRefreshImageCtx
mock_image_ctx(*ictx
);
814 MockRefreshParentRequest mock_refresh_parent_request
;
816 MockExclusiveLock mock_exclusive_lock
;
817 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
819 MockJournal mock_journal
;
821 expect_op_work_queue(mock_image_ctx
);
822 expect_test_features(mock_image_ctx
);
823 expect_is_exclusive_lock_owner(mock_exclusive_lock
, true);
825 // journal should be immediately opened if exclusive lock owned
827 expect_get_mutable_metadata(mock_image_ctx
, 0);
828 expect_get_flags(mock_image_ctx
, 0);
829 expect_get_group(mock_image_ctx
, 0);
830 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
832 MockJournalPolicy mock_journal_policy
;
833 expect_get_journal_policy(mock_image_ctx
, mock_journal_policy
);
834 expect_journal_disabled(mock_journal_policy
, false);
835 expect_open_journal(mock_image_ctx
, mock_journal
, 0);
838 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
841 ASSERT_EQ(0, ctx
.wait());
844 TEST_F(TestMockImageRefreshRequest
, EnableJournalWithoutExclusiveLock
) {
845 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
847 librbd::ImageCtx
*ictx
;
848 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
850 if (ictx
->test_features(RBD_FEATURE_FAST_DIFF
)) {
851 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_FAST_DIFF
,
855 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
856 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_OBJECT_MAP
,
860 MockRefreshImageCtx
mock_image_ctx(*ictx
);
861 MockRefreshParentRequest mock_refresh_parent_request
;
863 MockExclusiveLock mock_exclusive_lock
;
864 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
866 expect_op_work_queue(mock_image_ctx
);
867 expect_test_features(mock_image_ctx
);
868 expect_is_exclusive_lock_owner(mock_exclusive_lock
, false);
870 // do not open the journal if exclusive lock is not owned
872 expect_get_mutable_metadata(mock_image_ctx
, 0);
873 expect_get_flags(mock_image_ctx
, 0);
874 expect_get_group(mock_image_ctx
, 0);
875 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
876 expect_set_require_lock_on_read(mock_image_ctx
);
879 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
882 ASSERT_EQ(0, ctx
.wait());
885 TEST_F(TestMockImageRefreshRequest
, DisableJournal
) {
886 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
888 librbd::ImageCtx
*ictx
;
889 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
891 MockRefreshImageCtx
mock_image_ctx(*ictx
);
892 MockRefreshParentRequest mock_refresh_parent_request
;
894 MockExclusiveLock mock_exclusive_lock
;
895 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
897 MockObjectMap mock_object_map
;
898 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
899 mock_image_ctx
.object_map
= &mock_object_map
;
902 MockJournal
*mock_journal
= new MockJournal();
903 mock_image_ctx
.journal
= mock_journal
;
905 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
906 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_JOURNALING
,
910 expect_op_work_queue(mock_image_ctx
);
911 expect_test_features(mock_image_ctx
);
913 // verify journal is closed if feature disabled
915 expect_get_mutable_metadata(mock_image_ctx
, 0);
916 expect_get_flags(mock_image_ctx
, 0);
917 expect_get_group(mock_image_ctx
, 0);
918 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
919 expect_block_writes(mock_image_ctx
, 0);
920 expect_clear_require_lock_on_read(mock_image_ctx
);
921 expect_close_journal(mock_image_ctx
, *mock_journal
, 0);
922 expect_unblock_writes(mock_image_ctx
);
925 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
928 ASSERT_EQ(0, ctx
.wait());
931 TEST_F(TestMockImageRefreshRequest
, EnableObjectMapWithExclusiveLock
) {
932 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP
);
934 librbd::ImageCtx
*ictx
;
935 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
937 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
938 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_JOURNALING
,
942 MockRefreshImageCtx
mock_image_ctx(*ictx
);
943 MockRefreshParentRequest mock_refresh_parent_request
;
945 MockExclusiveLock mock_exclusive_lock
;
946 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
948 MockObjectMap mock_object_map
;
950 expect_op_work_queue(mock_image_ctx
);
951 expect_test_features(mock_image_ctx
);
952 expect_is_exclusive_lock_owner(mock_exclusive_lock
, true);
954 // object map should be immediately opened if exclusive lock owned
956 expect_get_mutable_metadata(mock_image_ctx
, 0);
957 expect_get_flags(mock_image_ctx
, 0);
958 expect_get_group(mock_image_ctx
, 0);
959 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
960 expect_open_object_map(mock_image_ctx
, &mock_object_map
, 0);
963 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
966 ASSERT_EQ(0, ctx
.wait());
969 TEST_F(TestMockImageRefreshRequest
, EnableObjectMapWithoutExclusiveLock
) {
970 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP
);
972 librbd::ImageCtx
*ictx
;
973 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
975 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
976 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_JOURNALING
,
980 MockRefreshImageCtx
mock_image_ctx(*ictx
);
981 MockRefreshParentRequest mock_refresh_parent_request
;
983 MockExclusiveLock mock_exclusive_lock
;
984 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
986 expect_op_work_queue(mock_image_ctx
);
987 expect_test_features(mock_image_ctx
);
988 expect_is_exclusive_lock_owner(mock_exclusive_lock
, false);
990 // do not open the object map if exclusive lock is not owned
992 expect_get_mutable_metadata(mock_image_ctx
, 0);
993 expect_get_flags(mock_image_ctx
, 0);
994 expect_get_group(mock_image_ctx
, 0);
995 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
998 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
1001 ASSERT_EQ(0, ctx
.wait());
1004 TEST_F(TestMockImageRefreshRequest
, DisableObjectMap
) {
1005 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP
);
1007 librbd::ImageCtx
*ictx
;
1008 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1010 MockRefreshImageCtx
mock_image_ctx(*ictx
);
1011 MockRefreshParentRequest mock_refresh_parent_request
;
1013 MockExclusiveLock mock_exclusive_lock
;
1014 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
1016 MockObjectMap
*mock_object_map
= new MockObjectMap();
1017 mock_image_ctx
.object_map
= mock_object_map
;
1019 MockJournal mock_journal
;
1020 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
1021 mock_image_ctx
.journal
= &mock_journal
;
1024 if (ictx
->test_features(RBD_FEATURE_FAST_DIFF
)) {
1025 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_FAST_DIFF
,
1029 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
1030 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_OBJECT_MAP
,
1034 expect_op_work_queue(mock_image_ctx
);
1035 expect_test_features(mock_image_ctx
);
1037 // verify object map is closed if feature disabled
1039 expect_get_mutable_metadata(mock_image_ctx
, 0);
1040 expect_get_flags(mock_image_ctx
, 0);
1041 expect_get_group(mock_image_ctx
, 0);
1042 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
1043 expect_close_object_map(mock_image_ctx
, *mock_object_map
, 0);
1046 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
1049 ASSERT_EQ(0, ctx
.wait());
1052 TEST_F(TestMockImageRefreshRequest
, OpenObjectMapError
) {
1053 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP
);
1055 librbd::ImageCtx
*ictx
;
1056 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1058 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
1059 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_JOURNALING
,
1063 MockRefreshImageCtx
mock_image_ctx(*ictx
);
1064 MockRefreshParentRequest mock_refresh_parent_request
;
1066 MockExclusiveLock mock_exclusive_lock
;
1067 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
1069 MockObjectMap
*mock_object_map
= new MockObjectMap();
1071 expect_op_work_queue(mock_image_ctx
);
1072 expect_test_features(mock_image_ctx
);
1073 expect_is_exclusive_lock_owner(mock_exclusive_lock
, true);
1075 // object map should be immediately opened if exclusive lock owned
1077 expect_get_mutable_metadata(mock_image_ctx
, 0);
1078 expect_get_flags(mock_image_ctx
, 0);
1079 expect_get_group(mock_image_ctx
, 0);
1080 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
1081 expect_open_object_map(mock_image_ctx
, mock_object_map
, -EFBIG
);
1084 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
1087 ASSERT_EQ(0, ctx
.wait());
1088 ASSERT_EQ(nullptr, mock_image_ctx
.object_map
);
1091 } // namespace image
1092 } // namespace librbd