]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd-mirror: fix issue with snapshot-based mirroring deletion propagation
authorJason Dillaman <dillaman@redhat.com>
Thu, 27 Feb 2020 02:49:25 +0000 (21:49 -0500)
committerJason Dillaman <dillaman@redhat.com>
Thu, 27 Feb 2020 21:33:21 +0000 (16:33 -0500)
The mirror uuid is only used for journal-based mirroring to determine if
the images are linked. Snapshot-based mirroring needs to ensure the
mirror peer uuid is still initialized even if the image isn't available.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/test/rbd_mirror/image_replayer/test_mock_PrepareLocalImageRequest.cc
src/test/rbd_mirror/image_replayer/test_mock_PrepareRemoteImageRequest.cc
src/tools/rbd_mirror/image_replayer/BootstrapRequest.cc
src/tools/rbd_mirror/image_replayer/PrepareLocalImageRequest.cc
src/tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.cc
src/tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.h
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

index 1888607a622416e2a9e0d33eff93e415da2b7440..d2cb1afb67735881027293563e597bd2b6f6bdc4 100644 (file)
@@ -101,7 +101,6 @@ struct StateBuilder<librbd::MockTestImageCtx> {
 
   std::string local_image_id;
   librbd::mirror::PromotionState local_promotion_state;
-  std::string local_primary_mirror_uuid;
 };
 
 GetMirrorImageIdRequest<librbd::MockTestImageCtx>* GetMirrorImageIdRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
@@ -116,6 +115,8 @@ struct StateBuilder<librbd::MockTestImageCtx>
   cls::rbd::MirrorImageMode mirror_image_mode =
     cls::rbd::MIRROR_IMAGE_MODE_JOURNAL;
 
+  std::string local_primary_mirror_uuid;
+
   static StateBuilder* create(const std::string&) {
     ceph_assert(s_instance != nullptr);
     return s_instance;
@@ -298,8 +299,6 @@ TEST_F(TestMockImageReplayerPrepareLocalImageRequest, SuccessSnapshot) {
             mock_journal_state_builder.mirror_image_mode);
   ASSERT_EQ(librbd::mirror::PROMOTION_STATE_NON_PRIMARY,
             mock_journal_state_builder.local_promotion_state);
-  ASSERT_EQ(std::string("remote mirror uuid"),
-            mock_journal_state_builder.local_primary_mirror_uuid);
 }
 
 TEST_F(TestMockImageReplayerPrepareLocalImageRequest, MirrorImageIdError) {
index 04ee88205db6dc682e8cefba3e5ba8c01b4d5a16..ae03f708c085f90dd4cd8a9b7895d904bb6bd655 100644 (file)
@@ -120,6 +120,8 @@ struct GetMirrorImageIdRequest<librbd::MockTestImageCtx> {
 template<>
 struct StateBuilder<librbd::MockTestImageCtx> {
   std::string local_image_id;
+  librbd::mirror::PromotionState local_promotion_state =
+    librbd::mirror::PROMOTION_STATE_NON_PRIMARY;
   std::string remote_image_id;
   std::string remote_mirror_uuid;
   librbd::mirror::PromotionState remote_promotion_state;
index b4b237d044f428a6197a791833f4fae82e35ba71..0ec96c58f8f9c393a76a903f0b9e8168e980e9f7 100644 (file)
@@ -178,7 +178,14 @@ void BootstrapRequest<I>::handle_prepare_remote_image(int r) {
     finish(r);
     return;
   } else if (r == -ENOENT || state_builder == nullptr) {
-    dout(10) << "remote image does not exist" << dendl;
+    dout(10) << "remote image does not exist";
+    if (state_builder != nullptr) {
+      *_dout << ": "
+             << "local_image_id=" << state_builder->local_image_id  << ", "
+             << "remote_image_id=" << state_builder->remote_image_id << ", "
+             << "is_linked=" << state_builder->is_linked();
+    }
+    *_dout << dendl;
 
     // TODO need to support multiple remote images
     if (state_builder != nullptr &&
index 4cbf2bd923b3b05c1e951bbdc6a403574b68050a..a64117425d93f5bedcc221303024d8a01078ac99 100644 (file)
@@ -131,7 +131,11 @@ void PrepareLocalImageRequest<I>::handle_get_mirror_info(int r) {
   switch (m_mirror_image.mode) {
   case cls::rbd::MIRROR_IMAGE_MODE_JOURNAL:
     // journal-based local image exists
-    *m_state_builder = journal::StateBuilder<I>::create(m_global_image_id);
+    {
+      auto state_builder = journal::StateBuilder<I>::create(m_global_image_id);
+      state_builder->local_primary_mirror_uuid = m_primary_mirror_uuid;
+      *m_state_builder = state_builder;
+    }
     break;
   case cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT:
     // snapshot-based local image exists
@@ -144,9 +148,11 @@ void PrepareLocalImageRequest<I>::handle_get_mirror_info(int r) {
     break;
   }
 
+  dout(10) << "local_image_id=" << m_local_image_id << ", "
+           << "local_promotion_state=" << m_promotion_state << ", "
+           << "local_primary_mirror_uuid=" << m_primary_mirror_uuid << dendl;
   (*m_state_builder)->local_image_id = m_local_image_id;
   (*m_state_builder)->local_promotion_state = m_promotion_state;
-  (*m_state_builder)->local_primary_mirror_uuid = m_primary_mirror_uuid;
   finish(0);
 }
 
index b3d4ec4e18aed7312e82c73d9b2ea7d5fa232c6c..3231d5fa02397f1f8bde18977becd1688ea7b58f 100644 (file)
@@ -60,7 +60,11 @@ void PrepareRemoteImageRequest<I>::handle_get_remote_image_id(int r) {
   dout(10) << "r=" << r << ", "
            << "remote_image_id=" << m_remote_image_id << dendl;
 
-  if (r < 0) {
+  if (r == -ENOENT) {
+    finalize_snapshot_state_builder(r);
+    finish(r);
+    return;
+  } else if (r < 0) {
     finish(r);
     return;
   }
@@ -88,6 +92,7 @@ void PrepareRemoteImageRequest<I>::handle_get_mirror_info(int r) {
 
   if (r == -ENOENT) {
     dout(10) << "image " << m_global_image_id << " not mirrored" << dendl;
+    finalize_snapshot_state_builder(r);
     finish(r);
     return;
   } else if (r < 0) {
@@ -110,7 +115,9 @@ void PrepareRemoteImageRequest<I>::handle_get_mirror_info(int r) {
     return;
   } else if (m_promotion_state != librbd::mirror::PROMOTION_STATE_PRIMARY &&
              (state_builder == nullptr ||
-              state_builder->local_image_id.empty())) {
+              state_builder->local_image_id.empty() ||
+              state_builder->local_promotion_state ==
+                librbd::mirror::PROMOTION_STATE_UNKNOWN)) {
     // no local image and remote isn't primary -- don't sync it
     dout(5) << "remote image is not primary -- not syncing" << dendl;
     finish(-EREMOTEIO);
@@ -122,7 +129,7 @@ void PrepareRemoteImageRequest<I>::handle_get_mirror_info(int r) {
     get_client();
     break;
   case cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT:
-    finalize_snapshot_state_builder();
+    finalize_snapshot_state_builder(0);
     finish(0);
     break;
   default:
@@ -240,18 +247,26 @@ void PrepareRemoteImageRequest<I>::finalize_journal_state_builder(
 }
 
 template <typename I>
-void PrepareRemoteImageRequest<I>::finalize_snapshot_state_builder() {
+void PrepareRemoteImageRequest<I>::finalize_snapshot_state_builder(int r) {
   snapshot::StateBuilder<I>* state_builder = nullptr;
   if (*m_state_builder != nullptr) {
-    // already verified that it's a matching builder in
-    // 'handle_get_mirror_info'
     state_builder = dynamic_cast<snapshot::StateBuilder<I>*>(*m_state_builder);
-    ceph_assert(state_builder != nullptr);
-  } else {
+  } else if (r >= 0) {
     state_builder = snapshot::StateBuilder<I>::create(m_global_image_id);
     *m_state_builder = state_builder;
   }
 
+  if (state_builder == nullptr) {
+    // local image prepare failed or is using journal-based mirroring
+    return;
+  }
+
+  dout(10) << "remote_mirror_uuid=" << m_remote_pool_meta.mirror_uuid << ", "
+           << "remote_mirror_peer_uuid="
+           << m_remote_pool_meta.mirror_peer_uuid << ", "
+           << "remote_image_id=" << m_remote_image_id << ", "
+           << "remote_promotion_state=" << m_promotion_state << dendl;
+  ceph_assert(state_builder != nullptr);
   state_builder->remote_mirror_uuid = m_remote_pool_meta.mirror_uuid;
   state_builder->remote_mirror_peer_uuid = m_remote_pool_meta.mirror_peer_uuid;
   state_builder->remote_image_id = m_remote_image_id;
index b546cdc80ffc7f52f9b6ce97934abcd5afe869ee..8006c50666a0695a7a783d35ce4fb43546270d4d 100644 (file)
@@ -118,7 +118,8 @@ private:
   bufferlist m_out_bl;
   std::string m_remote_image_id;
   cls::rbd::MirrorImage m_mirror_image;
-  librbd::mirror::PromotionState m_promotion_state;
+  librbd::mirror::PromotionState m_promotion_state =
+    librbd::mirror::PROMOTION_STATE_UNKNOWN;
   std::string m_primary_mirror_uuid;
 
   // journal-based mirroring
@@ -139,7 +140,7 @@ private:
 
   void finalize_journal_state_builder(cls::journal::ClientState client_state,
                                       const MirrorPeerClientMeta& client_meta);
-  void finalize_snapshot_state_builder();
+  void finalize_snapshot_state_builder(int r);
 
   void finish(int r);
 };
index 20a5378d47a586b0436914c0df4ca23aedb069d8..3cd03e51e5cab85e3a0bcbf9d2e5cd2d8df212be 100644 (file)
@@ -43,10 +43,8 @@ bool StateBuilder<I>::is_local_primary() const  {
 
 template <typename I>
 bool StateBuilder<I>::is_linked() const {
-  ceph_assert(!remote_mirror_uuid.empty());
   return (local_promotion_state ==
-            librbd::mirror::PROMOTION_STATE_NON_PRIMARY &&
-          local_primary_mirror_uuid == remote_mirror_uuid);
+            librbd::mirror::PROMOTION_STATE_NON_PRIMARY);
 }
 
 template <typename I>
index cb70fdf79727df94c64e4a48908709c795bb36f7..99f5fce4487785ab68eef79f7275b425c2091b69 100644 (file)
@@ -82,7 +82,6 @@ public:
   std::string local_image_id;
   librbd::mirror::PromotionState local_promotion_state =
     librbd::mirror::PROMOTION_STATE_PRIMARY;
-  std::string local_primary_mirror_uuid;
   ImageCtxT* local_image_ctx = nullptr;
 
   std::string remote_mirror_uuid;
index 8cb032b25c0bf3e832fd551aa0a167e5eddb84f2..c28e0694823f6cac8602eb00e24e3bda9ce8329e 100644 (file)
@@ -57,6 +57,13 @@ bool StateBuilder<I>::is_disconnected() const {
   return (remote_client_state == cls::journal::CLIENT_STATE_DISCONNECTED);
 }
 
+template <typename I>
+bool StateBuilder<I>::is_linked() const {
+  ceph_assert(!this->remote_mirror_uuid.empty());
+  return (image_replayer::StateBuilder<I>::is_linked() &&
+          local_primary_mirror_uuid == this->remote_mirror_uuid);
+}
+
 template <typename I>
 cls::rbd::MirrorImageMode StateBuilder<I>::get_mirror_image_mode() const {
   return cls::rbd::MIRROR_IMAGE_MODE_JOURNAL;
index f35ff9fe6249b67f828cf88d60ca2b506ee47198..3f3621727ce4a16a1ff6536ed6e1f25d464a6821 100644 (file)
@@ -37,6 +37,7 @@ public:
   void close(Context* on_finish) override;
 
   bool is_disconnected() const override;
+  bool is_linked() const override;
 
   cls::rbd::MirrorImageMode get_mirror_image_mode() const override;
 
@@ -63,6 +64,8 @@ public:
       PoolMetaCache* pool_meta_cache,
       ReplayerListener* replayer_listener) override;
 
+  std::string local_primary_mirror_uuid;
+
   Journaler* remote_journaler = nullptr;
   cls::journal::ClientState remote_client_state =
     cls::journal::CLIENT_STATE_CONNECTED;