]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd-mirror: keep events from different epochs independent 10045/head
authorJason Dillaman <dillaman@redhat.com>
Mon, 20 Jun 2016 15:41:31 +0000 (11:41 -0400)
committerLoic Dachary <ldachary@redhat.com>
Thu, 30 Jun 2016 07:22:17 +0000 (09:22 +0200)
Fixes: http://tracker.ceph.com/issues/16362
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
(cherry picked from commit 3a5b491ec61134dc2e18cbe4e27a54e64b17f7d2)

src/tools/rbd_mirror/ImageReplayer.cc
src/tools/rbd_mirror/ImageReplayer.h

index 10ad65eda08164798a444ed91e09f5cdeaaad528..450ab2845cb7aa4659d4fa7fe07a89b8dd788fa4 100644 (file)
@@ -662,7 +662,7 @@ void ImageReplayer<I>::flush(Context *on_finish)
 
   {
     Mutex::Locker locker(m_lock);
-    if (m_state == STATE_REPLAYING || m_state == STATE_REPLAYING) {
+    if (m_state == STATE_REPLAYING) {
       Context *ctx = new FunctionContext(
         [on_finish](int r) {
           if (on_finish != nullptr) {
@@ -786,19 +786,47 @@ template <typename I>
 void ImageReplayer<I>::replay_flush() {
   dout(20) << dendl;
 
+  {
+    Mutex::Locker locker(m_lock);
+    m_state = STATE_REPLAY_FLUSHING;
+  }
+
+  // shut down the replay to flush all IO and ops and create a new
+  // replayer to handle the new tag epoch
   Context *ctx = create_context_callback<
     ImageReplayer<I>, &ImageReplayer<I>::handle_replay_flush>(this);
-  flush(ctx);
+  ctx = new FunctionContext([this, ctx](int r) {
+      m_local_image_ctx->journal->stop_external_replay();
+      m_local_replay = nullptr;
+
+      if (r < 0) {
+        ctx->complete(r);
+        return;
+      }
+
+      Context *stop_ctx = create_context_callback<
+        ImageReplayer, &ImageReplayer<I>::handle_stop_replay_request>(this);
+      m_local_journal->start_external_replay(&m_local_replay, ctx, stop_ctx);
+    });
+  m_local_replay->shut_down(true, ctx);
 }
 
 template <typename I>
 void ImageReplayer<I>::handle_replay_flush(int r) {
   dout(20) << "r=" << r << dendl;
 
+  {
+    Mutex::Locker locker(m_lock);
+    assert(m_state == STATE_REPLAY_FLUSHING);
+    m_state = STATE_REPLAYING;
+  }
+
   if (r < 0) {
     derr << "replay flush encountered an error: " << cpp_strerror(r) << dendl;
     handle_replay_complete(r, "replay flush encountered an error");
     return;
+  } else if (on_replay_interrupted()) {
+    return;
   }
 
   get_remote_tag();
@@ -1024,6 +1052,7 @@ void ImageReplayer<I>::send_mirror_status_update(const OptionalState &opt_state)
     }
     break;
   case STATE_REPLAYING:
+  case STATE_REPLAY_FLUSHING:
     status.state = cls::rbd::MIRROR_IMAGE_STATUS_STATE_REPLAYING;
     {
       Context *on_req_finish = new FunctionContext(
@@ -1252,6 +1281,8 @@ std::string ImageReplayer<I>::to_string(const State state) {
     return "Starting";
   case ImageReplayer<I>::STATE_REPLAYING:
     return "Replaying";
+  case ImageReplayer<I>::STATE_REPLAY_FLUSHING:
+    return "ReplayFlushing";
   case ImageReplayer<I>::STATE_STOPPING:
     return "Stopping";
   case ImageReplayer<I>::STATE_STOPPED:
index 6b0f993932c31129bd72cd67481d1229388479a6..e4fe92575ab64fb81fb1bd5d470d2d3284c40675 100644 (file)
@@ -57,6 +57,7 @@ public:
     STATE_UNKNOWN,
     STATE_STARTING,
     STATE_REPLAYING,
+    STATE_REPLAY_FLUSHING,
     STATE_STOPPING,
     STATE_STOPPED,
   };