]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/tools/rbd_mirror/ImageReplayer.cc
update sources to v12.1.2
[ceph.git] / ceph / src / tools / rbd_mirror / ImageReplayer.cc
index b025566d5315125bc4d3d1d00bc27e231e5d49fc..f68d51d40d8d1aebb1f2f6aaadd03e4b8be43916 100644 (file)
@@ -271,7 +271,7 @@ void ImageReplayer<I>::RemoteJournalerListener::handle_update(
 
 template <typename I>
 ImageReplayer<I>::ImageReplayer(Threads<librbd::ImageCtx> *threads,
-                                shared_ptr<ImageDeleter> image_deleter,
+                                ImageDeleter<I>* image_deleter,
                                 InstanceWatcher<I> *instance_watcher,
                                 RadosRef local,
                                 const std::string &local_mirror_uuid,
@@ -326,6 +326,21 @@ ImageReplayer<I>::~ImageReplayer()
   delete m_asok_hook;
 }
 
+template <typename I>
+image_replayer::HealthState ImageReplayer<I>::get_health_state() const {
+  Mutex::Locker locker(m_lock);
+
+  if (!m_mirror_image_status_state) {
+    return image_replayer::HEALTH_STATE_OK;
+  } else if (*m_mirror_image_status_state ==
+               cls::rbd::MIRROR_IMAGE_STATUS_STATE_SYNCING ||
+             *m_mirror_image_status_state ==
+               cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN) {
+    return image_replayer::HEALTH_STATE_WARNING;
+  }
+  return image_replayer::HEALTH_STATE_ERROR;
+}
+
 template <typename I>
 void ImageReplayer<I>::add_remote_image(const std::string &mirror_uuid,
                                         const std::string &image_id,
@@ -445,7 +460,7 @@ void ImageReplayer<I>::bootstrap() {
   dout(20) << dendl;
 
   if (m_remote_images.empty()) {
-    on_start_fail(0, "waiting for primary remote image");
+    on_start_fail(-EREMOTEIO, "waiting for primary remote image");
     return;
   }
 
@@ -500,8 +515,8 @@ void ImageReplayer<I>::handle_bootstrap(int r) {
 
   if (r == -EREMOTEIO) {
     m_local_image_tag_owner = "";
-    dout(5) << "remote image is non-primary or local image is primary" << dendl;
-    on_start_fail(0, "remote image is non-primary or local image is primary");
+    dout(5) << "remote image is non-primary" << dendl;
+    on_start_fail(-EREMOTEIO, "remote image is non-primary");
     return;
   } else if (r == -EEXIST) {
     m_local_image_tag_owner = "";
@@ -682,7 +697,7 @@ void ImageReplayer<I>::on_start_fail(int r, const std::string &desc)
         Mutex::Locker locker(m_lock);
         assert(m_state == STATE_STARTING);
         m_state = STATE_STOPPING;
-        if (r < 0 && r != -ECANCELED) {
+        if (r < 0 && r != -ECANCELED && r != -EREMOTEIO) {
           derr << "start failed: " << cpp_strerror(r) << dendl;
         } else {
           dout(20) << "start canceled" << dendl;
@@ -1302,15 +1317,30 @@ void ImageReplayer<I>::send_mirror_status_update(const OptionalState &opt_state)
   State state;
   std::string state_desc;
   int last_r;
-  bool bootstrapping;
   bool stopping_replay;
+
+  OptionalMirrorImageStatusState mirror_image_status_state{
+    boost::make_optional(false, cls::rbd::MirrorImageStatusState{})};
+  image_replayer::BootstrapRequest<I>* bootstrap_request = nullptr;
   {
     Mutex::Locker locker(m_lock);
     state = m_state;
     state_desc = m_state_desc;
+    mirror_image_status_state = m_mirror_image_status_state;
     last_r = m_last_r;
-    bootstrapping = (m_bootstrap_request != nullptr);
     stopping_replay = (m_local_image_ctx != nullptr);
+
+    if (m_bootstrap_request != nullptr) {
+      bootstrap_request = m_bootstrap_request;
+      bootstrap_request->get();
+    }
+  }
+
+  bool syncing = false;
+  if (bootstrap_request != nullptr) {
+    syncing = bootstrap_request->is_syncing();
+    bootstrap_request->put();
+    bootstrap_request = nullptr;
   }
 
   if (opt_state) {
@@ -1321,9 +1351,10 @@ void ImageReplayer<I>::send_mirror_status_update(const OptionalState &opt_state)
   status.up = true;
   switch (state) {
   case STATE_STARTING:
-    if (bootstrapping) {
+    if (syncing) {
       status.state = cls::rbd::MIRROR_IMAGE_STATUS_STATE_SYNCING;
       status.description = state_desc.empty() ? "syncing" : state_desc;
+      mirror_image_status_state = status.state;
     } else {
       status.state = cls::rbd::MIRROR_IMAGE_STATUS_STATE_STARTING_REPLAY;
       status.description = "starting replay";
@@ -1351,6 +1382,7 @@ void ImageReplayer<I>::send_mirror_status_update(const OptionalState &opt_state)
         return;
       }
       status.description = "replaying, " + desc;
+      mirror_image_status_state = boost::none;
     }
     break;
   case STATE_STOPPING:
@@ -1361,18 +1393,35 @@ void ImageReplayer<I>::send_mirror_status_update(const OptionalState &opt_state)
     }
     // FALLTHROUGH
   case STATE_STOPPED:
-    if (last_r < 0) {
+    if (last_r == -EREMOTEIO) {
+      status.state = cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN;
+      status.description = state_desc;
+      mirror_image_status_state = status.state;
+    } else if (last_r < 0) {
       status.state = cls::rbd::MIRROR_IMAGE_STATUS_STATE_ERROR;
       status.description = state_desc;
+      mirror_image_status_state = status.state;
     } else {
       status.state = cls::rbd::MIRROR_IMAGE_STATUS_STATE_STOPPED;
       status.description = state_desc.empty() ? "stopped" : state_desc;
+      mirror_image_status_state = boost::none;
     }
     break;
   default:
     assert(!"invalid state");
   }
 
+  {
+    Mutex::Locker locker(m_lock);
+    m_mirror_image_status_state = mirror_image_status_state;
+  }
+
+  // prevent the status from ping-ponging when failed replays are restarted
+  if (mirror_image_status_state &&
+      *mirror_image_status_state == cls::rbd::MIRROR_IMAGE_STATUS_STATE_ERROR) {
+    status.state = *mirror_image_status_state;
+  }
+
   dout(20) << "status=" << status << dendl;
   librados::ObjectWriteOperation op;
   librbd::cls_client::mirror_image_status_set(&op, m_global_image_id, status);
@@ -1590,7 +1639,8 @@ void ImageReplayer<I>::handle_shut_down(int r) {
     if (m_stopping_for_resync) {
       m_image_deleter->schedule_image_delete(m_local,
                                              m_local_pool_id,
-                                             m_global_image_id);
+                                             m_global_image_id,
+                                             true);
       m_stopping_for_resync = false;
     }
   }