From 0e137de26e85942f8b40f7b13e564bd4c31b37f9 Mon Sep 17 00:00:00 2001 From: IvanGuan Date: Fri, 4 Jan 2019 12:22:27 +0800 Subject: [PATCH] client: fix fuse client hang because its pipe to mds is not ok If fuse client session had been killed by mds and the mds daemon restart or hot-standby switch happens right away but the client did not receive any message from monitor due to network or other whatever reason untill the mds become active again.Thus cause client didn't do closed_mds_session lead the seession still is STATE_OPEN but client can't send any message to mds because its pipe is not ok.So we should close the stale session so that it can be reopened again. Fixes: http://tracker.ceph.com/issues/36079 Signed-off-by: Guan yunfei --- src/client/Client.cc | 15 ++++++++++++++- src/mds/MDSMap.h | 10 ++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/client/Client.cc b/src/client/Client.cc index d5ac1f2f1d792..df1764add371f 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -2614,13 +2614,14 @@ void Client::handle_fs_map_user(MFSMapUser *m) void Client::handle_mds_map(MMDSMap* m) { + mds_gid_t old_inc, new_inc; if (m->get_epoch() <= mdsmap->get_epoch()) { ldout(cct, 1) << __func__ << " epoch " << m->get_epoch() << " is identical to or older than our " << mdsmap->get_epoch() << dendl; m->put(); return; - } + } ldout(cct, 1) << __func__ << " epoch " << m->get_epoch() << dendl; @@ -2666,6 +2667,13 @@ void Client::handle_mds_map(MMDSMap* m) if (!mdsmap->is_up(mds)) { session->con->mark_down(); } else if (mdsmap->get_addrs(mds) != session->addrs) { + old_inc = oldmap->get_incarnation(mds); + new_inc = mdsmap->get_incarnation(mds); + if (old_inc != new_inc) { + ldout(cct, 1) << "mds incarnation changed from " + << old_inc << " to " << new_inc << dendl; + oldstate = MDSMap::STATE_NULL; + } session->con->mark_down(); session->addrs = mdsmap->get_addrs(mds); // When new MDS starts to take over, notify kernel to trim unused entries @@ -2676,6 +2684,11 @@ void Client::handle_mds_map(MMDSMap* m) continue; // no change session->mds_state = newstate; + if (old_inc != new_inc && newstate > MDSMap::STATE_RECONNECT) { + // missed reconnect close the session so that it can be reopened + _closed_mds_session(session); + continue; + } if (newstate == MDSMap::STATE_RECONNECT) { session->con = messenger->connect_to_mds(session->addrs); send_reconnect(session); diff --git a/src/mds/MDSMap.h b/src/mds/MDSMap.h index 37a26e60028b1..85894aeffc460 100644 --- a/src/mds/MDSMap.h +++ b/src/mds/MDSMap.h @@ -616,6 +616,16 @@ class MDSMap { } } + /** + * Get MDS rank incarnation if the rank is up, else -1 + */ + mds_gid_t get_incarnation(mds_rank_t m) const { + std::map::const_iterator u = up.find(m); + if (u == up.end()) + return MDS_GID_NONE; + return (mds_gid_t)get_inc_gid(u->second); + } + int get_inc_gid(mds_gid_t gid) const { auto mds_info_entry = mds_info.find(gid); if (mds_info_entry != mds_info.end())