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/GetMetadataRequest.h"
18 #include "librbd/image/RefreshRequest.h"
19 #include "librbd/image/RefreshParentRequest.h"
20 #include "librbd/io/ImageDispatchSpec.h"
21 #include "gmock/gmock.h"
22 #include "gtest/gtest.h"
23 #include <arpa/inet.h>
25 #include <boost/scope_exit.hpp>
31 struct MockRefreshImageCtx
: public MockImageCtx
{
32 MockRefreshImageCtx(ImageCtx
&image_ctx
) : MockImageCtx(image_ctx
) {
36 } // anonymous namespace
41 struct GetMetadataRequest
<MockRefreshImageCtx
> {
43 std::map
<std::string
, bufferlist
>* pairs
= nullptr;
44 Context
* on_finish
= nullptr;
46 static GetMetadataRequest
* s_instance
;
47 static GetMetadataRequest
* create(librados::IoCtx
&,
48 const std::string
& oid
,
50 const std::string
& filter_key_prefix
,
51 const std::string
& last_key
,
53 std::map
<std::string
, bufferlist
>* pairs
,
55 ceph_assert(s_instance
!= nullptr);
56 EXPECT_EQ("conf_", filter_key_prefix
);
57 EXPECT_EQ("conf_", last_key
);
58 s_instance
->oid
= oid
;
59 s_instance
->pairs
= pairs
;
60 s_instance
->on_finish
= on_finish
;
64 GetMetadataRequest() {
68 MOCK_METHOD0(send
, void());
72 struct RefreshParentRequest
<MockRefreshImageCtx
> {
73 static RefreshParentRequest
* s_instance
;
74 static RefreshParentRequest
* create(MockRefreshImageCtx
&mock_image_ctx
,
75 const ParentImageInfo
&parent_md
,
76 const MigrationInfo
&migration_info
,
78 ceph_assert(s_instance
!= nullptr);
79 s_instance
->on_finish
= on_finish
;
82 static bool is_refresh_required(MockRefreshImageCtx
&mock_image_ctx
,
83 const ParentImageInfo
& parent_md
,
84 const MigrationInfo
&migration_info
) {
85 ceph_assert(s_instance
!= nullptr);
86 return s_instance
->is_refresh_required();
89 Context
*on_finish
= nullptr;
91 RefreshParentRequest() {
95 MOCK_CONST_METHOD0(is_refresh_required
, bool());
96 MOCK_METHOD0(send
, void());
97 MOCK_METHOD0(apply
, void());
98 MOCK_METHOD1(finalize
, void(Context
*));
101 GetMetadataRequest
<MockRefreshImageCtx
>* GetMetadataRequest
<MockRefreshImageCtx
>::s_instance
= nullptr;
102 RefreshParentRequest
<MockRefreshImageCtx
>* RefreshParentRequest
<MockRefreshImageCtx
>::s_instance
= nullptr;
109 struct ImageDispatchSpec
<librbd::MockRefreshImageCtx
> {
110 static ImageDispatchSpec
* s_instance
;
111 AioCompletion
*aio_comp
= nullptr;
113 static ImageDispatchSpec
* create_flush_request(
114 librbd::MockRefreshImageCtx
&image_ctx
, AioCompletion
*aio_comp
,
115 FlushSource flush_source
, const ZTracer::Trace
&parent_trace
) {
116 ceph_assert(s_instance
!= nullptr);
117 s_instance
->aio_comp
= aio_comp
;
121 MOCK_CONST_METHOD0(send
, void());
123 ImageDispatchSpec() {
128 ImageDispatchSpec
<librbd::MockRefreshImageCtx
>* ImageDispatchSpec
<librbd::MockRefreshImageCtx
>::s_instance
= nullptr;
133 inline ImageCtx
*get_image_ctx(librbd::MockRefreshImageCtx
*image_ctx
) {
134 return image_ctx
->image_ctx
;
138 } // namespace librbd
140 // template definitions
141 #include "librbd/image/RefreshRequest.cc"
143 ACTION_P(TestFeatures
, image_ctx
) {
144 return ((image_ctx
->features
& arg0
) != 0);
147 ACTION_P(ShutDownExclusiveLock
, image_ctx
) {
148 // shutting down exclusive lock will close object map and journal
149 image_ctx
->exclusive_lock
= nullptr;
150 image_ctx
->object_map
= nullptr;
151 image_ctx
->journal
= nullptr;
158 using ::testing::DoAll
;
159 using ::testing::DoDefault
;
160 using ::testing::InSequence
;
161 using ::testing::Invoke
;
162 using ::testing::Return
;
163 using ::testing::WithArg
;
164 using ::testing::StrEq
;
166 class TestMockImageRefreshRequest
: public TestMockFixture
{
168 typedef GetMetadataRequest
<MockRefreshImageCtx
> MockGetMetadataRequest
;
169 typedef RefreshRequest
<MockRefreshImageCtx
> MockRefreshRequest
;
170 typedef RefreshParentRequest
<MockRefreshImageCtx
> MockRefreshParentRequest
;
171 typedef io::ImageDispatchSpec
<librbd::MockRefreshImageCtx
> MockIoImageDispatchSpec
;
172 typedef std::map
<std::string
, bufferlist
> Metadata
;
174 void set_v1_migration_header(ImageCtx
*ictx
) {
176 ASSERT_EQ(0, read_header_bl(ictx
->md_ctx
, ictx
->header_oid
, hdr
, nullptr));
177 ASSERT_TRUE(hdr
.length() >= sizeof(rbd_obj_header_ondisk
));
178 ASSERT_EQ(0, memcmp(RBD_HEADER_TEXT
, hdr
.c_str(), sizeof(RBD_HEADER_TEXT
)));
180 bufferlist::iterator it
= hdr
.begin();
181 it
.copy_in(sizeof(RBD_MIGRATE_HEADER_TEXT
), RBD_MIGRATE_HEADER_TEXT
);
182 ASSERT_EQ(0, ictx
->md_ctx
.write(ictx
->header_oid
, hdr
, hdr
.length(), 0));
185 void expect_set_require_lock(MockRefreshImageCtx
&mock_image_ctx
,
186 librbd::io::Direction direction
, bool enabled
) {
187 EXPECT_CALL(*mock_image_ctx
.io_work_queue
, set_require_lock(direction
,
191 void expect_v1_read_header(MockRefreshImageCtx
&mock_image_ctx
, int r
) {
192 auto &expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
193 read(mock_image_ctx
.header_oid
, _
, _
, _
));
195 expect
.WillOnce(Return(r
));
197 expect
.WillOnce(DoDefault());
201 void expect_v1_get_snapshots(MockRefreshImageCtx
&mock_image_ctx
, int r
) {
202 auto &expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
203 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("snap_list"), _
, _
, _
));
205 expect
.WillOnce(Return(r
));
207 expect
.WillOnce(DoDefault());
211 void expect_v1_get_locks(MockRefreshImageCtx
&mock_image_ctx
, int r
) {
212 auto &expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
213 exec(mock_image_ctx
.header_oid
, _
, StrEq("lock"), StrEq("get_info"), _
, _
, _
));
215 expect
.WillOnce(Return(r
));
217 expect
.WillOnce(DoDefault());
221 void expect_get_mutable_metadata(MockRefreshImageCtx
&mock_image_ctx
,
222 uint64_t features
, int r
) {
223 auto &expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
224 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_size"), _
, _
, _
));
226 expect
.WillOnce(Return(r
));
228 uint64_t incompatible
= (
229 mock_image_ctx
.read_only
? features
& RBD_FEATURES_INCOMPATIBLE
:
230 features
& RBD_FEATURES_RW_INCOMPATIBLE
);
232 expect
.WillOnce(DoDefault());
233 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
234 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_features"), _
, _
, _
))
235 .WillOnce(WithArg
<5>(Invoke([features
, incompatible
](bufferlist
* out_bl
) {
236 encode(features
, *out_bl
);
237 encode(incompatible
, *out_bl
);
240 expect_get_flags(mock_image_ctx
, 0);
241 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
242 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_snapcontext"), _
, _
, _
))
243 .WillOnce(DoDefault());
244 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
245 exec(mock_image_ctx
.header_oid
, _
, StrEq("lock"), StrEq("get_info"), _
, _
, _
))
246 .WillOnce(DoDefault());
250 void expect_parent_overlap_get(MockRefreshImageCtx
&mock_image_ctx
, int r
) {
251 auto& expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
252 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"),
253 StrEq("parent_overlap_get"), _
, _
, _
));
255 expect
.WillOnce(Return(r
));
257 expect
.WillOnce(DoDefault());
261 void expect_get_parent(MockRefreshImageCtx
&mock_image_ctx
, int r
) {
262 auto& expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
263 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"),
264 StrEq("parent_get"), _
, _
, _
));
266 expect
.WillOnce(Return(r
));
268 expect
.WillOnce(DoDefault());
269 expect_parent_overlap_get(mock_image_ctx
, 0);
273 void expect_get_parent_legacy(MockRefreshImageCtx
&mock_image_ctx
, int r
) {
274 auto& expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
275 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"),
276 StrEq("get_parent"), _
, _
, _
));
278 expect
.WillOnce(Return(r
));
280 expect
.WillOnce(DoDefault());
284 void expect_get_migration_header(MockRefreshImageCtx
&mock_image_ctx
, int r
) {
285 auto &expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
286 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"),
287 StrEq("migration_get"), _
, _
, _
));
289 expect
.WillOnce(Return(r
));
291 expect
.WillOnce(DoDefault());
295 void expect_get_metadata(MockRefreshImageCtx
& mock_image_ctx
,
296 MockGetMetadataRequest
& mock_request
,
297 const std::string
& oid
,
298 const Metadata
& metadata
, int r
) {
299 EXPECT_CALL(mock_request
, send())
300 .WillOnce(Invoke([&mock_image_ctx
, &mock_request
, oid
, metadata
, r
]() {
301 ASSERT_EQ(oid
, mock_request
.oid
);
302 *mock_request
.pairs
= metadata
;
303 mock_image_ctx
.image_ctx
->op_work_queue
->queue(
304 mock_request
.on_finish
, r
);
308 void expect_get_flags(MockRefreshImageCtx
&mock_image_ctx
, int r
) {
309 auto &expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
310 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_flags"), _
, _
, _
));
312 expect
.WillOnce(Return(r
));
314 expect
.WillOnce(DoDefault());
318 void expect_get_op_features(MockRefreshImageCtx
&mock_image_ctx
,
319 uint64_t op_features
, int r
) {
320 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
321 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"),
322 StrEq("op_features_get"), _
, _
, _
))
323 .WillOnce(WithArg
<5>(Invoke([op_features
, r
](bufferlist
* out_bl
) {
324 encode(op_features
, *out_bl
);
329 void expect_get_group(MockRefreshImageCtx
&mock_image_ctx
, int r
) {
330 auto &expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
331 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"),
332 StrEq("image_group_get"), _
, _
, _
));
334 expect
.WillOnce(Return(r
));
336 expect
.WillOnce(DoDefault());
340 void expect_get_snapshots(MockRefreshImageCtx
&mock_image_ctx
,
341 bool legacy_parent
, int r
) {
342 auto &expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
343 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("snapshot_get"), _
, _
, _
));
345 expect
.WillOnce(Return(r
));
347 expect
.WillOnce(DoDefault());
349 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
350 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_parent"), _
, _
, _
))
351 .WillOnce(DoDefault());
353 expect_parent_overlap_get(mock_image_ctx
, 0);
355 expect_get_flags(mock_image_ctx
, 0);
356 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
357 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_protection_status"), _
, _
, _
))
358 .WillOnce(DoDefault());
362 void expect_get_snapshots_legacy(MockRefreshImageCtx
&mock_image_ctx
, int r
) {
363 auto &expect
= EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
364 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_snapshot_name"), _
, _
, _
));
366 expect
.WillOnce(Return(r
));
368 expect
.WillOnce(DoDefault());
369 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
370 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_size"), _
, _
, _
))
371 .WillOnce(DoDefault());
372 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
373 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_snapshot_timestamp"), _
, _
, _
))
374 .WillOnce(DoDefault());
375 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
376 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_parent"), _
, _
, _
))
377 .WillOnce(DoDefault());
378 expect_get_flags(mock_image_ctx
, 0);
379 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
380 exec(mock_image_ctx
.header_oid
, _
, StrEq("rbd"), StrEq("get_protection_status"), _
, _
, _
))
381 .WillOnce(DoDefault());
385 void expect_apply_metadata(MockRefreshImageCtx
&mock_image_ctx
,
387 EXPECT_CALL(*mock_image_ctx
.image_watcher
, is_unregistered())
388 .WillOnce(Return(false));
389 EXPECT_CALL(mock_image_ctx
, apply_metadata(_
, false))
390 .WillOnce(Return(r
));
393 void expect_add_snap(MockRefreshImageCtx
&mock_image_ctx
,
394 const std::string
&snap_name
, uint64_t snap_id
) {
395 EXPECT_CALL(mock_image_ctx
, add_snap(_
, snap_name
, snap_id
, _
, _
, _
, _
, _
));
398 void expect_init_exclusive_lock(MockRefreshImageCtx
&mock_image_ctx
,
399 MockExclusiveLock
&mock_exclusive_lock
,
401 EXPECT_CALL(mock_image_ctx
, create_exclusive_lock())
402 .WillOnce(Return(&mock_exclusive_lock
));
403 EXPECT_CALL(mock_exclusive_lock
, init(mock_image_ctx
.features
, _
))
404 .WillOnce(WithArg
<1>(CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
)));
407 void expect_shut_down_exclusive_lock(MockRefreshImageCtx
&mock_image_ctx
,
408 MockExclusiveLock
&mock_exclusive_lock
,
410 EXPECT_CALL(mock_exclusive_lock
, shut_down(_
))
411 .WillOnce(DoAll(ShutDownExclusiveLock(&mock_image_ctx
),
412 CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
)));
415 void expect_init_layout(MockRefreshImageCtx
&mock_image_ctx
) {
416 EXPECT_CALL(mock_image_ctx
, init_layout(_
));
419 void expect_test_features(MockRefreshImageCtx
&mock_image_ctx
) {
420 EXPECT_CALL(mock_image_ctx
, test_features(_
, _
))
421 .WillRepeatedly(TestFeatures(&mock_image_ctx
));
424 void expect_refresh_parent_is_required(MockRefreshParentRequest
&mock_refresh_parent_request
,
426 EXPECT_CALL(mock_refresh_parent_request
, is_refresh_required())
427 .WillRepeatedly(Return(required
));
430 void expect_refresh_parent_send(MockRefreshImageCtx
&mock_image_ctx
,
431 MockRefreshParentRequest
&mock_refresh_parent_request
,
433 EXPECT_CALL(mock_refresh_parent_request
, send())
434 .WillOnce(FinishRequest(&mock_refresh_parent_request
, r
,
438 void expect_refresh_parent_apply(MockRefreshParentRequest
&mock_refresh_parent_request
) {
439 EXPECT_CALL(mock_refresh_parent_request
, apply());
442 void expect_refresh_parent_finalize(MockRefreshImageCtx
&mock_image_ctx
,
443 MockRefreshParentRequest
&mock_refresh_parent_request
,
445 EXPECT_CALL(mock_refresh_parent_request
, finalize(_
))
446 .WillOnce(CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
));
449 void expect_is_exclusive_lock_owner(MockExclusiveLock
&mock_exclusive_lock
,
451 EXPECT_CALL(mock_exclusive_lock
, is_lock_owner()).WillOnce(Return(is_owner
));
454 void expect_get_journal_policy(MockImageCtx
&mock_image_ctx
,
455 MockJournalPolicy
&mock_journal_policy
) {
456 EXPECT_CALL(mock_image_ctx
, get_journal_policy())
457 .WillOnce(Return(&mock_journal_policy
));
460 void expect_journal_disabled(MockJournalPolicy
&mock_journal_policy
,
462 EXPECT_CALL(mock_journal_policy
, journal_disabled())
463 .WillOnce(Return(disabled
));
466 void expect_open_journal(MockRefreshImageCtx
&mock_image_ctx
,
467 MockJournal
&mock_journal
, int r
) {
468 EXPECT_CALL(mock_image_ctx
, create_journal())
469 .WillOnce(Return(&mock_journal
));
470 EXPECT_CALL(mock_journal
, open(_
))
471 .WillOnce(CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
));
474 void expect_close_journal(MockRefreshImageCtx
&mock_image_ctx
,
475 MockJournal
&mock_journal
, int r
) {
476 EXPECT_CALL(mock_journal
, close(_
))
477 .WillOnce(CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
));
480 void expect_open_object_map(MockRefreshImageCtx
&mock_image_ctx
,
481 MockObjectMap
*mock_object_map
, int r
) {
482 EXPECT_CALL(mock_image_ctx
, create_object_map(_
))
483 .WillOnce(Return(mock_object_map
));
484 EXPECT_CALL(*mock_object_map
, open(_
))
485 .WillOnce(CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
));
488 void expect_close_object_map(MockRefreshImageCtx
&mock_image_ctx
,
489 MockObjectMap
&mock_object_map
, int r
) {
490 EXPECT_CALL(mock_object_map
, close(_
))
491 .WillOnce(CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
));
494 void expect_get_snap_id(MockRefreshImageCtx
&mock_image_ctx
,
495 const std::string
&snap_name
,
497 EXPECT_CALL(mock_image_ctx
,
498 get_snap_id(_
, snap_name
)).WillOnce(Return(snap_id
));
501 void expect_block_writes(MockImageCtx
&mock_image_ctx
, int r
) {
502 EXPECT_CALL(*mock_image_ctx
.io_work_queue
, block_writes(_
))
503 .WillOnce(CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
));
506 void expect_unblock_writes(MockImageCtx
&mock_image_ctx
) {
507 EXPECT_CALL(*mock_image_ctx
.io_work_queue
, unblock_writes())
511 void expect_image_flush(MockIoImageDispatchSpec
&mock_image_request
, int r
) {
512 EXPECT_CALL(mock_image_request
, send())
513 .WillOnce(Invoke([&mock_image_request
, r
]() {
514 mock_image_request
.aio_comp
->set_request_count(1);
515 mock_image_request
.aio_comp
->add_request();
516 mock_image_request
.aio_comp
->complete_request(r
);
522 TEST_F(TestMockImageRefreshRequest
, SuccessV1
) {
525 librbd::ImageCtx
*ictx
;
526 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
528 MockRefreshImageCtx
mock_image_ctx(*ictx
);
529 expect_op_work_queue(mock_image_ctx
);
530 expect_test_features(mock_image_ctx
);
533 expect_v1_read_header(mock_image_ctx
, 0);
534 expect_v1_get_snapshots(mock_image_ctx
, 0);
535 expect_v1_get_locks(mock_image_ctx
, 0);
536 expect_init_layout(mock_image_ctx
);
539 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
542 ASSERT_EQ(0, ctx
.wait());
545 TEST_F(TestMockImageRefreshRequest
, SuccessSnapshotV1
) {
547 librbd::ImageCtx
*ictx
;
548 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
549 ASSERT_EQ(0, snap_create(*ictx
, "snap"));
550 ASSERT_EQ(0, ictx
->state
->refresh());
552 MockRefreshImageCtx
mock_image_ctx(*ictx
);
553 expect_op_work_queue(mock_image_ctx
);
554 expect_test_features(mock_image_ctx
);
557 expect_v1_read_header(mock_image_ctx
, 0);
558 expect_v1_get_snapshots(mock_image_ctx
, 0);
559 expect_v1_get_locks(mock_image_ctx
, 0);
560 expect_init_layout(mock_image_ctx
);
561 expect_add_snap(mock_image_ctx
, "snap", ictx
->snap_ids
.begin()->second
);
564 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
567 ASSERT_EQ(0, ctx
.wait());
570 TEST_F(TestMockImageRefreshRequest
, SuccessV2
) {
573 librbd::ImageCtx
*ictx
;
574 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
576 MockRefreshImageCtx
mock_image_ctx(*ictx
);
577 MockRefreshParentRequest mock_refresh_parent_request
;
578 MockExclusiveLock mock_exclusive_lock
;
579 expect_op_work_queue(mock_image_ctx
);
580 expect_test_features(mock_image_ctx
);
583 expect_get_mutable_metadata(mock_image_ctx
, ictx
->features
, 0);
584 expect_get_parent(mock_image_ctx
, 0);
585 MockGetMetadataRequest mock_get_metadata_request
;
586 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
,
587 mock_image_ctx
.header_oid
, {}, 0);
588 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
, RBD_INFO
, {},
590 expect_apply_metadata(mock_image_ctx
, 0);
591 expect_get_group(mock_image_ctx
, 0);
592 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
593 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
594 expect_init_exclusive_lock(mock_image_ctx
, mock_exclusive_lock
, 0);
598 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
601 ASSERT_EQ(0, ctx
.wait());
604 TEST_F(TestMockImageRefreshRequest
, SuccessSnapshotV2
) {
607 librbd::ImageCtx
*ictx
;
608 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
609 ASSERT_EQ(0, snap_create(*ictx
, "snap"));
611 MockRefreshImageCtx
mock_image_ctx(*ictx
);
612 MockRefreshParentRequest mock_refresh_parent_request
;
613 MockExclusiveLock mock_exclusive_lock
;
614 expect_op_work_queue(mock_image_ctx
);
615 expect_test_features(mock_image_ctx
);
618 expect_get_mutable_metadata(mock_image_ctx
, ictx
->features
, 0);
619 expect_get_parent(mock_image_ctx
, 0);
620 MockGetMetadataRequest mock_get_metadata_request
;
621 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
,
622 mock_image_ctx
.header_oid
, {}, 0);
623 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
, RBD_INFO
, {},
625 expect_apply_metadata(mock_image_ctx
, 0);
626 expect_get_group(mock_image_ctx
, 0);
627 expect_get_snapshots(mock_image_ctx
, false, 0);
628 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
629 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
630 expect_init_exclusive_lock(mock_image_ctx
, mock_exclusive_lock
, 0);
632 expect_add_snap(mock_image_ctx
, "snap", ictx
->snap_ids
.begin()->second
);
635 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
638 ASSERT_EQ(0, ctx
.wait());
641 TEST_F(TestMockImageRefreshRequest
, SuccessLegacySnapshotV2
) {
644 librbd::ImageCtx
*ictx
;
645 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
646 ASSERT_EQ(0, snap_create(*ictx
, "snap"));
648 MockRefreshImageCtx
mock_image_ctx(*ictx
);
649 MockRefreshParentRequest mock_refresh_parent_request
;
650 MockExclusiveLock mock_exclusive_lock
;
651 expect_op_work_queue(mock_image_ctx
);
652 expect_test_features(mock_image_ctx
);
655 expect_get_mutable_metadata(mock_image_ctx
, ictx
->features
, 0);
656 expect_get_parent(mock_image_ctx
, -EOPNOTSUPP
);
657 expect_get_parent_legacy(mock_image_ctx
, 0);
658 MockGetMetadataRequest mock_get_metadata_request
;
659 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
,
660 mock_image_ctx
.header_oid
, {}, 0);
661 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
, RBD_INFO
, {},
663 expect_apply_metadata(mock_image_ctx
, 0);
664 expect_get_group(mock_image_ctx
, 0);
665 expect_get_snapshots(mock_image_ctx
, true, -EOPNOTSUPP
);
666 expect_get_snapshots_legacy(mock_image_ctx
, 0);
667 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
668 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
669 expect_init_exclusive_lock(mock_image_ctx
, mock_exclusive_lock
, 0);
671 expect_add_snap(mock_image_ctx
, "snap", ictx
->snap_ids
.begin()->second
);
674 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
677 ASSERT_EQ(0, ctx
.wait());
680 TEST_F(TestMockImageRefreshRequest
, SuccessSetSnapshotV2
) {
683 librbd::ImageCtx
*ictx
;
684 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
685 ASSERT_EQ(0, snap_create(*ictx
, "snap"));
686 ASSERT_EQ(0, librbd::api::Image
<>::snap_set(ictx
,
687 cls::rbd::UserSnapshotNamespace(),
690 MockRefreshImageCtx
mock_image_ctx(*ictx
);
691 MockRefreshParentRequest mock_refresh_parent_request
;
692 MockObjectMap mock_object_map
;
693 expect_op_work_queue(mock_image_ctx
);
694 expect_test_features(mock_image_ctx
);
697 expect_get_mutable_metadata(mock_image_ctx
, ictx
->features
, 0);
698 expect_get_parent(mock_image_ctx
, 0);
699 MockGetMetadataRequest mock_get_metadata_request
;
700 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
,
701 mock_image_ctx
.header_oid
, {}, 0);
702 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
, RBD_INFO
, {},
704 expect_apply_metadata(mock_image_ctx
, 0);
705 expect_get_group(mock_image_ctx
, 0);
706 expect_get_snapshots(mock_image_ctx
, false, 0);
707 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
708 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
709 expect_open_object_map(mock_image_ctx
, &mock_object_map
, 0);
711 expect_add_snap(mock_image_ctx
, "snap", ictx
->snap_ids
.begin()->second
);
712 expect_get_snap_id(mock_image_ctx
, "snap", ictx
->snap_ids
.begin()->second
);
715 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
718 ASSERT_EQ(0, ctx
.wait());
721 TEST_F(TestMockImageRefreshRequest
, SuccessChild
) {
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 MockRefreshParentRequest
*mock_refresh_parent_request
= new MockRefreshParentRequest();
749 MockExclusiveLock mock_exclusive_lock
;
750 expect_op_work_queue(mock_image_ctx
);
751 expect_test_features(mock_image_ctx
);
754 expect_get_mutable_metadata(mock_image_ctx
, ictx2
->features
, 0);
755 expect_get_parent(mock_image_ctx
, 0);
756 MockGetMetadataRequest mock_get_metadata_request
;
757 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
,
758 mock_image_ctx
.header_oid
, {}, 0);
759 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
, RBD_INFO
, {},
761 expect_apply_metadata(mock_image_ctx
, 0);
762 expect_get_op_features(mock_image_ctx
, RBD_OPERATION_FEATURE_CLONE_CHILD
, 0);
763 expect_get_group(mock_image_ctx
, 0);
764 expect_refresh_parent_is_required(*mock_refresh_parent_request
, true);
765 expect_refresh_parent_send(mock_image_ctx
, *mock_refresh_parent_request
, 0);
766 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
767 expect_init_exclusive_lock(mock_image_ctx
, mock_exclusive_lock
, 0);
769 expect_refresh_parent_apply(*mock_refresh_parent_request
);
770 expect_refresh_parent_finalize(mock_image_ctx
, *mock_refresh_parent_request
, 0);
773 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
776 ASSERT_EQ(0, ctx
.wait());
779 TEST_F(TestMockImageRefreshRequest
, SuccessChildDontOpenParent
) {
780 REQUIRE_FEATURE(RBD_FEATURE_LAYERING
);
782 librbd::ImageCtx
*ictx
;
783 librbd::ImageCtx
*ictx2
= nullptr;
784 std::string clone_name
= get_temp_image_name();
786 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
787 ASSERT_EQ(0, snap_create(*ictx
, "snap"));
788 ASSERT_EQ(0, snap_protect(*ictx
, "snap"));
789 BOOST_SCOPE_EXIT_ALL((&)) {
790 if (ictx2
!= nullptr) {
794 librbd::NoOpProgressContext no_op
;
795 ASSERT_EQ(0, librbd::api::Image
<>::remove(m_ioctx
, clone_name
, no_op
));
796 ASSERT_EQ(0, ictx
->operations
->snap_unprotect(cls::rbd::UserSnapshotNamespace(), "snap"));
799 int order
= ictx
->order
;
800 ASSERT_EQ(0, librbd::clone(m_ioctx
, m_image_name
.c_str(), "snap", m_ioctx
,
801 clone_name
.c_str(), ictx
->features
, &order
, 0, 0));
803 ASSERT_EQ(0, open_image(clone_name
, &ictx2
));
805 MockRefreshImageCtx
mock_image_ctx(*ictx2
);
806 MockExclusiveLock mock_exclusive_lock
;
807 expect_op_work_queue(mock_image_ctx
);
808 expect_test_features(mock_image_ctx
);
811 expect_get_mutable_metadata(mock_image_ctx
, ictx2
->features
, 0);
812 expect_get_parent(mock_image_ctx
, 0);
813 MockGetMetadataRequest mock_get_metadata_request
;
814 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
,
815 mock_image_ctx
.header_oid
, {}, 0);
816 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
, RBD_INFO
, {},
818 expect_apply_metadata(mock_image_ctx
, 0);
819 expect_get_op_features(mock_image_ctx
, RBD_OPERATION_FEATURE_CLONE_CHILD
, 0);
820 expect_get_group(mock_image_ctx
, 0);
821 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
822 expect_init_exclusive_lock(mock_image_ctx
, mock_exclusive_lock
, 0);
826 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, true, &ctx
);
829 ASSERT_EQ(0, ctx
.wait());
832 TEST_F(TestMockImageRefreshRequest
, SuccessOpFeatures
) {
835 librbd::ImageCtx
*ictx
;
836 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
838 MockRefreshImageCtx
mock_image_ctx(*ictx
);
839 MockRefreshParentRequest mock_refresh_parent_request
;
840 MockExclusiveLock mock_exclusive_lock
;
841 expect_op_work_queue(mock_image_ctx
);
842 expect_test_features(mock_image_ctx
);
844 mock_image_ctx
.features
|= RBD_FEATURE_OPERATIONS
;
847 expect_get_mutable_metadata(mock_image_ctx
, mock_image_ctx
.features
, 0);
848 expect_get_parent(mock_image_ctx
, 0);
849 MockGetMetadataRequest mock_get_metadata_request
;
850 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
,
851 mock_image_ctx
.header_oid
, {}, 0);
852 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
, RBD_INFO
, {},
854 expect_apply_metadata(mock_image_ctx
, 0);
855 expect_get_op_features(mock_image_ctx
, 4096, 0);
856 expect_get_group(mock_image_ctx
, 0);
857 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
858 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
859 expect_init_exclusive_lock(mock_image_ctx
, mock_exclusive_lock
, 0);
863 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
866 ASSERT_EQ(0, ctx
.wait());
867 ASSERT_EQ(4096U, mock_image_ctx
.op_features
);
868 ASSERT_TRUE(mock_image_ctx
.operations_disabled
);
871 TEST_F(TestMockImageRefreshRequest
, DisableExclusiveLock
) {
872 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
874 librbd::ImageCtx
*ictx
;
875 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
877 MockRefreshImageCtx
mock_image_ctx(*ictx
);
878 MockRefreshParentRequest mock_refresh_parent_request
;
880 MockExclusiveLock mock_exclusive_lock
;
881 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
883 MockObjectMap mock_object_map
;
884 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
885 mock_image_ctx
.object_map
= &mock_object_map
;
888 MockJournal mock_journal
;
889 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
890 mock_image_ctx
.journal
= &mock_journal
;
893 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
894 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_JOURNALING
,
898 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
899 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_OBJECT_MAP
,
903 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
904 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_EXCLUSIVE_LOCK
,
908 ASSERT_EQ(0, ictx
->state
->refresh());
910 expect_op_work_queue(mock_image_ctx
);
911 expect_test_features(mock_image_ctx
);
913 // verify that exclusive lock is properly handled when object map
914 // and journaling were never enabled (or active)
916 expect_get_mutable_metadata(mock_image_ctx
, ictx
->features
, 0);
917 expect_get_parent(mock_image_ctx
, 0);
918 MockGetMetadataRequest mock_get_metadata_request
;
919 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
,
920 mock_image_ctx
.header_oid
, {}, 0);
921 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
, RBD_INFO
, {},
923 expect_apply_metadata(mock_image_ctx
, 0);
924 expect_get_group(mock_image_ctx
, 0);
925 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
926 expect_shut_down_exclusive_lock(mock_image_ctx
, mock_exclusive_lock
, 0);
929 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
932 ASSERT_EQ(0, ctx
.wait());
935 TEST_F(TestMockImageRefreshRequest
, DisableExclusiveLockWhileAcquiringLock
) {
936 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK
);
938 librbd::ImageCtx
*ictx
;
939 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
941 MockRefreshImageCtx
mock_image_ctx(*ictx
);
942 MockRefreshParentRequest mock_refresh_parent_request
;
944 MockExclusiveLock mock_exclusive_lock
;
945 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
947 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
948 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_JOURNALING
,
952 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
953 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_OBJECT_MAP
,
957 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
958 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_EXCLUSIVE_LOCK
,
962 ASSERT_EQ(0, ictx
->state
->refresh());
964 expect_op_work_queue(mock_image_ctx
);
965 expect_test_features(mock_image_ctx
);
967 // verify that exclusive lock is properly handled when object map
968 // and journaling were never enabled (or active)
970 expect_get_mutable_metadata(mock_image_ctx
, ictx
->features
, 0);
971 expect_get_parent(mock_image_ctx
, 0);
972 MockGetMetadataRequest mock_get_metadata_request
;
973 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
,
974 mock_image_ctx
.header_oid
, {}, 0);
975 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
, RBD_INFO
, {},
977 expect_apply_metadata(mock_image_ctx
, 0);
978 expect_get_group(mock_image_ctx
, 0);
979 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
982 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, true, false, &ctx
);
985 ASSERT_EQ(-ERESTART
, ctx
.wait());
988 TEST_F(TestMockImageRefreshRequest
, JournalDisabledByPolicy
) {
989 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
991 librbd::ImageCtx
*ictx
;
992 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
994 if (ictx
->test_features(RBD_FEATURE_FAST_DIFF
)) {
995 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_FAST_DIFF
,
999 ASSERT_EQ(0, ictx
->state
->refresh());
1001 MockRefreshImageCtx
mock_image_ctx(*ictx
);
1002 MockRefreshParentRequest mock_refresh_parent_request
;
1004 MockExclusiveLock mock_exclusive_lock
;
1005 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
1007 MockJournal mock_journal
;
1009 expect_op_work_queue(mock_image_ctx
);
1010 expect_test_features(mock_image_ctx
);
1011 expect_is_exclusive_lock_owner(mock_exclusive_lock
, true);
1014 expect_get_mutable_metadata(mock_image_ctx
, ictx
->features
, 0);
1015 expect_get_parent(mock_image_ctx
, 0);
1016 MockGetMetadataRequest mock_get_metadata_request
;
1017 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
,
1018 mock_image_ctx
.header_oid
, {}, 0);
1019 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
, RBD_INFO
, {},
1021 expect_apply_metadata(mock_image_ctx
, 0);
1022 expect_get_group(mock_image_ctx
, 0);
1023 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
1025 MockJournalPolicy mock_journal_policy
;
1026 expect_get_journal_policy(mock_image_ctx
, mock_journal_policy
);
1027 expect_journal_disabled(mock_journal_policy
, true);
1030 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
1033 ASSERT_EQ(0, ctx
.wait());
1036 TEST_F(TestMockImageRefreshRequest
, EnableJournalWithExclusiveLock
) {
1037 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
1039 librbd::ImageCtx
*ictx
;
1040 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1042 if (ictx
->test_features(RBD_FEATURE_FAST_DIFF
)) {
1043 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_FAST_DIFF
,
1047 ASSERT_EQ(0, ictx
->state
->refresh());
1049 MockRefreshImageCtx
mock_image_ctx(*ictx
);
1050 MockRefreshParentRequest mock_refresh_parent_request
;
1052 MockExclusiveLock mock_exclusive_lock
;
1053 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
1055 MockJournal mock_journal
;
1057 expect_op_work_queue(mock_image_ctx
);
1058 expect_test_features(mock_image_ctx
);
1059 expect_is_exclusive_lock_owner(mock_exclusive_lock
, true);
1061 // journal should be immediately opened if exclusive lock owned
1063 expect_get_mutable_metadata(mock_image_ctx
, ictx
->features
, 0);
1064 expect_get_parent(mock_image_ctx
, 0);
1065 MockGetMetadataRequest mock_get_metadata_request
;
1066 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
,
1067 mock_image_ctx
.header_oid
, {}, 0);
1068 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
, RBD_INFO
, {},
1070 expect_apply_metadata(mock_image_ctx
, 0);
1071 expect_get_group(mock_image_ctx
, 0);
1072 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
1074 MockJournalPolicy mock_journal_policy
;
1075 expect_get_journal_policy(mock_image_ctx
, mock_journal_policy
);
1076 expect_journal_disabled(mock_journal_policy
, false);
1077 expect_open_journal(mock_image_ctx
, mock_journal
, 0);
1080 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
1083 ASSERT_EQ(0, ctx
.wait());
1086 TEST_F(TestMockImageRefreshRequest
, EnableJournalWithoutExclusiveLock
) {
1087 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
1089 librbd::ImageCtx
*ictx
;
1090 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1092 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
1093 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_OBJECT_MAP
,
1097 ASSERT_EQ(0, ictx
->state
->refresh());
1099 MockRefreshImageCtx
mock_image_ctx(*ictx
);
1100 MockRefreshParentRequest mock_refresh_parent_request
;
1102 MockExclusiveLock mock_exclusive_lock
;
1103 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
1105 expect_op_work_queue(mock_image_ctx
);
1106 expect_test_features(mock_image_ctx
);
1107 expect_is_exclusive_lock_owner(mock_exclusive_lock
, false);
1109 // do not open the journal if exclusive lock is not owned
1111 expect_get_mutable_metadata(mock_image_ctx
, ictx
->features
, 0);
1112 expect_get_parent(mock_image_ctx
, 0);
1113 MockGetMetadataRequest mock_get_metadata_request
;
1114 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
,
1115 mock_image_ctx
.header_oid
, {}, 0);
1116 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
, RBD_INFO
, {},
1118 expect_apply_metadata(mock_image_ctx
, 0);
1119 expect_get_group(mock_image_ctx
, 0);
1120 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
1121 expect_set_require_lock(mock_image_ctx
, librbd::io::DIRECTION_BOTH
, true);
1124 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
1127 ASSERT_EQ(0, ctx
.wait());
1130 TEST_F(TestMockImageRefreshRequest
, DisableJournal
) {
1131 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
1133 librbd::ImageCtx
*ictx
;
1134 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1136 MockRefreshImageCtx
mock_image_ctx(*ictx
);
1137 MockRefreshParentRequest mock_refresh_parent_request
;
1139 MockExclusiveLock mock_exclusive_lock
;
1140 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
1142 MockObjectMap mock_object_map
;
1143 if (ictx
->test_features(RBD_FEATURE_OBJECT_MAP
)) {
1144 mock_image_ctx
.object_map
= &mock_object_map
;
1147 MockJournal mock_journal
;
1148 mock_image_ctx
.journal
= &mock_journal
;
1150 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
1151 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_JOURNALING
,
1155 ASSERT_EQ(0, ictx
->state
->refresh());
1157 expect_op_work_queue(mock_image_ctx
);
1158 expect_test_features(mock_image_ctx
);
1160 // verify journal is closed if feature disabled
1162 expect_get_mutable_metadata(mock_image_ctx
, ictx
->features
, 0);
1163 expect_get_parent(mock_image_ctx
, 0);
1164 MockGetMetadataRequest mock_get_metadata_request
;
1165 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
,
1166 mock_image_ctx
.header_oid
, {}, 0);
1167 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
, RBD_INFO
, {},
1169 expect_apply_metadata(mock_image_ctx
, 0);
1170 expect_get_group(mock_image_ctx
, 0);
1171 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
1172 expect_block_writes(mock_image_ctx
, 0);
1173 if (!mock_image_ctx
.clone_copy_on_read
) {
1174 expect_set_require_lock(mock_image_ctx
, librbd::io::DIRECTION_READ
, false);
1176 expect_close_journal(mock_image_ctx
, mock_journal
, 0);
1177 expect_unblock_writes(mock_image_ctx
);
1180 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
1183 ASSERT_EQ(0, ctx
.wait());
1186 TEST_F(TestMockImageRefreshRequest
, EnableObjectMapWithExclusiveLock
) {
1187 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP
);
1189 librbd::ImageCtx
*ictx
;
1190 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1192 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
1193 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_JOURNALING
,
1197 ASSERT_EQ(0, ictx
->state
->refresh());
1199 MockRefreshImageCtx
mock_image_ctx(*ictx
);
1200 MockRefreshParentRequest mock_refresh_parent_request
;
1202 MockExclusiveLock mock_exclusive_lock
;
1203 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
1205 MockObjectMap mock_object_map
;
1207 expect_op_work_queue(mock_image_ctx
);
1208 expect_test_features(mock_image_ctx
);
1209 expect_is_exclusive_lock_owner(mock_exclusive_lock
, true);
1211 // object map should be immediately opened if exclusive lock owned
1213 expect_get_mutable_metadata(mock_image_ctx
, ictx
->features
, 0);
1214 expect_get_parent(mock_image_ctx
, 0);
1215 MockGetMetadataRequest mock_get_metadata_request
;
1216 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
,
1217 mock_image_ctx
.header_oid
, {}, 0);
1218 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
, RBD_INFO
, {},
1220 expect_apply_metadata(mock_image_ctx
, 0);
1221 expect_get_group(mock_image_ctx
, 0);
1222 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
1223 expect_open_object_map(mock_image_ctx
, &mock_object_map
, 0);
1226 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
1229 ASSERT_EQ(0, ctx
.wait());
1232 TEST_F(TestMockImageRefreshRequest
, EnableObjectMapWithoutExclusiveLock
) {
1233 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP
);
1235 librbd::ImageCtx
*ictx
;
1236 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1238 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
1239 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_JOURNALING
,
1243 ASSERT_EQ(0, ictx
->state
->refresh());
1245 MockRefreshImageCtx
mock_image_ctx(*ictx
);
1246 MockRefreshParentRequest mock_refresh_parent_request
;
1248 MockExclusiveLock mock_exclusive_lock
;
1249 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
1251 expect_op_work_queue(mock_image_ctx
);
1252 expect_test_features(mock_image_ctx
);
1253 expect_is_exclusive_lock_owner(mock_exclusive_lock
, false);
1255 // do not open the object map if exclusive lock is not owned
1257 expect_get_mutable_metadata(mock_image_ctx
, ictx
->features
, 0);
1258 expect_get_parent(mock_image_ctx
, 0);
1259 MockGetMetadataRequest mock_get_metadata_request
;
1260 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
,
1261 mock_image_ctx
.header_oid
, {}, 0);
1262 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
, RBD_INFO
, {},
1264 expect_apply_metadata(mock_image_ctx
, 0);
1265 expect_get_group(mock_image_ctx
, 0);
1266 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
1269 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
1272 ASSERT_EQ(0, ctx
.wait());
1275 TEST_F(TestMockImageRefreshRequest
, DisableObjectMap
) {
1276 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP
);
1278 librbd::ImageCtx
*ictx
;
1279 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1281 MockRefreshImageCtx
mock_image_ctx(*ictx
);
1282 MockRefreshParentRequest mock_refresh_parent_request
;
1284 MockExclusiveLock mock_exclusive_lock
;
1285 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
1287 MockObjectMap mock_object_map
;
1288 mock_image_ctx
.object_map
= &mock_object_map
;
1290 MockJournal mock_journal
;
1291 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
1292 mock_image_ctx
.journal
= &mock_journal
;
1295 if (ictx
->test_features(RBD_FEATURE_FAST_DIFF
)) {
1296 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_FAST_DIFF
,
1300 ASSERT_EQ(0, ictx
->state
->refresh());
1302 expect_op_work_queue(mock_image_ctx
);
1303 expect_test_features(mock_image_ctx
);
1305 // verify object map is closed if feature disabled
1307 expect_get_mutable_metadata(mock_image_ctx
, ictx
->features
, 0);
1308 expect_get_parent(mock_image_ctx
, 0);
1309 MockGetMetadataRequest mock_get_metadata_request
;
1310 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
,
1311 mock_image_ctx
.header_oid
, {}, 0);
1312 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
, RBD_INFO
, {},
1314 expect_apply_metadata(mock_image_ctx
, 0);
1315 expect_get_group(mock_image_ctx
, 0);
1316 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
1317 expect_close_object_map(mock_image_ctx
, mock_object_map
, 0);
1320 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
1323 ASSERT_EQ(0, ctx
.wait());
1326 TEST_F(TestMockImageRefreshRequest
, OpenObjectMapError
) {
1327 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP
);
1329 librbd::ImageCtx
*ictx
;
1330 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1332 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
1333 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_JOURNALING
,
1337 ASSERT_EQ(0, ictx
->state
->refresh());
1339 MockRefreshImageCtx
mock_image_ctx(*ictx
);
1340 MockRefreshParentRequest mock_refresh_parent_request
;
1342 MockExclusiveLock mock_exclusive_lock
;
1343 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
1345 MockObjectMap mock_object_map
;
1347 expect_op_work_queue(mock_image_ctx
);
1348 expect_test_features(mock_image_ctx
);
1349 expect_is_exclusive_lock_owner(mock_exclusive_lock
, true);
1351 // object map should be immediately opened if exclusive lock owned
1353 expect_get_mutable_metadata(mock_image_ctx
, ictx
->features
, 0);
1354 expect_get_parent(mock_image_ctx
, 0);
1355 MockGetMetadataRequest mock_get_metadata_request
;
1356 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
,
1357 mock_image_ctx
.header_oid
, {}, 0);
1358 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
, RBD_INFO
, {},
1360 expect_apply_metadata(mock_image_ctx
, 0);
1361 expect_get_group(mock_image_ctx
, 0);
1362 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
1363 expect_open_object_map(mock_image_ctx
, &mock_object_map
, -EBLACKLISTED
);
1366 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false,
1370 ASSERT_EQ(-EBLACKLISTED
, ctx
.wait());
1371 ASSERT_EQ(nullptr, mock_image_ctx
.object_map
);
1374 TEST_F(TestMockImageRefreshRequest
, OpenObjectMapTooLarge
) {
1375 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP
);
1377 librbd::ImageCtx
*ictx
;
1378 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1380 if (ictx
->test_features(RBD_FEATURE_JOURNALING
)) {
1381 ASSERT_EQ(0, ictx
->operations
->update_features(RBD_FEATURE_JOURNALING
,
1385 ASSERT_EQ(0, ictx
->state
->refresh());
1387 MockRefreshImageCtx
mock_image_ctx(*ictx
);
1388 MockRefreshParentRequest mock_refresh_parent_request
;
1390 MockExclusiveLock mock_exclusive_lock
;
1391 mock_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
1393 MockObjectMap mock_object_map
;
1395 expect_op_work_queue(mock_image_ctx
);
1396 expect_test_features(mock_image_ctx
);
1397 expect_is_exclusive_lock_owner(mock_exclusive_lock
, true);
1399 // object map should be immediately opened if exclusive lock owned
1401 expect_get_mutable_metadata(mock_image_ctx
, ictx
->features
, 0);
1402 expect_get_parent(mock_image_ctx
, 0);
1403 MockGetMetadataRequest mock_get_metadata_request
;
1404 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
,
1405 mock_image_ctx
.header_oid
, {}, 0);
1406 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
, RBD_INFO
, {},
1408 expect_apply_metadata(mock_image_ctx
, 0);
1409 expect_get_group(mock_image_ctx
, 0);
1410 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
1411 expect_open_object_map(mock_image_ctx
, &mock_object_map
, -EFBIG
);
1414 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false,
1418 ASSERT_EQ(0, ctx
.wait());
1419 ASSERT_EQ(nullptr, mock_image_ctx
.object_map
);
1422 TEST_F(TestMockImageRefreshRequest
, ApplyMetadataError
) {
1423 REQUIRE_FORMAT_V2();
1425 librbd::ImageCtx
*ictx
;
1426 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1428 MockRefreshImageCtx
mock_image_ctx(*ictx
);
1429 MockRefreshParentRequest mock_refresh_parent_request
;
1430 MockExclusiveLock mock_exclusive_lock
;
1431 expect_op_work_queue(mock_image_ctx
);
1432 expect_test_features(mock_image_ctx
);
1435 expect_get_mutable_metadata(mock_image_ctx
, ictx
->features
, 0);
1436 expect_get_parent(mock_image_ctx
, 0);
1437 MockGetMetadataRequest mock_get_metadata_request
;
1438 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
,
1439 mock_image_ctx
.header_oid
, {}, 0);
1440 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
, RBD_INFO
, {},
1442 expect_apply_metadata(mock_image_ctx
, -EINVAL
);
1443 expect_get_group(mock_image_ctx
, 0);
1444 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
1445 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
1446 expect_init_exclusive_lock(mock_image_ctx
, mock_exclusive_lock
, 0);
1450 MockRefreshRequest
*req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx
);
1453 ASSERT_EQ(0, ctx
.wait());
1456 TEST_F(TestMockImageRefreshRequest
, NonPrimaryFeature
) {
1457 REQUIRE_FORMAT_V2();
1459 librbd::ImageCtx
*ictx
;
1460 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
1462 MockRefreshImageCtx
mock_image_ctx(*ictx
);
1463 MockRefreshParentRequest mock_refresh_parent_request
;
1464 MockExclusiveLock mock_exclusive_lock
;
1465 expect_op_work_queue(mock_image_ctx
);
1466 expect_test_features(mock_image_ctx
);
1470 // ensure the image is put into read-only mode
1471 expect_get_mutable_metadata(mock_image_ctx
,
1472 ictx
->features
| RBD_FEATURE_NON_PRIMARY
, 0);
1473 expect_get_parent(mock_image_ctx
, 0);
1474 MockGetMetadataRequest mock_get_metadata_request
;
1475 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
,
1476 mock_image_ctx
.header_oid
, {}, 0);
1477 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
, RBD_INFO
, {},
1479 expect_apply_metadata(mock_image_ctx
, 0);
1480 expect_get_group(mock_image_ctx
, 0);
1481 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
1484 auto req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx1
);
1487 ASSERT_EQ(0, ctx1
.wait());
1488 ASSERT_TRUE(mock_image_ctx
.read_only
);
1489 ASSERT_EQ(IMAGE_READ_ONLY_FLAG_NON_PRIMARY
, mock_image_ctx
.read_only_flags
);
1491 // try again but permit R/W against non-primary image
1492 mock_image_ctx
.read_only_mask
= ~IMAGE_READ_ONLY_FLAG_NON_PRIMARY
;
1494 expect_get_mutable_metadata(mock_image_ctx
,
1495 ictx
->features
| RBD_FEATURE_NON_PRIMARY
, 0);
1496 expect_get_parent(mock_image_ctx
, 0);
1497 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
,
1498 mock_image_ctx
.header_oid
, {}, 0);
1499 expect_get_metadata(mock_image_ctx
, mock_get_metadata_request
, RBD_INFO
, {},
1501 expect_apply_metadata(mock_image_ctx
, 0);
1502 expect_get_group(mock_image_ctx
, 0);
1503 expect_refresh_parent_is_required(mock_refresh_parent_request
, false);
1504 if (ictx
->test_features(RBD_FEATURE_EXCLUSIVE_LOCK
)) {
1505 expect_init_exclusive_lock(mock_image_ctx
, mock_exclusive_lock
, 0);
1509 req
= new MockRefreshRequest(mock_image_ctx
, false, false, &ctx2
);
1512 ASSERT_EQ(0, ctx2
.wait());
1513 ASSERT_FALSE(mock_image_ctx
.read_only
);
1514 ASSERT_EQ(0U, mock_image_ctx
.read_only_flags
);
1517 } // namespace image
1518 } // namespace librbd