mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Ian Kent <raven@themaw.net>
To: Christian Brauner <brauner@kernel.org>,
	Al Viro <viro@zeniv.linux.org.uk>
Cc: Ian Kent <raven@themaw.net>, Miklos Szeredi <miklos@szeredi.hu>,
	Eric Sandeen <sandeen@sandeen.net>,
	Frank Sorenson <fsorenso@redhat.com>,
	Jay Shin <jaeshin@redhat.com>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Yafang Shao <laoar.shao@gmail.com>, Jan Kara <jack@suse.cz>,
	Waiman Long <longman@redhat.com>,
	Matthew Wilcox <willy@infradead.org>,
	Wangkai <wangkai86@huawei.com>,
	Colin Walters <walters@verbum.org>,
	linux-fsdevel <linux-fsdevel@vger.kernel.org>,
	Kernel Mailing List <linux-kernel@vger.kernel.org>
Subject: [RFC PATCH] vfs: limit directory child dentry retention
Date: Tue, 31 Mar 2026 09:29:09 +0800	[thread overview]
Message-ID: <20260331012925.74840-2-raven@themaw.net> (raw)
In-Reply-To: <20260331012925.74840-1-raven@themaw.net>

If there's a very large number of children present in a directory dentry
then the benifit from retaining stale child dentries for re-use can
become ineffective. Even hashed lookup can become ineffective as hash
chains grow, time taken to umount a file system can increase a lot, as
well as child dentry traversals resulting in lock held too long log
messages.

But when a directory dentry has a very large number of children the
parent dentry reference count is dominated by the contribution of its
children. So it makes sense to not retain dentries if the parent
reference count is large.

Setting some large high water mark (eg. 500000) over which dentries
are discarded instead of retained on final dput() would help a lot
by preventing dentry caching contributing to the problem.

Signed-off-by: Ian Kent <raven@themaw.net>
---
 Documentation/admin-guide/sysctl/fs.rst |  7 +++++++
 fs/dcache.c                             | 28 +++++++++++++++++++++++++
 2 files changed, 35 insertions(+)

diff --git a/Documentation/admin-guide/sysctl/fs.rst b/Documentation/admin-guide/sysctl/fs.rst
index 9b7f65c3efd8..7649254f2d0d 100644
--- a/Documentation/admin-guide/sysctl/fs.rst
+++ b/Documentation/admin-guide/sysctl/fs.rst
@@ -75,6 +75,13 @@ negative dentries which do not map to any files. Instead,
 they help speeding up rejection of non-existing files provided
 by the users.
 
+dir-stale-max
+-------------
+
+Used to limit the number of stale child dentries retained in a
+directory before the benifit of caching the dentry is negated by
+the cost of traversing hash buckets during lookups or enumerating
+the directory children. Initially set to 500000.
 
 file-max & file-nr
 ------------------
diff --git a/fs/dcache.c b/fs/dcache.c
index 7ba1801d8132..298b4c3b1493 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -86,6 +86,14 @@ __cacheline_aligned_in_smp DEFINE_SEQLOCK(rename_lock);
 
 EXPORT_SYMBOL(rename_lock);
 
+static long dsm_zero = 0;
+static long dsm_max = ULONG_MAX/2;
+
+/* Highwater mark for number of stale entries in a directory (loosely
+ * measured by parent dentry reference count).
+ */
+static unsigned long dir_stale_max __read_mostly = 500000;
+
 static struct kmem_cache *__dentry_cache __ro_after_init;
 #define dentry_cache runtime_const_ptr(__dentry_cache)
 
@@ -216,6 +224,15 @@ static const struct ctl_table fs_dcache_sysctls[] = {
 		.extra1		= SYSCTL_ZERO,
 		.extra2		= SYSCTL_ONE,
 	},
+	{
+		.procname	= "dir-stale-max",
+		.data		= &dir_stale_max,
+		.maxlen		= sizeof(dir_stale_max),
+		.mode		= 0644,
+		.proc_handler	= proc_doulongvec_minmax,
+		.extra1		= &dsm_zero,
+		.extra2		= &dsm_max,
+	},
 };
 
 static const struct ctl_table vm_dcache_sysctls[] = {
@@ -768,6 +785,17 @@ static inline bool retain_dentry(struct dentry *dentry, bool locked)
 	if (unlikely(d_flags & DCACHE_DONTCACHE))
 		return false;
 
+	if (dir_stale_max) {
+		unsigned long p_count;
+
+		// If the parent reference count is higher than some large value
+		// its dominated by the contribution of its children so there's
+		// no benefit caching the dentry over re-allocating it.
+		p_count = READ_ONCE(dentry->d_parent->d_lockref.count);
+		if (unlikely(p_count > dir_stale_max))
+			return false;
+	}
+
 	// At this point it looks like we ought to keep it.  We also might
 	// need to do something - put it on LRU if it wasn't there already
 	// and mark it referenced if it was on LRU, but not marked yet.
-- 
2.53.0


  reply	other threads:[~2026-03-31  1:30 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-31  1:29 [RFC PATCH] Limit " Ian Kent
2026-03-31  1:29 ` Ian Kent [this message]
2026-03-31  9:39   ` [RFC PATCH] vfs: limit " Christian Brauner
2026-03-31  9:54     ` Gao Xiang
2026-03-31 14:59       ` Mateusz Guzik
2026-03-31 15:11         ` Gao Xiang
2026-04-01  1:38       ` Ian Kent
2026-04-01  1:47         ` Gao Xiang
2026-04-01  2:21           ` Ian Kent
2026-04-01  2:40             ` Linus Torvalds
2026-04-01  2:10     ` Ian Kent
2026-04-07 10:35       ` Christian Brauner
2026-04-07 12:41         ` Ian Kent
2026-04-08 10:17           ` Jan Kara
2026-04-09  0:59             ` Ian Kent

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260331012925.74840-2-raven@themaw.net \
    --to=raven@themaw.net \
    --cc=brauner@kernel.org \
    --cc=fsorenso@redhat.com \
    --cc=jack@suse.cz \
    --cc=jaeshin@redhat.com \
    --cc=laoar.shao@gmail.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=longman@redhat.com \
    --cc=miklos@szeredi.hu \
    --cc=sandeen@sandeen.net \
    --cc=torvalds@linux-foundation.org \
    --cc=viro@zeniv.linux.org.uk \
    --cc=walters@verbum.org \
    --cc=wangkai86@huawei.com \
    --cc=willy@infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®