From 26eca1b286c07495190b5dd6b14920cf1276bcd6 Mon Sep 17 00:00:00 2001 From: Yuan Lu Date: Thu, 23 Apr 2020 14:03:45 +0800 Subject: [PATCH] librbd: add WriteSameRequest Signed-off-by: Peterson, Scott Signed-off-by: Li, Xiaoyan Signed-off-by: Lu, Yuan Signed-off-by: Chamarthy, Mahati --- src/librbd/cache/rwl/Request.cc | 71 ++++++++++++++++++++++++++++++--- src/librbd/cache/rwl/Request.h | 38 +++++++++++++++++- 2 files changed, 103 insertions(+), 6 deletions(-) diff --git a/src/librbd/cache/rwl/Request.cc b/src/librbd/cache/rwl/Request.cc index e2e911c8082..8dc6f4c531d 100644 --- a/src/librbd/cache/rwl/Request.cc +++ b/src/librbd/cache/rwl/Request.cc @@ -113,7 +113,7 @@ C_WriteRequest::C_WriteRequest(T &rwl, const utime_t arrived, io::Extents &&i bufferlist&& bl, const int fadvise_flags, ceph::mutex &lock, PerfCounters *perfcounter, Context *user_req) : C_BlockIORequest(rwl, arrived, std::move(image_extents), std::move(bl), fadvise_flags, user_req), - m_lock(lock), m_perfcounter(perfcounter) { + m_perfcounter(perfcounter), m_lock(lock) { ldout(rwl.get_context(), 99) << this << dendl; } @@ -187,6 +187,11 @@ void C_WriteRequest::setup_buffer_resources( bytes_dirtied = bytes_cached; } +template +std::shared_ptr C_WriteRequest::create_operation(uint64_t offset, uint64_t len) { + return std::make_shared(*op_set, offset, len, rwl.get_context()); +} + template void C_WriteRequest::setup_log_operations(DeferredContexts &on_exit) { GenericWriteLogEntries log_entries; @@ -224,9 +229,8 @@ void C_WriteRequest::setup_log_operations(DeferredContexts &on_exit) { uint64_t buffer_offset = 0; for (auto &extent : this->image_extents) { /* operation->on_write_persist connected to m_prior_log_entries_persisted Gather */ - auto operation = - std::make_shared(*op_set, extent.first, extent.second, rwl.get_context()); - op_set->operations.emplace_back(operation); + auto operation = this->create_operation(extent.first, extent.second); + this->op_set->operations.emplace_back(operation); /* A WS is also a write */ ldout(rwl.get_context(), 20) << "write_req=" << *this << " op_set=" << op_set.get() @@ -311,7 +315,7 @@ void C_WriteRequest::dispatch() this->m_dispatched_time = now; ldout(cct, 15) << "write_req=" << this << " cell=" << this->get_cell() << dendl; - setup_log_operations(on_exit); + this->setup_log_operations(on_exit); bool append_deferred = false; if (!op_set->persist_on_flush && @@ -561,6 +565,63 @@ std::ostream &operator<<(std::ostream &os, return os; }; +template +C_WriteSameRequest::C_WriteSameRequest(T &rwl, const utime_t arrived, io::Extents &&image_extents, + bufferlist&& bl, const 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) { + ldout(rwl.get_context(), 20) << this << dendl; +} + +template +C_WriteSameRequest::~C_WriteSameRequest() { + ldout(rwl.get_context(), 20) << this << dendl; +} + +template +void C_WriteSameRequest::update_req_stats(utime_t &now) { + /* Write same stats excluded from most write stats + * because the read phase will make them look like slow writes in + * those histograms. */ + ldout(rwl.get_context(), 20) << this << dendl; + utime_t comp_latency = now - this->m_arrived_time; + this->m_perfcounter->tinc(l_librbd_rwl_ws_latency, comp_latency); +} + +/* Write sames will allocate one buffer, the size of the repeating pattern */ +template +void C_WriteSameRequest::setup_buffer_resources( + uint64_t &bytes_cached, uint64_t &bytes_dirtied, uint64_t &bytes_allocated, + uint64_t &number_lanes, uint64_t &number_log_entries, + uint64_t &number_unpublished_reserves) { + ldout(rwl.get_context(), 20) << this << dendl; + ceph_assert(this->image_extents.size() == 1); + bytes_dirtied += this->image_extents[0].second; + auto pattern_length = this->bl.length(); + this->m_resources.buffers.emplace_back(); + struct WriteBufferAllocation &buffer = this->m_resources.buffers.back(); + buffer.allocation_size = MIN_WRITE_ALLOC_SIZE; + buffer.allocated = false; + bytes_cached += pattern_length; + if (pattern_length > buffer.allocation_size) { + buffer.allocation_size = pattern_length; + } +} + +template +std::shared_ptr C_WriteSameRequest::create_operation(uint64_t offset, uint64_t len) { + ceph_assert(this->image_extents.size() == 1); + return std::make_shared(*this->op_set.get(), offset, len, + this->bl.length(), rwl.get_context()); +} + +template +std::ostream &operator<<(std::ostream &os, + const C_WriteSameRequest &req) { + os << (C_WriteRequest&)req; + 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 76a209bbe4f..c77ac448f8f 100644 --- a/src/librbd/cache/rwl/Request.h +++ b/src/librbd/cache/rwl/Request.h @@ -153,6 +153,8 @@ public: void dispatch() override; + virtual std::shared_ptr create_operation(uint64_t offset, uint64_t len); + virtual void setup_log_operations(DeferredContexts &on_exit); bool append_write_request(std::shared_ptr sync_point); @@ -165,6 +167,7 @@ public: protected: using C_BlockIORequest::m_resources; + PerfCounters *m_perfcounter = nullptr; /* Plain writes will allocate one buffer per request extent */ void setup_buffer_resources( uint64_t &bytes_cached, uint64_t &bytes_dirtied, uint64_t &bytes_allocated, @@ -176,7 +179,6 @@ private: std::atomic m_appended = {0}; bool m_queued = false; ceph::mutex &m_lock; - PerfCounters *m_perfcounter = nullptr; template friend std::ostream &operator<<(std::ostream &os, const C_WriteRequest &req); @@ -300,6 +302,40 @@ private: const C_DiscardRequest &req); }; +/** + * This is the custodian of the BlockGuard cell for this write same. + * + * A writesame allocates and persists a data buffer like a write, but the + * data buffer is usually much shorter than the write same. + */ +template +class C_WriteSameRequest : public C_WriteRequest { +public: + using C_BlockIORequest::rwl; + C_WriteSameRequest(T &rwl, const utime_t arrived, io::Extents &&image_extents, + bufferlist&& bl, const int fadvise_flags, ceph::mutex &lock, + PerfCounters *perfcounter, Context *user_req); + + ~C_WriteSameRequest() override; + + void update_req_stats(utime_t &now) override; + + void setup_buffer_resources( + uint64_t &bytes_cached, uint64_t &bytes_dirtied, uint64_t &bytes_allocated, + uint64_t &number_lanes, uint64_t &number_log_entries, + uint64_t &number_unpublished_reserves) override; + + std::shared_ptr create_operation(uint64_t offset, uint64_t len) override; + + const char *get_name() const override { + return "C_WriteSameRequest"; + } + + template + friend std::ostream &operator<<(std::ostream &os, + const C_WriteSameRequest &req); +}; + struct BlockGuardReqState { bool barrier = false; /* This is a barrier request */ bool current_barrier = false; /* This is the currently active barrier */ -- 2.39.5