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/MockImageWatcher.h"
8 #include "test/librbd/mock/MockJournal.h"
9 #include "test/librbd/mock/MockJournalPolicy.h"
10 #include "test/librbd/mock/MockObjectMap.h"
11 #include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
12 #include "test/librados_test_stub/MockTestMemRadosClient.h"
13 #include "librbd/ImageState.h"
14 #include "librbd/internal.h"
15 #include "librbd/Operations.h"
16 #include "librbd/api/Image.h"
17 #include "librbd/image/RefreshRequest.h"
18 #include "librbd/image/RefreshParentRequest.h"
19 #include "librbd/io/ImageDispatchSpec.h"
20 #include "gmock/gmock.h"
21 #include "gtest/gtest.h"
22 #include <arpa/inet.h>
24 #include <boost/scope_exit.hpp>
30 struct MockRefreshImageCtx
: public MockImageCtx
{
31 MockRefreshImageCtx(ImageCtx
&image_ctx
) : MockImageCtx(image_ctx
) {
35 } // anonymous namespace
40 struct RefreshParentRequest
<MockRefreshImageCtx
> {
41 static RefreshParentRequest
* s_instance
;
42 static RefreshParentRequest
* create(MockRefreshImageCtx
&mock_image_ctx
,
43 const ParentImageInfo
&parent_md
,
44 const MigrationInfo
&migration_info
,
46 ceph_assert(s_instance
!= nullptr);
47 s_instance
->on_finish
= on_finish
;
50 static bool is_refresh_required(MockRefreshImageCtx
&mock_image_ctx
,
51 const ParentImageInfo
& parent_md
,
52 const MigrationInfo
&migration_info
) {
53 ceph_assert(s_instance
!= nullptr);
54 return s_instance
->is_refresh_required();
57 Context
*on_finish
= nullptr;
59 RefreshParentRequest() {
63 MOCK_CONST_METHOD0(is_refresh_required
, bool());
64 MOCK_METHOD0(send
, void());
65 MOCK_METHOD0(apply
, void());
66 MOCK_METHOD1(finalize
, void(Context
*));
69 RefreshParentRequest
<MockRefreshImageCtx
>* RefreshParentRequest
<MockRefreshImageCtx
>::s_instance
= nullptr;
76 struct ImageDispatchSpec
<librbd::MockRefreshImageCtx
> {
77 static ImageDispatchSpec
* s_instance
;
78 AioCompletion
*aio_comp
= nullptr;
80 static ImageDispatchSpec
* create_flush_request(
81 librbd::MockRefreshImageCtx
&image_ctx
, AioCompletion
*aio_comp
,
82 FlushSource flush_source
, const ZTracer::Trace
&parent_trace
) {
83 ceph_assert(s_instance
!= nullptr);
84 s_instance
->aio_comp
= aio_comp
;
88 MOCK_CONST_METHOD0(send
, void());
95 ImageDispatchSpec
<librbd::MockRefreshImageCtx
>* ImageDispatchSpec
<librbd::MockRefreshImageCtx
>::s_instance
= nullptr;
100 inline ImageCtx
*get_image_ctx(librbd::MockRefreshImageCtx
*image_ctx
) {
101 return image_ctx
->image_ctx
;
105 } // namespace librbd
107 // template definitions
108 #include "librbd/image/RefreshRequest.cc"
110 ACTION_P(TestFeatures
, image_ctx
) {
111 return ((image_ctx
->features
& arg0
) != 0);
114 ACTION_P(ShutDownExclusiveLock
, image_ctx
) {
115 // shutting down exclusive lock will close object map and journal
116 image_ctx
->exclusive_lock
= nullptr;
117 image_ctx
->object_map
= nullptr;
118 image_ctx
->journal
= nullptr;
125 using ::testing::DoAll
;
126 using ::testing::DoDefault
;
127 using ::testing::InSequence
;
128 using ::testing::Invoke
;
129 using ::testing::Return
;
130 using ::testing::WithArg
;
131 using ::testing::StrEq
;
133 class TestMockImageRefreshRequest
: public TestMockFixture
{
135 typedef RefreshRequest
<MockRefreshImageCtx
> MockRefreshRequest
;
136 typedef RefreshParentRequest
<MockRefreshImageCtx
> MockRefreshParentRequest
;
137 typedef io::ImageDispatchSpec
<librbd::MockRefreshImageCtx
> MockIoImageDispatchSpec
;
139 void set_v1_migration_header(ImageCtx
*ictx
) {
141 ASSERT_EQ(0, read_header_bl(ictx
->md_ctx
, ictx
->header_oid
, hdr
, nullptr));
142 ASSERT_TRUE(hdr
.length() >= sizeof(rbd_obj_header_ondisk
));
143 ASSERT_EQ(0, memcmp(RBD_HEADER_TEXT
, hdr
.c_str(), sizeof(RBD_HEADER_TEXT
)));
145 bufferlist::iterator it
= hdr
.begin();
146 it
.copy_in(sizeof(RBD_MIGRATE_HEADER_TEXT
), RBD_MIGRATE_HEADER_TEXT
);
147 ASSERT_EQ(0, ictx
->md_ctx
.write(ictx
->header_oid
, hdr
, hdr
.length(), 0));
150 void expect_set_require_lock(MockRefreshImageCtx
&mock_image_ctx
,
151 librbd::io::Direction direction
, bool enabled
) {
152 EXPECT_CALL(*mock_image_ctx
.io_work_queue
, set_require_lock(direction
,
156 void expect_v1_read_header(MockRefreshImageCtx
&mock_image_ctx
, int r
) {
157 auto &expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
158 read(mock_image_ctx
.header_oid
, _
, _
, _
));
160 expect
.WillOnce(Return(r
));
162 expect
.WillOnce(DoDefault());
166 void expect_v1_get_snapshots(MockRefreshImageCtx
&mock_image_ctx
, int r
) {
167 auto &expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
168 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("snap_list"), _
, _
, _
));
170 expect
.WillOnce(Return(r
));
172 expect
.WillOnce(DoDefault());
176 void expect_v1_get_locks(MockRefreshImageCtx
&mock_image_ctx
, int r
) {
177 auto &expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
178 exec(mock_image_ctx
.header_oid
, _
, StrEq("lock"), StrEq("get_info"), _
, _
, _
));
180 expect
.WillOnce(Return(r
));
182 expect
.WillOnce(DoDefault());
186 void expect_get_mutable_metadata(MockRefreshImageCtx
&mock_image_ctx
,
187 uint64_t features
, int r
) {
188 auto &expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
189 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_size"), _
, _
, _
));
191 expect
.WillOnce(Return(r
));
193 uint64_t incompatible
= (
194 mock_image_ctx
.read_only
? features
& RBD_FEATURES_INCOMPATIBLE
:
195 features
& RBD_FEATURES_RW_INCOMPATIBLE
);
197 expect
.WillOnce(DoDefault());
198 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
199 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_features"), _
, _
, _
))
200 .WillOnce(WithArg
<5>(Invoke([features
, incompatible
](bufferlist
* out_bl
) {
201 encode(features
, *out_bl
);
202 encode(incompatible
, *out_bl
);
205 expect_get_flags(mock_image_ctx
, 0);
206 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
207 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_snapcontext"), _
, _
, _
))
208 .WillOnce(DoDefault());
209 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
210 exec(mock_image_ctx
.header_oid
, _
, StrEq("lock"), StrEq("get_info"), _
, _
, _
))
211 .WillOnce(DoDefault());
215 void expect_parent_overlap_get(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"),
218 StrEq("parent_overlap_get"), _
, _
, _
));
220 expect
.WillOnce(Return(r
));
222 expect
.WillOnce(DoDefault());
226 void expect_get_parent(MockRefreshImageCtx
&mock_image_ctx
, int r
) {
227 auto& expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
228 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"),
229 StrEq("parent_get"), _
, _
, _
));
231 expect
.WillOnce(Return(r
));
233 expect
.WillOnce(DoDefault());
234 expect_parent_overlap_get(mock_image_ctx
, 0);
238 void expect_get_parent_legacy(MockRefreshImageCtx
&mock_image_ctx
, int r
) {
239 auto& expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
240 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"),
241 StrEq("get_parent"), _
, _
, _
));
243 expect
.WillOnce(Return(r
));
245 expect
.WillOnce(DoDefault());
249 void expect_get_migration_header(MockRefreshImageCtx
&mock_image_ctx
, int r
) {
250 auto &expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
251 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"),
252 StrEq("migration_get"), _
, _
, _
));
254 expect
.WillOnce(Return(r
));
256 expect
.WillOnce(DoDefault());
260 void expect_get_metadata(MockRefreshImageCtx
&mock_image_ctx
, int r
) {
261 auto &expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
262 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("metadata_list"), _
, _
, _
));
264 expect
.WillOnce(Return(r
));
266 expect
.WillOnce(DoDefault());
267 EXPECT_CALL(*mock_image_ctx
.image_watcher
, is_unregistered())
268 .WillOnce(Return(false));
272 void expect_get_flags(MockRefreshImageCtx
&mock_image_ctx
, int r
) {
273 auto &expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
274 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_flags"), _
, _
, _
));
276 expect
.WillOnce(Return(r
));
278 expect
.WillOnce(DoDefault());
282 void expect_get_op_features(MockRefreshImageCtx
&mock_image_ctx
,
283 uint64_t op_features
, int r
) {
284 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
285 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"),
286 StrEq("op_features_get"), _
, _
, _
))
287 .WillOnce(WithArg
<5>(Invoke([op_features
, r
](bufferlist
* out_bl
) {
288 encode(op_features
, *out_bl
);
293 void expect_get_group(MockRefreshImageCtx
&mock_image_ctx
, int r
) {
294 auto &expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
295 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"),
296 StrEq("image_group_get"), _
, _
, _
));
298 expect
.WillOnce(Return(r
));
300 expect
.WillOnce(DoDefault());
304 void expect_get_snapshots(MockRefreshImageCtx
&mock_image_ctx
,
305 bool legacy_parent
, int r
) {
306 auto &expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
307 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("snapshot_get"), _
, _
, _
));
309 expect
.WillOnce(Return(r
));
311 expect
.WillOnce(DoDefault());
313 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
314 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_parent"), _
, _
, _
))
315 .WillOnce(DoDefault());
317 expect_parent_overlap_get(mock_image_ctx
, 0);
319 expect_get_flags(mock_image_ctx
, 0);
320 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
321 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_protection_status"), _
, _
, _
))
322 .WillOnce(DoDefault());
326 void expect_get_snapshots_legacy(MockRefreshImageCtx
&mock_image_ctx
, int r
) {
327 auto &expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
328 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_snapshot_name"), _
, _
, _
));
330 expect
.WillOnce(Return(r
));
332 expect
.WillOnce(DoDefault());
333 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
334 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_size"), _
, _
, _
))
335 .WillOnce(DoDefault());
336 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
337 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_snapshot_timestamp"), _
, _
, _
))
338 .WillOnce(DoDefault());
339 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
340 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_parent"), _
, _
, _
))
341 .WillOnce(DoDefault());
342 expect_get_flags(mock_image_ctx
, 0);
343 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
344 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_protection_status"), _
, _
, _
))
345 .WillOnce(DoDefault());
349 void expect_apply_metadata(MockRefreshImageCtx
&mock_image_ctx
,
351 EXPECT_CALL(mock_image_ctx
, apply_metadata(_
, false))
352 .WillOnce(Return(r
));
355 void expect_add_snap(MockRefreshImageCtx
&mock_image_ctx
,
356 const std::string
&snap_name
, uint64_t snap_id
) {
357 EXPECT_CALL(mock_image_ctx
, add_snap(_
, snap_name
, snap_id
, _
, _
, _
, _
, _
));
360 void expect_init_exclusive_lock(MockRefreshImageCtx
&mock_image_ctx
,
361 MockExclusiveLock
&mock_exclusive_lock
,
363 EXPECT_CALL(mock_image_ctx
, create_exclusive_lock())
364 .WillOnce(Return(&mock_exclusive_lock
));
365 EXPECT_CALL(mock_exclusive_lock
, init(mock_image_ctx
.features
, _
))
366 .WillOnce(WithArg
<1>(CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
)));
369 void expect_shut_down_exclusive_lock(MockRefreshImageCtx
&mock_image_ctx
,
370 MockExclusiveLock
&mock_exclusive_lock
,
372 EXPECT_CALL(mock_exclusive_lock
, shut_down(_
))
373 .WillOnce(DoAll(ShutDownExclusiveLock(&mock_image_ctx
),
374 CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
)));
377 void expect_init_layout(MockRefreshImageCtx
&mock_image_ctx
) {
378 EXPECT_CALL(mock_image_ctx
, init_layout());
381 void expect_test_features(MockRefreshImageCtx
&mock_image_ctx
) {
382 EXPECT_CALL(mock_image_ctx
, test_features(_
, _
))
383 .WillRepeatedly(TestFeatures(&mock_image_ctx
));
386 void expect_refresh_parent_is_required(MockRefreshParentRequest
&mock_refresh_parent_request
,
388 EXPECT_CALL(mock_refresh_parent_request
, is_refresh_required())
389 .WillRepeatedly(Return(required
));
392 void expect_refresh_parent_send(MockRefreshImageCtx
&mock_image_ctx
,
393 MockRefreshParentRequest
&mock_refresh_parent_request
,
395 EXPECT_CALL(mock_refresh_parent_request
, send())
396 .WillOnce(FinishRequest(&mock_refresh_parent_request
, r
,
400 void expect_refresh_parent_apply(MockRefreshParentRequest
&mock_refresh_parent_request
) {
401 EXPECT_CALL(mock_refresh_parent_request
, apply());
404 void expect_refresh_parent_finalize(MockRefreshImageCtx
&mock_image_ctx
,
405 MockRefreshParentRequest
&mock_refresh_parent_request
,
407 EXPECT_CALL(mock_refresh_parent_request
, finalize(_
))
408 .WillOnce(CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
));
411 void expect_is_exclusive_lock_owner(MockExclusiveLock
&mock_exclusive_lock
,
413 EXPECT_CALL(mock_exclusive_lock
, is_lock_owner()).WillOnce(Return(is_owner
));
416 void expect_get_journal_policy(MockImageCtx
&mock_image_ctx
,
417 MockJournalPolicy
&mock_journal_policy
) {
418 EXPECT_CALL(mock_image_ctx
, get_journal_policy())
419 .WillOnce(Return(&mock_journal_policy
));
422 void expect_journal_disabled(MockJournalPolicy
&mock_journal_policy
,
424 EXPECT_CALL(mock_journal_policy
, journal_disabled())
425 .WillOnce(Return(disabled
));
428 void expect_open_journal(MockRefreshImageCtx
&mock_image_ctx
,
429 MockJournal
&mock_journal
, int r
) {
430 EXPECT_CALL(mock_image_ctx
, create_journal())
431 .WillOnce(Return(&mock_journal
));
432 EXPECT_CALL(mock_journal
, open(_
))
433 .WillOnce(CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
));
436 void expect_close_journal(MockRefreshImageCtx
&mock_image_ctx
,
437 MockJournal
&mock_journal
, int r
) {
438 EXPECT_CALL(mock_journal
, close(_
))
439 .WillOnce(CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
));
442 void expect_open_object_map(MockRefreshImageCtx
&mock_image_ctx
,
443 MockObjectMap
*mock_object_map
, int r
) {
444 EXPECT_CALL(mock_image_ctx
, create_object_map(_
))
445 .WillOnce(Return(mock_object_map
));
446 EXPECT_CALL(*mock_object_map
, open(_
))
447 .WillOnce(CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
));
450 void expect_close_object_map(MockRefreshImageCtx
&mock_image_ctx
,
451 MockObjectMap
&mock_object_map
, int r
) {
452 EXPECT_CALL(mock_object_map
, close(_
))
453 .WillOnce(CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
));
456 void expect_get_snap_id(MockRefreshImageCtx
&mock_image_ctx
,
457 const std::string
&snap_name
,
459 EXPECT_CALL(mock_image_ctx
,
460 get_snap_id(_
, snap_name
)).WillOnce(Return(snap_id
));
463 void expect_block_writes(MockImageCtx
&mock_image_ctx
, int r
) {
464 EXPECT_CALL(*mock_image_ctx
.io_work_queue
, block_writes(_
))
465 .WillOnce(CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
));
468 void expect_unblock_writes(MockImageCtx
&mock_image_ctx
) {
469 EXPECT_CALL(*mock_image_ctx
.io_work_queue
, unblock_writes())
473 void expect_image_flush(MockIoImageDispatchSpec
&mock_image_request
, int r
) {
474 EXPECT_CALL(mock_image_request
, send())
475 .WillOnce(Invoke([&mock_image_request
, r
]() {
476 mock_image_request
.aio_comp
->set_request_count(1);
477 mock_image_request
.aio_comp
->add_request();
478 mock_image_request
.aio_comp
->complete_request(r
);
484 TEST_F(TestMockImageRefreshRequest
, SuccessV1
) {
487 librbd::ImageCtx
*ictx
;
488 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
490 MockRefreshImageCtx
mock_image_ctx(*ictx
);
491 expect_op_work_queue(mock_image_ctx
);
492 expect_test_features(mock_image_ctx
);
495 expect_v1_read_header(mock_image_ctx
, 0);
496 expect_v1_get_snapshots(mock_image_ctx
, 0);
497 expect_v1_get_locks(mock_image_ctx
, 0);
498 expect_init_layout(mock_image_ctx
);
501 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
504 ASSERT_EQ(0, ctx
.wait());
507 TEST_F(TestMockImageRefreshRequest
, SuccessSnapshotV1
) {
509 librbd::ImageCtx
*ictx
;
510 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
511 ASSERT_EQ(0, snap_create(*ictx
, "snap"));
512 ASSERT_EQ(0, ictx
->state
->refresh());
514 MockRefreshImageCtx
mock_image_ctx(*ictx
);
515 expect_op_work_queue(mock_image_ctx
);
516 expect_test_features(mock_image_ctx
);
519 expect_v1_read_header(mock_image_ctx
, 0);
520 expect_v1_get_snapshots(mock_image_ctx
, 0);
521 expect_v1_get_locks(mock_image_ctx
, 0);
522 expect_init_layout(mock_image_ctx
);
523 expect_add_snap(mock_image_ctx
, "snap", ictx
->snap_ids
.begin()->second
);
526 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
529 ASSERT_EQ(0, ctx
.wait());
532 TEST_F(TestMockImageRefreshRequest
, SuccessV2
) {
535 librbd::ImageCtx
*ictx
;
536 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
538 MockRefreshImageCtx
mock_image_ctx(*ictx
);
539 MockRefreshParentRequest mock_refresh_parent_request
;
540 MockExclusiveLock mock_exclusive_lock
;
541 expect_op_work_queue(mock_image_ctx
);
542 expect_test_features(mock_image_ctx
);
545 expect_get_mutable_metadata(mock_image_ctx
, ictx
->features
, 0);
546 expect_get_parent(mock_image_ctx
, 0);
547 expect_get_metadata(mock_image_ctx
, 0);
548 expect_apply_metadata(mock_image_ctx
, 0);
549 expect_get_group(mock_image_ctx
, -EOPNOTSUPP
);
550 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
551 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
552 expect_init_exclusive_lock(mock_image_ctx
, mock_exclusive_lock
, 0);
556 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
559 ASSERT_EQ(0, ctx
.wait());
562 TEST_F(TestMockImageRefreshRequest
, SuccessSnapshotV2
) {
565 librbd::ImageCtx
*ictx
;
566 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
567 ASSERT_EQ(0, snap_create(*ictx
, "snap"));
569 MockRefreshImageCtx
mock_image_ctx(*ictx
);
570 MockRefreshParentRequest mock_refresh_parent_request
;
571 MockExclusiveLock mock_exclusive_lock
;
572 expect_op_work_queue(mock_image_ctx
);
573 expect_test_features(mock_image_ctx
);
576 expect_get_mutable_metadata(mock_image_ctx
, ictx
->features
, 0);
577 expect_get_parent(mock_image_ctx
, 0);
578 expect_get_metadata(mock_image_ctx
, 0);
579 expect_apply_metadata(mock_image_ctx
, 0);
580 expect_get_group(mock_image_ctx
, 0);
581 expect_get_snapshots(mock_image_ctx
, false, 0);
582 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
583 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
584 expect_init_exclusive_lock(mock_image_ctx
, mock_exclusive_lock
, 0);
586 expect_add_snap(mock_image_ctx
, "snap", ictx
->snap_ids
.begin()->second
);
589 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
592 ASSERT_EQ(0, ctx
.wait());
595 TEST_F(TestMockImageRefreshRequest
, SuccessLegacySnapshotV2
) {
598 librbd::ImageCtx
*ictx
;
599 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
600 ASSERT_EQ(0, snap_create(*ictx
, "snap"));
602 MockRefreshImageCtx
mock_image_ctx(*ictx
);
603 MockRefreshParentRequest mock_refresh_parent_request
;
604 MockExclusiveLock mock_exclusive_lock
;
605 expect_op_work_queue(mock_image_ctx
);
606 expect_test_features(mock_image_ctx
);
609 expect_get_mutable_metadata(mock_image_ctx
, ictx
->features
, 0);
610 expect_get_parent(mock_image_ctx
, -EOPNOTSUPP
);
611 expect_get_parent_legacy(mock_image_ctx
, 0);
612 expect_get_metadata(mock_image_ctx
, 0);
613 expect_apply_metadata(mock_image_ctx
, 0);
614 expect_get_group(mock_image_ctx
, 0);
615 expect_get_snapshots(mock_image_ctx
, true, -EOPNOTSUPP
);
616 expect_get_snapshots_legacy(mock_image_ctx
, 0);
617 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
618 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
619 expect_init_exclusive_lock(mock_image_ctx
, mock_exclusive_lock
, 0);
621 expect_add_snap(mock_image_ctx
, "snap", ictx
->snap_ids
.begin()->second
);
624 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
627 ASSERT_EQ(0, ctx
.wait());
630 TEST_F(TestMockImageRefreshRequest
, SuccessSetSnapshotV2
) {
633 librbd::ImageCtx
*ictx
;
634 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
635 ASSERT_EQ(0, snap_create(*ictx
, "snap"));
636 ASSERT_EQ(0, librbd::api::Image
<>::snap_set(ictx
,
637 cls::rbd::UserSnapshotNamespace(),
640 MockRefreshImageCtx
mock_image_ctx(*ictx
);
641 MockRefreshParentRequest mock_refresh_parent_request
;
642 MockObjectMap mock_object_map
;
643 expect_op_work_queue(mock_image_ctx
);
644 expect_test_features(mock_image_ctx
);
647 expect_get_mutable_metadata(mock_image_ctx
, ictx
->features
, 0);
648 expect_get_parent(mock_image_ctx
, 0);
649 expect_get_metadata(mock_image_ctx
, 0);
650 expect_apply_metadata(mock_image_ctx
, 0);
651 expect_get_group(mock_image_ctx
, 0);
652 expect_get_snapshots(mock_image_ctx
, false, 0);
653 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
654 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
655 expect_open_object_map(mock_image_ctx
, &mock_object_map
, 0);
657 expect_add_snap(mock_image_ctx
, "snap", ictx
->snap_ids
.begin()->second
);
658 expect_get_snap_id(mock_image_ctx
, "snap", ictx
->snap_ids
.begin()->second
);
661 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
664 ASSERT_EQ(0, ctx
.wait());
667 TEST_F(TestMockImageRefreshRequest
, SuccessChild
) {
668 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
670 librbd::ImageCtx
*ictx
;
671 librbd::ImageCtx
*ictx2
= nullptr;
672 std::string clone_name
= get_temp_image_name();
674 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
675 ASSERT_EQ(0, snap_create(*ictx
, "snap"));
676 ASSERT_EQ(0, snap_protect(*ictx
, "snap"));
677 BOOST_SCOPE_EXIT_ALL((&)) {
678 if (ictx2
!= nullptr) {
682 librbd::NoOpProgressContext no_op
;
683 ASSERT_EQ(0, librbd::api::Image
<>::remove(m_ioctx
, clone_name
, no_op
));
684 ASSERT_EQ(0, ictx
->operations
->snap_unprotect(cls::rbd::UserSnapshotNamespace(), "snap"));
687 int order
= ictx
->order
;
688 ASSERT_EQ(0, librbd::clone(m_ioctx
, m_image_name
.c_str(), "snap", m_ioctx
,
689 clone_name
.c_str(), ictx
->features
, &order
, 0, 0));
691 ASSERT_EQ(0, open_image(clone_name
, &ictx2
));
693 MockRefreshImageCtx
mock_image_ctx(*ictx2
);
694 MockRefreshParentRequest
*mock_refresh_parent_request
= new MockRefreshParentRequest();
695 MockExclusiveLock mock_exclusive_lock
;
696 expect_op_work_queue(mock_image_ctx
);
697 expect_test_features(mock_image_ctx
);
700 expect_get_mutable_metadata(mock_image_ctx
, ictx2
->features
, 0);
701 expect_get_parent(mock_image_ctx
, 0);
702 expect_get_metadata(mock_image_ctx
, 0);
703 expect_apply_metadata(mock_image_ctx
, 0);
704 expect_get_op_features(mock_image_ctx
, RBD_OPERATION_FEATURE_CLONE_CHILD
, 0);
705 expect_get_group(mock_image_ctx
, 0);
706 expect_refresh_parent_is_required(*mock_refresh_parent_request
, true);
707 expect_refresh_parent_send(mock_image_ctx
, *mock_refresh_parent_request
, 0);
708 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
709 expect_init_exclusive_lock(mock_image_ctx
, mock_exclusive_lock
, 0);
711 expect_refresh_parent_apply(*mock_refresh_parent_request
);
712 expect_refresh_parent_finalize(mock_image_ctx
, *mock_refresh_parent_request
, 0);
715 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
718 ASSERT_EQ(0, ctx
.wait());
721 TEST_F(TestMockImageRefreshRequest
, SuccessChildDontOpenParent
) {
722 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
724 librbd::ImageCtx
*ictx
;
725 librbd::ImageCtx
*ictx2
= nullptr;
726 std::string clone_name
= get_temp_image_name();
728 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
729 ASSERT_EQ(0, snap_create(*ictx
, "snap"));
730 ASSERT_EQ(0, snap_protect(*ictx
, "snap"));
731 BOOST_SCOPE_EXIT_ALL((&)) {
732 if (ictx2
!= nullptr) {
736 librbd::NoOpProgressContext no_op
;
737 ASSERT_EQ(0, librbd::api::Image
<>::remove(m_ioctx
, clone_name
, no_op
));
738 ASSERT_EQ(0, ictx
->operations
->snap_unprotect(cls::rbd::UserSnapshotNamespace(), "snap"));
741 int order
= ictx
->order
;
742 ASSERT_EQ(0, librbd::clone(m_ioctx
, m_image_name
.c_str(), "snap", m_ioctx
,
743 clone_name
.c_str(), ictx
->features
, &order
, 0, 0));
745 ASSERT_EQ(0, open_image(clone_name
, &ictx2
));
747 MockRefreshImageCtx
mock_image_ctx(*ictx2
);
748 MockExclusiveLock mock_exclusive_lock
;
749 expect_op_work_queue(mock_image_ctx
);
750 expect_test_features(mock_image_ctx
);
753 expect_get_mutable_metadata(mock_image_ctx
, ictx2
->features
, 0);
754 expect_get_parent(mock_image_ctx
, 0);
755 expect_get_metadata(mock_image_ctx
, 0);
756 expect_apply_metadata(mock_image_ctx
, 0);
757 expect_get_op_features(mock_image_ctx
, RBD_OPERATION_FEATURE_CLONE_CHILD
, 0);
758 expect_get_group(mock_image_ctx
, 0);
759 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
760 expect_init_exclusive_lock(mock_image_ctx
, mock_exclusive_lock
, 0);
764 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, true, &ctx
);
767 ASSERT_EQ(0, ctx
.wait());
770 TEST_F(TestMockImageRefreshRequest
, SuccessOpFeatures
) {
773 librbd::ImageCtx
*ictx
;
774 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
776 MockRefreshImageCtx
mock_image_ctx(*ictx
);
777 MockRefreshParentRequest mock_refresh_parent_request
;
778 MockExclusiveLock mock_exclusive_lock
;
779 expect_op_work_queue(mock_image_ctx
);
780 expect_test_features(mock_image_ctx
);
782 mock_image_ctx
.features
|= RBD_FEATURE_OPERATIONS
;
785 expect_get_mutable_metadata(mock_image_ctx
, mock_image_ctx
.features
, 0);
786 expect_get_parent(mock_image_ctx
, 0);
787 expect_get_metadata(mock_image_ctx
, 0);
788 expect_apply_metadata(mock_image_ctx
, 0);
789 expect_get_op_features(mock_image_ctx
, 4096, 0);
790 expect_get_group(mock_image_ctx
, 0);
791 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
792 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
793 expect_init_exclusive_lock(mock_image_ctx
, mock_exclusive_lock
, 0);
797 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
800 ASSERT_EQ(0, ctx
.wait());
801 ASSERT_EQ(4096U, mock_image_ctx
.op_features
);
802 ASSERT_TRUE(mock_image_ctx
.operations_disabled
);
805 TEST_F(TestMockImageRefreshRequest
, DisableExclusiveLock
) {
806 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
808 librbd::ImageCtx
*ictx
;
809 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
811 MockRefreshImageCtx
mock_image_ctx(*ictx
);
812 MockRefreshParentRequest mock_refresh_parent_request
;
814 MockExclusiveLock
*mock_exclusive_lock
= new MockExclusiveLock();
815 mock_image_ctx
.exclusive_lock
= mock_exclusive_lock
;
817 MockObjectMap mock_object_map
;
818 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
819 mock_image_ctx
.object_map
= &mock_object_map
;
822 MockJournal mock_journal
;
823 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
824 mock_image_ctx
.journal
= &mock_journal
;
827 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
828 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_JOURNALING
,
832 if (ictx
->test_features(RBD_FEATURE_FAST_DIFF
)) {
833 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_FAST_DIFF
,
837 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
838 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_OBJECT_MAP
,
842 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
843 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_EXCLUSIVE_LOCK
,
847 ASSERT_EQ(0, ictx
->state
->refresh());
849 expect_op_work_queue(mock_image_ctx
);
850 expect_test_features(mock_image_ctx
);
852 // verify that exclusive lock is properly handled when object map
853 // and journaling were never enabled (or active)
855 expect_get_mutable_metadata(mock_image_ctx
, ictx
->features
, 0);
856 expect_get_parent(mock_image_ctx
, 0);
857 expect_get_metadata(mock_image_ctx
, 0);
858 expect_apply_metadata(mock_image_ctx
, 0);
859 expect_get_group(mock_image_ctx
, 0);
860 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
861 expect_shut_down_exclusive_lock(mock_image_ctx
, *mock_exclusive_lock
, 0);
864 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
867 ASSERT_EQ(0, ctx
.wait());
870 TEST_F(TestMockImageRefreshRequest
, DisableExclusiveLockWhileAcquiringLock
) {
871 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
873 librbd::ImageCtx
*ictx
;
874 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
876 MockRefreshImageCtx
mock_image_ctx(*ictx
);
877 MockRefreshParentRequest mock_refresh_parent_request
;
879 MockExclusiveLock mock_exclusive_lock
;
880 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
882 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
883 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_JOURNALING
,
887 if (ictx
->test_features(RBD_FEATURE_FAST_DIFF
)) {
888 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_FAST_DIFF
,
892 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
893 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_OBJECT_MAP
,
897 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
898 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_EXCLUSIVE_LOCK
,
902 ASSERT_EQ(0, ictx
->state
->refresh());
904 expect_op_work_queue(mock_image_ctx
);
905 expect_test_features(mock_image_ctx
);
907 // verify that exclusive lock is properly handled when object map
908 // and journaling were never enabled (or active)
910 expect_get_mutable_metadata(mock_image_ctx
, ictx
->features
, 0);
911 expect_get_parent(mock_image_ctx
, 0);
912 expect_get_metadata(mock_image_ctx
, 0);
913 expect_apply_metadata(mock_image_ctx
, 0);
914 expect_get_group(mock_image_ctx
, 0);
915 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
918 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, true, false, &ctx
);
921 ASSERT_EQ(-ERESTART
, ctx
.wait());
924 TEST_F(TestMockImageRefreshRequest
, JournalDisabledByPolicy
) {
925 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
927 librbd::ImageCtx
*ictx
;
928 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
930 if (ictx
->test_features(RBD_FEATURE_FAST_DIFF
)) {
931 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_FAST_DIFF
,
935 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
936 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_OBJECT_MAP
,
940 ASSERT_EQ(0, ictx
->state
->refresh());
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 MockJournal mock_journal
;
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);
955 expect_get_mutable_metadata(mock_image_ctx
, ictx
->features
, 0);
956 expect_get_parent(mock_image_ctx
, 0);
957 expect_get_metadata(mock_image_ctx
, 0);
958 expect_apply_metadata(mock_image_ctx
, 0);
959 expect_get_group(mock_image_ctx
, 0);
960 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
962 MockJournalPolicy mock_journal_policy
;
963 expect_get_journal_policy(mock_image_ctx
, mock_journal_policy
);
964 expect_journal_disabled(mock_journal_policy
, true);
967 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
970 ASSERT_EQ(0, ctx
.wait());
973 TEST_F(TestMockImageRefreshRequest
, EnableJournalWithExclusiveLock
) {
974 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
976 librbd::ImageCtx
*ictx
;
977 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
979 if (ictx
->test_features(RBD_FEATURE_FAST_DIFF
)) {
980 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_FAST_DIFF
,
984 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
985 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_OBJECT_MAP
,
989 ASSERT_EQ(0, ictx
->state
->refresh());
991 MockRefreshImageCtx
mock_image_ctx(*ictx
);
992 MockRefreshParentRequest mock_refresh_parent_request
;
994 MockExclusiveLock mock_exclusive_lock
;
995 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
997 MockJournal mock_journal
;
999 expect_op_work_queue(mock_image_ctx
);
1000 expect_test_features(mock_image_ctx
);
1001 expect_is_exclusive_lock_owner(mock_exclusive_lock
, true);
1003 // journal should be immediately opened if exclusive lock owned
1005 expect_get_mutable_metadata(mock_image_ctx
, ictx
->features
, 0);
1006 expect_get_parent(mock_image_ctx
, 0);
1007 expect_get_metadata(mock_image_ctx
, 0);
1008 expect_apply_metadata(mock_image_ctx
, 0);
1009 expect_get_group(mock_image_ctx
, 0);
1010 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
1012 MockJournalPolicy mock_journal_policy
;
1013 expect_get_journal_policy(mock_image_ctx
, mock_journal_policy
);
1014 expect_journal_disabled(mock_journal_policy
, false);
1015 expect_open_journal(mock_image_ctx
, mock_journal
, 0);
1018 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
1021 ASSERT_EQ(0, ctx
.wait());
1024 TEST_F(TestMockImageRefreshRequest
, EnableJournalWithoutExclusiveLock
) {
1025 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
1027 librbd::ImageCtx
*ictx
;
1028 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1030 if (ictx
->test_features(RBD_FEATURE_FAST_DIFF
)) {
1031 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_FAST_DIFF
,
1035 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
1036 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_OBJECT_MAP
,
1040 ASSERT_EQ(0, ictx
->state
->refresh());
1042 MockRefreshImageCtx
mock_image_ctx(*ictx
);
1043 MockRefreshParentRequest mock_refresh_parent_request
;
1045 MockExclusiveLock mock_exclusive_lock
;
1046 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
1048 expect_op_work_queue(mock_image_ctx
);
1049 expect_test_features(mock_image_ctx
);
1050 expect_is_exclusive_lock_owner(mock_exclusive_lock
, false);
1052 // do not open the journal if exclusive lock is not owned
1054 expect_get_mutable_metadata(mock_image_ctx
, ictx
->features
, 0);
1055 expect_get_parent(mock_image_ctx
, 0);
1056 expect_get_metadata(mock_image_ctx
, 0);
1057 expect_apply_metadata(mock_image_ctx
, 0);
1058 expect_get_group(mock_image_ctx
, 0);
1059 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
1060 expect_set_require_lock(mock_image_ctx
, librbd::io::DIRECTION_BOTH
, true);
1063 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
1066 ASSERT_EQ(0, ctx
.wait());
1069 TEST_F(TestMockImageRefreshRequest
, DisableJournal
) {
1070 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
1072 librbd::ImageCtx
*ictx
;
1073 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1075 MockRefreshImageCtx
mock_image_ctx(*ictx
);
1076 MockRefreshParentRequest mock_refresh_parent_request
;
1078 MockExclusiveLock mock_exclusive_lock
;
1079 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
1081 MockObjectMap mock_object_map
;
1082 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
1083 mock_image_ctx
.object_map
= &mock_object_map
;
1086 MockJournal
*mock_journal
= new MockJournal();
1087 mock_image_ctx
.journal
= mock_journal
;
1089 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
1090 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_JOURNALING
,
1094 ASSERT_EQ(0, ictx
->state
->refresh());
1096 expect_op_work_queue(mock_image_ctx
);
1097 expect_test_features(mock_image_ctx
);
1099 // verify journal is closed if feature disabled
1101 expect_get_mutable_metadata(mock_image_ctx
, ictx
->features
, 0);
1102 expect_get_parent(mock_image_ctx
, 0);
1103 expect_get_metadata(mock_image_ctx
, 0);
1104 expect_apply_metadata(mock_image_ctx
, 0);
1105 expect_get_group(mock_image_ctx
, 0);
1106 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
1107 expect_block_writes(mock_image_ctx
, 0);
1108 if (!mock_image_ctx
.clone_copy_on_read
) {
1109 expect_set_require_lock(mock_image_ctx
, librbd::io::DIRECTION_READ
, false);
1111 expect_close_journal(mock_image_ctx
, *mock_journal
, 0);
1112 expect_unblock_writes(mock_image_ctx
);
1115 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
1118 ASSERT_EQ(0, ctx
.wait());
1121 TEST_F(TestMockImageRefreshRequest
, EnableObjectMapWithExclusiveLock
) {
1122 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP
);
1124 librbd::ImageCtx
*ictx
;
1125 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1127 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
1128 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_JOURNALING
,
1132 ASSERT_EQ(0, ictx
->state
->refresh());
1134 MockRefreshImageCtx
mock_image_ctx(*ictx
);
1135 MockRefreshParentRequest mock_refresh_parent_request
;
1137 MockExclusiveLock mock_exclusive_lock
;
1138 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
1140 MockObjectMap mock_object_map
;
1142 expect_op_work_queue(mock_image_ctx
);
1143 expect_test_features(mock_image_ctx
);
1144 expect_is_exclusive_lock_owner(mock_exclusive_lock
, true);
1146 // object map should be immediately opened if exclusive lock owned
1148 expect_get_mutable_metadata(mock_image_ctx
, ictx
->features
, 0);
1149 expect_get_parent(mock_image_ctx
, 0);
1150 expect_get_metadata(mock_image_ctx
, 0);
1151 expect_apply_metadata(mock_image_ctx
, 0);
1152 expect_get_group(mock_image_ctx
, 0);
1153 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
1154 expect_open_object_map(mock_image_ctx
, &mock_object_map
, 0);
1157 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
1160 ASSERT_EQ(0, ctx
.wait());
1163 TEST_F(TestMockImageRefreshRequest
, EnableObjectMapWithoutExclusiveLock
) {
1164 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP
);
1166 librbd::ImageCtx
*ictx
;
1167 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1169 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
1170 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_JOURNALING
,
1174 ASSERT_EQ(0, ictx
->state
->refresh());
1176 MockRefreshImageCtx
mock_image_ctx(*ictx
);
1177 MockRefreshParentRequest mock_refresh_parent_request
;
1179 MockExclusiveLock mock_exclusive_lock
;
1180 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
1182 expect_op_work_queue(mock_image_ctx
);
1183 expect_test_features(mock_image_ctx
);
1184 expect_is_exclusive_lock_owner(mock_exclusive_lock
, false);
1186 // do not open the object map if exclusive lock is not owned
1188 expect_get_mutable_metadata(mock_image_ctx
, ictx
->features
, 0);
1189 expect_get_parent(mock_image_ctx
, 0);
1190 expect_get_metadata(mock_image_ctx
, 0);
1191 expect_apply_metadata(mock_image_ctx
, 0);
1192 expect_get_group(mock_image_ctx
, 0);
1193 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
1196 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
1199 ASSERT_EQ(0, ctx
.wait());
1202 TEST_F(TestMockImageRefreshRequest
, DisableObjectMap
) {
1203 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP
);
1205 librbd::ImageCtx
*ictx
;
1206 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1208 MockRefreshImageCtx
mock_image_ctx(*ictx
);
1209 MockRefreshParentRequest mock_refresh_parent_request
;
1211 MockExclusiveLock mock_exclusive_lock
;
1212 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
1214 MockObjectMap
*mock_object_map
= new MockObjectMap();
1215 mock_image_ctx
.object_map
= mock_object_map
;
1217 MockJournal mock_journal
;
1218 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
1219 mock_image_ctx
.journal
= &mock_journal
;
1222 if (ictx
->test_features(RBD_FEATURE_FAST_DIFF
)) {
1223 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_FAST_DIFF
,
1227 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
1228 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_OBJECT_MAP
,
1232 ASSERT_EQ(0, ictx
->state
->refresh());
1234 expect_op_work_queue(mock_image_ctx
);
1235 expect_test_features(mock_image_ctx
);
1237 // verify object map is closed if feature disabled
1239 expect_get_mutable_metadata(mock_image_ctx
, ictx
->features
, 0);
1240 expect_get_parent(mock_image_ctx
, 0);
1241 expect_get_metadata(mock_image_ctx
, 0);
1242 expect_apply_metadata(mock_image_ctx
, 0);
1243 expect_get_group(mock_image_ctx
, 0);
1244 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
1245 expect_close_object_map(mock_image_ctx
, *mock_object_map
, 0);
1248 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
1251 ASSERT_EQ(0, ctx
.wait());
1254 TEST_F(TestMockImageRefreshRequest
, OpenObjectMapError
) {
1255 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP
);
1257 librbd::ImageCtx
*ictx
;
1258 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1260 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
1261 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_JOURNALING
,
1265 ASSERT_EQ(0, ictx
->state
->refresh());
1267 MockRefreshImageCtx
mock_image_ctx(*ictx
);
1268 MockRefreshParentRequest mock_refresh_parent_request
;
1270 MockExclusiveLock mock_exclusive_lock
;
1271 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
1273 MockObjectMap
*mock_object_map
= new MockObjectMap();
1275 expect_op_work_queue(mock_image_ctx
);
1276 expect_test_features(mock_image_ctx
);
1277 expect_is_exclusive_lock_owner(mock_exclusive_lock
, true);
1279 // object map should be immediately opened if exclusive lock owned
1281 expect_get_mutable_metadata(mock_image_ctx
, ictx
->features
, 0);
1282 expect_get_parent(mock_image_ctx
, 0);
1283 expect_get_metadata(mock_image_ctx
, 0);
1284 expect_apply_metadata(mock_image_ctx
, 0);
1285 expect_get_group(mock_image_ctx
, 0);
1286 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
1287 expect_open_object_map(mock_image_ctx
, mock_object_map
, -EBLACKLISTED
);
1290 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false,
1294 ASSERT_EQ(-EBLACKLISTED
, ctx
.wait());
1295 ASSERT_EQ(nullptr, mock_image_ctx
.object_map
);
1298 TEST_F(TestMockImageRefreshRequest
, OpenObjectMapTooLarge
) {
1299 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP
);
1301 librbd::ImageCtx
*ictx
;
1302 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1304 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
1305 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_JOURNALING
,
1309 ASSERT_EQ(0, ictx
->state
->refresh());
1311 MockRefreshImageCtx
mock_image_ctx(*ictx
);
1312 MockRefreshParentRequest mock_refresh_parent_request
;
1314 MockExclusiveLock mock_exclusive_lock
;
1315 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
1317 MockObjectMap
*mock_object_map
= new MockObjectMap();
1319 expect_op_work_queue(mock_image_ctx
);
1320 expect_test_features(mock_image_ctx
);
1321 expect_is_exclusive_lock_owner(mock_exclusive_lock
, true);
1323 // object map should be immediately opened if exclusive lock owned
1325 expect_get_mutable_metadata(mock_image_ctx
, ictx
->features
, 0);
1326 expect_get_parent(mock_image_ctx
, 0);
1327 expect_get_metadata(mock_image_ctx
, 0);
1328 expect_apply_metadata(mock_image_ctx
, 0);
1329 expect_get_group(mock_image_ctx
, 0);
1330 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
1331 expect_open_object_map(mock_image_ctx
, mock_object_map
, -EFBIG
);
1334 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false,
1338 ASSERT_EQ(0, ctx
.wait());
1339 ASSERT_EQ(nullptr, mock_image_ctx
.object_map
);
1342 TEST_F(TestMockImageRefreshRequest
, ApplyMetadataError
) {
1343 REQUIRE_FORMAT_V2();
1345 librbd::ImageCtx
*ictx
;
1346 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1348 MockRefreshImageCtx
mock_image_ctx(*ictx
);
1349 MockRefreshParentRequest mock_refresh_parent_request
;
1350 MockExclusiveLock mock_exclusive_lock
;
1351 expect_op_work_queue(mock_image_ctx
);
1352 expect_test_features(mock_image_ctx
);
1355 expect_get_mutable_metadata(mock_image_ctx
, ictx
->features
, 0);
1356 expect_get_parent(mock_image_ctx
, 0);
1357 expect_get_metadata(mock_image_ctx
, 0);
1358 expect_apply_metadata(mock_image_ctx
, -EINVAL
);
1359 expect_get_group(mock_image_ctx
, 0);
1360 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
1361 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
1362 expect_init_exclusive_lock(mock_image_ctx
, mock_exclusive_lock
, 0);
1366 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
1369 ASSERT_EQ(0, ctx
.wait());
1372 } // namespace image
1373 } // namespace librbd