mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Ian Kent <raven@themaw.net>
To: Christian Brauner <brauner@kernel.org>
Cc: Al Viro <viro@zeniv.linux.org.uk>,
	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: Re: [RFC PATCH] vfs: limit directory child dentry retention
Date: Wed, 1 Apr 2026 10:10:55 +0800	[thread overview]
Message-ID: <d8e591a1-d105-408f-b794-48573e1aa2fd@themaw.net> (raw)
In-Reply-To: <20260331-engste-raushalten-f66cd264ce77@brauner>

On 31/3/26 17:39, Christian Brauner wrote:
> On Tue, Mar 31, 2026 at 09:29:09AM +0800, Ian Kent wrote:
>> 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.
> Fwiw, there's also e6957c99dca5 ("vfs: Add a sysctl for automated deletion of dentry")

I'm pretty sure I saw that earlier on but had forgotten about it when I

reviewed the bug this time around. It is essentially 681ce8623567 ("vfs:

Delete the associated dentry when deleting a file") with opt-in of course.


>
> This patch introduces the concept conditionally, where the associated
> dentry is deleted only when the user explicitly opts for it during file
> removal. A new sysctl fs.automated_deletion_of_dentry is added for this
> purpose. Its default value is set to 0.

I meant to update Documentation/admin-guide/sysctl/fs.rst to also say that

setting dir-stale-max to 0 disables it. I also get the impression you might

feel better about this if the default was 0 as well.


The thing that I don't much like with the d_delete() approach is that it

fails to cater for files that have been closed and are otherwise unused

who's dentries make there way to the LRU eventually resulting in the bad

behaviour being discussed.


>
> I have no massive objections to your approach. It feels a bit hacky tbh
> as it seems to degrade performance for new workloads in favor old
> workloads. The LRU should sort this out though.

My aim was to improve performance so I'm a bit puzzled by the comment.


The problem is the sheer number of dentry objects and the consequences

of that. Hash table chains growing will affect performance, umounting

the mount will take ages, and there are cases of child dentry traversals

in the VFS. Once you get a large number of stale dentries that necessarily

need to stay linked into the structures to get the benefit of caching your

exposed to this problem.


The LRU mechanism is so far unable to cope with this.


Ian

>
>> 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
>>

  parent reply	other threads:[~2026-04-01  2:11 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 ` [RFC PATCH] vfs: limit " Ian Kent
2026-03-31  9:39   ` 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 [this message]
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=d8e591a1-d105-408f-b794-48573e1aa2fd@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®