]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: don't mark unresponsive sessions holding no caps stale
authorYan, Zheng <zyan@redhat.com>
Mon, 17 Jun 2019 04:58:58 +0000 (12:58 +0800)
committerYan, Zheng <zyan@redhat.com>
Mon, 21 Oct 2019 02:52:22 +0000 (10:52 +0800)
When an unresponsive MDS session holds no caps, do not mark it stale
even after session_timeout; at session_autoclose, evict it directly.

Fixes: http://tracker.ceph.com/issues/17854
Signed-off-by: Rishabh Dave <ridave@redhat.com>
(cherry picked from commit 98af31d10f362c05ea8ed57495973b08599431e7)

 Conflicts:
src/mds/Server.cc

src/mds/Locker.cc
src/mds/Locker.h
src/mds/Server.cc
src/mds/SessionMap.h

index 6126f31931498ba61a0042296febd33a990dbdc4..4af5d42e08ca0df13c514223ea5a3cb00c1c0ae0 100644 (file)
@@ -2669,6 +2669,14 @@ void Locker::mark_need_snapflush_inode(CInode *in)
   }
 }
 
+bool Locker::is_revoking_any_caps_from(client_t client)
+{
+  auto it = revoking_caps_by_client.find(client);
+  if (it == revoking_caps_by_client.end())
+    return false;
+  return !it->second.empty();
+}
+
 void Locker::_do_null_snapflush(CInode *head_in, client_t client, snapid_t last)
 {
   dout(10) << "_do_null_snapflush client." << client << " on " << *head_in << dendl;
index ce9aeb22044bdb3d776c92abf74e54b6329f541f..5f8fa9c720f668081c49956ca301cae1fd07954d 100644 (file)
@@ -214,6 +214,7 @@ protected:
 public:
   void snapflush_nudge(CInode *in);
   void mark_need_snapflush_inode(CInode *in);
+  bool is_revoking_any_caps_from(client_t client);
 
   // local
 public:
index 82ad9c8c92f4d114f82b16f858ffbdc00d26d7d8..680a479e9512b3b91f836badb07063d23d50d2c9 100644 (file)
@@ -782,6 +782,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;
@@ -803,6 +805,21 @@ void Server::find_idle_sessions()
        }
       }
 
+      if (last_cap_renew_span >= mds->mdsmap->get_session_autoclose()) {
+       dout(20) << "evicting session " << session->info.inst << " since autoclose "
+                   "has arrived" << dendl;
+       // evict session without marking it stale
+       to_evict.push_back(session);
+       continue;
+      }
+
+      if (!session->is_any_flush_waiter() &&
+         !mds->locker->is_revoking_any_caps_from(session->get_client())) {
+       dout(20) << "deferring marking session " << session->info.inst << " stale "
+                   "since it holds no caps" << dendl;
+       continue;
+      }
+
       dout(10) << "new stale session " << session->info.inst
               << " last renewed caps " << last_cap_renew_span << "s ago" << dendl;
       new_stale.push_back(session);
@@ -833,38 +850,35 @@ 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;
-      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);
     }
index a404e19813c6e7e6eba5ee953a3ce9ef5ca8fbe9..d528205c5b2c7b6ebb43d79196ad2c46cc1e67fc 100644 (file)
@@ -271,13 +271,19 @@ public:
   void touch_cap(Capability *cap) {
     caps.push_front(&cap->item_session_caps);
   }
+
   void touch_cap_bottom(Capability *cap) {
     caps.push_back(&cap->item_session_caps);
   }
+
   void touch_lease(ClientLease *r) {
     leases.push_back(&r->item_session_lease);
   }
 
+  bool is_any_flush_waiter() {
+    return !waitfor_flush.empty();
+  }
+
   // -- leases --
   uint32_t lease_seq;