mount_cond.notify_all();
remove_session_caps(s, err);
kick_requests_closed(s);
+ mds_ranks_closing.erase(s->mds_num);
if (s->state == MetaSession::STATE_CLOSED)
mds_sessions.erase(s->mds_num);
}
for (auto &p : mds_sessions) {
if (p.second.state != MetaSession::STATE_CLOSING) {
_close_mds_session(&p.second);
+ mds_ranks_closing.insert(p.first);
}
}
// wait for sessions to close
- ldout(cct, 2) << "waiting for " << mds_sessions.size() << " mds sessions to close" << dendl;
+ double timo = cct->_conf.get_val<std::chrono::seconds>("client_shutdown_timeout").count();
+ ldout(cct, 2) << "waiting for " << mds_ranks_closing.size() << " mds session(s) to close (timeout: "
+ << timo << "s)" << dendl;
std::unique_lock l{client_lock, std::adopt_lock};
- mount_cond.wait(l);
+ if (!timo) {
+ mount_cond.wait(l);
+ } else if (!mount_cond.wait_for(l, ceph::make_timespan(timo), [this] { return mds_ranks_closing.empty(); })) {
+ ldout(cct, 1) << mds_ranks_closing.size() << " mds(s) did not respond to session close -- timing out." << dendl;
+ while (!mds_ranks_closing.empty()) {
+ auto session = mds_sessions.at(*mds_ranks_closing.begin());
+ // this prunes entry from mds_sessions and mds_ranks_closing
+ _closed_mds_session(&session, -ETIMEDOUT);
+ }
+ }
+
+ mds_ranks_closing.clear();
l.release();
}
}
// mds sessions
map<mds_rank_t, MetaSession> mds_sessions; // mds -> push seq
+ std::set<mds_rank_t> mds_ranks_closing; // mds ranks currently tearing down sessions
std::list<ceph::condition_variable*> waiting_for_mdsmap;
// FSMap, for when using mds_command
.set_default(2)
.set_min(1)
.set_description("Size of thread pool for ASIO completions")
+ .add_tag("client"),
+
+ Option("client_shutdown_timeout", Option::TYPE_SECS, Option::LEVEL_ADVANCED)
+ .set_flag(Option::FLAG_RUNTIME)
+ .set_default(30)
+ .set_min(0)
+ .set_description("timeout for shutting down CephFS")
+ .set_long_description("Timeout for shutting down CephFS via unmount or shutdown.")
.add_tag("client")
- });
+ });
}