Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / 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/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
23 namespace librbd {
24
25 namespace {
26
27 struct MockRefreshImageCtx : public MockImageCtx {
28   MockRefreshImageCtx(ImageCtx &image_ctx) : MockImageCtx(image_ctx) {
29   }
30 };
31
32 } // anonymous namespace
33
34 namespace image {
35
36 template <>
37 struct 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
64 RefreshParentRequest<MockRefreshImageCtx>* RefreshParentRequest<MockRefreshImageCtx>::s_instance = nullptr;
65
66 } // namespace image
67 } // namespace librbd
68
69 // template definitions
70 #include "librbd/image/RefreshRequest.cc"
71 template class librbd::image::RefreshRequest<librbd::MockRefreshImageCtx>;
72
73 ACTION_P(TestFeatures, image_ctx) {
74   return ((image_ctx->features & arg0) != 0);
75 }
76
77 ACTION_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
84 namespace librbd {
85 namespace image {
86
87 using ::testing::_;
88 using ::testing::DoAll;
89 using ::testing::DoDefault;
90 using ::testing::InSequence;
91 using ::testing::Return;
92 using ::testing::WithArg;
93 using ::testing::StrEq;
94
95 class TestMockImageRefreshRequest : public TestMockFixture {
96 public:
97   typedef RefreshRequest<MockRefreshImageCtx> MockRefreshRequest;
98   typedef RefreshParentRequest<MockRefreshImageCtx> MockRefreshParentRequest;
99
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));
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
339 TEST_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
362 TEST_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
387 TEST_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
415 TEST_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
449 TEST_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
485 TEST_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
536 TEST_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
582 TEST_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);
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
643 TEST_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
693 TEST_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
738 TEST_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
785 TEST_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);
817   expect_set_require_lock(mock_image_ctx, librbd::io::DIRECTION_BOTH, true);
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
826 TEST_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);
861   if (!mock_image_ctx.clone_copy_on_read) {
862     expect_set_require_lock(mock_image_ctx, librbd::io::DIRECTION_READ, false);
863   }
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
874 TEST_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
912 TEST_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
947 TEST_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
995 TEST_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