]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: fix deep copy skipping clean object
authorMykola Golub <mgolub@suse.com>
Wed, 2 Dec 2020 12:25:56 +0000 (12:25 +0000)
committerMykola Golub <mgolub@suse.com>
Wed, 2 Dec 2020 12:25:56 +0000 (12:25 +0000)
We need to map the destination object to source object(s) first
when deciding if we can skip copying.

Signed-off-by: Mykola Golub <mgolub@suse.com>
src/librbd/deep_copy/ImageCopyRequest.cc
src/librbd/deep_copy/ImageCopyRequest.h

index 859b13adb6ce96fff4245381ff0a14ecbfd43dd5..716341891c5a6ca34965eb321966385b73841b2c 100644 (file)
@@ -64,6 +64,30 @@ void ImageCopyRequest<I>::cancel() {
   m_canceled = true;
 }
 
+template <typename I>
+void ImageCopyRequest<I>::map_src_objects(uint64_t dst_object,
+                                          std::set<uint64_t> *src_objects) {
+  std::vector<std::pair<uint64_t, uint64_t>> 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<object_t, std::vector<ObjectExtent>> 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 <typename I>
 void ImageCopyRequest<I>::compute_diff() {
   ldout(m_cct, 10) << dendl;
@@ -147,10 +171,24 @@ int ImageCopyRequest<I>::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<uint64_t> 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;
index 63b4bf3daaf4e77188d36e6b33a68a201d99ec82..9b7934dd35adb9ae98ee3f0b7beb2015d7b2bd66 100644 (file)
@@ -14,6 +14,7 @@
 #include <functional>
 #include <map>
 #include <queue>
+#include <set>
 #include <vector>
 #include <boost/optional.hpp>
 
@@ -102,6 +103,8 @@ private:
 
   BitVector<2> m_object_diff_state;
 
+  void map_src_objects(uint64_t dst_object, std::set<uint64_t> *src_objects);
+
   void compute_diff();
   void handle_compute_diff(int r);