From: Samuel Just Date: Thu, 9 Apr 2015 22:01:29 +0000 (-0700) Subject: PGLog::proc_replica_log: handle split out overlapping entries X-Git-Tag: v9.0.2~187^2~3 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=6561e0d955c4563a8505b717de41f5bd89119f63;p=ceph.git PGLog::proc_replica_log: handle split out overlapping entries See the comment, if the overlapping entries between olog.head and log.tail were split out, last_update should be log.tail. Fixes: 11358 Signed-off-by: Samuel Just --- diff --git a/src/osd/PGLog.cc b/src/osd/PGLog.cc index edb7b24f37a..b9576c02047 100644 --- a/src/osd/PGLog.cc +++ b/src/osd/PGLog.cc @@ -190,6 +190,18 @@ void PGLog::proc_replica_log( dout(10) << "proc_replica_log for osd." << from << ": " << oinfo << " " << olog << " " << omissing << dendl; + if (olog.head < log.tail) { + dout(10) << __func__ << ": osd." << from << " does not overlap, not looking " + << "for divergent objects" << dendl; + return; + } + if (olog.head == log.head) { + dout(10) << __func__ << ": osd." << from << " same log head, not looking " + << "for divergent objects" << dendl; + return; + } + assert(olog.head >= log.tail); + /* basically what we're doing here is rewinding the remote log, dropping divergent entries, until we find something that matches @@ -207,48 +219,54 @@ void PGLog::proc_replica_log( << " have " << i->second.have << dendl; } - list::const_iterator fromiter = log.log.end(); - eversion_t lower_bound = log.tail; + list::const_reverse_iterator first_non_divergent = + log.log.rbegin(); while (1) { - if (fromiter == log.log.begin()) + if (first_non_divergent == log.log.rend()) break; - --fromiter; - if (fromiter->version <= olog.head) { - dout(20) << "merge_log cut point (usually last shared) is " - << *fromiter << dendl; - lower_bound = fromiter->version; - ++fromiter; + if (first_non_divergent->version <= olog.head) { + dout(20) << "merge_log point (usually last shared) is " + << *first_non_divergent << dendl; break; } - } + ++first_non_divergent; + } + + /* Because olog.head >= log.tail, we know that both pgs must at least have + * the event represented by log.tail. Thus, lower_bound >= log.tail. It's + * possible that olog/log contain no actual events between olog.head and + * log.tail, however, since they might have been split out. Thus, if + * we cannot find an event e such that log.tail <= e.version <= log.head, + * the last_update must actually be log.tail. + */ + eversion_t lu = + (first_non_divergent == log.log.rend() || + first_non_divergent->version < log.tail) ? + log.tail : + first_non_divergent->version; list divergent; list::const_iterator pp = olog.log.end(); - eversion_t lu(oinfo.last_update); while (true) { - if (pp == olog.log.begin()) { - if (pp != olog.log.end()) // no last_update adjustment if we discard nothing! - lu = olog.tail; + if (pp == olog.log.begin()) break; - } + --pp; const pg_log_entry_t& oe = *pp; // don't continue past the tail of our log. if (oe.version <= log.tail) { - lu = oe.version; ++pp; break; } - if (oe.version <= lower_bound) { - lu = oe.version; + if (oe.version <= lu) { ++pp; break; } divergent.push_front(oe); - } + } IndexedLog folog;