]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: add compare_and_write ImageRequest
authorwangzhengyong <wangzhengyong@cmss.chinamobile.com>
Mon, 12 Jun 2017 13:14:19 +0000 (21:14 +0800)
committerJason Dillaman <dillaman@redhat.com>
Wed, 26 Jul 2017 12:00:05 +0000 (08:00 -0400)
Signed-off-by: Zhengyong Wang <wangzhengyong@cmss.chinamobile.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 0a5d0263ee33e52b4a227423ef8f44fc3a694835..f394a1a80a1e8a91a3b3c612508da2556062af3f 100644 (file)
@@ -33,6 +33,12 @@ struct ImageCache {
   virtual void aio_writesame(uint64_t offset, uint64_t length,
                              ceph::bufferlist&& bl,
                              int fadvise_flags, Context *on_finish) = 0;
+  virtual void aio_compare_and_write(Extents&& image_extents,
+                                     ceph::bufferlist&& cmp_bl,
+                                     ceph::bufferlist&& bl,
+                                     uint64_t *mismatch_offset,
+                                     int fadvise_flags,
+                                     Context *on_finish) = 0;
 
   /// internal state methods
   virtual void init(Context *on_finish) = 0;
index cff7a531db2982c2142a4d9f26bfc9cff65740b8..d5c9c759c850614b77544bf0b1211eb91ba68629 100644 (file)
@@ -98,6 +98,27 @@ void ImageWriteback<I>::aio_writesame(uint64_t offset, uint64_t length,
   req.send();
 }
 
+template <typename I>
+void ImageWriteback<I>::aio_compare_and_write(Extents &&image_extents,
+                                              ceph::bufferlist&& cmp_bl,
+                                              ceph::bufferlist&& bl,
+                                              uint64_t *mismatch_offset,
+                                              int fadvise_flags,
+                                              Context *on_finish) {
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 20) << "image_extents=" << image_extents << ", "
+                 << "on_finish=" << on_finish << dendl;
+
+  auto aio_comp = io::AioCompletion::create_and_start(on_finish, &m_image_ctx,
+                                                      io::AIO_TYPE_COMPARE_AND_WRITE);
+  io::ImageCompareAndWriteRequest<I> req(m_image_ctx, aio_comp,
+                                         std::move(image_extents),
+                                         std::move(cmp_bl), std::move(bl),
+                                         mismatch_offset, fadvise_flags, {});
+  req.set_bypass_image_cache();
+  req.send();
+}
+
 } // namespace cache
 } // namespace librbd
 
index 1ffc450dfbbbd2d74b668129d06298c41faec85c..9bc9b5e6d26d9c6794c99646466c3e064d70c698 100644 (file)
@@ -36,7 +36,11 @@ public:
   void aio_writesame(uint64_t offset, uint64_t length,
                      ceph::bufferlist&& bl,
                      int fadvise_flags, Context *on_finish);
-
+  void aio_compare_and_write(Extents &&image_extents,
+                             ceph::bufferlist&& cmp_bl,
+                             ceph::bufferlist&& bl,
+                             uint64_t *mismatch_offset,
+                             int fadvise_flags, Context *on_finish);
 private:
   ImageCtxT &m_image_ctx;
 
index f892387acc8922931df844f6e9d215482477e28c..5b22fc7a6ced33b3075e4669ff2d1bc6ab0db4a1 100644 (file)
@@ -76,6 +76,22 @@ void PassthroughImageCache<I>::aio_writesame(uint64_t offset, uint64_t length,
                                   on_finish);
 }
 
+template <typename I>
+void PassthroughImageCache<I>::aio_compare_and_write(Extents &&image_extents,
+                                                     bufferlist&& cmp_bl,
+                                                     bufferlist&& bl,
+                                                     uint64_t *mismatch_offset,
+                                                     int fadvise_flags,
+                                                     Context *on_finish) {
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 20) << "image_extents=" << image_extents << ", "
+                 << "on_finish=" << on_finish << dendl;
+
+  m_image_writeback.aio_compare_and_write(
+    std::move(image_extents), std::move(cmp_bl), std::move(bl), mismatch_offset,
+    fadvise_flags, on_finish);
+}
+
 template <typename I>
 void PassthroughImageCache<I>::init(Context *on_finish) {
   CephContext *cct = m_image_ctx.cct;
index 089430c7b5b8bbd5aaedac8a88e31302ea010dfe..2dbe94dbe79beb2cacff78b029faedd67d8ebd63 100644 (file)
@@ -32,6 +32,10 @@ public:
   void aio_writesame(uint64_t offset, uint64_t length,
                      ceph::bufferlist&& bl,
                      int fadvise_flags, Context *on_finish) override;
+  void aio_compare_and_write(Extents&& image_extents,
+                             ceph::bufferlist&& cmp_bl, ceph::bufferlist&& bl,
+                             uint64_t *mismatch_offset,int fadvise_flags,
+                             Context *on_finish) override;
 
   /// internal state methods
   void init(Context *on_finish) override;
index 8afd6556a32c8bba0c3251b931a00a66a4c2fc6c..86ea5536adddd21e7f85c5cd2adb5c2440e4a2b3 100644 (file)
@@ -197,6 +197,21 @@ void ImageRequest<I>::aio_writesame(I *ictx, AioCompletion *c,
   req.send();
 }
 
+template <typename I>
+void ImageRequest<I>::aio_compare_and_write(I *ictx, AioCompletion *c,
+                                            Extents &&image_extents,
+                                            bufferlist &&cmp_bl,
+                                            bufferlist &&bl,
+                                            uint64_t *mismatch_offset,
+                                            int op_flags,
+                                            const ZTracer::Trace &parent_trace) {
+  ImageCompareAndWriteRequest<I> req(*ictx, c, std::move(image_extents),
+                                     std::move(cmp_bl), std::move(bl),
+                                     mismatch_offset, op_flags, parent_trace);
+  req.send();
+}
+
+
 template <typename I>
 void ImageRequest<I>::send() {
   I &image_ctx = this->m_image_ctx;
@@ -206,7 +221,7 @@ void ImageRequest<I>::send() {
   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;
+                 << "completion=" << aio_comp << dendl;
 
   aio_comp->get();
   int r = clip_request();
@@ -404,7 +419,11 @@ void AbstractImageWriteRequest<I>::send_request() {
                   image_ctx.journal->is_journal_appending());
   }
 
-  prune_object_extents(object_extents);
+  int ret = prune_object_extents(object_extents);
+  if (ret < 0) {
+    aio_comp->fail(ret);
+    return;
+  }
 
   if (!object_extents.empty()) {
     uint64_t journal_tid = 0;
@@ -583,11 +602,11 @@ uint64_t ImageDiscardRequest<I>::append_journal_event(
 }
 
 template <typename I>
-void ImageDiscardRequest<I>::prune_object_extents(ObjectExtents &object_extents) {
+int ImageDiscardRequest<I>::prune_object_extents(ObjectExtents &object_extents) {
   I &image_ctx = this->m_image_ctx;
   CephContext *cct = image_ctx.cct;
   if (!this->m_skip_partial_discard) {
-    return;
+    return 0;
   }
 
   for (auto p = object_extents.begin(); p != object_extents.end(); ) {
@@ -600,6 +619,8 @@ void ImageDiscardRequest<I>::prune_object_extents(ObjectExtents &object_extents)
       ++p;
     }
   }
+
+  return 0;
 }
 
 template <typename I>
@@ -876,6 +897,104 @@ void ImageWriteSameRequest<I>::update_stats(size_t length) {
   image_ctx.perfcounter->inc(l_librbd_ws_bytes, length);
 }
 
+template <typename I>
+uint64_t ImageCompareAndWriteRequest<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.size() == 1);
+  auto &extent = this->m_image_extents.front();
+  journal::EventEntry event_entry(journal::AioCompareAndWriteEvent(extent.first,
+                                                                   extent.second,
+                                                                   m_cmp_bl, m_bl));
+  tid = image_ctx.journal->append_io_event(std::move(event_entry),
+                                           requests, extent.first,
+                                           extent.second, synchronous);
+
+  AioCompletion *aio_comp = this->m_aio_comp;
+  aio_comp->associate_journal_event(tid);
+
+  return tid;
+}
+
+template <typename I>
+void ImageCompareAndWriteRequest<I>::send_object_cache_requests(
+  const ObjectExtents &object_extents, uint64_t journal_tid) {
+  I &image_ctx = this->m_image_ctx;
+
+  if (image_ctx.object_cacher != NULL) {
+    Mutex::Locker cache_locker(image_ctx.cache_lock);
+    image_ctx.object_cacher->discard_set(image_ctx.object_set,
+                                         object_extents);
+  }
+}
+
+template <typename I>
+void ImageCompareAndWriteRequest<I>::assemble_extent(
+  const ObjectExtent &object_extent, bufferlist *bl) {
+  for (auto q = object_extent.buffer_extents.begin();
+       q != object_extent.buffer_extents.end(); ++q) {
+    bufferlist sub_bl;
+    sub_bl.substr_of(m_bl, q->first, q->second);
+    bl->claim_append(sub_bl);
+  }
+}
+
+template <typename I>
+void ImageCompareAndWriteRequest<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(1);
+  C_AioRequest *req_comp = new C_AioRequest(aio_comp);
+  image_ctx.image_cache->aio_compare_and_write(
+    std::move(this->m_image_extents), std::move(m_cmp_bl), std::move(m_bl),
+    m_mismatch_offset, m_op_flags, req_comp);
+}
+
+template <typename I>
+ObjectRequestHandle *ImageCompareAndWriteRequest<I>::create_object_request(
+    const ObjectExtent &object_extent,
+    const ::SnapContext &snapc,
+    Context *on_finish) {
+  I &image_ctx = this->m_image_ctx;
+
+  bufferlist bl;
+  assemble_extent(object_extent, &bl);
+  ObjectRequest<I> *req = ObjectRequest<I>::create_compare_and_write(
+                                  &image_ctx, object_extent.oid.name,
+                                  object_extent.objectno, object_extent.offset,
+                                  m_cmp_bl, bl, snapc, m_mismatch_offset,
+                                  m_op_flags, this->m_trace, on_finish);
+  return req;
+}
+
+template <typename I>
+void ImageCompareAndWriteRequest<I>::update_stats(size_t length) {
+  I &image_ctx = this->m_image_ctx;
+  image_ctx.perfcounter->inc(l_librbd_cmp);
+  image_ctx.perfcounter->inc(l_librbd_cmp_bytes, length);
+}
+
+template <typename I>
+int ImageCompareAndWriteRequest<I>::prune_object_extents(ObjectExtents &object_extents) {
+  if (object_extents.size() > 1)
+    return -EINVAL;
+
+  I &image_ctx = this->m_image_ctx;
+  uint64_t sector_size = 512ULL;
+  uint64_t su = image_ctx.layout.stripe_unit;
+  ObjectExtent object_extent = object_extents.front();
+  if (object_extent.offset % sector_size + object_extent.length > sector_size ||
+      (su != 0 && (object_extent.offset % su + object_extent.length > su)))
+    return -EINVAL;
+
+  return 0;
+}
+
 } // namespace io
 } // namespace librbd
 
@@ -886,3 +1005,4 @@ 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>;
+template class librbd::io::ImageCompareAndWriteRequest<librbd::ImageCtx>;
index de19f490c6f282abe17185d2d6d884d43a51b16e..93538f6e3e7239ac8e7d01710ef679c711edd008 100644 (file)
@@ -73,6 +73,11 @@ public:
                             uint64_t len, bufferlist &&bl, int op_flags,
                            const ZTracer::Trace &parent_trace);
 
+  static void aio_compare_and_write(ImageCtxT *ictx, AioCompletion *c,
+                                    Extents &&image_extents, bufferlist &&cmp_bl,
+                                    bufferlist &&bl, uint64_t *mismatch_offset,
+                                    int op_flags, const ZTracer::Trace &parent_trace);
+
   virtual bool is_write_op() const {
     return false;
   }
@@ -171,7 +176,8 @@ protected:
 
   void send_request() override;
 
-  virtual void prune_object_extents(ObjectExtents &object_extents) {
+  virtual int prune_object_extents(ObjectExtents &object_extents) {
+    return 0;
   }
   virtual uint32_t get_object_cache_request_count(bool journaling) const {
     return 0;
@@ -264,7 +270,7 @@ protected:
     return "aio_discard";
   }
 
-  void prune_object_extents(ObjectExtents &object_extents) override;
+  int prune_object_extents(ObjectExtents &object_extents) override;
 
   void send_image_cache_request() override;
 
@@ -357,6 +363,53 @@ private:
   int m_op_flags;
 };
 
+template <typename ImageCtxT = ImageCtx>
+class ImageCompareAndWriteRequest : public AbstractImageWriteRequest<ImageCtxT> {
+public:
+  using typename ImageRequest<ImageCtxT>::ObjectRequests;
+  using typename AbstractImageWriteRequest<ImageCtxT>::ObjectExtents;
+
+  ImageCompareAndWriteRequest(ImageCtxT &image_ctx, AioCompletion *aio_comp,
+                              Extents &&image_extents, bufferlist &&cmp_bl,
+                              bufferlist &&bl, uint64_t *mismatch_offset,
+                              int op_flags, const ZTracer::Trace &parent_trace)
+      : AbstractImageWriteRequest<ImageCtxT>(
+          image_ctx, aio_comp, std::move(image_extents), "compare_and_write", parent_trace),
+        m_cmp_bl(std::move(cmp_bl)), m_bl(std::move(bl)),
+        m_mismatch_offset(mismatch_offset), m_op_flags(op_flags) {
+  }
+
+protected:
+  void send_image_cache_request() override;
+
+  void send_object_cache_requests(const ObjectExtents &object_extents,
+                                  uint64_t journal_tid) override;
+
+  void assemble_extent(const ObjectExtent &object_extent, bufferlist *bl);
+
+  ObjectRequestHandle *create_object_request(const ObjectExtent &object_extent,
+                                             const ::SnapContext &snapc,
+                                             Context *on_finish) override;
+
+  uint64_t append_journal_event(const ObjectRequests &requests,
+                                bool synchronous) override;
+  void update_stats(size_t length) override;
+
+  aio_type_t get_aio_type() const override {
+    return AIO_TYPE_COMPARE_AND_WRITE;
+  }
+  const char *get_request_type() const override {
+    return "aio_compare_and_write";
+  }
+
+  int prune_object_extents(ObjectExtents &object_extents) override;
+private:
+  bufferlist m_cmp_bl;
+  bufferlist m_bl;
+  uint64_t *m_mismatch_offset;
+  int m_op_flags;
+};
+
 } // namespace io
 } // namespace librbd
 
@@ -367,5 +420,6 @@ 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>;
+extern template class librbd::io::ImageCompareAndWriteRequest<librbd::ImageCtx>;
 
 #endif // CEPH_LIBRBD_IO_IMAGE_REQUEST_H