From: Jason Dillaman Date: Wed, 5 Feb 2020 20:54:55 +0000 (-0500) Subject: librbd: deep-copy objects from specified start position X-Git-Tag: v14.2.12~68^2~3 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=9a356117d231ce113941ec352477d8bf9d2afa91;p=ceph.git librbd: deep-copy objects from specified start position Only read data from from after the specified start position and copy it to the specified starting write position in the destination. Fixes: https://tracker.ceph.com/issues/43933 Signed-off-by: Jason Dillaman (cherry picked from commit d445ac503a9b8aa7a8f7d235023325cca44d58ce) --- diff --git a/src/librbd/DeepCopyRequest.cc b/src/librbd/DeepCopyRequest.cc index 1116c05d4ac3b..3350fa3b9d11b 100644 --- a/src/librbd/DeepCopyRequest.cc +++ b/src/librbd/DeepCopyRequest.cc @@ -158,7 +158,8 @@ void DeepCopyRequest::send_copy_image() { DeepCopyRequest, &DeepCopyRequest::handle_copy_image>(this); m_image_copy_request = ImageCopyRequest::create( m_src_image_ctx, m_dst_image_ctx, m_src_snap_id_start, m_src_snap_id_end, - m_flatten, m_object_number, *m_snap_seqs, m_prog_ctx, ctx); + m_dst_snap_id_start, m_flatten, m_object_number, *m_snap_seqs, m_prog_ctx, + ctx); m_image_copy_request->get(); m_lock.Unlock(); diff --git a/src/librbd/deep_copy/ImageCopyRequest.cc b/src/librbd/deep_copy/ImageCopyRequest.cc index 266e76b956b88..62e5409c27db8 100644 --- a/src/librbd/deep_copy/ImageCopyRequest.cc +++ b/src/librbd/deep_copy/ImageCopyRequest.cc @@ -25,6 +25,7 @@ template ImageCopyRequest::ImageCopyRequest(I *src_image_ctx, I *dst_image_ctx, librados::snap_t src_snap_id_start, librados::snap_t src_snap_id_end, + librados::snap_t dst_snap_id_start, bool flatten, const ObjectNumber &object_number, const SnapSeqs &snap_seqs, @@ -32,8 +33,8 @@ ImageCopyRequest::ImageCopyRequest(I *src_image_ctx, I *dst_image_ctx, Context *on_finish) : RefCountedObject(dst_image_ctx->cct, 1), m_src_image_ctx(src_image_ctx), m_dst_image_ctx(dst_image_ctx), m_src_snap_id_start(src_snap_id_start), - m_src_snap_id_end(src_snap_id_end), m_flatten(flatten), - m_object_number(object_number), m_snap_seqs(snap_seqs), + m_src_snap_id_end(src_snap_id_end), m_dst_snap_id_start(dst_snap_id_start), + m_flatten(flatten), m_object_number(object_number), m_snap_seqs(snap_seqs), m_prog_ctx(prog_ctx), m_on_finish(on_finish), m_cct(dst_image_ctx->cct), m_lock(unique_lock_name("ImageCopyRequest::m_lock", this)) { } @@ -126,7 +127,8 @@ void ImageCopyRequest::send_next_object_copy() { handle_object_copy(ono, r); }); ObjectCopyRequest *req = ObjectCopyRequest::create( - m_src_image_ctx, m_dst_image_ctx, m_snap_map, ono, m_flatten, ctx); + m_src_image_ctx, m_dst_image_ctx, m_src_snap_id_start, m_dst_snap_id_start, + m_snap_map, ono, m_flatten, ctx); req->send(); } diff --git a/src/librbd/deep_copy/ImageCopyRequest.h b/src/librbd/deep_copy/ImageCopyRequest.h index 5a50cdd16ffb2..189cb2375eacf 100644 --- a/src/librbd/deep_copy/ImageCopyRequest.h +++ b/src/librbd/deep_copy/ImageCopyRequest.h @@ -32,19 +32,21 @@ public: ImageCtxT *dst_image_ctx, librados::snap_t src_snap_id_start, librados::snap_t src_snap_id_end, + librados::snap_t dst_snap_id_start, bool flatten, const ObjectNumber &object_number, const SnapSeqs &snap_seqs, ProgressContext *prog_ctx, Context *on_finish) { return new ImageCopyRequest(src_image_ctx, dst_image_ctx, src_snap_id_start, - src_snap_id_end, flatten, object_number, - snap_seqs, prog_ctx, on_finish); + src_snap_id_end, dst_snap_id_start, flatten, + object_number, snap_seqs, prog_ctx, on_finish); } ImageCopyRequest(ImageCtxT *src_image_ctx, ImageCtxT *dst_image_ctx, librados::snap_t src_snap_id_start, librados::snap_t src_snap_id_end, + librados::snap_t dst_snap_id_start, bool flatten, const ObjectNumber &object_number, const SnapSeqs &snap_seqs, ProgressContext *prog_ctx, Context *on_finish); @@ -72,6 +74,7 @@ private: ImageCtxT *m_dst_image_ctx; librados::snap_t m_src_snap_id_start; librados::snap_t m_src_snap_id_end; + librados::snap_t m_dst_snap_id_start; bool m_flatten; ObjectNumber m_object_number; SnapSeqs m_snap_seqs; diff --git a/src/librbd/deep_copy/ObjectCopyRequest.cc b/src/librbd/deep_copy/ObjectCopyRequest.cc index 92a1750f1152e..2400757a72a79 100644 --- a/src/librbd/deep_copy/ObjectCopyRequest.cc +++ b/src/librbd/deep_copy/ObjectCopyRequest.cc @@ -43,13 +43,17 @@ using librbd::util::create_rados_callback; template ObjectCopyRequest::ObjectCopyRequest(I *src_image_ctx, I *dst_image_ctx, + librados::snap_t src_snap_id_start, + librados::snap_t dst_snap_id_start, const SnapMap &snap_map, uint64_t dst_object_number, bool flatten, Context *on_finish) : m_src_image_ctx(src_image_ctx), m_dst_image_ctx(dst_image_ctx), m_cct(dst_image_ctx->cct), - m_snap_map(snap_map), m_dst_object_number(dst_object_number), - m_flatten(flatten), m_on_finish(on_finish) { + m_src_snap_id_start(src_snap_id_start), + m_dst_snap_id_start(dst_snap_id_start), m_snap_map(snap_map), + m_dst_object_number(dst_object_number), m_flatten(flatten), + m_on_finish(on_finish) { ceph_assert(src_image_ctx->data_ctx.is_valid()); ceph_assert(dst_image_ctx->data_ctx.is_valid()); ceph_assert(!m_snap_map.empty()); @@ -321,12 +325,15 @@ void ObjectCopyRequest::send_write_object() { } // write snapshot context should be before actual snapshot - if (snap_map_it != m_snap_map.begin()) { - --snap_map_it; - ceph_assert(!snap_map_it->second.empty()); - dst_snap_seq = snap_map_it->second.front(); - dst_snap_ids = snap_map_it->second; + ceph_assert(!snap_map_it->second.empty()); + auto dst_snap_ids_it = snap_map_it->second.begin(); + ++dst_snap_ids_it; + + dst_snap_ids = SnapIds{dst_snap_ids_it, snap_map_it->second.end()}; + if (!dst_snap_ids.empty()) { + dst_snap_seq = dst_snap_ids.front(); } + ceph_assert(dst_snap_seq != CEPH_NOSNAP); } ldout(m_cct, 20) << "dst_snap_seq=" << dst_snap_seq << ", " @@ -585,10 +592,10 @@ void ObjectCopyRequest::compute_read_ops() { m_src_image_ctx->parent_lock.put_read(); librados::snap_t src_copy_point_snap_id = m_snap_map.rbegin()->first; - bool prev_exists = hide_parent; + bool prev_exists = (hide_parent || m_src_snap_id_start > 0); uint64_t prev_end_size = prev_exists ? m_src_image_ctx->layout.object_size : 0; - librados::snap_t start_src_snap_id = 0; + librados::snap_t start_src_snap_id = m_src_snap_id_start; for (auto &pair : m_snap_map) { ceph_assert(!pair.second.empty()); diff --git a/src/librbd/deep_copy/ObjectCopyRequest.h b/src/librbd/deep_copy/ObjectCopyRequest.h index 6df98e695ad0e..a0445f3bb01bd 100644 --- a/src/librbd/deep_copy/ObjectCopyRequest.h +++ b/src/librbd/deep_copy/ObjectCopyRequest.h @@ -29,16 +29,20 @@ class ObjectCopyRequest { public: static ObjectCopyRequest* create(ImageCtxT *src_image_ctx, ImageCtxT *dst_image_ctx, + librados::snap_t src_snap_id_start, + librados::snap_t dst_snap_id_start, const SnapMap &snap_map, uint64_t object_number, bool flatten, Context *on_finish) { - return new ObjectCopyRequest(src_image_ctx, dst_image_ctx, snap_map, + return new ObjectCopyRequest(src_image_ctx, dst_image_ctx, + src_snap_id_start, dst_snap_id_start, snap_map, object_number, flatten, on_finish); } ObjectCopyRequest(ImageCtxT *src_image_ctx, ImageCtxT *dst_image_ctx, - const SnapMap &snap_map, uint64_t object_number, - bool flatten, Context *on_finish); + librados::snap_t src_snap_id_start, + librados::snap_t dst_snap_id_start, const SnapMap &snap_map, + uint64_t object_number, bool flatten, Context *on_finish); void send(); @@ -136,6 +140,8 @@ private: ImageCtxT *m_src_image_ctx; ImageCtxT *m_dst_image_ctx; CephContext *m_cct; + librados::snap_t m_src_snap_id_start; + librados::snap_t m_dst_snap_id_start; SnapMap m_snap_map; uint64_t m_dst_object_number; bool m_flatten; diff --git a/src/librbd/io/CopyupRequest.cc b/src/librbd/io/CopyupRequest.cc index 06ef47ca86504..c2ebb10feda2c 100644 --- a/src/librbd/io/CopyupRequest.cc +++ b/src/librbd/io/CopyupRequest.cc @@ -235,8 +235,8 @@ void CopyupRequest::deep_copy() { auto ctx = util::create_context_callback< CopyupRequest, &CopyupRequest::handle_deep_copy>(this); auto req = deep_copy::ObjectCopyRequest::create( - m_image_ctx->parent, m_image_ctx, m_image_ctx->migration_info.snap_map, - m_object_no, m_flatten, ctx); + m_image_ctx->parent, m_image_ctx, 0, 0, + m_image_ctx->migration_info.snap_map, m_object_no, m_flatten, ctx); req->send(); } diff --git a/src/librbd/operation/MigrateRequest.cc b/src/librbd/operation/MigrateRequest.cc index 71a6f93288efa..e3ddff0e3e5dc 100644 --- a/src/librbd/operation/MigrateRequest.cc +++ b/src/librbd/operation/MigrateRequest.cc @@ -131,7 +131,7 @@ private: ceph_assert(image_ctx.parent != nullptr); auto req = deep_copy::ObjectCopyRequest::create( - image_ctx.parent, &image_ctx, image_ctx.migration_info.snap_map, + image_ctx.parent, &image_ctx, 0, 0, image_ctx.migration_info.snap_map, m_object_no, image_ctx.migration_info.flatten, ctx); ldout(cct, 20) << "deep copy object req " << req << ", object_no " diff --git a/src/test/librbd/deep_copy/test_mock_ImageCopyRequest.cc b/src/test/librbd/deep_copy/test_mock_ImageCopyRequest.cc index a3e5effd9989e..d6cc03a574f79 100644 --- a/src/test/librbd/deep_copy/test_mock_ImageCopyRequest.cc +++ b/src/test/librbd/deep_copy/test_mock_ImageCopyRequest.cc @@ -49,7 +49,10 @@ struct ObjectCopyRequest { static ObjectCopyRequest* s_instance; static ObjectCopyRequest* create( librbd::MockTestImageCtx *src_image_ctx, - librbd::MockTestImageCtx *dst_image_ctx, const SnapMap &snap_map, + librbd::MockTestImageCtx *dst_image_ctx, + librados::snap_t src_snap_id_start, + librados::snap_t dst_snap_id_start, + const SnapMap &snap_map, uint64_t object_number, bool flatten, Context *on_finish) { ceph_assert(s_instance != nullptr); Mutex::Locker locker(s_instance->lock); @@ -271,7 +274,7 @@ TEST_F(TestMockDeepCopyImageCopyRequest, SimpleImage) { C_SaferCond ctx; auto request = new MockImageCopyRequest(&mock_src_image_ctx, &mock_dst_image_ctx, - 0, snap_id_end, false, boost::none, + 0, snap_id_end, 0, false, boost::none, m_snap_seqs, &no_op, &ctx); request->send(); @@ -330,7 +333,7 @@ TEST_F(TestMockDeepCopyImageCopyRequest, OutOfOrder) { C_SaferCond ctx; auto request = new MockImageCopyRequest(&mock_src_image_ctx, &mock_dst_image_ctx, - 0, snap_id_end, false, boost::none, + 0, snap_id_end, 0, false, boost::none, m_snap_seqs, &prog_ctx, &ctx); request->send(); @@ -375,7 +378,7 @@ TEST_F(TestMockDeepCopyImageCopyRequest, SnapshotSubset) { C_SaferCond ctx; auto request = new MockImageCopyRequest(&mock_src_image_ctx, &mock_dst_image_ctx, - snap_id_start, snap_id_end, false, + snap_id_start, snap_id_end, 0, false, boost::none, m_snap_seqs, &no_op, &ctx); request->send(); @@ -405,7 +408,7 @@ TEST_F(TestMockDeepCopyImageCopyRequest, RestartPartialSync) { C_SaferCond ctx; auto request = new MockImageCopyRequest(&mock_src_image_ctx, &mock_dst_image_ctx, - 0, snap_id_end, false, + 0, snap_id_end, 0, false, librbd::deep_copy::ObjectNumber{0U}, m_snap_seqs, &no_op, &ctx); request->send(); @@ -439,7 +442,7 @@ TEST_F(TestMockDeepCopyImageCopyRequest, Cancel) { C_SaferCond ctx; auto request = new MockImageCopyRequest(&mock_src_image_ctx, &mock_dst_image_ctx, - 0, snap_id_end, false, boost::none, + 0, snap_id_end, 0, false, boost::none, m_snap_seqs, &no_op, &ctx); request->send(); @@ -484,7 +487,7 @@ TEST_F(TestMockDeepCopyImageCopyRequest, Cancel_Inflight_Sync) { C_SaferCond ctx; auto request = new MockImageCopyRequest(&mock_src_image_ctx, &mock_dst_image_ctx, - 0, snap_id_end, false, boost::none, + 0, snap_id_end, 0, false, boost::none, m_snap_seqs, &prog_ctx, &ctx); request->send(); @@ -514,7 +517,7 @@ TEST_F(TestMockDeepCopyImageCopyRequest, MissingSnap) { C_SaferCond ctx; auto request = new MockImageCopyRequest(&mock_src_image_ctx, &mock_dst_image_ctx, - 0, 123, false, boost::none, + 0, 123, 0, false, boost::none, m_snap_seqs, &no_op, &ctx); request->send(); ASSERT_EQ(-EINVAL, ctx.wait()); @@ -531,8 +534,9 @@ TEST_F(TestMockDeepCopyImageCopyRequest, MissingFromSnap) { C_SaferCond ctx; auto request = new MockImageCopyRequest(&mock_src_image_ctx, &mock_dst_image_ctx, - 123, snap_id_end, false, boost::none, - m_snap_seqs, &no_op, &ctx); + 123, snap_id_end, 0, false, + boost::none, m_snap_seqs, &no_op, + &ctx); request->send(); ASSERT_EQ(-EINVAL, ctx.wait()); } @@ -550,7 +554,7 @@ TEST_F(TestMockDeepCopyImageCopyRequest, EmptySnapMap) { C_SaferCond ctx; auto request = new MockImageCopyRequest(&mock_src_image_ctx, &mock_dst_image_ctx, - snap_id_start, snap_id_end, false, + snap_id_start, snap_id_end, 0, false, boost::none, {{0, 0}}, &no_op, &ctx); request->send(); ASSERT_EQ(-EINVAL, ctx.wait()); @@ -569,7 +573,7 @@ TEST_F(TestMockDeepCopyImageCopyRequest, EmptySnapSeqs) { C_SaferCond ctx; auto request = new MockImageCopyRequest(&mock_src_image_ctx, &mock_dst_image_ctx, - snap_id_start, snap_id_end, false, + snap_id_start, snap_id_end, 0, false, boost::none, {}, &no_op, &ctx); request->send(); ASSERT_EQ(-EINVAL, ctx.wait()); diff --git a/src/test/librbd/deep_copy/test_mock_ObjectCopyRequest.cc b/src/test/librbd/deep_copy/test_mock_ObjectCopyRequest.cc index 7816a507e90d7..ebaf479bfab51 100644 --- a/src/test/librbd/deep_copy/test_mock_ObjectCopyRequest.cc +++ b/src/test/librbd/deep_copy/test_mock_ObjectCopyRequest.cc @@ -205,9 +205,13 @@ public: MockObjectCopyRequest *create_request( librbd::MockTestImageCtx &mock_src_image_ctx, - librbd::MockTestImageCtx &mock_dst_image_ctx, Context *on_finish) { + librbd::MockTestImageCtx &mock_dst_image_ctx, + librados::snap_t src_snap_id_start, + librados::snap_t dst_snap_id_start, + Context *on_finish) { expect_get_object_name(mock_dst_image_ctx); return new MockObjectCopyRequest(&mock_src_image_ctx, &mock_dst_image_ctx, + src_snap_id_start, dst_snap_id_start, m_snap_map, 0, false, on_finish); } @@ -368,6 +372,26 @@ public: return it->first.second; } + int copy_objects() { + int r; + uint64_t object_size = 1 << m_src_image_ctx->order; + + bufferlist bl; + bl.append(std::string(object_size, '1')); + r = m_src_image_ctx->io_work_queue->read( + 0, object_size, librbd::io::ReadResult{&bl}, 0); + if (r < 0) { + return r; + } + + r = m_dst_image_ctx->io_work_queue->write(0, object_size, std::move(bl), 0); + if (r < 0) { + return r; + } + + return 0; + } + int compare_objects() { SnapMap snap_map(m_snap_map); if (snap_map.empty()) { @@ -420,6 +444,8 @@ public: } if (!src_bl.contents_equal(dst_bl)) { + std::cout << "src block: " << std::endl; src_bl.hexdump(std::cout); + std::cout << "dst block: " << std::endl; dst_bl.hexdump(std::cout); return -EBADMSG; } } @@ -456,7 +482,8 @@ TEST_F(TestMockDeepCopyObjectCopyRequest, DNE) { C_SaferCond ctx; MockObjectCopyRequest *request = create_request(mock_src_image_ctx, - mock_dst_image_ctx, &ctx); + mock_dst_image_ctx, 0, 0, + &ctx); librados::MockTestMemIoCtxImpl &mock_src_io_ctx(get_mock_io_ctx( request->get_src_io_ctx())); @@ -488,7 +515,8 @@ TEST_F(TestMockDeepCopyObjectCopyRequest, Write) { C_SaferCond ctx; MockObjectCopyRequest *request = create_request(mock_src_image_ctx, - mock_dst_image_ctx, &ctx); + mock_dst_image_ctx, 0, 0, + &ctx); librados::MockTestMemIoCtxImpl &mock_src_io_ctx(get_mock_io_ctx( request->get_src_io_ctx())); @@ -534,7 +562,8 @@ TEST_F(TestMockDeepCopyObjectCopyRequest, ReadMissingStaleSnapSet) { C_SaferCond ctx; MockObjectCopyRequest *request = create_request(mock_src_image_ctx, - mock_dst_image_ctx, &ctx); + mock_dst_image_ctx, 0, 0, + &ctx); librados::MockTestMemIoCtxImpl &mock_src_io_ctx(get_mock_io_ctx( request->get_src_io_ctx())); @@ -599,7 +628,8 @@ TEST_F(TestMockDeepCopyObjectCopyRequest, ReadMissingUpToDateSnapMap) { C_SaferCond ctx; MockObjectCopyRequest *request = create_request(mock_src_image_ctx, - mock_dst_image_ctx, &ctx); + mock_dst_image_ctx, 0, 0, + &ctx); librados::MockTestMemIoCtxImpl &mock_src_io_ctx(get_mock_io_ctx( request->get_src_io_ctx())); @@ -633,7 +663,8 @@ TEST_F(TestMockDeepCopyObjectCopyRequest, ReadError) { C_SaferCond ctx; MockObjectCopyRequest *request = create_request(mock_src_image_ctx, - mock_dst_image_ctx, &ctx); + mock_dst_image_ctx, 0, 0, + &ctx); librados::MockTestMemIoCtxImpl &mock_src_io_ctx(get_mock_io_ctx( request->get_src_io_ctx())); @@ -667,7 +698,8 @@ TEST_F(TestMockDeepCopyObjectCopyRequest, WriteError) { C_SaferCond ctx; MockObjectCopyRequest *request = create_request(mock_src_image_ctx, - mock_dst_image_ctx, &ctx); + mock_dst_image_ctx, 0, 0, + &ctx); librados::MockTestMemIoCtxImpl &mock_src_io_ctx(get_mock_io_ctx( request->get_src_io_ctx())); @@ -716,7 +748,8 @@ TEST_F(TestMockDeepCopyObjectCopyRequest, WriteSnaps) { C_SaferCond ctx; MockObjectCopyRequest *request = create_request(mock_src_image_ctx, - mock_dst_image_ctx, &ctx); + mock_dst_image_ctx, 0, 0, + &ctx); librados::MockTestMemIoCtxImpl &mock_src_io_ctx(get_mock_io_ctx( request->get_src_io_ctx())); @@ -781,7 +814,8 @@ TEST_F(TestMockDeepCopyObjectCopyRequest, Trim) { C_SaferCond ctx; MockObjectCopyRequest *request = create_request(mock_src_image_ctx, - mock_dst_image_ctx, &ctx); + mock_dst_image_ctx, 0, 0, + &ctx); librados::MockTestMemIoCtxImpl &mock_src_io_ctx(get_mock_io_ctx( request->get_src_io_ctx())); @@ -834,7 +868,8 @@ TEST_F(TestMockDeepCopyObjectCopyRequest, Remove) { C_SaferCond ctx; MockObjectCopyRequest *request = create_request(mock_src_image_ctx, - mock_dst_image_ctx, &ctx); + mock_dst_image_ctx, 0, 0, + &ctx); librados::MockTestMemIoCtxImpl &mock_src_io_ctx(get_mock_io_ctx( request->get_src_io_ctx())); @@ -885,7 +920,8 @@ TEST_F(TestMockDeepCopyObjectCopyRequest, ObjectMapUpdateError) { C_SaferCond ctx; MockObjectCopyRequest *request = create_request(mock_src_image_ctx, - mock_dst_image_ctx, &ctx); + mock_dst_image_ctx, 0, 0, + &ctx); librados::MockTestMemIoCtxImpl &mock_src_io_ctx(get_mock_io_ctx( request->get_src_io_ctx())); @@ -906,5 +942,99 @@ TEST_F(TestMockDeepCopyObjectCopyRequest, ObjectMapUpdateError) { ASSERT_EQ(-EBLACKLISTED, ctx.wait()); } +TEST_F(TestMockDeepCopyObjectCopyRequest, WriteSnapsStart) { + // scribble some data + interval_set one; + scribble(m_src_image_ctx, 10, 102400, &one); + ASSERT_EQ(0, copy_objects()); + ASSERT_EQ(0, create_snap("one")); + + auto src_snap_id_start = m_src_image_ctx->snaps[0]; + auto dst_snap_id_start = m_dst_image_ctx->snaps[0]; + + interval_set two; + scribble(m_src_image_ctx, 10, 102400, &two); + ASSERT_EQ(0, create_snap("two")); + + interval_set three; + scribble(m_src_image_ctx, 10, 102400, &three); + ASSERT_EQ(0, create_snap("three")); + + auto max_extent = one.range_end(); + if (max_extent < two.range_end()) { + interval_set resize_diff; + resize_diff.insert(max_extent, two.range_end() - max_extent); + two.union_of(resize_diff); + } + + max_extent = std::max(max_extent, two.range_end()); + if (max_extent < three.range_end()) { + interval_set resize_diff; + resize_diff.insert(max_extent, three.range_end() - max_extent); + three.union_of(resize_diff); + } + + interval_set four; + scribble(m_src_image_ctx, 10, 102400, &four); + + // map should begin after src start and src end's dst snap seqs should + // point to HEAD revision + m_snap_map.erase(src_snap_id_start); + m_snap_map[m_src_image_ctx->snaps[0]][0] = CEPH_NOSNAP; + + librbd::MockTestImageCtx mock_src_image_ctx(*m_src_image_ctx); + librbd::MockTestImageCtx mock_dst_image_ctx(*m_dst_image_ctx); + + librbd::MockExclusiveLock mock_exclusive_lock; + prepare_exclusive_lock(mock_dst_image_ctx, mock_exclusive_lock); + + librbd::MockObjectMap mock_object_map; + mock_dst_image_ctx.object_map = &mock_object_map; + + expect_test_features(mock_dst_image_ctx); + expect_get_object_count(mock_dst_image_ctx); + + C_SaferCond ctx; + MockObjectCopyRequest *request = create_request(mock_src_image_ctx, + mock_dst_image_ctx, + src_snap_id_start, + dst_snap_id_start, + &ctx); + + librados::MockTestMemIoCtxImpl &mock_src_io_ctx(get_mock_io_ctx( + request->get_src_io_ctx())); + librados::MockTestMemIoCtxImpl &mock_dst_io_ctx(get_mock_io_ctx( + request->get_dst_io_ctx())); + + InSequence seq; + expect_list_snaps(mock_src_image_ctx, mock_src_io_ctx, 0); + + expect_set_snap_read(mock_src_io_ctx, m_src_snap_ids[1]); + expect_sparse_read(mock_src_io_ctx, two, 0); + + expect_set_snap_read(mock_src_io_ctx, m_src_snap_ids[2]); + expect_sparse_read(mock_src_io_ctx, three, 0); + + expect_start_op(mock_exclusive_lock); + expect_write(mock_dst_io_ctx, two, + {m_dst_snap_ids[0], {m_dst_snap_ids[0]}}, 0); + + expect_start_op(mock_exclusive_lock); + expect_write(mock_dst_io_ctx, three, + {m_dst_snap_ids[1], {m_dst_snap_ids[1], m_dst_snap_ids[0]}}, 0); + + expect_start_op(mock_exclusive_lock); + expect_update_object_map(mock_dst_image_ctx, mock_object_map, + m_dst_snap_ids[1], OBJECT_EXISTS, 0); + + expect_start_op(mock_exclusive_lock); + expect_update_object_map(mock_dst_image_ctx, mock_object_map, + CEPH_NOSNAP, OBJECT_EXISTS, 0); + + request->send(); + ASSERT_EQ(0, ctx.wait()); + ASSERT_EQ(0, compare_objects()); +} + } // namespace deep_copy } // namespace librbd diff --git a/src/test/librbd/io/test_mock_CopyupRequest.cc b/src/test/librbd/io/test_mock_CopyupRequest.cc index c6a28595ae87a..7a30f59a138c2 100644 --- a/src/test/librbd/io/test_mock_CopyupRequest.cc +++ b/src/test/librbd/io/test_mock_CopyupRequest.cc @@ -47,6 +47,8 @@ struct ObjectCopyRequest { static ObjectCopyRequest* s_instance; static ObjectCopyRequest* create(librbd::MockImageCtx* parent_image_ctx, librbd::MockTestImageCtx* image_ctx, + librados::snap_t src_snap_id_start, + librados::snap_t dst_snap_id_start, const SnapMap &snap_map, uint64_t object_number, bool flatten, Context *on_finish) { diff --git a/src/test/librbd/test_mock_DeepCopyRequest.cc b/src/test/librbd/test_mock_DeepCopyRequest.cc index 58877028a697a..483c65aaa5e0a 100644 --- a/src/test/librbd/test_mock_DeepCopyRequest.cc +++ b/src/test/librbd/test_mock_DeepCopyRequest.cc @@ -40,10 +40,12 @@ public: static ImageCopyRequest* create( librbd::MockTestImageCtx *src_image_ctx, - librbd::MockTestImageCtx *dst_image_ctx, librados::snap_t snap_id_start, - librados::snap_t snap_id_end, bool flatten, - const ObjectNumber &object_number, const SnapSeqs &snap_seqs, - ProgressContext *prog_ctx, + librbd::MockTestImageCtx *dst_image_ctx, + librados::snap_t src_snap_id_start, + librados::snap_t src_snap_id_end, + librados::snap_t dst_snap_id_start, + bool flatten, const ObjectNumber &object_number, + const SnapSeqs &snap_seqs, ProgressContext *prog_ctx, Context *on_finish) { ceph_assert(s_instance != nullptr); s_instance->on_finish = on_finish;