};
};
+SessionMap::SessionMap(MDSRank *m)
+ : mds(m),
+ mds_session_metadata_threshold(g_conf().get_val<Option::size_t>("mds_session_metadata_threshold")) {
+}
+
void SessionMap::register_perfcounters()
{
PerfCountersBuilder plb(g_ceph_context, "mds_sessions",
};
}
+bool SessionMap::validate_and_encode_session(MDSRank *mds, Session *session, bufferlist& bl) {
+ session->info.encode(bl, mds->mdsmap->get_up_features());
+ return bl.length() < mds_session_metadata_threshold;
+}
+
void SessionMap::save(MDSContext *onsave, version_t needv)
{
dout(10) << __func__ << ": needv " << needv << ", v " << version << dendl;
dout(20) << " updating keys:" << dendl;
map<string, bufferlist> to_set;
+ std::set<entity_name_t> to_blocklist;
for(std::set<entity_name_t>::iterator i = dirty_sessions.begin();
i != dirty_sessions.end(); ++i) {
const entity_name_t name = *i;
session->is_stale() ||
session->is_killing()) {
dout(20) << " " << name << dendl;
- // Serialize K
- CachedStackStringStream css;
- *css << name;
// Serialize V
bufferlist bl;
- session->info.encode(bl, mds->mdsmap->get_up_features());
+ if (!validate_and_encode_session(mds, session, bl)) {
+ derr << __func__ << ": session (" << name << ") exceeds"
+ << " sesion metadata threshold - blocklisting" << dendl;
+ to_blocklist.emplace(name);
+ continue;
+ }
+
+ // Serialize K
+ CachedStackStringStream css;
+ *css << name;
// Add to RADOS op
to_set[std::string(css->strv())] = bl;
0,
new C_OnFinisher(new C_IO_SM_Save(this, version),
mds->finisher));
+ apply_blocklist(to_blocklist);
}
void SessionMap::_save_finish(version_t v)
{
ceph_assert(gather_bld != NULL);
- std::vector<entity_name_t> write_sessions;
+ std::set<entity_name_t> to_blocklist;
+ std::map<entity_name_t, bufferlist> write_sessions;
// Decide which sessions require a write
for (std::set<entity_name_t>::iterator i = tgt_sessions.begin();
// need to pre-empt that.
continue;
}
+
+ // Serialize V
+ bufferlist bl;
+ if (!validate_and_encode_session(mds, session, bl)) {
+ derr << __func__ << ": session (" << session_id << ") exceeds"
+ << " sesion metadata threshold - blocklisting" << dendl;
+ to_blocklist.emplace(session_id);
+ continue;
+ }
+
// Okay, passed all our checks, now we write
// this session out. The version we write
// into the OMAP may now be higher-versioned
// than the version in the header, but that's
// okay because it's never a problem to have
// an overly-fresh copy of a session.
- write_sessions.push_back(*i);
+ write_sessions.emplace(session_id, std::move(bl));
+ session->clear_dirty_completed_requests();
}
dout(4) << __func__ << ": writing " << write_sessions.size() << dendl;
// Batch writes into mds_sessionmap_keys_per_op
const uint32_t kpo = g_conf()->mds_sessionmap_keys_per_op;
map<string, bufferlist> to_set;
- for (uint32_t i = 0; i < write_sessions.size(); ++i) {
- const entity_name_t &session_id = write_sessions[i];
- Session *session = session_map[session_id];
- session->clear_dirty_completed_requests();
+ uint32_t i = 0;
+ for (auto &[session_id, bl] : write_sessions) {
// Serialize K
CachedStackStringStream css;
*css << session_id;
- // Serialize V
- bufferlist bl;
- session->info.encode(bl, mds->mdsmap->get_up_features());
-
// Add to RADOS op
- to_set[css->str()] = bl;
+ to_set[css->str()] = std::move(bl);
// Complete this write transaction?
if (i == write_sessions.size() - 1
new C_IO_SM_Save_One(this, on_safe),
mds->finisher));
}
+ ++i;
}
+
+ apply_blocklist(to_blocklist);
}
// =================
};
apply_to_open_sessions(mut);
}
+
+ if (changed.count("mds_session_metadata_threshold")) {
+ mds_session_metadata_threshold = g_conf().get_val<Option::size_t>("mds_session_metadata_threshold");
+ }
}
void SessionMap::update_average_session_age() {
logger->set(l_mdssm_avg_session_uptime, (uint64_t)avg_uptime);
}
+void SessionMap::apply_blocklist(const std::set<entity_name_t>& victims) {
+ if (victims.empty()) {
+ return;
+ }
+
+ C_GatherBuilder gather(g_ceph_context, new C_MDSInternalNoop);
+ for (auto &victim : victims) {
+ CachedStackStringStream css;
+ mds->evict_client(victim.num(), false, g_conf()->mds_session_blocklist_on_evict, *css,
+ gather.new_sub());
+ }
+ gather.activate();
+}
+
int SessionFilter::parse(
const std::vector<std::string> &args,
std::ostream *ss)