return free.contains(id) || projected_free.contains(id);
}
+bool InoTable::intersects_free(
+ const interval_set<inodeno_t> &other,
+ interval_set<inodeno_t> *intersection)
+{
+ interval_set<inodeno_t> i;
+ i.intersection_of(free, other);
+ if (intersection != nullptr) {
+ *intersection = i;
+ }
+ return !(i.empty());
+}
bool InoTable::repair(inodeno_t id)
{
void replay_reset();
bool repair(inodeno_t id);
bool is_marked_free(inodeno_t id) const;
+ bool intersects_free(
+ const interval_set<inodeno_t> &other,
+ interval_set<inodeno_t> *intersection);
void reset_state() override;
void encode_state(bufferlist& bl) const override {
break;
case MDS_BOOT_REPLAY_DONE:
assert(is_any_replay());
+
+ // Sessiontable and inotable should be in sync after replay, validate
+ // that they are consistent.
+ validate_sessions();
+
replay_done();
break;
}
}
+void MDSRank::validate_sessions()
+{
+ assert(mds_lock.is_locked_by_me());
+ std::vector<Session*> victims;
+
+ // Identify any sessions which have state inconsistent with other,
+ // after they have been loaded from rados during startup.
+ // Mitigate bugs like: http://tracker.ceph.com/issues/16842
+ const auto &sessions = sessionmap.get_sessions();
+ for (const auto &i : sessions) {
+ Session *session = i.second;
+ interval_set<inodeno_t> badones;
+ if (inotable->intersects_free(session->info.prealloc_inos, &badones)) {
+ clog->error() << "Client session loaded with invalid preallocated "
+ "inodes, evicting session " << *session;
+
+ // Make the session consistent with inotable so that it can
+ // be cleanly torn down
+ session->info.prealloc_inos.subtract(badones);
+
+ victims.push_back(session);
+ }
+ }
+
+ for (const auto &session: victims) {
+ server->kill_session(session, nullptr);
+ }
+}
+
void MDSRank::starting_done()
{
dout(3) << "starting_done" << dendl;