]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: fix reconnect race
authorSage Weil <sage@newdream.net>
Fri, 20 Nov 2009 21:03:41 +0000 (13:03 -0800)
committerSage Weil <sage@newdream.net>
Fri, 20 Nov 2009 21:40:38 +0000 (13:40 -0800)
Don't ignore client replay or session msgs if we are
moving to reconnect state.  The client may get the mdsmap
before us and send things our way, so take them if we
are reconnect, or if we want reconnect.

src/mds/MDS.cc
src/mds/MDS.h
src/mds/Server.cc

index 234e5e0a0343cd63acc52cb50ab4f81dac01bc24..2e63a66b84472dd8389d2e36addb014724ad7bd0 100644 (file)
@@ -994,6 +994,7 @@ void MDS::reconnect_start()
 {
   dout(1) << "reconnect_start" << dendl;
   server->reconnect_clients();
+  finish_contexts(waiting_for_reconnect);
 }
 void MDS::reconnect_done()
 {
index 9a919879bb14068171c6d18b9831aa95dfba612c..5c296417162c3c2816524f929c30974d25f37773 100644 (file)
@@ -184,7 +184,7 @@ class MDS : public Dispatcher {
   int state;         // my confirmed state
   int want_state;    // the state i want
 
-  list<Context*> waiting_for_active, waiting_for_replay;
+  list<Context*> waiting_for_active, waiting_for_replay, waiting_for_reconnect;
   list<Context*> replay_queue;
   map<int, list<Context*> > waiting_for_active_peer;
   list<Context*> waiting_for_nolaggy;
@@ -203,11 +203,15 @@ class MDS : public Dispatcher {
   void wait_for_replay(Context *c) { 
     waiting_for_replay.push_back(c); 
   }
+  void wait_for_reconnect(Context *c) {
+    waiting_for_reconnect.push_back(c);
+  }
   void enqueue_replay(Context *c) {
     replay_queue.push_back(c);
   }
 
   int get_state() { return state; } 
+  int get_want_state() { return want_state; } 
   bool is_creating() { return state == MDSMap::STATE_CREATING; }
   bool is_starting() { return state == MDSMap::STATE_STARTING; }
   bool is_standby()  { return state == MDSMap::STATE_STANDBY; }
index 5d07b7e4567c37537947f262673b6bc61fa419e0..a8faa79271ec685c6e2ab2b21c4b565749ef3334 100644 (file)
@@ -101,7 +101,7 @@ void Server::dispatch(Message *m)
   // active?
   if (!mds->is_active() && 
       !(mds->is_stopping() && m->get_orig_source().is_mds())) {
-    if (mds->is_reconnect() &&
+    if ((mds->is_reconnect() || mds->get_want_state() == CEPH_MDS_STATE_RECONNECT) &&
        m->get_type() == CEPH_MSG_CLIENT_REQUEST &&
        ((MClientRequest*)m)->is_replay()) {
       dout(3) << "queuing replayed op" << dendl;
@@ -457,6 +457,11 @@ void Server::handle_client_reconnect(MClientReconnect *m)
   int from = m->get_source().num();
   Session *session = get_session(m);
 
+  if (!mds->is_reconnect() && mds->get_want_state() == CEPH_MDS_STATE_RECONNECT) {
+    dout(10) << " we're almost in reconnect state (mdsmap delivery race?); waiting" << dendl;
+    mds->wait_for_reconnect(new C_MDS_RetryMessage(mds, m));
+    return;
+  }
   if (!mds->is_reconnect() || !session) {
     stringstream ss;
     utime_t delay = g_clock.now();