]> 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>
Wed, 26 Sep 2018 13:42:54 +0000 (21:42 +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>
src/client/Client.cc
src/client/Client.h
src/include/cephfs/libcephfs.h
src/libcephfs.cc
src/mds/Server.cc

index a8534663ad28d765dc20a5b5210c1666a3a6bffe..173df17ab42a95cdb81017e5cc92a24584937232 100644 (file)
@@ -14206,6 +14206,15 @@ void Client::set_uuid(const std::string& uuid)
   _close_sessions();
 }
 
+// called before mount. 0 means infinite
+void Client::set_session_timeout(unsigned timeout)
+{
+  Mutex::Locker l(client_lock);
+  assert(initialized);
+
+  metadata["timeout"] = stringify(timeout);
+}
+
 // called before mount
 int Client::start_reclaim(const std::string& uuid, unsigned flags,
                          const std::string& fs_name)
index b8c4d7cc044ae0bd0eb613f9e253198bcae38649..3aa3a03d8a231f0200eb0cacdcae5c6226e317ed 100644 (file)
@@ -298,6 +298,7 @@ public:
   void abort_conn();
 
   void set_uuid(const std::string& uuid);
+  void set_session_timeout(unsigned timeout);
   int start_reclaim(const std::string& uuid, unsigned flags,
                    const std::string& fs_name);
   void finish_reclaim();
index 4573fa5ce84437859e5a50876dbd722d669e1af5..31e319509737f65cd05e427d1781a67dbf115684 100644 (file)
@@ -1784,6 +1784,15 @@ mode_t ceph_umask(struct ceph_mount_info *cmount, mode_t mode);
  */
 void ceph_set_uuid(struct ceph_mount_info *cmount, const char *uuid);
 
+/**
+ * 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);
+
 /**
  * Start to reclaim states of other client
  * @param cmount the ceph mount handle to use.
index 9d27e23984a04ec04e078489168fde0724660124..0d8ad43f9f5817991904695ec1b334c34f698531 100644 (file)
@@ -1918,6 +1918,11 @@ extern "C" int ceph_set_deleg_timeout(class ceph_mount_info *cmount, uint32_t ti
   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);
+}
+
 extern "C" void ceph_set_uuid(class ceph_mount_info *cmount, const char *uuid)
 {
   cmount->get_client()->set_uuid(std::string(uuid));
index 8ba4d7fa6f97905b88d8e8c65881d476c12088f3..956a2adbe65419a48c33d8a7dabc2c27d6532815 100644 (file)
@@ -891,21 +891,53 @@ void Server::find_idle_sessions()
   //  (caps go stale, lease die)
   double queue_max_age = mds->get_dispatch_queue_max_age(ceph_clock_now());
   double cutoff = queue_max_age + mds->mdsmap->get_session_timeout();
-  while (1) {
-    Session *session = mds->sessionmap.get_oldest_session(Session::STATE_OPEN);
-    if (!session) break;
-    auto last_cap_renew_span = std::chrono::duration<double>(now-session->last_cap_renew).count();
-    if (last_cap_renew_span < cutoff) {
-      dout(20) << "laggiest active session is " << session->info.inst << " and renewed caps recently (" << last_cap_renew_span << "s ago)" << dendl;
-      break;
+
+  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;
+
+    for (auto session : *(sessions_p1->second)) {
+      auto last_cap_renew_span = std::chrono::duration<double>(now - session->last_cap_renew).count();
+      if (last_cap_renew_span < cutoff) {
+       dout(20) << "laggiest active session is " << session->info.inst
+                << " and renewed caps recently (" << last_cap_renew_span << "s ago)" << dendl;
+       continue;
+      }
+
+      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);
+      }
     }
 
-    dout(10) << "new stale session " << session->info.inst << " last renewed caps " << last_cap_renew_span << "s ago" << dendl;
-    mds->sessionmap.set_state(session, Session::STATE_STALE);
-    mds->locker->revoke_stale_caps(session);
-    mds->locker->remove_stale_leases(session);
-    mds->send_message_client(MClientSession::create(CEPH_SESSION_STALE, session->get_push_seq()), session);
-    finish_flush_session(session, session->get_push_seq());
+    for (auto session : new_stale) {
+      mds->sessionmap.set_state(session, Session::STATE_STALE);
+      mds->locker->revoke_stale_caps(session);
+      mds->locker->remove_stale_leases(session);
+      mds->send_message_client(MClientSession::create(CEPH_SESSION_STALE, session->get_push_seq()), session);
+      finish_flush_session(session, session->get_push_seq());
+    }
   }
 
   // autoclose
@@ -924,38 +956,35 @@ void Server::find_idle_sessions()
   }
 
   // Collect a list of sessions exceeding the autoclose threshold
-  std::vector<Session *> to_evict;
-  const auto sessions_p = mds->sessionmap.by_state.find(Session::STATE_STALE);
-  if (sessions_p == mds->sessionmap.by_state.end() || sessions_p->second->empty()) {
-    return;
+  const auto sessions_p2 = mds->sessionmap.by_state.find(Session::STATE_STALE);
+  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_p->second;
-  ceph_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;
-    }
-    ceph_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;
-      mds->evict_client(session->get_client().v, false, true,
-                        ss, nullptr);
+      mds->evict_client(session->get_client().v, false, true, ss, nullptr);
     } else {
       kill_session(session, NULL);
     }