From 59d8eeb81a5011ab61e6764724746069e96c44b9 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 24 Apr 2018 15:35:28 -0500 Subject: [PATCH] osd/PrimaryLogPG: defer evict if head *or* object intersect scrub interval Consider a scenario like: - scrub [3:2525d100:::earlier:head,3:2525d12f:::foo:200] - we see 3:2525d12f:::foo:100 and include it in scrub map - scrub [3:2525d12f:::foo:200, 3:2525dfff:::later:head] - some op(s) that cause scrub to be preempted - agent_work wants to evict 3:2525d12f:::foo:100 - write_blocked_by_scrub sees scrub is preempted, returns false - 3:2525d12f:::foo:100 is removed, :head SnapSet is updated - scrub rescrubs [3:2525d12f:::foo:200, 3:2525dfff:::later:head] - includes (updated) :head SnapSet - issues error like "3:2525d12f:::foo:100 is an unexpected clone" Fix the problem by checking if anything part of the object-to-evict and its head touch the scrub range; if so, back off. Do not let eviction preempt scrub; we can come back and do it later. Fixes: http://tracker.ceph.com/issues/23646 Signed-off-by: Sage Weil (cherry picked from commit c20a95b0b9f4082dcebb339135683b91fe39ec0a) --- src/osd/PG.cc | 7 +++++++ src/osd/PG.h | 3 +++ src/osd/PrimaryLogPG.cc | 3 ++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/osd/PG.cc b/src/osd/PG.cc index 2f8d976ec56db..715b95690bb7c 100644 --- a/src/osd/PG.cc +++ b/src/osd/PG.cc @@ -4976,6 +4976,13 @@ bool PG::write_blocked_by_scrub(const hobject_t& soid) return true; } +bool PG::range_intersects_scrub(const hobject_t &start, const hobject_t& end) +{ + // does [start, end] intersect [scrubber.start, scrubber.end) + return (start < scrubber.end && + end >= scrubber.start); +} + void PG::scrub_clear_state() { assert(is_locked()); diff --git a/src/osd/PG.h b/src/osd/PG.h index 3ff8721673f8a..a877f86e98ae3 100644 --- a/src/osd/PG.h +++ b/src/osd/PG.h @@ -1390,6 +1390,9 @@ public: // not stop until the scrub range is completed. bool write_blocked_by_scrub(const hobject_t &soid); + /// true if the given range intersects the scrub interval in any way + bool range_intersects_scrub(const hobject_t &start, const hobject_t& end); + void repair_object( const hobject_t& soid, list > *ok_peers, pg_shard_t bad_peer); diff --git a/src/osd/PrimaryLogPG.cc b/src/osd/PrimaryLogPG.cc index 99b2b1ca114f5..8637c63d405ce 100644 --- a/src/osd/PrimaryLogPG.cc +++ b/src/osd/PrimaryLogPG.cc @@ -13078,7 +13078,8 @@ bool PrimaryLogPG::agent_work(int start_max, int agent_flush_quota) osd->logger->inc(l_osd_agent_skip); continue; } - if (write_blocked_by_scrub(obc->obs.oi.soid)) { + if (range_intersects_scrub(obc->obs.oi.soid, + obc->obs.oi.soid.get_head())) { dout(20) << __func__ << " skip (scrubbing) " << obc->obs.oi << dendl; osd->logger->inc(l_osd_agent_skip); continue; -- 2.39.5