From 3f892b8e0d200becb3ef39e20d759c3ed67dcba8 Mon Sep 17 00:00:00 2001 From: Mykola Golub Date: Wed, 2 Dec 2020 12:25:56 +0000 Subject: [PATCH] librbd: fix deep copy skipping clean object We need to map the destination object to source object(s) first when deciding if we can skip copying. Signed-off-by: Mykola Golub --- src/librbd/deep_copy/ImageCopyRequest.cc | 46 +++++++++++++++++++++--- src/librbd/deep_copy/ImageCopyRequest.h | 3 ++ 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/librbd/deep_copy/ImageCopyRequest.cc b/src/librbd/deep_copy/ImageCopyRequest.cc index 859b13adb6ce9..716341891c5a6 100644 --- a/src/librbd/deep_copy/ImageCopyRequest.cc +++ b/src/librbd/deep_copy/ImageCopyRequest.cc @@ -64,6 +64,30 @@ void ImageCopyRequest::cancel() { m_canceled = true; } +template +void ImageCopyRequest::map_src_objects(uint64_t dst_object, + std::set *src_objects) { + std::vector> image_extents; + Striper::extent_to_file(m_cct, &m_dst_image_ctx->layout, dst_object, 0, + m_dst_image_ctx->layout.object_size, image_extents); + + for (auto &e : image_extents) { + std::map> src_object_extents; + Striper::file_to_extents(m_cct, m_src_image_ctx->format_string, + &m_src_image_ctx->layout, e.first, e.second, 0, + src_object_extents); + for (auto &p : src_object_extents) { + for (auto &s : p.second) { + src_objects->insert(s.objectno); + } + } + } + + ceph_assert(!src_objects->empty()); + + ldout(m_cct, 20) << dst_object << " -> " << *src_objects << dendl; +} + template void ImageCopyRequest::compute_diff() { ldout(m_cct, 10) << dendl; @@ -147,10 +171,24 @@ int ImageCopyRequest::send_next_object_copy() { } uint64_t ono = m_object_no++; - if (ono < m_object_diff_state.size() && - m_object_diff_state[ono] == object_map::DIFF_STATE_NONE) { - ldout(m_cct, 20) << "skipping clean object " << ono << dendl; - return 1; + + if (m_object_diff_state.size() > 0) { + std::set src_objects; + map_src_objects(ono, &src_objects); + + bool skip = true; + for (auto src_ono : src_objects) { + if (src_ono >= m_object_diff_state.size() || + m_object_diff_state[src_ono] != object_map::DIFF_STATE_NONE) { + skip = false; + break; + } + } + + if (skip) { + ldout(m_cct, 20) << "skipping clean object " << ono << dendl; + return 1; + } } ldout(m_cct, 20) << "object_num=" << ono << dendl; diff --git a/src/librbd/deep_copy/ImageCopyRequest.h b/src/librbd/deep_copy/ImageCopyRequest.h index 63b4bf3daaf4e..9b7934dd35adb 100644 --- a/src/librbd/deep_copy/ImageCopyRequest.h +++ b/src/librbd/deep_copy/ImageCopyRequest.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -102,6 +103,8 @@ private: BitVector<2> m_object_diff_state; + void map_src_objects(uint64_t dst_object, std::set *src_objects); + void compute_diff(); void handle_compute_diff(int r); -- 2.39.5