]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
osd/PrimaryLogPG: defer evict if head *or* object intersect scrub interval
authorSage Weil <sage@redhat.com>
Tue, 24 Apr 2018 20:35:28 +0000 (15:35 -0500)
committerDavid Zafman <dzafman@redhat.com>
Fri, 18 May 2018 16:37:57 +0000 (09:37 -0700)
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>
(cherry picked from commit c20a95b0b9f4082dcebb339135683b91fe39ec0a)

src/osd/PG.cc
src/osd/PG.h
src/osd/PrimaryLogPG.cc

index 2f8d976ec56db812c1e8899d1d9151f28f1b7a2f..715b95690bb7cdd99b71833688c56e47544b86d3 100644 (file)
@@ -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());
index 3ff8721673f8a57eacf2d5dec123ade5c213234c..a877f86e98ae37ad71210585616f751ca7b80a74 100644 (file)
@@ -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<pair<ScrubMap::object, pg_shard_t> > *ok_peers,
     pg_shard_t bad_peer);
index 99b2b1ca114f5d45c95ae84fc471ff4bd5693288..8637c63d405cea9dd0ace24e67464affb49697e0 100644 (file)
@@ -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;