]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/librbd/image/test_mock_RefreshRequest.cc
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / test / librbd / image / test_mock_RefreshRequest.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
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>
23 #include <list>
24 #include <boost/scope_exit.hpp>
25
26 namespace librbd {
27
28 namespace {
29
30 struct MockRefreshImageCtx : public MockImageCtx {
31 MockRefreshImageCtx(ImageCtx &image_ctx) : MockImageCtx(image_ctx) {
32 }
33 };
34
35 } // anonymous namespace
36
37 namespace image {
38
39 template <>
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,
45 Context *on_finish) {
46 ceph_assert(s_instance != nullptr);
47 s_instance->on_finish = on_finish;
48 return s_instance;
49 }
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();
55 }
56
57 Context *on_finish = nullptr;
58
59 RefreshParentRequest() {
60 s_instance = this;
61 }
62
63 MOCK_CONST_METHOD0(is_refresh_required, bool());
64 MOCK_METHOD0(send, void());
65 MOCK_METHOD0(apply, void());
66 MOCK_METHOD1(finalize, void(Context *));
67 };
68
69 RefreshParentRequest<MockRefreshImageCtx>* RefreshParentRequest<MockRefreshImageCtx>::s_instance = nullptr;
70
71 } // namespace image
72
73 namespace io {
74
75 template <>
76 struct ImageDispatchSpec<librbd::MockRefreshImageCtx> {
77 static ImageDispatchSpec* s_instance;
78 AioCompletion *aio_comp = nullptr;
79
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;
85 return s_instance;
86 }
87
88 MOCK_CONST_METHOD0(send, void());
89
90 ImageDispatchSpec() {
91 s_instance = this;
92 }
93 };
94
95 ImageDispatchSpec<librbd::MockRefreshImageCtx>* ImageDispatchSpec<librbd::MockRefreshImageCtx>::s_instance = nullptr;
96
97 } // namespace io
98 namespace util {
99
100 inline ImageCtx *get_image_ctx(librbd::MockRefreshImageCtx *image_ctx) {
101 return image_ctx->image_ctx;
102 }
103
104 } // namespace util
105 } // namespace librbd
106
107 // template definitions
108 #include "librbd/image/RefreshRequest.cc"
109
110 ACTION_P(TestFeatures, image_ctx) {
111 return ((image_ctx->features & arg0) != 0);
112 }
113
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;
119 }
120
121 namespace librbd {
122 namespace image {
123
124 using ::testing::_;
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;
132
133 class TestMockImageRefreshRequest : public TestMockFixture {
134 public:
135 typedef RefreshRequest<MockRefreshImageCtx> MockRefreshRequest;
136 typedef RefreshParentRequest<MockRefreshImageCtx> MockRefreshParentRequest;
137 typedef io::ImageDispatchSpec<librbd::MockRefreshImageCtx> MockIoImageDispatchSpec;
138
139 void set_v1_migration_header(ImageCtx *ictx) {
140 bufferlist hdr;
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)));
144
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));
148 }
149
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,
153 enabled));
154 }
155
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, _, _, _));
159 if (r < 0) {
160 expect.WillOnce(Return(r));
161 } else {
162 expect.WillOnce(DoDefault());
163 }
164 }
165
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"), _, _, _));
169 if (r < 0) {
170 expect.WillOnce(Return(r));
171 } else {
172 expect.WillOnce(DoDefault());
173 }
174 }
175
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"), _, _, _));
179 if (r < 0) {
180 expect.WillOnce(Return(r));
181 } else {
182 expect.WillOnce(DoDefault());
183 }
184 }
185
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"), _, _, _));
190 if (r < 0) {
191 expect.WillOnce(Return(r));
192 } else {
193 uint64_t incompatible = (
194 mock_image_ctx.read_only ? features & RBD_FEATURES_INCOMPATIBLE :
195 features & RBD_FEATURES_RW_INCOMPATIBLE);
196
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);
203 return 0;
204 })));
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());
212 }
213 }
214
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"), _, _, _));
219 if (r < 0) {
220 expect.WillOnce(Return(r));
221 } else {
222 expect.WillOnce(DoDefault());
223 }
224 }
225
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"), _, _, _));
230 if (r < 0) {
231 expect.WillOnce(Return(r));
232 } else {
233 expect.WillOnce(DoDefault());
234 expect_parent_overlap_get(mock_image_ctx, 0);
235 }
236 }
237
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"), _, _, _));
242 if (r < 0) {
243 expect.WillOnce(Return(r));
244 } else {
245 expect.WillOnce(DoDefault());
246 }
247 }
248
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"), _, _, _));
253 if (r < 0) {
254 expect.WillOnce(Return(r));
255 } else {
256 expect.WillOnce(DoDefault());
257 }
258 }
259
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"), _, _, _));
263 if (r < 0) {
264 expect.WillOnce(Return(r));
265 } else {
266 expect.WillOnce(DoDefault());
267 EXPECT_CALL(*mock_image_ctx.image_watcher, is_unregistered())
268 .WillOnce(Return(false));
269 }
270 }
271
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"), _, _, _));
275 if (r < 0) {
276 expect.WillOnce(Return(r));
277 } else {
278 expect.WillOnce(DoDefault());
279 }
280 }
281
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);
289 return r;
290 })));
291 }
292
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"), _, _, _));
297 if (r < 0) {
298 expect.WillOnce(Return(r));
299 } else {
300 expect.WillOnce(DoDefault());
301 }
302 }
303
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"), _, _, _));
308 if (r < 0) {
309 expect.WillOnce(Return(r));
310 } else {
311 expect.WillOnce(DoDefault());
312 if (legacy_parent) {
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());
316 } else {
317 expect_parent_overlap_get(mock_image_ctx, 0);
318 }
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());
323 }
324 }
325
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"), _, _, _));
329 if (r < 0) {
330 expect.WillOnce(Return(r));
331 } else {
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());
346 }
347 }
348
349 void expect_apply_metadata(MockRefreshImageCtx &mock_image_ctx,
350 int r) {
351 EXPECT_CALL(mock_image_ctx, apply_metadata(_, false))
352 .WillOnce(Return(r));
353 }
354
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, _, _, _, _, _));
358 }
359
360 void expect_init_exclusive_lock(MockRefreshImageCtx &mock_image_ctx,
361 MockExclusiveLock &mock_exclusive_lock,
362 int r) {
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)));
367 }
368
369 void expect_shut_down_exclusive_lock(MockRefreshImageCtx &mock_image_ctx,
370 MockExclusiveLock &mock_exclusive_lock,
371 int r) {
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)));
375 }
376
377 void expect_init_layout(MockRefreshImageCtx &mock_image_ctx) {
378 EXPECT_CALL(mock_image_ctx, init_layout());
379 }
380
381 void expect_test_features(MockRefreshImageCtx &mock_image_ctx) {
382 EXPECT_CALL(mock_image_ctx, test_features(_, _))
383 .WillRepeatedly(TestFeatures(&mock_image_ctx));
384 }
385
386 void expect_refresh_parent_is_required(MockRefreshParentRequest &mock_refresh_parent_request,
387 bool required) {
388 EXPECT_CALL(mock_refresh_parent_request, is_refresh_required())
389 .WillRepeatedly(Return(required));
390 }
391
392 void expect_refresh_parent_send(MockRefreshImageCtx &mock_image_ctx,
393 MockRefreshParentRequest &mock_refresh_parent_request,
394 int r) {
395 EXPECT_CALL(mock_refresh_parent_request, send())
396 .WillOnce(FinishRequest(&mock_refresh_parent_request, r,
397 &mock_image_ctx));
398 }
399
400 void expect_refresh_parent_apply(MockRefreshParentRequest &mock_refresh_parent_request) {
401 EXPECT_CALL(mock_refresh_parent_request, apply());
402 }
403
404 void expect_refresh_parent_finalize(MockRefreshImageCtx &mock_image_ctx,
405 MockRefreshParentRequest &mock_refresh_parent_request,
406 int r) {
407 EXPECT_CALL(mock_refresh_parent_request, finalize(_))
408 .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
409 }
410
411 void expect_is_exclusive_lock_owner(MockExclusiveLock &mock_exclusive_lock,
412 bool is_owner) {
413 EXPECT_CALL(mock_exclusive_lock, is_lock_owner()).WillOnce(Return(is_owner));
414 }
415
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));
420 }
421
422 void expect_journal_disabled(MockJournalPolicy &mock_journal_policy,
423 bool disabled) {
424 EXPECT_CALL(mock_journal_policy, journal_disabled())
425 .WillOnce(Return(disabled));
426 }
427
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));
434 }
435
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));
440 }
441
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));
448 }
449
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));
454 }
455
456 void expect_get_snap_id(MockRefreshImageCtx &mock_image_ctx,
457 const std::string &snap_name,
458 uint64_t snap_id) {
459 EXPECT_CALL(mock_image_ctx,
460 get_snap_id(_, snap_name)).WillOnce(Return(snap_id));
461 }
462
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));
466 }
467
468 void expect_unblock_writes(MockImageCtx &mock_image_ctx) {
469 EXPECT_CALL(*mock_image_ctx.io_work_queue, unblock_writes())
470 .Times(1);
471 }
472
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);
479 }));
480 }
481
482 };
483
484 TEST_F(TestMockImageRefreshRequest, SuccessV1) {
485 REQUIRE_FORMAT_V1();
486
487 librbd::ImageCtx *ictx;
488 ASSERT_EQ(0, open_image(m_image_name, &ictx));
489
490 MockRefreshImageCtx mock_image_ctx(*ictx);
491 expect_op_work_queue(mock_image_ctx);
492 expect_test_features(mock_image_ctx);
493
494 InSequence seq;
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);
499
500 C_SaferCond ctx;
501 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
502 req->send();
503
504 ASSERT_EQ(0, ctx.wait());
505 }
506
507 TEST_F(TestMockImageRefreshRequest, SuccessSnapshotV1) {
508 REQUIRE_FORMAT_V1();
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());
513
514 MockRefreshImageCtx mock_image_ctx(*ictx);
515 expect_op_work_queue(mock_image_ctx);
516 expect_test_features(mock_image_ctx);
517
518 InSequence seq;
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);
524
525 C_SaferCond ctx;
526 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
527 req->send();
528
529 ASSERT_EQ(0, ctx.wait());
530 }
531
532 TEST_F(TestMockImageRefreshRequest, SuccessV2) {
533 REQUIRE_FORMAT_V2();
534
535 librbd::ImageCtx *ictx;
536 ASSERT_EQ(0, open_image(m_image_name, &ictx));
537
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);
543
544 InSequence seq;
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);
553 }
554
555 C_SaferCond ctx;
556 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
557 req->send();
558
559 ASSERT_EQ(0, ctx.wait());
560 }
561
562 TEST_F(TestMockImageRefreshRequest, SuccessSnapshotV2) {
563 REQUIRE_FORMAT_V2();
564
565 librbd::ImageCtx *ictx;
566 ASSERT_EQ(0, open_image(m_image_name, &ictx));
567 ASSERT_EQ(0, snap_create(*ictx, "snap"));
568
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);
574
575 InSequence seq;
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);
585 }
586 expect_add_snap(mock_image_ctx, "snap", ictx->snap_ids.begin()->second);
587
588 C_SaferCond ctx;
589 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
590 req->send();
591
592 ASSERT_EQ(0, ctx.wait());
593 }
594
595 TEST_F(TestMockImageRefreshRequest, SuccessLegacySnapshotV2) {
596 REQUIRE_FORMAT_V2();
597
598 librbd::ImageCtx *ictx;
599 ASSERT_EQ(0, open_image(m_image_name, &ictx));
600 ASSERT_EQ(0, snap_create(*ictx, "snap"));
601
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);
607
608 InSequence seq;
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);
620 }
621 expect_add_snap(mock_image_ctx, "snap", ictx->snap_ids.begin()->second);
622
623 C_SaferCond ctx;
624 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
625 req->send();
626
627 ASSERT_EQ(0, ctx.wait());
628 }
629
630 TEST_F(TestMockImageRefreshRequest, SuccessSetSnapshotV2) {
631 REQUIRE_FORMAT_V2();
632
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(),
638 "snap"));
639
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);
645
646 InSequence seq;
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);
656 }
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);
659
660 C_SaferCond ctx;
661 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
662 req->send();
663
664 ASSERT_EQ(0, ctx.wait());
665 }
666
667 TEST_F(TestMockImageRefreshRequest, SuccessChild) {
668 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
669
670 librbd::ImageCtx *ictx;
671 librbd::ImageCtx *ictx2 = nullptr;
672 std::string clone_name = get_temp_image_name();
673
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) {
679 close_image(ictx2);
680 }
681
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"));
685 };
686
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));
690
691 ASSERT_EQ(0, open_image(clone_name, &ictx2));
692
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);
698
699 InSequence seq;
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);
710 }
711 expect_refresh_parent_apply(*mock_refresh_parent_request);
712 expect_refresh_parent_finalize(mock_image_ctx, *mock_refresh_parent_request, 0);
713
714 C_SaferCond ctx;
715 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
716 req->send();
717
718 ASSERT_EQ(0, ctx.wait());
719 }
720
721 TEST_F(TestMockImageRefreshRequest, SuccessChildDontOpenParent) {
722 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
723
724 librbd::ImageCtx *ictx;
725 librbd::ImageCtx *ictx2 = nullptr;
726 std::string clone_name = get_temp_image_name();
727
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) {
733 close_image(ictx2);
734 }
735
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"));
739 };
740
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));
744
745 ASSERT_EQ(0, open_image(clone_name, &ictx2));
746
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);
751
752 InSequence seq;
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);
761 }
762
763 C_SaferCond ctx;
764 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, true, &ctx);
765 req->send();
766
767 ASSERT_EQ(0, ctx.wait());
768 }
769
770 TEST_F(TestMockImageRefreshRequest, SuccessOpFeatures) {
771 REQUIRE_FORMAT_V2();
772
773 librbd::ImageCtx *ictx;
774 ASSERT_EQ(0, open_image(m_image_name, &ictx));
775
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);
781
782 mock_image_ctx.features |= RBD_FEATURE_OPERATIONS;
783
784 InSequence seq;
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);
794 }
795
796 C_SaferCond ctx;
797 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
798 req->send();
799
800 ASSERT_EQ(0, ctx.wait());
801 ASSERT_EQ(4096U, mock_image_ctx.op_features);
802 ASSERT_TRUE(mock_image_ctx.operations_disabled);
803 }
804
805 TEST_F(TestMockImageRefreshRequest, DisableExclusiveLock) {
806 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
807
808 librbd::ImageCtx *ictx;
809 ASSERT_EQ(0, open_image(m_image_name, &ictx));
810
811 MockRefreshImageCtx mock_image_ctx(*ictx);
812 MockRefreshParentRequest mock_refresh_parent_request;
813
814 MockExclusiveLock *mock_exclusive_lock = new MockExclusiveLock();
815 mock_image_ctx.exclusive_lock = mock_exclusive_lock;
816
817 MockObjectMap mock_object_map;
818 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
819 mock_image_ctx.object_map = &mock_object_map;
820 }
821
822 MockJournal mock_journal;
823 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
824 mock_image_ctx.journal = &mock_journal;
825 }
826
827 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
828 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
829 false));
830 }
831
832 if (ictx->test_features(RBD_FEATURE_FAST_DIFF)) {
833 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_FAST_DIFF,
834 false));
835 }
836
837 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
838 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_OBJECT_MAP,
839 false));
840 }
841
842 if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
843 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_EXCLUSIVE_LOCK,
844 false));
845 }
846
847 ASSERT_EQ(0, ictx->state->refresh());
848
849 expect_op_work_queue(mock_image_ctx);
850 expect_test_features(mock_image_ctx);
851
852 // verify that exclusive lock is properly handled when object map
853 // and journaling were never enabled (or active)
854 InSequence seq;
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);
862
863 C_SaferCond ctx;
864 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
865 req->send();
866
867 ASSERT_EQ(0, ctx.wait());
868 }
869
870 TEST_F(TestMockImageRefreshRequest, DisableExclusiveLockWhileAcquiringLock) {
871 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
872
873 librbd::ImageCtx *ictx;
874 ASSERT_EQ(0, open_image(m_image_name, &ictx));
875
876 MockRefreshImageCtx mock_image_ctx(*ictx);
877 MockRefreshParentRequest mock_refresh_parent_request;
878
879 MockExclusiveLock mock_exclusive_lock;
880 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
881
882 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
883 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
884 false));
885 }
886
887 if (ictx->test_features(RBD_FEATURE_FAST_DIFF)) {
888 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_FAST_DIFF,
889 false));
890 }
891
892 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
893 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_OBJECT_MAP,
894 false));
895 }
896
897 if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
898 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_EXCLUSIVE_LOCK,
899 false));
900 }
901
902 ASSERT_EQ(0, ictx->state->refresh());
903
904 expect_op_work_queue(mock_image_ctx);
905 expect_test_features(mock_image_ctx);
906
907 // verify that exclusive lock is properly handled when object map
908 // and journaling were never enabled (or active)
909 InSequence seq;
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);
916
917 C_SaferCond ctx;
918 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, true, false, &ctx);
919 req->send();
920
921 ASSERT_EQ(-ERESTART, ctx.wait());
922 }
923
924 TEST_F(TestMockImageRefreshRequest, JournalDisabledByPolicy) {
925 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
926
927 librbd::ImageCtx *ictx;
928 ASSERT_EQ(0, open_image(m_image_name, &ictx));
929
930 if (ictx->test_features(RBD_FEATURE_FAST_DIFF)) {
931 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_FAST_DIFF,
932 false));
933 }
934
935 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
936 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_OBJECT_MAP,
937 false));
938 }
939
940 ASSERT_EQ(0, ictx->state->refresh());
941
942 MockRefreshImageCtx mock_image_ctx(*ictx);
943 MockRefreshParentRequest mock_refresh_parent_request;
944
945 MockExclusiveLock mock_exclusive_lock;
946 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
947
948 MockJournal mock_journal;
949
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);
953
954 InSequence seq;
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);
961
962 MockJournalPolicy mock_journal_policy;
963 expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
964 expect_journal_disabled(mock_journal_policy, true);
965
966 C_SaferCond ctx;
967 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
968 req->send();
969
970 ASSERT_EQ(0, ctx.wait());
971 }
972
973 TEST_F(TestMockImageRefreshRequest, EnableJournalWithExclusiveLock) {
974 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
975
976 librbd::ImageCtx *ictx;
977 ASSERT_EQ(0, open_image(m_image_name, &ictx));
978
979 if (ictx->test_features(RBD_FEATURE_FAST_DIFF)) {
980 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_FAST_DIFF,
981 false));
982 }
983
984 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
985 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_OBJECT_MAP,
986 false));
987 }
988
989 ASSERT_EQ(0, ictx->state->refresh());
990
991 MockRefreshImageCtx mock_image_ctx(*ictx);
992 MockRefreshParentRequest mock_refresh_parent_request;
993
994 MockExclusiveLock mock_exclusive_lock;
995 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
996
997 MockJournal mock_journal;
998
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);
1002
1003 // journal should be immediately opened if exclusive lock owned
1004 InSequence seq;
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);
1011
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);
1016
1017 C_SaferCond ctx;
1018 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
1019 req->send();
1020
1021 ASSERT_EQ(0, ctx.wait());
1022 }
1023
1024 TEST_F(TestMockImageRefreshRequest, EnableJournalWithoutExclusiveLock) {
1025 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
1026
1027 librbd::ImageCtx *ictx;
1028 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1029
1030 if (ictx->test_features(RBD_FEATURE_FAST_DIFF)) {
1031 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_FAST_DIFF,
1032 false));
1033 }
1034
1035 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
1036 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_OBJECT_MAP,
1037 false));
1038 }
1039
1040 ASSERT_EQ(0, ictx->state->refresh());
1041
1042 MockRefreshImageCtx mock_image_ctx(*ictx);
1043 MockRefreshParentRequest mock_refresh_parent_request;
1044
1045 MockExclusiveLock mock_exclusive_lock;
1046 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
1047
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);
1051
1052 // do not open the journal if exclusive lock is not owned
1053 InSequence seq;
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);
1061
1062 C_SaferCond ctx;
1063 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
1064 req->send();
1065
1066 ASSERT_EQ(0, ctx.wait());
1067 }
1068
1069 TEST_F(TestMockImageRefreshRequest, DisableJournal) {
1070 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
1071
1072 librbd::ImageCtx *ictx;
1073 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1074
1075 MockRefreshImageCtx mock_image_ctx(*ictx);
1076 MockRefreshParentRequest mock_refresh_parent_request;
1077
1078 MockExclusiveLock mock_exclusive_lock;
1079 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
1080
1081 MockObjectMap mock_object_map;
1082 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
1083 mock_image_ctx.object_map = &mock_object_map;
1084 }
1085
1086 MockJournal *mock_journal = new MockJournal();
1087 mock_image_ctx.journal = mock_journal;
1088
1089 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
1090 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
1091 false));
1092 }
1093
1094 ASSERT_EQ(0, ictx->state->refresh());
1095
1096 expect_op_work_queue(mock_image_ctx);
1097 expect_test_features(mock_image_ctx);
1098
1099 // verify journal is closed if feature disabled
1100 InSequence seq;
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);
1110 }
1111 expect_close_journal(mock_image_ctx, *mock_journal, 0);
1112 expect_unblock_writes(mock_image_ctx);
1113
1114 C_SaferCond ctx;
1115 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
1116 req->send();
1117
1118 ASSERT_EQ(0, ctx.wait());
1119 }
1120
1121 TEST_F(TestMockImageRefreshRequest, EnableObjectMapWithExclusiveLock) {
1122 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
1123
1124 librbd::ImageCtx *ictx;
1125 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1126
1127 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
1128 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
1129 false));
1130 }
1131
1132 ASSERT_EQ(0, ictx->state->refresh());
1133
1134 MockRefreshImageCtx mock_image_ctx(*ictx);
1135 MockRefreshParentRequest mock_refresh_parent_request;
1136
1137 MockExclusiveLock mock_exclusive_lock;
1138 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
1139
1140 MockObjectMap mock_object_map;
1141
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);
1145
1146 // object map should be immediately opened if exclusive lock owned
1147 InSequence seq;
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);
1155
1156 C_SaferCond ctx;
1157 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
1158 req->send();
1159
1160 ASSERT_EQ(0, ctx.wait());
1161 }
1162
1163 TEST_F(TestMockImageRefreshRequest, EnableObjectMapWithoutExclusiveLock) {
1164 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
1165
1166 librbd::ImageCtx *ictx;
1167 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1168
1169 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
1170 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
1171 false));
1172 }
1173
1174 ASSERT_EQ(0, ictx->state->refresh());
1175
1176 MockRefreshImageCtx mock_image_ctx(*ictx);
1177 MockRefreshParentRequest mock_refresh_parent_request;
1178
1179 MockExclusiveLock mock_exclusive_lock;
1180 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
1181
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);
1185
1186 // do not open the object map if exclusive lock is not owned
1187 InSequence seq;
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);
1194
1195 C_SaferCond ctx;
1196 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
1197 req->send();
1198
1199 ASSERT_EQ(0, ctx.wait());
1200 }
1201
1202 TEST_F(TestMockImageRefreshRequest, DisableObjectMap) {
1203 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
1204
1205 librbd::ImageCtx *ictx;
1206 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1207
1208 MockRefreshImageCtx mock_image_ctx(*ictx);
1209 MockRefreshParentRequest mock_refresh_parent_request;
1210
1211 MockExclusiveLock mock_exclusive_lock;
1212 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
1213
1214 MockObjectMap *mock_object_map = new MockObjectMap();
1215 mock_image_ctx.object_map = mock_object_map;
1216
1217 MockJournal mock_journal;
1218 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
1219 mock_image_ctx.journal = &mock_journal;
1220 }
1221
1222 if (ictx->test_features(RBD_FEATURE_FAST_DIFF)) {
1223 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_FAST_DIFF,
1224 false));
1225 }
1226
1227 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
1228 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_OBJECT_MAP,
1229 false));
1230 }
1231
1232 ASSERT_EQ(0, ictx->state->refresh());
1233
1234 expect_op_work_queue(mock_image_ctx);
1235 expect_test_features(mock_image_ctx);
1236
1237 // verify object map is closed if feature disabled
1238 InSequence seq;
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);
1246
1247 C_SaferCond ctx;
1248 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
1249 req->send();
1250
1251 ASSERT_EQ(0, ctx.wait());
1252 }
1253
1254 TEST_F(TestMockImageRefreshRequest, OpenObjectMapError) {
1255 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
1256
1257 librbd::ImageCtx *ictx;
1258 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1259
1260 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
1261 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
1262 false));
1263 }
1264
1265 ASSERT_EQ(0, ictx->state->refresh());
1266
1267 MockRefreshImageCtx mock_image_ctx(*ictx);
1268 MockRefreshParentRequest mock_refresh_parent_request;
1269
1270 MockExclusiveLock mock_exclusive_lock;
1271 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
1272
1273 MockObjectMap *mock_object_map = new MockObjectMap();
1274
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);
1278
1279 // object map should be immediately opened if exclusive lock owned
1280 InSequence seq;
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);
1288
1289 C_SaferCond ctx;
1290 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false,
1291 &ctx);
1292 req->send();
1293
1294 ASSERT_EQ(-EBLACKLISTED, ctx.wait());
1295 ASSERT_EQ(nullptr, mock_image_ctx.object_map);
1296 }
1297
1298 TEST_F(TestMockImageRefreshRequest, OpenObjectMapTooLarge) {
1299 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
1300
1301 librbd::ImageCtx *ictx;
1302 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1303
1304 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
1305 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
1306 false));
1307 }
1308
1309 ASSERT_EQ(0, ictx->state->refresh());
1310
1311 MockRefreshImageCtx mock_image_ctx(*ictx);
1312 MockRefreshParentRequest mock_refresh_parent_request;
1313
1314 MockExclusiveLock mock_exclusive_lock;
1315 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
1316
1317 MockObjectMap *mock_object_map = new MockObjectMap();
1318
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);
1322
1323 // object map should be immediately opened if exclusive lock owned
1324 InSequence seq;
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);
1332
1333 C_SaferCond ctx;
1334 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false,
1335 &ctx);
1336 req->send();
1337
1338 ASSERT_EQ(0, ctx.wait());
1339 ASSERT_EQ(nullptr, mock_image_ctx.object_map);
1340 }
1341
1342 TEST_F(TestMockImageRefreshRequest, ApplyMetadataError) {
1343 REQUIRE_FORMAT_V2();
1344
1345 librbd::ImageCtx *ictx;
1346 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1347
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);
1353
1354 InSequence seq;
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);
1363 }
1364
1365 C_SaferCond ctx;
1366 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
1367 req->send();
1368
1369 ASSERT_EQ(0, ctx.wait());
1370 }
1371
1372 } // namespace image
1373 } // namespace librbd