]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
cephfs: Inotable repair during forward scrub
authorVishal Kanaujia <Vishal.Kanaujia@sandisk.com>
Wed, 13 Jul 2016 13:20:28 +0000 (18:50 +0530)
committerVishal Kanaujia <Vishal.Kanaujia@sandisk.com>
Wed, 13 Jul 2016 13:21:01 +0000 (18:51 +0530)
src/mds/CInode.cc
src/mds/InoTable.cc
src/mds/InoTable.h

index ed75d587abcb9b88862dc3147a5f3522edb36a93..9dabd9d571c4891fdbcc596226a8c5e3d0c1b62a 100644 (file)
@@ -46,6 +46,7 @@
 #include "include/assert.h"
 
 #include "mds/MDSContinuation.h"
+#include "mds/InoTable.h"
 
 #define dout_subsys ceph_subsys_mds
 #undef dout_prefix
@@ -3837,6 +3838,37 @@ void CInode::validate_disk_state(CInode::validated_data *results,
         }
       }
 next:
+      // If the inode's number was free in the InoTable, fix that
+      // (#15619)
+      {
+        const inode_t& inode = in->inode;
+        MDCache *mdcache = in->mdcache;
+        InoTable *inotable = mdcache->mds->inotable;
+
+        dout(10) << "scrub: inotable ino = 0x" << std::hex << inode.ino << dendl;
+        dout(10) << "scrub: inotable free says "
+          << inotable->is_marked_free(inode.ino) << dendl;
+
+        if (inotable->is_marked_free(inode.ino)) {
+          LogChannelRef clog = in->mdcache->mds->clog;
+          clog->error() << "scrub: inode wrongly marked free: 0x" << std::hex
+            << inode.ino;
+
+          if (in->scrub_infop->header && in->scrub_infop->header->repair) {
+            bool repaired = inotable->repair(inode.ino);
+            if (repaired) {
+              clog->error() << "inode table repaired for inode: 0x" << std::hex
+                << inode.ino;
+
+              inotable->save();
+            } else {
+              clog->error() << "Cannot repair inotable while other operations"
+                " are in progress";
+            }
+          }
+        }
+      }
+
       // quit if we're a file, or kick off directory checks otherwise
       // TODO: validate on-disk inode for non-base directories
       if (!in->is_dir()) {
index fd26a1176cb5e09f5dc15a881db1848fa990b8c0..9b6029c5e3652fa2f69617d7e65dfa294ef2674c 100644 (file)
@@ -190,3 +190,26 @@ void InoTable::generate_test_instances(list<InoTable*>& ls)
 {
   ls.push_back(new InoTable());
 }
+
+
+bool InoTable::is_marked_free(inodeno_t id) const
+{
+  return free.contains(id) || projected_free.contains(id);
+}
+
+
+bool InoTable::repair(inodeno_t id)
+{
+  if (projected_version != version) {
+    // Can't do the repair while other things are in flight
+    return false;
+  }
+
+  assert(is_marked_free(id));
+  dout(10) << "repair: before status. ino = 0x" << std::hex << id << " pver =" << projected_version << " ver= " << version << dendl;
+  free.erase(id);
+  projected_free.erase(id);
+  projected_version = ++version;
+  dout(10) << "repair: after status. ino = 0x" << std::hex <<id << " pver =" << projected_version << " ver= " << version << dendl;
+  return true;
+}
index a767d46587ca8282ee0b4b5cb4223469e471ffe1..3208a4c92fc556fe019d2759b75df70dba0181c7 100644 (file)
@@ -41,6 +41,8 @@ class InoTable : public MDSTable {
   void replay_alloc_ids(interval_set<inodeno_t>& inos);
   void replay_release_ids(interval_set<inodeno_t>& inos);
   void replay_reset();
+  bool repair(inodeno_t id);
+  bool is_marked_free(inodeno_t id) const;
 
   void reset_state();
   void encode_state(bufferlist& bl) const {