From: Sage Weil Date: Wed, 24 Aug 2011 04:25:13 +0000 (-0700) Subject: mon: fix store_state X-Git-Tag: v0.34~9 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=eaaefece778b042b91d7c7e7fd8e00d418d7e93a;p=ceph.git mon: fix store_state We need to bound the range we write to disk by m->last_committed; this got lost in translation in commit dfab2c91f53289b1d527fb87126a639f5d5275f1. Fixes paxos crashes in handle_begin mon/Paxos.cc: In function 'void Paxos::handle_begin(MMonPaxos*)', in thread '0x7fc74d11f700' mon/Paxos.cc: 393: FAILED assert(begin->last_committed == last_committed) Signed-off-by: Sage Weil --- diff --git a/src/mon/MonitorStore.cc b/src/mon/MonitorStore.cc index b8b7e4b7a7ca..19f1165bae50 100644 --- a/src/mon/MonitorStore.cc +++ b/src/mon/MonitorStore.cc @@ -340,18 +340,20 @@ int MonitorStore::write_bl_ss(bufferlist& bl, const char *a, const char *b, bool return 0; } -int MonitorStore::put_bl_sn_map(const char *a, map& vals) +int MonitorStore::put_bl_sn_map(const char *a, + map::iterator start, + map::iterator end) { - version_t first = vals.begin()->first; - version_t last = vals.rbegin()->first; + version_t first = start->first; + map::iterator lastp = end; + --lastp; + version_t last = lastp->first; dout(15) << "put_bl_sn_map " << a << "/[" << first << ".." << last << "]" << dendl; // only do a big sync if there are several values. - if (vals.size() < 5) { + if (last - first < 5) { // just do them individually - for (map::iterator p = vals.begin(); - p != vals.end(); - p++) { + for (map::iterator p = start; p != end; ++p) { int err = put_bl_sn(p->second, a, p->first); if (err < 0) return err; @@ -364,9 +366,7 @@ int MonitorStore::put_bl_sn_map(const char *a, map& vals) snprintf(dfn, sizeof(dfn), "%s/%s", dir.c_str(), a); ::mkdir(dfn, 0755); - for (map::iterator p = vals.begin(); - p != vals.end(); - p++) { + for (map::iterator p = start; p != end; ++p) { char tfn[1024], fn[1024]; snprintf(fn, sizeof(fn), "%s/%llu", dfn, (long long unsigned)p->first); @@ -391,9 +391,7 @@ int MonitorStore::put_bl_sn_map(const char *a, map& vals) ::close(dirfd); // rename them all into place - for (map::iterator p = vals.begin(); - p != vals.end(); - p++) { + for (map::iterator p = start; p != end; ++p) { char tfn[1024], fn[1024]; snprintf(fn, sizeof(fn), "%s/%llu", dfn, (long long unsigned)p->first); diff --git a/src/mon/MonitorStore.h b/src/mon/MonitorStore.h index 7c19814fa654..a520e5875760 100644 --- a/src/mon/MonitorStore.h +++ b/src/mon/MonitorStore.h @@ -75,7 +75,9 @@ public: * @param vals - map of int name -> values * @return 0 for success or negative error code */ - int put_bl_sn_map(const char *a, map& vals); + int put_bl_sn_map(const char *a, + map::iterator start, + map::iterator end); int erase_ss(const char *a, const char *b); int erase_sn(const char *a, version_t b) { diff --git a/src/mon/Paxos.cc b/src/mon/Paxos.cc index 869fa1160b0a..68a82fd40f36 100644 --- a/src/mon/Paxos.cc +++ b/src/mon/Paxos.cc @@ -201,31 +201,40 @@ void Paxos::store_state(MMonPaxos *m) last_committed = m->latest_version; first_committed = last_committed; mon->store->put_int(first_committed, machine_name, "first_committed"); + mon->store->put_int(last_committed, machine_name, "last_committed"); + return; } // build map of values to store - map vals; - vals.swap(m->values); - if (vals.size()) { - if (vals.begin()->first > last_committed + 1) { - // drop everything if it starts in the future. - dout(20) << " dropping full set, it starts at " << vals.begin()->first << " > last_committed+1" << dendl; - vals.clear(); - } else { - // drop anything we've already committed - if (vals.begin()->first <= last_committed) { - dout(20) << " dropping leading elements from " << vals.begin()->first << " to last_committed" << dendl; - while (!vals.empty() && vals.begin()->first <= last_committed) { - vals.erase(vals.begin()); - } - } - if (!vals.empty()) { - mon->store->put_bl_sn_map(machine_name, vals); - last_committed = vals.rbegin()->first; - } - } + // we want to write the range [last_committed, m->last_committed] only. + map::iterator start = m->values.begin(); + + if (start != m->values.end() && + start->first > last_committed + 1) { + // ignore everything if values start in the future. + dout(10) << "store_state ignoring all values, they start at " << start->first + << " > last_committed+1" << dendl; + start = m->values.end(); + } + + while (start != m->values.end() && + start->first <= last_committed) + ++start; + + map::iterator end = start; + while (end != m->values.end() && + end->first <= m->last_committed) { + last_committed = end->first; + ++end; + } + + if (start == end) { + dout(10) << "store_state nothing to commit" << dendl; + } else { + dout(10) << "store_state [" << start->first << ".." << last_committed << "]" << dendl; + mon->store->put_bl_sn_map(machine_name, start, end); + mon->store->put_int(last_committed, machine_name, "last_committed"); } - mon->store->put_int(last_committed, machine_name, "last_committed"); }