]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: handle journal and IO commits in either sequence
authorJason Dillaman <dillaman@redhat.com>
Wed, 16 Dec 2015 18:46:16 +0000 (13:46 -0500)
committerJason Dillaman <dillaman@redhat.com>
Fri, 15 Jan 2016 15:40:28 +0000 (10:40 -0500)
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/librbd/Journal.cc
src/librbd/Journal.h

index 882d13ab8edfda227b2937ad4db53ef9def7e7e8..eb0de9f128cf1c04dbc556c4600ff9692e37fbb9 100644 (file)
@@ -448,14 +448,16 @@ typename Journal<I>::Future Journal<I>::wait_event(Mutex &lock, uint64_t tid,
   CephContext *cct = m_image_ctx.cct;
 
   typename Events::iterator it = m_events.find(tid);
-  if (it == m_events.end() || it->second.safe) {
+  assert(it != m_events.end());
+
+  Event &event = it->second;
+  if (event.safe) {
     // journal entry already safe
     ldout(cct, 20) << "journal entry already safe" << dendl;
-    m_image_ctx.op_work_queue->queue(on_safe, 0);
+    m_image_ctx.op_work_queue->queue(on_safe, event.ret_val);
     return Future();
   }
 
-  Event &event = it->second;
   event.on_safe_contexts.push_back(on_safe);
   return event.future;
 }
@@ -518,8 +520,20 @@ void Journal<I>::complete_event(typename Events::iterator it, int r) {
   ldout(cct, 20) << this << " " << __func__ << ": tid=" << it->first << " "
                  << "r=" << r << dendl;
 
-  m_journaler->committed(it->second.future);
-  if (it->second.safe) {
+  Event &event = it->second;
+  if (r < 0) {
+    // event recorded to journal but failed to update disk, we cannot
+    // commit this IO event. this event must be replayed.
+    assert(event.safe);
+    lderr(cct) << "failed to commit IO to disk, replay required: "
+               << cpp_strerror(r) << dendl;
+  }
+
+  event.committed_io = true;
+  if (event.safe) {
+    if (r >= 0) {
+      m_journaler->committed(event.future);
+    }
     m_events.erase(it);
   }
 }
@@ -696,7 +710,6 @@ void Journal<I>::handle_event_safe(int r, uint64_t tid) {
   ldout(cct, 20) << this << " " << __func__ << ": r=" << r << ", "
                  << "tid=" << tid << dendl;
 
-  // TODO: ensure this callback never sees a failure
   AioCompletion *aio_comp;
   AioObjectRequests aio_object_requests;
   Contexts on_safe_contexts;
@@ -710,7 +723,14 @@ void Journal<I>::handle_event_safe(int r, uint64_t tid) {
     aio_object_requests.swap(event.aio_object_requests);
     on_safe_contexts.swap(event.on_safe_contexts);
 
-    if (event.pending_extents.empty()) {
+    if (r < 0 || event.committed_io) {
+      // failed journal write so IO won't be sent -- or IO extent was
+      // overwritten by future IO operations so this was a no-op IO event
+      event.ret_val = r;
+      m_journaler->committed(event.future);
+    }
+
+    if (event.committed_io) {
       m_events.erase(it);
     } else {
       event.safe = true;
index f81e1a2350247bc7d6bc1c9b2c58d7b2d85ed86d..bee4dbe98667d94fa95c2725bf3886d097fbb6e6 100644 (file)
@@ -147,19 +147,19 @@ private:
 
   struct Event {
     Future future;
-    AioCompletion *aio_comp;
+    AioCompletion *aio_comp = nullptr;
     AioObjectRequests aio_object_requests;
     Contexts on_safe_contexts;
     ExtentInterval pending_extents;
-    bool safe;
-    int ret_val;
+    bool committed_io = false;
+    bool safe = false;
+    int ret_val = 0;
 
-    Event() : aio_comp(NULL) {
+    Event() {
     }
     Event(const Future &_future, AioCompletion *_aio_comp,
           const AioObjectRequests &_requests, uint64_t offset, size_t length)
-      : future(_future), aio_comp(_aio_comp), aio_object_requests(_requests),
-        safe(false), ret_val(0) {
+      : future(_future), aio_comp(_aio_comp), aio_object_requests(_requests) {
       if (length > 0) {
         pending_extents.insert(offset, length);
       }