]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
PG: best_info must have a last_epoch_started as high as any other info
authorSamuel Just <sam.just@inktank.com>
Sat, 16 Jun 2012 00:09:42 +0000 (17:09 -0700)
committerSage Weil <sage@inktank.com>
Mon, 18 Jun 2012 18:18:30 +0000 (11:18 -0700)
We disregard incomplete infos during find_best_info, but we can't an
info with a last_epoch_started less that of the incomplete info.

This should avoid cases like #2462.  In that case, it appears that
a peer with empty info/log was chosen as authoritative even though
there was a non-empty incomplete peer.

Signed-off-by: Samuel Just <sam.just@inktank.com>
src/osd/PG.cc

index abf33d204ba7e334264e2d963ce6cbc0f1aa71e7..2e6013edf7182313e5ebf9398fad9c0efbf53ddf 100644 (file)
@@ -928,6 +928,7 @@ void PG::clear_primary_state()
  */
 map<int, pg_info_t>::const_iterator PG::find_best_info(const map<int, pg_info_t> &infos) const
 {
+  epoch_t last_epoch_started = 0;
   map<int, pg_info_t>::const_iterator best = infos.end();
   // find osd with newest last_update.  if there are multiples, prefer
   //  - a longer tail, if it brings another peer into log contiguity
@@ -935,6 +936,15 @@ map<int, pg_info_t>::const_iterator PG::find_best_info(const map<int, pg_info_t>
   for (map<int, pg_info_t>::const_iterator p = infos.begin();
        p != infos.end();
        ++p) {
+    // Only consider peers with the most recent last_epoch_started found
+    if (p->second.history.last_epoch_started > last_epoch_started) {
+      last_epoch_started = p->second.history.last_epoch_started;
+      if (best != infos.end() &&
+         last_epoch_started > best->second.history.last_epoch_started)
+       best = infos.end();
+    } else if (p->second.history.last_epoch_started < last_epoch_started) {
+      continue;
+    }
     // Disquality anyone who is incomplete (not fully backfilled)
     if (p->second.is_incomplete())
       continue;