]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: add CompareAndWrite ObjectRequest
authorwangzhengyong <wangzhengyong@cmss.chinamobile.com>
Fri, 2 Jun 2017 07:41:23 +0000 (15:41 +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/io/ObjectRequest.cc
src/librbd/io/ObjectRequest.h

index 6e16d8024035583c415865389771ab02ad719814..0b2415cf42e8a2f443e9d1f3e42d1bbaaf7c3feb 100644 (file)
@@ -9,6 +9,7 @@
 #include "common/RWLock.h"
 #include "common/WorkQueue.h"
 #include "include/Context.h"
+#include "include/err.h"
 
 #include "librbd/ExclusiveLock.h"
 #include "librbd/ImageCtx.h"
@@ -92,6 +93,23 @@ ObjectRequest<I>::create_writesame(I *ictx, const std::string &oid,
                                     op_flags, parent_trace, completion);
 }
 
+template <typename I>
+ObjectRequest<I>*
+ObjectRequest<I>::create_compare_and_write(I *ictx, const std::string &oid,
+                                           uint64_t object_no, uint64_t object_off,
+                                           const ceph::bufferlist &cmp_data,
+                                           const ceph::bufferlist &write_data,
+                                           const ::SnapContext &snapc,
+                                           uint64_t *mismatch_offset,
+                                           int op_flags,
+                                           const ZTracer::Trace &parent_trace,
+                                           Context *completion) {
+  return new ObjectCompareAndWriteRequest(util::get_image_ctx(ictx), oid,
+                                          object_no, object_off, cmp_data,
+                                          write_data, snapc, mismatch_offset,
+                                          op_flags, parent_trace, completion);
+}
+
 template <typename I>
 ObjectRequest<I>::ObjectRequest(ImageCtx *ictx, const std::string &oid,
                                 uint64_t objectno, uint64_t off,
@@ -692,6 +710,72 @@ void ObjectWriteSameRequest::send_write() {
   AbstractObjectWriteRequest::send_write();
 }
 
+void ObjectCompareAndWriteRequest::add_write_ops(librados::ObjectWriteOperation *wr,
+                                                 bool set_hints) {
+  RWLock::RLocker snap_locker(m_ictx->snap_lock);
+
+  if (set_hints && m_ictx->enable_alloc_hint &&
+      (m_ictx->object_map == nullptr || !m_object_exist)) {
+    wr->set_alloc_hint(m_ictx->get_object_size(), m_ictx->get_object_size());
+  }
+
+  // add cmpext ops
+  wr->cmpext(m_object_off, m_cmp_bl, nullptr);
+
+  if (m_object_off == 0 && m_object_len == m_ictx->get_object_size()) {
+    wr->write_full(m_write_bl);
+  } else {
+    wr->write(m_object_off, m_write_bl);
+  }
+  wr->set_op_flags2(m_op_flags);
+}
+
+void ObjectCompareAndWriteRequest::send_write() {
+  bool write_full = (m_object_off == 0 &&
+                     m_object_len == m_ictx->get_object_size());
+  ldout(m_ictx->cct, 20) << "send_write " << this << " " << m_oid << " "
+                         << m_object_off << "~" << m_object_len
+                         << " object exist " << m_object_exist
+                         << " write_full " << write_full << dendl;
+  if (write_full && !has_parent()) {
+    m_guard = false;
+  }
+
+  AbstractObjectWriteRequest::send_write();
+}
+
+void ObjectCompareAndWriteRequest::complete(int r)
+{
+  if (should_complete(r)) {
+    ImageCtx *image_ctx = this->m_ictx;
+    ldout(m_ictx->cct, 20) << "complete " << this << dendl;
+
+    if (this->m_hide_enoent && r == -ENOENT) {
+      r = 0;
+    }
+
+    vector<pair<uint64_t,uint64_t> > file_extents;
+    if (r <= -MAX_ERRNO) {
+      // object extent compare mismatch
+      uint64_t offset = -MAX_ERRNO - r;
+      Striper::extent_to_file(image_ctx->cct, &image_ctx->layout,
+                              this->m_object_no, offset, this->m_object_len,
+                              file_extents);
+
+      assert(file_extents.size() == 1);
+
+      uint64_t mismatch_offset = file_extents[0].first;
+      if (this->m_mismatch_offset)
+        *this->m_mismatch_offset = mismatch_offset;
+      r = -EILSEQ;
+    }
+
+    //compare and write object extent error
+    m_completion->complete(r);
+    delete this;
+  }
+}
+
 } // namespace io
 } // namespace librbd
 
index a236778c68fd6e8be9aa763874780e4ab0f0de65..e1ec6dc61cbe0d85544cdacc013e5b6c2556e58b 100644 (file)
@@ -81,6 +81,16 @@ public:
                                         int op_flags,
                                         const ZTracer::Trace &parent_trace,
                                          Context *completion);
+  static ObjectRequest* create_compare_and_write(ImageCtxT *ictx,
+                                                 const std::string &oid,
+                                                 uint64_t object_no,
+                                                 uint64_t object_off,
+                                                 const ceph::bufferlist &cmp_data,
+                                                 const ceph::bufferlist &write_data,
+                                                 const ::SnapContext &snapc,
+                                                 uint64_t *mismatch_offset, int op_flags,
+                                                 const ZTracer::Trace &parent_trace,
+                                                 Context *completion);
 
   ObjectRequest(ImageCtx *ictx, const std::string &oid,
                 uint64_t objectno, uint64_t off, uint64_t len,
@@ -95,7 +105,7 @@ public:
                               bool set_hints) {
   };
 
-  void complete(int r) override;
+  virtual void complete(int r);
 
   virtual bool should_complete(int r) = 0;
   void send() override = 0;
@@ -521,6 +531,48 @@ private:
   int m_op_flags;
 };
 
+class ObjectCompareAndWriteRequest : public AbstractObjectWriteRequest {
+public:
+  typedef std::vector<std::pair<uint64_t, uint64_t> > Extents;
+
+  ObjectCompareAndWriteRequest(ImageCtx *ictx, const std::string &oid,
+                               uint64_t object_no, uint64_t object_off,
+                               const ceph::bufferlist &cmp_bl,
+                               const ceph::bufferlist &write_bl,
+                               const ::SnapContext &snapc,
+                               uint64_t *mismatch_offset, int op_flags,
+                               const ZTracer::Trace &parent_trace,
+                               Context *completion)
+   : AbstractObjectWriteRequest(ictx, oid, object_no, object_off,
+                                cmp_bl.length(), snapc, false, "compare_and_write",
+                                parent_trace, completion),
+    m_cmp_bl(cmp_bl), m_write_bl(write_bl),
+    m_mismatch_offset(mismatch_offset), m_op_flags(op_flags) {
+  }
+
+  const char *get_op_type() const override {
+    return "compare_and_write";
+  }
+
+  bool pre_object_map_update(uint8_t *new_state) override {
+    *new_state = OBJECT_EXISTS;
+    return true;
+  }
+
+  void complete(int r) override;
+protected:
+  void add_write_ops(librados::ObjectWriteOperation *wr,
+                     bool set_hints) override;
+
+  void send_write() override;
+
+private:
+  ceph::bufferlist m_cmp_bl;
+  ceph::bufferlist m_write_bl;
+  uint64_t *m_mismatch_offset;
+  int m_op_flags;
+};
+
 } // namespace io
 } // namespace librbd