]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: stop journal recorder before starting external replay
authorJason Dillaman <dillaman@redhat.com>
Tue, 7 Jun 2016 16:42:52 +0000 (12:42 -0400)
committerJason Dillaman <dillaman@redhat.com>
Fri, 10 Jun 2016 16:44:41 +0000 (12:44 -0400)
Fixes: http://tracker.ceph.com/issues/16165
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
(cherry picked from commit 5aa6eb2782bdb5cde6a050a5f7a4e683800414c0)

src/librbd/Journal.cc
src/librbd/Journal.h
src/test/rbd_mirror/test_mock_ImageReplayer.cc
src/tools/rbd_mirror/ImageReplayer.cc
src/tools/rbd_mirror/ImageReplayer.h

index b24e8611e0bb48f2d3018c359ba2ec75f293682a..b874005843ee7e080eda4adac50a1a7b34916c34 100644 (file)
@@ -1070,7 +1070,8 @@ typename Journal<I>::Future Journal<I>::wait_event(Mutex &lock, uint64_t tid,
 }
 
 template <typename I>
-int Journal<I>::start_external_replay(journal::Replay<I> **journal_replay) {
+void Journal<I>::start_external_replay(journal::Replay<I> **journal_replay,
+                                       Context *on_finish) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << dendl;
 
@@ -1078,11 +1079,42 @@ int Journal<I>::start_external_replay(journal::Replay<I> **journal_replay) {
   assert(m_state == STATE_READY);
   assert(m_journal_replay == nullptr);
 
+  on_finish = util::create_async_context_callback(m_image_ctx, on_finish);
+  on_finish = new FunctionContext(
+    [this, journal_replay, on_finish](int r) {
+      handle_start_external_replay(r, journal_replay, on_finish);
+    });
+
+  // safely flush all in-flight events before starting external replay
+  m_journaler->stop_append(util::create_async_context_callback(m_image_ctx,
+                                                               on_finish));
+}
+
+template <typename I>
+void Journal<I>::handle_start_external_replay(int r,
+                                              journal::Replay<I> **journal_replay,
+                                              Context *on_finish) {
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 20) << this << " " << __func__ << dendl;
+
+  Mutex::Locker locker(m_lock);
+  assert(m_state == STATE_READY);
+  assert(m_journal_replay == nullptr);
+
+  if (r < 0) {
+    lderr(cct) << "failed to stop recording: " << cpp_strerror(r) << dendl;
+    *journal_replay = nullptr;
+
+    // get back to a sane-state
+    start_append();
+    on_finish->complete(r);
+    return;
+  }
+
   transition_state(STATE_REPLAYING, 0);
   m_journal_replay = journal::Replay<I>::create(m_image_ctx);
-
   *journal_replay = m_journal_replay;
-  return 0;
+  on_finish->complete(0);
 }
 
 template <typename I>
@@ -1093,7 +1125,8 @@ void Journal<I>::stop_external_replay() {
 
   delete m_journal_replay;
   m_journal_replay = nullptr;
-  transition_state(STATE_READY, 0);
+
+  start_append();
 }
 
 template <typename I>
@@ -1177,6 +1210,15 @@ void Journal<I>::complete_event(typename Events::iterator it, int r) {
   }
 }
 
+template <typename I>
+void Journal<I>::start_append() {
+  assert(m_lock.is_locked());
+  m_journaler->start_append(m_image_ctx.journal_object_flush_interval,
+                           m_image_ctx.journal_object_flush_bytes,
+                           m_image_ctx.journal_object_flush_age);
+  transition_state(STATE_READY, 0);
+}
+
 template <typename I>
 void Journal<I>::handle_initialized(int r) {
   CephContext *cct = m_image_ctx.cct;
@@ -1429,10 +1471,7 @@ void Journal<I>::handle_flushing_replay() {
   m_journal_replay = NULL;
 
   m_error_result = 0;
-  m_journaler->start_append(m_image_ctx.journal_object_flush_interval,
-                           m_image_ctx.journal_object_flush_bytes,
-                           m_image_ctx.journal_object_flush_age);
-  transition_state(STATE_READY, 0);
+  start_append();
 }
 
 template <typename I>
index 3d36b28b40249f18946a6bdfc76e18a82010ad8b..d77d50ed286806be39f3c110499b0c0ffed803fe 100644 (file)
@@ -154,7 +154,8 @@ public:
     return op_tid;
   }
 
-  int start_external_replay(journal::Replay<ImageCtxT> **journal_replay);
+  void start_external_replay(journal::Replay<ImageCtxT> **journal_replay,
+                             Context *on_finish);
   void stop_external_replay();
 
 private:
@@ -298,6 +299,8 @@ private:
 
   void complete_event(typename Events::iterator it, int r);
 
+  void start_append();
+
   void handle_initialized(int r);
   void handle_get_tags(int r);
 
@@ -306,6 +309,10 @@ private:
   void handle_replay_process_ready(int r);
   void handle_replay_process_safe(ReplayEntry replay_entry, int r);
 
+  void handle_start_external_replay(int r,
+                                    journal::Replay<ImageCtxT> **journal_replay,
+                                    Context *on_finish);
+
   void handle_flushing_restart(int r);
   void handle_flushing_replay();
 
index b5cfcd9d356e4ce9c74b9d131f4f0e88abdf98af..8ff318afac8f4d63ea097aa8caeb8ec9f8ba23c4 100644 (file)
@@ -21,7 +21,8 @@ struct MockTestImageCtx : public MockImageCtx {
 };
 
 struct MockTestJournal : public MockJournal {
-  MOCK_METHOD1(start_external_replay, int(journal::Replay<MockTestImageCtx> **));
+  MOCK_METHOD2(start_external_replay, void(journal::Replay<MockTestImageCtx> **,
+                                           Context *on_finish));
   MOCK_METHOD0(stop_external_replay, void());
 };
 
index 8d503516890b98960df855a6b8d6cec383a7e38e..42c90cd44908b49689de7c9b7d831718c5e92b8f 100644 (file)
@@ -465,7 +465,15 @@ template <typename I>
 void ImageReplayer<I>::start_replay() {
   dout(20) << dendl;
 
-  int r = m_local_image_ctx->journal->start_external_replay(&m_local_replay);
+  Context *ctx = create_context_callback<
+    ImageReplayer, &ImageReplayer<I>::handle_start_replay>(this);
+  m_local_image_ctx->journal->start_external_replay(&m_local_replay, ctx);
+}
+
+template <typename I>
+void ImageReplayer<I>::handle_start_replay(int r) {
+  dout(20) << "r=" << r << dendl;
+
   if (r < 0) {
     derr << "error starting external replay on local image "
         <<  m_local_image_id << ": " << cpp_strerror(r) << dendl;
index b6bf4a25c443a749746bf9a1a2a6c1bc3bb616c6..6b0f993932c31129bd72cd67481d1229388479a6 100644 (file)
@@ -302,6 +302,7 @@ private:
   void handle_init_remote_journaler(int r);
 
   void start_replay();
+  void handle_start_replay(int r);
 
   void replay_flush();
   void handle_replay_flush(int r);