summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Lang <sam.lang@inktank.com>2013-04-04 15:59:56 -0500
committerSam Lang <sam.lang@inktank.com>2013-04-11 10:25:46 -0500
commit3a1cf53c30b67efbec46f893b3248939ca6d610c (patch)
tree5f161fabbc6d40df0562c7c43ed9a6fbb6c3f15a
parenta3298713bb0078e53071b702cba4530436b7a946 (diff)
downloadceph-3a1cf53c30b67efbec46f893b3248939ca6d610c.tar.gz
client: Unify session close handling
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>
-rw-r--r--src/client/Client.cc24
1 files changed, 12 insertions, 12 deletions
diff --git a/src/client/Client.cc b/src/client/Client.cc
index 420c3ad00f2..aae22ffa980 100644
--- a/src/client/Client.cc
+++ b/src/client/Client.cc
@@ -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);
}