]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: create primary mirror snapshot when enabling mirroring
authorJason Dillaman <dillaman@redhat.com>
Thu, 30 Jan 2020 20:35:48 +0000 (15:35 -0500)
committerJason Dillaman <dillaman@redhat.com>
Fri, 31 Jan 2020 04:14:20 +0000 (23:14 -0500)
This will create an initial primary mirror snapshot when enabling
snapshot-based mirroring on an image.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/librbd/api/Migration.cc
src/librbd/mirror/EnableRequest.cc
src/librbd/mirror/EnableRequest.h
src/librbd/mirror/snapshot/CreatePrimaryRequest.cc
src/test/librbd/test_mirroring.cc

index 73294503217710c9e4052ef80ccf9a86a8243f30..a2fb4fb08b2dd2df4a02dd95329561d26a1f2eb0 100644 (file)
@@ -1495,8 +1495,7 @@ int Migration<I>::enable_mirroring(
 
   C_SaferCond ctx;
   auto req = mirror::EnableRequest<I>::create(
-    image_ctx->md_ctx, image_ctx->id, mirror_image_mode, "",
-    image_ctx->op_work_queue, &ctx);
+    image_ctx, mirror_image_mode, &ctx);
   req->send();
   r = ctx.wait();
   if (r < 0) {
index 767ec2590dd162977977cf3b680eac5bb0c0ac35..50f2afb7a48428387f36a150ef8e074ac731c06f 100644 (file)
@@ -9,6 +9,7 @@
 #include "librbd/Journal.h"
 #include "librbd/Utils.h"
 #include "librbd/mirror/ImageStateUpdateRequest.h"
+#include "librbd/mirror/snapshot/CreatePrimaryRequest.h"
 
 #define dout_subsys ceph_subsys_rbd
 #undef dout_prefix
@@ -24,10 +25,11 @@ using util::create_rados_callback;
 template <typename I>
 EnableRequest<I>::EnableRequest(librados::IoCtx &io_ctx,
                                 const std::string &image_id,
+                                I* image_ctx,
                                 cls::rbd::MirrorImageMode mode,
                                 const std::string &non_primary_global_image_id,
                                 ContextWQ *op_work_queue, Context *on_finish)
-  : m_io_ctx(io_ctx), m_image_id(image_id),
+  : m_io_ctx(io_ctx), m_image_id(image_id), m_image_ctx(image_ctx),
     m_mode(mode), m_non_primary_global_image_id(non_primary_global_image_id),
     m_op_work_queue(op_work_queue), m_on_finish(on_finish),
     m_cct(reinterpret_cast<CephContext*>(io_ctx.cct())) {
@@ -35,11 +37,11 @@ EnableRequest<I>::EnableRequest(librados::IoCtx &io_ctx,
 
 template <typename I>
 void EnableRequest<I>::send() {
-  send_get_mirror_image();
+  get_mirror_image();
 }
 
 template <typename I>
-void EnableRequest<I>::send_get_mirror_image() {
+void EnableRequest<I>::get_mirror_image() {
   ldout(m_cct, 10) << dendl;
 
   librados::ObjectReadOperation op;
@@ -55,34 +57,36 @@ void EnableRequest<I>::send_get_mirror_image() {
 }
 
 template <typename I>
-Context *EnableRequest<I>::handle_get_mirror_image(int *result) {
-  ldout(m_cct, 10) << "r=" << *result << dendl;
+void EnableRequest<I>::handle_get_mirror_image(int r) {
+  ldout(m_cct, 10) << "r=" << r << dendl;
 
-  if (*result == 0) {
+  if (r == 0) {
     auto iter = m_out_bl.cbegin();
-    *result = cls_client::mirror_image_get_finish(&iter, &m_mirror_image);
+    r = cls_client::mirror_image_get_finish(&iter, &m_mirror_image);
   }
 
-  if (*result == 0) {
+  if (r == 0) {
     if (m_mirror_image.mode != m_mode) {
       lderr(m_cct) << "invalid current image mirror mode" << dendl;
-      *result = -EINVAL;
+      r = -EINVAL;
     } else if (m_mirror_image.state == cls::rbd::MIRROR_IMAGE_STATE_ENABLED) {
       ldout(m_cct, 10) << "mirroring is already enabled" << dendl;
     } else {
       lderr(m_cct) << "currently disabling" << dendl;
-      *result = -EINVAL;
+      r = -EINVAL;
     }
-    return m_on_finish;
+    finish(r);
+    return;
   }
 
-  if (*result != -ENOENT) {
-    lderr(m_cct) << "failed to retrieve mirror image: " << cpp_strerror(*result)
+  if (r != -ENOENT) {
+    lderr(m_cct) << "failed to retrieve mirror image: " << cpp_strerror(r)
                  << dendl;
-    return m_on_finish;
+    finish(r);
+    return;
   }
 
-  *result = 0;
+  r = 0;
   m_mirror_image.mode = m_mode;
   if (m_non_primary_global_image_id.empty()) {
     uuid_d uuid_gen;
@@ -92,17 +96,17 @@ Context *EnableRequest<I>::handle_get_mirror_image(int *result) {
     m_mirror_image.global_image_id = m_non_primary_global_image_id;
   }
 
-  send_get_tag_owner();
-  return nullptr;
+  get_tag_owner();
 }
 
 template <typename I>
-void EnableRequest<I>::send_get_tag_owner() {
+void EnableRequest<I>::get_tag_owner() {
   if (m_mirror_image.mode == cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT ||
       !m_non_primary_global_image_id.empty()) {
-    send_image_state_update();
+    create_primary_snapshot();
     return;
   }
+
   ldout(m_cct, 10)  << dendl;
 
   using klass = EnableRequest<I>;
@@ -113,27 +117,53 @@ void EnableRequest<I>::send_get_tag_owner() {
 }
 
 template <typename I>
-Context *EnableRequest<I>::handle_get_tag_owner(int *result) {
-  ldout(m_cct, 10) << "r=" << *result << dendl;
+void EnableRequest<I>::handle_get_tag_owner(int r) {
+  ldout(m_cct, 10) << "r=" << r << dendl;
 
-  if (*result < 0) {
-    lderr(m_cct) << "failed to check tag ownership: " << cpp_strerror(*result)
+  if (r < 0) {
+    lderr(m_cct) << "failed to check tag ownership: " << cpp_strerror(r)
                  << dendl;
-    return m_on_finish;
+    finish(r);
+    return;
   }
 
   if (!m_is_primary) {
     lderr(m_cct) << "last journal tag not owned by local cluster" << dendl;
-    *result = -EINVAL;
-    return m_on_finish;
+    finish(-EINVAL);
+    return;
   }
 
-  send_image_state_update();
-  return nullptr;
+  image_state_update();
 }
 
 template <typename I>
-void EnableRequest<I>::send_image_state_update() {
+void EnableRequest<I>::create_primary_snapshot() {
+  if (!m_non_primary_global_image_id.empty()) {
+    image_state_update();
+    return;
+  }
+
+  ldout(m_cct, 10) << dendl;
+
+  ceph_assert(m_image_ctx != nullptr);
+  auto ctx = create_context_callback<
+    EnableRequest<I>,
+    &EnableRequest<I>::handle_create_primary_snapshot>(this);
+  auto req = snapshot::CreatePrimaryRequest<I>::create(
+    m_image_ctx, m_mirror_image.global_image_id,
+    snapshot::CREATE_PRIMARY_FLAG_IGNORE_EMPTY_PEERS, &m_snap_id, ctx);
+  req->send();
+}
+
+template <typename I>
+void EnableRequest<I>::handle_create_primary_snapshot(int r) {
+  ldout(m_cct, 10) << "r=" << r << dendl;
+
+  image_state_update();
+}
+
+template <typename I>
+void EnableRequest<I>::image_state_update() {
   ldout(m_cct, 10) << dendl;
 
   auto ctx = create_context_callback<
@@ -145,15 +175,23 @@ void EnableRequest<I>::send_image_state_update() {
 }
 
 template <typename I>
-Context *EnableRequest<I>::handle_image_state_update(int *result) {
-  ldout(m_cct, 10) << "r=" << *result << dendl;
+void EnableRequest<I>::handle_image_state_update(int r) {
+  ldout(m_cct, 10) << "r=" << r << dendl;
 
-  if (*result < 0) {
-    lderr(m_cct) << "failed to enable mirroring: " << cpp_strerror(*result)
+  if (r < 0) {
+    lderr(m_cct) << "failed to enable mirroring: " << cpp_strerror(r)
                  << dendl;
   }
 
-  return m_on_finish;
+  finish(r);
+}
+
+template <typename I>
+void EnableRequest<I>::finish(int r) {
+  ldout(m_cct, 10) << "r=" << r << dendl;
+
+  m_on_finish->complete(r);
+  delete this;
 }
 
 } // namespace mirror
index 374f038c86d11a1835b9939a00af49f8a76ac3b6..853e96a7efca37c478ea1e6bc98250c5f8ff9ccd 100644 (file)
@@ -9,6 +9,7 @@
 #include "include/rbd/librbd.hpp"
 #include "cls/rbd/cls_rbd_types.h"
 #include "librbd/ImageCtx.h"
+#include "librbd/mirror/Types.h"
 #include <map>
 #include <string>
 
@@ -24,15 +25,15 @@ public:
   static EnableRequest *create(ImageCtxT *image_ctx,
                                cls::rbd::MirrorImageMode mode,
                                Context *on_finish) {
-    return create(image_ctx->md_ctx, image_ctx->id, mode, "",
-                  image_ctx->op_work_queue, on_finish);
+    return new EnableRequest(image_ctx->md_ctx, image_ctx->id, image_ctx, mode,
+                             "", image_ctx->op_work_queue, on_finish);
   }
   static EnableRequest *create(librados::IoCtx &io_ctx,
                                const std::string &image_id,
                                cls::rbd::MirrorImageMode mode,
                                const std::string &non_primary_global_image_id,
                                ContextWQ *op_work_queue, Context *on_finish) {
-    return new EnableRequest(io_ctx, image_id, mode,
+    return new EnableRequest(io_ctx, image_id, nullptr, mode,
                              non_primary_global_image_id, op_work_queue,
                              on_finish);
   }
@@ -48,9 +49,12 @@ private:
    *    v
    * GET_MIRROR_IMAGE * * * * * * *
    *    |                         * (on error)
-   *    v                         *
+   *    v (skip if not needed)    *
    * GET_TAG_OWNER  * * * * * * * *
-   *    |  (skip if not needed)   *
+   *    |                         *
+   *    v (skip if not needed)    *
+   * CREATE_PRIMARY_SNAPSHOT  * * *
+   *    |                         *
    *    v                         *
    * IMAGE_STATE_UPDATE * * * * * *
    *    |                         *
@@ -61,33 +65,38 @@ private:
    */
 
   EnableRequest(librados::IoCtx &io_ctx, const std::string &image_id,
-                cls::rbd::MirrorImageMode mode,
+                ImageCtxT* image_ctx, cls::rbd::MirrorImageMode mode,
                 const std::string &non_primary_global_image_id,
                 ContextWQ *op_work_queue, Context *on_finish);
 
   librados::IoCtx &m_io_ctx;
   std::string m_image_id;
+  ImageCtxT* m_image_ctx;
   cls::rbd::MirrorImageMode m_mode;
   std::string m_non_primary_global_image_id;
   ContextWQ *m_op_work_queue;
   Context *m_on_finish;
 
   CephContext *m_cct = nullptr;
-  bool m_is_primary = false;
   bufferlist m_out_bl;
   cls::rbd::MirrorImage m_mirror_image;
 
-  void send_get_mirror_image();
-  Context *handle_get_mirror_image(int *result);
+  bool m_is_primary = false;
+  uint64_t m_snap_id = CEPH_NOSNAP;
+
+  void get_mirror_image();
+  void handle_get_mirror_image(int r);
+
+  void get_tag_owner();
+  void handle_get_tag_owner(int r);
 
-  void send_get_features();
-  Context *handle_get_features(int *result);
+  void create_primary_snapshot();
+  void handle_create_primary_snapshot(int r);
 
-  void send_get_tag_owner();
-  Context *handle_get_tag_owner(int *result);
+  void image_state_update();
+  void handle_image_state_update(int r);
 
-  void send_image_state_update();
-  Context *handle_image_state_update(int *result);
+  void finish(int r);
 };
 
 } // namespace mirror
index c4e8547546883541c12f092653100d0ef38c47a9..4343935eafa801a5ea3b971f86a1402b2d1d2572 100644 (file)
@@ -172,9 +172,6 @@ void CreatePrimaryRequest<I>::unlink_peer() {
         prev_snap_id = 0;
         continue;
       }
-      if (info->mirror_peer_uuids.count(peer) == 0) {
-        continue;
-      }
       count++;
       if (count == max_snapshots - 1) {
         prev_snap_id = snap_it.first;
index c805fb778fe31abbb3a8bf6f107795f54b7b0b10..76acec6919580fe3dc1e1d0da5aee32d53cd0600 100644 (file)
@@ -1137,8 +1137,8 @@ TEST_F(TestMirroring, Snapshot)
   ASSERT_EQ(0, image.mirror_image_create_snapshot(&snap_id));
   vector<librbd::snap_info_t> snaps;
   ASSERT_EQ(0, image.snap_list(snaps));
-  ASSERT_EQ(1U, snaps.size());
-  ASSERT_EQ(snaps[0].id, snap_id);
+  ASSERT_EQ(2U, snaps.size());
+  ASSERT_EQ(snaps[1].id, snap_id);
 
   ASSERT_EQ(0, image.mirror_image_create_snapshot(&snap_id));
   ASSERT_EQ(0, image.mirror_image_create_snapshot(&snap_id));
@@ -1198,8 +1198,8 @@ TEST_F(TestMirroring, SnapshotRemoveOnDisable)
 
   vector<librbd::snap_info_t> snaps;
   ASSERT_EQ(0, image.snap_list(snaps));
-  ASSERT_EQ(1U, snaps.size());
-  ASSERT_EQ(snaps[0].id, snap_id);
+  ASSERT_EQ(2U, snaps.size());
+  ASSERT_EQ(snaps[1].id, snap_id);
 
   ASSERT_EQ(0, image.mirror_image_disable(false));