]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: validate prealloc_inos on sessions after load 16107/head
authorJohn Spray <john.spray@redhat.com>
Mon, 27 Mar 2017 11:56:31 +0000 (12:56 +0100)
committerNathan Cutler <ncutler@suse.com>
Tue, 4 Jul 2017 11:26:24 +0000 (13:26 +0200)
Mitigates http://tracker.ceph.com/issues/16842

Signed-off-by: John Spray <john.spray@redhat.com>
(cherry picked from commit c39aaf90ed1b23343eba2b341bb8ee6a50a4ea74)

src/mds/InoTable.cc
src/mds/InoTable.h
src/mds/MDSRank.cc
src/mds/MDSRank.h

index 9b6029c5e3652fa2f69617d7e65dfa294ef2674c..097cd7fccbc801e55735ac51729ace52b6eb19d2 100644 (file)
@@ -197,6 +197,17 @@ bool InoTable::is_marked_free(inodeno_t id) const
   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)
 {
index a787d348a32b87735faf37b03ab622b96214879d..5f6a0b385ac7876c16e2d37908c82910cb1f93f9 100644 (file)
@@ -43,6 +43,9 @@ class InoTable : public MDSTable {
   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 {
index 63ad51bd9567073f024b1539d190c4e94f291251..392b99f86f7c920ec4392d2386c0b0943ee0f9da 100644 (file)
@@ -993,11 +993,45 @@ void MDSRank::boot_start(BootStep step, int r)
       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;
index 6f5cf1030959f4c1006ede40a042bbff89c64a76..32838b5835d09e63079ca6e2a24f0a45b858866b 100644 (file)
@@ -461,6 +461,8 @@ class MDSRank {
     void active_start();
     void stopping_start();
     void stopping_done();
+
+    void validate_sessions();
     // <<<
     
     // >>>