]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/librbd/image/test_mock_RefreshRequest.cc
import 15.2.0 Octopus source
[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/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>
24 #include <list>
25 #include <boost/scope_exit.hpp>
26
27 namespace librbd {
28
29 namespace {
30
31 struct MockRefreshImageCtx : public MockImageCtx {
32 MockRefreshImageCtx(ImageCtx &image_ctx) : MockImageCtx(image_ctx) {
33 }
34 };
35
36 } // anonymous namespace
37
38 namespace image {
39
40 template <>
41 struct GetMetadataRequest<MockRefreshImageCtx> {
42 std::string oid;
43 std::map<std::string, bufferlist>* pairs = nullptr;
44 Context* on_finish = nullptr;
45
46 static GetMetadataRequest* s_instance;
47 static GetMetadataRequest* create(librados::IoCtx&,
48 const std::string& oid,
49 bool filter_internal,
50 const std::string& filter_key_prefix,
51 const std::string& last_key,
52 uint32_t max_results,
53 std::map<std::string, bufferlist>* pairs,
54 Context* on_finish) {
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;
61 return s_instance;
62 }
63
64 GetMetadataRequest() {
65 s_instance = this;
66 }
67
68 MOCK_METHOD0(send, void());
69 };
70
71 template <>
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,
77 Context *on_finish) {
78 ceph_assert(s_instance != nullptr);
79 s_instance->on_finish = on_finish;
80 return s_instance;
81 }
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();
87 }
88
89 Context *on_finish = nullptr;
90
91 RefreshParentRequest() {
92 s_instance = this;
93 }
94
95 MOCK_CONST_METHOD0(is_refresh_required, bool());
96 MOCK_METHOD0(send, void());
97 MOCK_METHOD0(apply, void());
98 MOCK_METHOD1(finalize, void(Context *));
99 };
100
101 GetMetadataRequest<MockRefreshImageCtx>* GetMetadataRequest<MockRefreshImageCtx>::s_instance = nullptr;
102 RefreshParentRequest<MockRefreshImageCtx>* RefreshParentRequest<MockRefreshImageCtx>::s_instance = nullptr;
103
104 } // namespace image
105
106 namespace io {
107
108 template <>
109 struct ImageDispatchSpec<librbd::MockRefreshImageCtx> {
110 static ImageDispatchSpec* s_instance;
111 AioCompletion *aio_comp = nullptr;
112
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;
118 return s_instance;
119 }
120
121 MOCK_CONST_METHOD0(send, void());
122
123 ImageDispatchSpec() {
124 s_instance = this;
125 }
126 };
127
128 ImageDispatchSpec<librbd::MockRefreshImageCtx>* ImageDispatchSpec<librbd::MockRefreshImageCtx>::s_instance = nullptr;
129
130 } // namespace io
131 namespace util {
132
133 inline ImageCtx *get_image_ctx(librbd::MockRefreshImageCtx *image_ctx) {
134 return image_ctx->image_ctx;
135 }
136
137 } // namespace util
138 } // namespace librbd
139
140 // template definitions
141 #include "librbd/image/RefreshRequest.cc"
142
143 ACTION_P(TestFeatures, image_ctx) {
144 return ((image_ctx->features & arg0) != 0);
145 }
146
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;
152 }
153
154 namespace librbd {
155 namespace image {
156
157 using ::testing::_;
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;
165
166 class TestMockImageRefreshRequest : public TestMockFixture {
167 public:
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;
173
174 void set_v1_migration_header(ImageCtx *ictx) {
175 bufferlist hdr;
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)));
179
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));
183 }
184
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,
188 enabled));
189 }
190
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, _, _, _));
194 if (r < 0) {
195 expect.WillOnce(Return(r));
196 } else {
197 expect.WillOnce(DoDefault());
198 }
199 }
200
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"), _, _, _));
204 if (r < 0) {
205 expect.WillOnce(Return(r));
206 } else {
207 expect.WillOnce(DoDefault());
208 }
209 }
210
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"), _, _, _));
214 if (r < 0) {
215 expect.WillOnce(Return(r));
216 } else {
217 expect.WillOnce(DoDefault());
218 }
219 }
220
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"), _, _, _));
225 if (r < 0) {
226 expect.WillOnce(Return(r));
227 } else {
228 uint64_t incompatible = (
229 mock_image_ctx.read_only ? features & RBD_FEATURES_INCOMPATIBLE :
230 features & RBD_FEATURES_RW_INCOMPATIBLE);
231
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);
238 return 0;
239 })));
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());
247 }
248 }
249
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"), _, _, _));
254 if (r < 0) {
255 expect.WillOnce(Return(r));
256 } else {
257 expect.WillOnce(DoDefault());
258 }
259 }
260
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"), _, _, _));
265 if (r < 0) {
266 expect.WillOnce(Return(r));
267 } else {
268 expect.WillOnce(DoDefault());
269 expect_parent_overlap_get(mock_image_ctx, 0);
270 }
271 }
272
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"), _, _, _));
277 if (r < 0) {
278 expect.WillOnce(Return(r));
279 } else {
280 expect.WillOnce(DoDefault());
281 }
282 }
283
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"), _, _, _));
288 if (r < 0) {
289 expect.WillOnce(Return(r));
290 } else {
291 expect.WillOnce(DoDefault());
292 }
293 }
294
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);
305 }));
306 }
307
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"), _, _, _));
311 if (r < 0) {
312 expect.WillOnce(Return(r));
313 } else {
314 expect.WillOnce(DoDefault());
315 }
316 }
317
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);
325 return r;
326 })));
327 }
328
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"), _, _, _));
333 if (r < 0) {
334 expect.WillOnce(Return(r));
335 } else {
336 expect.WillOnce(DoDefault());
337 }
338 }
339
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"), _, _, _));
344 if (r < 0) {
345 expect.WillOnce(Return(r));
346 } else {
347 expect.WillOnce(DoDefault());
348 if (legacy_parent) {
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());
352 } else {
353 expect_parent_overlap_get(mock_image_ctx, 0);
354 }
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());
359 }
360 }
361
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"), _, _, _));
365 if (r < 0) {
366 expect.WillOnce(Return(r));
367 } else {
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());
382 }
383 }
384
385 void expect_apply_metadata(MockRefreshImageCtx &mock_image_ctx,
386 int r) {
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));
391 }
392
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, _, _, _, _, _));
396 }
397
398 void expect_init_exclusive_lock(MockRefreshImageCtx &mock_image_ctx,
399 MockExclusiveLock &mock_exclusive_lock,
400 int r) {
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)));
405 }
406
407 void expect_shut_down_exclusive_lock(MockRefreshImageCtx &mock_image_ctx,
408 MockExclusiveLock &mock_exclusive_lock,
409 int r) {
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)));
413 }
414
415 void expect_init_layout(MockRefreshImageCtx &mock_image_ctx) {
416 EXPECT_CALL(mock_image_ctx, init_layout(_));
417 }
418
419 void expect_test_features(MockRefreshImageCtx &mock_image_ctx) {
420 EXPECT_CALL(mock_image_ctx, test_features(_, _))
421 .WillRepeatedly(TestFeatures(&mock_image_ctx));
422 }
423
424 void expect_refresh_parent_is_required(MockRefreshParentRequest &mock_refresh_parent_request,
425 bool required) {
426 EXPECT_CALL(mock_refresh_parent_request, is_refresh_required())
427 .WillRepeatedly(Return(required));
428 }
429
430 void expect_refresh_parent_send(MockRefreshImageCtx &mock_image_ctx,
431 MockRefreshParentRequest &mock_refresh_parent_request,
432 int r) {
433 EXPECT_CALL(mock_refresh_parent_request, send())
434 .WillOnce(FinishRequest(&mock_refresh_parent_request, r,
435 &mock_image_ctx));
436 }
437
438 void expect_refresh_parent_apply(MockRefreshParentRequest &mock_refresh_parent_request) {
439 EXPECT_CALL(mock_refresh_parent_request, apply());
440 }
441
442 void expect_refresh_parent_finalize(MockRefreshImageCtx &mock_image_ctx,
443 MockRefreshParentRequest &mock_refresh_parent_request,
444 int r) {
445 EXPECT_CALL(mock_refresh_parent_request, finalize(_))
446 .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
447 }
448
449 void expect_is_exclusive_lock_owner(MockExclusiveLock &mock_exclusive_lock,
450 bool is_owner) {
451 EXPECT_CALL(mock_exclusive_lock, is_lock_owner()).WillOnce(Return(is_owner));
452 }
453
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));
458 }
459
460 void expect_journal_disabled(MockJournalPolicy &mock_journal_policy,
461 bool disabled) {
462 EXPECT_CALL(mock_journal_policy, journal_disabled())
463 .WillOnce(Return(disabled));
464 }
465
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));
472 }
473
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));
478 }
479
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));
486 }
487
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));
492 }
493
494 void expect_get_snap_id(MockRefreshImageCtx &mock_image_ctx,
495 const std::string &snap_name,
496 uint64_t snap_id) {
497 EXPECT_CALL(mock_image_ctx,
498 get_snap_id(_, snap_name)).WillOnce(Return(snap_id));
499 }
500
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));
504 }
505
506 void expect_unblock_writes(MockImageCtx &mock_image_ctx) {
507 EXPECT_CALL(*mock_image_ctx.io_work_queue, unblock_writes())
508 .Times(1);
509 }
510
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);
517 }));
518 }
519
520 };
521
522 TEST_F(TestMockImageRefreshRequest, SuccessV1) {
523 REQUIRE_FORMAT_V1();
524
525 librbd::ImageCtx *ictx;
526 ASSERT_EQ(0, open_image(m_image_name, &ictx));
527
528 MockRefreshImageCtx mock_image_ctx(*ictx);
529 expect_op_work_queue(mock_image_ctx);
530 expect_test_features(mock_image_ctx);
531
532 InSequence seq;
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);
537
538 C_SaferCond ctx;
539 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
540 req->send();
541
542 ASSERT_EQ(0, ctx.wait());
543 }
544
545 TEST_F(TestMockImageRefreshRequest, SuccessSnapshotV1) {
546 REQUIRE_FORMAT_V1();
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());
551
552 MockRefreshImageCtx mock_image_ctx(*ictx);
553 expect_op_work_queue(mock_image_ctx);
554 expect_test_features(mock_image_ctx);
555
556 InSequence seq;
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);
562
563 C_SaferCond ctx;
564 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
565 req->send();
566
567 ASSERT_EQ(0, ctx.wait());
568 }
569
570 TEST_F(TestMockImageRefreshRequest, SuccessV2) {
571 REQUIRE_FORMAT_V2();
572
573 librbd::ImageCtx *ictx;
574 ASSERT_EQ(0, open_image(m_image_name, &ictx));
575
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);
581
582 InSequence seq;
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, {},
589 0);
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);
595 }
596
597 C_SaferCond ctx;
598 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
599 req->send();
600
601 ASSERT_EQ(0, ctx.wait());
602 }
603
604 TEST_F(TestMockImageRefreshRequest, SuccessSnapshotV2) {
605 REQUIRE_FORMAT_V2();
606
607 librbd::ImageCtx *ictx;
608 ASSERT_EQ(0, open_image(m_image_name, &ictx));
609 ASSERT_EQ(0, snap_create(*ictx, "snap"));
610
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);
616
617 InSequence seq;
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, {},
624 0);
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);
631 }
632 expect_add_snap(mock_image_ctx, "snap", ictx->snap_ids.begin()->second);
633
634 C_SaferCond ctx;
635 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
636 req->send();
637
638 ASSERT_EQ(0, ctx.wait());
639 }
640
641 TEST_F(TestMockImageRefreshRequest, SuccessLegacySnapshotV2) {
642 REQUIRE_FORMAT_V2();
643
644 librbd::ImageCtx *ictx;
645 ASSERT_EQ(0, open_image(m_image_name, &ictx));
646 ASSERT_EQ(0, snap_create(*ictx, "snap"));
647
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);
653
654 InSequence seq;
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, {},
662 0);
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);
670 }
671 expect_add_snap(mock_image_ctx, "snap", ictx->snap_ids.begin()->second);
672
673 C_SaferCond ctx;
674 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
675 req->send();
676
677 ASSERT_EQ(0, ctx.wait());
678 }
679
680 TEST_F(TestMockImageRefreshRequest, SuccessSetSnapshotV2) {
681 REQUIRE_FORMAT_V2();
682
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(),
688 "snap"));
689
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);
695
696 InSequence seq;
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, {},
703 0);
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);
710 }
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);
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, SuccessChild) {
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 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);
752
753 InSequence seq;
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, {},
760 0);
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);
768 }
769 expect_refresh_parent_apply(*mock_refresh_parent_request);
770 expect_refresh_parent_finalize(mock_image_ctx, *mock_refresh_parent_request, 0);
771
772 C_SaferCond ctx;
773 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
774 req->send();
775
776 ASSERT_EQ(0, ctx.wait());
777 }
778
779 TEST_F(TestMockImageRefreshRequest, SuccessChildDontOpenParent) {
780 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
781
782 librbd::ImageCtx *ictx;
783 librbd::ImageCtx *ictx2 = nullptr;
784 std::string clone_name = get_temp_image_name();
785
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) {
791 close_image(ictx2);
792 }
793
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"));
797 };
798
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));
802
803 ASSERT_EQ(0, open_image(clone_name, &ictx2));
804
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);
809
810 InSequence seq;
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, {},
817 0);
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);
823 }
824
825 C_SaferCond ctx;
826 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, true, &ctx);
827 req->send();
828
829 ASSERT_EQ(0, ctx.wait());
830 }
831
832 TEST_F(TestMockImageRefreshRequest, SuccessOpFeatures) {
833 REQUIRE_FORMAT_V2();
834
835 librbd::ImageCtx *ictx;
836 ASSERT_EQ(0, open_image(m_image_name, &ictx));
837
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);
843
844 mock_image_ctx.features |= RBD_FEATURE_OPERATIONS;
845
846 InSequence seq;
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, {},
853 0);
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);
860 }
861
862 C_SaferCond ctx;
863 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
864 req->send();
865
866 ASSERT_EQ(0, ctx.wait());
867 ASSERT_EQ(4096U, mock_image_ctx.op_features);
868 ASSERT_TRUE(mock_image_ctx.operations_disabled);
869 }
870
871 TEST_F(TestMockImageRefreshRequest, DisableExclusiveLock) {
872 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
873
874 librbd::ImageCtx *ictx;
875 ASSERT_EQ(0, open_image(m_image_name, &ictx));
876
877 MockRefreshImageCtx mock_image_ctx(*ictx);
878 MockRefreshParentRequest mock_refresh_parent_request;
879
880 MockExclusiveLock mock_exclusive_lock;
881 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
882
883 MockObjectMap mock_object_map;
884 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
885 mock_image_ctx.object_map = &mock_object_map;
886 }
887
888 MockJournal mock_journal;
889 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
890 mock_image_ctx.journal = &mock_journal;
891 }
892
893 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
894 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
895 false));
896 }
897
898 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
899 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_OBJECT_MAP,
900 false));
901 }
902
903 if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
904 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_EXCLUSIVE_LOCK,
905 false));
906 }
907
908 ASSERT_EQ(0, ictx->state->refresh());
909
910 expect_op_work_queue(mock_image_ctx);
911 expect_test_features(mock_image_ctx);
912
913 // verify that exclusive lock is properly handled when object map
914 // and journaling were never enabled (or active)
915 InSequence seq;
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, {},
922 0);
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);
927
928 C_SaferCond ctx;
929 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
930 req->send();
931
932 ASSERT_EQ(0, ctx.wait());
933 }
934
935 TEST_F(TestMockImageRefreshRequest, DisableExclusiveLockWhileAcquiringLock) {
936 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
937
938 librbd::ImageCtx *ictx;
939 ASSERT_EQ(0, open_image(m_image_name, &ictx));
940
941 MockRefreshImageCtx mock_image_ctx(*ictx);
942 MockRefreshParentRequest mock_refresh_parent_request;
943
944 MockExclusiveLock mock_exclusive_lock;
945 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
946
947 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
948 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
949 false));
950 }
951
952 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
953 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_OBJECT_MAP,
954 false));
955 }
956
957 if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
958 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_EXCLUSIVE_LOCK,
959 false));
960 }
961
962 ASSERT_EQ(0, ictx->state->refresh());
963
964 expect_op_work_queue(mock_image_ctx);
965 expect_test_features(mock_image_ctx);
966
967 // verify that exclusive lock is properly handled when object map
968 // and journaling were never enabled (or active)
969 InSequence seq;
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, {},
976 0);
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);
980
981 C_SaferCond ctx;
982 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, true, false, &ctx);
983 req->send();
984
985 ASSERT_EQ(-ERESTART, ctx.wait());
986 }
987
988 TEST_F(TestMockImageRefreshRequest, JournalDisabledByPolicy) {
989 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
990
991 librbd::ImageCtx *ictx;
992 ASSERT_EQ(0, open_image(m_image_name, &ictx));
993
994 if (ictx->test_features(RBD_FEATURE_FAST_DIFF)) {
995 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_FAST_DIFF,
996 false));
997 }
998
999 ASSERT_EQ(0, ictx->state->refresh());
1000
1001 MockRefreshImageCtx mock_image_ctx(*ictx);
1002 MockRefreshParentRequest mock_refresh_parent_request;
1003
1004 MockExclusiveLock mock_exclusive_lock;
1005 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
1006
1007 MockJournal mock_journal;
1008
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);
1012
1013 InSequence seq;
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, {},
1020 0);
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);
1024
1025 MockJournalPolicy mock_journal_policy;
1026 expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
1027 expect_journal_disabled(mock_journal_policy, true);
1028
1029 C_SaferCond ctx;
1030 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
1031 req->send();
1032
1033 ASSERT_EQ(0, ctx.wait());
1034 }
1035
1036 TEST_F(TestMockImageRefreshRequest, EnableJournalWithExclusiveLock) {
1037 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
1038
1039 librbd::ImageCtx *ictx;
1040 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1041
1042 if (ictx->test_features(RBD_FEATURE_FAST_DIFF)) {
1043 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_FAST_DIFF,
1044 false));
1045 }
1046
1047 ASSERT_EQ(0, ictx->state->refresh());
1048
1049 MockRefreshImageCtx mock_image_ctx(*ictx);
1050 MockRefreshParentRequest mock_refresh_parent_request;
1051
1052 MockExclusiveLock mock_exclusive_lock;
1053 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
1054
1055 MockJournal mock_journal;
1056
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);
1060
1061 // journal should be immediately opened if exclusive lock owned
1062 InSequence seq;
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, {},
1069 0);
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);
1073
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);
1078
1079 C_SaferCond ctx;
1080 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
1081 req->send();
1082
1083 ASSERT_EQ(0, ctx.wait());
1084 }
1085
1086 TEST_F(TestMockImageRefreshRequest, EnableJournalWithoutExclusiveLock) {
1087 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
1088
1089 librbd::ImageCtx *ictx;
1090 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1091
1092 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
1093 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_OBJECT_MAP,
1094 false));
1095 }
1096
1097 ASSERT_EQ(0, ictx->state->refresh());
1098
1099 MockRefreshImageCtx mock_image_ctx(*ictx);
1100 MockRefreshParentRequest mock_refresh_parent_request;
1101
1102 MockExclusiveLock mock_exclusive_lock;
1103 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
1104
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);
1108
1109 // do not open the journal if exclusive lock is not owned
1110 InSequence seq;
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, {},
1117 0);
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);
1122
1123 C_SaferCond ctx;
1124 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
1125 req->send();
1126
1127 ASSERT_EQ(0, ctx.wait());
1128 }
1129
1130 TEST_F(TestMockImageRefreshRequest, DisableJournal) {
1131 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
1132
1133 librbd::ImageCtx *ictx;
1134 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1135
1136 MockRefreshImageCtx mock_image_ctx(*ictx);
1137 MockRefreshParentRequest mock_refresh_parent_request;
1138
1139 MockExclusiveLock mock_exclusive_lock;
1140 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
1141
1142 MockObjectMap mock_object_map;
1143 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
1144 mock_image_ctx.object_map = &mock_object_map;
1145 }
1146
1147 MockJournal mock_journal;
1148 mock_image_ctx.journal = &mock_journal;
1149
1150 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
1151 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
1152 false));
1153 }
1154
1155 ASSERT_EQ(0, ictx->state->refresh());
1156
1157 expect_op_work_queue(mock_image_ctx);
1158 expect_test_features(mock_image_ctx);
1159
1160 // verify journal is closed if feature disabled
1161 InSequence seq;
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, {},
1168 0);
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);
1175 }
1176 expect_close_journal(mock_image_ctx, mock_journal, 0);
1177 expect_unblock_writes(mock_image_ctx);
1178
1179 C_SaferCond ctx;
1180 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
1181 req->send();
1182
1183 ASSERT_EQ(0, ctx.wait());
1184 }
1185
1186 TEST_F(TestMockImageRefreshRequest, EnableObjectMapWithExclusiveLock) {
1187 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
1188
1189 librbd::ImageCtx *ictx;
1190 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1191
1192 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
1193 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
1194 false));
1195 }
1196
1197 ASSERT_EQ(0, ictx->state->refresh());
1198
1199 MockRefreshImageCtx mock_image_ctx(*ictx);
1200 MockRefreshParentRequest mock_refresh_parent_request;
1201
1202 MockExclusiveLock mock_exclusive_lock;
1203 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
1204
1205 MockObjectMap mock_object_map;
1206
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);
1210
1211 // object map should be immediately opened if exclusive lock owned
1212 InSequence seq;
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, {},
1219 0);
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);
1224
1225 C_SaferCond ctx;
1226 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
1227 req->send();
1228
1229 ASSERT_EQ(0, ctx.wait());
1230 }
1231
1232 TEST_F(TestMockImageRefreshRequest, EnableObjectMapWithoutExclusiveLock) {
1233 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
1234
1235 librbd::ImageCtx *ictx;
1236 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1237
1238 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
1239 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
1240 false));
1241 }
1242
1243 ASSERT_EQ(0, ictx->state->refresh());
1244
1245 MockRefreshImageCtx mock_image_ctx(*ictx);
1246 MockRefreshParentRequest mock_refresh_parent_request;
1247
1248 MockExclusiveLock mock_exclusive_lock;
1249 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
1250
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);
1254
1255 // do not open the object map if exclusive lock is not owned
1256 InSequence seq;
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, {},
1263 0);
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);
1267
1268 C_SaferCond ctx;
1269 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
1270 req->send();
1271
1272 ASSERT_EQ(0, ctx.wait());
1273 }
1274
1275 TEST_F(TestMockImageRefreshRequest, DisableObjectMap) {
1276 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
1277
1278 librbd::ImageCtx *ictx;
1279 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1280
1281 MockRefreshImageCtx mock_image_ctx(*ictx);
1282 MockRefreshParentRequest mock_refresh_parent_request;
1283
1284 MockExclusiveLock mock_exclusive_lock;
1285 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
1286
1287 MockObjectMap mock_object_map;
1288 mock_image_ctx.object_map = &mock_object_map;
1289
1290 MockJournal mock_journal;
1291 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
1292 mock_image_ctx.journal = &mock_journal;
1293 }
1294
1295 if (ictx->test_features(RBD_FEATURE_FAST_DIFF)) {
1296 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_FAST_DIFF,
1297 false));
1298 }
1299
1300 ASSERT_EQ(0, ictx->state->refresh());
1301
1302 expect_op_work_queue(mock_image_ctx);
1303 expect_test_features(mock_image_ctx);
1304
1305 // verify object map is closed if feature disabled
1306 InSequence seq;
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, {},
1313 0);
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);
1318
1319 C_SaferCond ctx;
1320 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
1321 req->send();
1322
1323 ASSERT_EQ(0, ctx.wait());
1324 }
1325
1326 TEST_F(TestMockImageRefreshRequest, OpenObjectMapError) {
1327 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
1328
1329 librbd::ImageCtx *ictx;
1330 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1331
1332 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
1333 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
1334 false));
1335 }
1336
1337 ASSERT_EQ(0, ictx->state->refresh());
1338
1339 MockRefreshImageCtx mock_image_ctx(*ictx);
1340 MockRefreshParentRequest mock_refresh_parent_request;
1341
1342 MockExclusiveLock mock_exclusive_lock;
1343 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
1344
1345 MockObjectMap mock_object_map;
1346
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);
1350
1351 // object map should be immediately opened if exclusive lock owned
1352 InSequence seq;
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, {},
1359 0);
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);
1364
1365 C_SaferCond ctx;
1366 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false,
1367 &ctx);
1368 req->send();
1369
1370 ASSERT_EQ(-EBLACKLISTED, ctx.wait());
1371 ASSERT_EQ(nullptr, mock_image_ctx.object_map);
1372 }
1373
1374 TEST_F(TestMockImageRefreshRequest, OpenObjectMapTooLarge) {
1375 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
1376
1377 librbd::ImageCtx *ictx;
1378 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1379
1380 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
1381 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
1382 false));
1383 }
1384
1385 ASSERT_EQ(0, ictx->state->refresh());
1386
1387 MockRefreshImageCtx mock_image_ctx(*ictx);
1388 MockRefreshParentRequest mock_refresh_parent_request;
1389
1390 MockExclusiveLock mock_exclusive_lock;
1391 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
1392
1393 MockObjectMap mock_object_map;
1394
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);
1398
1399 // object map should be immediately opened if exclusive lock owned
1400 InSequence seq;
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, {},
1407 0);
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);
1412
1413 C_SaferCond ctx;
1414 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false,
1415 &ctx);
1416 req->send();
1417
1418 ASSERT_EQ(0, ctx.wait());
1419 ASSERT_EQ(nullptr, mock_image_ctx.object_map);
1420 }
1421
1422 TEST_F(TestMockImageRefreshRequest, ApplyMetadataError) {
1423 REQUIRE_FORMAT_V2();
1424
1425 librbd::ImageCtx *ictx;
1426 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1427
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);
1433
1434 InSequence seq;
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, {},
1441 0);
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);
1447 }
1448
1449 C_SaferCond ctx;
1450 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
1451 req->send();
1452
1453 ASSERT_EQ(0, ctx.wait());
1454 }
1455
1456 TEST_F(TestMockImageRefreshRequest, NonPrimaryFeature) {
1457 REQUIRE_FORMAT_V2();
1458
1459 librbd::ImageCtx *ictx;
1460 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1461
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);
1467
1468 InSequence seq;
1469
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, {},
1478 0);
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);
1482
1483 C_SaferCond ctx1;
1484 auto req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx1);
1485 req->send();
1486
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);
1490
1491 // try again but permit R/W against non-primary image
1492 mock_image_ctx.read_only_mask = ~IMAGE_READ_ONLY_FLAG_NON_PRIMARY;
1493
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, {},
1500 0);
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);
1506 }
1507
1508 C_SaferCond ctx2;
1509 req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx2);
1510 req->send();
1511
1512 ASSERT_EQ(0, ctx2.wait());
1513 ASSERT_FALSE(mock_image_ctx.read_only);
1514 ASSERT_EQ(0U, mock_image_ctx.read_only_flags);
1515 }
1516
1517 } // namespace image
1518 } // namespace librbd