From 5259683e7819c22c14b21b1dd678a33e14574f21 Mon Sep 17 00:00:00 2001 From: Vishal Kanaujia Date: Wed, 13 Jul 2016 18:50:28 +0530 Subject: [PATCH] cephfs: Inotable repair during forward scrub --- src/mds/CInode.cc | 32 ++++++++++++++++++++++++++++++++ src/mds/InoTable.cc | 23 +++++++++++++++++++++++ src/mds/InoTable.h | 2 ++ 3 files changed, 57 insertions(+) diff --git a/src/mds/CInode.cc b/src/mds/CInode.cc index ed75d587abc..9dabd9d571c 100644 --- a/src/mds/CInode.cc +++ b/src/mds/CInode.cc @@ -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()) { diff --git a/src/mds/InoTable.cc b/src/mds/InoTable.cc index fd26a1176cb..9b6029c5e36 100644 --- a/src/mds/InoTable.cc +++ b/src/mds/InoTable.cc @@ -190,3 +190,26 @@ void InoTable::generate_test_instances(list& 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 <