]>
Commit | Line | Data |
---|---|---|
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 | ||
26 | namespace librbd { | |
27 | ||
28 | namespace { | |
29 | ||
30 | struct MockRefreshImageCtx : public MockImageCtx { | |
31 | MockRefreshImageCtx(ImageCtx &image_ctx) : MockImageCtx(image_ctx) { | |
32 | } | |
33 | }; | |
34 | ||
35 | } // anonymous namespace | |
36 | ||
37 | namespace image { | |
38 | ||
39 | template <> | |
40 | struct RefreshParentRequest<MockRefreshImageCtx> { | |
41 | static RefreshParentRequest* s_instance; | |
42 | static RefreshParentRequest* create(MockRefreshImageCtx &mock_image_ctx, | |
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 | ||
69 | RefreshParentRequest<MockRefreshImageCtx>* RefreshParentRequest<MockRefreshImageCtx>::s_instance = nullptr; | |
70 | ||
71 | } // namespace image | |
11fdf7f2 TL |
72 | |
73 | namespace io { | |
74 | ||
75 | template <> | |
76 | struct ImageDispatchSpec<librbd::MockRefreshImageCtx> { | |
77 | static ImageDispatchSpec* s_instance; | |
78 | AioCompletion *aio_comp = nullptr; | |
79 | ||
80 | static ImageDispatchSpec* create_flush_request( | |
81 | librbd::MockRefreshImageCtx &image_ctx, AioCompletion *aio_comp, | |
82 | FlushSource flush_source, const ZTracer::Trace &parent_trace) { | |
83 | ceph_assert(s_instance != nullptr); | |
84 | s_instance->aio_comp = aio_comp; | |
85 | return s_instance; | |
86 | } | |
87 | ||
88 | MOCK_CONST_METHOD0(send, void()); | |
89 | ||
90 | ImageDispatchSpec() { | |
91 | s_instance = this; | |
92 | } | |
93 | }; | |
94 | ||
95 | ImageDispatchSpec<librbd::MockRefreshImageCtx>* ImageDispatchSpec<librbd::MockRefreshImageCtx>::s_instance = nullptr; | |
96 | ||
97 | } // namespace io | |
98 | namespace util { | |
99 | ||
100 | inline ImageCtx *get_image_ctx(librbd::MockRefreshImageCtx *image_ctx) { | |
101 | return image_ctx->image_ctx; | |
102 | } | |
103 | ||
104 | } // namespace util | |
7c673cae FG |
105 | } // namespace librbd |
106 | ||
107 | // template definitions | |
108 | #include "librbd/image/RefreshRequest.cc" | |
7c673cae FG |
109 | |
110 | ACTION_P(TestFeatures, image_ctx) { | |
111 | return ((image_ctx->features & arg0) != 0); | |
112 | } | |
113 | ||
114 | ACTION_P(ShutDownExclusiveLock, image_ctx) { | |
115 | // shutting down exclusive lock will close object map and journal | |
116 | image_ctx->exclusive_lock = nullptr; | |
117 | image_ctx->object_map = nullptr; | |
118 | image_ctx->journal = nullptr; | |
119 | } | |
120 | ||
121 | namespace librbd { | |
122 | namespace image { | |
123 | ||
124 | using ::testing::_; | |
125 | using ::testing::DoAll; | |
126 | using ::testing::DoDefault; | |
127 | using ::testing::InSequence; | |
11fdf7f2 | 128 | using ::testing::Invoke; |
7c673cae FG |
129 | using ::testing::Return; |
130 | using ::testing::WithArg; | |
131 | using ::testing::StrEq; | |
132 | ||
133 | class TestMockImageRefreshRequest : public TestMockFixture { | |
134 | public: | |
135 | typedef RefreshRequest<MockRefreshImageCtx> MockRefreshRequest; | |
136 | typedef RefreshParentRequest<MockRefreshImageCtx> MockRefreshParentRequest; | |
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 | ||
487 | TEST_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 | ||
510 | TEST_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 | ||
535 | TEST_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 | ||
565 | TEST_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 | ||
598 | TEST_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 |
633 | TEST_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 |
670 | TEST_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 | ||
707 | TEST_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 | ||
761 | TEST_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 |
810 | TEST_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 |
845 | TEST_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 | ||
905 | TEST_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 | ||
954 | TEST_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 |
998 | TEST_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 | ||
1044 | TEST_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 | ||
1084 | TEST_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 | ||
1136 | TEST_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 | ||
1178 | TEST_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 | ||
1217 | TEST_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 | ||
1264 | TEST_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 | ||
1308 | TEST_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 |
1352 | TEST_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 |