]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/librbd/image/test_mock_RefreshRequest.cc
import ceph nautilus 14.2.2
[ceph.git] / ceph / src / test / librbd / image / test_mock_RefreshRequest.cc
CommitLineData
7c673cae
FG
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"
11fdf7f2 7#include "test/librbd/mock/MockImageWatcher.h"
7c673cae
FG
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"
11fdf7f2 16#include "librbd/api/Image.h"
7c673cae
FG
17#include "librbd/image/RefreshRequest.h"
18#include "librbd/image/RefreshParentRequest.h"
11fdf7f2 19#include "librbd/io/ImageDispatchSpec.h"
7c673cae
FG
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
26namespace librbd {
27
28namespace {
29
30struct MockRefreshImageCtx : public MockImageCtx {
31 MockRefreshImageCtx(ImageCtx &image_ctx) : MockImageCtx(image_ctx) {
32 }
33};
34
35} // anonymous namespace
36
37namespace image {
38
39template <>
40struct RefreshParentRequest<MockRefreshImageCtx> {
41 static RefreshParentRequest* s_instance;
42 static RefreshParentRequest* create(MockRefreshImageCtx &mock_image_ctx,
11fdf7f2
TL
43 const ParentImageInfo &parent_md,
44 const MigrationInfo &migration_info,
7c673cae 45 Context *on_finish) {
11fdf7f2 46 ceph_assert(s_instance != nullptr);
7c673cae
FG
47 s_instance->on_finish = on_finish;
48 return s_instance;
49 }
50 static bool is_refresh_required(MockRefreshImageCtx &mock_image_ctx,
11fdf7f2
TL
51 const ParentImageInfo& parent_md,
52 const MigrationInfo &migration_info) {
53 ceph_assert(s_instance != nullptr);
7c673cae
FG
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
69RefreshParentRequest<MockRefreshImageCtx>* RefreshParentRequest<MockRefreshImageCtx>::s_instance = nullptr;
70
71} // namespace image
11fdf7f2
TL
72
73namespace io {
74
75template <>
76struct 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
95ImageDispatchSpec<librbd::MockRefreshImageCtx>* ImageDispatchSpec<librbd::MockRefreshImageCtx>::s_instance = nullptr;
96
97} // namespace io
98namespace util {
99
100inline ImageCtx *get_image_ctx(librbd::MockRefreshImageCtx *image_ctx) {
101 return image_ctx->image_ctx;
102}
103
104} // namespace util
7c673cae
FG
105} // namespace librbd
106
107// template definitions
108#include "librbd/image/RefreshRequest.cc"
7c673cae
FG
109
110ACTION_P(TestFeatures, image_ctx) {
111 return ((image_ctx->features & arg0) != 0);
112}
113
114ACTION_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
121namespace librbd {
122namespace image {
123
124using ::testing::_;
125using ::testing::DoAll;
126using ::testing::DoDefault;
127using ::testing::InSequence;
11fdf7f2 128using ::testing::Invoke;
7c673cae
FG
129using ::testing::Return;
130using ::testing::WithArg;
131using ::testing::StrEq;
132
133class TestMockImageRefreshRequest : public TestMockFixture {
134public:
135 typedef RefreshRequest<MockRefreshImageCtx> MockRefreshRequest;
136 typedef RefreshParentRequest<MockRefreshImageCtx> MockRefreshParentRequest;
11fdf7f2
TL
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 }
7c673cae 149
224ce89b
WB
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));
7c673cae
FG
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
11fdf7f2
TL
186 void expect_get_mutable_metadata(MockRefreshImageCtx &mock_image_ctx,
187 uint64_t features, int r) {
7c673cae
FG
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 {
11fdf7f2
TL
193 uint64_t incompatible = (
194 mock_image_ctx.read_only ? features & RBD_FEATURES_INCOMPATIBLE :
195 features & RBD_FEATURES_RW_INCOMPATIBLE);
196
7c673cae
FG
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"), _, _, _))
11fdf7f2
TL
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);
7c673cae
FG
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());
7c673cae
FG
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
11fdf7f2
TL
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
b32b8144
FG
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());
11fdf7f2
TL
267 EXPECT_CALL(*mock_image_ctx.image_watcher, is_unregistered())
268 .WillOnce(Return(false));
b32b8144
FG
269 }
270 }
271
7c673cae
FG
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
11fdf7f2
TL
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
7c673cae
FG
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"),
11fdf7f2 296 StrEq("image_group_get"), _, _, _));
7c673cae
FG
297 if (r < 0) {
298 expect.WillOnce(Return(r));
299 } else {
300 expect.WillOnce(DoDefault());
301 }
302 }
303
11fdf7f2
TL
304 void expect_get_snapshots(MockRefreshImageCtx &mock_image_ctx,
305 bool legacy_parent, int r) {
7c673cae 306 auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
11fdf7f2 307 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("snapshot_get"), _, _, _));
7c673cae
FG
308 if (r < 0) {
309 expect.WillOnce(Return(r));
310 } else {
311 expect.WillOnce(DoDefault());
11fdf7f2
TL
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);
7c673cae
FG
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
81eedcae
TL
326 void expect_get_snapshots_legacy(MockRefreshImageCtx &mock_image_ctx,
327 bool include_timestamp, int r) {
7c673cae 328 auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
11fdf7f2 329 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_snapshot_name"), _, _, _));
7c673cae
FG
330 if (r < 0) {
331 expect.WillOnce(Return(r));
332 } else {
333 expect.WillOnce(DoDefault());
11fdf7f2
TL
334 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
335 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_size"), _, _, _))
336 .WillOnce(DoDefault());
81eedcae
TL
337 if (include_timestamp) {
338 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
339 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_snapshot_timestamp"), _, _, _))
340 .WillOnce(DoDefault());
341 }
11fdf7f2
TL
342 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
343 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_parent"), _, _, _))
344 .WillOnce(DoDefault());
345 expect_get_flags(mock_image_ctx, 0);
346 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
347 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_protection_status"), _, _, _))
348 .WillOnce(DoDefault());
7c673cae
FG
349 }
350 }
351
b32b8144
FG
352 void expect_apply_metadata(MockRefreshImageCtx &mock_image_ctx,
353 int r) {
354 EXPECT_CALL(mock_image_ctx, apply_metadata(_, false))
355 .WillOnce(Return(r));
356 }
357
7c673cae
FG
358 void expect_add_snap(MockRefreshImageCtx &mock_image_ctx,
359 const std::string &snap_name, uint64_t snap_id) {
360 EXPECT_CALL(mock_image_ctx, add_snap(_, snap_name, snap_id, _, _, _, _, _));
361 }
362
363 void expect_init_exclusive_lock(MockRefreshImageCtx &mock_image_ctx,
364 MockExclusiveLock &mock_exclusive_lock,
365 int r) {
366 EXPECT_CALL(mock_image_ctx, create_exclusive_lock())
367 .WillOnce(Return(&mock_exclusive_lock));
368 EXPECT_CALL(mock_exclusive_lock, init(mock_image_ctx.features, _))
369 .WillOnce(WithArg<1>(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue)));
370 }
371
372 void expect_shut_down_exclusive_lock(MockRefreshImageCtx &mock_image_ctx,
373 MockExclusiveLock &mock_exclusive_lock,
374 int r) {
375 EXPECT_CALL(mock_exclusive_lock, shut_down(_))
376 .WillOnce(DoAll(ShutDownExclusiveLock(&mock_image_ctx),
377 CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue)));
378 }
379
380 void expect_init_layout(MockRefreshImageCtx &mock_image_ctx) {
381 EXPECT_CALL(mock_image_ctx, init_layout());
382 }
383
384 void expect_test_features(MockRefreshImageCtx &mock_image_ctx) {
385 EXPECT_CALL(mock_image_ctx, test_features(_, _))
386 .WillRepeatedly(TestFeatures(&mock_image_ctx));
387 }
388
389 void expect_refresh_parent_is_required(MockRefreshParentRequest &mock_refresh_parent_request,
390 bool required) {
391 EXPECT_CALL(mock_refresh_parent_request, is_refresh_required())
392 .WillRepeatedly(Return(required));
393 }
394
395 void expect_refresh_parent_send(MockRefreshImageCtx &mock_image_ctx,
396 MockRefreshParentRequest &mock_refresh_parent_request,
397 int r) {
398 EXPECT_CALL(mock_refresh_parent_request, send())
399 .WillOnce(FinishRequest(&mock_refresh_parent_request, r,
400 &mock_image_ctx));
401 }
402
403 void expect_refresh_parent_apply(MockRefreshParentRequest &mock_refresh_parent_request) {
404 EXPECT_CALL(mock_refresh_parent_request, apply());
405 }
406
407 void expect_refresh_parent_finalize(MockRefreshImageCtx &mock_image_ctx,
408 MockRefreshParentRequest &mock_refresh_parent_request,
409 int r) {
410 EXPECT_CALL(mock_refresh_parent_request, finalize(_))
411 .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
412 }
413
414 void expect_is_exclusive_lock_owner(MockExclusiveLock &mock_exclusive_lock,
415 bool is_owner) {
416 EXPECT_CALL(mock_exclusive_lock, is_lock_owner()).WillOnce(Return(is_owner));
417 }
418
419 void expect_get_journal_policy(MockImageCtx &mock_image_ctx,
420 MockJournalPolicy &mock_journal_policy) {
421 EXPECT_CALL(mock_image_ctx, get_journal_policy())
422 .WillOnce(Return(&mock_journal_policy));
423 }
424
425 void expect_journal_disabled(MockJournalPolicy &mock_journal_policy,
426 bool disabled) {
427 EXPECT_CALL(mock_journal_policy, journal_disabled())
428 .WillOnce(Return(disabled));
429 }
430
431 void expect_open_journal(MockRefreshImageCtx &mock_image_ctx,
432 MockJournal &mock_journal, int r) {
433 EXPECT_CALL(mock_image_ctx, create_journal())
434 .WillOnce(Return(&mock_journal));
435 EXPECT_CALL(mock_journal, open(_))
436 .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
437 }
438
439 void expect_close_journal(MockRefreshImageCtx &mock_image_ctx,
440 MockJournal &mock_journal, int r) {
441 EXPECT_CALL(mock_journal, close(_))
442 .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
443 }
444
445 void expect_open_object_map(MockRefreshImageCtx &mock_image_ctx,
446 MockObjectMap *mock_object_map, int r) {
447 EXPECT_CALL(mock_image_ctx, create_object_map(_))
448 .WillOnce(Return(mock_object_map));
449 EXPECT_CALL(*mock_object_map, open(_))
450 .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
451 }
452
453 void expect_close_object_map(MockRefreshImageCtx &mock_image_ctx,
454 MockObjectMap &mock_object_map, int r) {
455 EXPECT_CALL(mock_object_map, close(_))
456 .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
457 }
458
459 void expect_get_snap_id(MockRefreshImageCtx &mock_image_ctx,
460 const std::string &snap_name,
461 uint64_t snap_id) {
462 EXPECT_CALL(mock_image_ctx,
463 get_snap_id(_, snap_name)).WillOnce(Return(snap_id));
464 }
465
466 void expect_block_writes(MockImageCtx &mock_image_ctx, int r) {
467 EXPECT_CALL(*mock_image_ctx.io_work_queue, block_writes(_))
468 .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
469 }
470
471 void expect_unblock_writes(MockImageCtx &mock_image_ctx) {
472 EXPECT_CALL(*mock_image_ctx.io_work_queue, unblock_writes())
473 .Times(1);
474 }
475
11fdf7f2
TL
476 void expect_image_flush(MockIoImageDispatchSpec &mock_image_request, int r) {
477 EXPECT_CALL(mock_image_request, send())
478 .WillOnce(Invoke([&mock_image_request, r]() {
479 mock_image_request.aio_comp->set_request_count(1);
480 mock_image_request.aio_comp->add_request();
481 mock_image_request.aio_comp->complete_request(r);
482 }));
483 }
484
7c673cae
FG
485};
486
487TEST_F(TestMockImageRefreshRequest, SuccessV1) {
488 REQUIRE_FORMAT_V1();
489
490 librbd::ImageCtx *ictx;
491 ASSERT_EQ(0, open_image(m_image_name, &ictx));
492
493 MockRefreshImageCtx mock_image_ctx(*ictx);
494 expect_op_work_queue(mock_image_ctx);
495 expect_test_features(mock_image_ctx);
496
497 InSequence seq;
498 expect_v1_read_header(mock_image_ctx, 0);
499 expect_v1_get_snapshots(mock_image_ctx, 0);
500 expect_v1_get_locks(mock_image_ctx, 0);
501 expect_init_layout(mock_image_ctx);
502
503 C_SaferCond ctx;
504 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
505 req->send();
506
507 ASSERT_EQ(0, ctx.wait());
508}
509
510TEST_F(TestMockImageRefreshRequest, SuccessSnapshotV1) {
511 REQUIRE_FORMAT_V1();
512 librbd::ImageCtx *ictx;
513 ASSERT_EQ(0, open_image(m_image_name, &ictx));
514 ASSERT_EQ(0, snap_create(*ictx, "snap"));
515 ASSERT_EQ(0, ictx->state->refresh());
516
517 MockRefreshImageCtx mock_image_ctx(*ictx);
518 expect_op_work_queue(mock_image_ctx);
519 expect_test_features(mock_image_ctx);
520
521 InSequence seq;
522 expect_v1_read_header(mock_image_ctx, 0);
523 expect_v1_get_snapshots(mock_image_ctx, 0);
524 expect_v1_get_locks(mock_image_ctx, 0);
525 expect_init_layout(mock_image_ctx);
526 expect_add_snap(mock_image_ctx, "snap", ictx->snap_ids.begin()->second);
527
528 C_SaferCond ctx;
529 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
530 req->send();
531
532 ASSERT_EQ(0, ctx.wait());
533}
534
535TEST_F(TestMockImageRefreshRequest, SuccessV2) {
536 REQUIRE_FORMAT_V2();
537
538 librbd::ImageCtx *ictx;
539 ASSERT_EQ(0, open_image(m_image_name, &ictx));
540
541 MockRefreshImageCtx mock_image_ctx(*ictx);
542 MockRefreshParentRequest mock_refresh_parent_request;
543 MockExclusiveLock mock_exclusive_lock;
544 expect_op_work_queue(mock_image_ctx);
545 expect_test_features(mock_image_ctx);
546
547 InSequence seq;
11fdf7f2
TL
548 expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
549 expect_get_parent(mock_image_ctx, 0);
b32b8144
FG
550 expect_get_metadata(mock_image_ctx, 0);
551 expect_apply_metadata(mock_image_ctx, 0);
11fdf7f2 552 expect_get_group(mock_image_ctx, -EOPNOTSUPP);
7c673cae
FG
553 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
554 if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
555 expect_init_exclusive_lock(mock_image_ctx, mock_exclusive_lock, 0);
556 }
557
558 C_SaferCond ctx;
559 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
560 req->send();
561
562 ASSERT_EQ(0, ctx.wait());
563}
564
565TEST_F(TestMockImageRefreshRequest, SuccessSnapshotV2) {
566 REQUIRE_FORMAT_V2();
567
568 librbd::ImageCtx *ictx;
569 ASSERT_EQ(0, open_image(m_image_name, &ictx));
570 ASSERT_EQ(0, snap_create(*ictx, "snap"));
571
572 MockRefreshImageCtx mock_image_ctx(*ictx);
573 MockRefreshParentRequest mock_refresh_parent_request;
574 MockExclusiveLock mock_exclusive_lock;
575 expect_op_work_queue(mock_image_ctx);
576 expect_test_features(mock_image_ctx);
577
578 InSequence seq;
11fdf7f2
TL
579 expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
580 expect_get_parent(mock_image_ctx, 0);
b32b8144
FG
581 expect_get_metadata(mock_image_ctx, 0);
582 expect_apply_metadata(mock_image_ctx, 0);
7c673cae 583 expect_get_group(mock_image_ctx, 0);
11fdf7f2
TL
584 expect_get_snapshots(mock_image_ctx, false, 0);
585 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
586 if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
587 expect_init_exclusive_lock(mock_image_ctx, mock_exclusive_lock, 0);
588 }
589 expect_add_snap(mock_image_ctx, "snap", ictx->snap_ids.begin()->second);
590
591 C_SaferCond ctx;
592 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
593 req->send();
594
595 ASSERT_EQ(0, ctx.wait());
596}
597
598TEST_F(TestMockImageRefreshRequest, SuccessLegacySnapshotV2) {
599 REQUIRE_FORMAT_V2();
600
601 librbd::ImageCtx *ictx;
602 ASSERT_EQ(0, open_image(m_image_name, &ictx));
603 ASSERT_EQ(0, snap_create(*ictx, "snap"));
604
605 MockRefreshImageCtx mock_image_ctx(*ictx);
606 MockRefreshParentRequest mock_refresh_parent_request;
607 MockExclusiveLock mock_exclusive_lock;
608 expect_op_work_queue(mock_image_ctx);
609 expect_test_features(mock_image_ctx);
610
611 InSequence seq;
612 expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
613 expect_get_parent(mock_image_ctx, -EOPNOTSUPP);
614 expect_get_parent_legacy(mock_image_ctx, 0);
615 expect_get_metadata(mock_image_ctx, 0);
616 expect_apply_metadata(mock_image_ctx, 0);
617 expect_get_group(mock_image_ctx, 0);
618 expect_get_snapshots(mock_image_ctx, true, -EOPNOTSUPP);
81eedcae 619 expect_get_snapshots_legacy(mock_image_ctx, true, 0);
7c673cae
FG
620 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
621 if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
622 expect_init_exclusive_lock(mock_image_ctx, mock_exclusive_lock, 0);
623 }
624 expect_add_snap(mock_image_ctx, "snap", ictx->snap_ids.begin()->second);
625
626 C_SaferCond ctx;
627 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
628 req->send();
629
630 ASSERT_EQ(0, ctx.wait());
631}
632
81eedcae
TL
633TEST_F(TestMockImageRefreshRequest, SuccessLegacySnapshotNoTimestampV2) {
634 REQUIRE_FORMAT_V2();
635
636 librbd::ImageCtx *ictx;
637 ASSERT_EQ(0, open_image(m_image_name, &ictx));
638 ASSERT_EQ(0, snap_create(*ictx, "snap"));
639
640 MockRefreshImageCtx mock_image_ctx(*ictx);
641 MockRefreshParentRequest mock_refresh_parent_request;
642 MockExclusiveLock mock_exclusive_lock;
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, -EOPNOTSUPP);
649 expect_get_parent_legacy(mock_image_ctx, 0);
650 expect_get_metadata(mock_image_ctx, 0);
651 expect_apply_metadata(mock_image_ctx, 0);
652 expect_get_group(mock_image_ctx, 0);
653 expect_get_snapshots(mock_image_ctx, true, -EOPNOTSUPP);
654 expect_get_snapshots_legacy(mock_image_ctx, true, -EOPNOTSUPP);
655 expect_get_snapshots_legacy(mock_image_ctx, false, 0);
656 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
657 if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
658 expect_init_exclusive_lock(mock_image_ctx, mock_exclusive_lock, 0);
659 }
660 expect_add_snap(mock_image_ctx, "snap", ictx->snap_ids.begin()->second);
661
662 C_SaferCond ctx;
663 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
664 req->send();
665
666 ASSERT_EQ(0, ctx.wait());
667}
668
669
7c673cae
FG
670TEST_F(TestMockImageRefreshRequest, SuccessSetSnapshotV2) {
671 REQUIRE_FORMAT_V2();
672
673 librbd::ImageCtx *ictx;
674 ASSERT_EQ(0, open_image(m_image_name, &ictx));
675 ASSERT_EQ(0, snap_create(*ictx, "snap"));
11fdf7f2
TL
676 ASSERT_EQ(0, librbd::api::Image<>::snap_set(ictx,
677 cls::rbd::UserSnapshotNamespace(),
678 "snap"));
7c673cae
FG
679
680 MockRefreshImageCtx mock_image_ctx(*ictx);
681 MockRefreshParentRequest mock_refresh_parent_request;
682 MockObjectMap mock_object_map;
683 expect_op_work_queue(mock_image_ctx);
684 expect_test_features(mock_image_ctx);
685
686 InSequence seq;
11fdf7f2
TL
687 expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
688 expect_get_parent(mock_image_ctx, 0);
b32b8144
FG
689 expect_get_metadata(mock_image_ctx, 0);
690 expect_apply_metadata(mock_image_ctx, 0);
7c673cae 691 expect_get_group(mock_image_ctx, 0);
11fdf7f2 692 expect_get_snapshots(mock_image_ctx, false, 0);
7c673cae
FG
693 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
694 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
695 expect_open_object_map(mock_image_ctx, &mock_object_map, 0);
696 }
697 expect_add_snap(mock_image_ctx, "snap", ictx->snap_ids.begin()->second);
698 expect_get_snap_id(mock_image_ctx, "snap", ictx->snap_ids.begin()->second);
699
700 C_SaferCond ctx;
701 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
702 req->send();
703
704 ASSERT_EQ(0, ctx.wait());
705}
706
707TEST_F(TestMockImageRefreshRequest, SuccessChild) {
708 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
709
710 librbd::ImageCtx *ictx;
711 librbd::ImageCtx *ictx2 = nullptr;
712 std::string clone_name = get_temp_image_name();
713
714 ASSERT_EQ(0, open_image(m_image_name, &ictx));
715 ASSERT_EQ(0, snap_create(*ictx, "snap"));
716 ASSERT_EQ(0, snap_protect(*ictx, "snap"));
717 BOOST_SCOPE_EXIT_ALL((&)) {
718 if (ictx2 != nullptr) {
719 close_image(ictx2);
720 }
721
722 librbd::NoOpProgressContext no_op;
11fdf7f2 723 ASSERT_EQ(0, librbd::api::Image<>::remove(m_ioctx, clone_name, no_op));
7c673cae
FG
724 ASSERT_EQ(0, ictx->operations->snap_unprotect(cls::rbd::UserSnapshotNamespace(), "snap"));
725 };
726
727 int order = ictx->order;
728 ASSERT_EQ(0, librbd::clone(m_ioctx, m_image_name.c_str(), "snap", m_ioctx,
729 clone_name.c_str(), ictx->features, &order, 0, 0));
730
731 ASSERT_EQ(0, open_image(clone_name, &ictx2));
732
733 MockRefreshImageCtx mock_image_ctx(*ictx2);
734 MockRefreshParentRequest *mock_refresh_parent_request = new MockRefreshParentRequest();
735 MockExclusiveLock mock_exclusive_lock;
736 expect_op_work_queue(mock_image_ctx);
737 expect_test_features(mock_image_ctx);
738
739 InSequence seq;
11fdf7f2
TL
740 expect_get_mutable_metadata(mock_image_ctx, ictx2->features, 0);
741 expect_get_parent(mock_image_ctx, 0);
b32b8144
FG
742 expect_get_metadata(mock_image_ctx, 0);
743 expect_apply_metadata(mock_image_ctx, 0);
11fdf7f2 744 expect_get_op_features(mock_image_ctx, RBD_OPERATION_FEATURE_CLONE_CHILD, 0);
7c673cae
FG
745 expect_get_group(mock_image_ctx, 0);
746 expect_refresh_parent_is_required(*mock_refresh_parent_request, true);
747 expect_refresh_parent_send(mock_image_ctx, *mock_refresh_parent_request, 0);
748 if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
749 expect_init_exclusive_lock(mock_image_ctx, mock_exclusive_lock, 0);
750 }
751 expect_refresh_parent_apply(*mock_refresh_parent_request);
752 expect_refresh_parent_finalize(mock_image_ctx, *mock_refresh_parent_request, 0);
753
754 C_SaferCond ctx;
755 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
756 req->send();
757
758 ASSERT_EQ(0, ctx.wait());
759}
760
761TEST_F(TestMockImageRefreshRequest, SuccessChildDontOpenParent) {
762 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
763
764 librbd::ImageCtx *ictx;
765 librbd::ImageCtx *ictx2 = nullptr;
766 std::string clone_name = get_temp_image_name();
767
768 ASSERT_EQ(0, open_image(m_image_name, &ictx));
769 ASSERT_EQ(0, snap_create(*ictx, "snap"));
770 ASSERT_EQ(0, snap_protect(*ictx, "snap"));
771 BOOST_SCOPE_EXIT_ALL((&)) {
772 if (ictx2 != nullptr) {
773 close_image(ictx2);
774 }
775
776 librbd::NoOpProgressContext no_op;
11fdf7f2 777 ASSERT_EQ(0, librbd::api::Image<>::remove(m_ioctx, clone_name, no_op));
7c673cae
FG
778 ASSERT_EQ(0, ictx->operations->snap_unprotect(cls::rbd::UserSnapshotNamespace(), "snap"));
779 };
780
781 int order = ictx->order;
782 ASSERT_EQ(0, librbd::clone(m_ioctx, m_image_name.c_str(), "snap", m_ioctx,
783 clone_name.c_str(), ictx->features, &order, 0, 0));
784
785 ASSERT_EQ(0, open_image(clone_name, &ictx2));
786
787 MockRefreshImageCtx mock_image_ctx(*ictx2);
788 MockExclusiveLock mock_exclusive_lock;
789 expect_op_work_queue(mock_image_ctx);
790 expect_test_features(mock_image_ctx);
791
792 InSequence seq;
11fdf7f2
TL
793 expect_get_mutable_metadata(mock_image_ctx, ictx2->features, 0);
794 expect_get_parent(mock_image_ctx, 0);
b32b8144
FG
795 expect_get_metadata(mock_image_ctx, 0);
796 expect_apply_metadata(mock_image_ctx, 0);
11fdf7f2 797 expect_get_op_features(mock_image_ctx, RBD_OPERATION_FEATURE_CLONE_CHILD, 0);
7c673cae
FG
798 expect_get_group(mock_image_ctx, 0);
799 if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
800 expect_init_exclusive_lock(mock_image_ctx, mock_exclusive_lock, 0);
801 }
802
803 C_SaferCond ctx;
804 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, true, &ctx);
805 req->send();
806
807 ASSERT_EQ(0, ctx.wait());
808}
809
11fdf7f2
TL
810TEST_F(TestMockImageRefreshRequest, SuccessOpFeatures) {
811 REQUIRE_FORMAT_V2();
812
813 librbd::ImageCtx *ictx;
814 ASSERT_EQ(0, open_image(m_image_name, &ictx));
815
816 MockRefreshImageCtx mock_image_ctx(*ictx);
817 MockRefreshParentRequest mock_refresh_parent_request;
818 MockExclusiveLock mock_exclusive_lock;
819 expect_op_work_queue(mock_image_ctx);
820 expect_test_features(mock_image_ctx);
821
822 mock_image_ctx.features |= RBD_FEATURE_OPERATIONS;
823
824 InSequence seq;
825 expect_get_mutable_metadata(mock_image_ctx, mock_image_ctx.features, 0);
826 expect_get_parent(mock_image_ctx, 0);
827 expect_get_metadata(mock_image_ctx, 0);
828 expect_apply_metadata(mock_image_ctx, 0);
829 expect_get_op_features(mock_image_ctx, 4096, 0);
830 expect_get_group(mock_image_ctx, 0);
831 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
832 if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
833 expect_init_exclusive_lock(mock_image_ctx, mock_exclusive_lock, 0);
834 }
835
836 C_SaferCond ctx;
837 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
838 req->send();
839
840 ASSERT_EQ(0, ctx.wait());
841 ASSERT_EQ(4096U, mock_image_ctx.op_features);
842 ASSERT_TRUE(mock_image_ctx.operations_disabled);
843}
844
7c673cae
FG
845TEST_F(TestMockImageRefreshRequest, DisableExclusiveLock) {
846 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
847
848 librbd::ImageCtx *ictx;
849 ASSERT_EQ(0, open_image(m_image_name, &ictx));
850
851 MockRefreshImageCtx mock_image_ctx(*ictx);
852 MockRefreshParentRequest mock_refresh_parent_request;
853
854 MockExclusiveLock *mock_exclusive_lock = new MockExclusiveLock();
855 mock_image_ctx.exclusive_lock = mock_exclusive_lock;
856
857 MockObjectMap mock_object_map;
858 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
859 mock_image_ctx.object_map = &mock_object_map;
860 }
861
862 MockJournal mock_journal;
863 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
864 mock_image_ctx.journal = &mock_journal;
865 }
866
867 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
868 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
869 false));
870 }
871
7c673cae
FG
872 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
873 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_OBJECT_MAP,
874 false));
875 }
876
877 if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
878 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_EXCLUSIVE_LOCK,
879 false));
880 }
881
11fdf7f2
TL
882 ASSERT_EQ(0, ictx->state->refresh());
883
7c673cae
FG
884 expect_op_work_queue(mock_image_ctx);
885 expect_test_features(mock_image_ctx);
886
887 // verify that exclusive lock is properly handled when object map
888 // and journaling were never enabled (or active)
889 InSequence seq;
11fdf7f2
TL
890 expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
891 expect_get_parent(mock_image_ctx, 0);
b32b8144
FG
892 expect_get_metadata(mock_image_ctx, 0);
893 expect_apply_metadata(mock_image_ctx, 0);
7c673cae
FG
894 expect_get_group(mock_image_ctx, 0);
895 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
7c673cae
FG
896 expect_shut_down_exclusive_lock(mock_image_ctx, *mock_exclusive_lock, 0);
897
898 C_SaferCond ctx;
899 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
900 req->send();
901
902 ASSERT_EQ(0, ctx.wait());
903}
904
905TEST_F(TestMockImageRefreshRequest, DisableExclusiveLockWhileAcquiringLock) {
906 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
907
908 librbd::ImageCtx *ictx;
909 ASSERT_EQ(0, open_image(m_image_name, &ictx));
910
911 MockRefreshImageCtx mock_image_ctx(*ictx);
912 MockRefreshParentRequest mock_refresh_parent_request;
913
914 MockExclusiveLock mock_exclusive_lock;
915 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
916
917 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
918 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
919 false));
920 }
921
7c673cae
FG
922 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
923 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_OBJECT_MAP,
924 false));
925 }
926
927 if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
928 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_EXCLUSIVE_LOCK,
929 false));
930 }
931
11fdf7f2
TL
932 ASSERT_EQ(0, ictx->state->refresh());
933
7c673cae
FG
934 expect_op_work_queue(mock_image_ctx);
935 expect_test_features(mock_image_ctx);
936
937 // verify that exclusive lock is properly handled when object map
938 // and journaling were never enabled (or active)
939 InSequence seq;
11fdf7f2
TL
940 expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
941 expect_get_parent(mock_image_ctx, 0);
b32b8144
FG
942 expect_get_metadata(mock_image_ctx, 0);
943 expect_apply_metadata(mock_image_ctx, 0);
7c673cae
FG
944 expect_get_group(mock_image_ctx, 0);
945 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
946
947 C_SaferCond ctx;
948 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, true, false, &ctx);
949 req->send();
950
951 ASSERT_EQ(-ERESTART, ctx.wait());
952}
953
954TEST_F(TestMockImageRefreshRequest, JournalDisabledByPolicy) {
955 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
956
957 librbd::ImageCtx *ictx;
958 ASSERT_EQ(0, open_image(m_image_name, &ictx));
959
960 if (ictx->test_features(RBD_FEATURE_FAST_DIFF)) {
961 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_FAST_DIFF,
962 false));
963 }
964
11fdf7f2
TL
965 ASSERT_EQ(0, ictx->state->refresh());
966
7c673cae
FG
967 MockRefreshImageCtx mock_image_ctx(*ictx);
968 MockRefreshParentRequest mock_refresh_parent_request;
969
970 MockExclusiveLock mock_exclusive_lock;
971 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
972
973 MockJournal mock_journal;
974
975 expect_op_work_queue(mock_image_ctx);
976 expect_test_features(mock_image_ctx);
977 expect_is_exclusive_lock_owner(mock_exclusive_lock, true);
978
979 InSequence seq;
11fdf7f2
TL
980 expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
981 expect_get_parent(mock_image_ctx, 0);
b32b8144
FG
982 expect_get_metadata(mock_image_ctx, 0);
983 expect_apply_metadata(mock_image_ctx, 0);
7c673cae
FG
984 expect_get_group(mock_image_ctx, 0);
985 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
986
987 MockJournalPolicy mock_journal_policy;
988 expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
989 expect_journal_disabled(mock_journal_policy, true);
990
991 C_SaferCond ctx;
992 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
993 req->send();
994
995 ASSERT_EQ(0, ctx.wait());
996}
997
7c673cae
FG
998TEST_F(TestMockImageRefreshRequest, EnableJournalWithExclusiveLock) {
999 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
1000
1001 librbd::ImageCtx *ictx;
1002 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1003
1004 if (ictx->test_features(RBD_FEATURE_FAST_DIFF)) {
1005 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_FAST_DIFF,
1006 false));
1007 }
1008
11fdf7f2
TL
1009 ASSERT_EQ(0, ictx->state->refresh());
1010
7c673cae
FG
1011 MockRefreshImageCtx mock_image_ctx(*ictx);
1012 MockRefreshParentRequest mock_refresh_parent_request;
1013
1014 MockExclusiveLock mock_exclusive_lock;
1015 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
1016
1017 MockJournal mock_journal;
1018
1019 expect_op_work_queue(mock_image_ctx);
1020 expect_test_features(mock_image_ctx);
1021 expect_is_exclusive_lock_owner(mock_exclusive_lock, true);
1022
1023 // journal should be immediately opened if exclusive lock owned
1024 InSequence seq;
11fdf7f2
TL
1025 expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
1026 expect_get_parent(mock_image_ctx, 0);
b32b8144
FG
1027 expect_get_metadata(mock_image_ctx, 0);
1028 expect_apply_metadata(mock_image_ctx, 0);
7c673cae
FG
1029 expect_get_group(mock_image_ctx, 0);
1030 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
1031
1032 MockJournalPolicy mock_journal_policy;
1033 expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
1034 expect_journal_disabled(mock_journal_policy, false);
1035 expect_open_journal(mock_image_ctx, mock_journal, 0);
1036
1037 C_SaferCond ctx;
1038 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
1039 req->send();
1040
1041 ASSERT_EQ(0, ctx.wait());
1042}
1043
1044TEST_F(TestMockImageRefreshRequest, EnableJournalWithoutExclusiveLock) {
1045 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
1046
1047 librbd::ImageCtx *ictx;
1048 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1049
7c673cae
FG
1050 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
1051 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_OBJECT_MAP,
1052 false));
1053 }
1054
11fdf7f2
TL
1055 ASSERT_EQ(0, ictx->state->refresh());
1056
7c673cae
FG
1057 MockRefreshImageCtx mock_image_ctx(*ictx);
1058 MockRefreshParentRequest mock_refresh_parent_request;
1059
1060 MockExclusiveLock mock_exclusive_lock;
1061 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
1062
1063 expect_op_work_queue(mock_image_ctx);
1064 expect_test_features(mock_image_ctx);
1065 expect_is_exclusive_lock_owner(mock_exclusive_lock, false);
1066
1067 // do not open the journal if exclusive lock is not owned
1068 InSequence seq;
11fdf7f2
TL
1069 expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
1070 expect_get_parent(mock_image_ctx, 0);
b32b8144
FG
1071 expect_get_metadata(mock_image_ctx, 0);
1072 expect_apply_metadata(mock_image_ctx, 0);
7c673cae
FG
1073 expect_get_group(mock_image_ctx, 0);
1074 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
224ce89b 1075 expect_set_require_lock(mock_image_ctx, librbd::io::DIRECTION_BOTH, true);
7c673cae
FG
1076
1077 C_SaferCond ctx;
1078 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
1079 req->send();
1080
1081 ASSERT_EQ(0, ctx.wait());
1082}
1083
1084TEST_F(TestMockImageRefreshRequest, DisableJournal) {
1085 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
1086
1087 librbd::ImageCtx *ictx;
1088 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1089
1090 MockRefreshImageCtx mock_image_ctx(*ictx);
1091 MockRefreshParentRequest mock_refresh_parent_request;
1092
1093 MockExclusiveLock mock_exclusive_lock;
1094 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
1095
1096 MockObjectMap mock_object_map;
1097 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
1098 mock_image_ctx.object_map = &mock_object_map;
1099 }
1100
1101 MockJournal *mock_journal = new MockJournal();
1102 mock_image_ctx.journal = mock_journal;
1103
1104 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
1105 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
1106 false));
1107 }
1108
11fdf7f2
TL
1109 ASSERT_EQ(0, ictx->state->refresh());
1110
7c673cae
FG
1111 expect_op_work_queue(mock_image_ctx);
1112 expect_test_features(mock_image_ctx);
1113
1114 // verify journal is closed if feature disabled
1115 InSequence seq;
11fdf7f2
TL
1116 expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
1117 expect_get_parent(mock_image_ctx, 0);
b32b8144
FG
1118 expect_get_metadata(mock_image_ctx, 0);
1119 expect_apply_metadata(mock_image_ctx, 0);
7c673cae
FG
1120 expect_get_group(mock_image_ctx, 0);
1121 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
1122 expect_block_writes(mock_image_ctx, 0);
224ce89b
WB
1123 if (!mock_image_ctx.clone_copy_on_read) {
1124 expect_set_require_lock(mock_image_ctx, librbd::io::DIRECTION_READ, false);
1125 }
7c673cae
FG
1126 expect_close_journal(mock_image_ctx, *mock_journal, 0);
1127 expect_unblock_writes(mock_image_ctx);
1128
1129 C_SaferCond ctx;
1130 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
1131 req->send();
1132
1133 ASSERT_EQ(0, ctx.wait());
1134}
1135
1136TEST_F(TestMockImageRefreshRequest, EnableObjectMapWithExclusiveLock) {
1137 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
1138
1139 librbd::ImageCtx *ictx;
1140 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1141
1142 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
1143 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
1144 false));
1145 }
1146
11fdf7f2
TL
1147 ASSERT_EQ(0, ictx->state->refresh());
1148
7c673cae
FG
1149 MockRefreshImageCtx mock_image_ctx(*ictx);
1150 MockRefreshParentRequest mock_refresh_parent_request;
1151
1152 MockExclusiveLock mock_exclusive_lock;
1153 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
1154
1155 MockObjectMap mock_object_map;
1156
1157 expect_op_work_queue(mock_image_ctx);
1158 expect_test_features(mock_image_ctx);
1159 expect_is_exclusive_lock_owner(mock_exclusive_lock, true);
1160
1161 // object map should be immediately opened if exclusive lock owned
1162 InSequence seq;
11fdf7f2
TL
1163 expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
1164 expect_get_parent(mock_image_ctx, 0);
b32b8144
FG
1165 expect_get_metadata(mock_image_ctx, 0);
1166 expect_apply_metadata(mock_image_ctx, 0);
7c673cae
FG
1167 expect_get_group(mock_image_ctx, 0);
1168 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
1169 expect_open_object_map(mock_image_ctx, &mock_object_map, 0);
1170
1171 C_SaferCond ctx;
1172 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
1173 req->send();
1174
1175 ASSERT_EQ(0, ctx.wait());
1176}
1177
1178TEST_F(TestMockImageRefreshRequest, EnableObjectMapWithoutExclusiveLock) {
1179 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
1180
1181 librbd::ImageCtx *ictx;
1182 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1183
1184 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
1185 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
1186 false));
1187 }
1188
11fdf7f2
TL
1189 ASSERT_EQ(0, ictx->state->refresh());
1190
7c673cae
FG
1191 MockRefreshImageCtx mock_image_ctx(*ictx);
1192 MockRefreshParentRequest mock_refresh_parent_request;
1193
1194 MockExclusiveLock mock_exclusive_lock;
1195 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
1196
1197 expect_op_work_queue(mock_image_ctx);
1198 expect_test_features(mock_image_ctx);
1199 expect_is_exclusive_lock_owner(mock_exclusive_lock, false);
1200
1201 // do not open the object map if exclusive lock is not owned
1202 InSequence seq;
11fdf7f2
TL
1203 expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
1204 expect_get_parent(mock_image_ctx, 0);
b32b8144
FG
1205 expect_get_metadata(mock_image_ctx, 0);
1206 expect_apply_metadata(mock_image_ctx, 0);
7c673cae
FG
1207 expect_get_group(mock_image_ctx, 0);
1208 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
1209
1210 C_SaferCond ctx;
1211 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
1212 req->send();
1213
1214 ASSERT_EQ(0, ctx.wait());
1215}
1216
1217TEST_F(TestMockImageRefreshRequest, DisableObjectMap) {
1218 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
1219
1220 librbd::ImageCtx *ictx;
1221 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1222
1223 MockRefreshImageCtx mock_image_ctx(*ictx);
1224 MockRefreshParentRequest mock_refresh_parent_request;
1225
1226 MockExclusiveLock mock_exclusive_lock;
1227 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
1228
1229 MockObjectMap *mock_object_map = new MockObjectMap();
1230 mock_image_ctx.object_map = mock_object_map;
1231
1232 MockJournal mock_journal;
1233 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
1234 mock_image_ctx.journal = &mock_journal;
1235 }
1236
1237 if (ictx->test_features(RBD_FEATURE_FAST_DIFF)) {
1238 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_FAST_DIFF,
1239 false));
1240 }
1241
11fdf7f2
TL
1242 ASSERT_EQ(0, ictx->state->refresh());
1243
7c673cae
FG
1244 expect_op_work_queue(mock_image_ctx);
1245 expect_test_features(mock_image_ctx);
1246
1247 // verify object map is closed if feature disabled
1248 InSequence seq;
11fdf7f2
TL
1249 expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
1250 expect_get_parent(mock_image_ctx, 0);
b32b8144
FG
1251 expect_get_metadata(mock_image_ctx, 0);
1252 expect_apply_metadata(mock_image_ctx, 0);
7c673cae
FG
1253 expect_get_group(mock_image_ctx, 0);
1254 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
1255 expect_close_object_map(mock_image_ctx, *mock_object_map, 0);
1256
1257 C_SaferCond ctx;
1258 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
1259 req->send();
1260
1261 ASSERT_EQ(0, ctx.wait());
1262}
1263
1264TEST_F(TestMockImageRefreshRequest, OpenObjectMapError) {
1265 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
1266
1267 librbd::ImageCtx *ictx;
1268 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1269
1270 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
1271 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
1272 false));
1273 }
1274
11fdf7f2
TL
1275 ASSERT_EQ(0, ictx->state->refresh());
1276
1277 MockRefreshImageCtx mock_image_ctx(*ictx);
1278 MockRefreshParentRequest mock_refresh_parent_request;
1279
1280 MockExclusiveLock mock_exclusive_lock;
1281 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
1282
1283 MockObjectMap *mock_object_map = new MockObjectMap();
1284
1285 expect_op_work_queue(mock_image_ctx);
1286 expect_test_features(mock_image_ctx);
1287 expect_is_exclusive_lock_owner(mock_exclusive_lock, true);
1288
1289 // object map should be immediately opened if exclusive lock owned
1290 InSequence seq;
1291 expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
1292 expect_get_parent(mock_image_ctx, 0);
1293 expect_get_metadata(mock_image_ctx, 0);
1294 expect_apply_metadata(mock_image_ctx, 0);
1295 expect_get_group(mock_image_ctx, 0);
1296 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
1297 expect_open_object_map(mock_image_ctx, mock_object_map, -EBLACKLISTED);
1298
1299 C_SaferCond ctx;
1300 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false,
1301 &ctx);
1302 req->send();
1303
1304 ASSERT_EQ(-EBLACKLISTED, ctx.wait());
1305 ASSERT_EQ(nullptr, mock_image_ctx.object_map);
1306}
1307
1308TEST_F(TestMockImageRefreshRequest, OpenObjectMapTooLarge) {
1309 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
1310
1311 librbd::ImageCtx *ictx;
1312 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1313
1314 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
1315 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
1316 false));
1317 }
1318
1319 ASSERT_EQ(0, ictx->state->refresh());
1320
7c673cae
FG
1321 MockRefreshImageCtx mock_image_ctx(*ictx);
1322 MockRefreshParentRequest mock_refresh_parent_request;
1323
1324 MockExclusiveLock mock_exclusive_lock;
1325 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
1326
1327 MockObjectMap *mock_object_map = new MockObjectMap();
1328
1329 expect_op_work_queue(mock_image_ctx);
1330 expect_test_features(mock_image_ctx);
1331 expect_is_exclusive_lock_owner(mock_exclusive_lock, true);
1332
1333 // object map should be immediately opened if exclusive lock owned
1334 InSequence seq;
11fdf7f2
TL
1335 expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
1336 expect_get_parent(mock_image_ctx, 0);
b32b8144
FG
1337 expect_get_metadata(mock_image_ctx, 0);
1338 expect_apply_metadata(mock_image_ctx, 0);
7c673cae
FG
1339 expect_get_group(mock_image_ctx, 0);
1340 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
1341 expect_open_object_map(mock_image_ctx, mock_object_map, -EFBIG);
1342
1343 C_SaferCond ctx;
11fdf7f2
TL
1344 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false,
1345 &ctx);
7c673cae
FG
1346 req->send();
1347
1348 ASSERT_EQ(0, ctx.wait());
1349 ASSERT_EQ(nullptr, mock_image_ctx.object_map);
1350}
1351
b32b8144
FG
1352TEST_F(TestMockImageRefreshRequest, ApplyMetadataError) {
1353 REQUIRE_FORMAT_V2();
1354
1355 librbd::ImageCtx *ictx;
1356 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1357
1358 MockRefreshImageCtx mock_image_ctx(*ictx);
1359 MockRefreshParentRequest mock_refresh_parent_request;
1360 MockExclusiveLock mock_exclusive_lock;
1361 expect_op_work_queue(mock_image_ctx);
1362 expect_test_features(mock_image_ctx);
1363
1364 InSequence seq;
11fdf7f2
TL
1365 expect_get_mutable_metadata(mock_image_ctx, ictx->features, 0);
1366 expect_get_parent(mock_image_ctx, 0);
b32b8144
FG
1367 expect_get_metadata(mock_image_ctx, 0);
1368 expect_apply_metadata(mock_image_ctx, -EINVAL);
b32b8144
FG
1369 expect_get_group(mock_image_ctx, 0);
1370 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
1371 if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
1372 expect_init_exclusive_lock(mock_image_ctx, mock_exclusive_lock, 0);
1373 }
1374
1375 C_SaferCond ctx;
1376 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
1377 req->send();
1378
1379 ASSERT_EQ(0, ctx.wait());
1380}
1381
7c673cae
FG
1382} // namespace image
1383} // namespace librbd