From: Jason Dillaman Date: Mon, 14 Dec 2015 20:28:38 +0000 (-0500) Subject: journal: avoid race between flush request and in-flight flushes X-Git-Tag: v10.0.2~39^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=664903fbee4909d0f48d634cf2f694f8b5c1a554;p=ceph.git journal: avoid race between flush request and in-flight flushes 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 --- diff --git a/src/journal/ObjectRecorder.cc b/src/journal/ObjectRecorder.cc index 7c0143f025e53..29f1378ea61b2 100644 --- a/src/journal/ObjectRecorder.cc +++ b/src/journal/ObjectRecorder.cc @@ -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(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) { diff --git a/src/journal/ObjectRecorder.h b/src/journal/ObjectRecorder.h index f9a776863de31..2cc85415e5eb5 100644 --- a/src/journal/ObjectRecorder.h +++ b/src/journal/ObjectRecorder.h @@ -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();