]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: ensure deep-copy snapshot map includes all destination snap ids
authorJason Dillaman <dillaman@redhat.com>
Wed, 5 Feb 2020 20:27:39 +0000 (15:27 -0500)
committerJason Dillaman <dillaman@redhat.com>
Thu, 13 Feb 2020 13:11:17 +0000 (08:11 -0500)
When deep-copying from an arbitrary start snapshot id, the snap sequence
will be missing all older snapshots. Additionally, snapshot types that
are not deep-copied still need to be included in the destination snap
map.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/librbd/deep_copy/ImageCopyRequest.cc
src/librbd/deep_copy/ImageCopyRequest.h
src/librbd/deep_copy/Utils.cc
src/librbd/deep_copy/Utils.h
src/librbd/image/RefreshRequest.cc

index 2fd2ed4a40a516da2bd4cabb7797d18ef0132548..75cdae00b8ac3088ea1161a0a16b86cd1bcacc06 100644 (file)
@@ -23,16 +23,16 @@ using librbd::util::unique_lock_name;
 
 template <typename I>
 ImageCopyRequest<I>::ImageCopyRequest(I *src_image_ctx, I *dst_image_ctx,
-                                      librados::snap_t snap_id_start,
-                                      librados::snap_t snap_id_end,
+                                      librados::snap_t src_snap_id_start,
+                                      librados::snap_t src_snap_id_end,
                                       bool flatten,
                                       const ObjectNumber &object_number,
                                       const SnapSeqs &snap_seqs,
                                       ProgressContext *prog_ctx,
                                       Context *on_finish)
   : RefCountedObject(dst_image_ctx->cct), m_src_image_ctx(src_image_ctx),
-    m_dst_image_ctx(dst_image_ctx), m_snap_id_start(snap_id_start),
-    m_snap_id_end(snap_id_end), m_flatten(flatten),
+    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_prog_ctx(prog_ctx), m_on_finish(on_finish), m_cct(dst_image_ctx->cct),
     m_lock(ceph::make_mutex(unique_lock_name("ImageCopyRequest::m_lock", this))) {
@@ -40,8 +40,12 @@ ImageCopyRequest<I>::ImageCopyRequest(I *src_image_ctx, I *dst_image_ctx,
 
 template <typename I>
 void ImageCopyRequest<I>::send() {
-  util::compute_snap_map(m_snap_id_start, m_snap_id_end, m_snap_seqs,
+  m_dst_image_ctx->image_lock.lock_shared();
+  util::compute_snap_map(m_dst_image_ctx->cct, m_src_snap_id_start,
+                         m_src_snap_id_end, m_dst_image_ctx->snaps, m_snap_seqs,
                          &m_snap_map);
+  m_dst_image_ctx->image_lock.unlock_shared();
+
   if (m_snap_map.empty()) {
     lderr(m_cct) << "failed to map snapshots within boundary" << dendl;
     finish(-EINVAL);
index 15c3cd2951d22930a7cef311a61ef0aafe85f295..8b0860087229bca44e3cc3be0f7f4158f9a61f6a 100644 (file)
@@ -30,19 +30,21 @@ class ImageCopyRequest : public RefCountedObject {
 public:
   static ImageCopyRequest* create(ImageCtxT *src_image_ctx,
                                   ImageCtxT *dst_image_ctx,
-                                  librados::snap_t snap_id_start,
-                                  librados::snap_t snap_id_end, bool flatten,
+                                  librados::snap_t src_snap_id_start,
+                                  librados::snap_t src_snap_id_end,
+                                  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, snap_id_start,
-                                snap_id_end, flatten, object_number, snap_seqs,
-                                prog_ctx, 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);
   }
 
   ImageCopyRequest(ImageCtxT *src_image_ctx, ImageCtxT *dst_image_ctx,
-                   librados::snap_t snap_id_start, librados::snap_t snap_id_end,
+                   librados::snap_t src_snap_id_start,
+                   librados::snap_t src_snap_id_end,
                    bool flatten, const ObjectNumber &object_number,
                    const SnapSeqs &snap_seqs, ProgressContext *prog_ctx,
                    Context *on_finish);
@@ -68,8 +70,8 @@ private:
 
   ImageCtxT *m_src_image_ctx;
   ImageCtxT *m_dst_image_ctx;
-  librados::snap_t m_snap_id_start;
-  librados::snap_t m_snap_id_end;
+  librados::snap_t m_src_snap_id_start;
+  librados::snap_t m_src_snap_id_end;
   bool m_flatten;
   ObjectNumber m_object_number;
   SnapSeqs m_snap_seqs;
index 32b96587d194c202cc9c251abeff991606fbdeea..c2dd25020e43bb29158563e4626bf390589da7b8 100644 (file)
@@ -1,29 +1,61 @@
 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
 // vim: ts=8 sw=2 smarttab
 
+#include "common/debug.h"
 #include "Utils.h"
+#include <set>
 
 namespace librbd {
 namespace deep_copy {
 namespace util {
 
-void compute_snap_map(librados::snap_t snap_id_start,
-                      librados::snap_t snap_id_end,
+#define dout_subsys ceph_subsys_rbd
+#undef dout_prefix
+#define dout_prefix *_dout << "librbd::deep_copy::util::" << __func__ << ": "
+
+void compute_snap_map(CephContext* cct,
+                      librados::snap_t src_snap_id_start,
+                      librados::snap_t src_snap_id_end,
+                      const SnapIds& dst_snap_ids,
                       const SnapSeqs &snap_seqs,
                       SnapMap *snap_map) {
+  std::set<librados::snap_t> ordered_dst_snap_ids{
+    dst_snap_ids.begin(), dst_snap_ids.end()};
+  auto dst_snap_id_it = ordered_dst_snap_ids.begin();
+
   SnapIds snap_ids;
   for (auto &it : snap_seqs) {
+    // ensure all dst snap ids are included in the mapping table since
+    // deep copy will skip non-user snapshots
+    while (dst_snap_id_it != ordered_dst_snap_ids.end()) {
+      if (*dst_snap_id_it < it.second) {
+        snap_ids.insert(snap_ids.begin(), *dst_snap_id_it);
+      } else if (*dst_snap_id_it > it.second) {
+        break;
+      }
+      ++dst_snap_id_it;
+    }
+
+    // we should only have the HEAD revision in the the last snap seq
+    ceph_assert(snap_ids.empty() || snap_ids[0] != CEPH_NOSNAP);
     snap_ids.insert(snap_ids.begin(), it.second);
-    if (it.first < snap_id_start) {
+
+    if (it.first < src_snap_id_start) {
       continue;
-    } else if (it.first > snap_id_end) {
+    } else if (it.first > src_snap_id_end) {
       break;
     }
 
     (*snap_map)[it.first] = snap_ids;
   }
+
+  ldout(cct, 10) << "src_snap_id_start=" << src_snap_id_start << ", "
+                 << "src_snap_id_end=" << src_snap_id_end << ", "
+                 << "dst_snap_ids=" << dst_snap_ids << ", "
+                 << "snap_seqs=" << snap_seqs << ", "
+                 << "snap_map=" << *snap_map << dendl;
 }
 
-} // util
+} // namespace util
 } // namespace deep_copy
 } // namespace librbd
index 28e1d6d7ea475d9fd0dfaadbe31f9a789436aea4..0681548db0f079fa5c3285a8ffa0484968e5e7b5 100644 (file)
 
 #include <boost/optional.hpp>
 
+struct CephContext;
+
 namespace librbd {
 namespace deep_copy {
 namespace util {
 
-void compute_snap_map(librados::snap_t snap_id_start,
-                      librados::snap_t snap_id_end,
+void compute_snap_map(CephContext* cct,
+                      librados::snap_t src_snap_id_start,
+                      librados::snap_t src_snap_id_end,
+                      const SnapIds& dst_snap_ids,
                       const SnapSeqs &snap_seqs,
                       SnapMap *snap_map);
 
index eaccf7f36fd7841fd18c1248570b4feb1300a772..adc0afb4b8faf8c7f0771f9c10649f3741e2123b 100644 (file)
@@ -1494,8 +1494,8 @@ bool RefreshRequest<I>::get_migration_info(ParentImageInfo *parent_md,
                      m_migration_spec.image_name, m_migration_spec.image_id, {},
                      overlap, m_migration_spec.flatten};
 
-  deep_copy::util::compute_snap_map(0, CEPH_NOSNAP, snap_seqs,
-                                    &migration_info->snap_map);
+  deep_copy::util::compute_snap_map(m_image_ctx.cct, 0, CEPH_NOSNAP, {},
+                                    snap_seqs, &migration_info->snap_map);
   return true;
 }