]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd-mirror: helper abstraction layer for image sync points
authorJason Dillaman <dillaman@redhat.com>
Wed, 8 Jan 2020 00:32:19 +0000 (19:32 -0500)
committerJason Dillaman <dillaman@redhat.com>
Thu, 9 Jan 2020 15:48:52 +0000 (10:48 -0500)
The initial implementation interfaces with the remote journal
to store the sync points and snapshot sequence map in the
client meta.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/tools/rbd_mirror/CMakeLists.txt
src/tools/rbd_mirror/image_replayer/StateBuilder.cc
src/tools/rbd_mirror/image_replayer/StateBuilder.h
src/tools/rbd_mirror/image_replayer/journal/StateBuilder.cc
src/tools/rbd_mirror/image_replayer/journal/StateBuilder.h
src/tools/rbd_mirror/image_replayer/journal/SyncPointHandler.cc [new file with mode: 0644]
src/tools/rbd_mirror/image_replayer/journal/SyncPointHandler.h [new file with mode: 0644]
src/tools/rbd_mirror/image_sync/Types.h [new file with mode: 0644]

index b920d1d8d80ffb72dd6c1cd86f8085ca74aed4e4..60dff58144ac122fc89fdc875af1274a439f9b30 100644 (file)
@@ -48,6 +48,7 @@ set(rbd_mirror_internal
   image_replayer/journal/Replayer.cc
   image_replayer/journal/ReplayStatusFormatter.cc
   image_replayer/journal/StateBuilder.cc
+  image_replayer/journal/SyncPointHandler.cc
   image_sync/SyncPointCreateRequest.cc
   image_sync/SyncPointPruneRequest.cc
   pool_watcher/RefreshImagesRequest.cc
index b740e0bd4d0926cb499b74329ca2eb5fc306795a..7c45648b87b4aa3fa8c6e704a31a681a89c4cf7b 100644 (file)
@@ -9,6 +9,7 @@
 #include "journal/Journaler.h"
 #include "librbd/ImageCtx.h"
 #include "tools/rbd_mirror/image_replayer/CloseImageRequest.h"
+#include "tools/rbd_mirror/image_sync/Types.h"
 
 #define dout_context g_ceph_context
 #define dout_subsys ceph_subsys_rbd_mirror
@@ -30,6 +31,7 @@ StateBuilder<I>::StateBuilder(const std::string& global_image_id)
 template <typename I>
 StateBuilder<I>::~StateBuilder() {
   ceph_assert(local_image_ctx == nullptr);
+  ceph_assert(m_sync_point_handler == nullptr);
 }
 
 template <typename I>
@@ -61,6 +63,17 @@ void StateBuilder<I>::handle_close_local_image(int r, Context* on_finish) {
   on_finish->complete(r);
 }
 
+template <typename I>
+void StateBuilder<I>::destroy_sync_point_handler() {
+  if (m_sync_point_handler == nullptr) {
+    return;
+  }
+
+  dout(15) << dendl;
+  m_sync_point_handler->destroy();
+  m_sync_point_handler = nullptr;
+}
+
 } // namespace image_replayer
 } // namespace mirror
 } // namespace rbd
index 81f26d4c563573d722cdcf559314aefb63dda979..b506fc24e75f6d0872a4bd490b03ed6958e75a77 100644 (file)
@@ -11,6 +11,9 @@ namespace librbd { struct ImageCtx; }
 
 namespace rbd {
 namespace mirror {
+
+namespace image_sync { struct SyncPointHandler; }
+
 namespace image_replayer {
 
 template <typename ImageCtxT>
@@ -34,6 +37,9 @@ public:
 
   virtual cls::rbd::MirrorImageMode get_mirror_image_mode() const = 0;
 
+  virtual image_sync::SyncPointHandler* create_sync_point_handler() = 0;
+  void destroy_sync_point_handler();
+
   std::string global_image_id;
 
   std::string local_image_id;
@@ -43,12 +49,13 @@ public:
   std::string remote_image_id;
 
 protected:
+  image_sync::SyncPointHandler* m_sync_point_handler = nullptr;
+
   StateBuilder(const std::string& global_image_id);
 
   void close_local_image(Context* on_finish);
 
 private:
-
   void handle_close_local_image(int r, Context* on_finish);
 };
 
index db8b7ab5f8fbdc513e3ab6b5d2191e8c3beceee7..edab1a3cabcb9d7a3f2243af350a07227060a806 100644 (file)
@@ -9,6 +9,7 @@
 #include "journal/Journaler.h"
 #include "librbd/ImageCtx.h"
 #include "librbd/Journal.h"
+#include "tools/rbd_mirror/image_replayer/journal/SyncPointHandler.h"
 
 #define dout_context g_ceph_context
 #define dout_subsys ceph_subsys_rbd_mirror
@@ -66,6 +67,14 @@ cls::rbd::MirrorImageMode StateBuilder<I>::get_mirror_image_mode() const {
   return cls::rbd::MIRROR_IMAGE_MODE_JOURNAL;
 }
 
+template <typename I>
+image_sync::SyncPointHandler* StateBuilder<I>::create_sync_point_handler() {
+  dout(10) << dendl;
+
+  this->m_sync_point_handler = SyncPointHandler<I>::create(this);
+  return this->m_sync_point_handler;
+}
+
 template <typename I>
 void StateBuilder<I>::shut_down_remote_journaler(Context* on_finish) {
   if (remote_journaler == nullptr) {
index 751c09bc1c8c4c1df1418338800e0b8beed65568..5d9edba47ceba0a7441eb80274e13308e27fc12b 100644 (file)
@@ -19,6 +19,8 @@ namespace mirror {
 namespace image_replayer {
 namespace journal {
 
+template <typename> class SyncPointHandler;
+
 template <typename ImageCtxT>
 class StateBuilder : public image_replayer::StateBuilder<ImageCtxT> {
 public:
@@ -41,6 +43,8 @@ public:
 
   cls::rbd::MirrorImageMode get_mirror_image_mode() const override;
 
+  image_sync::SyncPointHandler* create_sync_point_handler() override;
+
   std::string local_tag_owner;
 
   Journaler* remote_journaler = nullptr;
@@ -48,6 +52,8 @@ public:
     cls::journal::CLIENT_STATE_CONNECTED;
   librbd::journal::MirrorPeerClientMeta remote_client_meta;
 
+  SyncPointHandler<ImageCtxT>* sync_point_handler = nullptr;
+
 private:
 
   void shut_down_remote_journaler(Context* on_finish);
diff --git a/src/tools/rbd_mirror/image_replayer/journal/SyncPointHandler.cc b/src/tools/rbd_mirror/image_replayer/journal/SyncPointHandler.cc
new file mode 100644 (file)
index 0000000..66d13e5
--- /dev/null
@@ -0,0 +1,109 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "SyncPointHandler.h"
+#include "StateBuilder.h"
+#include "include/ceph_assert.h"
+#include "include/Context.h"
+#include "common/debug.h"
+#include "common/errno.h"
+#include "journal/Journaler.h"
+#include "librbd/ImageCtx.h"
+
+#define dout_context g_ceph_context
+#define dout_subsys ceph_subsys_rbd_mirror
+#undef dout_prefix
+#define dout_prefix *_dout << "rbd::mirror::image_replayer::journal::" \
+                           << "SyncPointHandler: " << this << " " \
+                           << __func__ << ": "
+
+namespace rbd {
+namespace mirror {
+namespace image_replayer {
+namespace journal {
+
+template <typename I>
+SyncPointHandler<I>::SyncPointHandler(StateBuilder<I>* state_builder)
+  : m_state_builder(state_builder),
+    m_client_meta_copy(state_builder->remote_client_meta) {
+}
+
+template <typename I>
+typename SyncPointHandler<I>::SyncPoints
+SyncPointHandler<I>::get_sync_points() const {
+  SyncPoints sync_points;
+  for (auto& sync_point : m_client_meta_copy.sync_points) {
+    sync_points.emplace_back(
+      sync_point.snap_namespace,
+      sync_point.snap_name,
+      sync_point.from_snap_name,
+      sync_point.object_number);
+  }
+  return sync_points;
+}
+
+template <typename I>
+librbd::SnapSeqs SyncPointHandler<I>::get_snap_seqs() const {
+  return m_client_meta_copy.snap_seqs;
+}
+
+template <typename I>
+void SyncPointHandler<I>::update_sync_points(
+    const librbd::SnapSeqs& snap_seqs, const SyncPoints& sync_points,
+    bool sync_complete, Context* on_finish) {
+  dout(10) << dendl;
+
+  if (sync_complete && sync_points.empty()) {
+    m_client_meta_copy.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
+  }
+
+  m_client_meta_copy.snap_seqs = snap_seqs;
+  m_client_meta_copy.sync_points.clear();
+  for (auto& sync_point : sync_points) {
+    m_client_meta_copy.sync_points.emplace_back(
+      sync_point.snap_namespace,
+      sync_point.snap_name,
+      sync_point.from_snap_name,
+      sync_point.object_number);
+
+    if (sync_point.object_number) {
+      m_client_meta_copy.sync_object_count = std::max(
+        m_client_meta_copy.sync_object_count, *sync_point.object_number + 1);
+    }
+  }
+
+  dout(20) << "client_meta=" << m_client_meta_copy << dendl;
+  bufferlist client_data_bl;
+  librbd::journal::ClientData client_data{m_client_meta_copy};
+  encode(client_data, client_data_bl);
+
+  auto ctx = new LambdaContext([this, on_finish](int r) {
+      handle_update_sync_points(r, on_finish);
+    });
+  m_state_builder->remote_journaler->update_client(client_data_bl, ctx);
+}
+
+template <typename I>
+void SyncPointHandler<I>::handle_update_sync_points(int r, Context* on_finish) {
+  dout(10) << "r=" << r << dendl;
+
+  if (r >= 0) {
+    m_state_builder->remote_client_meta.snap_seqs =
+      m_client_meta_copy.snap_seqs;
+    m_state_builder->remote_client_meta.sync_points =
+      m_client_meta_copy.sync_points;
+  } else {
+    derr << "failed to update remote journal client meta for image "
+         << m_state_builder->global_image_id << ": " << cpp_strerror(r)
+         << dendl;
+  }
+
+  on_finish->complete(r);
+}
+
+} // namespace journal
+} // namespace image_sync
+} // namespace mirror
+} // namespace rbd
+
+template class rbd::mirror::image_replayer::journal::SyncPointHandler<librbd::ImageCtx>;
diff --git a/src/tools/rbd_mirror/image_replayer/journal/SyncPointHandler.h b/src/tools/rbd_mirror/image_replayer/journal/SyncPointHandler.h
new file mode 100644 (file)
index 0000000..b4f492c
--- /dev/null
@@ -0,0 +1,55 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#ifndef RBD_MIRROR_IMAGE_REPLAYER_JOURNAL_SYNC_POINT_HANDLER_H
+#define RBD_MIRROR_IMAGE_REPLAYER_JOURNAL_SYNC_POINT_HANDLER_H
+
+#include "tools/rbd_mirror/image_sync/Types.h"
+#include "librbd/journal/Types.h"
+
+struct Context;
+namespace librbd { struct ImageCtx; }
+
+namespace rbd {
+namespace mirror {
+namespace image_replayer {
+namespace journal {
+
+template <typename> class StateBuilder;
+
+template <typename ImageCtxT>
+class SyncPointHandler : public image_sync::SyncPointHandler {
+public:
+  using SyncPoint = image_sync::SyncPoint;
+  using SyncPoints = image_sync::SyncPoints;
+
+  static SyncPointHandler* create(StateBuilder<ImageCtxT>* state_builder) {
+    return new SyncPointHandler(state_builder);
+  }
+  SyncPointHandler(StateBuilder<ImageCtxT>* state_builder);
+
+  SyncPoints get_sync_points() const override;
+  librbd::SnapSeqs get_snap_seqs() const override;
+
+  void update_sync_points(const librbd::SnapSeqs& snap_seqs,
+                          const SyncPoints& sync_points,
+                          bool sync_complete,
+                          Context* on_finish) override;
+
+private:
+  StateBuilder<ImageCtxT>* m_state_builder;
+
+  librbd::journal::MirrorPeerClientMeta m_client_meta_copy;
+
+  void handle_update_sync_points(int r, Context* on_finish);
+
+};
+
+} // namespace journal
+} // namespace image_sync
+} // namespace mirror
+} // namespace rbd
+
+extern template class rbd::mirror::image_replayer::journal::SyncPointHandler<librbd::ImageCtx>;
+
+#endif // RBD_MIRROR_IMAGE_REPLAYER_JOURNAL_SYNC_POINT_HANDLER_H
diff --git a/src/tools/rbd_mirror/image_sync/Types.h b/src/tools/rbd_mirror/image_sync/Types.h
new file mode 100644 (file)
index 0000000..d748dc9
--- /dev/null
@@ -0,0 +1,74 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#ifndef RBD_MIRROR_IMAGE_SYNC_TYPES_H
+#define RBD_MIRROR_IMAGE_SYNC_TYPES_H
+
+#include "cls/rbd/cls_rbd_types.h"
+#include "librbd/Types.h"
+#include <list>
+#include <string>
+#include <boost/optional.hpp>
+
+struct Context;
+
+namespace rbd {
+namespace mirror {
+namespace image_sync {
+
+struct SyncPoint {
+  typedef boost::optional<uint64_t> ObjectNumber;
+
+  SyncPoint() {
+  }
+  SyncPoint(const cls::rbd::SnapshotNamespace& snap_namespace,
+            const std::string& snap_name,
+            const std::string& from_snap_name,
+            const ObjectNumber& object_number)
+    : snap_namespace(snap_namespace), snap_name(snap_name),
+      from_snap_name(from_snap_name), object_number(object_number) {
+  }
+
+  cls::rbd::SnapshotNamespace snap_namespace =
+    {cls::rbd::UserSnapshotNamespace{}};
+  std::string snap_name;
+  std::string from_snap_name;
+  ObjectNumber object_number = boost::none;
+
+  bool operator==(const SyncPoint& rhs) const {
+    return (snap_namespace == rhs.snap_namespace &&
+            snap_name == rhs.snap_name &&
+            from_snap_name == rhs.from_snap_name &&
+            object_number == rhs.object_number);
+  }
+};
+
+typedef std::list<SyncPoint> SyncPoints;
+
+struct SyncPointHandler {
+public:
+  SyncPointHandler(const SyncPointHandler&) = delete;
+  SyncPointHandler& operator=(const SyncPointHandler&) = delete;
+
+  virtual ~SyncPointHandler() {}
+  virtual void destroy() {
+    delete this;
+  }
+
+  virtual SyncPoints get_sync_points() const = 0;
+  virtual librbd::SnapSeqs get_snap_seqs() const = 0;
+
+  virtual void update_sync_points(const librbd::SnapSeqs& snap_seq,
+                                  const SyncPoints& sync_points,
+                                  bool sync_complete,
+                                  Context* on_finish) = 0;
+
+protected:
+  SyncPointHandler() {}
+};
+
+} // namespace image_sync
+} // namespace mirror
+} // namespace rbd
+
+#endif // RBD_MIRROR_IMAGE_SYNC_TYPES_H