]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: prevent dirfrag scrub/fragment from running at the same time
authorYan, Zheng <zyan@redhat.com>
Wed, 20 May 2020 03:38:51 +0000 (11:38 +0800)
committerYan, Zheng <zyan@redhat.com>
Mon, 16 Nov 2020 01:02:17 +0000 (09:02 +0800)
When a CDir is in scrub stack, mds should not split/merge it.

Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
src/mds/MDCache.cc
src/mds/ScrubStack.cc
src/mds/ScrubStack.h

index 8dca77d888f75bc54779c6077e796b3765319940..234c630bef3ccfc1f30b37c5e083bad8e637af53 100644 (file)
@@ -11396,12 +11396,12 @@ bool MDCache::can_fragment(CInode *diri, const std::vector<CDir*>& 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;
index 3e66f7603dd9f280ea88b5d4b396676543198a3f..c9df60201955f6d520f660e1c49432d98a6d2e4d 100644 (file)
@@ -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<CDir*>(*it)) {
       MDSContext *ctx = nullptr;
       dir->scrub_aborted(&ctx);
+      dir->auth_unpin(this);
       if (ctx != nullptr) {
        ctx->complete(-ECANCELED);
       }
index 02c17299be1984a0368b804118be9268ed239b67..0259eafb224179a00ac157e4c52a444c9d2362a5 100644 (file)
@@ -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);