1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
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/cache/MockImageCache.h"
9 #include "librbd/io/ImageRequest.h"
10 #include "librbd/io/ObjectDispatchSpec.h"
11 #include "librbd/io/Utils.h"
16 struct MockTestImageCtx
;
18 struct MockTestJournal
: public MockJournal
{
19 MOCK_METHOD4(append_write_event
, uint64_t(uint64_t, size_t,
20 const bufferlist
&, bool));
21 MOCK_METHOD5(append_compare_and_write_event
, uint64_t(uint64_t, size_t,
25 MOCK_METHOD5(append_io_event_mock
, uint64_t(const journal::EventEntry
&,
26 uint64_t, size_t, bool, int));
27 uint64_t append_io_event(journal::EventEntry
&&event_entry
,
28 uint64_t offset
, size_t length
,
29 bool flush_entry
, int filter_ret_val
) {
30 // googlemock doesn't support move semantics
31 return append_io_event_mock(event_entry
, offset
, length
, flush_entry
,
35 MOCK_METHOD2(commit_io_event
, void(uint64_t, int));
38 struct MockTestImageCtx
: public MockImageCtx
{
39 MockTestImageCtx(ImageCtx
&image_ctx
) : MockImageCtx(image_ctx
) {
42 MockTestJournal
* journal
;
45 } // anonymous namespace
49 inline ImageCtx
*get_image_ctx(MockTestImageCtx
*image_ctx
) {
50 return image_ctx
->image_ctx
;
56 #include "librbd/io/ImageRequest.cc"
64 void area_to_object_extents(MockTestImageCtx
* image_ctx
, uint64_t offset
,
65 uint64_t length
, ImageArea area
,
66 uint64_t buffer_offset
,
67 striper::LightweightObjectExtents
* object_extents
) {
68 Striper::file_to_extents(image_ctx
->cct
, &image_ctx
->layout
, offset
, length
,
69 0, buffer_offset
, object_extents
);
73 std::pair
<Extents
, ImageArea
> object_to_area_extents(
74 MockTestImageCtx
* image_ctx
, uint64_t object_no
,
75 const Extents
& object_extents
) {
77 for (auto [off
, len
] : object_extents
) {
78 Striper::extent_to_file(image_ctx
->cct
, &image_ctx
->layout
, object_no
, off
,
81 return {std::move(extents
), ImageArea::DATA
};
87 using ::testing::InSequence
;
88 using ::testing::Invoke
;
89 using ::testing::Return
;
90 using ::testing::WithArg
;
91 using ::testing::WithoutArgs
;
92 using ::testing::Exactly
;
94 struct TestMockIoImageRequest
: public TestMockFixture
{
95 typedef ImageRequest
<librbd::MockTestImageCtx
> MockImageRequest
;
96 typedef ImageReadRequest
<librbd::MockTestImageCtx
> MockImageReadRequest
;
97 typedef ImageWriteRequest
<librbd::MockTestImageCtx
> MockImageWriteRequest
;
98 typedef ImageDiscardRequest
<librbd::MockTestImageCtx
> MockImageDiscardRequest
;
99 typedef ImageFlushRequest
<librbd::MockTestImageCtx
> MockImageFlushRequest
;
100 typedef ImageWriteSameRequest
<librbd::MockTestImageCtx
> MockImageWriteSameRequest
;
101 typedef ImageCompareAndWriteRequest
<librbd::MockTestImageCtx
> MockImageCompareAndWriteRequest
;
102 typedef ImageListSnapsRequest
<librbd::MockTestImageCtx
> MockImageListSnapsRequest
;
104 void expect_is_journal_appending(MockTestJournal
&mock_journal
, bool appending
) {
105 EXPECT_CALL(mock_journal
, is_journal_appending())
106 .WillOnce(Return(appending
));
109 void expect_get_modify_timestamp(MockTestImageCtx
&mock_image_ctx
,
112 mock_image_ctx
.mtime_update_interval
= 5;
113 EXPECT_CALL(mock_image_ctx
, get_modify_timestamp())
114 .WillOnce(Return(ceph_clock_now() - utime_t(10,0)));
116 mock_image_ctx
.mtime_update_interval
= 600;
117 EXPECT_CALL(mock_image_ctx
, get_modify_timestamp())
118 .WillOnce(Return(ceph_clock_now()));
122 void expect_journal_append_io_event(MockTestJournal
&mock_journal
, uint64_t journal_tid
,
123 uint64_t offset
, size_t length
) {
124 EXPECT_CALL(mock_journal
, append_io_event_mock(_
, offset
, length
, _
, _
))
125 .WillOnce(Return(journal_tid
));
128 void expect_object_discard_request(MockTestImageCtx
&mock_image_ctx
,
129 uint64_t object_no
, uint64_t offset
,
130 uint32_t length
, int r
) {
131 EXPECT_CALL(*mock_image_ctx
.io_object_dispatcher
, send(_
))
132 .WillOnce(Invoke([&mock_image_ctx
, object_no
, offset
, length
, r
]
133 (ObjectDispatchSpec
* spec
) {
134 auto* discard_spec
= boost::get
<ObjectDispatchSpec::DiscardRequest
>(&spec
->request
);
135 ASSERT_TRUE(discard_spec
!= nullptr);
136 ASSERT_EQ(object_no
, discard_spec
->object_no
);
137 ASSERT_EQ(offset
, discard_spec
->object_off
);
138 ASSERT_EQ(length
, discard_spec
->object_len
);
140 spec
->dispatch_result
= io::DISPATCH_RESULT_COMPLETE
;
141 mock_image_ctx
.image_ctx
->op_work_queue
->queue(&spec
->dispatcher_ctx
, r
);
145 void expect_object_request_send(MockTestImageCtx
&mock_image_ctx
,
147 EXPECT_CALL(*mock_image_ctx
.io_object_dispatcher
, send(_
))
148 .WillOnce(Invoke([&mock_image_ctx
, r
](ObjectDispatchSpec
* spec
) {
149 spec
->dispatch_result
= io::DISPATCH_RESULT_COMPLETE
;
150 mock_image_ctx
.image_ctx
->op_work_queue
->queue(&spec
->dispatcher_ctx
, r
);
154 void expect_object_list_snaps_request(MockTestImageCtx
&mock_image_ctx
,
156 const SnapshotDelta
& snap_delta
,
158 EXPECT_CALL(*mock_image_ctx
.io_object_dispatcher
, send(_
))
160 Invoke([&mock_image_ctx
, object_no
, snap_delta
, r
]
161 (ObjectDispatchSpec
* spec
) {
162 auto request
= boost::get
<
163 librbd::io::ObjectDispatchSpec::ListSnapsRequest
>(
165 ASSERT_TRUE(request
!= nullptr);
166 ASSERT_EQ(object_no
, request
->object_no
);
168 *request
->snapshot_delta
= snap_delta
;
169 spec
->dispatch_result
= io::DISPATCH_RESULT_COMPLETE
;
170 mock_image_ctx
.image_ctx
->op_work_queue
->queue(&spec
->dispatcher_ctx
, r
);
175 TEST_F(TestMockIoImageRequest
, AioWriteModifyTimestamp
) {
178 librbd::ImageCtx
*ictx
;
179 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
181 MockTestImageCtx
mock_image_ctx(*ictx
);
182 MockTestJournal mock_journal
;
183 mock_image_ctx
.journal
= &mock_journal
;
185 mock_image_ctx
.mtime_update_interval
= 5;
187 utime_t dummy
= ceph_clock_now();
188 dummy
-= utime_t(10,0);
190 EXPECT_CALL(mock_image_ctx
, get_modify_timestamp())
192 .WillOnce(Return(dummy
))
193 .WillOnce(Return(dummy
))
194 .WillOnce(Return(dummy
+ utime_t(10,0)));
196 EXPECT_CALL(mock_image_ctx
, set_modify_timestamp(_
))
200 expect_is_journal_appending(mock_journal
, false);
201 expect_object_request_send(mock_image_ctx
, 0);
203 C_SaferCond aio_comp_ctx_1
, aio_comp_ctx_2
;
204 AioCompletion
*aio_comp_1
= AioCompletion::create_and_start(
205 &aio_comp_ctx_1
, ictx
, AIO_TYPE_WRITE
);
207 AioCompletion
*aio_comp_2
= AioCompletion::create_and_start(
208 &aio_comp_ctx_2
, ictx
, AIO_TYPE_WRITE
);
212 MockImageWriteRequest
mock_aio_image_write_1(
213 mock_image_ctx
, aio_comp_1
, {{0, 1}}, ImageArea::DATA
, std::move(bl
),
216 std::shared_lock owner_locker
{mock_image_ctx
.owner_lock
};
217 mock_aio_image_write_1
.send();
219 ASSERT_EQ(0, aio_comp_ctx_1
.wait());
221 expect_is_journal_appending(mock_journal
, false);
222 expect_object_request_send(mock_image_ctx
, 0);
225 MockImageWriteRequest
mock_aio_image_write_2(
226 mock_image_ctx
, aio_comp_2
, {{0, 1}}, ImageArea::DATA
, std::move(bl
),
229 std::shared_lock owner_locker
{mock_image_ctx
.owner_lock
};
230 mock_aio_image_write_2
.send();
232 ASSERT_EQ(0, aio_comp_ctx_2
.wait());
235 TEST_F(TestMockIoImageRequest
, AioReadAccessTimestamp
) {
238 librbd::ImageCtx
*ictx
;
239 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
241 MockTestImageCtx
mock_image_ctx(*ictx
);
242 MockTestJournal mock_journal
;
243 mock_image_ctx
.journal
= &mock_journal
;
245 mock_image_ctx
.atime_update_interval
= 5;
247 utime_t dummy
= ceph_clock_now();
248 dummy
-= utime_t(10,0);
250 EXPECT_CALL(mock_image_ctx
, get_access_timestamp())
252 .WillOnce(Return(dummy
))
253 .WillOnce(Return(dummy
))
254 .WillOnce(Return(dummy
+ utime_t(10,0)));
256 EXPECT_CALL(mock_image_ctx
, set_access_timestamp(_
))
260 expect_object_request_send(mock_image_ctx
, 0);
262 C_SaferCond aio_comp_ctx_1
, aio_comp_ctx_2
;
263 AioCompletion
*aio_comp_1
= AioCompletion::create_and_start(
264 &aio_comp_ctx_1
, ictx
, AIO_TYPE_READ
);
268 MockImageReadRequest
mock_aio_image_read_1(
269 mock_image_ctx
, aio_comp_1
, {{0, 1}}, ImageArea::DATA
, std::move(rr
),
270 mock_image_ctx
.get_data_io_context(), 0, 0, {});
272 std::shared_lock owner_locker
{mock_image_ctx
.owner_lock
};
273 mock_aio_image_read_1
.send();
275 ASSERT_EQ(1, aio_comp_ctx_1
.wait());
277 AioCompletion
*aio_comp_2
= AioCompletion::create_and_start(
278 &aio_comp_ctx_2
, ictx
, AIO_TYPE_READ
);
279 expect_object_request_send(mock_image_ctx
, 0);
281 MockImageReadRequest
mock_aio_image_read_2(
282 mock_image_ctx
, aio_comp_2
, {{0, 1}}, ImageArea::DATA
, std::move(rr
),
283 mock_image_ctx
.get_data_io_context(), 0, 0, {});
285 std::shared_lock owner_locker
{mock_image_ctx
.owner_lock
};
286 mock_aio_image_read_2
.send();
288 ASSERT_EQ(1, aio_comp_ctx_2
.wait());
291 TEST_F(TestMockIoImageRequest
, PartialDiscard
) {
292 librbd::ImageCtx
*ictx
;
293 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
294 ictx
->discard_granularity_bytes
= 0;
296 MockTestImageCtx
mock_image_ctx(*ictx
);
297 mock_image_ctx
.journal
= nullptr;
300 expect_get_modify_timestamp(mock_image_ctx
, false);
301 expect_object_discard_request(mock_image_ctx
, 0, 16, 63, 0);
302 expect_object_discard_request(mock_image_ctx
, 0, 84, 100, 0);
304 C_SaferCond aio_comp_ctx
;
305 AioCompletion
*aio_comp
= AioCompletion::create_and_start(
306 &aio_comp_ctx
, ictx
, AIO_TYPE_DISCARD
);
307 MockImageDiscardRequest
mock_aio_image_discard(
308 mock_image_ctx
, aio_comp
, {{16, 63}, {84, 100}}, ImageArea::DATA
,
309 ictx
->discard_granularity_bytes
, {});
311 std::shared_lock owner_locker
{mock_image_ctx
.owner_lock
};
312 mock_aio_image_discard
.send();
314 ASSERT_EQ(0, aio_comp_ctx
.wait());
317 TEST_F(TestMockIoImageRequest
, TailDiscard
) {
318 librbd::ImageCtx
*ictx
;
319 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
320 ASSERT_EQ(0, resize(ictx
, ictx
->layout
.object_size
));
321 ictx
->discard_granularity_bytes
= 2 * ictx
->layout
.object_size
;
323 MockTestImageCtx
mock_image_ctx(*ictx
);
324 mock_image_ctx
.journal
= nullptr;
327 expect_get_modify_timestamp(mock_image_ctx
, false);
328 expect_object_discard_request(
329 mock_image_ctx
, 0, ictx
->layout
.object_size
- 1024, 1024, 0);
331 C_SaferCond aio_comp_ctx
;
332 AioCompletion
*aio_comp
= AioCompletion::create_and_start(
333 &aio_comp_ctx
, ictx
, AIO_TYPE_DISCARD
);
334 MockImageDiscardRequest
mock_aio_image_discard(
335 mock_image_ctx
, aio_comp
,
336 {{ictx
->layout
.object_size
- 1024, 1024}}, ImageArea::DATA
,
337 ictx
->discard_granularity_bytes
, {});
339 std::shared_lock owner_locker
{mock_image_ctx
.owner_lock
};
340 mock_aio_image_discard
.send();
342 ASSERT_EQ(0, aio_comp_ctx
.wait());
345 TEST_F(TestMockIoImageRequest
, DiscardGranularity
) {
346 librbd::ImageCtx
*ictx
;
347 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
348 ASSERT_EQ(0, resize(ictx
, ictx
->layout
.object_size
));
349 ictx
->discard_granularity_bytes
= 32;
351 MockTestImageCtx
mock_image_ctx(*ictx
);
352 mock_image_ctx
.journal
= nullptr;
355 expect_get_modify_timestamp(mock_image_ctx
, false);
356 expect_object_discard_request(mock_image_ctx
, 0, 32, 32, 0);
357 expect_object_discard_request(mock_image_ctx
, 0, 96, 64, 0);
358 expect_object_discard_request(
359 mock_image_ctx
, 0, ictx
->layout
.object_size
- 32, 32, 0);
361 C_SaferCond aio_comp_ctx
;
362 AioCompletion
*aio_comp
= AioCompletion::create_and_start(
363 &aio_comp_ctx
, ictx
, AIO_TYPE_DISCARD
);
364 MockImageDiscardRequest
mock_aio_image_discard(
365 mock_image_ctx
, aio_comp
,
366 {{16, 63}, {96, 31}, {84, 100}, {ictx
->layout
.object_size
- 33, 33}},
367 ImageArea::DATA
, ictx
->discard_granularity_bytes
, {});
369 std::shared_lock owner_locker
{mock_image_ctx
.owner_lock
};
370 mock_aio_image_discard
.send();
372 ASSERT_EQ(0, aio_comp_ctx
.wait());
375 TEST_F(TestMockIoImageRequest
, PartialDiscardJournalAppendEnabled
) {
376 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
378 librbd::ImageCtx
*ictx
;
379 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
380 ictx
->discard_granularity_bytes
= 0;
382 MockTestImageCtx
mock_image_ctx(*ictx
);
383 MockTestJournal mock_journal
;
384 mock_image_ctx
.journal
= &mock_journal
;
387 expect_get_modify_timestamp(mock_image_ctx
, false);
388 expect_is_journal_appending(mock_journal
, true);
389 expect_journal_append_io_event(mock_journal
, 0, 16, 63);
390 expect_journal_append_io_event(mock_journal
, 1, 84, 100);
391 expect_object_discard_request(mock_image_ctx
, 0, 16, 63, 0);
392 expect_object_discard_request(mock_image_ctx
, 0, 84, 100, 0);
394 C_SaferCond aio_comp_ctx
;
395 AioCompletion
*aio_comp
= AioCompletion::create_and_start(
396 &aio_comp_ctx
, ictx
, AIO_TYPE_DISCARD
);
397 MockImageDiscardRequest
mock_aio_image_discard(
398 mock_image_ctx
, aio_comp
, {{16, 63}, {84, 100}}, ImageArea::DATA
,
399 ictx
->discard_granularity_bytes
, {});
401 std::shared_lock owner_locker
{mock_image_ctx
.owner_lock
};
402 mock_aio_image_discard
.send();
404 ASSERT_EQ(0, aio_comp_ctx
.wait());
407 TEST_F(TestMockIoImageRequest
, TailDiscardJournalAppendEnabled
) {
408 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
410 librbd::ImageCtx
*ictx
;
411 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
412 ASSERT_EQ(0, resize(ictx
, ictx
->layout
.object_size
));
413 ictx
->discard_granularity_bytes
= 2 * ictx
->layout
.object_size
;
415 MockTestImageCtx
mock_image_ctx(*ictx
);
416 MockTestJournal mock_journal
;
417 mock_image_ctx
.journal
= &mock_journal
;
420 expect_get_modify_timestamp(mock_image_ctx
, false);
421 expect_is_journal_appending(mock_journal
, true);
422 expect_journal_append_io_event(
423 mock_journal
, 0, ictx
->layout
.object_size
- 1024, 1024);
424 expect_object_discard_request(
425 mock_image_ctx
, 0, ictx
->layout
.object_size
- 1024, 1024, 0);
427 C_SaferCond aio_comp_ctx
;
428 AioCompletion
*aio_comp
= AioCompletion::create_and_start(
429 &aio_comp_ctx
, ictx
, AIO_TYPE_DISCARD
);
430 MockImageDiscardRequest
mock_aio_image_discard(
431 mock_image_ctx
, aio_comp
,
432 {{ictx
->layout
.object_size
- 1024, 1024}}, ImageArea::DATA
,
433 ictx
->discard_granularity_bytes
, {});
435 std::shared_lock owner_locker
{mock_image_ctx
.owner_lock
};
436 mock_aio_image_discard
.send();
438 ASSERT_EQ(0, aio_comp_ctx
.wait());
441 TEST_F(TestMockIoImageRequest
, PruneRequiredDiscardJournalAppendEnabled
) {
442 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
444 librbd::ImageCtx
*ictx
;
445 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
446 ictx
->discard_granularity_bytes
= 32;
448 MockTestImageCtx
mock_image_ctx(*ictx
);
449 MockTestJournal mock_journal
;
450 mock_image_ctx
.journal
= &mock_journal
;
453 expect_get_modify_timestamp(mock_image_ctx
, false);
454 expect_is_journal_appending(mock_journal
, true);
455 EXPECT_CALL(mock_journal
, append_io_event_mock(_
, _
, _
, _
, _
)).Times(0);
456 EXPECT_CALL(*mock_image_ctx
.io_object_dispatcher
, send(_
)).Times(0);
458 C_SaferCond aio_comp_ctx
;
459 AioCompletion
*aio_comp
= AioCompletion::create_and_start(
460 &aio_comp_ctx
, ictx
, AIO_TYPE_DISCARD
);
461 MockImageDiscardRequest
mock_aio_image_discard(
462 mock_image_ctx
, aio_comp
, {{96, 31}}, ImageArea::DATA
,
463 ictx
->discard_granularity_bytes
, {});
465 std::shared_lock owner_locker
{mock_image_ctx
.owner_lock
};
466 mock_aio_image_discard
.send();
468 ASSERT_EQ(0, aio_comp_ctx
.wait());
471 TEST_F(TestMockIoImageRequest
, LengthModifiedDiscardJournalAppendEnabled
) {
472 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
474 librbd::ImageCtx
*ictx
;
475 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
476 ictx
->discard_granularity_bytes
= 32;
478 MockTestImageCtx
mock_image_ctx(*ictx
);
479 MockTestJournal mock_journal
;
480 mock_image_ctx
.journal
= &mock_journal
;
483 expect_get_modify_timestamp(mock_image_ctx
, false);
484 expect_is_journal_appending(mock_journal
, true);
485 expect_journal_append_io_event(mock_journal
, 0, 32, 32);
486 expect_object_discard_request(mock_image_ctx
, 0, 32, 32, 0);
488 C_SaferCond aio_comp_ctx
;
489 AioCompletion
*aio_comp
= AioCompletion::create_and_start(
490 &aio_comp_ctx
, ictx
, AIO_TYPE_DISCARD
);
491 MockImageDiscardRequest
mock_aio_image_discard(
492 mock_image_ctx
, aio_comp
, {{16, 63}}, ImageArea::DATA
,
493 ictx
->discard_granularity_bytes
, {});
495 std::shared_lock owner_locker
{mock_image_ctx
.owner_lock
};
496 mock_aio_image_discard
.send();
498 ASSERT_EQ(0, aio_comp_ctx
.wait());
501 TEST_F(TestMockIoImageRequest
, DiscardGranularityJournalAppendEnabled
) {
502 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
504 librbd::ImageCtx
*ictx
;
505 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
506 ASSERT_EQ(0, resize(ictx
, ictx
->layout
.object_size
));
507 ictx
->discard_granularity_bytes
= 32;
509 MockTestImageCtx
mock_image_ctx(*ictx
);
510 MockTestJournal mock_journal
;
511 mock_image_ctx
.journal
= &mock_journal
;
514 expect_get_modify_timestamp(mock_image_ctx
, false);
515 expect_is_journal_appending(mock_journal
, true);
516 expect_journal_append_io_event(mock_journal
, 0, 32, 32);
517 expect_journal_append_io_event(mock_journal
, 1, 96, 64);
518 expect_journal_append_io_event(
519 mock_journal
, 2, ictx
->layout
.object_size
- 32, 32);
520 expect_object_discard_request(mock_image_ctx
, 0, 32, 32, 0);
521 expect_object_discard_request(mock_image_ctx
, 0, 96, 64, 0);
522 expect_object_discard_request(
523 mock_image_ctx
, 0, ictx
->layout
.object_size
- 32, 32, 0);
525 C_SaferCond aio_comp_ctx
;
526 AioCompletion
*aio_comp
= AioCompletion::create_and_start(
527 &aio_comp_ctx
, ictx
, AIO_TYPE_DISCARD
);
528 MockImageDiscardRequest
mock_aio_image_discard(
529 mock_image_ctx
, aio_comp
,
530 {{16, 63}, {96, 31}, {84, 100}, {ictx
->layout
.object_size
- 33, 33}},
531 ImageArea::DATA
, ictx
->discard_granularity_bytes
, {});
533 std::shared_lock owner_locker
{mock_image_ctx
.owner_lock
};
534 mock_aio_image_discard
.send();
536 ASSERT_EQ(0, aio_comp_ctx
.wait());
539 TEST_F(TestMockIoImageRequest
, AioWriteJournalAppendDisabled
) {
540 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
542 librbd::ImageCtx
*ictx
;
543 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
545 MockTestImageCtx
mock_image_ctx(*ictx
);
546 MockTestJournal mock_journal
;
547 mock_image_ctx
.journal
= &mock_journal
;
550 expect_get_modify_timestamp(mock_image_ctx
, false);
551 expect_is_journal_appending(mock_journal
, false);
552 expect_object_request_send(mock_image_ctx
, 0);
554 C_SaferCond aio_comp_ctx
;
555 AioCompletion
*aio_comp
= AioCompletion::create_and_start(
556 &aio_comp_ctx
, ictx
, AIO_TYPE_WRITE
);
560 MockImageWriteRequest
mock_aio_image_write(
561 mock_image_ctx
, aio_comp
, {{0, 1}}, ImageArea::DATA
, std::move(bl
), 0, {});
563 std::shared_lock owner_locker
{mock_image_ctx
.owner_lock
};
564 mock_aio_image_write
.send();
566 ASSERT_EQ(0, aio_comp_ctx
.wait());
569 TEST_F(TestMockIoImageRequest
, AioDiscardJournalAppendDisabled
) {
570 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
572 librbd::ImageCtx
*ictx
;
573 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
574 ictx
->discard_granularity_bytes
= 0;
576 MockTestImageCtx
mock_image_ctx(*ictx
);
577 MockTestJournal mock_journal
;
578 mock_image_ctx
.journal
= &mock_journal
;
581 expect_get_modify_timestamp(mock_image_ctx
, false);
582 expect_is_journal_appending(mock_journal
, false);
583 expect_object_request_send(mock_image_ctx
, 0);
585 C_SaferCond aio_comp_ctx
;
586 AioCompletion
*aio_comp
= AioCompletion::create_and_start(
587 &aio_comp_ctx
, ictx
, AIO_TYPE_DISCARD
);
588 MockImageDiscardRequest
mock_aio_image_discard(
589 mock_image_ctx
, aio_comp
, {{0, 1}}, ImageArea::DATA
,
590 ictx
->discard_granularity_bytes
, {});
592 std::shared_lock owner_locker
{mock_image_ctx
.owner_lock
};
593 mock_aio_image_discard
.send();
595 ASSERT_EQ(0, aio_comp_ctx
.wait());
598 TEST_F(TestMockIoImageRequest
, AioFlushJournalAppendDisabled
) {
599 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
601 librbd::ImageCtx
*ictx
;
602 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
604 MockTestImageCtx
mock_image_ctx(*ictx
);
605 MockTestJournal mock_journal
;
606 mock_image_ctx
.journal
= &mock_journal
;
608 expect_op_work_queue(mock_image_ctx
);
611 expect_is_journal_appending(mock_journal
, false);
612 expect_object_request_send(mock_image_ctx
, 0);
614 C_SaferCond aio_comp_ctx
;
615 AioCompletion
*aio_comp
= AioCompletion::create_and_start(
616 &aio_comp_ctx
, ictx
, AIO_TYPE_FLUSH
);
617 MockImageFlushRequest
mock_aio_image_flush(mock_image_ctx
, aio_comp
,
618 FLUSH_SOURCE_USER
, {});
620 std::shared_lock owner_locker
{mock_image_ctx
.owner_lock
};
621 mock_aio_image_flush
.send();
623 ASSERT_EQ(0, aio_comp_ctx
.wait());
626 TEST_F(TestMockIoImageRequest
, AioWriteSameJournalAppendDisabled
) {
627 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
629 librbd::ImageCtx
*ictx
;
630 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
632 MockTestImageCtx
mock_image_ctx(*ictx
);
633 MockTestJournal mock_journal
;
634 mock_image_ctx
.journal
= &mock_journal
;
637 expect_get_modify_timestamp(mock_image_ctx
, false);
638 expect_is_journal_appending(mock_journal
, false);
639 expect_object_request_send(mock_image_ctx
, 0);
641 C_SaferCond aio_comp_ctx
;
642 AioCompletion
*aio_comp
= AioCompletion::create_and_start(
643 &aio_comp_ctx
, ictx
, AIO_TYPE_WRITESAME
);
647 MockImageWriteSameRequest
mock_aio_image_writesame(
648 mock_image_ctx
, aio_comp
, {{0, 1}}, ImageArea::DATA
, std::move(bl
), 0, {});
650 std::shared_lock owner_locker
{mock_image_ctx
.owner_lock
};
651 mock_aio_image_writesame
.send();
653 ASSERT_EQ(0, aio_comp_ctx
.wait());
656 TEST_F(TestMockIoImageRequest
, AioCompareAndWriteJournalAppendDisabled
) {
657 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
659 librbd::ImageCtx
*ictx
;
660 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
662 MockTestImageCtx
mock_image_ctx(*ictx
);
663 MockTestJournal mock_journal
;
664 mock_image_ctx
.journal
= &mock_journal
;
667 expect_get_modify_timestamp(mock_image_ctx
, false);
668 expect_is_journal_appending(mock_journal
, false);
669 expect_object_request_send(mock_image_ctx
, 0);
671 C_SaferCond aio_comp_ctx
;
672 AioCompletion
*aio_comp
= AioCompletion::create_and_start(
673 &aio_comp_ctx
, ictx
, AIO_TYPE_COMPARE_AND_WRITE
);
678 write_bl
.append("1");
679 uint64_t mismatch_offset
;
680 MockImageCompareAndWriteRequest
mock_aio_image_write(
681 mock_image_ctx
, aio_comp
, {{0, 1}}, ImageArea::DATA
,
682 std::move(cmp_bl
), std::move(write_bl
), &mismatch_offset
, 0, {});
684 std::shared_lock owner_locker
{mock_image_ctx
.owner_lock
};
685 mock_aio_image_write
.send();
687 ASSERT_EQ(0, aio_comp_ctx
.wait());
690 TEST_F(TestMockIoImageRequest
, ListSnaps
) {
691 librbd::ImageCtx
*ictx
;
692 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
694 MockTestImageCtx
mock_image_ctx(*ictx
);
695 mock_image_ctx
.layout
.object_size
= 16384;
696 mock_image_ctx
.layout
.stripe_unit
= 4096;
697 mock_image_ctx
.layout
.stripe_count
= 2;
701 SnapshotDelta object_snapshot_delta
;
702 object_snapshot_delta
[{5,6}].insert(
703 0, 1024, {SPARSE_EXTENT_STATE_DATA
, 1024});
704 object_snapshot_delta
[{5,5}].insert(
705 4096, 4096, {SPARSE_EXTENT_STATE_ZEROED
, 4096});
706 expect_object_list_snaps_request(mock_image_ctx
, 0, object_snapshot_delta
, 0);
707 object_snapshot_delta
= {};
708 object_snapshot_delta
[{5,6}].insert(
709 1024, 3072, {SPARSE_EXTENT_STATE_DATA
, 3072});
710 object_snapshot_delta
[{5,5}].insert(
711 2048, 2048, {SPARSE_EXTENT_STATE_ZEROED
, 2048});
712 expect_object_list_snaps_request(mock_image_ctx
, 1, object_snapshot_delta
, 0);
714 SnapshotDelta snapshot_delta
;
715 C_SaferCond aio_comp_ctx
;
716 AioCompletion
*aio_comp
= AioCompletion::create_and_start(
717 &aio_comp_ctx
, ictx
, AIO_TYPE_GENERIC
);
718 MockImageListSnapsRequest
mock_image_list_snaps_request(
719 mock_image_ctx
, aio_comp
, {{0, 16384}, {16384, 16384}}, ImageArea::DATA
,
720 {0, CEPH_NOSNAP
}, 0, &snapshot_delta
, {});
722 std::shared_lock owner_locker
{mock_image_ctx
.owner_lock
};
723 mock_image_list_snaps_request
.send();
725 ASSERT_EQ(0, aio_comp_ctx
.wait());
727 SnapshotDelta expected_snapshot_delta
;
728 expected_snapshot_delta
[{5,6}].insert(
729 0, 1024, {SPARSE_EXTENT_STATE_DATA
, 1024});
730 expected_snapshot_delta
[{5,6}].insert(
731 5120, 3072, {SPARSE_EXTENT_STATE_DATA
, 3072});
732 expected_snapshot_delta
[{5,5}].insert(
733 6144, 6144, {SPARSE_EXTENT_STATE_ZEROED
, 6144});
734 ASSERT_EQ(expected_snapshot_delta
, snapshot_delta
);
738 } // namespace librbd