From: Yan, Zheng Date: Fri, 4 May 2018 03:11:35 +0000 (+0800) Subject: mds: allow client to specify its session timeout X-Git-Tag: v12.2.13~44^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=8eedc498b8aa69a837a9c2b28b198aef75ecda42;p=ceph.git mds: allow client to specify its session timeout This is for ganesha client (it is expected to be reclaimed if it dies) The default session timeout may be too short to reliably get ganesha back up. Signed-off-by: "Yan, Zheng" (cherry picked from commit eb4c36bf23f32cf9117d62660a4919dcfe80baa5) Conflicts: src/client/Client.cc src/client/Client.h src/include/cephfs/libcephfs.h src/libcephfs.cc src/mds/Server.cc --- diff --git a/src/client/Client.cc b/src/client/Client.cc index 1e6a0d9eb38..35ea7100eae 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -14081,6 +14081,15 @@ void Client::clear_filer_flags(int flags) objecter->clear_global_op_flag(flags); } +// called before mount. 0 means infinite +void Client::set_session_timeout(unsigned timeout) +{ + Mutex::Locker l(client_lock); + assert(initialized); + + metadata["timeout"] = stringify(timeout); +} + /** * This is included in cap release messages, to cause * the MDS to wait until this OSD map epoch. It is necessary diff --git a/src/client/Client.h b/src/client/Client.h index 4a304466a40..32b7fbda3a6 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -956,6 +956,8 @@ public: bool require_mds=false); void unmount(); + void set_session_timeout(unsigned timeout); + int mds_command( const std::string &mds_spec, const std::vector& cmd, diff --git a/src/include/cephfs/libcephfs.h b/src/include/cephfs/libcephfs.h index cb90130fbce..4fa1af40a0f 100644 --- a/src/include/cephfs/libcephfs.h +++ b/src/include/cephfs/libcephfs.h @@ -1655,6 +1655,15 @@ int ceph_set_deleg_timeout(struct ceph_mount_info *cmount, uint32_t timeout); */ int ceph_ll_delegation(struct ceph_mount_info *cmount, Fh *fh, unsigned int cmd, ceph_deleg_cb_t cb, void *priv); + +/** + * Set ceph client session timeout + * @param cmount the ceph mount handle to use. + * @param timeout the timeout to set + * + * Must be called before mount. + */ +void ceph_set_session_timeout(struct ceph_mount_info *cmount, unsigned timeout); #ifdef __cplusplus } #endif diff --git a/src/libcephfs.cc b/src/libcephfs.cc index 6b99359d8c8..2c8e65e4aa9 100644 --- a/src/libcephfs.cc +++ b/src/libcephfs.cc @@ -1771,3 +1771,8 @@ extern "C" int ceph_set_deleg_timeout(class ceph_mount_info *cmount, uint32_t ti return -ENOTCONN; return cmount->get_client()->set_deleg_timeout(timeout); } + +extern "C" void ceph_set_session_timeout(class ceph_mount_info *cmount, unsigned timeout) +{ + cmount->get_client()->set_session_timeout(timeout); +} diff --git a/src/mds/Server.cc b/src/mds/Server.cc index aabf1c3f14a..6c331455337 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -767,6 +767,8 @@ void Server::find_idle_sessions() double queue_max_age = mds->get_dispatch_queue_max_age(ceph_clock_now()); double cutoff = queue_max_age + mds->mdsmap->get_session_timeout(); + std::vector to_evict; + const auto sessions_p1 = mds->sessionmap.by_state.find(Session::STATE_OPEN); if (sessions_p1 != mds->sessionmap.by_state.end() && !sessions_p1->second->empty()) { std::vector new_stale; @@ -788,9 +790,29 @@ void Server::find_idle_sessions() } } - dout(10) << "new stale session " << session->info.inst - << " last renewed caps " << last_cap_renew_span << "s ago" << dendl; - new_stale.push_back(session); + auto it = session->info.client_metadata.find("timeout"); + if (it != session->info.client_metadata.end()) { + unsigned timeout = strtoul(it->second.c_str(), nullptr, 0); + if (timeout == 0) { + dout(10) << "skipping session " << session->info.inst + << ", infinite timeout specified" << dendl; + continue; + } + double cutoff = queue_max_age + timeout; + if (last_cap_renew_span < cutoff) { + dout(10) << "skipping session " << session->info.inst + << ", timeout (" << timeout << ") specified" + << " and renewed caps recently (" << last_cap_renew_span << "s ago)" << dendl; + continue; + } + + // do not go through stale, evict it directly. + to_evict.push_back(session); + } else { + dout(10) << "new stale session " << session->info.inst + << " last renewed caps " << last_cap_renew_span << "s ago" << dendl; + new_stale.push_back(session); + } } for (auto session : new_stale) { @@ -818,33 +840,31 @@ void Server::find_idle_sessions() } // Collect a list of sessions exceeding the autoclose threshold - std::vector to_evict; const auto sessions_p2 = mds->sessionmap.by_state.find(Session::STATE_STALE); - if (sessions_p2 == mds->sessionmap.by_state.end() || sessions_p2->second->empty()) { - return; + if (sessions_p2 != mds->sessionmap.by_state.end() && !sessions_p2->second->empty()) { + for (auto session : *(sessions_p2->second)) { + assert(session->is_stale()); + auto last_cap_renew_span = std::chrono::duration(now - session->last_cap_renew).count(); + if (last_cap_renew_span < cutoff) { + dout(20) << "oldest stale session is " << session->info.inst + << " and recently renewed caps " << last_cap_renew_span << "s ago" << dendl; + break; + } + to_evict.push_back(session); + } } - const auto &stale_sessions = sessions_p2->second; - assert(stale_sessions != nullptr); - for (const auto &session: *stale_sessions) { - auto last_cap_renew_span = std::chrono::duration(now-session->last_cap_renew).count(); + for (auto session: to_evict) { if (session->is_importing()) { - dout(10) << "stopping at importing session " << session->info.inst << dendl; - break; - } - assert(session->is_stale()); - if (last_cap_renew_span < cutoff) { - dout(20) << "oldest stale session is " << session->info.inst << " and recently renewed caps " << last_cap_renew_span << "s ago" << dendl; - break; + dout(10) << "skipping session " << session->info.inst << ", it's being imported" << dendl; + continue; } - to_evict.push_back(session); - } - - for (const auto &session: to_evict) { - auto last_cap_renew_span = std::chrono::duration(now-session->last_cap_renew).count(); - mds->clog->warn() << "evicting unresponsive client " << *session << ", after " << last_cap_renew_span << " seconds"; - dout(10) << "autoclosing stale session " << session->info.inst << " last renewed caps " << last_cap_renew_span << "s ago" << dendl; + auto last_cap_renew_span = std::chrono::duration(now - session->last_cap_renew).count(); + mds->clog->warn() << "evicting unresponsive client " << *session + << ", after " << last_cap_renew_span << " seconds"; + dout(10) << "autoclosing stale session " << session->info.inst + << " last renewed caps " << last_cap_renew_span << "s ago" << dendl; if (g_conf->mds_session_blacklist_on_timeout) { std::stringstream ss;