]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
osd/PrimaryLogPG: defer evict if head *or* object intersect scrub interval 21628/head
authorSage Weil <sage@redhat.com>
Tue, 24 Apr 2018 20:35:28 +0000 (15:35 -0500)
committerSage Weil <sage@redhat.com>
Tue, 24 Apr 2018 21:04:27 +0000 (16:04 -0500)
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 <sage@redhat.com>
src/osd/PG.cc
src/osd/PG.h
src/osd/PrimaryLogPG.cc

index ae6eca5a86999d78beb57daff7dfb89f544014cf..432e197c8272573e36ef8dddd485793b3ca1c774 100644 (file)
@@ -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());
index 9cc06683169c0aceed24c9d66df3242c822e8a92..1185754d2fc1a284728f3aeaec7f734e9216df2b 100644 (file)
@@ -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<pair<ScrubMap::object, pg_shard_t> > *ok_peers,
     pg_shard_t bad_peer);
index a5c260740f8e609d2887661c8991b4d8943470e7..dc2d7fcec21faf577ac6e50831c5237dd0b73045 100644 (file)
@@ -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;