]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: add writesame AioImageRequest
authorGui Hecheng <guihecheng@cmss.chinamobile.com>
Wed, 22 Feb 2017 09:16:55 +0000 (17:16 +0800)
committerGui Hecheng <guihecheng@cmss.chinamobile.com>
Thu, 23 Feb 2017 09:25:14 +0000 (17:25 +0800)
Based on pr: https://github.com/ceph/ceph/pull/10019.

Signed-off-by: Gui Hecheng <guihecheng@cmss.chinamobile.com>
Signed-off-by: Mingxin Liu <mingxin@xsky.com>
src/librbd/cache/ImageCache.h
src/librbd/cache/ImageWriteback.cc
src/librbd/cache/ImageWriteback.h
src/librbd/cache/PassthroughImageCache.cc
src/librbd/cache/PassthroughImageCache.h
src/librbd/io/ImageRequest.cc
src/librbd/io/ImageRequest.h

index 859993b0ff993d71ff2c38937ed84ecd7b069ea1..02a6467aa60ea640b6e16e5723d22f22d02408c3 100644 (file)
@@ -30,6 +30,9 @@ struct ImageCache {
   virtual void aio_discard(uint64_t offset, uint64_t length,
                            Context *on_finish) = 0;
   virtual void aio_flush(Context *on_finish) = 0;
+  virtual void aio_writesame(uint64_t offset, uint64_t length,
+                             ceph::bufferlist&& bl,
+                             int fadvise_flags, Context *on_finish) = 0;
 
   /// internal state methods
   virtual void init(Context *on_finish) = 0;
index 6867eec255297afa9a5b39637627841461ce978d..69b28c3d27481311d1de13b51d31387c990cc43c 100644 (file)
@@ -78,6 +78,24 @@ void ImageWriteback<I>::aio_flush(Context *on_finish) {
   req.send();
 }
 
+template <typename I>
+void ImageWriteback<I>::aio_writesame(uint64_t offset, uint64_t length,
+                                      ceph::bufferlist&& bl,
+                                      int fadvise_flags, Context *on_finish) {
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 20) << "offset=" << offset << ", "
+                 << "length=" << length << ", "
+                 << "data_len=" << bl.length() << ", "
+                 << "on_finish=" << on_finish << dendl;
+
+  auto aio_comp = io::AioCompletion::create_and_start(on_finish, &m_image_ctx,
+                                                      io::AIO_TYPE_WRITESAME);
+  io::ImageWriteSameRequest<I> req(m_image_ctx, aio_comp, offset, length,
+                                   std::move(bl), fadvise_flags);
+  req.set_bypass_image_cache();
+  req.send();
+}
+
 } // namespace cache
 } // namespace librbd
 
index c3737800ecbf06d2392b33431bd40a8dbaaabb39..29ea713baa880fdb67e8cd480fa0e76b368dd826 100644 (file)
@@ -32,6 +32,9 @@ public:
                  int fadvise_flags, Context *on_finish);
   void aio_discard(uint64_t offset, uint64_t length, Context *on_finish);
   void aio_flush(Context *on_finish);
+  void aio_writesame(uint64_t offset, uint64_t length,
+                     ceph::bufferlist&& bl,
+                     int fadvise_flags, Context *on_finish);
 
 private:
   ImageCtxT &m_image_ctx;
index 0ad2f4ef87790de3b2ced069d852d139ca4ad755..62f81aca329849f432ac3ab0906cabec160999f9 100644 (file)
@@ -62,6 +62,20 @@ void PassthroughImageCache<I>::aio_flush(Context *on_finish) {
   m_image_writeback.aio_flush(on_finish);
 }
 
+template <typename I>
+void PassthroughImageCache<I>::aio_writesame(uint64_t offset, uint64_t length,
+                                             bufferlist&& bl, int fadvise_flags,
+                                             Context *on_finish) {
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 20) << "offset=" << offset << ", "
+                 << "length=" << length << ", "
+                 << "data_len=" << bl.length() << ", "
+                 << "on_finish=" << on_finish << dendl;
+
+  m_image_writeback.aio_writesame(offset, length, std::move(bl), fadvise_flags,
+                                  on_finish);
+}
+
 template <typename I>
 void PassthroughImageCache<I>::init(Context *on_finish) {
   CephContext *cct = m_image_ctx.cct;
index 9e451d1a7af10cf47a49756d40b6877b8ae92e6e..2abea0efb77708b12f08819513dee1392445ccbf 100644 (file)
@@ -29,6 +29,9 @@ public:
   void aio_discard(uint64_t offset, uint64_t length,
                    Context *on_finish) override;
   void aio_flush(Context *on_finish) override;
+  virtual void aio_writesame(uint64_t offset, uint64_t length,
+                             ceph::bufferlist&& bl,
+                             int fadvise_flags, Context *on_finish);
 
   /// internal state methods
   void init(Context *on_finish) override;
index e2b873d067318f15fdc11de515e63db0de069789..44b6ea1813b538a591437d41a2106a5defaa3ae7 100644 (file)
@@ -141,6 +141,15 @@ void ImageRequest<I>::aio_flush(I *ictx, AioCompletion *c) {
   req.send();
 }
 
+template <typename I>
+void ImageRequest<I>::aio_writesame(I *ictx, AioCompletion *c,
+                                    uint64_t off, uint64_t len,
+                                    bufferlist &&bl,
+                                    int op_flags) {
+  ImageWriteSameRequest<I> req(*ictx, c, off, len, std::move(bl), op_flags);
+  req.send();
+}
+
 template <typename I>
 void ImageRequest<I>::send() {
   I &image_ctx = this->m_image_ctx;
@@ -654,6 +663,151 @@ void ImageFlushRequest<I>::send_image_cache_request() {
   image_ctx.image_cache->aio_flush(req_comp);
 }
 
+template <typename I>
+bool ImageWriteSameRequest<I>::assemble_writesame_extent(const ObjectExtent &object_extent,
+                                                         bufferlist *bl, bool force_write) {
+  size_t m_data_len = m_data_bl.length();
+
+  if (!force_write) {
+    bool may_writesame = true;
+
+    for (auto q = object_extent.buffer_extents.begin();
+         q != object_extent.buffer_extents.end(); ++q) {
+      if (!(q->first % m_data_len == 0 && q->second % m_data_len == 0)) {
+        may_writesame = false;
+        break;
+      }
+    }
+
+    if (may_writesame) {
+      bl->append(m_data_bl);
+      return true;
+    }
+  }
+
+  for (auto q = object_extent.buffer_extents.begin();
+       q != object_extent.buffer_extents.end(); ++q) {
+    bufferlist sub_bl;
+    uint64_t sub_off = q->first % m_data_len;
+    uint64_t sub_len = m_data_len - sub_off;
+    uint64_t extent_left = q->second;
+    while (extent_left >= sub_len) {
+      sub_bl.substr_of(m_data_bl, sub_off, sub_len);
+      bl->claim_append(sub_bl);
+      extent_left -= sub_len;
+      if (sub_off) {
+       sub_off = 0;
+       sub_len = m_data_len;
+      }
+    }
+    if (extent_left) {
+      sub_bl.substr_of(m_data_bl, sub_off, extent_left);
+      bl->claim_append(sub_bl);
+    }
+  }
+  return false;
+}
+
+template <typename I>
+uint64_t ImageWriteSameRequest<I>::append_journal_event(
+    const ObjectRequests &requests, bool synchronous) {
+  I &image_ctx = this->m_image_ctx;
+
+  uint64_t tid = 0;
+  assert(!this->m_image_extents.empty());
+  for (auto &extent : this->m_image_extents) {
+    journal::EventEntry event_entry(journal::AioWriteSameEvent(extent.first,
+                                                               extent.second,
+                                                               m_data_bl));
+    tid = image_ctx.journal->append_io_event(std::move(event_entry),
+                                             requests, extent.first,
+                                             extent.second, synchronous);
+  }
+
+  if (image_ctx.object_cacher == NULL) {
+    AioCompletion *aio_comp = this->m_aio_comp;
+    aio_comp->associate_journal_event(tid);
+  }
+  return tid;
+}
+
+template <typename I>
+void ImageWriteSameRequest<I>::send_image_cache_request() {
+  I &image_ctx = this->m_image_ctx;
+  assert(image_ctx.image_cache != nullptr);
+
+  AioCompletion *aio_comp = this->m_aio_comp;
+  aio_comp->set_request_count(this->m_image_extents.size());
+  for (auto &extent : this->m_image_extents) {
+    C_AioRequest *req_comp = new C_AioRequest(aio_comp);
+    image_ctx.image_cache->aio_writesame(extent.first, extent.second,
+                                         std::move(m_data_bl), m_op_flags,
+                                         req_comp);
+  }
+}
+
+template <typename I>
+void ImageWriteSameRequest<I>::send_object_cache_requests(
+    const ObjectExtents &object_extents, uint64_t journal_tid) {
+  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_writesame_extent(object_extent, &bl, true);
+
+    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);
+  }
+}
+
+template <typename I>
+void ImageWriteSameRequest<I>::send_object_requests(
+    const ObjectExtents &object_extents, const ::SnapContext &snapc,
+    ObjectRequests *object_requests) {
+  I &image_ctx = this->m_image_ctx;
+
+  // cache handles creating object requests during writeback
+  if (image_ctx.object_cacher == NULL) {
+    AbstractImageWriteRequest<I>::send_object_requests(object_extents, snapc,
+                                                       object_requests);
+  }
+}
+
+template <typename I>
+ObjectRequestHandle *ImageWriteSameRequest<I>::create_object_request(
+    const ObjectExtent &object_extent, const ::SnapContext &snapc,
+    Context *on_finish) {
+  I &image_ctx = this->m_image_ctx;
+  assert(image_ctx.object_cacher == NULL);
+
+  bufferlist bl;
+  ObjectRequest<I> *req;
+
+  if (assemble_writesame_extent(object_extent, &bl, false)) {
+    req = ObjectRequest<I>::create_writesame(
+      &image_ctx, object_extent.oid.name, object_extent.objectno,
+      object_extent.offset, object_extent.length,
+      bl, snapc, on_finish, m_op_flags);
+    return req;
+  }
+  req = ObjectRequest<I>::create_write(
+    &image_ctx, object_extent.oid.name, object_extent.objectno,
+    object_extent.offset,
+    bl, snapc, on_finish, m_op_flags);
+  return req;
+}
+
+template <typename I>
+void ImageWriteSameRequest<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);
+}
+
 } // namespace io
 } // namespace librbd
 
@@ -663,3 +817,4 @@ template class librbd::io::AbstractImageWriteRequest<librbd::ImageCtx>;
 template class librbd::io::ImageWriteRequest<librbd::ImageCtx>;
 template class librbd::io::ImageDiscardRequest<librbd::ImageCtx>;
 template class librbd::io::ImageFlushRequest<librbd::ImageCtx>;
+template class librbd::io::ImageWriteSameRequest<librbd::ImageCtx>;
index 0bdca22e63b25a743234e7f482b643d49481e325..4c8ae76f5bb49834a9bd4873718c67ff1a777acf 100644 (file)
@@ -37,6 +37,8 @@ public:
   static void aio_discard(ImageCtxT *ictx, AioCompletion *c, uint64_t off,
                           uint64_t len);
   static void aio_flush(ImageCtxT *ictx, AioCompletion *c);
+  static void aio_writesame(ImageCtxT *ictx, AioCompletion *c, uint64_t off,
+                            uint64_t len, bufferlist &&bl, int op_flags);
 
   virtual bool is_write_op() const {
     return false;
@@ -257,6 +259,50 @@ protected:
   }
 };
 
+template <typename ImageCtxT = ImageCtx>
+class ImageWriteSameRequest : public AbstractImageWriteRequest<ImageCtxT> {
+public:
+  ImageWriteSameRequest(ImageCtxT &image_ctx, AioCompletion *aio_comp,
+                        uint64_t off, uint64_t len, bufferlist &&bl,
+                        int op_flags)
+    : AbstractImageWriteRequest<ImageCtxT>(image_ctx, aio_comp, {{off, len}}),
+      m_data_bl(std::move(bl)), m_op_flags(op_flags) {
+  }
+
+protected:
+  using typename ImageRequest<ImageCtxT>::ObjectRequests;
+  using typename AbstractImageWriteRequest<ImageCtxT>::ObjectExtents;
+
+  virtual aio_type_t get_aio_type() const {
+    return AIO_TYPE_WRITESAME;
+  }
+  virtual const char *get_request_type() const {
+    return "aio_writesame";
+  }
+
+  bool assemble_writesame_extent(const ObjectExtent &object_extent,
+                                 bufferlist *bl, bool force_write);
+
+  virtual void send_image_cache_request() override;
+
+  virtual void send_object_cache_requests(const ObjectExtents &object_extents,
+                                          uint64_t journal_tid);
+
+  virtual void send_object_requests(const ObjectExtents &object_extents,
+                                    const ::SnapContext &snapc,
+                                    ObjectRequests *object_requests);
+  virtual ObjectRequestHandle *create_object_request(
+      const ObjectExtent &object_extent, const ::SnapContext &snapc,
+      Context *on_finish);
+
+  virtual uint64_t append_journal_event(const ObjectRequests &requests,
+                                        bool synchronous);
+  virtual void update_stats(size_t length);
+private:
+  bufferlist m_data_bl;
+  int m_op_flags;
+};
+
 } // namespace io
 } // namespace librbd
 
@@ -266,5 +312,6 @@ extern template class librbd::io::AbstractImageWriteRequest<librbd::ImageCtx>;
 extern template class librbd::io::ImageWriteRequest<librbd::ImageCtx>;
 extern template class librbd::io::ImageDiscardRequest<librbd::ImageCtx>;
 extern template class librbd::io::ImageFlushRequest<librbd::ImageCtx>;
+extern template class librbd::io::ImageWriteSameRequest<librbd::ImageCtx>;
 
 #endif // CEPH_LIBRBD_IO_IMAGE_REQUEST_H