diff options
author | Simon Gao <simon29rock@gmail.com> | 2020-05-15 11:19:14 +0200 |
---|---|---|
committer | Yan, Zheng <zyan@redhat.com> | 2020-11-16 02:02:17 +0100 |
commit | b43af152bab2c9f67fe311ba9450e06fd41e82e4 (patch) | |
tree | 232eee17d8d31495c6ca54cddd0ccb389067870a /src/mds/CDir.cc | |
parent | mds: make both CInode and CDir as entities of scrub (diff) | |
download | ceph-b43af152bab2c9f67fe311ba9450e06fd41e82e4.tar.xz ceph-b43af152bab2c9f67fe311ba9450e06fd41e82e4.zip |
mds: change scrub traverse from post-order to breadth-first search
After using breadth-first search, scrubing a dir inode does not need
to wait until all of its descendant difrags/inodes are scrubbed. This
simplfies scrub code a lot. The downside is that a scrubbed dir inode
no longer implies corresponding subtree has been fully scrubbed. It
makes later scrub (without force option) less efficient.
Signed-off-by: Simon Gao <simon29rock@gmail.com>
Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
Diffstat (limited to 'src/mds/CDir.cc')
-rw-r--r-- | src/mds/CDir.cc | 209 |
1 files changed, 15 insertions, 194 deletions
diff --git a/src/mds/CDir.cc b/src/mds/CDir.cc index cab73b2352e..5073c6b4ea3 100644 --- a/src/mds/CDir.cc +++ b/src/mds/CDir.cc @@ -2049,11 +2049,6 @@ void CDir::_omap_fetched(bufferlist& hdrbl, map<string, bufferlist>& omap, wanted_items.clear(); mark_complete(); state_clear(STATE_FETCHING); - - if (scrub_infop && scrub_infop->need_scrub_local) { - scrub_infop->need_scrub_local = false; - scrub_local(); - } } // open & force frags @@ -3469,10 +3464,8 @@ void CDir::scrub_info_create() const std::unique_ptr<scrub_info_t> si(new scrub_info_t()); - si->last_recursive.version = si->recursive_start.version = - pf->recursive_scrub_version; - si->last_recursive.time = si->recursive_start.time = - pf->recursive_scrub_stamp; + si->last_recursive.version = pf->recursive_scrub_version; + si->last_recursive.time = pf->recursive_scrub_stamp; si->last_local.version = pf->localized_scrub_version; si->last_local.time = pf->localized_scrub_stamp; @@ -3488,227 +3481,55 @@ void CDir::scrub_initialize(const ScrubHeaderRef& header, MDSContext* f) scrub_info(); scrub_infop->header = header; scrub_infop->on_finish = f; -} - -void CDir::scrub_initialize_data() -{ - dout(20) << __func__ << dendl; - ceph_assert(is_complete()); - - // FIXME: weird implicit construction, is someone else meant - // to be calling scrub_info_create first? - scrub_info(); - ceph_assert(scrub_infop && !scrub_infop->directory_scrubbing); - - scrub_infop->recursive_start.version = get_projected_version(); - scrub_infop->recursive_start.time = ceph_clock_now(); - - scrub_infop->directories_to_scrub.clear(); - scrub_infop->directories_scrubbing.clear(); - scrub_infop->directories_scrubbed.clear(); - scrub_infop->others_to_scrub.clear(); - scrub_infop->others_scrubbing.clear(); - scrub_infop->others_scrubbed.clear(); - - for (auto i = items.begin(); - i != items.end(); - ++i) { - // TODO: handle snapshot scrubbing - if (i->first.snapid != CEPH_NOSNAP) - continue; - - CDentry::linkage_t *dnl = i->second->get_projected_linkage(); - if (dnl->is_primary()) { - if (dnl->get_inode()->is_dir()) - scrub_infop->directories_to_scrub.insert(i->first); - else - scrub_infop->others_to_scrub.insert(i->first); - } else if (dnl->is_remote()) { - // TODO: check remote linkage - } - } scrub_infop->directory_scrubbing = true; } void CDir::scrub_aborted(MDSContext **c) { dout(20) << __func__ << dendl; - ceph_assert(scrub_infop && scrub_infop->directory_scrubbing); + ceph_assert(scrub_is_in_progress()); *c = scrub_infop->on_finish; scrub_infop->on_finish = nullptr; scrub_infop->directory_scrubbing = false; - scrub_infop->need_scrub_local = false; scrub_infop->last_scrub_dirty = false; - scrub_infop->pending_scrub_error = false; - scrub_infop->dirty_scrub_stamps.clear(); scrub_infop.reset(); } void CDir::scrub_finished(MDSContext **c) { dout(20) << __func__ << dendl; - ceph_assert(scrub_infop && scrub_infop->directory_scrubbing); - - ceph_assert(scrub_infop->directories_to_scrub.empty()); - ceph_assert(scrub_infop->directories_scrubbing.empty()); - scrub_infop->directories_scrubbed.clear(); - ceph_assert(scrub_infop->others_to_scrub.empty()); - ceph_assert(scrub_infop->others_scrubbing.empty()); - scrub_infop->others_scrubbed.clear(); + ceph_assert(scrub_is_in_progress()); scrub_infop->directory_scrubbing = false; - scrub_infop->last_recursive = scrub_infop->recursive_start; + scrub_infop->last_local.time = ceph_clock_now(); + scrub_infop->last_local.version = get_version(); + if (scrub_infop->header->get_recursive()) + scrub_infop->last_recursive = scrub_infop->last_local; + scrub_infop->last_scrub_dirty = true; *c = scrub_infop->on_finish; scrub_infop->on_finish = nullptr; } -int CDir::_next_dentry_on_set(dentry_key_set &dns, bool missing_okay, - MDSContext *cb, CDentry **dnout) -{ - dentry_key_t dnkey; - CDentry *dn; - - while (!dns.empty()) { - set<dentry_key_t>::iterator front = dns.begin(); - dnkey = *front; - dn = lookup(dnkey.name); - if (!dn) { - if (!is_complete() && - (!has_bloom() || is_in_bloom(dnkey.name))) { - // need to re-read this dirfrag - fetch(cb); - return EAGAIN; - } - // okay, we lost it - if (missing_okay) { - dout(15) << " we no longer have directory dentry " - << dnkey.name << ", assuming it got renamed" << dendl; - dns.erase(dnkey); - continue; - } else { - dout(5) << " we lost dentry " << dnkey.name - << ", bailing out because that's impossible!" << dendl; - ceph_abort(); - } - } - // okay, we got a dentry - dns.erase(dnkey); - - if (dn->get_projected_version() < scrub_infop->last_recursive.version && - !(scrub_infop->header->get_force())) { - dout(15) << " skip dentry " << dnkey.name - << ", no change since last scrub" << dendl; - continue; - } - - if (!dn->get_linkage()->is_primary()) { - dout(15) << " skip dentry " << dnkey.name - << ", no longer primary" << dendl; - continue; - } - - *dnout = dn; - return 0; - } - *dnout = NULL; - return ENOENT; -} - -int CDir::scrub_dentry_next(MDSContext *cb, CDentry **dnout) -{ - dout(20) << __func__ << dendl; - ceph_assert(scrub_infop && scrub_infop->directory_scrubbing); - - dout(20) << "trying to scrub directories underneath us" << dendl; - int rval = _next_dentry_on_set(scrub_infop->directories_to_scrub, true, - cb, dnout); - if (rval == 0) { - dout(20) << __func__ << " inserted to directories scrubbing: " - << *dnout << dendl; - scrub_infop->directories_scrubbing.insert((*dnout)->key()); - } else if (rval == EAGAIN) { - // we don't need to do anything else - } else { // we emptied out the directory scrub set - ceph_assert(rval == ENOENT); - dout(20) << "no directories left, moving on to other kinds of dentries" - << dendl; - - rval = _next_dentry_on_set(scrub_infop->others_to_scrub, false, cb, dnout); - if (rval == 0) { - dout(20) << __func__ << " inserted to others scrubbing: " - << *dnout << dendl; - scrub_infop->others_scrubbing.insert((*dnout)->key()); - } - } - dout(20) << " returning " << rval << " with dn=" << *dnout << dendl; - return rval; -} - -std::vector<CDentry*> CDir::scrub_dentries_scrubbing() -{ - dout(20) << __func__ << dendl; - ceph_assert(scrub_infop && scrub_infop->directory_scrubbing); - - std::vector<CDentry*> result; - for (auto& scrub_info : scrub_infop->directories_scrubbing) { - CDentry *d = lookup(scrub_info.name, scrub_info.snapid); - ceph_assert(d); - result.push_back(d); - } - for (auto& scrub_info : scrub_infop->others_scrubbing) { - CDentry *d = lookup(scrub_info.name, scrub_info.snapid); - ceph_assert(d); - result.push_back(d); - } - return result; -} - -void CDir::scrub_dentry_finished(CDentry *dn) -{ - dout(20) << __func__ << " on dn " << *dn << dendl; - ceph_assert(scrub_infop && scrub_infop->directory_scrubbing); - dentry_key_t dn_key = dn->key(); - if (scrub_infop->directories_scrubbing.erase(dn_key)) { - scrub_infop->directories_scrubbed.insert(dn_key); - } else { - ceph_assert(scrub_infop->others_scrubbing.count(dn_key)); - scrub_infop->others_scrubbing.erase(dn_key); - scrub_infop->others_scrubbed.insert(dn_key); - } -} - void CDir::scrub_maybe_delete_info() { if (scrub_infop && !scrub_infop->directory_scrubbing && - !scrub_infop->need_scrub_local && - !scrub_infop->last_scrub_dirty && - !scrub_infop->pending_scrub_error && - scrub_infop->dirty_scrub_stamps.empty()) { + !scrub_infop->last_scrub_dirty) scrub_infop.reset(); - } } bool CDir::scrub_local() { ceph_assert(is_complete()); - bool rval = check_rstats(true); - - scrub_info(); - if (rval) { - scrub_infop->last_local.time = ceph_clock_now(); - scrub_infop->last_local.version = get_projected_version(); - scrub_infop->pending_scrub_error = false; - scrub_infop->last_scrub_dirty = true; - } else { - scrub_infop->pending_scrub_error = true; - if (scrub_infop->header->get_repair()) - mdcache->repair_dirfrag_stats(this); + bool good = check_rstats(true); + if (!good && scrub_infop->header->get_repair()) { + mdcache->repair_dirfrag_stats(this); + scrub_infop->header->set_repaired(); } - return rval; + return good; } std::string CDir::get_path() const |