From c20a95b0b9f4082dcebb339135683b91fe39ec0a 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 --- 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 ae6eca5a86999..432e197c82725 100644 --- a/src/osd/PG.cc +++ b/src/osd/PG.cc @@ -5205,6 +5205,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 9cc06683169c0..1185754d2fc1a 100644 --- a/src/osd/PG.h +++ b/src/osd/PG.h @@ -1709,6 +1709,9 @@ protected: // 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 a5c260740f8e6..dc2d7fcec21fa 100644 --- a/src/osd/PrimaryLogPG.cc +++ b/src/osd/PrimaryLogPG.cc @@ -13761,7 +13761,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