}
void CDentry::scrub_initialize(CDir *parent, bool recurse, bool children,
+ ScrubHeaderRefConst header,
Context *f)
{
if (!scrub_infop)
scrub_infop->scrub_children = children;
scrub_infop->dentry_scrubbing = true;
scrub_infop->on_finish = f;
+ scrub_infop->header = header;
auth_pin(this);
}
*c = scrub_infop->on_finish;
+ if (scrub_infop->header && scrub_infop->header->origin == this) {
+ // We are at the point that a tagging scrub was initiated
+ LogChannelRef clog = dir->cache->mds->clog;
+ clog->info() << "scrub complete with tag '"
+ << scrub_infop->header->tag << "'";
+
+ }
+
delete scrub_infop;
scrub_infop = NULL;
#include "SimpleLock.h"
#include "LocalLock.h"
+#include "ScrubHeader.h"
class CInode;
class CDir;
bool scrub_children; /// true if we have to scrub all direct children
bool dentry_scrubbing; /// safety check
Context *on_finish; /// called when we finish scrubbing
+ ScrubHeaderRefConst header;
+
scrub_info_t() :
scrub_parent(NULL), scrub_recursive(false),
scrub_children(false), dentry_scrubbing(false), on_finish(NULL)
return scrub_infop;
}
void scrub_initialize(CDir *parent, bool recurse, bool children,
+ ScrubHeaderRefConst header,
Context *f);
void scrub_finished(Context **c);
}
};
-void MDCache::enqueue_scrub(const string& path, Formatter *f, Context *fin)
+void MDCache::enqueue_scrub(
+ const string& path,
+ const std::string &tag,
+ Formatter *f, Context *fin)
{
dout(10) << "scrub_dentry " << path << dendl;
MDRequestRef mdr = request_start_internal(CEPH_MDS_OP_ENQUEUE_SCRUB);
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, "foobar");
+ mdr->internal_op_private = new EnqueueScrubParams(true, true, tag);
enqueue_scrub_work(mdr);
}
return;
}
- mds->scrubstack->enqueue_dentry_bottom(dn, true, true, args->tag, NULL);
+ 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;
/**
* Create and start an OP_ENQUEUE_SCRUB
*/
- void enqueue_scrub(const string& path, Formatter *f, Context *fin);
+ void enqueue_scrub(const string& path, const std::string &tag,
+ Formatter *f, Context *fin);
/**
* Resolve path to a dentry and pass it onto the ScrubStack.
asok_hook,
"scrub an inode and output results");
assert(r == 0);
+ r = admin_socket->register_command("tag path",
+ "tag path name=path,type=CephString"
+ " name=tag,type=CephString",
+ asok_hook,
+ "Apply scrub tag recursively");
+ assert(r == 0);
r = admin_socket->register_command("flush_path",
"flush_path name=path,type=CephString",
asok_hook,
} else if (command == "tag path") {
string path;
cmd_getval(g_ceph_context, cmdmap, "path", path);
- command_tag_path(f, path);
+ string tag;
+ cmd_getval(g_ceph_context, cmdmap, "tag", tag);
+ command_tag_path(f, path, tag);
} else if (command == "flush_path") {
string path;
cmd_getval(g_ceph_context, cmdmap, "path", path);
// scrub_dentry() finishers will dump the data for us; we're done!
}
-void MDSRank::command_tag_path(Formatter *f, const string& path)
+void MDSRank::command_tag_path(Formatter *f,
+ const string& path, const std::string &tag)
{
C_SaferCond scond;
{
Mutex::Locker l(mds_lock);
- mdcache->enqueue_scrub(path, f, &scond);
+ mdcache->enqueue_scrub(path, tag, f, &scond);
}
scond.wait();
}
protected:
void command_scrub_path(Formatter *f, const string& path);
- void command_tag_path(Formatter *f, const string& path);
+ void command_tag_path(Formatter *f, const string& path,
+ const string &tag);
void command_flush_path(Formatter *f, const string& path);
void command_flush_journal(Formatter *f);
void command_get_subtrees(Formatter *f);
mds/Migrator.h \
mds/ScatterLock.h \
mds/ScrubStack.h \
+ mds/ScrubHeader.h \
mds/Server.h \
mds/SessionMap.h \
mds/SimpleLock.h \
--- /dev/null
+
+#ifndef SCRUB_HEADER_H_
+#define SCRUB_HEADER_H_
+
+class CDentry;
+
+/**
+ * Externally input parameters for a scrub, associated with the root
+ * of where we are doing a recursive scrub
+ *
+ * TODO: swallow up 'recurse' and 'children' settings here instead of
+ * passing them down into every scrub_info structure
+ */
+class ScrubHeader {
+public:
+ std::string tag;
+ CDentry *origin;
+};
+typedef ceph::shared_ptr<ScrubHeader> ScrubHeaderRef;
+typedef ceph::shared_ptr<const ScrubHeader> ScrubHeaderRefConst;
+
+#endif // SCRUB_HEADER_H_
+
}
void ScrubStack::_enqueue_dentry(CDentry *dn, CDir *parent, bool recursive,
- bool children, const std::string &tag,
+ bool children, ScrubHeaderRefConst header,
MDSInternalContextBase *on_finish, bool top)
{
dout(10) << __func__ << " with {" << *dn << "}"
<< ", recursive=" << recursive << ", children=" << children
<< ", on_finish=" << on_finish << ", top=" << top << dendl;
assert(mdcache->mds->mds_lock.is_locked_by_me());
- dn->scrub_initialize(parent, recursive, children, on_finish);
+ dn->scrub_initialize(parent, recursive, children, header, on_finish);
if (top)
push_dentry(dn);
else
}
void ScrubStack::enqueue_dentry(CDentry *dn, bool recursive, bool children,
- const std::string &tag,
+ ScrubHeaderRefConst header,
MDSInternalContextBase *on_finish, bool top)
{
- _enqueue_dentry(dn, NULL, recursive, children, tag, on_finish, top);
+ _enqueue_dentry(dn, NULL, recursive, children, header, on_finish, top);
kick_off_scrubs();
}
// never get random IO errors here.
assert(r == 0);
+
+ CDentry *parent_dn = dir->get_inode()->get_parent_dn();
+ ScrubHeaderRefConst header = parent_dn->scrub_info()->header;
+
// FIXME: Do I *really* need to construct a kick context for every
// single dentry I'm going to scrub?
MDSInternalContext *on_d_scrub = new C_KickOffScrubs(mdcache->mds, this);
_enqueue_dentry(dn,
dir,
- /*
- * FIXME: look up params from dir's inode's parent
- */
-#if 0
- dir->scrub_info()->scrub_recursive,
- dir->scrub_info()->scrub_children,
-#else
- true,
- true,
-#endif
- // FIXME: carry tag through
- "foobar",
+ parent_dn->scrub_info()->scrub_recursive,
+ false, // We are already recursing so scrub_children not meaningful
+ header,
on_d_scrub,
true);
*added_children = true;
}
-
-#if 0
- bool any_unscrubbed = false;
-
- for (CDir::map_t::iterator i = dir->begin(); i != dir->end(); ++ i) {
- CDentry *dn = i->second;
-
- if (dir->scrub_info()->directories_scrubbed.count(i->first) == 0
- && dir->scrub_info()->others_scrubbed.count(i->first) == 0) {
- dout(20) << __func__ << " dn not yet scrubbed: " << *dn << dendl;
- any_unscrubbed = true;
- }
-
- if (dn->scrub_info()->dentry_scrubbing
- || dir->scrub_info()->directories_scrubbed.count(i->first)
- || dir->scrub_info()->others_scrubbed.count(i->first)) {
- dout(20) << __func__ << " skipping already scrubbing or scrubbed " << *dn << dendl;
- continue;
- }
-
- C_KickOffScrubs *c = new C_KickOffScrubs(mdcache->mds, this);
-
- _enqueue_dentry(dn,
- dir,
- /*
- * FIXME: look up params from dir's inode's parent
- */
-#if 0
- dir->scrub_info()->scrub_recursive,
- dir->scrub_info()->scrub_children,
-#else
- true,
- true,
-#endif
- // FIXME: carry tag through
- "foobar",
- c,
- true);
-
- *added_children = true;
- }
-
- *done = !any_unscrubbed;
-#endif
}
void ScrubStack::scrub_file_dentry(CDentry *dn)
#include "CDentry.h"
#include "CInode.h"
#include "MDSContext.h"
+#include "ScrubHeader.h"
#include "include/elist.h"
* @param children True if we want to scrub the direct children of
* dn but aren't doing a recursive scrub. (Otherwise, all checks are
* local to dn's disk state.)
- * @param tag If non-empty, tag applied to each verified rados object
+ * @param header The ScrubHeader propagated from whereever this scrub
+ * was initiated
*/
void enqueue_dentry_top(CDentry *dn, bool recursive, bool children,
- const std::string &tag,
+ ScrubHeaderRefConst header,
MDSInternalContextBase *on_finish) {
- enqueue_dentry(dn, recursive, children, tag, on_finish, true);
+ enqueue_dentry(dn, recursive, children, header, on_finish, true);
}
/** Like enqueue_dentry_top, but we wait for all pending scrubs before
* starting this one.
*/
void enqueue_dentry_bottom(CDentry *dn, bool recursive, bool children,
- const std::string &tag,
+ ScrubHeaderRefConst header,
MDSInternalContextBase *on_finish) {
- enqueue_dentry(dn, recursive, children, tag, on_finish, false);
+ enqueue_dentry(dn, recursive, children, header, on_finish, false);
}
private:
* the given scrub params, and then try and kick off more scrubbing.
*/
void enqueue_dentry(CDentry *dn, bool recursive, bool children,
- const std::string &tag,
+ ScrubHeaderRefConst header,
MDSInternalContextBase *on_finish, bool top);
void _enqueue_dentry(CDentry *dn, CDir *parent, bool recursive, bool children,
- const std::string &tag,
+ ScrubHeaderRefConst header,
MDSInternalContextBase *on_finish, bool top);
/**
* Kick off as many scrubs as are appropriate, based on the current