scrub_infop->last_local.time = ceph_clock_now(g_ceph_context);
scrub_infop->last_local.version = get_projected_version();
scrub_infop->last_scrub_dirty = true;
- } else {
+ } else if (inode->scrub_infop &&
+ inode->scrub_infop->header &&
+ inode->scrub_infop->header->repair) {
cache->repair_dirfrag_stats(this, NULL);
}
return rval;
!nest_info.same_sums(in->inode.rstat)) {
results->raw_stats.error_str
<< "freshly-calculated rstats don't match existing ones";
- in->mdcache->repair_inode_stats(in, NULL);
+ if (in->scrub_infop &&
+ in->scrub_infop->header &&
+ in->scrub_infop->header->repair)
+ in->mdcache->repair_inode_stats(in, NULL);
goto next;
}
results->raw_stats.passed = true;
void MDCache::enqueue_scrub(
const string& path,
const std::string &tag,
- bool recursive,
+ bool recursive, bool repair,
Formatter *f, Context *fin)
{
dout(10) << __func__ << path << dendl;
ScrubHeaderRef &header = cs->header;
header->tag = tag;
header->recursive = recursive;
+ header->repair = repair;
header->formatter = f;
mdr->internal_op_finish = cs;
* Create and start an OP_ENQUEUE_SCRUB
*/
void enqueue_scrub(const string& path, const std::string &tag,
- bool recursive, Formatter *f, Context *fin);
+ bool recursive, bool repair, Formatter *f, Context *fin);
void repair_inode_stats(CInode *diri, Context *fin);
void repair_dirfrag_stats(CDir *dir, Context *fin);
};
"show slowest recent ops");
assert(r == 0);
r = admin_socket->register_command("scrub_path",
- "scrub_path name=path,type=CephString",
+ "scrub_path name=path,type=CephString "
+ "name=scrubops,type=CephChoices,strings=recursive|repair,n=N,req=false",
asok_hook,
"scrub an inode and output results");
assert(r == 0);
}
} else if (command == "scrub_path") {
string path;
+ vector<string> scrubop_vec;
+ cmd_getval(g_ceph_context, cmdmap, "scrubops", scrubop_vec);
cmd_getval(g_ceph_context, cmdmap, "path", path);
- command_scrub_path(f, path);
+ command_scrub_path(f, path, scrubop_vec);
} else if (command == "tag path") {
string path;
cmd_getval(g_ceph_context, cmdmap, "path", path);
f->close_section(); //sessions
}
-void MDSRank::command_scrub_path(Formatter *f, const string& path)
+void MDSRank::command_scrub_path(Formatter *f, const string& path, vector<string>& scrubop_vec)
{
+ bool recursive = false;
+ bool repair = false;
+ for (vector<string>::iterator i = scrubop_vec.begin() ; i != scrubop_vec.end(); ++i) {
+ if (*i == "recursive")
+ recursive = true;
+ else if (*i == "repair")
+ repair = true;
+ }
C_SaferCond scond;
{
Mutex::Locker l(mds_lock);
- mdcache->enqueue_scrub(path, "", false, f, &scond);
+ mdcache->enqueue_scrub(path, "", recursive, repair, f, &scond);
}
scond.wait();
// scrub_dentry() finishers will dump the data for us; we're done!
C_SaferCond scond;
{
Mutex::Locker l(mds_lock);
- mdcache->enqueue_scrub(path, tag, true, f, &scond);
+ mdcache->enqueue_scrub(path, tag, true, false, f, &scond);
}
scond.wait();
}
protected:
void dump_clientreplay_status(Formatter *f) const;
- void command_scrub_path(Formatter *f, const string& path);
+ void command_scrub_path(Formatter *f, const string& path, vector<string>& scrubop_vec);
void command_tag_path(Formatter *f, const string& path,
const string &tag);
void command_flush_path(Formatter *f, const string& path);
std::string tag;
bool recursive;
+ bool repair;
Formatter *formatter;
};
typedef ceph::shared_ptr<ScrubHeader> ScrubHeaderRef;
if (all_frags_done) {
assert (!*added_children); // can't do this if children are still pending
- if (!dn->scrub_info()->on_finish) {
- scrubs_in_progress++;
- dn->scrub_set_finisher(&scrub_kick);
- }
-
// OK, so now I can... fire off a validate on the dir inode, and
// when it completes, come through here again, noticing that we've
// set a flag to indicate the the validate happened, and
// FIXME: the magic-constructing scrub_info() is going to leave
// an unneeded scrub_infop lying around here
if (!dn->scrub_info()->dentry_children_done) {
+ if (!dn->scrub_info()->on_finish) {
+ scrubs_in_progress++;
+ dn->scrub_set_finisher(&scrub_kick);
+ }
+
dn->scrub_children_finished();
CInode *in = dn->get_projected_inode();
C_InodeValidated *fin = new C_InodeValidated(mdcache->mds, this, dn);