]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
librbd: restore missing flush on write-block logic
authorJason Dillaman <dillaman@redhat.com>
Thu, 28 May 2020 21:59:39 +0000 (17:59 -0400)
committerJason Dillaman <dillaman@redhat.com>
Wed, 3 Jun 2020 13:45:24 +0000 (09:45 -0400)
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 <dillaman@redhat.com>
src/librbd/io/WriteBlockImageDispatch.cc
src/librbd/io/WriteBlockImageDispatch.h

index 6cc8676427812285361ef40c1b3fbf6faafdd17e..ab69b3d85f36004d1e7e0f14d1ae122ca8e41972 100644 (file)
 namespace librbd {
 namespace io {
 
+template <typename I>
+struct WriteBlockImageDispatch<I>::C_BlockedWrites : public Context {
+  WriteBlockImageDispatch *dispatch;
+  explicit C_BlockedWrites(WriteBlockImageDispatch *dispatch)
+    : dispatch(dispatch) {
+  }
+
+  void finish(int r) override {
+    dispatch->handle_blocked_writes(r);
+  }
+};
+
 template <typename I>
 WriteBlockImageDispatch<I>::WriteBlockImageDispatch(I* image_ctx)
   : m_image_ctx(image_ctx),
@@ -202,14 +214,15 @@ void WriteBlockImageDispatch<I>::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<I>::flush_io(Context* on_finish) {
   req->send();
 }
 
+template <typename I>
+void WriteBlockImageDispatch<I>::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
 
index 2c8064ed4a9ed4ceda25767e0909c4898384830a..42e7fed82822053ee35439fa7c3c7970af593a2c 100644 (file)
@@ -84,6 +84,8 @@ public:
   void handle_finished(int r, uint64_t tid) override;
 
 private:
+  struct C_BlockedWrites;
+
   typedef std::list<Context*> Contexts;
   typedef std::set<uint64_t> Tids;
 
@@ -101,6 +103,8 @@ private:
                   Context* on_dispatched);
   void flush_io(Context* on_finish);
 
+  void handle_blocked_writes(int r);
+
 };
 
 } // namespace io