]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: allow client to specify its session timeout
authorYan, Zheng <zyan@redhat.com>
Fri, 4 May 2018 03:11:35 +0000 (11:11 +0800)
committerYan, Zheng <zyan@redhat.com>
Tue, 12 Nov 2019 13:48:38 +0000 (21:48 +0800)
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" <zyan@redhat.com>
(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

src/client/Client.cc
src/client/Client.h
src/include/cephfs/libcephfs.h
src/libcephfs.cc
src/mds/Server.cc

index 1e6a0d9eb38135aea6dab2c637ba7c260016890c..35ea7100eae8388b52552a57a328c379e3ea4980 100644 (file)
@@ -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
index 4a304466a40ccb8f26af019f03a11a98b5f298d8..32b7fbda3a69e5c27f85f2741179dd3bd79664b0 100644 (file)
@@ -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<std::string>& cmd,
index cb90130fbce6f2d6750c4187e53908a652b7672e..4fa1af40a0fe67298f01e187265ec4fee5d2df7c 100644 (file)
@@ -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
index 6b99359d8c83b94f0319c64b99ca7c726abab037..2c8e65e4aa9e3a25923b54af3b14a9e2cab4cae5 100644 (file)
@@ -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);
+}
index aabf1c3f14ada453addcd057c175c0afc769851a..6c3314553378586c9376d01fd56690c9dddc552d 100644 (file)
@@ -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<Session*> 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<Session*> 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<Session *> 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<double>(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<double>(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<double>(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<double>(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;