From: Jason Dillaman Date: Fri, 21 Aug 2020 14:37:41 +0000 (-0400) Subject: librbd: flush requests could race past initiation of write ops X-Git-Tag: v16.1.0~1350^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=4e1633edfc28244ac13e6870f906e01e2e49e840;p=ceph.git librbd: flush requests could race past initiation of write ops 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 --- diff --git a/src/librbd/io/QueueImageDispatch.cc b/src/librbd/io/QueueImageDispatch.cc index 7cb5dfc51484..607d35df3f7f 100644 --- a/src/librbd/io/QueueImageDispatch.cc +++ b/src/librbd/io/QueueImageDispatch.cc @@ -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 QueueImageDispatch::QueueImageDispatch(I* image_ctx) - : m_image_ctx(image_ctx) { + : m_image_ctx(image_ctx), m_flush_tracker(new FlushTracker(image_ctx)) { auto cct = m_image_ctx->cct; ldout(cct, 5) << "ictx=" << image_ctx << dendl; } +template +QueueImageDispatch::~QueueImageDispatch() { + delete m_flush_tracker; +} + template void QueueImageDispatch::shut_down(Context* on_finish) { + m_flush_tracker->shut_down(); on_finish->complete(0); } @@ -39,7 +46,7 @@ bool QueueImageDispatch::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 @@ -51,7 +58,7 @@ bool QueueImageDispatch::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 @@ -63,7 +70,7 @@ bool QueueImageDispatch::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 @@ -75,7 +82,7 @@ bool QueueImageDispatch::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 @@ -88,7 +95,7 @@ bool QueueImageDispatch::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 @@ -104,16 +111,31 @@ bool QueueImageDispatch::flush( return false; } - return enqueue(dispatch_result, on_dispatched); + *dispatch_result = DISPATCH_RESULT_CONTINUE; + m_flush_tracker->flush(on_dispatched); + return true; +} + +template +void QueueImageDispatch::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 bool QueueImageDispatch::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; diff --git a/src/librbd/io/QueueImageDispatch.h b/src/librbd/io/QueueImageDispatch.h index 03d5068d759b..5592d1d5bd75 100644 --- a/src/librbd/io/QueueImageDispatch.h +++ b/src/librbd/io/QueueImageDispatch.h @@ -23,11 +23,13 @@ struct ImageCtx; namespace io { struct AioCompletion; +template class FlushTracker; template 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* 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* m_flush_tracker; + + bool enqueue(bool read_op, uint64_t tid, DispatchResult* dispatch_result, + Context* on_dispatched); };