scrub_dentry_work(mdr);
}
-/**
- * The private data for an OP_ENQUEUE_SCRUB MDRequest
- */
-class EnqueueScrubParams
-{
- public:
- const bool recursive;
- const bool children;
- const std::string tag;
- EnqueueScrubParams(bool r, bool c, const std::string &tag_)
- : recursive(r), children(c), tag(tag_)
- {}
-};
-
-
void MDCache::scrub_dentry_work(MDRequestRef& mdr)
{
set<SimpleLock*> rdlocks, wrlocks, xlocks;
return;
}
-
-class C_ScrubEnqueued : public Context
+class C_MDS_EnqueueScrub : public Context
{
-public:
- MDRequestRef mdr;
- Context *on_finish;
Formatter *formatter;
- C_ScrubEnqueued(MDRequestRef& mdr,
- Context *fin, Formatter *f) :
- mdr(mdr), on_finish(fin), formatter(f) {}
+ Context *on_finish;
+public:
+ ScrubHeaderRef header;
+ C_MDS_EnqueueScrub(Formatter *f, Context *fin) :
+ formatter(f), on_finish(fin), header(new ScrubHeader()) {}
+
+ Context *take_finisher() {
+ Context *fin = on_finish;
+ on_finish = NULL;
+ return fin;
+ }
void finish(int r) {
-#if 0
- if (r >= 0) { // we got into the scrubbing dump it
- results.dump(formatter);
- } else { // we failed the lookup or something; dump ourselves
+ if (r < 0) { // we failed the lookup or something; dump ourselves
formatter->open_object_section("results");
formatter->dump_int("return_code", r);
formatter->close_section(); // results
}
-#endif
- on_finish->complete(r);
+ if (on_finish)
+ on_finish->complete(r);
}
};
void MDCache::enqueue_scrub(
const string& path,
const std::string &tag,
+ bool recursive,
Formatter *f, Context *fin)
{
- dout(10) << "scrub_dentry " << path << dendl;
+ dout(10) << __func__ << path << dendl;
MDRequestRef mdr = request_start_internal(CEPH_MDS_OP_ENQUEUE_SCRUB);
filepath fp(path.c_str());
mdr->set_filepath(fp);
- C_ScrubEnqueued *se = new C_ScrubEnqueued(mdr, fin, f);
- mdr->internal_op_finish = se;
- // TODO pass through tag/args
- mdr->internal_op_private = new EnqueueScrubParams(true, true, tag);
+ C_MDS_EnqueueScrub *cs = new C_MDS_EnqueueScrub(f, fin);
+ ScrubHeaderRef &header = cs->header;
+ header->tag = tag;
+ header->recursive = recursive;
+ header->formatter = f;
+
+ mdr->internal_op_finish = cs;
enqueue_scrub_work(mdr);
}
return;
CDentry *dn = in->get_parent_dn();
-
// We got to this inode by path, so it must have a parent
assert(dn != NULL);
- // Not setting a completion context here because we don't
- // want to block asok caller on long running scrub
- EnqueueScrubParams *args = static_cast<EnqueueScrubParams*>(
- mdr->internal_op_private);
- assert(args != NULL);
+ C_MDS_EnqueueScrub *cs = static_cast<C_MDS_EnqueueScrub*>(mdr->internal_op_finish);
+ ScrubHeaderRef &header = cs->header;
// Cannot scrub same dentry twice at same time
if (dn->scrub_info()->dentry_scrubbing) {
return;
}
- ScrubHeaderRef header(new ScrubHeader());
-
- header->tag = args->tag;
header->origin = dn;
- mds->scrubstack->enqueue_dentry_bottom(dn, true, true, header, NULL);
- delete args;
- mdr->internal_op_private = NULL;
+ // only set completion context for non-recursive scrub, because we don't
+ // want to block asok caller on long running scrub
+ Context *fin = NULL;
+ if (!header->recursive)
+ fin = cs->take_finisher();
+
+ mds->scrubstack->enqueue_dentry_bottom(dn, header->recursive, false, header, fin);
- // Successfully enqueued
mds->server->respond_to_request(mdr, 0);
return;
}
* Create and start an OP_ENQUEUE_SCRUB
*/
void enqueue_scrub(const string& path, const std::string &tag,
- Formatter *f, Context *fin);
+ bool recursive, Formatter *f, Context *fin);
void repair_inode_stats(CInode *diri, Context *fin);
void repair_dirfrag_stats(CDir *dir, Context *fin);
};
C_SaferCond scond;
{
Mutex::Locker l(mds_lock);
- mdcache->scrub_dentry(path, f, &scond);
+ mdcache->enqueue_scrub(path, "", false, 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, f, &scond);
+ mdcache->enqueue_scrub(path, tag, true, f, &scond);
}
scond.wait();
}
*/
class ScrubHeader {
public:
- std::string tag;
CDentry *origin;
+ std::string tag;
+
+ bool recursive;
+ Formatter *formatter;
};
typedef ceph::shared_ptr<ScrubHeader> ScrubHeaderRef;
typedef ceph::shared_ptr<const ScrubHeader> ScrubHeaderRefConst;
void ScrubStack::_enqueue_dentry(CDentry *dn, CDir *parent, bool recursive,
bool children, const ScrubHeaderRefConst& header,
- MDSInternalContextBase *on_finish, bool top)
+ Context *on_finish, bool top)
{
dout(10) << __func__ << " with {" << *dn << "}"
<< ", recursive=" << recursive << ", children=" << children
void ScrubStack::enqueue_dentry(CDentry *dn, bool recursive, bool children,
const ScrubHeaderRefConst& header,
- MDSInternalContextBase *on_finish, bool top)
+ Context *on_finish, bool top)
{
_enqueue_dentry(dn, NULL, recursive, children, header, on_finish, top);
kick_off_scrubs();
assert(dn->scrub_info_p != NULL);
dn->scrub_info_p->inode_validated = true;
#endif
+ const ScrubHeaderRefConst header = dn->scrub_info()->header;
Context *c = NULL;
CInode *in = dn->get_projected_inode();
// just the dentry.
dn->scrub_finished(&c);
}
+
+ if (!header->recursive && dn == header->origin) {
+ if (r >= 0) { // we got into the scrubbing dump it
+ result.dump(header->formatter);
+ } else { // we failed the lookup or something; dump ourselves
+ header->formatter->open_object_section("results");
+ header->formatter->dump_int("return_code", r);
+ header->formatter->close_section(); // results
+ }
+ }
if (c) {
finisher->queue(new MDSIOContextWrapper(mdcache->mds, c), 0);
}
*/
void enqueue_dentry_top(CDentry *dn, bool recursive, bool children,
const ScrubHeaderRefConst& header,
- MDSInternalContextBase *on_finish) {
+ Context *on_finish) {
enqueue_dentry(dn, recursive, children, header, on_finish, true);
}
/** Like enqueue_dentry_top, but we wait for all pending scrubs before
*/
void enqueue_dentry_bottom(CDentry *dn, bool recursive, bool children,
const ScrubHeaderRefConst& header,
- MDSInternalContextBase *on_finish) {
+ Context *on_finish) {
enqueue_dentry(dn, recursive, children, header, on_finish, false);
}
*/
void enqueue_dentry(CDentry *dn, bool recursive, bool children,
const ScrubHeaderRefConst& header,
- MDSInternalContextBase *on_finish, bool top);
+ Context *on_finish, bool top);
void _enqueue_dentry(CDentry *dn, CDir *parent, bool recursive, bool children,
const ScrubHeaderRefConst& header,
- MDSInternalContextBase *on_finish, bool top);
+ Context *on_finish, bool top);
/**
* Kick off as many scrubs as are appropriate, based on the current
* state of the stack.