]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/mon/Elector.cc
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / mon / Elector.cc
index f69bcf16d5a6395b4eed8550012099a28124a834..ca46d8c74245471ab369850fa1e760e7aa99f6d1 100644 (file)
@@ -20,7 +20,7 @@
 #include "messages/MMonElection.h"
 
 #include "common/config.h"
-#include "include/assert.h"
+#include "include/ceph_assert.h"
 
 #define dout_subsys ceph_subsys_mon
 #undef dout_prefix
@@ -58,7 +58,7 @@ void Elector::shutdown()
 void Elector::bump_epoch(epoch_t e) 
 {
   dout(10) << "bump_epoch " << epoch << " to " << e << dendl;
-  assert(epoch <= e);
+  ceph_assert(epoch <= e);
   epoch = e;
   auto t(std::make_shared<MonitorDBStore::Transaction>());
   t->put(Monitor::MONITOR_NAME, "election_epoch", epoch);
@@ -91,11 +91,11 @@ void Elector::start()
     auto t(std::make_shared<MonitorDBStore::Transaction>());
     t->put(Monitor::MONITOR_NAME, "election_writeable_test", rand());
     int r = mon->store->apply_transaction(t);
-    assert(r >= 0);
+    ceph_assert(r >= 0);
   }
-  start_stamp = ceph_clock_now();
   electing_me = true;
   acked_me[mon->rank].cluster_features = CEPH_FEATURES_ALL;
+  acked_me[mon->rank].mon_release = ceph_release();
   acked_me[mon->rank].mon_features = ceph::features::mon::get_supported();
   mon->collect_metadata(&acked_me[mon->rank].metadata);
   leader_acked = -1;
@@ -106,7 +106,8 @@ void Elector::start()
     MMonElection *m =
       new MMonElection(MMonElection::OP_PROPOSE, epoch, mon->monmap);
     m->mon_features = ceph::features::mon::get_supported();
-    mon->messenger->send_message(m, mon->monmap->get_inst(i));
+    m->mon_release = ceph_release();
+    mon->send_mon_message(m, i);
   }
   
   reset_timer();
@@ -124,18 +125,12 @@ void Elector::defer(int who)
 
   // ack them
   leader_acked = who;
-  ack_stamp = ceph_clock_now();
   MMonElection *m = new MMonElection(MMonElection::OP_ACK, epoch, mon->monmap);
   m->mon_features = ceph::features::mon::get_supported();
+  m->mon_release = ceph_release();
   mon->collect_metadata(&m->metadata);
 
-  // This field is unused completely in luminous, but jewel uses it to
-  // determine whether we are a dumpling mon due to some crufty old
-  // code.  It only needs to see this buffer non-empty, so put
-  // something useless there.
-  m->sharing_bl = mon->get_local_commands_bl(mon->get_required_mon_features());
-
-  mon->messenger->send_message(m, mon->monmap->get_inst(who));
+  mon->send_mon_message(m, who);
   
   // set a timer
   reset_timer(1.0);  // give the leader some extra time to declare victory
@@ -160,7 +155,7 @@ void Elector::reset_timer(double plus)
    * Leader.
    */
   expire_event = mon->timer.add_event_after(
-    g_conf->mon_election_timeout + plus,
+    g_conf()->mon_election_timeout + plus,
     new C_MonContext(mon, [this](int) {
        expire();
       }));
@@ -203,6 +198,7 @@ void Elector::victory()
   mon_feature_t mon_features = ceph::features::mon::get_supported();
   set<int> quorum;
   map<int,Metadata> metadata;
+  int min_mon_release = -1;
   for (map<int, elector_info_t>::iterator p = acked_me.begin();
        p != acked_me.end();
        ++p) {
@@ -210,11 +206,14 @@ void Elector::victory()
     cluster_features &= p->second.cluster_features;
     mon_features &= p->second.mon_features;
     metadata[p->first] = p->second.metadata;
+    if (min_mon_release < 0 || p->second.mon_release < min_mon_release) {
+      min_mon_release = p->second.mon_release;
+    }
   }
 
   cancel_timer();
   
-  assert(epoch % 2 == 1);  // election
+  ceph_assert(epoch % 2 == 1);  // election
   bump_epoch(epoch+1);     // is over!
 
   // tell everyone!
@@ -228,12 +227,14 @@ void Elector::victory()
     m->quorum_features = cluster_features;
     m->mon_features = mon_features;
     m->sharing_bl = mon->get_local_commands_bl(mon_features);
-    mon->messenger->send_message(m, mon->monmap->get_inst(*p));
+    m->mon_release = min_mon_release;
+    mon->send_mon_message(m, *p);
   }
 
   // tell monitor
   mon->win_election(epoch, quorum,
-                    cluster_features, mon_features, metadata);
+                    cluster_features, mon_features, min_mon_release,
+                   metadata);
 }
 
 
@@ -244,7 +245,7 @@ void Elector::handle_propose(MonOpRequestRef op)
   dout(5) << "handle_propose from " << m->get_source() << dendl;
   int from = m->get_source().num();
 
-  assert(m->epoch % 2 == 1); // election
+  ceph_assert(m->epoch % 2 == 1); // election
   uint64_t required_features = mon->get_required_features();
   mon_feature_t required_mon_features = mon->get_required_mon_features();
 
@@ -260,6 +261,12 @@ void Elector::handle_propose(MonOpRequestRef op)
            << " without required features" << dendl;
     nak_old_peer(op);
     return;
+  } else if (mon->monmap->min_mon_release > m->mon_release) {
+    dout(5) << " ignoring propose from mon" << from
+           << " release " << m->mon_release
+           << " < min_mon_release " << mon->monmap->min_mon_release << dendl;
+    nak_old_peer(op);
+    return;
   } else if (!m->mon_features.contains_all(required_mon_features)) {
     // all the features in 'required_mon_features' not in 'm->mon_features'
     mon_feature_t missing = required_mon_features.diff(m->mon_features);
@@ -287,7 +294,7 @@ void Elector::handle_propose(MonOpRequestRef op)
   if (mon->rank < from) {
     // i would win over them.
     if (leader_acked >= 0) {        // we already acked someone
-      assert(leader_acked < from);  // and they still win, of course
+      ceph_assert(leader_acked < from);  // and they still win, of course
       dout(5) << "no, we already acked " << leader_acked << dendl;
     } else {
       // wait, i should win!
@@ -315,14 +322,14 @@ void Elector::handle_ack(MonOpRequestRef op)
   dout(5) << "handle_ack from " << m->get_source() << dendl;
   int from = m->get_source().num();
 
-  assert(m->epoch % 2 == 1); // election
+  ceph_assert(m->epoch % 2 == 1); // election
   if (m->epoch > epoch) {
     dout(5) << "woah, that's a newer epoch, i must have rebooted.  bumping and re-starting!" << dendl;
     bump_epoch(m->epoch);
     start();
     return;
   }
-  assert(m->epoch == epoch);
+  ceph_assert(m->epoch == epoch);
   uint64_t required_features = mon->get_required_features();
   if ((required_features ^ m->get_connection()->get_features()) &
       required_features) {
@@ -344,6 +351,7 @@ void Elector::handle_ack(MonOpRequestRef op)
     // thanks
     acked_me[from].cluster_features = m->get_connection()->get_features();
     acked_me[from].mon_features = m->mon_features;
+    acked_me[from].mon_release = m->mon_release;
     acked_me[from].metadata = m->metadata;
     dout(5) << " so far i have {";
     for (map<int, elector_info_t>::const_iterator p = acked_me.begin();
@@ -364,7 +372,7 @@ void Elector::handle_ack(MonOpRequestRef op)
     }
   } else {
     // ignore, i'm deferring already.
-    assert(leader_acked >= 0);
+    ceph_assert(leader_acked >= 0);
   }
 }
 
@@ -379,8 +387,8 @@ void Elector::handle_victory(MonOpRequestRef op)
           << dendl;
   int from = m->get_source().num();
 
-  assert(from < mon->rank);
-  assert(m->epoch % 2 == 0);  
+  ceph_assert(from < mon->rank);
+  ceph_assert(m->epoch % 2 == 0);  
 
   leader_acked = -1;
 
@@ -396,15 +404,15 @@ void Elector::handle_victory(MonOpRequestRef op)
 
   // they win
   mon->lose_election(epoch, m->quorum, from,
-                     m->quorum_features, m->mon_features);
+                     m->quorum_features, m->mon_features, m->mon_release);
 
   // cancel my timer
   cancel_timer();
 
   // stash leader's commands
-  assert(m->sharing_bl.length());
+  ceph_assert(m->sharing_bl.length());
   vector<MonCommand> new_cmds;
-  bufferlist::iterator bi = m->sharing_bl.begin();
+  auto bi = m->sharing_bl.cbegin();
   MonCommand::decode_vector(new_cmds, bi);
   mon->set_leader_commands(new_cmds);
 }
@@ -417,16 +425,16 @@ void Elector::nak_old_peer(MonOpRequestRef op)
   uint64_t required_features = mon->get_required_features();
   mon_feature_t required_mon_features = mon->get_required_mon_features();
   dout(10) << "sending nak to peer " << m->get_source()
-    << " that only supports " << supported_features
-    << " " << m->mon_features
-    << " of the required " << required_features
-    << " " << required_mon_features
-    << dendl;
-
+          << " supports " << supported_features << " " << m->mon_features
+          << ", required " << required_features << " " << required_mon_features
+          << ", release " << m->mon_release
+          << " vs required " << mon->monmap->min_mon_release
+          << dendl;
   MMonElection *reply = new MMonElection(MMonElection::OP_NAK, m->epoch,
                                          mon->monmap);
   reply->quorum_features = required_features;
   reply->mon_features = required_mon_features;
+  reply->mon_release = mon->monmap->min_mon_release;
   mon->features.encode(reply->sharing_bl);
   m->get_connection()->send_message(reply);
 }
@@ -438,20 +446,25 @@ void Elector::handle_nak(MonOpRequestRef op)
   dout(1) << "handle_nak from " << m->get_source()
          << " quorum_features " << m->quorum_features
           << " " << m->mon_features
+         << " min_mon_release " << m->mon_release
           << dendl;
 
-  CompatSet other;
-  bufferlist::iterator bi = m->sharing_bl.begin();
-  other.decode(bi);
-  CompatSet diff = Monitor::get_supported_features().unsupported(other);
-
-  mon_feature_t mon_supported = ceph::features::mon::get_supported();
-  // all features in 'm->mon_features' not in 'mon_supported'
-  mon_feature_t mon_diff = m->mon_features.diff(mon_supported);
+  if (m->mon_release > ceph_release()) {
+    derr << "Shutting down because I am release " << ceph_release()
+        << " < min_mon_release " << m->mon_release << dendl;
+  } else {
+    CompatSet other;
+    auto bi = m->sharing_bl.cbegin();
+    other.decode(bi);
+    CompatSet diff = Monitor::get_supported_features().unsupported(other);
 
-  derr << "Shutting down because I do not support required monitor features: { "
-       << diff << " } " << mon_diff << dendl;
+    mon_feature_t mon_supported = ceph::features::mon::get_supported();
+    // all features in 'm->mon_features' not in 'mon_supported'
+    mon_feature_t mon_diff = m->mon_features.diff(mon_supported);
 
+    derr << "Shutting down because I lack required monitor features: { "
+        << diff << " } " << mon_diff << dendl;
+  }
   exit(0);
   // the end!
 }
@@ -459,7 +472,7 @@ void Elector::handle_nak(MonOpRequestRef op)
 void Elector::dispatch(MonOpRequestRef op)
 {
   op->mark_event("elector:dispatch");
-  assert(op->is_type_election());
+  ceph_assert(op->is_type_election());
 
   switch (op->get_req()->get_type()) {