From: wangzhengyong Date: Fri, 2 Jun 2017 07:41:23 +0000 (+0800) Subject: librbd: add CompareAndWrite ObjectRequest X-Git-Tag: v12.1.2~106^2~12 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=cd61316857099e594d67a366a34ee6d8f6f7785b;p=ceph.git librbd: add CompareAndWrite ObjectRequest Signed-off-by: Zhengyong Wang --- diff --git a/src/librbd/io/ObjectRequest.cc b/src/librbd/io/ObjectRequest.cc index 6e16d8024035..0b2415cf42e8 100644 --- a/src/librbd/io/ObjectRequest.cc +++ b/src/librbd/io/ObjectRequest.cc @@ -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::create_writesame(I *ictx, const std::string &oid, op_flags, parent_trace, completion); } +template +ObjectRequest* +ObjectRequest::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 ObjectRequest::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 > 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 diff --git a/src/librbd/io/ObjectRequest.h b/src/librbd/io/ObjectRequest.h index a236778c68fd..e1ec6dc61cbe 100644 --- a/src/librbd/io/ObjectRequest.h +++ b/src/librbd/io/ObjectRequest.h @@ -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 > 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