From 4cdb293e08f0ea066511c9e33f48635d20d58dd9 Mon Sep 17 00:00:00 2001 From: Ronen Friedman Date: Thu, 28 Jan 2021 19:04:35 +0200 Subject: [PATCH] osd: fix the scrubber behavior on multiple preemption attempts Latest scrub code creates a time window in which a specific scrub is marked as "preempted", but future preemptions are prohibited. Write operations handled are then blocked but not restarted on time. Fixes: https://tracker.ceph.com/issues/48793 Signed-off-by: Ronen Friedman --- src/osd/pg_scrubber.cc | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/osd/pg_scrubber.cc b/src/osd/pg_scrubber.cc index 0eb513714e270..526eff86c658f 100644 --- a/src/osd/pg_scrubber.cc +++ b/src/osd/pg_scrubber.cc @@ -585,17 +585,21 @@ bool PgScrubber::write_blocked_by_scrub(const hobject_t& soid) << preemption_data.is_preemptable() << " already preempted? " << preemption_data.was_preempted() << dendl; + if (preemption_data.was_preempted()) { + // otherwise - write requests arriving while 'already preempted' is set + // but 'preemptable' is not - will not be allowed to continue, and will + // not be requeued on time. + return false; + } + if (preemption_data.is_preemptable()) { - if (!preemption_data.was_preempted()) { - dout(10) << __func__ << " " << soid << " preempted" << dendl; + dout(10) << __func__ << " " << soid << " preempted" << dendl; - // signal the preemption - preemption_data.do_preempt(); + // signal the preemption + preemption_data.do_preempt(); + m_end = m_start; // free the range we were scrubbing - } else { - dout(10) << __func__ << " " << soid << " already preempted" << dendl; - } return false; } return true; @@ -616,6 +620,8 @@ bool PgScrubber::range_intersects_scrub(const hobject_t& start, const hobject_t& */ void PgScrubber::add_delayed_scheduling() { + m_end = m_start; // not blocking any range now + milliseconds sleep_time{0ms}; if (m_needs_sleep) { double scrub_sleep = 1000.0 * m_osds->osd->scrub_sleep_time(m_flags.required); @@ -1288,7 +1294,6 @@ void PgScrubber::map_from_replica(OpRequestRef op) if (m->preempted) { dout(10) << __func__ << " replica was preempted, setting flag" << dendl; - ceph_assert(preemption_data.is_preemptable()); // otherwise - how dare the replica! preemption_data.do_preempt(); } -- 2.39.5