From: Yan, Zheng Date: Tue, 15 Dec 2015 14:28:44 +0000 (+0800) Subject: mds: make scrubstack queue CInode instead of CDentry X-Git-Tag: v10.1.0~176^2~1^2~12 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=84ed3cd7b91ea7e6cd7094c102cb78cb8b5a81f9;p=ceph.git mds: make scrubstack queue CInode instead of CDentry There are two problems that enqueue CDentry in scrub stack. First, the scrub stack code can't handle base inodes; second, the linkage of a CDentry can change in the middle of scrubbing, this can confuse the scrub stack code. Signed-off-by: Yan, Zheng --- diff --git a/src/mds/CDentry.cc b/src/mds/CDentry.cc index b7ccea9d0999..83470dca68fb 100644 --- a/src/mds/CDentry.cc +++ b/src/mds/CDentry.cc @@ -621,57 +621,3 @@ std::string CDentry::linkage_t::get_remote_d_type_string() const default: assert(0); return ""; } } - -void CDentry::scrub_initialize(CDir *parent, bool recurse, bool children, - const ScrubHeaderRefConst& header, - Context *f) -{ - if (!scrub_infop) - scrub_info_create(); - else - assert(!scrub_infop->dentry_scrubbing); - - scrub_infop->scrub_parent = parent; - scrub_infop->scrub_recursive = recurse; - scrub_infop->scrub_children = children; - scrub_infop->dentry_scrubbing = true; - scrub_infop->on_finish = f; - scrub_infop->header = header; - - auth_pin(this); -} - -void CDentry::scrub_finished(Context **c) -{ - dout(10) << __func__ << dendl; - assert(scrub_info()->dentry_scrubbing); - - if (scrub_infop->scrub_parent) { - scrub_infop->scrub_parent->scrub_dentry_finished(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; - - auth_unpin(this); -} - -void CDentry::scrub_info_create() const -{ - assert(!scrub_infop); - - // break out of const-land to set up implicit initial state - CDentry *me = const_cast(this); - - // we don't need to change or set up any default parameters; assign directly - me->scrub_infop = new scrub_info_t(); -} diff --git a/src/mds/CDentry.h b/src/mds/CDentry.h index 4fc0ba0340ef..7861b4d97242 100644 --- a/src/mds/CDentry.h +++ b/src/mds/CDentry.h @@ -81,14 +81,14 @@ public: static const int PIN_INODEPIN = 1; // linked inode is pinned static const int PIN_FRAGMENTING = -2; // containing dir is refragmenting static const int PIN_PURGING = 3; - static const int PIN_SCRUBQUEUE = 4; // TODO: negative value? + static const int PIN_SCRUBPARENT = 4; const char *pin_name(int p) const { switch (p) { case PIN_INODEPIN: return "inodepin"; case PIN_FRAGMENTING: return "fragmenting"; case PIN_PURGING: return "purging"; - case PIN_SCRUBQUEUE: return "scrub_enqueued"; + case PIN_SCRUBPARENT: return "scrubparent"; default: return generic_pin_name(p); } } @@ -140,25 +140,6 @@ public: } void link_remote(CInode *in); }; - - class scrub_info_t { - public: - CDir *scrub_parent; /// This either matches get_parent_dir() or NULL - bool scrub_recursive; /// true if we are scrubbing everything under this - bool scrub_children; /// true if we have to scrub all direct children - bool dentry_scrubbing; /// safety check - bool dentry_children_done; /// safety check - bool inode_validated; /// Has our inode's validate_disk_state run? - 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), - dentry_children_done(false), inode_validated(false), - on_finish(NULL) - {} - }; protected: CDir *dir; // containing dirfrag @@ -167,34 +148,10 @@ protected: version_t version; // dir version when last touched. version_t projected_version; // what it will be when i unlock/commit. - scrub_info_t* scrub_infop; public: elist::item item_dirty; elist::item item_stray; - elist::item item_scrub; - - const scrub_info_t *scrub_info() const { - if(!scrub_infop) - scrub_info_create(); - return scrub_infop; - } - void scrub_initialize(CDir *parent, bool recurse, bool children, - const ScrubHeaderRefConst& header, - Context *f); - void scrub_finished(Context **c); - void scrub_children_finished() { - scrub_infop->dentry_children_done = true; - } - void scrub_set_finisher(Context *c) { - scrub_infop->on_finish = c; - } - -private: - /** - * Create a scrub_info_t struct for the scrub_infop pointer. - */ - void scrub_info_create() const; protected: friend class Migrator; @@ -221,7 +178,6 @@ public: first(f), last(l), dir(0), version(0), projected_version(0), - scrub_infop(NULL), item_dirty(this), lock(this, &lock_type), versionlock(this, &versionlock_type) { @@ -234,7 +190,6 @@ public: first(f), last(l), dir(0), version(0), projected_version(0), - scrub_infop(NULL), item_dirty(this), lock(this, &lock_type), versionlock(this, &versionlock_type) { @@ -244,8 +199,6 @@ public: linkage.remote_d_type = dt; } ~CDentry() { - assert(!scrub_infop); - assert(!item_scrub.is_on_list()); g_num_dn--; g_num_dns++; } diff --git a/src/mds/CInode.cc b/src/mds/CInode.cc index ad4ee4529ead..c4b06dd71b89 100644 --- a/src/mds/CInode.cc +++ b/src/mds/CInode.cc @@ -4146,7 +4146,8 @@ void CInode::scrub_maybe_delete_info() } } -void CInode::scrub_initialize(const ScrubHeaderRefConst& header) +void CInode::scrub_initialize(CDentry *scrub_parent, + const ScrubHeaderRefConst& header, Context *f) { dout(20) << __func__ << " with scrub_version " << get_version() << dendl; assert(!scrub_infop || !scrub_infop->scrub_in_progress); @@ -4166,10 +4167,17 @@ void CInode::scrub_initialize(const ScrubHeaderRefConst& header) scrub_infop->dirfrag_stamps[*i]; } } + + if (scrub_parent) + scrub_parent->get(CDentry::PIN_SCRUBPARENT); + scrub_infop->scrub_parent = scrub_parent; + scrub_infop->on_finish = f; scrub_infop->scrub_in_progress = true; + scrub_infop->children_scrubbed = false; + scrub_infop->header = header; + scrub_infop->scrub_start_version = get_version(); scrub_infop->scrub_start_stamp = ceph_clock_now(g_ceph_context); - scrub_infop->header = header; // right now we don't handle remote inodes } @@ -4248,9 +4256,24 @@ void CInode::scrub_finished(Context **c) { } assert(i->second.last_scrub_version == i->second.scrub_start_version); } + scrub_infop->last_scrub_version = scrub_infop->scrub_start_version; scrub_infop->last_scrub_stamp = scrub_infop->scrub_start_stamp; scrub_infop->last_scrub_dirty = true; scrub_infop->scrub_in_progress = false; - parent->scrub_finished(c); + + if (scrub_infop->scrub_parent) { + CDentry *dn = scrub_infop->scrub_parent; + scrub_infop->scrub_parent = NULL; + dn->dir->scrub_dentry_finished(dn); + dn->put(CDentry::PIN_SCRUBPARENT); + } + + *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 = mdcache->mds->clog; + clog->info() << "scrub complete with tag '" << scrub_infop->header->tag << "'"; + } } diff --git a/src/mds/CInode.h b/src/mds/CInode.h index 50482964a25b..98af256f3c40 100644 --- a/src/mds/CInode.h +++ b/src/mds/CInode.h @@ -171,6 +171,7 @@ public: static const int PIN_EXPORTINGCAPS = 22; static const int PIN_DIRTYPARENT = 23; static const int PIN_DIRWAITER = 24; + static const int PIN_SCRUBQUEUE = 25; const char *pin_name(int p) const { switch (p) { @@ -195,6 +196,7 @@ public: case PIN_DIRTYRSTAT: return "dirtyrstat"; case PIN_DIRTYPARENT: return "dirtyparent"; case PIN_DIRWAITER: return "dirwaiter"; + case PIN_SCRUBQUEUE: return "scrubqueue"; default: return generic_pin_name(p); } } @@ -259,15 +261,22 @@ public: class scrub_info_t : public scrub_stamp_info_t { public: + CDentry *scrub_parent; + Context *on_finish; + bool last_scrub_dirty; /// are our stamps dirty with respect to disk state? bool scrub_in_progress; /// are we currently scrubbing? + bool children_scrubbed; + /// my own (temporary) stamps and versions for each dirfrag we have std::map dirfrag_stamps; ScrubHeaderRefConst header; - scrub_info_t() : scrub_stamp_info_t(), last_scrub_dirty(false), - scrub_in_progress(false) {} + scrub_info_t() : scrub_stamp_info_t(), + scrub_parent(NULL), on_finish(NULL), + last_scrub_dirty(false), scrub_in_progress(false), + children_scrubbed(false) {} }; const scrub_info_t *scrub_info() const{ @@ -283,7 +292,8 @@ public: * @param scrub_version What version are we scrubbing at (usually, parent * directory's get_projected_version()) */ - void scrub_initialize(const ScrubHeaderRefConst& header); + void scrub_initialize(CDentry *scrub_parent, + const ScrubHeaderRefConst& header, Context *f); /** * Get the next dirfrag to scrub. Gives you a frag_t in output param which * you must convert to a CDir (and possibly load off disk). @@ -315,6 +325,16 @@ public: * be complete()ed. */ void scrub_finished(Context **c); + /** + * Report to the CInode that alldirfrags it owns have been scrubbed. + */ + void scrub_children_finished() { + scrub_infop->children_scrubbed = true; + } + void scrub_set_finisher(Context *c) { + assert(!scrub_infop->on_finish); + scrub_infop->on_finish = c; + } private: /** @@ -600,6 +620,7 @@ public: elist::item item_dirty_dirfrag_dir; elist::item item_dirty_dirfrag_nest; elist::item item_dirty_dirfrag_dirfragtree; + elist::item item_scrub; public: int auth_pin_freeze_allowance; diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index bdadc6d1f716..9eb47f8b02cc 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -11740,20 +11740,16 @@ void MDCache::enqueue_scrub_work(MDRequestRef& mdr) if (!locked) return; - CDentry *dn = in->get_parent_dn(); - // We got to this inode by path, so it must have a parent - assert(dn != NULL); - C_MDS_EnqueueScrub *cs = static_cast(mdr->internal_op_finish); ScrubHeaderRef &header = cs->header; // Cannot scrub same dentry twice at same time - if (dn->scrub_info()->dentry_scrubbing) { + if (in->scrub_info()->scrub_in_progress) { mds->server->respond_to_request(mdr, -EBUSY); return; } - header->origin = dn; + header->origin = in; // only set completion context for non-recursive scrub, because we don't // want to block asok caller on long running scrub @@ -11761,7 +11757,7 @@ void MDCache::enqueue_scrub_work(MDRequestRef& mdr) if (!header->recursive) fin = cs->take_finisher(); - mds->scrubstack->enqueue_dentry_bottom(dn, header->recursive, false, header, fin); + mds->scrubstack->enqueue_inode_bottom(in, header, fin); mds->server->respond_to_request(mdr, 0); return; diff --git a/src/mds/ScrubHeader.h b/src/mds/ScrubHeader.h index 35d355695e31..3b7eadea23e6 100644 --- a/src/mds/ScrubHeader.h +++ b/src/mds/ScrubHeader.h @@ -2,7 +2,7 @@ #ifndef SCRUB_HEADER_H_ #define SCRUB_HEADER_H_ -class CDentry; +class CInode; /** * Externally input parameters for a scrub, associated with the root @@ -13,7 +13,7 @@ class CDentry; */ class ScrubHeader { public: - CDentry *origin; + CInode *origin; std::string tag; bool recursive; diff --git a/src/mds/ScrubStack.cc b/src/mds/ScrubStack.cc index df55b8fa2acd..f3e5ce887be3 100644 --- a/src/mds/ScrubStack.cc +++ b/src/mds/ScrubStack.cc @@ -27,56 +27,54 @@ static ostream& _prefix(std::ostream *_dout, MDSRank *mds) { return *_dout << "mds." << mds->get_nodeid() << ".scrubstack "; } -void ScrubStack::push_dentry(CDentry *dentry) +void ScrubStack::push_inode(CInode *in) { - dout(20) << "pushing " << *dentry << " on top of ScrubStack" << dendl; - if (!dentry->item_scrub.is_on_list()) { - dentry->get(CDentry::PIN_SCRUBQUEUE); + dout(20) << "pushing " << *in << " on top of ScrubStack" << dendl; + if (!in->item_scrub.is_on_list()) { + in->get(CInode::PIN_SCRUBQUEUE); stack_size++; } - dentry_stack.push_front(&dentry->item_scrub); + inode_stack.push_front(&in->item_scrub); } -void ScrubStack::push_dentry_bottom(CDentry *dentry) +void ScrubStack::push_inode_bottom(CInode *in) { - dout(20) << "pushing " << *dentry << " on bottom of ScrubStack" << dendl; - if (!dentry->item_scrub.is_on_list()) { - dentry->get(CDentry::PIN_SCRUBQUEUE); + dout(20) << "pushing " << *in << " on bottom of ScrubStack" << dendl; + if (!in->item_scrub.is_on_list()) { + in->get(CInode::PIN_SCRUBQUEUE); stack_size++; } - dentry_stack.push_back(&dentry->item_scrub); + inode_stack.push_back(&in->item_scrub); } -void ScrubStack::pop_dentry(CDentry *dn) +void ScrubStack::pop_inode(CInode *in) { - dout(20) << "popping " << *dn + dout(20) << "popping " << *in << " off of ScrubStack" << dendl; - assert(dn->item_scrub.is_on_list()); - dn->put(CDentry::PIN_SCRUBQUEUE); - dn->item_scrub.remove_myself(); + assert(in->item_scrub.is_on_list()); + in->put(CInode::PIN_SCRUBQUEUE); + in->item_scrub.remove_myself(); stack_size--; } -void ScrubStack::_enqueue_dentry(CDentry *dn, CDir *parent, bool recursive, - bool children, const ScrubHeaderRefConst& header, - Context *on_finish, bool top) +void ScrubStack::_enqueue_inode(CInode *in, CDentry *parent, + const ScrubHeaderRefConst& header, + Context *on_finish, bool top) { - dout(10) << __func__ << " with {" << *dn << "}" - << ", recursive=" << recursive << ", children=" << children + dout(10) << __func__ << " with {" << *in << "}" << ", on_finish=" << on_finish << ", top=" << top << dendl; assert(mdcache->mds->mds_lock.is_locked_by_me()); - dn->scrub_initialize(parent, recursive, children, header, on_finish); + in->scrub_initialize(parent, header, on_finish); if (top) - push_dentry(dn); + push_inode(in); else - push_dentry_bottom(dn); + push_inode_bottom(in); } -void ScrubStack::enqueue_dentry(CDentry *dn, bool recursive, bool children, - const ScrubHeaderRefConst& header, - Context *on_finish, bool top) +void ScrubStack::enqueue_inode(CInode *in, const ScrubHeaderRefConst& header, + Context *on_finish, bool top) { - _enqueue_dentry(dn, NULL, recursive, children, header, on_finish, top); + _enqueue_inode(in, NULL, header, on_finish, top); kick_off_scrubs(); } @@ -85,38 +83,36 @@ void ScrubStack::kick_off_scrubs() dout(20) << __func__ << " entering with " << scrubs_in_progress << " in " "progress and " << stack_size << " in the stack" << dendl; bool can_continue = true; - elist::iterator i = dentry_stack.begin(); + elist::iterator i = inode_stack.begin(); while (g_conf->mds_max_scrub_ops_in_progress > scrubs_in_progress && can_continue && !i.end()) { - CDentry *cur = *i; - - dout(20) << __func__ << " examining dentry " << *cur << dendl; - - CInode *curi = cur->get_projected_inode(); + CInode *curi = *i; ++i; // we have our reference, push iterator forward + dout(20) << __func__ << " examining " << *curi << dendl; + if (!curi->is_dir()) { // it's a regular file, symlink, or hard link - pop_dentry(cur); // we only touch it this once, so remove from stack + pop_inode(curi); // we only touch it this once, so remove from stack - if (!cur->scrub_info()->on_finish) { + if (!curi->scrub_info()->on_finish) { scrubs_in_progress++; - cur->scrub_set_finisher(&scrub_kick); + curi->scrub_set_finisher(&scrub_kick); } - scrub_file_dentry(cur); + scrub_file_inode(curi); can_continue = true; } else { bool completed; // it's done, so pop it off the stack bool terminal; // not done, but we can start ops on other directories bool progress; // it added new dentries to the top of the stack - scrub_dir_dentry(cur, &progress, &terminal, &completed); + scrub_dir_inode(curi, &progress, &terminal, &completed); if (completed) { dout(20) << __func__ << " dir completed" << dendl; - pop_dentry(cur); + pop_inode(curi); } else if (progress) { dout(20) << __func__ << " dir progressed" << dendl; // we added new stuff to top of stack, so reset ourselves there - i = dentry_stack.begin(); + i = inode_stack.begin(); } else { dout(20) << __func__ << " dir no-op" << dendl; } @@ -126,34 +122,20 @@ void ScrubStack::kick_off_scrubs() } } -void ScrubStack::scrub_dir_dentry(CDentry *dn, - bool *added_children, - bool *terminal, - bool *done) +void ScrubStack::scrub_dir_inode(CInode *in, + bool *added_children, + bool *terminal, + bool *done) { - assert(dn != NULL); - dout(10) << __func__ << *dn << dendl; - - CInode *in = dn->get_projected_inode(); - // FIXME: greg -- is get_version the appropriate version? (i.e. is scrub_version - // // meant to be an actual version that we're scrubbing, or something else?) - if (!in->scrub_info()->scrub_in_progress) { - // We may come through here more than once on our way up and down - // the stack... or actually is that right? Should we perhaps - // only see ourselves once on the way down and once on the way - // back up again, and not do this? - in->scrub_initialize(dn->scrub_info()->header); - } + dout(10) << __func__ << *in << dendl; *added_children = false; bool all_frags_terminal = true; bool all_frags_done = true; - if (!dn->scrub_info()->scrub_children && - !dn->scrub_info()->scrub_recursive) { - dout(20) << "!scrub_children and !scrub_recursive" << dendl; - } else { + const ScrubHeaderRefConst& header = in->scrub_info()->header; + if (header->recursive) { list scrubbing_frags; list scrubbing_cdirs; in->scrub_dirfrags_scrubbing(&scrubbing_frags); @@ -200,8 +182,8 @@ void ScrubStack::scrub_dir_dentry(CDentry *dn, bool frag_added_children = false; bool frag_terminal = true; bool frag_done = false; - scrub_dirfrag(cur_dir, dn->scrub_info()->scrub_recursive, - &frag_added_children, &frag_terminal, &frag_done); + scrub_dirfrag(cur_dir, header, + &frag_added_children, &frag_terminal, &frag_done); if (frag_done) { // FIXME is this right? Can we end up hitting this more than // once and is that a problem? @@ -214,14 +196,17 @@ void ScrubStack::scrub_dir_dentry(CDentry *dn, dout(20) << "finished looping; all_frags_terminal=" << all_frags_terminal << ", all_frags_done=" << all_frags_done << dendl; + } else { + dout(20) << "!scrub_recursive" << dendl; } + if (all_frags_done) { assert (!*added_children); // can't do this if children are still pending // 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 - scrub_dir_dentry_final(dn); + scrub_dir_inode_final(in); } *terminal = all_frags_terminal; @@ -262,9 +247,9 @@ class C_InodeValidated : public MDSInternalContext public: ScrubStack *stack; CInode::validated_data result; - CDentry *target; + CInode *target; - C_InodeValidated(MDSRank *mds, ScrubStack *stack_, CDentry *target_) + C_InodeValidated(MDSRank *mds, ScrubStack *stack_, CInode *target_) : MDSInternalContext(mds), stack(stack_), target(target_) {} @@ -275,9 +260,9 @@ class C_InodeValidated : public MDSInternalContext }; -void ScrubStack::scrub_dir_dentry_final(CDentry *dn) +void ScrubStack::scrub_dir_inode_final(CInode *in) { - dout(20) << __func__ << *dn << dendl; + dout(20) << __func__ << *in << dendl; // Two passes through this function. First one triggers inode validation, // second one sets finally_done @@ -286,24 +271,24 @@ void ScrubStack::scrub_dir_dentry_final(CDentry *dn) // doing our validate_disk_state on the inode // 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) { + if (!in->scrub_info()->children_scrubbed) { + if (!in->scrub_info()->on_finish) { scrubs_in_progress++; - dn->scrub_set_finisher(&scrub_kick); + in->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); + in->scrub_children_finished(); + C_InodeValidated *fin = new C_InodeValidated(mdcache->mds, this, in); in->validate_disk_state(&fin->result, fin); } return; } -void ScrubStack::scrub_dirfrag(CDir *dir, bool recursive, - bool *added_children, - bool *is_terminal, bool *done) +void ScrubStack::scrub_dirfrag(CDir *dir, + const ScrubHeaderRefConst& header, + bool *added_children, bool *is_terminal, + bool *done) { assert(dir != NULL); @@ -312,7 +297,6 @@ void ScrubStack::scrub_dirfrag(CDir *dir, bool recursive, *is_terminal = false; *done = false; - const ScrubHeaderRefConst& header = dir->get_inode()->scrub_info()->header; if (!dir->scrub_info()->directory_scrubbing) { // Get the frag complete before calling @@ -376,58 +360,39 @@ void ScrubStack::scrub_dirfrag(CDir *dir, bool recursive, // never get random IO errors here. assert(r == 0); - // FIXME: Do I *really* need to construct a kick context for every // single dentry I'm going to scrub? - _enqueue_dentry(dn, - dir, - recursive, - false, // We are already recursing so scrub_children not meaningful - header, - NULL, - true); + _enqueue_inode(dn->get_projected_inode(), dn, header, NULL, true); *added_children = true; } } -void ScrubStack::scrub_file_dentry(CDentry *dn) +void ScrubStack::scrub_file_inode(CInode *in) { - assert(dn->get_linkage()->get_inode() != NULL); - - CInode *in = dn->get_projected_inode(); - C_InodeValidated *fin = new C_InodeValidated(mdcache->mds, this, dn); - + C_InodeValidated *fin = new C_InodeValidated(mdcache->mds, this, in); // At this stage the DN is already past scrub_initialize, so // it's in the cache, it has PIN_SCRUBQUEUE and it is authpinned in->validate_disk_state(&fin->result, fin); } -void ScrubStack::_validate_inode_done(CDentry *dn, int r, - const CInode::validated_data &result) +void ScrubStack::_validate_inode_done(CInode *in, int r, + const CInode::validated_data &result) { // FIXME: do something real with result! DamageTable! Spamming // the cluster log for debugging purposes LogChannelRef clog = mdcache->mds->clog; - clog->info() << __func__ << " " << *dn << " r=" << r; + clog->info() << __func__ << " " << *in << " r=" << r; #if 0 - assert(dn->scrub_info_p != NULL); - dn->scrub_info_p->inode_validated = true; + assert(in->scrub_infop != NULL); + in->scrub_infop->inode_validated = true; #endif - const ScrubHeaderRefConst header = dn->scrub_info()->header; + const ScrubHeaderRefConst header = in->scrub_info()->header; Context *c = NULL; - CInode *in = dn->get_projected_inode(); - if (in->is_dir()) { - // For directories, inodes undergo a scrub_init/scrub_finish cycle - in->scrub_finished(&c); - } else { - // For regular files, we never touch the scrub_info on the inode, - // just the dentry. - dn->scrub_finished(&c); - } + in->scrub_finished(&c); - if (!header->recursive && dn == header->origin) { + if (!header->recursive && in == 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 diff --git a/src/mds/ScrubStack.h b/src/mds/ScrubStack.h index 87f3ca242e6f..39dbddcffb26 100644 --- a/src/mds/ScrubStack.h +++ b/src/mds/ScrubStack.h @@ -32,7 +32,7 @@ protected: Finisher *finisher; /// The stack of dentries we want to scrub - elist dentry_stack; + elist inode_stack; /// current number of dentries we're actually scrubbing int scrubs_in_progress; ScrubStack *scrubstack; // hack for dout @@ -55,53 +55,44 @@ public: MDCache *mdcache; ScrubStack(MDCache *mdc, Finisher *finisher_) : finisher(finisher_), - dentry_stack(member_offset(CDentry, item_scrub)), + inode_stack(member_offset(CInode, item_scrub)), scrubs_in_progress(0), scrubstack(this), stack_size(0), scrub_kick(mdc, this), mdcache(mdc) {} ~ScrubStack() { - assert(dentry_stack.empty()); + assert(inode_stack.empty()); assert(!scrubs_in_progress); } /** - * Put a dentry on the top of the scrub stack, so it is the highest priority. + * Put a inode on the top of the scrub stack, so it is the highest priority. * If there are other scrubs in progress, they will not continue scrubbing new * entries until this one is completed. - * @param dn The dentry to scrub - * @param recursive True if we want to recursively scrub the - * entire hierarchy under dn. - * @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 in The inodey to scrub * @param header The ScrubHeader propagated from whereever this scrub * was initiated */ - void enqueue_dentry_top(CDentry *dn, bool recursive, bool children, - const ScrubHeaderRefConst& header, - Context *on_finish) { - enqueue_dentry(dn, recursive, children, header, on_finish, true); + void enqueue_inode_top(CInode *in, const ScrubHeaderRefConst& header, + Context *on_finish) { + enqueue_inode(in, header, on_finish, true); } - /** Like enqueue_dentry_top, but we wait for all pending scrubs before + /** Like enqueue_inode_top, but we wait for all pending scrubs before * starting this one. */ - void enqueue_dentry_bottom(CDentry *dn, bool recursive, bool children, - const ScrubHeaderRefConst& header, - Context *on_finish) { - enqueue_dentry(dn, recursive, children, header, on_finish, false); + void enqueue_inode_bottom(CInode *in, const ScrubHeaderRefConst& header, + Context *on_finish) { + enqueue_inode(in, header, on_finish, false); } private: /** - * Put the dentry at either the top or bottom of the stack, with + * Put the inode at either the top or bottom of the stack, with * the given scrub params, and then try and kick off more scrubbing. */ - void enqueue_dentry(CDentry *dn, bool recursive, bool children, - const ScrubHeaderRefConst& header, + void enqueue_inode(CInode *in, const ScrubHeaderRefConst& header, Context *on_finish, bool top); - void _enqueue_dentry(CDentry *dn, CDir *parent, bool recursive, bool children, - const ScrubHeaderRefConst& header, + void _enqueue_inode(CInode *in, CDentry *parent, const ScrubHeaderRefConst& header, Context *on_finish, bool top); /** * Kick off as many scrubs as are appropriate, based on the current @@ -109,34 +100,32 @@ private: */ void kick_off_scrubs(); /** - * Push a dentry on top of the stack. + * Push a indoe on top of the stack. */ - inline void push_dentry(CDentry *dentry); + inline void push_inode(CInode *in); /** - * Push a dentry to the bottom of the stack. + * Push a inode to the bottom of the stack. */ - inline void push_dentry_bottom(CDentry *dentry); + inline void push_inode_bottom(CInode *in); /** - * Pop the given dentry off the stack. + * Pop the given inode off the stack. */ - inline void pop_dentry(CDentry *dn); + inline void pop_inode(CInode *in); /** - * Scrub a file-representing dentry. - * @param dn The dentry to scrub - * @param progress Out pointer to a bool, which will be set to true. - * @pre dn->get_projected_inode()->is_file()==true; + * Scrub a file inode. + * @param in The indoe to scrub */ - void scrub_file_dentry(CDentry *dn); + void scrub_file_inode(CInode *in); /** * Callback from completion of CInode::validate_disk_state - * @param dn The dentry owning the inode we were validating + * @param in The inode we were validating * @param r The return status from validate_disk_state * @param result Populated results from validate_disk_state */ - void _validate_inode_done(CDentry *dn, int r, - const CInode::validated_data &result); + void _validate_inode_done(CInode *in, int r, + const CInode::validated_data &result); friend class C_InodeValidated; /** @@ -152,15 +141,15 @@ private: * * 4) If all dirfrags have been scrubbed, scrub my inode. * - * @param dn The CDentry to scrub as a directory + * @param in The CInode to scrub as a directory * @param added_dentries set to true if we pushed some of our children * onto the ScrubStack * @param is_terminal set to true if there are no descendant dentries * remaining to start scrubbing. * @param done set to true if we and all our children have finished scrubbing */ - void scrub_dir_dentry(CDentry *dn, bool *added_children, bool *is_terminal, - bool *done); + void scrub_dir_inode(CInode *in, bool *added_children, bool *is_terminal, + bool *done); /** * Make progress on scrubbing a dirfrag. It may return after each of the * following steps, but will report making progress on each one. @@ -175,14 +164,14 @@ private: * progress. Try again later. * */ - void scrub_dirfrag(CDir *dir, bool recursive, + void scrub_dirfrag(CDir *dir, const ScrubHeaderRefConst& header, bool *added_children, bool *is_terminal, bool *done); /** * Scrub a directory-representing dentry. * - * @param dn The CDentry of the directory we're doing final scrub on. + * @param in The directory inode we're doing final scrub on. */ - void scrub_dir_dentry_final(CDentry *dn); + void scrub_dir_inode_final(CInode *in); /** * Get a CDir into memory, and return it if it's already complete.