]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/tools/rbd_mirror/ImageReplayer.cc
import quincy beta 17.1.0
[ceph.git] / ceph / src / tools / rbd_mirror / ImageReplayer.cc
index 561b7097f8b6f830b847a3dd92b5a332f3bae434..cec1f5463e6065f75610349d5a37f14086d1ca67 100644 (file)
@@ -244,7 +244,7 @@ ImageReplayer<I>::~ImageReplayer()
   unregister_admin_socket_hook();
   ceph_assert(m_state_builder == nullptr);
   ceph_assert(m_on_start_finish == nullptr);
-  ceph_assert(m_on_stop_finish == nullptr);
+  ceph_assert(m_on_stop_contexts.empty());
   ceph_assert(m_bootstrap_request == nullptr);
   ceph_assert(m_update_status_task == nullptr);
   delete m_replayer_listener;
@@ -316,7 +316,7 @@ void ImageReplayer<I>::start(Context *on_finish, bool manual, bool restart)
         ceph_assert(m_on_start_finish == nullptr);
         m_on_start_finish = on_finish;
       }
-      ceph_assert(m_on_stop_finish == nullptr);
+      ceph_assert(m_on_stop_contexts.empty());
     }
   }
 
@@ -522,39 +522,54 @@ void ImageReplayer<I>::stop(Context *on_finish, bool manual, bool restart)
 
   image_replayer::BootstrapRequest<I> *bootstrap_request = nullptr;
   bool shut_down_replay = false;
-  bool running = true;
+  bool is_stopped = false;
   {
     std::lock_guard locker{m_lock};
 
-    if (restart) {
-      m_restart_requested = true;
-    }
-
     if (!is_running_()) {
-      running = false;
+      if (manual && !m_manual_stop) {
+        dout(10) << "marking manual" << dendl;
+        m_manual_stop = true;
+      }
       if (!restart && m_restart_requested) {
         dout(10) << "canceling restart" << dendl;
         m_restart_requested = false;
       }
+      if (is_stopped_()) {
+        dout(10) << "already stopped" << dendl;
+        is_stopped = true;
+      } else {
+        dout(10) << "joining in-flight stop" << dendl;
+        if (on_finish != nullptr) {
+          m_on_stop_contexts.push_back(on_finish);
+        }
+      }
     } else {
-      if (!is_stopped_()) {
-       if (m_state == STATE_STARTING) {
-         dout(10) << "canceling start" << dendl;
-         if (m_bootstrap_request != nullptr) {
-            bootstrap_request = m_bootstrap_request;
-            bootstrap_request->get();
-         }
-       } else {
-         dout(10) << "interrupting replay" << dendl;
-         shut_down_replay = true;
-       }
-
-        ceph_assert(m_on_stop_finish == nullptr);
-        std::swap(m_on_stop_finish, on_finish);
-        m_stop_requested = true;
-        m_manual_stop = manual;
+      if (m_state == STATE_STARTING) {
+        dout(10) << "canceling start" << dendl;
+        if (m_bootstrap_request != nullptr) {
+          bootstrap_request = m_bootstrap_request;
+          bootstrap_request->get();
+        }
+      } else {
+        dout(10) << "interrupting replay" << dendl;
+        shut_down_replay = true;
       }
+
+      ceph_assert(m_on_stop_contexts.empty());
+      if (on_finish != nullptr) {
+        m_on_stop_contexts.push_back(on_finish);
+      }
+      m_stop_requested = true;
+      m_manual_stop = manual;
+    }
+  }
+
+  if (is_stopped) {
+    if (on_finish) {
+      on_finish->complete(-EINVAL);
     }
+    return;
   }
 
   // avoid holding lock since bootstrap request will update status
@@ -564,18 +579,8 @@ void ImageReplayer<I>::stop(Context *on_finish, bool manual, bool restart)
     bootstrap_request->put();
   }
 
-  if (!running) {
-    dout(20) << "not running" << dendl;
-    if (on_finish) {
-      on_finish->complete(-EINVAL);
-    }
-    return;
-  }
-
   if (shut_down_replay) {
     on_stop_journal_replay();
-  } else if (on_finish != nullptr) {
-    on_finish->complete(0);
   }
 }
 
@@ -984,11 +989,11 @@ void ImageReplayer<I>::handle_shut_down(int r) {
 
   dout(10) << "stop complete" << dendl;
   Context *on_start = nullptr;
-  Context *on_stop = nullptr;
+  Contexts on_stop_contexts;
   {
     std::lock_guard locker{m_lock};
     std::swap(on_start, m_on_start_finish);
-    std::swap(on_stop, m_on_stop_finish);
+    on_stop_contexts = std::move(m_on_stop_contexts);
     m_stop_requested = false;
     ceph_assert(m_state == STATE_STOPPING);
     m_state = STATE_STOPPED;
@@ -999,9 +1004,9 @@ void ImageReplayer<I>::handle_shut_down(int r) {
     on_start->complete(r);
     r = 0;
   }
-  if (on_stop != nullptr) {
-    dout(10) << "on stop finish complete, r=" << r << dendl;
-    on_stop->complete(r);
+  for (auto ctx : on_stop_contexts) {
+    dout(10) << "on stop finish " << ctx << " complete, r=" << r << dendl;
+    ctx->complete(r);
   }
 }