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