]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: flush context potentially completing too early
authorJason Dillaman <dillaman@redhat.com>
Tue, 24 Feb 2015 17:53:45 +0000 (12:53 -0500)
committerJason Dillaman <dillaman@redhat.com>
Thu, 26 Feb 2015 00:51:07 +0000 (19:51 -0500)
If the async operation associated with a flush request completes,
only complete the flush contexts if no previous operations are
still in flight. Otherwise, move the flush contexts to an older
in-flight async operation.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/librbd/AsyncOperation.cc
src/librbd/ImageCtx.cc

index cdb131067956c454d4f21cfa3de219b5e2f5b467..2f0ef81e4181fc0d45f2d1f8066a61a3e0aa9547 100644 (file)
@@ -17,14 +17,26 @@ void AsyncOperation::start_op(ImageCtx &image_ctx) {
 
   ldout(m_image_ctx->cct, 20) << this << " " << __func__ << dendl; 
   Mutex::Locker l(m_image_ctx->async_ops_lock);
-  m_image_ctx->async_ops.push_back(&m_xlist_item);
+  m_image_ctx->async_ops.push_front(&m_xlist_item);
 }
 
 void AsyncOperation::finish_op() {
   ldout(m_image_ctx->cct, 20) << this << " " << __func__ << dendl;
   {
     Mutex::Locker l(m_image_ctx->async_ops_lock);
+    xlist<AsyncOperation *>::iterator iter(&m_xlist_item);
+    ++iter;
     assert(m_xlist_item.remove_myself());
+
+    // linked list stored newest -> oldest ops
+    if (!iter.end()) {
+      ldout(m_image_ctx->cct, 20) << "moving flush contexts to previous op: "
+                                  << *iter << dendl;
+      (*iter)->m_flush_contexts.insert((*iter)->m_flush_contexts.end(),
+                                       m_flush_contexts.begin(),
+                                       m_flush_contexts.end());
+      return;
+    }
   }
 
   while (!m_flush_contexts.empty()) {
index 9fbc04ca489287e8e3c6c9e49df59bcbb0f8487d..2637d64acc155fd132eb37e2c76da6cfde5e24af 100644 (file)
@@ -708,6 +708,6 @@ namespace librbd {
 
     ldout(cct, 20) << "flush async operations: " << on_finish << " "
                    << "count=" << async_ops.size() << dendl;
-    async_ops.back()->add_flush_context(on_finish);
+    async_ops.front()->add_flush_context(on_finish);
   }
 }