From: Yan, Zheng Date: Wed, 20 May 2020 03:38:51 +0000 (+0800) Subject: mds: prevent dirfrag scrub/fragment from running at the same time X-Git-Tag: v16.1.0~577^2~15 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=a4c9bfc5b44ba8802e681c8352b6bf3e3ac9c722;p=ceph.git mds: prevent dirfrag scrub/fragment from running at the same time When a CDir is in scrub stack, mds should not split/merge it. Signed-off-by: "Yan, Zheng" --- diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index 8dca77d888f7..234c630bef3c 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -11396,12 +11396,12 @@ bool MDCache::can_fragment(CInode *diri, const std::vector& dirs) return false; } - if (diri->scrub_is_in_progress()) { - dout(7) << "can_fragment: scrub in progress" << dendl; - return false; - } - for (const auto& dir : dirs) { + if (dir->scrub_is_in_progress()) { + dout(7) << "can_fragment: scrub in progress " << *dir << dendl; + return false; + } + if (dir->state_test(CDir::STATE_FRAGMENTING)) { dout(7) << "can_fragment: already fragmenting " << *dir << dendl; return false; diff --git a/src/mds/ScrubStack.cc b/src/mds/ScrubStack.cc index 3e66f7603dd9..c9df60201955 100644 --- a/src/mds/ScrubStack.cc +++ b/src/mds/ScrubStack.cc @@ -70,6 +70,7 @@ void ScrubStack::_enqueue(MDSCacheObject *obj, ScrubHeaderRef& header, dout(10) << __func__ << " with {" << *dir << "}" << ", on_finish=" << on_finish << ", top=" << top << dendl; // The edge directory must be in memory + dir->auth_pin(this); dir->scrub_initialize(header, on_finish); } else { ceph_assert(0 == "queue dentry to scrub stack"); @@ -197,14 +198,21 @@ void ScrubStack::scrub_dir_inode(CInode *in, bool *added_children, bool *done) for (auto &fg : frags) { CDir *dir = in->get_or_open_dirfrag(mdcache, fg); - if (dir->get_version() == 0) + if (!dir->is_auth()) { + dout(20) << __func__ << " not auth " << *dir << dendl; + // no-op + } else if (!dir->can_auth_pin()) { + dout(20) << __func__ << " freezing/frozen " << *dir << dendl; + dir->add_waiter(CDir::WAIT_UNFREEZE, gather.new_sub()); + } else if (dir->get_version() == 0) { + dout(20) << __func__ << " barebones " << *dir << dendl; dir->fetch(gather.new_sub()); + } } if (gather.has_subs()) { scrubs_in_progress++; gather.set_finisher(&scrub_kick); gather.activate(); - dout(10) << __func__ << " barebones dirfrags, fetching" << dendl; return; } @@ -242,7 +250,6 @@ class C_InodeValidated : public MDSInternalContext } }; - void ScrubStack::scrub_dir_inode_final(CInode *in) { dout(20) << __func__ << " " << *in << dendl; @@ -298,6 +305,7 @@ void ScrubStack::scrub_dirfrag(CDir *dir, bool *done) MDSContext *c = nullptr; dir->scrub_finished(&c); + dir->auth_unpin(this); if (c) finisher->queue(new MDSIOContextWrapper(mdcache->mds, c), 0); @@ -554,6 +562,7 @@ void ScrubStack::abort_pending_scrubs() { } else if (CDir *dir = dynamic_cast(*it)) { MDSContext *ctx = nullptr; dir->scrub_aborted(&ctx); + dir->auth_unpin(this); if (ctx != nullptr) { ctx->complete(-ECANCELED); } diff --git a/src/mds/ScrubStack.h b/src/mds/ScrubStack.h index 02c17299be19..0259eafb2241 100644 --- a/src/mds/ScrubStack.h +++ b/src/mds/ScrubStack.h @@ -181,7 +181,7 @@ private: * Scrub a dirfrag. It queues child dentries, then does final * scrub of the dirfrag. * - * @param dir The dirfrag to scrub + * @param dir The dirfrag to scrub (must be auth) * @param done set to true if we started to do final scrub */ void scrub_dirfrag(CDir *dir, bool *done);