if (is_reconnect())
server->reconnect_tick();
+ if (is_clientreplay())
+ maybe_clientreplay_done();
if (is_active()) {
balancer->tick();
return true;
}
- // done with all client replayed requests?
- if (is_clientreplay() &&
- mdcache->is_open() &&
- replay_queue.empty() &&
- beacon.get_want_state() == MDSMap::STATE_CLIENTREPLAY) {
- int num_requests = mdcache->get_num_client_requests();
- dout(10) << " still have " << num_requests << " active replay requests" << dendl;
- if (num_requests == 0)
- clientreplay_done();
- }
-
// hack: thrash exports
static utime_t start;
utime_t now = ceph_clock_now();
return;
}
- if (replay_queue.empty())
+ if (replay_queue.empty() && !server->get_num_pending_reclaim())
request_state(MDSMap::STATE_ACTIVE);
else
request_state(MDSMap::STATE_CLIENTREPLAY);
bool MDSRank::queue_one_replay()
{
- if (replay_queue.empty()) {
+ if (!replay_queue.empty()) {
+ queue_waiter(replay_queue.front());
+ replay_queue.pop_front();
+ return true;
+ }
+ // don't go to active if there are session waiting for being reclaimed
+ if (!server->get_num_pending_reclaim())
mdlog->wait_for_safe(new C_MDS_VoidFn(this, &MDSRank::clientreplay_done));
- return false;
+ return false;
+}
+
+void MDSRank::maybe_clientreplay_done()
+{
+ if (is_clientreplay() &&
+ get_want_state() == MDSMap::STATE_CLIENTREPLAY &&
+ replay_queue.empty()) {
+ int num_requests = mdcache->get_num_client_requests();
+ int num_reclaim = server->get_num_pending_reclaim();
+ if (!num_requests && !num_reclaim) {
+ clientreplay_done();
+ } else {
+ dout(1) << " still have " << num_requests << " active replay requests, "
+ << num_reclaim << " sessions need to be reclaimed" << dendl;
+ }
}
- queue_waiter(replay_queue.front());
- replay_queue.pop_front();
- return true;
}
void MDSRank::clientreplay_done()
}
bool queue_one_replay();
+ void maybe_clientreplay_done();
void set_osd_epoch_barrier(epoch_t e);
epoch_t get_osd_epoch_barrier() const {return osd_epoch_barrier;}
dout(20) << " killing client lease of " << *dn << dendl;
dn->remove_client_lease(r, mds->locker);
}
- if (client_reconnect_gather.count(session->info.get_client())) {
+ if (client_reconnect_gather.erase(session->info.get_client())) {
dout(20) << " removing client from reconnect set" << dendl;
- client_reconnect_gather.erase(session->info.get_client());
-
if (client_reconnect_gather.empty()) {
dout(7) << " client " << session->info.inst << " was last reconnect, finishing" << dendl;
reconnect_gather_finish();
}
}
+ if (client_reclaim_gather.erase(session->info.get_client())) {
+ dout(20) << " removing client from reclaim set" << dendl;
+ if (client_reclaim_gather.empty()) {
+ dout(7) << " client " << session->info.inst << " was last reclaimed, finishing" << dendl;
+ mds->maybe_clientreplay_done();
+ }
+ }
if (session->is_closing()) {
// mark con disposable. if there is a fault, we will get a
{
reconnect_done = reconnect_done_;
+ auto now = clock::now();
set<Session*> sessions;
mds->sessionmap.get_client_session_set(sessions);
for (auto session : sessions) {
- if (session->is_open())
- client_reconnect_gather.insert(session->get_client());
+ if (session->is_open()) {
+ client_reconnect_gather.insert(session->get_client());
+ session->last_cap_renew = now;
+ }
}
if (client_reconnect_gather.empty()) {
++p) {
Session *session = mds->sessionmap.get_session(entity_name_t::CLIENT(p->v));
ceph_assert(session);
- dout(1) << "reconnect gave up on " << session->info.inst << dendl;
+
+ // 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;
+ }
+
+ dout(1) << "reconnect gives up on " << session->info.inst << dendl;
mds->clog->warn() << "evicting unresponsive client " << *session
<< ", after waiting " << g_conf()->mds_reconnect_timeout
size_t apply_blacklist(const std::set<entity_addr_t> &blacklist);
void journal_close_session(Session *session, int state, Context *on_safe);
+ set<client_t> client_reclaim_gather;
+ size_t get_num_pending_reclaim() const { return client_reclaim_gather.size(); }
Session *find_session_by_uuid(std::string_view uuid);
void reclaim_session(Session *session, const MClientReclaim::const_ref &m);
void finish_reclaim_session(Session *session, const MClientReclaimReply::ref &reply=nullptr);