From 3aeda5827b6482b2d5bd35bc899d3d291d50e4e5 Mon Sep 17 00:00:00 2001 From: John Spray Date: Wed, 15 Jul 2015 17:24:07 +0100 Subject: [PATCH] mds: implement ScrubHeader A place for scrubbed dentries to learn about the params that started the scrub off, such as the tag. Signed-off-by: John Spray --- src/mds/CDentry.cc | 10 ++++++ src/mds/CDentry.h | 4 +++ src/mds/MDCache.cc | 14 ++++++-- src/mds/MDCache.h | 3 +- src/mds/MDSDaemon.cc | 6 ++++ src/mds/MDSRank.cc | 9 +++-- src/mds/MDSRank.h | 3 +- src/mds/Makefile-server.am | 1 + src/mds/ScrubHeader.h | 23 ++++++++++++ src/mds/ScrubStack.cc | 71 ++++++-------------------------------- src/mds/ScrubStack.h | 16 +++++---- 11 files changed, 85 insertions(+), 75 deletions(-) create mode 100644 src/mds/ScrubHeader.h diff --git a/src/mds/CDentry.cc b/src/mds/CDentry.cc index d40b5a02574b..f241b81b6932 100644 --- a/src/mds/CDentry.cc +++ b/src/mds/CDentry.cc @@ -623,6 +623,7 @@ std::string CDentry::linkage_t::get_remote_d_type_string() const } void CDentry::scrub_initialize(CDir *parent, bool recurse, bool children, + ScrubHeaderRefConst header, Context *f) { if (!scrub_infop) @@ -635,6 +636,7 @@ void CDentry::scrub_initialize(CDir *parent, bool recurse, bool children, scrub_infop->scrub_children = children; scrub_infop->dentry_scrubbing = true; scrub_infop->on_finish = f; + scrub_infop->header = header; auth_pin(this); } @@ -650,6 +652,14 @@ void CDentry::scrub_finished(Context **c) *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; diff --git a/src/mds/CDentry.h b/src/mds/CDentry.h index 7470ff4db6ad..ee133384372f 100644 --- a/src/mds/CDentry.h +++ b/src/mds/CDentry.h @@ -29,6 +29,7 @@ #include "SimpleLock.h" #include "LocalLock.h" +#include "ScrubHeader.h" class CInode; class CDir; @@ -147,6 +148,8 @@ public: 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) @@ -173,6 +176,7 @@ public: return scrub_infop; } void scrub_initialize(CDir *parent, bool recurse, bool children, + ScrubHeaderRefConst header, Context *f); void scrub_finished(Context **c); diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index bf654735214a..e7889793f5c7 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -11739,7 +11739,10 @@ public: } }; -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); @@ -11749,7 +11752,7 @@ void MDCache::enqueue_scrub(const string& path, Formatter *f, Context *fin) 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); } @@ -11784,7 +11787,12 @@ void MDCache::enqueue_scrub_work(MDRequestRef& 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; diff --git a/src/mds/MDCache.h b/src/mds/MDCache.h index 3158b9cc7a8f..93eb697f4102 100644 --- a/src/mds/MDCache.h +++ b/src/mds/MDCache.h @@ -1128,7 +1128,8 @@ public: /** * 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. diff --git a/src/mds/MDSDaemon.cc b/src/mds/MDSDaemon.cc index 7f7def1361d6..4109891af33d 100644 --- a/src/mds/MDSDaemon.cc +++ b/src/mds/MDSDaemon.cc @@ -236,6 +236,12 @@ void MDSDaemon::set_up_admin_socket() 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, diff --git a/src/mds/MDSRank.cc b/src/mds/MDSRank.cc index 85ca8b158e8b..1f0619ddd60c 100644 --- a/src/mds/MDSRank.cc +++ b/src/mds/MDSRank.cc @@ -1718,7 +1718,9 @@ bool MDSRankDispatcher::handle_asok_command( } 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); @@ -1858,12 +1860,13 @@ void MDSRank::command_scrub_path(Formatter *f, const string& 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(); } diff --git a/src/mds/MDSRank.h b/src/mds/MDSRank.h index 237b7368e119..8d2667b15bae 100644 --- a/src/mds/MDSRank.h +++ b/src/mds/MDSRank.h @@ -368,7 +368,8 @@ class MDSRank { 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); diff --git a/src/mds/Makefile-server.am b/src/mds/Makefile-server.am index 1de7c5465ead..951bb8907cb4 100644 --- a/src/mds/Makefile-server.am +++ b/src/mds/Makefile-server.am @@ -37,6 +37,7 @@ noinst_HEADERS += \ mds/Migrator.h \ mds/ScatterLock.h \ mds/ScrubStack.h \ + mds/ScrubHeader.h \ mds/Server.h \ mds/SessionMap.h \ mds/SimpleLock.h \ diff --git a/src/mds/ScrubHeader.h b/src/mds/ScrubHeader.h new file mode 100644 index 000000000000..288f3a38a19c --- /dev/null +++ b/src/mds/ScrubHeader.h @@ -0,0 +1,23 @@ + +#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 ScrubHeaderRef; +typedef ceph::shared_ptr ScrubHeaderRefConst; + +#endif // SCRUB_HEADER_H_ + diff --git a/src/mds/ScrubStack.cc b/src/mds/ScrubStack.cc index 67029c6bb922..c5abc86d44d8 100644 --- a/src/mds/ScrubStack.cc +++ b/src/mds/ScrubStack.cc @@ -58,14 +58,14 @@ void ScrubStack::pop_dentry(CDentry *dn) } 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 @@ -73,10 +73,10 @@ void ScrubStack::_enqueue_dentry(CDentry *dn, CDir *parent, bool recursive, } 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(); } @@ -348,72 +348,23 @@ void ScrubStack::scrub_dirfrag(CDir *dir, bool *added_children, // 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) diff --git a/src/mds/ScrubStack.h b/src/mds/ScrubStack.h index 0be512646d70..14ae869be5a7 100644 --- a/src/mds/ScrubStack.h +++ b/src/mds/ScrubStack.h @@ -19,6 +19,7 @@ #include "CDentry.h" #include "CInode.h" #include "MDSContext.h" +#include "ScrubHeader.h" #include "include/elist.h" @@ -59,20 +60,21 @@ public: * @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: @@ -81,10 +83,10 @@ 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 -- 2.47.3