]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
journal: avoid race between flush request and in-flight flushes 6923/head
authorJason Dillaman <dillaman@redhat.com>
Mon, 14 Dec 2015 20:28:38 +0000 (15:28 -0500)
committerJason Dillaman <dillaman@redhat.com>
Mon, 14 Dec 2015 20:28:38 +0000 (15:28 -0500)
Previously, if the journal object was empty, a flush request could
complete instantly even if there is an in-flight 'record safe'
callback.

Fixes: #14060
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/journal/ObjectRecorder.cc
src/journal/ObjectRecorder.h

index 7c0143f025e53977aeaedd897839b25964c21d25..29f1378ea61b23f827a93fc51885655a6d9325ce 100644 (file)
@@ -30,7 +30,7 @@ ObjectRecorder::ObjectRecorder(librados::IoCtx &ioctx, const std::string &oid,
     m_append_task(NULL),
     m_lock(utils::unique_lock_name("ObjectRecorder::m_lock", this)),
     m_append_tid(0), m_pending_bytes(0), m_size(0), m_overflowed(false),
-    m_object_closed(false) {
+    m_object_closed(false), m_in_flight_flushes(false) {
   m_ioctx.dup(ioctx);
   m_cct = reinterpret_cast<CephContext*>(m_ioctx.cct());
   assert(m_overflow_handler != NULL);
@@ -73,6 +73,13 @@ void ObjectRecorder::flush(Context *on_safe) {
   {
     Mutex::Locker locker(m_lock);
 
+    // if currently handling flush notifications, wait so that
+    // we notify in the correct order (since lock is dropped on
+    // callback)
+    if (m_in_flight_flushes) {
+      m_in_flight_flushes_cond.Wait(m_lock);
+    }
+
     // attach the flush to the most recent append
     if (!m_append_buffers.empty()) {
       future = Future(m_append_buffers.rbegin()->first);
@@ -229,6 +236,7 @@ void ObjectRecorder::handle_append_flushed(uint64_t tid, int r) {
       // all remaining unsent appends should be redirected to new object
       notify_overflow();
     }
+    m_in_flight_flushes = true;
   }
 
   // Flag the associated futures as complete.
@@ -238,6 +246,11 @@ void ObjectRecorder::handle_append_flushed(uint64_t tid, int r) {
                      << dendl;
     buf_it->first->safe(r);
   }
+
+  // wake up any flush requests that raced with a RADOS callback
+  Mutex::Locker locker(m_lock);
+  m_in_flight_flushes = false;
+  m_in_flight_flushes_cond.Signal();
 }
 
 void ObjectRecorder::append_overflowed(uint64_t tid) {
index f9a776863de312f17561c4ee5a70f112409247b9..2cc85415e5eb5c4f410f532923b12e8e69a11d11 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "include/Context.h"
 #include "include/rados/librados.hpp"
+#include "common/Cond.h"
 #include "common/Mutex.h"
 #include "common/RefCountedObj.h"
 #include "journal/FutureImpl.h"
@@ -131,6 +132,9 @@ private:
 
   bufferlist m_prefetch_bl;
 
+  bool m_in_flight_flushes;
+  Cond m_in_flight_flushes_cond;
+
   void handle_append_task();
   void cancel_append_task();
   void schedule_append_task();