From 8464c06412b72673ca9d01d35e8f68451e1982b3 Mon Sep 17 00:00:00 2001 From: Joao Eduardo Luis Date: Mon, 13 May 2013 15:36:59 +0100 Subject: [PATCH] mon: Monitor: tolerate GV duplicates during conversion Fixes: #4974 Signed-off-by: Joao Eduardo Luis (cherry picked from commit ba05b16ee2b6e25141f2ab88265a1cf92dcd493c) --- src/mon/Monitor.cc | 37 ++++++++++++++++++++++++++++++++++--- src/mon/Monitor.h | 2 ++ 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/mon/Monitor.cc b/src/mon/Monitor.cc index 56cd291cd24ae..3c40ad3808526 100644 --- a/src/mon/Monitor.cc +++ b/src/mon/Monitor.cc @@ -4404,23 +4404,54 @@ void Monitor::StoreConverter::_convert_machines(string machine) dout(20) << __func__ << " " << machine << " ver " << ver << " -> " << gv << dendl; + MonitorDBStore::Transaction paxos_tx; + if (gvs.count(gv) == 0) { - gvs.insert(gv); + gvs.insert(gv); } else { dout(0) << __func__ << " " << machine << " gv " << gv << " already exists" << dendl; - assert(0 == "Duplicate GV -- something is wrong!"); + + // Duplicates aren't supposed to happen, but an old bug introduced + // them and the mds state machine wasn't ever trimmed, so many users + // will see them. So we'll just merge them all in one + // single paxos version. + // We know that they are either from another paxos machine or + // they are from the same paxos machine but their version is + // lower than ours -- given that we are iterating all versions + // from the lowest to the highest, duh! + // We'll just append our stuff to the existing paxos transaction + // as if nothing had happened. + + // Just make sure we are correct. This shouldn't take long and + // should never be triggered! + set >& s = gv_map[gv]; + for (set >::iterator it = s.begin(); + it != s.end(); ++it) { + if (it->first == machine) + assert(it->second + 1 == ver); + } + + bufferlist paxos_bl; + int r = db->get("paxos", gv, paxos_bl); + assert(r >= 0); + paxos_tx.append_from_encoded(paxos_bl); } + gv_map[gv].insert(make_pair(machine,ver)); bufferlist tx_bl; tx.encode(tx_bl); - tx.put("paxos", gv, tx_bl); + paxos_tx.append_from_encoded(tx_bl); + bufferlist paxos_bl; + paxos_tx.encode(paxos_bl); + tx.put("paxos", gv, paxos_bl); } db->apply_transaction(tx); } version_t lc = db->get(machine, "last_committed"); + dout(20) << __func__ << " lc " << lc << " last_committed " << last_committed << dendl; assert(lc == last_committed); MonitorDBStore::Transaction tx; diff --git a/src/mon/Monitor.h b/src/mon/Monitor.h index c06d2fbb54e3d..57da2aba539c6 100644 --- a/src/mon/Monitor.h +++ b/src/mon/Monitor.h @@ -1450,6 +1450,8 @@ public: boost::scoped_ptr store; set gvs; + map > > gv_map; + version_t highest_last_pn; version_t highest_accepted_pn; -- 2.39.5