From: Jason Dillaman Date: Wed, 27 Jul 2016 03:26:08 +0000 (-0400) Subject: librbd: convert AioImageRequest derived classes to templates X-Git-Tag: v10.2.3~48^2~5 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=026f6d2da25d41f21f5bb5f8ee367cc7601296f7;p=ceph.git librbd: convert AioImageRequest derived classes to templates Signed-off-by: Jason Dillaman (cherry picked from commit a945c2c235d9259b1d4a8a579d7e6efc2ed35916) --- diff --git a/src/librbd/AioImageRequest.cc b/src/librbd/AioImageRequest.cc index 807c7e0699a46..f7fb0a5d04993 100644 --- a/src/librbd/AioImageRequest.cc +++ b/src/librbd/AioImageRequest.cc @@ -7,6 +7,7 @@ #include "librbd/ImageCtx.h" #include "librbd/internal.h" #include "librbd/Journal.h" +#include "librbd/Utils.h" #include "librbd/journal/Types.h" #include "include/rados/librados.hpp" #include "osdc/Striper.h" @@ -17,16 +18,19 @@ namespace librbd { +using util::get_image_ctx; + namespace { +template struct C_DiscardJournalCommit : public Context { typedef std::vector ObjectExtents; - ImageCtx &image_ctx; + ImageCtxT &image_ctx; AioCompletion *aio_comp; ObjectExtents object_extents; - C_DiscardJournalCommit(ImageCtx &_image_ctx, AioCompletion *_aio_comp, + C_DiscardJournalCommit(ImageCtxT &_image_ctx, AioCompletion *_aio_comp, const ObjectExtents &_object_extents, uint64_t tid) : image_ctx(_image_ctx), aio_comp(_aio_comp), object_extents(_object_extents) { @@ -49,11 +53,12 @@ struct C_DiscardJournalCommit : public Context { } }; +template struct C_FlushJournalCommit : public Context { - ImageCtx &image_ctx; + ImageCtxT &image_ctx; AioCompletion *aio_comp; - C_FlushJournalCommit(ImageCtx &_image_ctx, AioCompletion *_aio_comp, + C_FlushJournalCommit(ImageCtxT &_image_ctx, AioCompletion *_aio_comp, uint64_t tid) : image_ctx(_image_ctx), aio_comp(_aio_comp) { CephContext *cct = image_ctx.cct; @@ -108,79 +113,84 @@ void AioImageRequest::aio_discard(I *ictx, AioCompletion *c, template void AioImageRequest::aio_flush(I *ictx, AioCompletion *c) { - assert(c->is_initialized(AIO_TYPE_FLUSH)); AioImageFlush req(*ictx, c); req.send(); } template void AioImageRequest::send() { - assert(m_image_ctx.owner_lock.is_locked()); + I &image_ctx = this->m_image_ctx; + assert(image_ctx.owner_lock.is_locked()); assert(m_aio_comp->is_initialized(get_aio_type())); assert(m_aio_comp->is_started() ^ (get_aio_type() == AIO_TYPE_FLUSH)); - CephContext *cct = m_image_ctx.cct; - ldout(cct, 20) << get_request_type() << ": ictx=" << &m_image_ctx << ", " - << "completion=" << m_aio_comp << dendl; + CephContext *cct = image_ctx.cct; + AioCompletion *aio_comp = this->m_aio_comp; + ldout(cct, 20) << get_request_type() << ": ictx=" << &image_ctx << ", " + << "completion=" << aio_comp << dendl; - m_aio_comp->get(); + aio_comp->get(); send_request(); } template void AioImageRequest::fail(int r) { - m_aio_comp->get(); - m_aio_comp->fail(r); + AioCompletion *aio_comp = this->m_aio_comp; + aio_comp->get(); + aio_comp->fail(r); } -void AioImageRead::send_request() { - CephContext *cct = m_image_ctx.cct; +template +void AioImageRead::send_request() { + I &image_ctx = this->m_image_ctx; + CephContext *cct = image_ctx.cct; - if (m_image_ctx.object_cacher && m_image_ctx.readahead_max_bytes > 0 && + if (image_ctx.object_cacher && image_ctx.readahead_max_bytes > 0 && !(m_op_flags & LIBRADOS_OP_FLAG_FADVISE_RANDOM)) { - readahead(&m_image_ctx, m_image_extents); + readahead(get_image_ctx(&image_ctx), m_image_extents); } + AioCompletion *aio_comp = this->m_aio_comp; librados::snap_t snap_id; map > object_extents; uint64_t buffer_ofs = 0; { // prevent image size from changing between computing clip and recording // pending async operation - RWLock::RLocker snap_locker(m_image_ctx.snap_lock); - snap_id = m_image_ctx.snap_id; + RWLock::RLocker snap_locker(image_ctx.snap_lock); + snap_id = image_ctx.snap_id; // map for (vector >::const_iterator p = m_image_extents.begin(); p != m_image_extents.end(); ++p) { uint64_t len = p->second; - int r = clip_io(&m_image_ctx, p->first, &len); + int r = clip_io(get_image_ctx(&image_ctx), p->first, &len); if (r < 0) { - m_aio_comp->fail(r); + aio_comp->fail(r); return; } if (len == 0) { continue; } - Striper::file_to_extents(cct, m_image_ctx.format_string, - &m_image_ctx.layout, p->first, len, 0, + Striper::file_to_extents(cct, image_ctx.format_string, + &image_ctx.layout, p->first, len, 0, object_extents, buffer_ofs); buffer_ofs += len; } } - m_aio_comp->read_buf = m_buf; - m_aio_comp->read_buf_len = buffer_ofs; - m_aio_comp->read_bl = m_pbl; + aio_comp->read_buf = m_buf; + aio_comp->read_buf_len = buffer_ofs; + aio_comp->read_bl = m_pbl; // pre-calculate the expected number of read requests uint32_t request_count = 0; for (auto &object_extent : object_extents) { request_count += object_extent.second.size(); } - m_aio_comp->set_request_count(request_count); + aio_comp->set_request_count(request_count); // issue the requests for (auto &object_extent : object_extents) { @@ -189,74 +199,79 @@ void AioImageRead::send_request() { << extent.length << " from " << extent.buffer_extents << dendl; - C_AioRead *req_comp = new C_AioRead(m_aio_comp); - AioObjectRead *req = new AioObjectRead(&m_image_ctx, extent.oid.name, + C_AioRead *req_comp = new C_AioRead(aio_comp); + AioObjectRead *req = new AioObjectRead(get_image_ctx(&image_ctx), + extent.oid.name, extent.objectno, extent.offset, extent.length, extent.buffer_extents, snap_id, true, req_comp, m_op_flags); req_comp->set_req(req); - if (m_image_ctx.object_cacher) { - C_CacheRead *cache_comp = new C_CacheRead(&m_image_ctx, req); - m_image_ctx.aio_read_from_cache(extent.oid, extent.objectno, - &req->data(), extent.length, - extent.offset, cache_comp, m_op_flags); + if (image_ctx.object_cacher) { + C_CacheRead *cache_comp = new C_CacheRead(get_image_ctx(&image_ctx), + req); + image_ctx.aio_read_from_cache(extent.oid, extent.objectno, + &req->data(), extent.length, + extent.offset, cache_comp, m_op_flags); } else { req->send(); } } } - m_aio_comp->put(); + aio_comp->put(); - m_image_ctx.perfcounter->inc(l_librbd_rd); - m_image_ctx.perfcounter->inc(l_librbd_rd_bytes, buffer_ofs); + image_ctx.perfcounter->inc(l_librbd_rd); + image_ctx.perfcounter->inc(l_librbd_rd_bytes, buffer_ofs); } -void AbstractAioImageWrite::send_request() { - CephContext *cct = m_image_ctx.cct; +template +void AbstractAioImageWrite::send_request() { + I &image_ctx = this->m_image_ctx; + CephContext *cct = image_ctx.cct; - RWLock::RLocker md_locker(m_image_ctx.md_lock); + RWLock::RLocker md_locker(image_ctx.md_lock); bool journaling = false; + AioCompletion *aio_comp = this->m_aio_comp; uint64_t clip_len = m_len; ObjectExtents object_extents; ::SnapContext snapc; { // prevent image size from changing between computing clip and recording // pending async operation - RWLock::RLocker snap_locker(m_image_ctx.snap_lock); - if (m_image_ctx.snap_id != CEPH_NOSNAP || m_image_ctx.read_only) { - m_aio_comp->fail(-EROFS); + RWLock::RLocker snap_locker(image_ctx.snap_lock); + if (image_ctx.snap_id != CEPH_NOSNAP || image_ctx.read_only) { + aio_comp->fail(-EROFS); return; } - int r = clip_io(&m_image_ctx, m_off, &clip_len); + int r = clip_io(get_image_ctx(&image_ctx), m_off, &clip_len); if (r < 0) { - m_aio_comp->fail(r); + aio_comp->fail(r); return; } - snapc = m_image_ctx.snapc; + snapc = image_ctx.snapc; // map to object extents if (clip_len > 0) { - Striper::file_to_extents(cct, m_image_ctx.format_string, - &m_image_ctx.layout, m_off, clip_len, 0, + Striper::file_to_extents(cct, image_ctx.format_string, + &image_ctx.layout, m_off, clip_len, 0, object_extents); } - journaling = (m_image_ctx.journal != nullptr && - m_image_ctx.journal->is_journal_appending()); + journaling = (image_ctx.journal != nullptr && + image_ctx.journal->is_journal_appending()); } prune_object_extents(object_extents); if (!object_extents.empty()) { uint64_t journal_tid = 0; - m_aio_comp->set_request_count( + aio_comp->set_request_count( object_extents.size() + get_cache_request_count(journaling)); AioObjectRequests requests; @@ -265,32 +280,35 @@ void AbstractAioImageWrite::send_request() { if (journaling) { // in-flight ops are flushed prior to closing the journal - assert(m_image_ctx.journal != NULL); + assert(image_ctx.journal != NULL); journal_tid = append_journal_event(requests, m_synchronous); } - if (m_image_ctx.object_cacher != NULL) { + if (image_ctx.object_cacher != NULL) { send_cache_requests(object_extents, journal_tid); } } else { // no IO to perform -- fire completion - m_aio_comp->unblock(); + aio_comp->unblock(); } update_stats(clip_len); - m_aio_comp->put(); + aio_comp->put(); } -void AbstractAioImageWrite::send_object_requests( +template +void AbstractAioImageWrite::send_object_requests( const ObjectExtents &object_extents, const ::SnapContext &snapc, AioObjectRequests *aio_object_requests) { - CephContext *cct = m_image_ctx.cct; + I &image_ctx = this->m_image_ctx; + CephContext *cct = image_ctx.cct; + AioCompletion *aio_comp = this->m_aio_comp; for (ObjectExtents::const_iterator p = object_extents.begin(); p != object_extents.end(); ++p) { ldout(cct, 20) << " oid " << p->oid << " " << p->offset << "~" << p->length << " from " << p->buffer_extents << dendl; - C_AioRequest *req_comp = new C_AioRequest(m_aio_comp); + C_AioRequest *req_comp = new C_AioRequest(aio_comp); AioObjectRequest *request = create_object_request(*p, snapc, req_comp); // if journaling, stash the request for later; otherwise send @@ -304,61 +322,73 @@ void AbstractAioImageWrite::send_object_requests( } } -void AioImageWrite::assemble_extent(const ObjectExtent &object_extent, +template +void AioImageWrite::assemble_extent(const ObjectExtent &object_extent, bufferlist *bl) { - for (Extents::const_iterator q = object_extent.buffer_extents.begin(); + for (auto q = object_extent.buffer_extents.begin(); q != object_extent.buffer_extents.end(); ++q) { bl->append(m_buf + q->first, q->second);; } } -uint64_t AioImageWrite::append_journal_event( +template +uint64_t AioImageWrite::append_journal_event( const AioObjectRequests &requests, bool synchronous) { bufferlist bl; - bl.append(m_buf, m_len); - - uint64_t tid = m_image_ctx.journal->append_write_event(m_off, m_len, bl, - requests, synchronous); - if (m_image_ctx.object_cacher == NULL) { - m_aio_comp->associate_journal_event(tid); + bl.append(m_buf, this->m_len); + + I &image_ctx = this->m_image_ctx; + uint64_t tid = image_ctx.journal->append_write_event(this->m_off, this->m_len, + bl, requests, + synchronous); + if (image_ctx.object_cacher == NULL) { + AioCompletion *aio_comp = this->m_aio_comp; + aio_comp->associate_journal_event(tid); } return tid; } -void AioImageWrite::send_cache_requests(const ObjectExtents &object_extents, +template +void AioImageWrite::send_cache_requests(const ObjectExtents &object_extents, uint64_t journal_tid) { - for (ObjectExtents::const_iterator p = object_extents.begin(); - p != object_extents.end(); ++p) { + I &image_ctx = this->m_image_ctx; + for (auto p = object_extents.begin(); p != object_extents.end(); ++p) { const ObjectExtent &object_extent = *p; bufferlist bl; assemble_extent(object_extent, &bl); - C_AioRequest *req_comp = new C_AioRequest(m_aio_comp); - m_image_ctx.write_to_cache(object_extent.oid, bl, object_extent.length, - object_extent.offset, req_comp, m_op_flags, + AioCompletion *aio_comp = this->m_aio_comp; + C_AioRequest *req_comp = new C_AioRequest(aio_comp); + image_ctx.write_to_cache(object_extent.oid, bl, object_extent.length, + object_extent.offset, req_comp, m_op_flags, journal_tid); } } -void AioImageWrite::send_object_requests( +template +void AioImageWrite::send_object_requests( const ObjectExtents &object_extents, const ::SnapContext &snapc, AioObjectRequests *aio_object_requests) { + I &image_ctx = this->m_image_ctx; + // cache handles creating object requests during writeback - if (m_image_ctx.object_cacher == NULL) { - AbstractAioImageWrite::send_object_requests(object_extents, snapc, + if (image_ctx.object_cacher == NULL) { + AbstractAioImageWrite::send_object_requests(object_extents, snapc, aio_object_requests); } } -AioObjectRequest *AioImageWrite::create_object_request( +template +AioObjectRequest *AioImageWrite::create_object_request( const ObjectExtent &object_extent, const ::SnapContext &snapc, Context *on_finish) { - assert(m_image_ctx.object_cacher == NULL); + I &image_ctx = this->m_image_ctx; + assert(image_ctx.object_cacher == NULL); bufferlist bl; assemble_extent(object_extent, &bl); - AioObjectWrite *req = new AioObjectWrite(&m_image_ctx, + AioObjectWrite *req = new AioObjectWrite(get_image_ctx(&image_ctx), object_extent.oid.name, object_extent.objectno, object_extent.offset, bl, @@ -367,29 +397,39 @@ AioObjectRequest *AioImageWrite::create_object_request( return req; } -void AioImageWrite::update_stats(size_t length) { - m_image_ctx.perfcounter->inc(l_librbd_wr); - m_image_ctx.perfcounter->inc(l_librbd_wr_bytes, length); +template +void AioImageWrite::update_stats(size_t length) { + I &image_ctx = this->m_image_ctx; + image_ctx.perfcounter->inc(l_librbd_wr); + image_ctx.perfcounter->inc(l_librbd_wr_bytes, length); } -uint64_t AioImageDiscard::append_journal_event( +template +uint64_t AioImageDiscard::append_journal_event( const AioObjectRequests &requests, bool synchronous) { - journal::EventEntry event_entry(journal::AioDiscardEvent(m_off, m_len)); - uint64_t tid = m_image_ctx.journal->append_io_event(std::move(event_entry), - requests, m_off, m_len, - synchronous); - m_aio_comp->associate_journal_event(tid); + I &image_ctx = this->m_image_ctx; + + journal::EventEntry event_entry(journal::AioDiscardEvent(this->m_off, + this->m_len)); + uint64_t tid = image_ctx.journal->append_io_event(std::move(event_entry), + requests, this->m_off, + this->m_len, synchronous); + + AioCompletion *aio_comp = this->m_aio_comp; + aio_comp->associate_journal_event(tid); return tid; } -void AioImageDiscard::prune_object_extents(ObjectExtents &object_extents) { - CephContext *cct = m_image_ctx.cct; +template +void AioImageDiscard::prune_object_extents(ObjectExtents &object_extents) { + I &image_ctx = this->m_image_ctx; + CephContext *cct = image_ctx.cct; if (!cct->_conf->rbd_skip_partial_discard) { return; } for (auto p = object_extents.begin(); p != object_extents.end(); ) { - if (p->offset + p->length < m_image_ctx.layout.object_size) { + if (p->offset + p->length < image_ctx.layout.object_size) { ldout(cct, 20) << " oid " << p->oid << " " << p->offset << "~" << p->length << " from " << p->buffer_extents << ": skip partial discard" << dendl; @@ -400,88 +440,108 @@ void AioImageDiscard::prune_object_extents(ObjectExtents &object_extents) { } } -uint32_t AioImageDiscard::get_cache_request_count(bool journaling) const { +template +uint32_t AioImageDiscard::get_cache_request_count(bool journaling) const { // extra completion request is required for tracking journal commit - return (m_image_ctx.object_cacher != nullptr && journaling ? 1 : 0); + I &image_ctx = this->m_image_ctx; + return (image_ctx.object_cacher != nullptr && journaling ? 1 : 0); } -void AioImageDiscard::send_cache_requests(const ObjectExtents &object_extents, +template +void AioImageDiscard::send_cache_requests(const ObjectExtents &object_extents, uint64_t journal_tid) { + I &image_ctx = this->m_image_ctx; if (journal_tid == 0) { - Mutex::Locker cache_locker(m_image_ctx.cache_lock); - m_image_ctx.object_cacher->discard_set(m_image_ctx.object_set, - object_extents); + Mutex::Locker cache_locker(image_ctx.cache_lock); + image_ctx.object_cacher->discard_set(image_ctx.object_set, + object_extents); } else { // cannot discard from cache until journal has committed - assert(m_image_ctx.journal != NULL); - m_image_ctx.journal->wait_event( - journal_tid, new C_DiscardJournalCommit(m_image_ctx, m_aio_comp, - object_extents, journal_tid)); + assert(image_ctx.journal != NULL); + AioCompletion *aio_comp = this->m_aio_comp; + image_ctx.journal->wait_event( + journal_tid, new C_DiscardJournalCommit(image_ctx, aio_comp, + object_extents, journal_tid)); } } -AioObjectRequest *AioImageDiscard::create_object_request( +template +AioObjectRequest *AioImageDiscard::create_object_request( const ObjectExtent &object_extent, const ::SnapContext &snapc, Context *on_finish) { + I &image_ctx = this->m_image_ctx; + AioObjectRequest *req; - if (object_extent.length == m_image_ctx.layout.object_size) { - req = new AioObjectRemove(&m_image_ctx, object_extent.oid.name, + if (object_extent.length == image_ctx.layout.object_size) { + req = new AioObjectRemove(get_image_ctx(&image_ctx), + object_extent.oid.name, object_extent.objectno, snapc, on_finish); } else if (object_extent.offset + object_extent.length == - m_image_ctx.layout.object_size) { - req = new AioObjectTruncate(&m_image_ctx, object_extent.oid.name, + image_ctx.layout.object_size) { + req = new AioObjectTruncate(get_image_ctx(&image_ctx), + object_extent.oid.name, object_extent.objectno, object_extent.offset, snapc, on_finish); } else { - req = new AioObjectZero(&m_image_ctx, object_extent.oid.name, + req = new AioObjectZero(get_image_ctx(&image_ctx), + object_extent.oid.name, object_extent.objectno, object_extent.offset, object_extent.length, snapc, on_finish); } return req; } -void AioImageDiscard::update_stats(size_t length) { - m_image_ctx.perfcounter->inc(l_librbd_discard); - m_image_ctx.perfcounter->inc(l_librbd_discard_bytes, length); +template +void AioImageDiscard::update_stats(size_t length) { + I &image_ctx = this->m_image_ctx; + image_ctx.perfcounter->inc(l_librbd_discard); + image_ctx.perfcounter->inc(l_librbd_discard_bytes, length); } -void AioImageFlush::send_request() { +template +void AioImageFlush::send_request() { + I &image_ctx = this->m_image_ctx; bool journaling = false; { - RWLock::RLocker snap_locker(m_image_ctx.snap_lock); - journaling = (m_image_ctx.journal != nullptr && - m_image_ctx.journal->is_journal_appending()); + RWLock::RLocker snap_locker(image_ctx.snap_lock); + journaling = (image_ctx.journal != nullptr && + image_ctx.journal->is_journal_appending()); } + AioCompletion *aio_comp = this->m_aio_comp; if (journaling) { // in-flight ops are flushed prior to closing the journal - uint64_t journal_tid = m_image_ctx.journal->append_io_event( + uint64_t journal_tid = image_ctx.journal->append_io_event( journal::EventEntry(journal::AioFlushEvent()), AioObjectRequests(), 0, 0, false); - m_aio_comp->set_request_count(2); + aio_comp->set_request_count(2); - C_FlushJournalCommit *ctx = new C_FlushJournalCommit(m_image_ctx, - m_aio_comp, - journal_tid); - C_AioRequest *req_comp = new C_AioRequest(m_aio_comp); - m_image_ctx.journal->flush_event(journal_tid, ctx); - m_aio_comp->associate_journal_event(journal_tid); - m_image_ctx.flush_async_operations(req_comp); + C_FlushJournalCommit *ctx = new C_FlushJournalCommit(image_ctx, + aio_comp, + journal_tid); + C_AioRequest *req_comp = new C_AioRequest(aio_comp); + image_ctx.journal->flush_event(journal_tid, ctx); + aio_comp->associate_journal_event(journal_tid); + image_ctx.flush_async_operations(req_comp); } else { // flush rbd cache only when journaling is not enabled - m_aio_comp->set_request_count(1); - C_AioRequest *req_comp = new C_AioRequest(m_aio_comp); - m_image_ctx.flush(req_comp); + aio_comp->set_request_count(1); + C_AioRequest *req_comp = new C_AioRequest(aio_comp); + image_ctx.flush(req_comp); } // track flush op for block writes - m_aio_comp->start_op(true); - m_aio_comp->put(); + aio_comp->start_op(true); + aio_comp->put(); - m_image_ctx.perfcounter->inc(l_librbd_aio_flush); + image_ctx.perfcounter->inc(l_librbd_aio_flush); } } // namespace librbd template class librbd::AioImageRequest; +template class librbd::AbstractAioImageWrite; +template class librbd::AioImageWrite; +template class librbd::AioImageDiscard; +template class librbd::AioImageFlush; diff --git a/src/librbd/AioImageRequest.h b/src/librbd/AioImageRequest.h index b36c09b27132d..f1605954089de 100644 --- a/src/librbd/AioImageRequest.h +++ b/src/librbd/AioImageRequest.h @@ -62,20 +62,24 @@ protected: virtual const char *get_request_type() const = 0; }; -class AioImageRead : public AioImageRequest<> { +template +class AioImageRead : public AioImageRequest { public: - AioImageRead(ImageCtx &image_ctx, AioCompletion *aio_comp, uint64_t off, + using typename AioImageRequest::Extents; + + AioImageRead(ImageCtxT &image_ctx, AioCompletion *aio_comp, uint64_t off, size_t len, char *buf, bufferlist *pbl, int op_flags) - : AioImageRequest(image_ctx, aio_comp), m_buf(buf), m_pbl(pbl), + : AioImageRequest(image_ctx, aio_comp), m_buf(buf), m_pbl(pbl), m_op_flags(op_flags) { m_image_extents.push_back(std::make_pair(off, len)); } - AioImageRead(ImageCtx &image_ctx, AioCompletion *aio_comp, + AioImageRead(ImageCtxT &image_ctx, AioCompletion *aio_comp, const Extents &image_extents, char *buf, bufferlist *pbl, int op_flags) - : AioImageRequest(image_ctx, aio_comp), m_image_extents(image_extents), - m_buf(buf), m_pbl(pbl), m_op_flags(op_flags) { + : AioImageRequest(image_ctx, aio_comp), + m_image_extents(image_extents), m_buf(buf), m_pbl(pbl), + m_op_flags(op_flags) { } protected: @@ -93,7 +97,8 @@ private: int m_op_flags; }; -class AbstractAioImageWrite : public AioImageRequest<> { +template +class AbstractAioImageWrite : public AioImageRequest { public: virtual bool is_write_op() const { return true; @@ -104,14 +109,16 @@ public: } protected: + using typename AioImageRequest::AioObjectRequests; + typedef std::vector ObjectExtents; const uint64_t m_off; const size_t m_len; - AbstractAioImageWrite(ImageCtx &image_ctx, AioCompletion *aio_comp, + AbstractAioImageWrite(ImageCtxT &image_ctx, AioCompletion *aio_comp, uint64_t off, size_t len) - : AioImageRequest(image_ctx, aio_comp), m_off(off), m_len(len), + : AioImageRequest(image_ctx, aio_comp), m_off(off), m_len(len), m_synchronous(false) { } @@ -140,15 +147,19 @@ private: bool m_synchronous; }; -class AioImageWrite : public AbstractAioImageWrite { +template +class AioImageWrite : public AbstractAioImageWrite { public: - AioImageWrite(ImageCtx &image_ctx, AioCompletion *aio_comp, uint64_t off, + AioImageWrite(ImageCtxT &image_ctx, AioCompletion *aio_comp, uint64_t off, size_t len, const char *buf, int op_flags) - : AbstractAioImageWrite(image_ctx, aio_comp, off, len), m_buf(buf), - m_op_flags(op_flags) { + : AbstractAioImageWrite(image_ctx, aio_comp, off, len), + m_buf(buf), m_op_flags(op_flags) { } protected: + using typename AioImageRequest::AioObjectRequests; + using typename AbstractAioImageWrite::ObjectExtents; + virtual aio_type_t get_aio_type() const { return AIO_TYPE_WRITE; } @@ -176,14 +187,18 @@ private: int m_op_flags; }; -class AioImageDiscard : public AbstractAioImageWrite { +template +class AioImageDiscard : public AbstractAioImageWrite { public: - AioImageDiscard(ImageCtx &image_ctx, AioCompletion *aio_comp, uint64_t off, + AioImageDiscard(ImageCtxT &image_ctx, AioCompletion *aio_comp, uint64_t off, uint64_t len) - : AbstractAioImageWrite(image_ctx, aio_comp, off, len) { + : AbstractAioImageWrite(image_ctx, aio_comp, off, len) { } protected: + using typename AioImageRequest::AioObjectRequests; + using typename AbstractAioImageWrite::ObjectExtents; + virtual aio_type_t get_aio_type() const { return AIO_TYPE_DISCARD; } @@ -205,10 +220,11 @@ protected: virtual void update_stats(size_t length); }; -class AioImageFlush : public AioImageRequest<> { +template +class AioImageFlush : public AioImageRequest { public: - AioImageFlush(ImageCtx &image_ctx, AioCompletion *aio_comp) - : AioImageRequest(image_ctx, aio_comp) { + AioImageFlush(ImageCtxT &image_ctx, AioCompletion *aio_comp) + : AioImageRequest(image_ctx, aio_comp) { } virtual bool is_write_op() const { @@ -216,6 +232,8 @@ public: } protected: + using typename AioImageRequest::AioObjectRequests; + virtual void send_request(); virtual aio_type_t get_aio_type() const { return AIO_TYPE_FLUSH; @@ -228,5 +246,9 @@ protected: } // namespace librbd extern template class librbd::AioImageRequest; +extern template class librbd::AbstractAioImageWrite; +extern template class librbd::AioImageWrite; +extern template class librbd::AioImageDiscard; +extern template class librbd::AioImageFlush; #endif // CEPH_LIBRBD_AIO_IMAGE_REQUEST_H diff --git a/src/librbd/AioImageRequestWQ.cc b/src/librbd/AioImageRequestWQ.cc index 55889e8f250e1..a3e8aac95deb8 100644 --- a/src/librbd/AioImageRequestWQ.cc +++ b/src/librbd/AioImageRequestWQ.cc @@ -52,7 +52,7 @@ ssize_t AioImageRequestWQ::write(uint64_t off, uint64_t len, const char *buf, << "len = " << len << dendl; m_image_ctx.snap_lock.get_read(); - int r = clip_io(&m_image_ctx, off, &len); + int r = clip_io(util::get_image_ctx(&m_image_ctx), off, &len); m_image_ctx.snap_lock.put_read(); if (r < 0) { lderr(cct) << "invalid IO request: " << cpp_strerror(r) << dendl; @@ -76,7 +76,7 @@ int AioImageRequestWQ::discard(uint64_t off, uint64_t len) { << "len = " << len << dendl; m_image_ctx.snap_lock.get_read(); - int r = clip_io(&m_image_ctx, off, &len); + int r = clip_io(util::get_image_ctx(&m_image_ctx), off, &len); m_image_ctx.snap_lock.put_read(); if (r < 0) { lderr(cct) << "invalid IO request: " << cpp_strerror(r) << dendl; @@ -123,7 +123,7 @@ void AioImageRequestWQ::aio_read(AioCompletion *c, uint64_t off, uint64_t len, if (m_image_ctx.non_blocking_aio || writes_blocked() || !writes_empty() || lock_required) { - queue(new AioImageRead(m_image_ctx, c, off, len, buf, pbl, op_flags)); + queue(new AioImageRead<>(m_image_ctx, c, off, len, buf, pbl, op_flags)); } else { c->start_op(); AioImageRequest<>::aio_read(&m_image_ctx, c, off, len, buf, pbl, op_flags); @@ -150,7 +150,7 @@ void AioImageRequestWQ::aio_write(AioCompletion *c, uint64_t off, uint64_t len, RWLock::RLocker owner_locker(m_image_ctx.owner_lock); if (m_image_ctx.non_blocking_aio || writes_blocked()) { - queue(new AioImageWrite(m_image_ctx, c, off, len, buf, op_flags)); + queue(new AioImageWrite<>(m_image_ctx, c, off, len, buf, op_flags)); } else { c->start_op(); AioImageRequest<>::aio_write(&m_image_ctx, c, off, len, buf, op_flags); @@ -176,7 +176,7 @@ void AioImageRequestWQ::aio_discard(AioCompletion *c, uint64_t off, RWLock::RLocker owner_locker(m_image_ctx.owner_lock); if (m_image_ctx.non_blocking_aio || writes_blocked()) { - queue(new AioImageDiscard(m_image_ctx, c, off, len)); + queue(new AioImageDiscard<>(m_image_ctx, c, off, len)); } else { c->start_op(); AioImageRequest<>::aio_discard(&m_image_ctx, c, off, len); @@ -200,7 +200,7 @@ void AioImageRequestWQ::aio_flush(AioCompletion *c, bool native_async) { RWLock::RLocker owner_locker(m_image_ctx.owner_lock); if (m_image_ctx.non_blocking_aio || writes_blocked() || !writes_empty()) { - queue(new AioImageFlush(m_image_ctx, c)); + queue(new AioImageFlush<>(m_image_ctx, c)); } else { AioImageRequest<>::aio_flush(&m_image_ctx, c); finish_in_flight_op(); diff --git a/src/librbd/Utils.h b/src/librbd/Utils.h index 799bf0f8d3994..59040819e9595 100644 --- a/src/librbd/Utils.h +++ b/src/librbd/Utils.h @@ -152,6 +152,7 @@ Context *create_async_context_callback(I &image_ctx, Context *on_finish) { image_ctx.op_work_queue, on_finish); } +// TODO: temporary until AioCompletion supports templated ImageCtx inline ImageCtx *get_image_ctx(ImageCtx *image_ctx) { return image_ctx; } diff --git a/src/test/librbd/mock/MockImageCtx.h b/src/test/librbd/mock/MockImageCtx.h index b7b73c835fa6f..e43927a9e0ab1 100644 --- a/src/test/librbd/mock/MockImageCtx.h +++ b/src/test/librbd/mock/MockImageCtx.h @@ -39,6 +39,7 @@ struct MockImageCtx { MockImageCtx(librbd::ImageCtx &image_ctx) : image_ctx(&image_ctx), cct(image_ctx.cct), + perfcounter(image_ctx.perfcounter), snap_name(image_ctx.snap_name), snap_id(image_ctx.snap_id), snap_exists(image_ctx.snap_exists), @@ -47,6 +48,7 @@ struct MockImageCtx { snap_info(image_ctx.snap_info), snap_ids(image_ctx.snap_ids), object_cacher(image_ctx.object_cacher), + object_set(image_ctx.object_set), old_format(image_ctx.old_format), read_only(image_ctx.read_only), lockers(image_ctx.lockers), @@ -70,9 +72,11 @@ struct MockImageCtx { id(image_ctx.id), name(image_ctx.name), parent_md(image_ctx.parent_md), + format_string(image_ctx.format_string), layout(image_ctx.layout), aio_work_queue(new MockAioImageRequestWQ()), op_work_queue(new MockContextWQ()), + readahead_max_bytes(image_ctx.readahead_max_bytes), parent(NULL), operations(new MockOperations()), state(new MockImageState()), image_watcher(NULL), object_map(NULL), @@ -145,6 +149,7 @@ struct MockImageCtx { MOCK_METHOD2(rm_snap, void(std::string in_snap_name, librados::snap_t id)); MOCK_METHOD1(flush, void(Context *)); + MOCK_METHOD1(flush_async_operations, void(Context *)); MOCK_METHOD1(flush_copyup, void(Context *)); MOCK_METHOD1(invalidate_cache, void(Context *)); @@ -165,8 +170,14 @@ struct MockImageCtx { MOCK_CONST_METHOD0(get_journal_policy, journal::Policy*()); + MOCK_METHOD7(aio_read_from_cache, void(object_t, uint64_t, bufferlist *, + size_t, uint64_t, Context *, int)); + MOCK_METHOD7(write_to_cache, void(object_t, const bufferlist&, size_t, + uint64_t, Context *, int, uint64_t)); + ImageCtx *image_ctx; CephContext *cct; + PerfCounters *perfcounter; std::string snap_name; uint64_t snap_id; @@ -178,6 +189,7 @@ struct MockImageCtx { std::map snap_ids; ObjectCacher *object_cacher; + ObjectCacher::ObjectSet *object_set; bool old_format; bool read_only; @@ -209,6 +221,7 @@ struct MockImageCtx { std::string id; std::string name; parent_info parent_md; + char *format_string; file_layout_t layout; @@ -221,6 +234,7 @@ struct MockImageCtx { MockContextWQ *op_work_queue; MockReadahead readahead; + uint64_t readahead_max_bytes; MockImageCtx *parent; MockOperations *operations; diff --git a/src/test/librbd/mock/MockJournal.h b/src/test/librbd/mock/MockJournal.h index 18f14218190e1..d0e718b24aed5 100644 --- a/src/test/librbd/mock/MockJournal.h +++ b/src/test/librbd/mock/MockJournal.h @@ -7,10 +7,15 @@ #include "gmock/gmock.h" #include "librbd/Journal.h" #include "librbd/journal/Types.h" +#include namespace librbd { +struct AioObjectRequest; + struct MockJournal { + typedef std::list AioObjectRequests; + static MockJournal *s_instance; static MockJournal *get_instance() { assert(s_instance != nullptr); @@ -48,6 +53,21 @@ struct MockJournal { MOCK_METHOD0(allocate_op_tid, uint64_t()); + MOCK_METHOD5(append_write_event, uint64_t(uint64_t, size_t, + const bufferlist &, + const AioObjectRequests &, bool)); + MOCK_METHOD5(append_io_event_mock, uint64_t(const journal::EventEntry&, + const AioObjectRequests &, + uint64_t, size_t, bool)); + uint64_t append_io_event(journal::EventEntry &&event_entry, + const AioObjectRequests &requests, + uint64_t offset, size_t length, + bool flush_entry) { + // googlemock doesn't support move semantics + return append_io_event_mock(event_entry, requests, offset, length, + flush_entry); + } + MOCK_METHOD3(append_op_event_mock, void(uint64_t, const journal::EventEntry&, Context *)); void append_op_event(uint64_t op_tid, journal::EventEntry &&event_entry, @@ -56,6 +76,9 @@ struct MockJournal { append_op_event_mock(op_tid, event_entry, on_safe); } + MOCK_METHOD2(flush_event, void(uint64_t, Context *)); + MOCK_METHOD2(wait_event, void(uint64_t, Context *)); + MOCK_METHOD3(commit_op_event, void(uint64_t, int, Context *)); MOCK_METHOD2(replay_op_ready, void(uint64_t, Context *));