]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: convert AioImageRequest derived classes to templates
authorJason Dillaman <dillaman@redhat.com>
Wed, 27 Jul 2016 03:26:08 +0000 (23:26 -0400)
committerMykola Golub <mgolub@mirantis.com>
Fri, 19 Aug 2016 19:59:07 +0000 (22:59 +0300)
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
(cherry picked from commit a945c2c235d9259b1d4a8a579d7e6efc2ed35916)

src/librbd/AioImageRequest.cc
src/librbd/AioImageRequest.h
src/librbd/AioImageRequestWQ.cc
src/librbd/Utils.h
src/test/librbd/mock/MockImageCtx.h
src/test/librbd/mock/MockJournal.h

index 807c7e0699a46ee99cfc0407e03692700d42b40c..f7fb0a5d04993466ad93d4a1a5f106175ebf9bc0 100644 (file)
@@ -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"
 
 namespace librbd {
 
+using util::get_image_ctx;
+
 namespace {
 
+template <typename ImageCtxT = ImageCtx>
 struct C_DiscardJournalCommit : public Context {
   typedef std::vector<ObjectExtent> 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 <typename ImageCtxT = ImageCtx>
 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<I>::aio_discard(I *ictx, AioCompletion *c,
 
 template <typename I>
 void AioImageRequest<I>::aio_flush(I *ictx, AioCompletion *c) {
-  assert(c->is_initialized(AIO_TYPE_FLUSH));
   AioImageFlush req(*ictx, c);
   req.send();
 }
 
 template <typename I>
 void AioImageRequest<I>::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 <typename I>
 void AioImageRequest<I>::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 <typename I>
+void AioImageRead<I>::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_t,vector<ObjectExtent> > 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<pair<uint64_t,uint64_t> >::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 <typename I>
+void AbstractAioImageWrite<I>::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 <typename I>
+void AbstractAioImageWrite<I>::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 <typename I>
+void AioImageWrite<I>::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 <typename I>
+uint64_t AioImageWrite<I>::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 <typename I>
+void AioImageWrite<I>::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 <typename I>
+void AioImageWrite<I>::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<I>::send_object_requests(object_extents, snapc,
                                                 aio_object_requests);
   }
 }
 
-AioObjectRequest *AioImageWrite::create_object_request(
+template <typename I>
+AioObjectRequest *AioImageWrite<I>::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 <typename I>
+void AioImageWrite<I>::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 <typename I>
+uint64_t AioImageDiscard<I>::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 <typename I>
+void AioImageDiscard<I>::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 <typename I>
+uint32_t AioImageDiscard<I>::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 <typename I>
+void AioImageDiscard<I>::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<I>(image_ctx, aio_comp,
+                                                 object_extents, journal_tid));
   }
 }
 
-AioObjectRequest *AioImageDiscard::create_object_request(
+template <typename I>
+AioObjectRequest *AioImageDiscard<I>::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 <typename I>
+void AioImageDiscard<I>::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 <typename I>
+void AioImageFlush<I>::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<I> *ctx = new C_FlushJournalCommit<I>(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<librbd::ImageCtx>;
+template class librbd::AbstractAioImageWrite<librbd::ImageCtx>;
+template class librbd::AioImageWrite<librbd::ImageCtx>;
+template class librbd::AioImageDiscard<librbd::ImageCtx>;
+template class librbd::AioImageFlush<librbd::ImageCtx>;
index b36c09b27132dc14a5645c2dbd30e184f8b604c6..f1605954089dedd0e67767e87ee7c3f1383d2e94 100644 (file)
@@ -62,20 +62,24 @@ protected:
   virtual const char *get_request_type() const = 0;
 };
 
-class AioImageRead : public AioImageRequest<> {
+template <typename ImageCtxT = ImageCtx>
+class AioImageRead : public AioImageRequest<ImageCtxT> {
 public:
-  AioImageRead(ImageCtx &image_ctx, AioCompletion *aio_comp, uint64_t off,
+  using typename AioImageRequest<ImageCtxT>::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<ImageCtxT>(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<ImageCtxT>(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 <typename ImageCtxT = ImageCtx>
+class AbstractAioImageWrite : public AioImageRequest<ImageCtxT> {
 public:
   virtual bool is_write_op() const {
     return true;
@@ -104,14 +109,16 @@ public:
   }
 
 protected:
+  using typename AioImageRequest<ImageCtxT>::AioObjectRequests;
+
   typedef std::vector<ObjectExtent> 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<ImageCtxT>(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 <typename ImageCtxT = ImageCtx>
+class AioImageWrite : public AbstractAioImageWrite<ImageCtxT> {
 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<ImageCtxT>(image_ctx, aio_comp, off, len),
+      m_buf(buf), m_op_flags(op_flags) {
   }
 
 protected:
+  using typename AioImageRequest<ImageCtxT>::AioObjectRequests;
+  using typename AbstractAioImageWrite<ImageCtxT>::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 <typename ImageCtxT = ImageCtx>
+class AioImageDiscard : public AbstractAioImageWrite<ImageCtxT> {
 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<ImageCtxT>(image_ctx, aio_comp, off, len) {
   }
 
 protected:
+  using typename AioImageRequest<ImageCtxT>::AioObjectRequests;
+  using typename AbstractAioImageWrite<ImageCtxT>::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 <typename ImageCtxT = ImageCtx>
+class AioImageFlush : public AioImageRequest<ImageCtxT> {
 public:
-  AioImageFlush(ImageCtx &image_ctx, AioCompletion *aio_comp)
-    : AioImageRequest(image_ctx, aio_comp) {
+  AioImageFlush(ImageCtxT &image_ctx, AioCompletion *aio_comp)
+    : AioImageRequest<ImageCtxT>(image_ctx, aio_comp) {
   }
 
   virtual bool is_write_op() const {
@@ -216,6 +232,8 @@ public:
   }
 
 protected:
+  using typename AioImageRequest<ImageCtxT>::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<librbd::ImageCtx>;
+extern template class librbd::AbstractAioImageWrite<librbd::ImageCtx>;
+extern template class librbd::AioImageWrite<librbd::ImageCtx>;
+extern template class librbd::AioImageDiscard<librbd::ImageCtx>;
+extern template class librbd::AioImageFlush<librbd::ImageCtx>;
 
 #endif // CEPH_LIBRBD_AIO_IMAGE_REQUEST_H
index 55889e8f250e1df78f1c90540698d6f2ecdc4f39..a3e8aac95deb8f619157a9fb973ebf8bb650367c 100644 (file)
@@ -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();
index 799bf0f8d3994c81079af1c3b653319bcb3ced1a..59040819e959559534aca9ca987e433f041229a6 100644 (file)
@@ -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;
 }
index b7b73c835fa6fc938c650fe4b819c5d11dd062b2..e43927a9e0ab10865448c2951d5a2c2594c0fd7c 100644 (file)
@@ -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<std::string, librados::snap_t> 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;
index 18f14218190e1661546443c2103fec8691051644..d0e718b24aed5143ee6511c48b9dd6762490d76f 100644 (file)
@@ -7,10 +7,15 @@
 #include "gmock/gmock.h"
 #include "librbd/Journal.h"
 #include "librbd/journal/Types.h"
+#include <list>
 
 namespace librbd {
 
+struct AioObjectRequest;
+
 struct MockJournal {
+  typedef std::list<AioObjectRequest *> 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 *));