From: Jason Dillaman Date: Thu, 28 May 2020 21:59:39 +0000 (-0400) Subject: librbd: restore missing flush on write-block logic X-Git-Tag: v16.1.0~2152^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=c62926f511f017c1862cfad7967f95d934814b6a;p=ceph.git librbd: restore missing flush on write-block logic When creating the new image dispatch layer, the original flush upon write-block was dropped. This is resulting in some random race conditions where object IO is still in-flight when the write-block indicates it's complete. Signed-off-by: Jason Dillaman --- diff --git a/src/librbd/io/WriteBlockImageDispatch.cc b/src/librbd/io/WriteBlockImageDispatch.cc index 6cc86764278..ab69b3d85f3 100644 --- a/src/librbd/io/WriteBlockImageDispatch.cc +++ b/src/librbd/io/WriteBlockImageDispatch.cc @@ -18,6 +18,18 @@ namespace librbd { namespace io { +template +struct WriteBlockImageDispatch::C_BlockedWrites : public Context { + WriteBlockImageDispatch *dispatch; + explicit C_BlockedWrites(WriteBlockImageDispatch *dispatch) + : dispatch(dispatch) { + } + + void finish(int r) override { + dispatch->handle_blocked_writes(r); + } +}; + template WriteBlockImageDispatch::WriteBlockImageDispatch(I* image_ctx) : m_image_ctx(image_ctx), @@ -202,14 +214,15 @@ void WriteBlockImageDispatch::handle_finished(int r, uint64_t tid) { } m_in_flight_write_tids.erase(it); - Contexts write_blocker_contexts; - if (m_in_flight_write_tids.empty()) { - std::swap(write_blocker_contexts, m_write_blocker_contexts); + bool writes_blocked = false; + if (m_write_blockers > 0 && m_in_flight_write_tids.empty()) { + ldout(cct, 10) << "flushing all in-flight IO for blocked writes" << dendl; + writes_blocked = true; } locker.unlock(); - for (auto ctx : write_blocker_contexts) { - ctx->complete(0); + if (writes_blocked) { + flush_io(new C_BlockedWrites(this)); } } @@ -245,6 +258,22 @@ void WriteBlockImageDispatch::flush_io(Context* on_finish) { req->send(); } +template +void WriteBlockImageDispatch::handle_blocked_writes(int r) { + auto cct = m_image_ctx->cct; + ldout(cct, 10) << dendl; + + Contexts write_blocker_contexts; + { + std::unique_lock locker{m_lock}; + std::swap(write_blocker_contexts, m_write_blocker_contexts); + } + + for (auto ctx : write_blocker_contexts) { + ctx->complete(0); + } +} + } // namespace io } // namespace librbd diff --git a/src/librbd/io/WriteBlockImageDispatch.h b/src/librbd/io/WriteBlockImageDispatch.h index 2c8064ed4a9..42e7fed8282 100644 --- a/src/librbd/io/WriteBlockImageDispatch.h +++ b/src/librbd/io/WriteBlockImageDispatch.h @@ -84,6 +84,8 @@ public: void handle_finished(int r, uint64_t tid) override; private: + struct C_BlockedWrites; + typedef std::list Contexts; typedef std::set Tids; @@ -101,6 +103,8 @@ private: Context* on_dispatched); void flush_io(Context* on_finish); + void handle_blocked_writes(int r); + }; } // namespace io