From fc8b8d628e26168f207134d088de250d6dab1fdb Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Wed, 15 Jul 2015 17:32:28 -0400 Subject: [PATCH] librbd: inform the journal when pending IO safely commits When caching is disabled, the AioCompletion notifies the journal that the update is safe. When caching is enabled, writeback can result in partial write extents being overwritten (and no longer associated to the original journal event). In this case, the writeback handler is responsible for informing the journal when writes are safe. Signed-off-by: Jason Dillaman --- src/librbd/AioCompletion.cc | 13 ++++++++++ src/librbd/AioCompletion.h | 7 ++++- src/librbd/AioImageRequest.cc | 49 ++++++++++++++++++++++++++++++----- src/librbd/Journal.cc | 4 +-- 4 files changed, 64 insertions(+), 9 deletions(-) diff --git a/src/librbd/AioCompletion.cc b/src/librbd/AioCompletion.cc index 982a03fc7f798..ac6754d19a097 100644 --- a/src/librbd/AioCompletion.cc +++ b/src/librbd/AioCompletion.cc @@ -14,6 +14,7 @@ #include "librbd/internal.h" #include "librbd/AioCompletion.h" +#include "librbd/Journal.h" #ifdef WITH_LTTNG #include "tracing/librbd.h" @@ -86,6 +87,12 @@ namespace librbd { break; } + // inform the journal that the op has successfully committed + if (journal_tid != 0) { + assert(ictx->journal != NULL); + ictx->journal->commit_event(journal_tid, rval); + } + // note: possible for image to be closed after op marked finished if (async_op.started()) { async_op.finish_op(); @@ -148,6 +155,12 @@ namespace librbd { put_unlock(); } + void AioCompletion::associate_journal_event(uint64_t tid) { + Mutex::Locker l(lock); + assert(!done); + journal_tid = tid; + } + bool AioCompletion::is_complete() { tracepoint(librbd, aio_is_complete_enter, this); bool done; diff --git a/src/librbd/AioCompletion.h b/src/librbd/AioCompletion.h index 94ed682dd2e8b..532f7e261536c 100644 --- a/src/librbd/AioCompletion.h +++ b/src/librbd/AioCompletion.h @@ -62,13 +62,16 @@ namespace librbd { AsyncOperation async_op; + uint64_t journal_tid; + AioCompletion() : lock("AioCompletion::lock", true, false), done(false), rval(0), complete_cb(NULL), complete_arg(NULL), rbd_comp(NULL), pending_count(0), blockers(1), ref(1), released(false), ictx(NULL), aio_type(AIO_TYPE_NONE), - read_bl(NULL), read_buf(NULL), read_buf_len(0) { + read_bl(NULL), read_buf(NULL), read_buf_len(0), + journal_tid(0) { } ~AioCompletion() { } @@ -99,6 +102,8 @@ namespace librbd { void complete_request(CephContext *cct, ssize_t r); + void associate_journal_event(uint64_t tid); + bool is_complete(); ssize_t get_return_value(); diff --git a/src/librbd/AioImageRequest.cc b/src/librbd/AioImageRequest.cc index a902adcaf4f4b..daa99ecad9b30 100644 --- a/src/librbd/AioImageRequest.cc +++ b/src/librbd/AioImageRequest.cc @@ -50,6 +50,29 @@ struct C_DiscardJournalCommit : public Context { } }; +struct C_FlushJournalCommit : public Context { + ImageCtx &image_ctx; + AioCompletion *aio_comp; + + C_FlushJournalCommit(ImageCtx &_image_ctx, AioCompletion *_aio_comp, + uint64_t tid) + : image_ctx(_image_ctx), aio_comp(_aio_comp) { + CephContext *cct = image_ctx.cct; + ldout(cct, 20) << this << " C_FlushJournalCommit: " + << "delaying flush until journal tid " << tid << " " + << "safe" << dendl; + + aio_comp->add_request(); + } + + virtual void finish(int r) { + CephContext *cct = image_ctx.cct; + ldout(cct, 20) << this << " C_FlushJournalCommit: journal committed" + << dendl; + aio_comp->complete_request(cct, r); + } +}; + } // anonymous namespace void AioImageRequest::aio_read( @@ -275,8 +298,13 @@ uint64_t AioImageWrite::append_journal_event( bl.append(m_buf, m_len); journal::EventEntry event_entry(journal::AioWriteEvent(m_off, m_len, bl)); - return m_image_ctx.journal->append_event(m_aio_comp, event_entry, requests, - m_off, m_len, synchronous); + uint64_t tid = m_image_ctx.journal->append_event(m_aio_comp, event_entry, + requests, m_off, m_len, + synchronous); + if (m_image_ctx.object_cacher == NULL) { + m_aio_comp->associate_journal_event(tid); + } + return tid; } void AioImageWrite::send_cache_requests(const ObjectExtents &object_extents, @@ -330,8 +358,11 @@ void AioImageWrite::update_stats(size_t length) { uint64_t AioImageDiscard::append_journal_event( const AioObjectRequests &requests, bool synchronous) { journal::EventEntry event_entry(journal::AioDiscardEvent(m_off, m_len)); - return m_image_ctx.journal->append_event(m_aio_comp, event_entry, requests, - m_off, m_len, synchronous); + uint64_t tid = m_image_ctx.journal->append_event(m_aio_comp, event_entry, + requests, m_off, m_len, + synchronous); + m_aio_comp->associate_journal_event(tid); + return tid; } void AioImageDiscard::send_cache_requests(const ObjectExtents &object_extents, @@ -387,9 +418,15 @@ void AioImageFlush::send_request() { // journal the flush event RWLock::RLocker snap_locker(m_image_ctx.snap_lock); if (m_image_ctx.journal != NULL) { - m_image_ctx.journal->append_event( + uint64_t journal_tid = m_image_ctx.journal->append_event( m_aio_comp, journal::EventEntry(journal::AioFlushEvent()), - AioObjectRequests(), 0, 0, true); + AioObjectRequests(), 0, 0, false); + + C_FlushJournalCommit *ctx = new C_FlushJournalCommit(m_image_ctx, + m_aio_comp, + journal_tid); + m_image_ctx.journal->flush_event(journal_tid, ctx); + m_aio_comp->associate_journal_event(journal_tid); } } diff --git a/src/librbd/Journal.cc b/src/librbd/Journal.cc index 1278ef36cf754..ab848160101d4 100644 --- a/src/librbd/Journal.cc +++ b/src/librbd/Journal.cc @@ -312,13 +312,13 @@ void Journal::destroy_journaler() { void Journal::complete_event(Events::iterator it, int r) { assert(m_lock.is_locked()); + assert(m_state == STATE_RECORDING); CephContext *cct = m_image_ctx.cct; ldout(cct, 20) << this << " " << __func__ << ": tid=" << it->first << " " << "r=" << r << dendl; - // TODO - + m_journaler->committed(it->second.future); m_events.erase(it); } -- 2.39.5