]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
mds: validate prealloc_inos on sessions after load
authorJohn Spray <john.spray@redhat.com>
Mon, 27 Mar 2017 11:56:31 +0000 (12:56 +0100)
committerJohn Spray <john.spray@redhat.com>
Thu, 13 Apr 2017 16:32:07 +0000 (12:32 -0400)
Mitigates http://tracker.ceph.com/issues/16842

Signed-off-by: John Spray <john.spray@redhat.com>
src/mds/InoTable.cc
src/mds/InoTable.h
src/mds/MDSRank.cc
src/mds/MDSRank.h

index f192b12ac05c6bbf2df2a92c33684d81f959108c..fc1faa876427cd430c4cb3212327d4ef25ae7e56 100644 (file)
@@ -198,6 +198,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 eb538f9c849e214bb3a92a1fdba2cdeb78457bfc..3eeba37d471f09a2a3bc572f5c351939bf0a6776 100644 (file)
@@ -1036,11 +1036,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 8c0802561b69b8bf22fcd717919deb6ae6e852a3..5fc6376b6b857bbc0175f2c9770c8b5c8f80c86c 100644 (file)
@@ -480,6 +480,8 @@ class MDSRank {
     void active_start();
     void stopping_start();
     void stopping_done();
+
+    void validate_sessions();
     // <<<
     
     // >>>