From b9d81029aeeb13e6cbdfb6ccffa2868beea2d6ab Mon Sep 17 00:00:00 2001 From: Radoslaw Zarzynski Date: Wed, 7 Dec 2022 20:41:07 +0000 Subject: [PATCH] crimson/osd: implement basic osd_snap_trim_sleep support Signed-off-by: Radoslaw Zarzynski --- .../osd/osd_operations/snaptrim_event.cc | 26 ++++++++++++++++--- .../osd/osd_operations/snaptrim_event.h | 17 ++++++++++-- src/crimson/osd/pg.cc | 6 +++-- 3 files changed, 41 insertions(+), 8 deletions(-) diff --git a/src/crimson/osd/osd_operations/snaptrim_event.cc b/src/crimson/osd/osd_operations/snaptrim_event.cc index 816e06e44a6d3..960af069e0c88 100644 --- a/src/crimson/osd/osd_operations/snaptrim_event.cc +++ b/src/crimson/osd/osd_operations/snaptrim_event.cc @@ -64,6 +64,7 @@ void SnapTrimEvent::print(std::ostream &lhs) const lhs << "SnapTrimEvent(" << "pgid=" << pg->get_pgid() << " snapid=" << snapid + << " needs_pause=" << needs_pause << ")"; } @@ -155,11 +156,28 @@ seastar::future SnapTrimEvent::with_pg( wait_subop ).then_interruptible([this] { logger().debug("{}: awaiting completion", *this); - return subop_blocker.wait_completion().then([this] { - logger().debug("{}: all completed", *this); - return interruptor::make_ready_future( - seastar::stop_iteration::no); + return subop_blocker.wait_completion(); + }).then_interruptible([this] { + if (!needs_pause) { + return interruptor::now(); + } + // let's know operators we're waiting + return enter_stage( + wait_trim_timer + ).then_interruptible([this] { + using crimson::common::local_conf; + const auto time_to_sleep = + local_conf().template get_val("osd_snap_trim_sleep"); + logger().debug("{}: time_to_sleep {}", *this, time_to_sleep); + // TODO: this logic should be more sophisticated and distinguish + // between SSDs, HDDs and the hybrid case + return seastar::sleep( + std::chrono::milliseconds(std::lround(time_to_sleep * 1000))); }); + }).then_interruptible([this] { + logger().debug("{}: all completed", *this); + return interruptor::make_ready_future( + seastar::stop_iteration::no); }); }); }); diff --git a/src/crimson/osd/osd_operations/snaptrim_event.h b/src/crimson/osd/osd_operations/snaptrim_event.h index 7f5d2e5910df0..58eacb35a7406 100644 --- a/src/crimson/osd/osd_operations/snaptrim_event.h +++ b/src/crimson/osd/osd_operations/snaptrim_event.h @@ -32,10 +32,14 @@ class SnapTrimEvent final : public PhasedOperationT { public: static constexpr OperationTypeCode type = OperationTypeCode::snaptrim_event; - SnapTrimEvent(Ref pg, SnapMapper& snap_mapper, snapid_t snapid) + SnapTrimEvent(Ref pg, + SnapMapper& snap_mapper, + const snapid_t snapid, + const bool needs_pause) : pg(std::move(pg)), snap_mapper(snap_mapper), - snapid(snapid) {} + snapid(snapid), + needs_pause(needs_pause) {} void print(std::ostream &) const final; void dump_detail(ceph::Formatter* f) const final; @@ -68,10 +72,18 @@ private: static constexpr auto type_name = "SnapTrimEvent::wait_subop"; } wait_subop; + // an instantiator can instruct us to go over this stage and then + // wait for the future to implement throttling. It is implemented + // that way to for the sake of tracking ops. + struct WaitTrimTimer : OrderedExclusivePhaseT { + static constexpr auto type_name = "SnapTrimEvent::wait_trim_timer"; + } wait_trim_timer; + PipelineHandle handle; Ref pg; SnapMapper& snap_mapper; const snapid_t snapid; + const bool needs_pause; public: PipelineHandle& get_handle() { return handle; } @@ -84,6 +96,7 @@ public: CommonPGPipeline::GetOBC::BlockingEvent, CommonPGPipeline::Process::BlockingEvent, WaitSubop::BlockingEvent, + WaitTrimTimer::BlockingEvent, CompletionEvent > tracking_events; }; diff --git a/src/crimson/osd/pg.cc b/src/crimson/osd/pg.cc index c8ddbd00122a8..69076ad82669f 100644 --- a/src/crimson/osd/pg.cc +++ b/src/crimson/osd/pg.cc @@ -457,13 +457,15 @@ void PG::on_active_actmap() [this] { const auto to_trim = snap_trimq.range_start(); snap_trimq.erase(to_trim); - return seastar::repeat([to_trim, this] { + const auto needs_pause = !snap_trimq.empty(); + return seastar::repeat([to_trim, needs_pause, this] { logger().debug("{}: going to start SnapTrimEvent, to_trim={}", *this, to_trim); return shard_services.start_operation( this, snap_mapper, - to_trim).second; + to_trim, + needs_pause).second; }).then([this, trimmed=to_trim] { logger().debug("{}: trimmed snap={}", *this, trimmed); }); -- 2.39.5