]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/librbd/image/test_mock_RefreshRequest.cc
update sources to v12.1.1
[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"
7#include "test/librbd/mock/MockJournal.h"
8#include "test/librbd/mock/MockJournalPolicy.h"
9#include "test/librbd/mock/MockObjectMap.h"
10#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
11#include "test/librados_test_stub/MockTestMemRadosClient.h"
12#include "librbd/ImageState.h"
13#include "librbd/internal.h"
14#include "librbd/Operations.h"
15#include "librbd/image/RefreshRequest.h"
16#include "librbd/image/RefreshParentRequest.h"
17#include "gmock/gmock.h"
18#include "gtest/gtest.h"
19#include <arpa/inet.h>
20#include <list>
21#include <boost/scope_exit.hpp>
22
23namespace librbd {
24
25namespace {
26
27struct MockRefreshImageCtx : public MockImageCtx {
28 MockRefreshImageCtx(ImageCtx &image_ctx) : MockImageCtx(image_ctx) {
29 }
30};
31
32} // anonymous namespace
33
34namespace image {
35
36template <>
37struct RefreshParentRequest<MockRefreshImageCtx> {
38 static RefreshParentRequest* s_instance;
39 static RefreshParentRequest* create(MockRefreshImageCtx &mock_image_ctx,
40 const ParentInfo& parent_md,
41 Context *on_finish) {
42 assert(s_instance != nullptr);
43 s_instance->on_finish = on_finish;
44 return s_instance;
45 }
46 static bool is_refresh_required(MockRefreshImageCtx &mock_image_ctx,
47 const ParentInfo& parent_md) {
48 assert(s_instance != nullptr);
49 return s_instance->is_refresh_required();
50 }
51
52 Context *on_finish = nullptr;
53
54 RefreshParentRequest() {
55 s_instance = this;
56 }
57
58 MOCK_CONST_METHOD0(is_refresh_required, bool());
59 MOCK_METHOD0(send, void());
60 MOCK_METHOD0(apply, void());
61 MOCK_METHOD1(finalize, void(Context *));
62};
63
64RefreshParentRequest<MockRefreshImageCtx>* RefreshParentRequest<MockRefreshImageCtx>::s_instance = nullptr;
65
66} // namespace image
67} // namespace librbd
68
69// template definitions
70#include "librbd/image/RefreshRequest.cc"
71template class librbd::image::RefreshRequest<librbd::MockRefreshImageCtx>;
72
73ACTION_P(TestFeatures, image_ctx) {
74 return ((image_ctx->features & arg0) != 0);
75}
76
77ACTION_P(ShutDownExclusiveLock, image_ctx) {
78 // shutting down exclusive lock will close object map and journal
79 image_ctx->exclusive_lock = nullptr;
80 image_ctx->object_map = nullptr;
81 image_ctx->journal = nullptr;
82}
83
84namespace librbd {
85namespace image {
86
87using ::testing::_;
88using ::testing::DoAll;
89using ::testing::DoDefault;
90using ::testing::InSequence;
91using ::testing::Return;
92using ::testing::WithArg;
93using ::testing::StrEq;
94
95class TestMockImageRefreshRequest : public TestMockFixture {
96public:
97 typedef RefreshRequest<MockRefreshImageCtx> MockRefreshRequest;
98 typedef RefreshParentRequest<MockRefreshImageCtx> MockRefreshParentRequest;
99
224ce89b
WB
100 void expect_set_require_lock(MockRefreshImageCtx &mock_image_ctx,
101 librbd::io::Direction direction, bool enabled) {
102 EXPECT_CALL(*mock_image_ctx.io_work_queue, set_require_lock(direction,
103 enabled));
7c673cae
FG
104 }
105
106 void expect_v1_read_header(MockRefreshImageCtx &mock_image_ctx, int r) {
107 auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
108 read(mock_image_ctx.header_oid, _, _, _));
109 if (r < 0) {
110 expect.WillOnce(Return(r));
111 } else {
112 expect.WillOnce(DoDefault());
113 }
114 }
115
116 void expect_v1_get_snapshots(MockRefreshImageCtx &mock_image_ctx, int r) {
117 auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
118 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("snap_list"), _, _, _));
119 if (r < 0) {
120 expect.WillOnce(Return(r));
121 } else {
122 expect.WillOnce(DoDefault());
123 }
124 }
125
126 void expect_v1_get_locks(MockRefreshImageCtx &mock_image_ctx, int r) {
127 auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
128 exec(mock_image_ctx.header_oid, _, StrEq("lock"), StrEq("get_info"), _, _, _));
129 if (r < 0) {
130 expect.WillOnce(Return(r));
131 } else {
132 expect.WillOnce(DoDefault());
133 }
134 }
135
136 void expect_get_mutable_metadata(MockRefreshImageCtx &mock_image_ctx, int r) {
137 auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
138 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_size"), _, _, _));
139 if (r < 0) {
140 expect.WillOnce(Return(r));
141 } else {
142 expect.WillOnce(DoDefault());
143 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
144 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_features"), _, _, _))
145 .WillOnce(DoDefault());
146 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
147 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_snapcontext"), _, _, _))
148 .WillOnce(DoDefault());
149 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
150 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_parent"), _, _, _))
151 .WillOnce(DoDefault());
152 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
153 exec(mock_image_ctx.header_oid, _, StrEq("lock"), StrEq("get_info"), _, _, _))
154 .WillOnce(DoDefault());
155 }
156 }
157
158 void expect_get_flags(MockRefreshImageCtx &mock_image_ctx, int r) {
159 auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
160 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_flags"), _, _, _));
161 if (r < 0) {
162 expect.WillOnce(Return(r));
163 } else {
164 expect.WillOnce(DoDefault());
165 }
166 }
167
168 void expect_get_group(MockRefreshImageCtx &mock_image_ctx, int r) {
169 auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
170 exec(mock_image_ctx.header_oid, _, StrEq("rbd"),
171 StrEq("image_get_group"), _, _, _));
172 if (r < 0) {
173 expect.WillOnce(Return(r));
174 } else {
175 expect.WillOnce(DoDefault());
176 }
177 }
178
179
180 void expect_get_snapshots(MockRefreshImageCtx &mock_image_ctx, int r) {
181 auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
182 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_snapshot_name"), _, _, _));
183 if (r < 0) {
184 expect.WillOnce(Return(r));
185 } else {
186 expect.WillOnce(DoDefault());
187 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
188 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_size"), _, _, _))
189 .WillOnce(DoDefault());
190 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
191 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_parent"), _, _, _))
192 .WillOnce(DoDefault());
193 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
194 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_protection_status"), _, _, _))
195 .WillOnce(DoDefault());
196 }
197 }
198
199 void expect_snap_timestamp_list(MockRefreshImageCtx &mock_image_ctx, int r) {
200 auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
201 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_snapshot_timestamp"), _, _, _));
202 if (r < 0) {
203 expect.WillOnce(Return(r));
204 } else {
205 expect.WillOnce(DoDefault());
206 }
207 }
208
209 void expect_snap_namespace_list(MockRefreshImageCtx &mock_image_ctx, int r) {
210 auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
211 exec(mock_image_ctx.header_oid, _, StrEq("rbd"), StrEq("get_snapshot_namespace"), _, _, _));
212 if (r < 0) {
213 expect.WillOnce(Return(r));
214 } else {
215 expect.WillOnce(DoDefault());
216 }
217 }
218
219 void expect_add_snap(MockRefreshImageCtx &mock_image_ctx,
220 const std::string &snap_name, uint64_t snap_id) {
221 EXPECT_CALL(mock_image_ctx, add_snap(_, snap_name, snap_id, _, _, _, _, _));
222 }
223
224 void expect_init_exclusive_lock(MockRefreshImageCtx &mock_image_ctx,
225 MockExclusiveLock &mock_exclusive_lock,
226 int r) {
227 EXPECT_CALL(mock_image_ctx, create_exclusive_lock())
228 .WillOnce(Return(&mock_exclusive_lock));
229 EXPECT_CALL(mock_exclusive_lock, init(mock_image_ctx.features, _))
230 .WillOnce(WithArg<1>(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue)));
231 }
232
233 void expect_shut_down_exclusive_lock(MockRefreshImageCtx &mock_image_ctx,
234 MockExclusiveLock &mock_exclusive_lock,
235 int r) {
236 EXPECT_CALL(mock_exclusive_lock, shut_down(_))
237 .WillOnce(DoAll(ShutDownExclusiveLock(&mock_image_ctx),
238 CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue)));
239 }
240
241 void expect_init_layout(MockRefreshImageCtx &mock_image_ctx) {
242 EXPECT_CALL(mock_image_ctx, init_layout());
243 }
244
245 void expect_test_features(MockRefreshImageCtx &mock_image_ctx) {
246 EXPECT_CALL(mock_image_ctx, test_features(_, _))
247 .WillRepeatedly(TestFeatures(&mock_image_ctx));
248 }
249
250 void expect_refresh_parent_is_required(MockRefreshParentRequest &mock_refresh_parent_request,
251 bool required) {
252 EXPECT_CALL(mock_refresh_parent_request, is_refresh_required())
253 .WillRepeatedly(Return(required));
254 }
255
256 void expect_refresh_parent_send(MockRefreshImageCtx &mock_image_ctx,
257 MockRefreshParentRequest &mock_refresh_parent_request,
258 int r) {
259 EXPECT_CALL(mock_refresh_parent_request, send())
260 .WillOnce(FinishRequest(&mock_refresh_parent_request, r,
261 &mock_image_ctx));
262 }
263
264 void expect_refresh_parent_apply(MockRefreshParentRequest &mock_refresh_parent_request) {
265 EXPECT_CALL(mock_refresh_parent_request, apply());
266 }
267
268 void expect_refresh_parent_finalize(MockRefreshImageCtx &mock_image_ctx,
269 MockRefreshParentRequest &mock_refresh_parent_request,
270 int r) {
271 EXPECT_CALL(mock_refresh_parent_request, finalize(_))
272 .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
273 }
274
275 void expect_is_exclusive_lock_owner(MockExclusiveLock &mock_exclusive_lock,
276 bool is_owner) {
277 EXPECT_CALL(mock_exclusive_lock, is_lock_owner()).WillOnce(Return(is_owner));
278 }
279
280 void expect_get_journal_policy(MockImageCtx &mock_image_ctx,
281 MockJournalPolicy &mock_journal_policy) {
282 EXPECT_CALL(mock_image_ctx, get_journal_policy())
283 .WillOnce(Return(&mock_journal_policy));
284 }
285
286 void expect_journal_disabled(MockJournalPolicy &mock_journal_policy,
287 bool disabled) {
288 EXPECT_CALL(mock_journal_policy, journal_disabled())
289 .WillOnce(Return(disabled));
290 }
291
292 void expect_open_journal(MockRefreshImageCtx &mock_image_ctx,
293 MockJournal &mock_journal, int r) {
294 EXPECT_CALL(mock_image_ctx, create_journal())
295 .WillOnce(Return(&mock_journal));
296 EXPECT_CALL(mock_journal, open(_))
297 .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
298 }
299
300 void expect_close_journal(MockRefreshImageCtx &mock_image_ctx,
301 MockJournal &mock_journal, int r) {
302 EXPECT_CALL(mock_journal, close(_))
303 .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
304 }
305
306 void expect_open_object_map(MockRefreshImageCtx &mock_image_ctx,
307 MockObjectMap *mock_object_map, int r) {
308 EXPECT_CALL(mock_image_ctx, create_object_map(_))
309 .WillOnce(Return(mock_object_map));
310 EXPECT_CALL(*mock_object_map, open(_))
311 .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
312 }
313
314 void expect_close_object_map(MockRefreshImageCtx &mock_image_ctx,
315 MockObjectMap &mock_object_map, int r) {
316 EXPECT_CALL(mock_object_map, close(_))
317 .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
318 }
319
320 void expect_get_snap_id(MockRefreshImageCtx &mock_image_ctx,
321 const std::string &snap_name,
322 uint64_t snap_id) {
323 EXPECT_CALL(mock_image_ctx,
324 get_snap_id(_, snap_name)).WillOnce(Return(snap_id));
325 }
326
327 void expect_block_writes(MockImageCtx &mock_image_ctx, int r) {
328 EXPECT_CALL(*mock_image_ctx.io_work_queue, block_writes(_))
329 .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
330 }
331
332 void expect_unblock_writes(MockImageCtx &mock_image_ctx) {
333 EXPECT_CALL(*mock_image_ctx.io_work_queue, unblock_writes())
334 .Times(1);
335 }
336
337};
338
339TEST_F(TestMockImageRefreshRequest, SuccessV1) {
340 REQUIRE_FORMAT_V1();
341
342 librbd::ImageCtx *ictx;
343 ASSERT_EQ(0, open_image(m_image_name, &ictx));
344
345 MockRefreshImageCtx mock_image_ctx(*ictx);
346 expect_op_work_queue(mock_image_ctx);
347 expect_test_features(mock_image_ctx);
348
349 InSequence seq;
350 expect_v1_read_header(mock_image_ctx, 0);
351 expect_v1_get_snapshots(mock_image_ctx, 0);
352 expect_v1_get_locks(mock_image_ctx, 0);
353 expect_init_layout(mock_image_ctx);
354
355 C_SaferCond ctx;
356 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
357 req->send();
358
359 ASSERT_EQ(0, ctx.wait());
360}
361
362TEST_F(TestMockImageRefreshRequest, SuccessSnapshotV1) {
363 REQUIRE_FORMAT_V1();
364 librbd::ImageCtx *ictx;
365 ASSERT_EQ(0, open_image(m_image_name, &ictx));
366 ASSERT_EQ(0, snap_create(*ictx, "snap"));
367 ASSERT_EQ(0, ictx->state->refresh());
368
369 MockRefreshImageCtx mock_image_ctx(*ictx);
370 expect_op_work_queue(mock_image_ctx);
371 expect_test_features(mock_image_ctx);
372
373 InSequence seq;
374 expect_v1_read_header(mock_image_ctx, 0);
375 expect_v1_get_snapshots(mock_image_ctx, 0);
376 expect_v1_get_locks(mock_image_ctx, 0);
377 expect_init_layout(mock_image_ctx);
378 expect_add_snap(mock_image_ctx, "snap", ictx->snap_ids.begin()->second);
379
380 C_SaferCond ctx;
381 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
382 req->send();
383
384 ASSERT_EQ(0, ctx.wait());
385}
386
387TEST_F(TestMockImageRefreshRequest, SuccessV2) {
388 REQUIRE_FORMAT_V2();
389
390 librbd::ImageCtx *ictx;
391 ASSERT_EQ(0, open_image(m_image_name, &ictx));
392
393 MockRefreshImageCtx mock_image_ctx(*ictx);
394 MockRefreshParentRequest mock_refresh_parent_request;
395 MockExclusiveLock mock_exclusive_lock;
396 expect_op_work_queue(mock_image_ctx);
397 expect_test_features(mock_image_ctx);
398
399 InSequence seq;
400 expect_get_mutable_metadata(mock_image_ctx, 0);
401 expect_get_flags(mock_image_ctx, 0);
402 expect_get_group(mock_image_ctx, 0);
403 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
404 if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
405 expect_init_exclusive_lock(mock_image_ctx, mock_exclusive_lock, 0);
406 }
407
408 C_SaferCond ctx;
409 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
410 req->send();
411
412 ASSERT_EQ(0, ctx.wait());
413}
414
415TEST_F(TestMockImageRefreshRequest, SuccessSnapshotV2) {
416 REQUIRE_FORMAT_V2();
417
418 librbd::ImageCtx *ictx;
419 ASSERT_EQ(0, open_image(m_image_name, &ictx));
420 ASSERT_EQ(0, snap_create(*ictx, "snap"));
421
422 MockRefreshImageCtx mock_image_ctx(*ictx);
423 MockRefreshParentRequest mock_refresh_parent_request;
424 MockExclusiveLock mock_exclusive_lock;
425 expect_op_work_queue(mock_image_ctx);
426 expect_test_features(mock_image_ctx);
427
428 InSequence seq;
429 expect_get_mutable_metadata(mock_image_ctx, 0);
430 expect_get_flags(mock_image_ctx, 0);
431 expect_get_flags(mock_image_ctx, 0);
432 expect_get_group(mock_image_ctx, 0);
433 expect_get_snapshots(mock_image_ctx, 0);
434 expect_snap_timestamp_list(mock_image_ctx, 0);
435 expect_snap_namespace_list(mock_image_ctx, 0);
436 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
437 if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
438 expect_init_exclusive_lock(mock_image_ctx, mock_exclusive_lock, 0);
439 }
440 expect_add_snap(mock_image_ctx, "snap", ictx->snap_ids.begin()->second);
441
442 C_SaferCond ctx;
443 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
444 req->send();
445
446 ASSERT_EQ(0, ctx.wait());
447}
448
449TEST_F(TestMockImageRefreshRequest, SuccessSetSnapshotV2) {
450 REQUIRE_FORMAT_V2();
451
452 librbd::ImageCtx *ictx;
453 ASSERT_EQ(0, open_image(m_image_name, &ictx));
454 ASSERT_EQ(0, snap_create(*ictx, "snap"));
455 ASSERT_EQ(0, librbd::snap_set(ictx, cls::rbd::UserSnapshotNamespace(), "snap"));
456
457 MockRefreshImageCtx mock_image_ctx(*ictx);
458 MockRefreshParentRequest mock_refresh_parent_request;
459 MockObjectMap mock_object_map;
460 expect_op_work_queue(mock_image_ctx);
461 expect_test_features(mock_image_ctx);
462
463 InSequence seq;
464 expect_get_mutable_metadata(mock_image_ctx, 0);
465 expect_get_flags(mock_image_ctx, 0);
466 expect_get_flags(mock_image_ctx, 0);
467 expect_get_group(mock_image_ctx, 0);
468 expect_get_snapshots(mock_image_ctx, 0);
469 expect_snap_timestamp_list(mock_image_ctx, 0);
470 expect_snap_namespace_list(mock_image_ctx, 0);
471 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
472 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
473 expect_open_object_map(mock_image_ctx, &mock_object_map, 0);
474 }
475 expect_add_snap(mock_image_ctx, "snap", ictx->snap_ids.begin()->second);
476 expect_get_snap_id(mock_image_ctx, "snap", ictx->snap_ids.begin()->second);
477
478 C_SaferCond ctx;
479 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
480 req->send();
481
482 ASSERT_EQ(0, ctx.wait());
483}
484
485TEST_F(TestMockImageRefreshRequest, SuccessChild) {
486 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
487
488 librbd::ImageCtx *ictx;
489 librbd::ImageCtx *ictx2 = nullptr;
490 std::string clone_name = get_temp_image_name();
491
492 ASSERT_EQ(0, open_image(m_image_name, &ictx));
493 ASSERT_EQ(0, snap_create(*ictx, "snap"));
494 ASSERT_EQ(0, snap_protect(*ictx, "snap"));
495 BOOST_SCOPE_EXIT_ALL((&)) {
496 if (ictx2 != nullptr) {
497 close_image(ictx2);
498 }
499
500 librbd::NoOpProgressContext no_op;
501 ASSERT_EQ(0, librbd::remove(m_ioctx, clone_name, "", no_op));
502 ASSERT_EQ(0, ictx->operations->snap_unprotect(cls::rbd::UserSnapshotNamespace(), "snap"));
503 };
504
505 int order = ictx->order;
506 ASSERT_EQ(0, librbd::clone(m_ioctx, m_image_name.c_str(), "snap", m_ioctx,
507 clone_name.c_str(), ictx->features, &order, 0, 0));
508
509 ASSERT_EQ(0, open_image(clone_name, &ictx2));
510
511 MockRefreshImageCtx mock_image_ctx(*ictx2);
512 MockRefreshParentRequest *mock_refresh_parent_request = new MockRefreshParentRequest();
513 MockExclusiveLock mock_exclusive_lock;
514 expect_op_work_queue(mock_image_ctx);
515 expect_test_features(mock_image_ctx);
516
517 InSequence seq;
518 expect_get_mutable_metadata(mock_image_ctx, 0);
519 expect_get_flags(mock_image_ctx, 0);
520 expect_get_group(mock_image_ctx, 0);
521 expect_refresh_parent_is_required(*mock_refresh_parent_request, true);
522 expect_refresh_parent_send(mock_image_ctx, *mock_refresh_parent_request, 0);
523 if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
524 expect_init_exclusive_lock(mock_image_ctx, mock_exclusive_lock, 0);
525 }
526 expect_refresh_parent_apply(*mock_refresh_parent_request);
527 expect_refresh_parent_finalize(mock_image_ctx, *mock_refresh_parent_request, 0);
528
529 C_SaferCond ctx;
530 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
531 req->send();
532
533 ASSERT_EQ(0, ctx.wait());
534}
535
536TEST_F(TestMockImageRefreshRequest, SuccessChildDontOpenParent) {
537 REQUIRE_FEATURE(RBD_FEATURE_LAYERING);
538
539 librbd::ImageCtx *ictx;
540 librbd::ImageCtx *ictx2 = nullptr;
541 std::string clone_name = get_temp_image_name();
542
543 ASSERT_EQ(0, open_image(m_image_name, &ictx));
544 ASSERT_EQ(0, snap_create(*ictx, "snap"));
545 ASSERT_EQ(0, snap_protect(*ictx, "snap"));
546 BOOST_SCOPE_EXIT_ALL((&)) {
547 if (ictx2 != nullptr) {
548 close_image(ictx2);
549 }
550
551 librbd::NoOpProgressContext no_op;
552 ASSERT_EQ(0, librbd::remove(m_ioctx, clone_name, "", no_op));
553 ASSERT_EQ(0, ictx->operations->snap_unprotect(cls::rbd::UserSnapshotNamespace(), "snap"));
554 };
555
556 int order = ictx->order;
557 ASSERT_EQ(0, librbd::clone(m_ioctx, m_image_name.c_str(), "snap", m_ioctx,
558 clone_name.c_str(), ictx->features, &order, 0, 0));
559
560 ASSERT_EQ(0, open_image(clone_name, &ictx2));
561
562 MockRefreshImageCtx mock_image_ctx(*ictx2);
563 MockExclusiveLock mock_exclusive_lock;
564 expect_op_work_queue(mock_image_ctx);
565 expect_test_features(mock_image_ctx);
566
567 InSequence seq;
568 expect_get_mutable_metadata(mock_image_ctx, 0);
569 expect_get_flags(mock_image_ctx, 0);
570 expect_get_group(mock_image_ctx, 0);
571 if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
572 expect_init_exclusive_lock(mock_image_ctx, mock_exclusive_lock, 0);
573 }
574
575 C_SaferCond ctx;
576 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, true, &ctx);
577 req->send();
578
579 ASSERT_EQ(0, ctx.wait());
580}
581
582TEST_F(TestMockImageRefreshRequest, DisableExclusiveLock) {
583 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
584
585 librbd::ImageCtx *ictx;
586 ASSERT_EQ(0, open_image(m_image_name, &ictx));
587
588 MockRefreshImageCtx mock_image_ctx(*ictx);
589 MockRefreshParentRequest mock_refresh_parent_request;
590
591 MockExclusiveLock *mock_exclusive_lock = new MockExclusiveLock();
592 mock_image_ctx.exclusive_lock = mock_exclusive_lock;
593
594 MockObjectMap mock_object_map;
595 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
596 mock_image_ctx.object_map = &mock_object_map;
597 }
598
599 MockJournal mock_journal;
600 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
601 mock_image_ctx.journal = &mock_journal;
602 }
603
604 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
605 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
606 false));
607 }
608
609 if (ictx->test_features(RBD_FEATURE_FAST_DIFF)) {
610 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_FAST_DIFF,
611 false));
612 }
613
614 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
615 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_OBJECT_MAP,
616 false));
617 }
618
619 if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
620 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_EXCLUSIVE_LOCK,
621 false));
622 }
623
624 expect_op_work_queue(mock_image_ctx);
625 expect_test_features(mock_image_ctx);
626
627 // verify that exclusive lock is properly handled when object map
628 // and journaling were never enabled (or active)
629 InSequence seq;
630 expect_get_mutable_metadata(mock_image_ctx, 0);
631 expect_get_flags(mock_image_ctx, 0);
632 expect_get_group(mock_image_ctx, 0);
633 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
7c673cae
FG
634 expect_shut_down_exclusive_lock(mock_image_ctx, *mock_exclusive_lock, 0);
635
636 C_SaferCond ctx;
637 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
638 req->send();
639
640 ASSERT_EQ(0, ctx.wait());
641}
642
643TEST_F(TestMockImageRefreshRequest, DisableExclusiveLockWhileAcquiringLock) {
644 REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
645
646 librbd::ImageCtx *ictx;
647 ASSERT_EQ(0, open_image(m_image_name, &ictx));
648
649 MockRefreshImageCtx mock_image_ctx(*ictx);
650 MockRefreshParentRequest mock_refresh_parent_request;
651
652 MockExclusiveLock mock_exclusive_lock;
653 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
654
655 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
656 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
657 false));
658 }
659
660 if (ictx->test_features(RBD_FEATURE_FAST_DIFF)) {
661 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_FAST_DIFF,
662 false));
663 }
664
665 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
666 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_OBJECT_MAP,
667 false));
668 }
669
670 if (ictx->test_features(RBD_FEATURE_EXCLUSIVE_LOCK)) {
671 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_EXCLUSIVE_LOCK,
672 false));
673 }
674
675 expect_op_work_queue(mock_image_ctx);
676 expect_test_features(mock_image_ctx);
677
678 // verify that exclusive lock is properly handled when object map
679 // and journaling were never enabled (or active)
680 InSequence seq;
681 expect_get_mutable_metadata(mock_image_ctx, 0);
682 expect_get_flags(mock_image_ctx, 0);
683 expect_get_group(mock_image_ctx, 0);
684 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
685
686 C_SaferCond ctx;
687 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, true, false, &ctx);
688 req->send();
689
690 ASSERT_EQ(-ERESTART, ctx.wait());
691}
692
693TEST_F(TestMockImageRefreshRequest, JournalDisabledByPolicy) {
694 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
695
696 librbd::ImageCtx *ictx;
697 ASSERT_EQ(0, open_image(m_image_name, &ictx));
698
699 if (ictx->test_features(RBD_FEATURE_FAST_DIFF)) {
700 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_FAST_DIFF,
701 false));
702 }
703
704 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
705 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_OBJECT_MAP,
706 false));
707 }
708
709 MockRefreshImageCtx mock_image_ctx(*ictx);
710 MockRefreshParentRequest mock_refresh_parent_request;
711
712 MockExclusiveLock mock_exclusive_lock;
713 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
714
715 MockJournal mock_journal;
716
717 expect_op_work_queue(mock_image_ctx);
718 expect_test_features(mock_image_ctx);
719 expect_is_exclusive_lock_owner(mock_exclusive_lock, true);
720
721 InSequence seq;
722 expect_get_mutable_metadata(mock_image_ctx, 0);
723 expect_get_flags(mock_image_ctx, 0);
724 expect_get_group(mock_image_ctx, 0);
725 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
726
727 MockJournalPolicy mock_journal_policy;
728 expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
729 expect_journal_disabled(mock_journal_policy, true);
730
731 C_SaferCond ctx;
732 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
733 req->send();
734
735 ASSERT_EQ(0, ctx.wait());
736}
737
7c673cae
FG
738TEST_F(TestMockImageRefreshRequest, EnableJournalWithExclusiveLock) {
739 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
740
741 librbd::ImageCtx *ictx;
742 ASSERT_EQ(0, open_image(m_image_name, &ictx));
743
744 if (ictx->test_features(RBD_FEATURE_FAST_DIFF)) {
745 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_FAST_DIFF,
746 false));
747 }
748
749 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
750 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_OBJECT_MAP,
751 false));
752 }
753
754 MockRefreshImageCtx mock_image_ctx(*ictx);
755 MockRefreshParentRequest mock_refresh_parent_request;
756
757 MockExclusiveLock mock_exclusive_lock;
758 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
759
760 MockJournal mock_journal;
761
762 expect_op_work_queue(mock_image_ctx);
763 expect_test_features(mock_image_ctx);
764 expect_is_exclusive_lock_owner(mock_exclusive_lock, true);
765
766 // journal should be immediately opened if exclusive lock owned
767 InSequence seq;
768 expect_get_mutable_metadata(mock_image_ctx, 0);
769 expect_get_flags(mock_image_ctx, 0);
770 expect_get_group(mock_image_ctx, 0);
771 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
772
773 MockJournalPolicy mock_journal_policy;
774 expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
775 expect_journal_disabled(mock_journal_policy, false);
776 expect_open_journal(mock_image_ctx, mock_journal, 0);
777
778 C_SaferCond ctx;
779 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
780 req->send();
781
782 ASSERT_EQ(0, ctx.wait());
783}
784
785TEST_F(TestMockImageRefreshRequest, EnableJournalWithoutExclusiveLock) {
786 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
787
788 librbd::ImageCtx *ictx;
789 ASSERT_EQ(0, open_image(m_image_name, &ictx));
790
791 if (ictx->test_features(RBD_FEATURE_FAST_DIFF)) {
792 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_FAST_DIFF,
793 false));
794 }
795
796 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
797 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_OBJECT_MAP,
798 false));
799 }
800
801 MockRefreshImageCtx mock_image_ctx(*ictx);
802 MockRefreshParentRequest mock_refresh_parent_request;
803
804 MockExclusiveLock mock_exclusive_lock;
805 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
806
807 expect_op_work_queue(mock_image_ctx);
808 expect_test_features(mock_image_ctx);
809 expect_is_exclusive_lock_owner(mock_exclusive_lock, false);
810
811 // do not open the journal if exclusive lock is not owned
812 InSequence seq;
813 expect_get_mutable_metadata(mock_image_ctx, 0);
814 expect_get_flags(mock_image_ctx, 0);
815 expect_get_group(mock_image_ctx, 0);
816 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
224ce89b 817 expect_set_require_lock(mock_image_ctx, librbd::io::DIRECTION_BOTH, true);
7c673cae
FG
818
819 C_SaferCond ctx;
820 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
821 req->send();
822
823 ASSERT_EQ(0, ctx.wait());
824}
825
826TEST_F(TestMockImageRefreshRequest, DisableJournal) {
827 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING);
828
829 librbd::ImageCtx *ictx;
830 ASSERT_EQ(0, open_image(m_image_name, &ictx));
831
832 MockRefreshImageCtx mock_image_ctx(*ictx);
833 MockRefreshParentRequest mock_refresh_parent_request;
834
835 MockExclusiveLock mock_exclusive_lock;
836 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
837
838 MockObjectMap mock_object_map;
839 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
840 mock_image_ctx.object_map = &mock_object_map;
841 }
842
843 MockJournal *mock_journal = new MockJournal();
844 mock_image_ctx.journal = mock_journal;
845
846 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
847 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
848 false));
849 }
850
851 expect_op_work_queue(mock_image_ctx);
852 expect_test_features(mock_image_ctx);
853
854 // verify journal is closed if feature disabled
855 InSequence seq;
856 expect_get_mutable_metadata(mock_image_ctx, 0);
857 expect_get_flags(mock_image_ctx, 0);
858 expect_get_group(mock_image_ctx, 0);
859 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
860 expect_block_writes(mock_image_ctx, 0);
224ce89b
WB
861 if (!mock_image_ctx.clone_copy_on_read) {
862 expect_set_require_lock(mock_image_ctx, librbd::io::DIRECTION_READ, false);
863 }
7c673cae
FG
864 expect_close_journal(mock_image_ctx, *mock_journal, 0);
865 expect_unblock_writes(mock_image_ctx);
866
867 C_SaferCond ctx;
868 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
869 req->send();
870
871 ASSERT_EQ(0, ctx.wait());
872}
873
874TEST_F(TestMockImageRefreshRequest, EnableObjectMapWithExclusiveLock) {
875 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
876
877 librbd::ImageCtx *ictx;
878 ASSERT_EQ(0, open_image(m_image_name, &ictx));
879
880 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
881 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
882 false));
883 }
884
885 MockRefreshImageCtx mock_image_ctx(*ictx);
886 MockRefreshParentRequest mock_refresh_parent_request;
887
888 MockExclusiveLock mock_exclusive_lock;
889 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
890
891 MockObjectMap mock_object_map;
892
893 expect_op_work_queue(mock_image_ctx);
894 expect_test_features(mock_image_ctx);
895 expect_is_exclusive_lock_owner(mock_exclusive_lock, true);
896
897 // object map should be immediately opened if exclusive lock owned
898 InSequence seq;
899 expect_get_mutable_metadata(mock_image_ctx, 0);
900 expect_get_flags(mock_image_ctx, 0);
901 expect_get_group(mock_image_ctx, 0);
902 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
903 expect_open_object_map(mock_image_ctx, &mock_object_map, 0);
904
905 C_SaferCond ctx;
906 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
907 req->send();
908
909 ASSERT_EQ(0, ctx.wait());
910}
911
912TEST_F(TestMockImageRefreshRequest, EnableObjectMapWithoutExclusiveLock) {
913 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
914
915 librbd::ImageCtx *ictx;
916 ASSERT_EQ(0, open_image(m_image_name, &ictx));
917
918 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
919 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
920 false));
921 }
922
923 MockRefreshImageCtx mock_image_ctx(*ictx);
924 MockRefreshParentRequest mock_refresh_parent_request;
925
926 MockExclusiveLock mock_exclusive_lock;
927 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
928
929 expect_op_work_queue(mock_image_ctx);
930 expect_test_features(mock_image_ctx);
931 expect_is_exclusive_lock_owner(mock_exclusive_lock, false);
932
933 // do not open the object map if exclusive lock is not owned
934 InSequence seq;
935 expect_get_mutable_metadata(mock_image_ctx, 0);
936 expect_get_flags(mock_image_ctx, 0);
937 expect_get_group(mock_image_ctx, 0);
938 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
939
940 C_SaferCond ctx;
941 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
942 req->send();
943
944 ASSERT_EQ(0, ctx.wait());
945}
946
947TEST_F(TestMockImageRefreshRequest, DisableObjectMap) {
948 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
949
950 librbd::ImageCtx *ictx;
951 ASSERT_EQ(0, open_image(m_image_name, &ictx));
952
953 MockRefreshImageCtx mock_image_ctx(*ictx);
954 MockRefreshParentRequest mock_refresh_parent_request;
955
956 MockExclusiveLock mock_exclusive_lock;
957 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
958
959 MockObjectMap *mock_object_map = new MockObjectMap();
960 mock_image_ctx.object_map = mock_object_map;
961
962 MockJournal mock_journal;
963 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
964 mock_image_ctx.journal = &mock_journal;
965 }
966
967 if (ictx->test_features(RBD_FEATURE_FAST_DIFF)) {
968 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_FAST_DIFF,
969 false));
970 }
971
972 if (ictx->test_features(RBD_FEATURE_OBJECT_MAP)) {
973 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_OBJECT_MAP,
974 false));
975 }
976
977 expect_op_work_queue(mock_image_ctx);
978 expect_test_features(mock_image_ctx);
979
980 // verify object map is closed if feature disabled
981 InSequence seq;
982 expect_get_mutable_metadata(mock_image_ctx, 0);
983 expect_get_flags(mock_image_ctx, 0);
984 expect_get_group(mock_image_ctx, 0);
985 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
986 expect_close_object_map(mock_image_ctx, *mock_object_map, 0);
987
988 C_SaferCond ctx;
989 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
990 req->send();
991
992 ASSERT_EQ(0, ctx.wait());
993}
994
995TEST_F(TestMockImageRefreshRequest, OpenObjectMapError) {
996 REQUIRE_FEATURE(RBD_FEATURE_OBJECT_MAP);
997
998 librbd::ImageCtx *ictx;
999 ASSERT_EQ(0, open_image(m_image_name, &ictx));
1000
1001 if (ictx->test_features(RBD_FEATURE_JOURNALING)) {
1002 ASSERT_EQ(0, ictx->operations->update_features(RBD_FEATURE_JOURNALING,
1003 false));
1004 }
1005
1006 MockRefreshImageCtx mock_image_ctx(*ictx);
1007 MockRefreshParentRequest mock_refresh_parent_request;
1008
1009 MockExclusiveLock mock_exclusive_lock;
1010 mock_image_ctx.exclusive_lock = &mock_exclusive_lock;
1011
1012 MockObjectMap *mock_object_map = new MockObjectMap();
1013
1014 expect_op_work_queue(mock_image_ctx);
1015 expect_test_features(mock_image_ctx);
1016 expect_is_exclusive_lock_owner(mock_exclusive_lock, true);
1017
1018 // object map should be immediately opened if exclusive lock owned
1019 InSequence seq;
1020 expect_get_mutable_metadata(mock_image_ctx, 0);
1021 expect_get_flags(mock_image_ctx, 0);
1022 expect_get_group(mock_image_ctx, 0);
1023 expect_refresh_parent_is_required(mock_refresh_parent_request, false);
1024 expect_open_object_map(mock_image_ctx, mock_object_map, -EFBIG);
1025
1026 C_SaferCond ctx;
1027 MockRefreshRequest *req = new MockRefreshRequest(mock_image_ctx, false, false, &ctx);
1028 req->send();
1029
1030 ASSERT_EQ(0, ctx.wait());
1031 ASSERT_EQ(nullptr, mock_image_ctx.object_map);
1032}
1033
1034} // namespace image
1035} // namespace librbd