Merge PR #25536 into master

* refs/pull/25536/head:
	mds: don't wait for snapclient sync when handling reconnect
	mds: extend reconnect period when mds is busy
	mds: renew client session when receiving any message
	mds: use mono_clock for reconnect timeout

Reviewed-by: Patrick Donnelly <pdonnell@redhat.com>
This commit is contained in:
Patrick Donnelly 2018-12-21 17:16:11 -08:00
commit ebb26940fb
No known key found for this signature in database
GPG Key ID: 3A2A7E25BEA8AADB
4 changed files with 87 additions and 58 deletions

View File

@ -966,9 +966,14 @@ void MDSRank::ProgressThread::shutdown()
bool MDSRankDispatcher::ms_dispatch(const Message::const_ref &m)
{
bool ret;
if (m->get_source().is_client()) {
Session *session = static_cast<Session*>(m->get_connection()->get_priv().get());
if (session)
session->last_seen = Session::clock::now();
}
inc_dispatch_depth();
ret = _dispatch(m, true);
bool ret = _dispatch(m, true);
dec_dispatch_depth();
return ret;
}
@ -1293,6 +1298,7 @@ Session *MDSRank::get_session(const Message::const_ref &m)
session->preopen_out_queue.pop_front();
}
imported_session->auth_caps = session->auth_caps;
imported_session->last_seen = session->last_seen;
ceph_assert(session->get_nref() == 1);
imported_session->get_connection()->set_priv(imported_session->get());
session = imported_session;

View File

@ -922,7 +922,16 @@ void Server::find_idle_sessions()
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;
break;
}
if (session->last_seen > session->last_cap_renew) {
last_cap_renew_span = std::chrono::duration<double>(now - session->last_seen).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");
@ -1155,7 +1164,7 @@ void Server::reconnect_clients(MDSInternalContext *reconnect_done_)
// clients will get the mdsmap and discover we're reconnecting via the monitor.
reconnect_start = ceph_clock_now();
reconnect_start = now;
dout(1) << "reconnect_clients -- " << client_reconnect_gather.size() << " sessions" << dendl;
mds->sessionmap.dump();
}
@ -1173,8 +1182,7 @@ void Server::handle_client_reconnect(const MClientReconnect::const_ref &m)
return;
}
utime_t delay = ceph_clock_now();
delay -= reconnect_start;
auto delay = std::chrono::duration<double>(clock::now() - reconnect_start).count();
dout(10) << " reconnect_start " << reconnect_start << " delay " << delay << dendl;
bool deny = false;
@ -1221,13 +1229,6 @@ void Server::handle_client_reconnect(const MClientReconnect::const_ref &m)
return;
}
// opening snaprealm past parents needs to use snaptable
if (!mds->snapclient->is_synced()) {
dout(10) << " snaptable isn't synced, waiting" << dendl;
mds->snapclient->wait_for_sync(new C_MDS_RetryMessage(mds, m));
return;
}
// notify client of success with an OPEN
auto reply = MClientSession::create(CEPH_SESSION_OPEN);
if (session->info.has_feature(CEPHFS_FEATURE_MIMIC))
@ -1290,6 +1291,8 @@ void Server::handle_client_reconnect(const MClientReconnect::const_ref &m)
}
mdcache->rejoin_recovered_client(session->get_client(), session->info.inst);
reconnect_last_seen = clock::now();
// remove from gather set
client_reconnect_gather.erase(from);
if (client_reconnect_gather.empty())
@ -1386,63 +1389,81 @@ void Server::reconnect_gather_finish()
void Server::reconnect_tick()
{
if (reconnect_evicting) {
dout(4) << "reconnect_tick: waiting for evictions" << dendl;
dout(7) << "reconnect_tick: waiting for evictions" << dendl;
return;
}
utime_t reconnect_end = reconnect_start;
reconnect_end += g_conf()->mds_reconnect_timeout;
if (ceph_clock_now() >= reconnect_end &&
!client_reconnect_gather.empty()) {
dout(10) << "reconnect timed out" << dendl;
if (client_reconnect_gather.empty())
return;
// If we're doing blacklist evictions, use this to wait for them before
// proceeding to reconnect_gather_finish
MDSGatherBuilder gather(g_ceph_context);
auto now = clock::now();
auto elapse1 = std::chrono::duration<double>(now - reconnect_start).count();
if (elapse1 < g_conf()->mds_reconnect_timeout)
return;
for (set<client_t>::iterator p = client_reconnect_gather.begin();
p != client_reconnect_gather.end();
++p) {
Session *session = mds->sessionmap.get_session(entity_name_t::CLIENT(p->v));
ceph_assert(session);
vector<Session*> remaining_sessions;
remaining_sessions.reserve(client_reconnect_gather.size());
for (auto c : client_reconnect_gather) {
Session *session = mds->sessionmap.get_session(entity_name_t::CLIENT(c.v));
ceph_assert(session);
remaining_sessions.push_back(session);
// client re-sends cap flush messages before the reconnect message
if (session->last_seen > reconnect_last_seen)
reconnect_last_seen = session->last_seen;
}
// Keep sessions that have specified timeout. These sessions will prevent
// mds from going to active. MDS goes to active after they all have been
// killed or reclaimed.
if (session->info.client_metadata.find("timeout") !=
session->info.client_metadata.end()) {
dout(1) << "reconnect keeps " << session->info.inst << ", need to be reclaimed" << dendl;
client_reclaim_gather.insert(session->get_client());
continue;
}
auto elapse2 = std::chrono::duration<double>(now - reconnect_last_seen).count();
if (elapse2 < g_conf()->mds_reconnect_timeout / 2) {
dout(7) << "reconnect_tick: last seen " << elapse2
<< " seconds ago, extending reconnect interval" << dendl;
return;
}
dout(1) << "reconnect gives up on " << session->info.inst << dendl;
dout(7) << "reconnect timed out, " << remaining_sessions.size()
<< " clients have not reconnected in time" << dendl;
mds->clog->warn() << "evicting unresponsive client " << *session
<< ", after waiting " << g_conf()->mds_reconnect_timeout
<< " seconds during MDS startup";
// If we're doing blacklist evictions, use this to wait for them before
// proceeding to reconnect_gather_finish
MDSGatherBuilder gather(g_ceph_context);
if (g_conf()->mds_session_blacklist_on_timeout) {
std::stringstream ss;
mds->evict_client(session->get_client().v, false, true, ss,
gather.new_sub());
} else {
kill_session(session, NULL);
}
failed_reconnects++;
for (auto session : remaining_sessions) {
// Keep sessions that have specified timeout. These sessions will prevent
// mds from going to active. MDS goes to active after they all have been
// killed or reclaimed.
if (session->info.client_metadata.find("timeout") !=
session->info.client_metadata.end()) {
dout(1) << "reconnect keeps " << session->info.inst
<< ", need to be reclaimed" << dendl;
client_reclaim_gather.insert(session->get_client());
continue;
}
client_reconnect_gather.clear();
if (gather.has_subs()) {
dout(1) << "reconnect will complete once clients are evicted" << dendl;
gather.set_finisher(new MDSInternalContextWrapper(mds, new FunctionContext(
[this](int r){reconnect_gather_finish();})));
gather.activate();
reconnect_evicting = true;
dout(1) << "reconnect gives up on " << session->info.inst << dendl;
mds->clog->warn() << "evicting unresponsive client " << *session
<< ", after waiting " << elapse1
<< " seconds during MDS startup";
if (g_conf()->mds_session_blacklist_on_timeout) {
std::stringstream ss;
mds->evict_client(session->get_client().v, false, true, ss,
gather.new_sub());
} else {
reconnect_gather_finish();
kill_session(session, NULL);
}
failed_reconnects++;
}
client_reconnect_gather.clear();
if (gather.has_subs()) {
dout(1) << "reconnect will complete once clients are evicted" << dendl;
gather.set_finisher(new MDSInternalContextWrapper(mds, new FunctionContext(
[this](int r){reconnect_gather_finish();})));
gather.activate();
reconnect_evicting = true;
} else {
reconnect_gather_finish();
}
}

View File

@ -96,7 +96,8 @@ private:
int failed_reconnects;
bool reconnect_evicting; // true if I am waiting for evictions to complete
// before proceeding to reconnect_gather_finish
utime_t reconnect_start;
time reconnect_start = clock::zero();
time reconnect_last_seen = clock::zero();
set<client_t> client_reconnect_gather; // clients i need a reconnect msg from.
feature_bitset_t supported_features;

View File

@ -250,6 +250,7 @@ public:
xlist<Capability*> caps; // inodes with caps; front=most recently used
xlist<ClientLease*> leases; // metadata leases to clients
time last_cap_renew = clock::zero();
time last_seen = clock::zero();
public:
version_t inc_push_seq() { return ++cap_push_seq; }