From: Sage Weil Date: Tue, 24 Apr 2018 20:35:28 +0000 (-0500) Subject: osd/PrimaryLogPG: defer evict if head *or* object intersect scrub interval X-Git-Tag: v13.1.0~102^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=refs%2Fpull%2F21628%2Fhead;p=ceph.git 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 --- diff --git a/src/osd/PG.cc b/src/osd/PG.cc index ae6eca5a8699..432e197c8272 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 9cc06683169c..1185754d2fc1 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 a5c260740f8e..dc2d7fcec21f 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;