From: Greg Farnum Date: Thu, 23 Jan 2014 21:08:26 +0000 (-0800) Subject: Elector: ignore messages from mons without required feature capabilities X-Git-Tag: v0.78~251^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=687b570b719d34abebf1673b001f40b96e15189f;p=ceph.git Elector: ignore messages from mons without required feature capabilities We maintain a list of required_features which the other monitor's features must supply. This starts out at 0 and is initialized from the monitor's list of features whenever we start electing. Despite the scary sound of "just ignore it", this is safe: the monitor will only record features as required once a quorum has formed in which every monitor supports them. After that happens, monitors which do not support those features will be unable to read the whole mon store/understand the pg reports/whatever else, so letting them into the quorum would be buggy behavior. So if we ignore a monitor, it will not be able to start nor join an election round with anybody who was in our quorum -- that is, the ignored monitor cannot form a separate quorum. By ignoring it here, we also prevent it from endlessly calling elections against the real quorum. Unfortunately there is no way to communicate to old monitors that they cannot join the quorum -- there are no existing messages for that purpose, and eg adding a new op to the MMonElection message will just cause it to crash, which we don't want to do either. Fixes: #7215 Signed-off-by: Greg Farnum --- diff --git a/src/mon/Elector.cc b/src/mon/Elector.cc index 44c9485730ec..fdab343c8a5c 100644 --- a/src/mon/Elector.cc +++ b/src/mon/Elector.cc @@ -75,6 +75,7 @@ void Elector::start() acked_me.clear(); classic_mons.clear(); + required_features = mon->apply_compatset_features_to_quorum_requirements(); init(); // start by trying to elect me @@ -210,10 +211,14 @@ void Elector::handle_propose(MMonElection *m) int from = m->get_source().num(); assert(m->epoch % 2 == 1); // election - if (m->epoch > epoch) { + if ((required_features ^ m->get_connection()->get_features()) & + required_features) { + dout(5) << " ignoring propose from mon without required features" << dendl; + m->put(); + return; + } else if (m->epoch > epoch) { bump_epoch(m->epoch); - } - else if (m->epoch < epoch) { + } else if (m->epoch < epoch) { // got an "old" propose, if (epoch % 2 == 0 && // in a non-election cycle mon->quorum.count(from) == 0) { // from someone outside the quorum diff --git a/src/mon/Elector.h b/src/mon/Elector.h index bee3b3082332..0b2b893ba34e 100644 --- a/src/mon/Elector.h +++ b/src/mon/Elector.h @@ -115,6 +115,8 @@ class Elector { */ map acked_me; set classic_mons; + /// features which a monitor must hold for us to defer to them + uint64_t required_features; /** * @} */ @@ -323,11 +325,12 @@ class Elector { * @param m A Monitor instance */ Elector(Monitor *m) : mon(m), - expire_event(0), - epoch(0), - participating(true), - electing_me(false), - leader_acked(-1) { } + expire_event(0), + epoch(0), + participating(true), + electing_me(false), + required_features(0), + leader_acked(-1) { } /** * Initiate the Elector class.