From cd896c3bfc4f8d5e13627d5c6a81092fd9dc63b3 Mon Sep 17 00:00:00 2001 From: Yuan Lu Date: Sun, 26 Apr 2020 15:47:33 +0800 Subject: [PATCH] librbd: add DiscardRequest 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 | 108 +++++++++++++++++++++++++++++++- src/librbd/cache/rwl/Request.h | 44 +++++++++++++ 2 files changed, 151 insertions(+), 1 deletion(-) diff --git a/src/librbd/cache/rwl/Request.cc b/src/librbd/cache/rwl/Request.cc index a19dfbba469..e2e911c8082 100644 --- a/src/librbd/cache/rwl/Request.cc +++ b/src/librbd/cache/rwl/Request.cc @@ -232,7 +232,9 @@ void C_WriteRequest::setup_log_operations(DeferredContexts &on_exit) { ldout(rwl.get_context(), 20) << "write_req=" << *this << " op_set=" << op_set.get() << " operation=" << operation << dendl; log_entries.emplace_back(operation->log_entry); - rwl.inc_last_op_sequence_num(); + if (!op_set->persist_on_flush) { + rwl.inc_last_op_sequence_num(); + } operation->init(true, allocation, current_sync_gen, rwl.get_last_op_sequence_num(), this->bl, buffer_offset, op_set->persist_on_flush); buffer_offset += operation->log_entry->write_bytes(); @@ -455,6 +457,110 @@ void C_ReadRequest::finish(int r) { } } +template +C_DiscardRequest::C_DiscardRequest(T &rwl, const utime_t arrived, io::Extents &&image_extents, + uint32_t discard_granularity_bytes, ceph::mutex &lock, + PerfCounters *perfcounter, Context *user_req) + : C_BlockIORequest(rwl, arrived, std::move(image_extents), bufferlist(), 0, user_req), + m_discard_granularity_bytes(discard_granularity_bytes), + m_lock(lock), + m_perfcounter(perfcounter) { + ldout(rwl.get_context(), 20) << this << dendl; +} + +template +C_DiscardRequest::~C_DiscardRequest() { + ldout(rwl.get_context(), 20) << this << dendl; +} + +template +bool C_DiscardRequest::alloc_resources() { + ldout(rwl.get_context(), 20) << "req type=" << get_name() << " " + << "req=[" << *this << "]" << dendl; + return rwl.alloc_resources(this); +} + +template +void C_DiscardRequest::setup_log_operations() { + std::lock_guard locker(m_lock); + GenericWriteLogEntries log_entries; + for (auto &extent : this->image_extents) { + op = std::make_shared(rwl.get_current_sync_point(), + extent.first, + extent.second, + m_discard_granularity_bytes, + this->m_dispatched_time, + m_perfcounter, + rwl.get_context()); + log_entries.emplace_back(op->log_entry); + break; + } + uint64_t current_sync_gen = rwl.get_current_sync_gen(); + bool persist_on_flush = rwl.get_persist_on_flush(); + if (!persist_on_flush) { + rwl.inc_last_op_sequence_num(); + } + auto discard_req = this; + Context *on_write_persist = new LambdaContext( + [this, discard_req](int r) { + ldout(rwl.get_context(), 20) << "discard_req=" << discard_req + << " cell=" << discard_req->get_cell() << dendl; + ceph_assert(discard_req->get_cell()); + discard_req->complete_user_request(r); + discard_req->release_cell(); + }); + op->init(current_sync_gen, persist_on_flush, rwl.get_last_op_sequence_num(), on_write_persist); + rwl.add_into_log_map(log_entries); +} + +template +void C_DiscardRequest::dispatch() { + utime_t now = ceph_clock_now(); + ldout(rwl.get_context(), 20) << "req type=" << get_name() << " " + << "req=[" << *this << "]" << dendl; + ceph_assert(this->m_resources.allocated); + this->m_dispatched_time = now; + setup_log_operations(); + m_perfcounter->inc(l_librbd_rwl_log_ops, 1); + rwl.schedule_append(op); +} + +template +void C_DiscardRequest::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) { + number_log_entries = 1; + /* No bytes are allocated for a discard, but we count the discarded bytes + * as dirty. This means it's possible to have more bytes dirty than + * there are bytes cached or allocated. */ + for (auto &extent : this->image_extents) { + bytes_dirtied = extent.second; + break; + } +} + +template +void C_DiscardRequest::blockguard_acquired(GuardedRequestFunctionContext &guard_ctx) { + ldout(rwl.get_context(), 20) << " cell=" << guard_ctx.cell << dendl; + + ceph_assert(guard_ctx.cell); + this->detained = guard_ctx.state.detained; /* overlapped */ + this->set_cell(guard_ctx.cell); +} + +template +std::ostream &operator<<(std::ostream &os, + const C_DiscardRequest &req) { + os << (C_BlockIORequest&)req; + if (req.op) { + os << " op=[" << *req.op << "]"; + } else { + os << " op=nullptr"; + } + 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 5426f7950ba..76a209bbe4f 100644 --- a/src/librbd/cache/rwl/Request.h +++ b/src/librbd/cache/rwl/Request.h @@ -256,6 +256,50 @@ private: PerfCounters *m_perfcounter; }; +/** + * This is the custodian of the BlockGuard cell for this discard. As in the + * case of write, the block guard is not released until the discard persists + * everywhere. + */ +template +class C_DiscardRequest : public C_BlockIORequest { +public: + using C_BlockIORequest::rwl; + std::shared_ptr op; + + C_DiscardRequest(T &rwl, const utime_t arrived, io::Extents &&image_extents, + uint32_t discard_granularity_bytes, ceph::mutex &lock, + PerfCounters *perfcounter, Context *user_req); + + ~C_DiscardRequest() override; + void finish_req(int r) override {} + + bool alloc_resources() override; + + void deferred_handler() override { } + + void setup_log_operations(); + + void dispatch() override; + + void blockguard_acquired(GuardedRequestFunctionContext &guard_ctx); + + const char *get_name() const override { + return "C_DiscardRequest"; + } + 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; +private: + uint32_t m_discard_granularity_bytes; + ceph::mutex &m_lock; + PerfCounters *m_perfcounter = nullptr; + template + friend std::ostream &operator<<(std::ostream &os, + const C_DiscardRequest &req); +}; + struct BlockGuardReqState { bool barrier = false; /* This is a barrier request */ bool current_barrier = false; /* This is the currently active barrier */ -- 2.39.5