mirror of
https://github.com/ceph/ceph
synced 2025-01-01 08:32:24 +00:00
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:
commit
ebb26940fb
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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; }
|
||||
|
Loading…
Reference in New Issue
Block a user