From: Yuan Lu Date: Thu, 30 Apr 2020 06:10:19 +0000 (+0800) Subject: librbd: add CompAndWriteRequest X-Git-Tag: v17.0.0~2429^2~2 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=5d719ff919ef790a235808ed325a7e190e83205f;p=ceph.git librbd: add CompAndWriteRequest Signed-off-by: Peterson, Scott Signed-off-by: Li, Xiaoyan Signed-off-by: Lu, Yuan Signed-off-by: Chamarthy, Mahati --- diff --git a/src/librbd/cache/rwl/Request.cc b/src/librbd/cache/rwl/Request.cc index 8dc6f4c531df6..147fe0cce3d17 100644 --- a/src/librbd/cache/rwl/Request.cc +++ b/src/librbd/cache/rwl/Request.cc @@ -622,6 +622,54 @@ std::ostream &operator<<(std::ostream &os, return os; }; +template +C_CompAndWriteRequest::C_CompAndWriteRequest(T &rwl, const utime_t arrived, io::Extents &&image_extents, + bufferlist&& cmp_bl, bufferlist&& bl, uint64_t *mismatch_offset, + int fadvise_flags, ceph::mutex &lock, PerfCounters *perfcounter, + Context *user_req) + : C_WriteRequest(rwl, arrived, std::move(image_extents), std::move(bl), fadvise_flags, lock, perfcounter, user_req), + mismatch_offset(mismatch_offset), cmp_bl(std::move(cmp_bl)) { + ldout(rwl.get_context(), 20) << dendl; +} + +template +C_CompAndWriteRequest::~C_CompAndWriteRequest() { + ldout(rwl.get_context(), 20) << dendl; +} + +template +void C_CompAndWriteRequest::finish_req(int r) { + if (compare_succeeded) { + C_WriteRequest::finish_req(r); + } else { + utime_t now = ceph_clock_now(); + update_req_stats(now); + } +} + +template +void C_CompAndWriteRequest::update_req_stats(utime_t &now) { + /* Compare-and-write stats. Compare-and-write excluded from most write + * stats because the read phase will make them look like slow writes in + * those histograms. */ + if (!compare_succeeded) { + this->m_perfcounter->inc(l_librbd_rwl_cmp_fails, 1); + } + utime_t comp_latency = now - this->m_arrived_time; + this->m_perfcounter->tinc(l_librbd_rwl_cmp_latency, comp_latency); +} + +template +std::ostream &operator<<(std::ostream &os, + const C_CompAndWriteRequest &req) { + os << (C_WriteRequest&)req + << "cmp_bl=" << req.cmp_bl << ", " + << "read_bl=" << req.read_bl << ", " + << "compare_succeeded=" << req.compare_succeeded << ", " + << "mismatch_offset=" << req.mismatch_offset; + return os; +}; + std::ostream &operator<<(std::ostream &os, const BlockGuardReqState &r) { os << "barrier=" << r.barrier << ", " diff --git a/src/librbd/cache/rwl/Request.h b/src/librbd/cache/rwl/Request.h index c77ac448f8fd0..bc8ef9327a6f5 100644 --- a/src/librbd/cache/rwl/Request.h +++ b/src/librbd/cache/rwl/Request.h @@ -336,6 +336,44 @@ public: const C_WriteSameRequest &req); }; +/** + * This is the custodian of the BlockGuard cell for this compare and write. The + * block guard is acquired before the read begins to guarantee atomicity of this + * operation. If this results in a write, the block guard will be released + * when the write completes to all replicas. + */ +template +class C_CompAndWriteRequest : public C_WriteRequest { +public: + using C_BlockIORequest::rwl; + bool compare_succeeded = false; + uint64_t *mismatch_offset; + bufferlist cmp_bl; + bufferlist read_bl; + C_CompAndWriteRequest(T &rwl, const utime_t arrived, io::Extents &&image_extents, + bufferlist&& cmp_bl, bufferlist&& bl, uint64_t *mismatch_offset, + int fadvise_flags, ceph::mutex &lock, PerfCounters *perfcounter, + Context *user_req); + ~C_CompAndWriteRequest(); + + void finish_req(int r) override; + + void update_req_stats(utime_t &now) override; + + /* + * Compare and write doesn't implement alloc_resources(), deferred_handler(), + * or dispatch(). We use the implementation in C_WriteRequest(), and only if the + * compare phase succeeds and a write is actually performed. + */ + + const char *get_name() const override { + return "C_CompAndWriteRequest"; + } + template + friend std::ostream &operator<<(std::ostream &os, + const C_CompAndWriteRequest &req); +}; + struct BlockGuardReqState { bool barrier = false; /* This is a barrier request */ bool current_barrier = false; /* This is the currently active barrier */