#include "include/assert.h"
#include "mds/MDSContinuation.h"
+#include "mds/InoTable.h"
#define dout_subsys ceph_subsys_mds
#undef dout_prefix
}
}
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()) {
{
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;
+}
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 {