]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
client: Unify session close handling
authorSam Lang <sam.lang@inktank.com>
Thu, 4 Apr 2013 20:59:56 +0000 (15:59 -0500)
committerSam Lang <sam.lang@inktank.com>
Thu, 11 Apr 2013 15:25:46 +0000 (10:25 -0500)
If mds failure causes client reconnect while the
client is unmounting, the client will send a session
close request to the mds even if there are outstanding
inodes in the cache waiting to receive flush_acks.   This
causes the mds to send back a session close message and
the client closes the connection, so that when the mds tries
to send flush acks back to the client, they get dropped, resulting
in the client hanging on unmount.  The pattern for this bug is:

1. mds restart
2. client sends session open request
3. client unmount sets unmounting flag and waits for flush_acks
4. mds sends session open reply
5. client sends session close request (because its unmounting)
6. mds sends session close, client closes connection
7. mds tries to send flush_acks, but drops them because the connection
is gone

This patch unifies the session close handling so that the client
only sends a session close in unmount once all flush acks have been
received.  If the mds restarts during session close, the reconnect
logic will kick the session close waiter so that session close requests
are re-sent for session close replies not yet received.

Signed-off-by: Sam Lang <sam.lang@inktank.com>
src/client/Client.cc

index 420c3ad00f2975c51bff384f6af6344392edcc9e..aae22ffa980dbf319223b14b72d834bb303d31c7 100644 (file)
@@ -1534,9 +1534,7 @@ void Client::handle_client_session(MClientSession *m)
   case CEPH_SESSION_OPEN:
     renew_caps(session);
     session->state = MetaSession::STATE_OPEN;
-    if (unmounting) {
-      _close_mds_session(session);
-    } else {
+    if (!unmounting) {
       connect_mds_targets(from);
     }
     signal_cond_list(session->waiting_for_open);
@@ -1966,6 +1964,8 @@ void Client::send_reconnect(MetaSession *session)
   resend_unsafe_requests(session);
 
   messenger->send_message(m, session->con);
+
+  mount_cond.Signal();
 }
 
 
@@ -3778,17 +3778,17 @@ void Client::unmount()
   }
 
   
-  // send session closes!
-  for (map<int,MetaSession*>::iterator p = mds_sessions.begin();
-       p != mds_sessions.end();
-       ++p) {
-    if (p->second->state != MetaSession::STATE_CLOSING) {
-      _close_mds_session(p->second);
+  while (!mds_sessions.empty()) {
+    // send session closes!
+    for (map<int,MetaSession*>::iterator p = mds_sessions.begin();
+       p != mds_sessions.end();
+       ++p) {
+      if (p->second->state != MetaSession::STATE_CLOSING) {
+       _close_mds_session(p->second);
+      }
     }
-  }
 
-  // wait for sessions to close
-  while (!mds_sessions.empty()) {
+    // wait for sessions to close
     ldout(cct, 2) << "waiting for " << mds_sessions.size() << " mds sessions to close" << dendl;
     mount_cond.Wait(client_lock);
   }