From: Vishal Kanaujia Date: Wed, 13 Jul 2016 13:20:28 +0000 (+0530) Subject: cephfs: Inotable repair during forward scrub X-Git-Tag: ses5-milestone5~274^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=refs%2Fpull%2F10281%2Fhead;p=ceph.git cephfs: Inotable repair during forward scrub --- diff --git a/src/mds/CInode.cc b/src/mds/CInode.cc index ed75d587abcb..9dabd9d571c4 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 fd26a1176cb5..9b6029c5e365 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 <