]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd / journal: async journal removal state machine
authorVenky Shankar <vshankar@redhat.com>
Tue, 5 Jul 2016 13:20:31 +0000 (18:50 +0530)
committerVenky Shankar <vshankar@redhat.com>
Sun, 7 Aug 2016 11:01:37 +0000 (16:31 +0530)
Signed-off-by: Venky Shankar <vshankar@redhat.com>
src/librbd/CMakeLists.txt
src/librbd/Journal.cc
src/librbd/Makefile.am
src/librbd/journal/RemoveRequest.cc [new file with mode: 0644]
src/librbd/journal/RemoveRequest.h [new file with mode: 0644]
src/test/librbd/test_mock_Journal.cc

index 216f76d666f5c01aabe160dc5c5a1fa2d5531aab..889ff5488f2de2aec02edf31c3c131b836ae277a 100644 (file)
@@ -36,6 +36,7 @@ set(librbd_internal_srcs
   image/SetSnapRequest.cc
   image_watcher/Notifier.cc
   image_watcher/NotifyLockOwner.cc
+  journal/RemoveRequest.cc
   journal/Replay.cc
   journal/StandardPolicy.cc
   object_map/InvalidateRequest.cc
index d807af7160632ca2972878295f3e6ead94f912db..74a4f96fa89fe39141f06e1b229b8c032ab408fe 100644 (file)
@@ -17,6 +17,7 @@
 #include "common/Timer.h"
 #include "common/WorkQueue.h"
 #include "include/rados/librados.hpp"
+#include "librbd/journal/RemoveRequest.h"
 
 #include <boost/scope_exit.hpp>
 
@@ -394,40 +395,18 @@ int Journal<I>::remove(librados::IoCtx &io_ctx, const std::string &image_id) {
   CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
   ldout(cct, 5) << __func__ << ": image=" << image_id << dendl;
 
-  Journaler journaler(io_ctx, image_id, IMAGE_CLIENT_ID, {});
-
-  bool journal_exists;
-  int r = journaler.exists(&journal_exists);
-  if (r < 0) {
-    lderr(cct) << __func__ << ": "
-               << "failed to stat journal header: " << cpp_strerror(r) << dendl;
-    return r;
-  } else if (!journal_exists) {
-    return 0;
-  }
-
   C_SaferCond cond;
-  journaler.init(&cond);
-  BOOST_SCOPE_EXIT_ALL(&journaler) {
-    journaler.shut_down();
-  };
+  ContextWQ op_work_queue("librbd::op_work_queue",
+                          cct->_conf->rbd_op_thread_timeout,
+                          ImageCtx::get_thread_pool_instance(cct));
+  journal::RemoveRequest<I> *req = journal::RemoveRequest<I>::create(
+    io_ctx, image_id, IMAGE_CLIENT_ID, &op_work_queue, &cond);
+  req->send();
 
-  r = cond.wait();
-  if (r == -ENOENT) {
-    return 0;
-  } else if (r < 0) {
-    lderr(cct) << __func__ << ": "
-               << "failed to initialize journal: " << cpp_strerror(r) << dendl;
-    return r;
-  }
+  int r = cond.wait();
+  op_work_queue.drain();
 
-  r = journaler.remove(true);
-  if (r < 0) {
-    lderr(cct) << __func__ << ": "
-               << "failed to remove journal: " << cpp_strerror(r) << dendl;
-    return r;
-  }
-  return 0;
+  return r;
 }
 
 template <typename I>
index f5b036232aaa9120ce7633afa868e086ce9d7126..d961203f43226e4ab2fbad043aae62ff0cf09d88 100644 (file)
@@ -41,6 +41,7 @@ librbd_internal_la_SOURCES = \
        librbd/image/SetSnapRequest.cc \
        librbd/image_watcher/Notifier.cc \
        librbd/image_watcher/NotifyLockOwner.cc \
+       librbd/journal/RemoveRequest.cc \
        librbd/journal/Replay.cc \
        librbd/journal/StandardPolicy.cc \
        librbd/object_map/InvalidateRequest.cc \
@@ -129,6 +130,7 @@ noinst_HEADERS += \
        librbd/image/SetSnapRequest.h \
        librbd/image_watcher/Notifier.h \
        librbd/image_watcher/NotifyLockOwner.h \
+       librbd/journal/RemoveRequest.h \
        librbd/journal/Policy.h \
        librbd/journal/Replay.h \
        librbd/journal/StandardPolicy.h \
diff --git a/src/librbd/journal/RemoveRequest.cc b/src/librbd/journal/RemoveRequest.cc
new file mode 100644 (file)
index 0000000..c9dd020
--- /dev/null
@@ -0,0 +1,155 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "common/dout.h"
+#include "common/errno.h"
+#include "common/Timer.h"
+#include "common/WorkQueue.h"
+#include "journal/Settings.h"
+#include "include/assert.h"
+#include "librbd/Utils.h"
+#include "librbd/journal/RemoveRequest.h"
+
+#define dout_subsys ceph_subsys_rbd
+#undef dout_prefix
+#define dout_prefix *_dout << "librbd::Journal::RemoveRequest: "
+
+namespace librbd {
+
+using util::create_context_callback;
+
+namespace journal {
+
+template<typename I>
+RemoveRequest<I>::RemoveRequest(IoCtx &ioctx, const std::string &image_id,
+                                              const std::string &client_id,
+                                              ContextWQ *op_work_queue,
+                                              Context *on_finish)
+  : m_image_id(image_id), m_image_client_id(client_id),
+    m_op_work_queue(op_work_queue), m_on_finish(on_finish) {
+  m_ioctx.dup(ioctx);
+  m_cct = reinterpret_cast<CephContext *>(m_ioctx.cct());
+}
+
+template<typename I>
+void RemoveRequest<I>::send() {
+  ldout(m_cct, 20) << this << " " << __func__ << dendl;
+
+  stat_journal();
+}
+
+template<typename I>
+void RemoveRequest<I>::stat_journal() {
+  ldout(m_cct, 20) << this << " " << __func__ << dendl;
+
+  ImageCtx::get_timer_instance(m_cct, &m_timer, &m_timer_lock);
+  m_journaler = new Journaler(m_op_work_queue, m_timer, m_timer_lock,
+                              m_ioctx, m_image_id, m_image_client_id, {});
+
+  using klass = RemoveRequest<I>;
+  Context *ctx = create_context_callback<klass, &klass::handle_stat_journal>(this);
+
+  m_journaler->exists(ctx);
+}
+
+template<typename I>
+Context *RemoveRequest<I>::handle_stat_journal(int *result) {
+  ldout(m_cct, 20) << __func__ << ": r=" << *result << dendl;
+
+  if ((*result < 0) && (*result != -ENOENT)) {
+    lderr(m_cct) << "failed to stat journal header: " << cpp_strerror(*result) << dendl;
+    shut_down_journaler(*result);
+    return nullptr;
+  }
+
+  if (*result == -ENOENT) {
+    shut_down_journaler(0);
+    return nullptr;
+  }
+
+  init_journaler();
+  return nullptr;
+}
+
+template<typename I>
+void RemoveRequest<I>::init_journaler() {
+  ldout(m_cct, 20) << this << " " << __func__ << dendl;
+
+  using klass = RemoveRequest<I>;
+  Context *ctx = create_context_callback<klass, &klass::handle_init_journaler>(this);
+
+  m_journaler->init(ctx);
+}
+
+template<typename I>
+Context *RemoveRequest<I>::handle_init_journaler(int *result) {
+  ldout(m_cct, 20) << __func__ << ": r=" << *result << dendl;
+
+  if ((*result < 0) && (*result != -ENOENT)) {
+    lderr(m_cct) << "failed to init journaler: " << cpp_strerror(*result) << dendl;
+    shut_down_journaler(*result);
+    return nullptr;
+  }
+
+  remove_journal();
+  return nullptr;
+}
+
+template<typename I>
+void RemoveRequest<I>::remove_journal() {
+  ldout(m_cct, 20) << this << " " << __func__ << dendl;
+
+  using klass = RemoveRequest<I>;
+  Context *ctx = create_context_callback<klass, &klass::handle_remove_journal>(this);
+
+  m_journaler->remove(true, ctx);
+}
+
+template<typename I>
+Context *RemoveRequest<I>::handle_remove_journal(int *result) {
+  ldout(m_cct, 20) << __func__ << ": r=" << *result << dendl;
+
+  if (*result < 0) {
+    lderr(m_cct) << "failed to remove journal: " << cpp_strerror(*result) << dendl;
+  }
+
+  shut_down_journaler(*result);
+  return nullptr;
+}
+
+template<typename I>
+void RemoveRequest<I>::shut_down_journaler(int r) {
+  ldout(m_cct, 20) << this << " " << __func__ << dendl;
+
+  m_r_saved = r;
+
+  using klass = RemoveRequest<I>;
+  Context *ctx = create_context_callback<klass, &klass::handle_journaler_shutdown>(this);
+
+  m_journaler->shut_down(ctx);
+}
+
+template<typename I>
+Context *RemoveRequest<I>::handle_journaler_shutdown(int *result) {
+  ldout(m_cct, 20) << __func__ << ": r=" << *result << dendl;
+
+  if (*result < 0) {
+    lderr(m_cct) << "failed to shut down journaler: " << cpp_strerror(*result) << dendl;
+  }
+
+  delete m_journaler;
+
+  if (m_r_saved == 0) {
+    ldout(m_cct, 20) << "done." << dendl;
+  }
+
+  m_on_finish->complete(m_r_saved);
+  delete this;
+
+  return nullptr;
+}
+
+} // namespace journal
+} // namespace librbd
+
+template class librbd::journal::RemoveRequest<librbd::ImageCtx>;
diff --git a/src/librbd/journal/RemoveRequest.h b/src/librbd/journal/RemoveRequest.h
new file mode 100644 (file)
index 0000000..e710a13
--- /dev/null
@@ -0,0 +1,82 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#ifndef CEPH_LIBRBD_JOURNAL_REMOVE_REQUEST_H
+#define CEPH_LIBRBD_JOURNAL_REMOVE_REQUEST_H
+
+#include "include/int_types.h"
+#include "include/buffer.h"
+#include "include/rados/librados.hpp"
+#include "include/rbd/librbd.hpp"
+#include "common/Mutex.h"
+#include "librbd/ImageCtx.h"
+#include "journal/Journaler.h"
+#include "librbd/journal/TypeTraits.h"
+
+using librados::IoCtx;
+using journal::Journaler;
+
+class Context;
+class ContextWQ;
+class SafeTimer;
+
+namespace journal {
+  class Journaler;
+}
+
+namespace librbd {
+
+class ImageCtx;
+
+namespace journal {
+
+template<typename ImageCtxT = ImageCtx>
+class RemoveRequest {
+public:
+  static RemoveRequest *create(IoCtx &ioctx, const std::string &image_id,
+                                      const std::string &client_id,
+                                      ContextWQ *op_work_queue, Context *on_finish) {
+    return new RemoveRequest(ioctx, image_id, client_id,
+                                    op_work_queue, on_finish);
+  }
+
+  void send();
+
+private:
+  typedef typename TypeTraits<ImageCtxT>::Journaler Journaler;
+
+  RemoveRequest(IoCtx &ioctx, const std::string &image_id,
+                       const std::string &client_id,
+                       ContextWQ *op_work_queue, Context *on_finish);
+
+  IoCtx m_ioctx;
+  std::string m_image_id;
+  std::string m_image_client_id;
+  ContextWQ *m_op_work_queue;
+  Context *m_on_finish;
+
+  CephContext *m_cct;
+  Journaler *m_journaler;
+  SafeTimer *m_timer;
+  Mutex *m_timer_lock;
+  int m_r_saved;
+
+  void stat_journal();
+  Context *handle_stat_journal(int *result);
+
+  void init_journaler();
+  Context *handle_init_journaler(int *result);
+
+  void remove_journal();
+  Context *handle_remove_journal(int *result);
+
+  void shut_down_journaler(int r);
+  Context *handle_journaler_shutdown(int *result);
+};
+
+} // namespace journal
+} // namespace librbd
+
+extern template class librbd::journal::RemoveRequest<librbd::ImageCtx>;
+
+#endif // CEPH_LIBRBD_JOURNAL_REMOVE_REQUEST_H
index 3785f2ce783e2a4e7fe208774f6925a9bd676e22..1a8f5817519bd60fc46a19e1d29d353ce61edc2e 100644 (file)
@@ -15,6 +15,7 @@
 #include "librbd/Journal.h"
 #include "librbd/Utils.h"
 #include "librbd/journal/Replay.h"
+#include "librbd/journal/RemoveRequest.h"
 #include "librbd/journal/Types.h"
 #include "librbd/journal/TypeTraits.h"
 #include "gmock/gmock.h"
@@ -89,6 +90,36 @@ public:
 
 MockReplay *MockReplay::s_instance = nullptr;
 
+struct MockRemove {
+  static MockRemove *s_instance;
+  static MockRemove &get_instance() {
+    assert(s_instance != nullptr);
+    return *s_instance;
+  }
+
+  MockRemove() {
+    s_instance = this;
+  }
+
+  MOCK_METHOD0(send, void());
+};
+
+template <>
+class RemoveRequest<MockJournalImageCtx> {
+public:
+  static RemoveRequest *create(IoCtx &ioctx, const std::string &imageid,
+                                      const std::string &client_id,
+                                      ContextWQ *op_work_queue, Context *on_finish) {
+    return new RemoveRequest();
+  }
+
+  void send() {
+    MockRemove::get_instance().send();
+  }
+};
+
+MockRemove *MockRemove::s_instance = nullptr;
+
 } // namespace journal
 } // namespace librbd