]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: initial integration of maintenance op journal replay
authorJason Dillaman <dillaman@redhat.com>
Thu, 17 Dec 2015 20:28:31 +0000 (15:28 -0500)
committerJason Dillaman <dillaman@redhat.com>
Fri, 15 Jan 2016 15:40:29 +0000 (10:40 -0500)
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/librbd/journal/Replay.cc
src/librbd/journal/Replay.h

index b0bb1ce573cf9813819922d0812039ace783fa0d..c2b5eabe074121d7c6bad6142e156d698f857120 100644 (file)
@@ -2,10 +2,13 @@
 // vim: ts=8 sw=2 smarttab
 
 #include "librbd/journal/Replay.h"
+#include "common/WorkQueue.h"
 #include "librbd/AioCompletion.h"
 #include "librbd/AioImageRequest.h"
 #include "librbd/ImageCtx.h"
 #include "librbd/internal.h"
+#include "librbd/Operations.h"
+#include "librbd/Utils.h"
 
 #define dout_subsys ceph_subsys_rbd
 #undef dout_prefix
 namespace librbd {
 namespace journal {
 
+namespace {
+
+static NoOpProgressContext no_op_progress_callback;
+
+} // anonymous namespace
+
+
 template <typename I>
 Replay<I>::Replay(I &image_ctx)
   : m_image_ctx(image_ctx), m_lock("Replay<I>::m_lock"), m_flush_ctx(nullptr),
@@ -22,7 +32,7 @@ Replay<I>::Replay(I &image_ctx)
 
 template <typename I>
 Replay<I>::~Replay() {
-  assert(m_aio_completions.empty());
+  assert(m_op_contexts.empty() && m_aio_completions.empty());
 }
 
 template <typename I>
@@ -48,12 +58,14 @@ void Replay<I>::flush(Context *on_finish) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << dendl;
 
+  on_finish = util::create_async_context_callback(
+    m_image_ctx, on_finish);
   {
     Mutex::Locker locker(m_lock);
     assert(m_flush_ctx == nullptr);
     m_flush_ctx = on_finish;
 
-    if (!m_aio_completions.empty()) {
+    if (!m_op_contexts.empty() || !m_aio_completions.empty()) {
       return;
     }
   }
@@ -105,6 +117,9 @@ void Replay<I>::handle_event(const journal::SnapCreateEvent &event,
                             Context *on_safe) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": Snap create event" << dendl;
+
+  Context *on_finish = create_op_context_callback(on_safe);
+  m_image_ctx.operations->snap_create(event.snap_name.c_str(), on_finish);
 }
 
 template <typename I>
@@ -112,6 +127,9 @@ void Replay<I>::handle_event(const journal::SnapRemoveEvent &event,
                             Context *on_safe) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": Snap remove event" << dendl;
+
+  Context *on_finish = create_op_context_callback(on_safe);
+  m_image_ctx.operations->snap_remove(event.snap_name.c_str(), on_finish);
 }
 
 template <typename I>
@@ -119,6 +137,10 @@ void Replay<I>::handle_event(const journal::SnapRenameEvent &event,
                             Context *on_safe) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": Snap rename event" << dendl;
+
+  Context *on_finish = create_op_context_callback(on_safe);
+  m_image_ctx.operations->snap_rename(event.snap_id, event.snap_name.c_str(),
+                                      on_finish);
 }
 
 template <typename I>
@@ -126,6 +148,9 @@ void Replay<I>::handle_event(const journal::SnapProtectEvent &event,
                             Context *on_safe) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": Snap protect event" << dendl;
+
+  Context *on_finish = create_op_context_callback(on_safe);
+  m_image_ctx.operations->snap_protect(event.snap_name.c_str(), on_finish);
 }
 
 template <typename I>
@@ -134,6 +159,9 @@ void Replay<I>::handle_event(const journal::SnapUnprotectEvent &event,
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": Snap unprotect event"
                  << dendl;
+
+  Context *on_finish = create_op_context_callback(on_safe);
+  m_image_ctx.operations->snap_unprotect(event.snap_name.c_str(), on_finish);
 }
 
 template <typename I>
@@ -142,6 +170,10 @@ void Replay<I>::handle_event(const journal::SnapRollbackEvent &event,
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": Snap rollback start event"
                  << dendl;
+
+  Context *on_finish = create_op_context_callback(on_safe);
+  m_image_ctx.operations->snap_rollback(event.snap_name.c_str(),
+                                        no_op_progress_callback, on_finish);
 }
 
 template <typename I>
@@ -149,6 +181,9 @@ void Replay<I>::handle_event(const journal::RenameEvent &event,
                             Context *on_safe) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": Rename event" << dendl;
+
+  Context *on_finish = create_op_context_callback(on_safe);
+  m_image_ctx.operations->rename(event.image_name.c_str(), on_finish);
 }
 
 template <typename I>
@@ -156,6 +191,10 @@ void Replay<I>::handle_event(const journal::ResizeEvent &event,
                             Context *on_safe) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": Resize start event" << dendl;
+
+  Context *on_finish = create_op_context_callback(on_safe);
+  m_image_ctx.operations->resize(event.size, no_op_progress_callback,
+                                 on_finish);
 }
 
 template <typename I>
@@ -163,6 +202,9 @@ void Replay<I>::handle_event(const journal::FlattenEvent &event,
                             Context *on_safe) {
   CephContext *cct = m_image_ctx.cct;
   ldout(cct, 20) << this << " " << __func__ << ": Flatten start event" << dendl;
+
+  Context *on_finish = create_op_context_callback(on_safe);
+  m_image_ctx.operations->flatten(no_op_progress_callback, on_finish);
 }
 
 template <typename I>
@@ -173,6 +215,42 @@ void Replay<I>::handle_event(const journal::UnknownEvent &event,
   on_safe->complete(0);
 }
 
+template <typename I>
+Context *Replay<I>::create_op_context_callback(Context *on_safe) {
+  C_OpOnFinish *on_finish;
+  {
+    on_finish = new C_OpOnFinish(this);
+    m_op_contexts[on_finish] = on_safe;
+  }
+  return on_finish;
+}
+
+template <typename I>
+void Replay<I>::handle_op_context_callback(Context *on_op_finish, int r) {
+  Context *on_safe = nullptr;
+  Context *on_flush = nullptr;
+  {
+    Mutex::Locker locker(m_lock);
+    auto it = m_op_contexts.find(on_op_finish);
+    assert(it != m_op_contexts.end());
+
+    if (m_ret_val == 0 && r < 0) {
+      m_ret_val = r;
+    }
+
+    on_safe = it->second;
+    m_op_contexts.erase(it);
+    if (m_op_contexts.empty() && m_aio_completions.empty()) {
+      on_flush = m_flush_ctx;
+    }
+  }
+
+  on_safe->complete(r);
+  if (on_flush != nullptr) {
+    on_flush->complete(m_ret_val);
+  }
+}
+
 template <typename I>
 AioCompletion *Replay<I>::create_aio_completion(Context *on_safe) {
   Mutex::Locker locker(m_lock);
@@ -185,35 +263,34 @@ AioCompletion *Replay<I>::create_aio_completion(Context *on_safe) {
 
 template <typename I>
 void Replay<I>::handle_aio_completion(AioCompletion *aio_comp) {
-  Context *on_finish = nullptr;
+  int r;
+  Context *on_safe = nullptr;
+  Context *on_flush = nullptr;
   {
     Mutex::Locker locker(m_lock);
-
     AioCompletions::iterator it = m_aio_completions.find(aio_comp);
     assert(it != m_aio_completions.end());
 
-    int r = aio_comp->get_return_value();
+    r = aio_comp->get_return_value();
+    if (m_ret_val == 0 && r < 0) {
+      m_ret_val = r;
+    }
 
     CephContext *cct = m_image_ctx.cct;
     ldout(cct, 20) << this << " " << __func__ << ": "
                    << "aio_comp=" << aio_comp << ", "
                    << "r=" << r << dendl;
 
-    Context *on_safe = it->second;
-    on_safe->complete(r);
-
-    if (r < 0 && m_ret_val == 0) {
-      m_ret_val = r;
-    }
-
+    on_safe = it->second;
     m_aio_completions.erase(it);
-    if (m_aio_completions.empty()) {
-      on_finish = m_flush_ctx;
+    if (m_op_contexts.empty() && m_aio_completions.empty()) {
+      on_flush = m_flush_ctx;
     }
   }
 
-  if (on_finish != nullptr) {
-    on_finish->complete(m_ret_val);
+  on_safe->complete(r);
+  if (on_flush != nullptr) {
+    on_flush->complete(m_ret_val);
   }
 }
 
index 3eeb452648ad4c3d7774e172c954f0eeaef8b547..5a8c559866d6fa87edb6a3a36b1fabf8990e2f16 100644 (file)
@@ -6,14 +6,14 @@
 
 #include "include/int_types.h"
 #include "include/buffer_fwd.h"
+#include "include/Context.h"
+#include "include/unordered_map.h"
 #include "include/rbd/librbd.hpp"
 #include "common/Mutex.h"
 #include "librbd/journal/Entries.h"
 #include <boost/variant.hpp>
 #include <map>
 
-class Context;
-
 namespace librbd {
 
 class AioCompletion;
@@ -28,14 +28,25 @@ public:
     return new Replay(image_ctx);
   }
 
+  Replay(ImageCtxT &image_ctx);
   ~Replay();
 
   int process(bufferlist::iterator it, Context *on_safe = NULL);
   void flush(Context *on_finish);
 
 private:
+  typedef ceph::unordered_map<Context *, Context *> OpContexts;
   typedef std::map<AioCompletion*,Context*> AioCompletions;
 
+  struct C_OpOnFinish : public Context {
+    Replay *replay;
+    C_OpOnFinish(Replay *replay) : replay(replay) {
+    }
+    virtual void finish(int r) override {
+      replay->handle_op_context_callback(this, r);
+    }
+  };
+
   struct EventVisitor : public boost::static_visitor<void> {
     Replay *replay;
     Context *on_safe;
@@ -54,12 +65,11 @@ private:
 
   Mutex m_lock;
 
+  OpContexts m_op_contexts;
   AioCompletions m_aio_completions;
   Context *m_flush_ctx;
   int m_ret_val;
 
-  Replay(ImageCtxT &image_ctx);
-
   void handle_event(const AioDiscardEvent &event, Context *on_safe);
   void handle_event(const AioWriteEvent &event, Context *on_safe);
   void handle_event(const AioFlushEvent &event, Context *on_safe);
@@ -75,6 +85,9 @@ private:
   void handle_event(const FlattenEvent &event, Context *on_safe);
   void handle_event(const UnknownEvent &event, Context *on_safe);
 
+  Context *create_op_context_callback(Context *on_safe);
+  void handle_op_context_callback(Context *on_op_finish, int r);
+
   AioCompletion *create_aio_completion(Context *on_safe);
   void handle_aio_completion(AioCompletion *aio_comp);