1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "test/rbd_mirror/test_mock_fixture.h"
5 #include "include/interval_set.h"
6 #include "include/rbd/librbd.hpp"
7 #include "include/rbd/object_map_types.h"
8 #include "librbd/ImageCtx.h"
9 #include "librbd/ImageState.h"
10 #include "librbd/internal.h"
11 #include "librbd/Operations.h"
12 #include "librbd/io/ImageRequestWQ.h"
13 #include "librbd/io/ReadResult.h"
14 #include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
15 #include "test/librbd/mock/MockImageCtx.h"
16 #include "tools/rbd_mirror/Threads.h"
17 #include "tools/rbd_mirror/image_sync/ObjectCopyRequest.h"
22 struct MockTestImageCtx
: public librbd::MockImageCtx
{
23 MockTestImageCtx(librbd::ImageCtx
&image_ctx
)
24 : librbd::MockImageCtx(image_ctx
) {
28 } // anonymous namespace
31 // template definitions
32 #include "tools/rbd_mirror/image_sync/ObjectCopyRequest.cc"
33 template class rbd::mirror::image_sync::ObjectCopyRequest
<librbd::MockTestImageCtx
>;
35 bool operator==(const SnapContext
& rhs
, const SnapContext
& lhs
) {
36 return (rhs
.seq
== lhs
.seq
&& rhs
.snaps
== lhs
.snaps
);
41 namespace image_sync
{
44 using ::testing::DoAll
;
45 using ::testing::DoDefault
;
46 using ::testing::InSequence
;
47 using ::testing::Invoke
;
48 using ::testing::Return
;
49 using ::testing::ReturnNew
;
50 using ::testing::WithArg
;
54 void scribble(librbd::ImageCtx
*image_ctx
, int num_ops
, size_t max_size
,
55 interval_set
<uint64_t> *what
)
57 uint64_t object_size
= 1 << image_ctx
->order
;
58 for (int i
=0; i
<num_ops
; i
++) {
59 uint64_t off
= rand() % (object_size
- max_size
+ 1);
60 uint64_t len
= 1 + rand() % max_size
;
63 bl
.append(std::string(len
, '1'));
65 int r
= image_ctx
->io_work_queue
->write(off
, len
, std::move(bl
), 0);
66 ASSERT_EQ(static_cast<int>(len
), r
);
68 interval_set
<uint64_t> w
;
72 std::cout
<< " wrote " << *what
<< std::endl
;
75 } // anonymous namespace
77 class TestMockImageSyncObjectCopyRequest
: public TestMockFixture
{
79 typedef ObjectCopyRequest
<librbd::MockTestImageCtx
> MockObjectCopyRequest
;
81 void SetUp() override
{
82 TestMockFixture::SetUp();
85 ASSERT_EQ(0, create_image(rbd
, m_remote_io_ctx
, m_image_name
, m_image_size
));
86 ASSERT_EQ(0, open_image(m_remote_io_ctx
, m_image_name
, &m_remote_image_ctx
));
88 ASSERT_EQ(0, create_image(rbd
, m_local_io_ctx
, m_image_name
, m_image_size
));
89 ASSERT_EQ(0, open_image(m_local_io_ctx
, m_image_name
, &m_local_image_ctx
));
92 void expect_start_op(librbd::MockExclusiveLock
&mock_exclusive_lock
) {
93 EXPECT_CALL(mock_exclusive_lock
, start_op(_
)).WillOnce(
94 ReturnNew
<FunctionContext
>([](int) {}));
97 void expect_list_snaps(librbd::MockTestImageCtx
&mock_image_ctx
,
98 librados::MockTestMemIoCtxImpl
&mock_io_ctx
,
99 const librados::snap_set_t
&snap_set
) {
100 expect_set_snap_read(mock_io_ctx
, CEPH_SNAPDIR
);
101 EXPECT_CALL(mock_io_ctx
,
102 list_snaps(mock_image_ctx
.image_ctx
->get_object_name(0), _
))
103 .WillOnce(DoAll(WithArg
<1>(Invoke([&snap_set
](librados::snap_set_t
*out_snap_set
) {
104 *out_snap_set
= snap_set
;
109 void expect_list_snaps(librbd::MockTestImageCtx
&mock_image_ctx
,
110 librados::MockTestMemIoCtxImpl
&mock_io_ctx
, int r
) {
111 expect_set_snap_read(mock_io_ctx
, CEPH_SNAPDIR
);
112 auto &expect
= EXPECT_CALL(mock_io_ctx
,
113 list_snaps(mock_image_ctx
.image_ctx
->get_object_name(0),
116 expect
.WillOnce(Return(r
));
118 expect
.WillOnce(DoDefault());
122 void expect_get_object_name(librbd::MockTestImageCtx
&mock_image_ctx
) {
123 EXPECT_CALL(mock_image_ctx
, get_object_name(0))
124 .WillOnce(Return(mock_image_ctx
.image_ctx
->get_object_name(0)));
127 MockObjectCopyRequest
*create_request(librbd::MockTestImageCtx
&mock_remote_image_ctx
,
128 librbd::MockTestImageCtx
&mock_local_image_ctx
,
129 Context
*on_finish
) {
130 expect_get_object_name(mock_local_image_ctx
);
131 expect_get_object_name(mock_remote_image_ctx
);
132 return new MockObjectCopyRequest(&mock_local_image_ctx
,
133 &mock_remote_image_ctx
, &m_snap_map
,
137 void expect_set_snap_read(librados::MockTestMemIoCtxImpl
&mock_io_ctx
,
139 EXPECT_CALL(mock_io_ctx
, set_snap_read(snap_id
));
142 void expect_sparse_read(librados::MockTestMemIoCtxImpl
&mock_io_ctx
, uint64_t offset
,
143 uint64_t length
, int r
) {
145 auto &expect
= EXPECT_CALL(mock_io_ctx
, sparse_read(_
, offset
, length
, _
, _
));
147 expect
.WillOnce(Return(r
));
149 expect
.WillOnce(DoDefault());
153 void expect_sparse_read(librados::MockTestMemIoCtxImpl
&mock_io_ctx
,
154 const interval_set
<uint64_t> &extents
, int r
) {
155 for (auto extent
: extents
) {
156 expect_sparse_read(mock_io_ctx
, extent
.first
, extent
.second
, r
);
163 void expect_write(librados::MockTestMemIoCtxImpl
&mock_io_ctx
,
164 uint64_t offset
, uint64_t length
,
165 const SnapContext
&snapc
, int r
) {
166 auto &expect
= EXPECT_CALL(mock_io_ctx
, write(_
, _
, length
, offset
, snapc
));
168 expect
.WillOnce(Return(r
));
170 expect
.WillOnce(DoDefault());
174 void expect_write(librados::MockTestMemIoCtxImpl
&mock_io_ctx
,
175 const interval_set
<uint64_t> &extents
,
176 const SnapContext
&snapc
, int r
) {
177 for (auto extent
: extents
) {
178 expect_write(mock_io_ctx
, extent
.first
, extent
.second
, snapc
, r
);
185 void expect_truncate(librados::MockTestMemIoCtxImpl
&mock_io_ctx
,
186 uint64_t offset
, int r
) {
187 auto &expect
= EXPECT_CALL(mock_io_ctx
, truncate(_
, offset
, _
));
189 expect
.WillOnce(Return(r
));
191 expect
.WillOnce(DoDefault());
195 void expect_remove(librados::MockTestMemIoCtxImpl
&mock_io_ctx
, int r
) {
196 auto &expect
= EXPECT_CALL(mock_io_ctx
, remove(_
, _
));
198 expect
.WillOnce(Return(r
));
200 expect
.WillOnce(DoDefault());
204 void expect_update_object_map(librbd::MockTestImageCtx
&mock_image_ctx
,
205 librbd::MockObjectMap
&mock_object_map
,
206 librados::snap_t snap_id
, uint8_t state
,
208 if (mock_image_ctx
.image_ctx
->object_map
!= nullptr) {
209 auto &expect
= EXPECT_CALL(mock_object_map
, aio_update(snap_id
, 0, 1, state
, _
, _
, false, _
));
211 expect
.WillOnce(DoAll(WithArg
<7>(Invoke([this, r
](Context
*ctx
) {
212 m_threads
->work_queue
->queue(ctx
, r
);
216 expect
.WillOnce(DoAll(WithArg
<7>(Invoke([&mock_image_ctx
, snap_id
, state
, r
](Context
*ctx
) {
217 assert(mock_image_ctx
.image_ctx
->snap_lock
.is_locked());
218 assert(mock_image_ctx
.image_ctx
->object_map_lock
.is_wlocked());
219 mock_image_ctx
.image_ctx
->object_map
->aio_update
<Context
>(
220 snap_id
, 0, 1, state
, boost::none
, {}, false, ctx
);
227 using TestFixture::create_snap
;
228 int create_snap(const char* snap_name
) {
229 librados::snap_t remote_snap_id
;
230 int r
= create_snap(m_remote_image_ctx
, snap_name
, &remote_snap_id
);
235 librados::snap_t local_snap_id
;
236 r
= create_snap(m_local_image_ctx
, snap_name
, &local_snap_id
);
241 // collection of all existing snaps in local image
242 MockObjectCopyRequest::SnapIds
local_snap_ids({local_snap_id
});
243 if (!m_snap_map
.empty()) {
244 local_snap_ids
.insert(local_snap_ids
.end(),
245 m_snap_map
.rbegin()->second
.begin(),
246 m_snap_map
.rbegin()->second
.end());
248 m_snap_map
[remote_snap_id
] = local_snap_ids
;
249 m_remote_snap_ids
.push_back(remote_snap_id
);
250 m_local_snap_ids
.push_back(local_snap_id
);
255 std::string
get_snap_name(librbd::ImageCtx
*image_ctx
,
256 librados::snap_t snap_id
) {
257 auto it
= std::find_if(image_ctx
->snap_ids
.begin(),
258 image_ctx
->snap_ids
.end(),
259 [snap_id
](const std::pair
<std::pair
<cls::rbd::SnapshotNamespace
,
261 librados::snap_t
> &pair
) {
262 return (pair
.second
== snap_id
);
264 if (it
== image_ctx
->snap_ids
.end()) {
267 return it
->first
.second
;
270 int compare_objects() {
271 MockObjectCopyRequest::SnapMap
snap_map(m_snap_map
);
272 if (snap_map
.empty()) {
277 uint64_t object_size
= 1 << m_remote_image_ctx
->order
;
278 while (!snap_map
.empty()) {
279 librados::snap_t remote_snap_id
= snap_map
.begin()->first
;
280 librados::snap_t local_snap_id
= *snap_map
.begin()->second
.begin();
281 snap_map
.erase(snap_map
.begin());
283 std::string snap_name
= get_snap_name(m_remote_image_ctx
, remote_snap_id
);
284 if (snap_name
.empty()) {
288 std::cout
<< "comparing '" << snap_name
<< " (" << remote_snap_id
289 << " to " << local_snap_id
<< ")" << std::endl
;
291 r
= librbd::snap_set(m_remote_image_ctx
,
292 cls::rbd::UserSnapshotNamespace(),
298 r
= librbd::snap_set(m_local_image_ctx
,
299 cls::rbd::UserSnapshotNamespace(),
305 bufferlist remote_bl
;
306 remote_bl
.append(std::string(object_size
, '1'));
307 r
= m_remote_image_ctx
->io_work_queue
->read(
308 0, object_size
, librbd::io::ReadResult
{&remote_bl
}, 0);
314 local_bl
.append(std::string(object_size
, '1'));
315 r
= m_local_image_ctx
->io_work_queue
->read(
316 0, object_size
, librbd::io::ReadResult
{&local_bl
}, 0);
321 if (!remote_bl
.contents_equal(local_bl
)) {
326 r
= librbd::snap_set(m_remote_image_ctx
,
327 cls::rbd::UserSnapshotNamespace(),
332 r
= librbd::snap_set(m_local_image_ctx
,
333 cls::rbd::UserSnapshotNamespace(),
342 librbd::ImageCtx
*m_remote_image_ctx
;
343 librbd::ImageCtx
*m_local_image_ctx
;
345 MockObjectCopyRequest::SnapMap m_snap_map
;
346 std::vector
<librados::snap_t
> m_remote_snap_ids
;
347 std::vector
<librados::snap_t
> m_local_snap_ids
;
350 TEST_F(TestMockImageSyncObjectCopyRequest
, DNE
) {
351 ASSERT_EQ(0, create_snap("sync"));
352 librbd::MockTestImageCtx
mock_remote_image_ctx(*m_remote_image_ctx
);
353 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
355 librbd::MockExclusiveLock mock_exclusive_lock
;
356 mock_local_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
358 librbd::MockObjectMap mock_object_map
;
359 mock_local_image_ctx
.object_map
= &mock_object_map
;
360 expect_test_features(mock_local_image_ctx
);
363 MockObjectCopyRequest
*request
= create_request(mock_remote_image_ctx
,
364 mock_local_image_ctx
, &ctx
);
366 librados::MockTestMemIoCtxImpl
&mock_remote_io_ctx(get_mock_io_ctx(
367 request
->get_remote_io_ctx()));
370 expect_list_snaps(mock_remote_image_ctx
, mock_remote_io_ctx
, -ENOENT
);
373 ASSERT_EQ(0, ctx
.wait());
376 TEST_F(TestMockImageSyncObjectCopyRequest
, Write
) {
377 // scribble some data
378 interval_set
<uint64_t> one
;
379 scribble(m_remote_image_ctx
, 10, 102400, &one
);
381 ASSERT_EQ(0, create_snap("sync"));
382 librbd::MockTestImageCtx
mock_remote_image_ctx(*m_remote_image_ctx
);
383 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
385 librbd::MockExclusiveLock mock_exclusive_lock
;
386 mock_local_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
388 librbd::MockObjectMap mock_object_map
;
389 mock_local_image_ctx
.object_map
= &mock_object_map
;
391 expect_test_features(mock_local_image_ctx
);
394 MockObjectCopyRequest
*request
= create_request(mock_remote_image_ctx
,
395 mock_local_image_ctx
, &ctx
);
397 librados::MockTestMemIoCtxImpl
&mock_remote_io_ctx(get_mock_io_ctx(
398 request
->get_remote_io_ctx()));
399 librados::MockTestMemIoCtxImpl
&mock_local_io_ctx(get_mock_io_ctx(
400 request
->get_local_io_ctx()));
403 expect_list_snaps(mock_remote_image_ctx
, mock_remote_io_ctx
, 0);
404 expect_set_snap_read(mock_remote_io_ctx
, m_remote_snap_ids
[0]);
405 expect_sparse_read(mock_remote_io_ctx
, 0, one
.range_end(), 0);
406 expect_start_op(mock_exclusive_lock
);
407 expect_write(mock_local_io_ctx
, 0, one
.range_end(), {0, {}}, 0);
408 expect_start_op(mock_exclusive_lock
);
409 expect_update_object_map(mock_local_image_ctx
, mock_object_map
,
410 m_local_snap_ids
[0], OBJECT_EXISTS
, 0);
413 ASSERT_EQ(0, ctx
.wait());
414 ASSERT_EQ(0, compare_objects());
417 TEST_F(TestMockImageSyncObjectCopyRequest
, ReadMissingStaleSnapSet
) {
418 ASSERT_EQ(0, create_snap("one"));
419 ASSERT_EQ(0, create_snap("two"));
421 // scribble some data
422 interval_set
<uint64_t> one
;
423 scribble(m_remote_image_ctx
, 10, 102400, &one
);
424 ASSERT_EQ(0, create_snap("three"));
426 ASSERT_EQ(0, create_snap("sync"));
427 librbd::MockTestImageCtx
mock_remote_image_ctx(*m_remote_image_ctx
);
428 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
430 librbd::MockExclusiveLock mock_exclusive_lock
;
431 mock_local_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
433 librbd::MockObjectMap mock_object_map
;
434 mock_local_image_ctx
.object_map
= &mock_object_map
;
436 expect_test_features(mock_local_image_ctx
);
439 MockObjectCopyRequest
*request
= create_request(mock_remote_image_ctx
,
440 mock_local_image_ctx
, &ctx
);
442 librados::MockTestMemIoCtxImpl
&mock_remote_io_ctx(get_mock_io_ctx(
443 request
->get_remote_io_ctx()));
444 librados::MockTestMemIoCtxImpl
&mock_local_io_ctx(get_mock_io_ctx(
445 request
->get_local_io_ctx()));
447 librados::clone_info_t dummy_clone_info
;
448 dummy_clone_info
.cloneid
= librados::SNAP_HEAD
;
449 dummy_clone_info
.size
= 123;
451 librados::snap_set_t dummy_snap_set1
;
452 dummy_snap_set1
.clones
.push_back(dummy_clone_info
);
454 dummy_clone_info
.size
= 234;
455 librados::snap_set_t dummy_snap_set2
;
456 dummy_snap_set2
.clones
.push_back(dummy_clone_info
);
459 expect_list_snaps(mock_remote_image_ctx
, mock_remote_io_ctx
, dummy_snap_set1
);
460 expect_set_snap_read(mock_remote_io_ctx
, m_remote_snap_ids
[3]);
461 expect_sparse_read(mock_remote_io_ctx
, 0, 123, -ENOENT
);
462 expect_list_snaps(mock_remote_image_ctx
, mock_remote_io_ctx
, dummy_snap_set2
);
463 expect_set_snap_read(mock_remote_io_ctx
, m_remote_snap_ids
[3]);
464 expect_sparse_read(mock_remote_io_ctx
, 0, 234, -ENOENT
);
465 expect_list_snaps(mock_remote_image_ctx
, mock_remote_io_ctx
, 0);
466 expect_set_snap_read(mock_remote_io_ctx
, m_remote_snap_ids
[3]);
467 expect_sparse_read(mock_remote_io_ctx
, 0, one
.range_end(), 0);
468 expect_start_op(mock_exclusive_lock
);
469 expect_write(mock_local_io_ctx
, 0, one
.range_end(),
470 {m_local_snap_ids
[1], {m_local_snap_ids
[1],
471 m_local_snap_ids
[0]}},
473 expect_start_op(mock_exclusive_lock
);
474 expect_update_object_map(mock_local_image_ctx
, mock_object_map
,
475 m_local_snap_ids
[2], OBJECT_EXISTS
, 0);
476 expect_start_op(mock_exclusive_lock
);
477 expect_update_object_map(mock_local_image_ctx
, mock_object_map
,
478 m_local_snap_ids
[3], OBJECT_EXISTS_CLEAN
, 0);
481 ASSERT_EQ(0, ctx
.wait());
482 ASSERT_EQ(0, compare_objects());
485 TEST_F(TestMockImageSyncObjectCopyRequest
, ReadMissingUpToDateSnapMap
) {
486 // scribble some data
487 interval_set
<uint64_t> one
;
488 scribble(m_remote_image_ctx
, 10, 102400, &one
);
490 ASSERT_EQ(0, create_snap("sync"));
491 librbd::MockTestImageCtx
mock_remote_image_ctx(*m_remote_image_ctx
);
492 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
494 librbd::MockExclusiveLock mock_exclusive_lock
;
495 mock_local_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
497 librbd::MockObjectMap mock_object_map
;
498 mock_local_image_ctx
.object_map
= &mock_object_map
;
500 expect_test_features(mock_local_image_ctx
);
503 MockObjectCopyRequest
*request
= create_request(mock_remote_image_ctx
,
504 mock_local_image_ctx
, &ctx
);
506 librados::MockTestMemIoCtxImpl
&mock_remote_io_ctx(get_mock_io_ctx(
507 request
->get_remote_io_ctx()));
510 expect_list_snaps(mock_remote_image_ctx
, mock_remote_io_ctx
, 0);
511 expect_set_snap_read(mock_remote_io_ctx
, m_remote_snap_ids
[0]);
512 expect_sparse_read(mock_remote_io_ctx
, 0, one
.range_end(), -ENOENT
);
513 expect_list_snaps(mock_remote_image_ctx
, mock_remote_io_ctx
, 0);
516 ASSERT_EQ(-ENOENT
, ctx
.wait());
519 TEST_F(TestMockImageSyncObjectCopyRequest
, ReadError
) {
520 // scribble some data
521 interval_set
<uint64_t> one
;
522 scribble(m_remote_image_ctx
, 10, 102400, &one
);
524 ASSERT_EQ(0, create_snap("sync"));
525 librbd::MockTestImageCtx
mock_remote_image_ctx(*m_remote_image_ctx
);
526 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
528 librbd::MockExclusiveLock mock_exclusive_lock
;
529 mock_local_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
531 librbd::MockObjectMap mock_object_map
;
532 mock_local_image_ctx
.object_map
= &mock_object_map
;
534 expect_test_features(mock_local_image_ctx
);
537 MockObjectCopyRequest
*request
= create_request(mock_remote_image_ctx
,
538 mock_local_image_ctx
, &ctx
);
540 librados::MockTestMemIoCtxImpl
&mock_remote_io_ctx(get_mock_io_ctx(
541 request
->get_remote_io_ctx()));
544 expect_list_snaps(mock_remote_image_ctx
, mock_remote_io_ctx
, 0);
545 expect_set_snap_read(mock_remote_io_ctx
, m_remote_snap_ids
[0]);
546 expect_sparse_read(mock_remote_io_ctx
, 0, one
.range_end(), -EINVAL
);
549 ASSERT_EQ(-EINVAL
, ctx
.wait());
552 TEST_F(TestMockImageSyncObjectCopyRequest
, WriteError
) {
553 // scribble some data
554 interval_set
<uint64_t> one
;
555 scribble(m_remote_image_ctx
, 10, 102400, &one
);
557 ASSERT_EQ(0, create_snap("sync"));
558 librbd::MockTestImageCtx
mock_remote_image_ctx(*m_remote_image_ctx
);
559 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
561 librbd::MockExclusiveLock mock_exclusive_lock
;
562 mock_local_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
564 librbd::MockObjectMap mock_object_map
;
565 mock_local_image_ctx
.object_map
= &mock_object_map
;
567 expect_test_features(mock_local_image_ctx
);
570 MockObjectCopyRequest
*request
= create_request(mock_remote_image_ctx
,
571 mock_local_image_ctx
, &ctx
);
573 librados::MockTestMemIoCtxImpl
&mock_remote_io_ctx(get_mock_io_ctx(
574 request
->get_remote_io_ctx()));
575 librados::MockTestMemIoCtxImpl
&mock_local_io_ctx(get_mock_io_ctx(
576 request
->get_local_io_ctx()));
579 expect_list_snaps(mock_remote_image_ctx
, mock_remote_io_ctx
, 0);
580 expect_set_snap_read(mock_remote_io_ctx
, m_remote_snap_ids
[0]);
581 expect_sparse_read(mock_remote_io_ctx
, 0, one
.range_end(), 0);
582 expect_start_op(mock_exclusive_lock
);
583 expect_write(mock_local_io_ctx
, 0, one
.range_end(), {0, {}}, -EINVAL
);
586 ASSERT_EQ(-EINVAL
, ctx
.wait());
589 TEST_F(TestMockImageSyncObjectCopyRequest
, WriteSnaps
) {
590 // scribble some data
591 interval_set
<uint64_t> one
;
592 scribble(m_remote_image_ctx
, 10, 102400, &one
);
593 ASSERT_EQ(0, create_snap("one"));
595 interval_set
<uint64_t> two
;
596 scribble(m_remote_image_ctx
, 10, 102400, &two
);
597 ASSERT_EQ(0, create_snap("two"));
599 if (one
.range_end() < two
.range_end()) {
600 interval_set
<uint64_t> resize_diff
;
601 resize_diff
.insert(one
.range_end(), two
.range_end() - one
.range_end());
602 two
.union_of(resize_diff
);
605 ASSERT_EQ(0, create_snap("sync"));
606 librbd::MockTestImageCtx
mock_remote_image_ctx(*m_remote_image_ctx
);
607 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
609 librbd::MockExclusiveLock mock_exclusive_lock
;
610 mock_local_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
612 librbd::MockObjectMap mock_object_map
;
613 mock_local_image_ctx
.object_map
= &mock_object_map
;
615 expect_test_features(mock_local_image_ctx
);
618 MockObjectCopyRequest
*request
= create_request(mock_remote_image_ctx
,
619 mock_local_image_ctx
, &ctx
);
621 librados::MockTestMemIoCtxImpl
&mock_remote_io_ctx(get_mock_io_ctx(
622 request
->get_remote_io_ctx()));
623 librados::MockTestMemIoCtxImpl
&mock_local_io_ctx(get_mock_io_ctx(
624 request
->get_local_io_ctx()));
627 expect_list_snaps(mock_remote_image_ctx
, mock_remote_io_ctx
, 0);
628 expect_set_snap_read(mock_remote_io_ctx
, m_remote_snap_ids
[0]);
629 expect_sparse_read(mock_remote_io_ctx
, 0, one
.range_end(), 0);
630 expect_start_op(mock_exclusive_lock
);
631 expect_write(mock_local_io_ctx
, 0, one
.range_end(), {0, {}}, 0);
632 expect_set_snap_read(mock_remote_io_ctx
, m_remote_snap_ids
[2]);
633 expect_sparse_read(mock_remote_io_ctx
, two
, 0);
634 expect_start_op(mock_exclusive_lock
);
635 expect_write(mock_local_io_ctx
, two
,
636 {m_local_snap_ids
[0], {m_local_snap_ids
[0]}}, 0);
637 expect_start_op(mock_exclusive_lock
);
638 expect_update_object_map(mock_local_image_ctx
, mock_object_map
,
639 m_local_snap_ids
[0], OBJECT_EXISTS
, 0);
640 expect_start_op(mock_exclusive_lock
);
641 expect_update_object_map(mock_local_image_ctx
, mock_object_map
,
642 m_local_snap_ids
[1], OBJECT_EXISTS
, 0);
643 expect_start_op(mock_exclusive_lock
);
644 expect_update_object_map(mock_local_image_ctx
, mock_object_map
,
645 m_local_snap_ids
[2], OBJECT_EXISTS_CLEAN
, 0);
648 ASSERT_EQ(0, ctx
.wait());
649 ASSERT_EQ(0, compare_objects());
652 TEST_F(TestMockImageSyncObjectCopyRequest
, Trim
) {
653 ASSERT_EQ(0, m_remote_image_ctx
->operations
->metadata_set(
654 "conf_rbd_skip_partial_discard", "false"));
655 // scribble some data
656 interval_set
<uint64_t> one
;
657 scribble(m_remote_image_ctx
, 10, 102400, &one
);
658 ASSERT_EQ(0, create_snap("one"));
661 uint64_t trim_offset
= rand() % one
.range_end();
662 ASSERT_LE(0, m_remote_image_ctx
->io_work_queue
->discard(
663 trim_offset
, one
.range_end() - trim_offset
, m_remote_image_ctx
->skip_partial_discard
));
664 ASSERT_EQ(0, create_snap("sync"));
666 librbd::MockTestImageCtx
mock_remote_image_ctx(*m_remote_image_ctx
);
667 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
669 librbd::MockExclusiveLock mock_exclusive_lock
;
670 mock_local_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
672 librbd::MockObjectMap mock_object_map
;
673 mock_local_image_ctx
.object_map
= &mock_object_map
;
675 expect_test_features(mock_local_image_ctx
);
678 MockObjectCopyRequest
*request
= create_request(mock_remote_image_ctx
,
679 mock_local_image_ctx
, &ctx
);
681 librados::MockTestMemIoCtxImpl
&mock_remote_io_ctx(get_mock_io_ctx(
682 request
->get_remote_io_ctx()));
683 librados::MockTestMemIoCtxImpl
&mock_local_io_ctx(get_mock_io_ctx(
684 request
->get_local_io_ctx()));
687 expect_list_snaps(mock_remote_image_ctx
, mock_remote_io_ctx
, 0);
688 expect_set_snap_read(mock_remote_io_ctx
, m_remote_snap_ids
[0]);
689 expect_sparse_read(mock_remote_io_ctx
, 0, one
.range_end(), 0);
690 expect_start_op(mock_exclusive_lock
);
691 expect_write(mock_local_io_ctx
, 0, one
.range_end(), {0, {}}, 0);
692 expect_start_op(mock_exclusive_lock
);
693 expect_truncate(mock_local_io_ctx
, trim_offset
, 0);
694 expect_start_op(mock_exclusive_lock
);
695 expect_update_object_map(mock_local_image_ctx
, mock_object_map
,
696 m_local_snap_ids
[0], OBJECT_EXISTS
, 0);
697 expect_start_op(mock_exclusive_lock
);
698 expect_update_object_map(mock_local_image_ctx
, mock_object_map
,
699 m_local_snap_ids
[1], OBJECT_EXISTS
, 0);
702 ASSERT_EQ(0, ctx
.wait());
703 ASSERT_EQ(0, compare_objects());
706 TEST_F(TestMockImageSyncObjectCopyRequest
, Remove
) {
707 // scribble some data
708 interval_set
<uint64_t> one
;
709 scribble(m_remote_image_ctx
, 10, 102400, &one
);
710 ASSERT_EQ(0, create_snap("one"));
711 ASSERT_EQ(0, create_snap("two"));
714 uint64_t object_size
= 1 << m_remote_image_ctx
->order
;
715 ASSERT_LE(0, m_remote_image_ctx
->io_work_queue
->discard(0, object_size
, m_remote_image_ctx
->skip_partial_discard
));
716 ASSERT_EQ(0, create_snap("sync"));
717 librbd::MockTestImageCtx
mock_remote_image_ctx(*m_remote_image_ctx
);
718 librbd::MockTestImageCtx
mock_local_image_ctx(*m_local_image_ctx
);
720 librbd::MockExclusiveLock mock_exclusive_lock
;
721 mock_local_image_ctx
.exclusive_lock
= &mock_exclusive_lock
;
723 librbd::MockObjectMap mock_object_map
;
724 mock_local_image_ctx
.object_map
= &mock_object_map
;
726 expect_test_features(mock_local_image_ctx
);
729 MockObjectCopyRequest
*request
= create_request(mock_remote_image_ctx
,
730 mock_local_image_ctx
, &ctx
);
732 librados::MockTestMemIoCtxImpl
&mock_remote_io_ctx(get_mock_io_ctx(
733 request
->get_remote_io_ctx()));
734 librados::MockTestMemIoCtxImpl
&mock_local_io_ctx(get_mock_io_ctx(
735 request
->get_local_io_ctx()));
738 expect_list_snaps(mock_remote_image_ctx
, mock_remote_io_ctx
, 0);
739 expect_set_snap_read(mock_remote_io_ctx
, m_remote_snap_ids
[1]);
740 expect_sparse_read(mock_remote_io_ctx
, 0, one
.range_end(), 0);
741 expect_start_op(mock_exclusive_lock
);
742 expect_write(mock_local_io_ctx
, 0, one
.range_end(), {0, {}}, 0);
743 expect_start_op(mock_exclusive_lock
);
744 expect_remove(mock_local_io_ctx
, 0);
745 expect_start_op(mock_exclusive_lock
);
746 expect_update_object_map(mock_local_image_ctx
, mock_object_map
,
747 m_local_snap_ids
[0], OBJECT_EXISTS
, 0);
748 expect_start_op(mock_exclusive_lock
);
749 expect_update_object_map(mock_local_image_ctx
, mock_object_map
,
750 m_local_snap_ids
[1], OBJECT_EXISTS_CLEAN
, 0);
753 ASSERT_EQ(0, ctx
.wait());
754 ASSERT_EQ(0, compare_objects());
757 } // namespace image_sync
758 } // namespace mirror