]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
librbd: flush requests could race past initiation of write ops
authorJason Dillaman <dillaman@redhat.com>
Fri, 21 Aug 2020 14:37:41 +0000 (10:37 -0400)
committerJason Dillaman <dillaman@redhat.com>
Fri, 21 Aug 2020 14:37:41 +0000 (10:37 -0400)
Now that IO is being processed by multiple threads, it's possible
that a write operation that was issued prior to a flush would not
have been started prior to the processing of the flush.

Fixes: https://tracker.ceph.com/issues/47050
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/librbd/io/QueueImageDispatch.cc
src/librbd/io/QueueImageDispatch.h

index 7cb5dfc5148497f2d740c8ea293a3cbf6a1d77bf..607d35df3f7f494d69c8ab9efdee2a89ea9cbec1 100644 (file)
@@ -8,6 +8,7 @@
 #include "librbd/ImageCtx.h"
 #include "librbd/Utils.h"
 #include "librbd/io/AioCompletion.h"
+#include "librbd/io/FlushTracker.h"
 #include "librbd/io/ImageDispatchSpec.h"
 
 #define dout_subsys ceph_subsys_rbd
@@ -20,13 +21,19 @@ namespace io {
 
 template <typename I>
 QueueImageDispatch<I>::QueueImageDispatch(I* image_ctx)
-  : m_image_ctx(image_ctx) {
+  : m_image_ctx(image_ctx), m_flush_tracker(new FlushTracker<I>(image_ctx)) {
   auto cct = m_image_ctx->cct;
   ldout(cct, 5) << "ictx=" << image_ctx << dendl;
 }
 
+template <typename I>
+QueueImageDispatch<I>::~QueueImageDispatch() {
+  delete m_flush_tracker;
+}
+
 template <typename I>
 void QueueImageDispatch<I>::shut_down(Context* on_finish) {
+  m_flush_tracker->shut_down();
   on_finish->complete(0);
 }
 
@@ -39,7 +46,7 @@ bool QueueImageDispatch<I>::read(
   auto cct = m_image_ctx->cct;
   ldout(cct, 20) << "tid=" << tid << dendl;
 
-  return enqueue(dispatch_result, on_dispatched);
+  return enqueue(true, tid, dispatch_result, on_dispatched);
 }
 
 template <typename I>
@@ -51,7 +58,7 @@ bool QueueImageDispatch<I>::write(
   auto cct = m_image_ctx->cct;
   ldout(cct, 20) << "tid=" << tid << dendl;
 
-  return enqueue(dispatch_result, on_dispatched);
+  return enqueue(false, tid, dispatch_result, on_dispatched);
 }
 
 template <typename I>
@@ -63,7 +70,7 @@ bool QueueImageDispatch<I>::discard(
   auto cct = m_image_ctx->cct;
   ldout(cct, 20) << "tid=" << tid << dendl;
 
-  return enqueue(dispatch_result, on_dispatched);
+  return enqueue(false, tid, dispatch_result, on_dispatched);
 }
 
 template <typename I>
@@ -75,7 +82,7 @@ bool QueueImageDispatch<I>::write_same(
   auto cct = m_image_ctx->cct;
   ldout(cct, 20) << "tid=" << tid << dendl;
 
-  return enqueue(dispatch_result, on_dispatched);
+  return enqueue(false, tid, dispatch_result, on_dispatched);
 }
 
 template <typename I>
@@ -88,7 +95,7 @@ bool QueueImageDispatch<I>::compare_and_write(
   auto cct = m_image_ctx->cct;
   ldout(cct, 20) << "tid=" << tid << dendl;
 
-  return enqueue(dispatch_result, on_dispatched);
+  return enqueue(false, tid, dispatch_result, on_dispatched);
 }
 
 template <typename I>
@@ -104,16 +111,31 @@ bool QueueImageDispatch<I>::flush(
     return false;
   }
 
-  return enqueue(dispatch_result, on_dispatched);
+  *dispatch_result = DISPATCH_RESULT_CONTINUE;
+  m_flush_tracker->flush(on_dispatched);
+  return true;
+}
+
+template <typename I>
+void QueueImageDispatch<I>::handle_finished(int r, uint64_t tid) {
+  auto cct = m_image_ctx->cct;
+  ldout(cct, 20) << "tid=" << tid << dendl;
+
+  m_flush_tracker->finish_io(tid);
 }
 
 template <typename I>
 bool QueueImageDispatch<I>::enqueue(
-    DispatchResult* dispatch_result, Context* on_dispatched) {
+    bool read_op, uint64_t tid, DispatchResult* dispatch_result,
+    Context* on_dispatched) {
   if (!m_image_ctx->non_blocking_aio) {
     return false;
   }
 
+  if (!read_op) {
+    m_flush_tracker->start_io(tid);
+  }
+
   *dispatch_result = DISPATCH_RESULT_CONTINUE;
   m_image_ctx->asio_engine->post(on_dispatched, 0);
   return true;
index 03d5068d759b6d842bb3eae4435bfe91407d9805..5592d1d5bd754b26211c49e86d668f32376f7110 100644 (file)
@@ -23,11 +23,13 @@ struct ImageCtx;
 namespace io {
 
 struct AioCompletion;
+template <typename> class FlushTracker;
 
 template <typename ImageCtxT>
 class QueueImageDispatch : public ImageDispatchInterface {
 public:
   QueueImageDispatch(ImageCtxT* image_ctx);
+  ~QueueImageDispatch();
 
   ImageDispatchLayer get_dispatch_layer() const override {
     return IMAGE_DISPATCH_LAYER_QUEUE;
@@ -69,13 +71,15 @@ public:
       std::atomic<uint32_t>* image_dispatch_flags,
       DispatchResult* dispatch_result, Context* on_dispatched) override;
 
-  void handle_finished(int r, uint64_t tid) override {
-  }
+  void handle_finished(int r, uint64_t tid) override;
 
 private:
   ImageCtxT* m_image_ctx;
 
-  bool enqueue(DispatchResult* dispatch_result, Context* on_dispatched);
+  FlushTracker<ImageCtxT>* m_flush_tracker;
+
+  bool enqueue(bool read_op, uint64_t tid, DispatchResult* dispatch_result,
+               Context* on_dispatched);
 
 };