]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: scrub pins more inodes than the mds_cache_memory_limit 67808/head
authorsajibreadd <sajibreadd@gmail.com>
Thu, 9 Oct 2025 11:48:35 +0000 (13:48 +0200)
committersajibreadd <sajibreadd@gmail.com>
Mon, 16 Mar 2026 09:45:25 +0000 (10:45 +0100)
For scrubbing dirfrag we are pushing children back into the scrub stack. Instead we can follow the same
strategy for scrub directory and pushing children front of the scrub stack, and in kick_off_scrubs always
start scrubbing from the front of the stack. It will prevent ScrubStack to pinning whole level of the file-system
tree.

Fixes: https://tracker.ceph.com/issues/71167
Signed-off-by: Md Mahamudur Rahaman Sajib <mahamudur.sajib@croit.io>
(cherry picked from commit 581565585ecf8bc85707dc44dff14e130be51188)

Conflicts:
src/mds/ScrubStack.cc

src/mds/ScrubStack.cc
src/mds/ScrubStack.h

index 6675a4e172359ae8467da2bbd7553fb3f0b75214..0562edc4e8daba4bceb65710b36279c0f3e3747d 100644 (file)
@@ -307,16 +307,16 @@ void ScrubStack::kick_off_scrubs()
        }
       }
     } else if (CDir *dir = dynamic_cast<CDir*>(*it)) {
-      auto next = it;
-      ++next;
+      ++it;
+      bool added_children = false;
       bool done = false; // it's done, so pop it off the stack
-      scrub_dirfrag(dir, &done);
+      scrub_dirfrag(dir, &added_children, &done);
       if (done) {
-       dout(20) << __func__ << " dirfrag, done" << dendl;
-       ++it; // child inodes were queued at bottom of stack
-       dequeue(dir);
-      } else {
-       it = next;
+        dout(20) << __func__ << " dirfrag, done" << dendl;
+        dequeue(dir);
+      }
+      if (added_children) {
+        it = scrub_stack.begin();
       }
     } else {
       ceph_assert(0 == "dentry in scrub stack");
@@ -487,7 +487,7 @@ void ScrubStack::scrub_dir_inode_final(CInode *in)
   return;
 }
 
-void ScrubStack::scrub_dirfrag(CDir *dir, bool *done)
+void ScrubStack::scrub_dirfrag(CDir *dir, bool *added_children, bool *done)
 {
   ceph_assert(dir != NULL);
 
@@ -528,7 +528,8 @@ void ScrubStack::scrub_dirfrag(CDir *dir, bool *done)
        continue;
       }
       if (dnl->is_primary()) {
-       _enqueue(dnl->get_inode(), header, false);
+  *added_children = true;
+       _enqueue(dnl->get_inode(), header, true);
       } else if (dnl->is_remote()) {
        // TODO: check remote linkage
       }
index a8b7e870dbf9784615f9c7cfd671e9f0a108b562..c3b8164b38149c2ddb48b1abb6e8696aa19ec5ee 100644 (file)
@@ -235,9 +235,10 @@ private:
    * scrub of the dirfrag.
    *
    * @param dir The dirfrag to scrub (must be auth)
+   * @param added_children set to true if we pushed some of our children
    * @param done set to true if we started to do final scrub
    */
-  void scrub_dirfrag(CDir *dir, bool *done);
+  void scrub_dirfrag(CDir *dir, bool *added_children, bool *done);
   /**
    * Scrub a directory-representing dentry.
    *