|
|
Log in / Subscribe / Register

Limiting negative dentries

By Jake Edge
July 3, 2026

LSFMM+BPF

A number of problems related to negative directory entries (dentries) were the topic of a filesystem-track session at the 2026 Linux Storage, Filesystem, Memory Management, and BPF Summit. Negative dentries are used to indicate that a file of a given name does not exist in a directory; it is an optimization that short-circuits the lookup of the file name when the answer is already known. Miklos Szeredi led a session that discussed some problems that come from having too many negative dentries for a directory.

He began by noting that Ian Kent had reported a problem with hundreds of millions of negative dentries for a directory; in that case, the fsnotify_set_children_dentry_flags() call was made, which will iterate over all of the dentries in the directory and cause a soft lockup. A related issue is that the reference count field of the d_lockref lock in struct dentry can overflow if enough dentries are created, Szeredi said. It is not negative-dentry-specific, but it would be hard to create two-billion positive dentries for a directory. Kent had also mentioned that the hash chains may grow too long when there are so many negative dentries, but Szeredi is not sure that is a real problem.

Amir Goldstein had previously suggested moving the negative dentries to the end of the d_children list in struct dentry, Szeredi said. That would allow iterators like fsnotify_set_children_dentry_flags() to stop when they reach the first negative dentry. Chuck Lever was concerned that the order of child dentries might be exposed via getdents(), thus moving the negative dentries might cause reordering in a way that would break users of getdents(); Szeredi did not think that would be a problem, however. An alternative might be to add calls to cond_resched() into the code that walks the d_children list, Szeredi said; that would be more complex but would also address any soft lockups that are caused by positive dentries, not just those from negative dentries.

Jan Kara was also concerned that moving negative dentries to the end might cause ordering problems if one of those dentries is changed to a positive dentry when a file is created. Some of the child-walking iterators depend on not missing any entries, he believes, so there could be problems inserting the updated dentry into the d_children list. "I am not saying it's impossible, I am just not sure whether there will not be some catch." Szeredi said that he thought the iterators' locking would prevent those kinds of problems as long as the dentry update also used that lock.

David Howells raised the idea of switching the data structure used to track the children to something more suited to handling massive numbers of negative dentries. He did not have a concrete suggestion for what that data structure might be, however. Christian Brauner said that "in principle there is nothing stopping us from changing the data structure", though it would require agreement from others.

Brauner asked about a patch set from Kent that would limit the number of dentries that could accumulate for the children of a directory. Brauner thinks that some kind of heuristic limit on dentries should be explored, separate from possible limits on negative dentries. That could perhaps lead to a "meaningful heuristic that isn't just a sysfs file" to better manage negative dentries. The problem with the accumulation of too many negative dentries has been around for ten years or more, he said; it is time to fix it.

There is an opportunity to add to the existing sysfs knob (dentry-negative), Brauner said. The current default is "we will swamp your RAM with all of the dentries that we want", which is fine for some workloads. Other users have complained about accumulating negative dentries, which is why dentry-negative can be set to one to cause unlink() to remove the dentry rather than turn it into a negative one. That does not solve the negative-dentry problem for everyone, however, so more options may be needed.

Szeredi pointed out that user space would have to be in charge of managing that. "Yes, that's my solution for everything", Brauner said to laughter. It is often the case that user space is better placed to determine these kinds of things, he continued. "Pushing everything out to user space, a la BPF, isn't a great solution always, but for a lot of that stuff we see that it actually works." He pointed to the out-of-memory (OOM) killer as an example where the kernel really cannot make a sensible choice for all workloads so user space is better placed to do so.

Jeff Layton agreed that policy choices should be left to user space. However, Ted Ts'o noted that doing so is in tension with "decades of experience that users never change the defaults"; he suggested that sophisticated users have a knob available, but that the default work well for the common case. He thought that perhaps a limit of 1,000 negative dentries per directory would be sufficient for "all sane workloads", but surely "my imagination is failing me". He would like to find out about workloads where that limit would be a problem in order to understand what other options might make sense.

The overflow of the reference count for the per-dentry lock, which came up as part of the too-many-dentries problem, is serious, Brauner said. It requires two-billion dentries, Kara said, so it is hard to hit. Brauner wondered if there could be some kind of built-in limit so that it could not happen. Layton asked if the count was actually overflowing, but Szeredi said it was a theoretical problem, not one that has been reported.

Goldstein asked whether the superblock shrinkers prioritized negative dentries for eviction and reclaiming. Layton said that they probably do not since the dentries are maintained on a least-recently used (LRU) basis. Goldstein wondered if that should change. While Kara thought that perhaps it should, Szeredi pointed out that the problems occur on systems with too much memory so that the shrinkers are not being run at all.

There was some unfocused talk about ways to limit the count and avoid the overflow as time ran out on the session.


Index entries for this article
KernelDentry cache
ConferenceStorage, Filesystem, Memory-Management and BPF Summit/2026


to post comments

what workflow creates so many negative dentries?

Posted Jul 3, 2026 16:22 UTC (Fri) by jepler (subscriber, #105975) [Link] (4 responses)

I'm trying to imagine why this would occur with a non-pathological program. C compilers when searching an include path could create thousands, possibly... But doesn't software mostly try to open files that exist?

what workflow creates so many negative dentries?

Posted Jul 3, 2026 18:37 UTC (Fri) by jake (editor, #205) [Link]

> I'm trying to imagine why this would occur with a non-pathological program.

It seems I failed to work in a link to a previous LSFMM+BPF session on negative dentries, which I meant to do: https://lwn.net/Articles/894098/

That has some information on workloads that end up with huge numbers of negative dentries. As do some of the links from it (and links from those links :) It is a longstanding problem as can be seen in our index entry: https://lwn.net/Kernel/Index/#Dentry_cache

jake

what workflow creates so many negative dentries?

Posted Jul 4, 2026 11:54 UTC (Sat) by mokki (subscriber, #33200) [Link]

I saw the soft lockups from negative dentries regularly 15 years ago. It was on a huge (at the time) build machine.
It just repeated endlessly: git checkout, build, rm -rf
Each round left all the files as negative dentries.
And when the system finally ran out of memory it basically locked up for minutes and would not clear most of the dentries.
I had to run a cron job in th background to flush then regularly

what workflow creates so many negative dentries?

Posted Jul 5, 2026 0:29 UTC (Sun) by mathstuf (subscriber, #69389) [Link]

> I'm trying to imagine why this would occur with a non-pathological program.

Content-addressed storage caches could do this.

what workflow creates so many negative dentries?

Posted Jul 7, 2026 3:46 UTC (Tue) by whack (subscriber, #184251) [Link]

I ran into this in production on Kubernetes. Symptoms were that pods (processes) were being evicted for no clear reason, but Kubernetes said it was due to memory pressure.

The problem? Negative dentries filling the filesystem cache!

Turns out, the blame was a health check a script for that process. It called curl every few seconds to check for health, and curl was adding 5mb to the cache (negative dentries!) every time it ran. It took a while but then suddenly poof! Process evicted due to using too much memory.

It’s a bug that still shows as open. Here’s two comments I made on it with extra details:

Report: https://github.com/kubernetes/kubernetes/issues/43916#iss...
Workaround: https://github.com/kubernetes/kubernetes/issues/43916#iss...

preempt_lazy?

Posted Jul 4, 2026 11:24 UTC (Sat) by meyert (subscriber, #32097) [Link] (1 responses)

Maybe stupid question regarding cond_resched() isn't that something PREEMPT_LAZY is supposed to solve?

preempt_lazy?

Posted Jul 4, 2026 19:59 UTC (Sat) by neilbrown (subscriber, #359) [Link]

You need to hold a lock to walk the list, so it would be cond_resched_lock() except that if you drop the lock you might lose your place so it really becomes
If (need_resched()) {
       insert_dcache_cursor();
       spin_unlock();
       cond_resched();
       spin_lock();
       remove_cursor();
}

Why list negative children?

Posted Jul 4, 2026 20:10 UTC (Sat) by neilbrown (subscriber, #359) [Link] (3 responses)

I thought keeping negatives at the end of the child list would be good too, until I looked at the code.
The children list is an hlist so there is only a pointer to head, not to tail. So you can only add to the head.

So next thought: why put negative dentries on the children list at all? I cannot think of any good reason.

Leaving them off wouldn't solve all the problems, but it would solve one important one.

Why list negative children?

Posted Jul 4, 2026 21:10 UTC (Sat) by willy (subscriber, #9762) [Link] (2 responses)

When you rm a directory, you can delete all its negative dentry children too

Why list negative children?

Posted Jul 4, 2026 21:52 UTC (Sat) by sdalley (subscriber, #18550) [Link]

Does this happen automatically on directory deletion these days? Or is there a simple step one can take from user space to ensure it?

Why list negative children?

Posted Jul 4, 2026 22:27 UTC (Sat) by neilbrown (subscriber, #359) [Link]

> When you rm a directory, you can delete all its negative dentry children too

Yes, that is a slight advantage of listing the negative children, but is it worth the cost?

I imagine that the sibling linkage would be used to keep negative dentries on a per-superblock list which allows them to be purged at unmount time. This could also serve as an lru list which might be purged more proactively.
Most of the dentries on this list are uninteresting, but we cannot be sure which. Certainly the children of a deleted parent are definitely uninteresting so the proactive purge would get rid of them more forcefully, but do we need more than that.

I can imagine removing a directory tree might create a great many negative dentries which might tip the balance. We could get an approximate count of these based on the remaining refcount on a directory when it is deleted, and use that to expedite the purge.

Or we could possibly keep the negative-children chain in the directory inode, possibly unioned with i_devices and i_linklen.

Are negative dentries the right abstraction in the first place?

Posted Jul 4, 2026 20:56 UTC (Sat) by NYKevin (subscriber, #129325) [Link] (1 responses)

Whenever I hear about negative dentries, the first thing I think of is a bloom filter. A bloom filter isn't quite the right data structure for this problem, or at least I don't think it is, but it's surprisingly close.

A bloom filter is a probabilistic data structure with two operations: insert and query. You insert keys (usually strings), and can later query for whether a given key was inserted. The filter will return either "maybe" or "no." This isn't useful as a direct substitute for negative dentries, because (assuming the keys represent non-existing dentries) both answers require us to take the slow path. We would need a data structure that returns "maybe" or "yes" (so that we can skip the slow path on a "yes").

Unfortunately, all of the materials I found on the web suggest that the closest equivalent to such an "inverse Bloom filter" is some kind of cache, which is exactly what negative dentries already are.

So then the question is whether we're allowed to make more substantial refactors. For example, we might give each directory a lazily-initialized bloom filter. Initially, the directory would use negative dentries as in the current design. If the directory is ever fully scanned, however, we would take the opportunity to initialize the bloom filter with all of the *positive* dentries we find on disk, then delete all of its negative dentries and consult the bloom filter instead of looking for negative dentries. We would then need to keep the bloom filter up to date by inserting newly created dentries as we go. If the filter gets too full, we would erase it and go back to using negative dentries until it can be re-initialized. As a bonus, newly-created directories are initially empty, and can be initialized with an empty bloom filter immediately.

Obviously, there are serious concurrency hazards to this approach. My assumption is that the filesystem is capable of guarding against those hazards without a serious performance penalty (because it already must do so for regular read-write conflicts anyway). But I might be wrong about that.

Are negative dentries the right abstraction in the first place?

Posted Jul 5, 2026 6:43 UTC (Sun) by fraetor (subscriber, #161147) [Link]

I'd be somewhat concerned about potential impact on reading positive dentries, especially given that should be the common case. The cost of a bloom filter lookup should be small. but without looking at the code I assume the reading of dentries is already very optimised.

The other problem I see is how to delete a dentrie, as you can't remove something from a bloom filter without rebuilding it entirely. While the probabilistic nature of a bloom filter means you would need to handle that case anyway (its the maybe), a common use case for a negative dentrie would be for a small number of entries queried very frequently, which would lose the performance benefit if deleted. But perhaps these frequently queried files wouldn't have existed in the first place.

Positive to negative ratio

Posted Jul 7, 2026 10:40 UTC (Tue) by Fowl (subscriber, #65667) [Link] (8 responses)

I’m imaging the implementation is probably not simple, but would setting a limit at some ratio of positive entires work? Surely finding the negative entry gets harder than not finding the actual file at some point? Does a directory with 10 files need them at all?

Keeping counts might be difficult, but it doesn’t need to be precise - even just a few buckets maybe.

I guess there’d a potential for a “cliff” (instead of gradual performance degradation) at reaching any limit at all if there’s not been one before.

Positive to negative ratio

Posted Jul 7, 2026 12:25 UTC (Tue) by Klaasjan (subscriber, #4951) [Link]

Just to confirm: I had essentially the same question (but was afraid to ask; not a kernel hacker)

Positive to negative ratio

Posted Jul 7, 2026 13:48 UTC (Tue) by paulj (subscriber, #341) [Link] (1 responses)

I have the same question. Why is the answer not a limit on the -dentry cache list, given there exists some number of entries beyond which the -dentry cache list apparently has a /greater/ cost than just doing the lookup?

Positive to negative ratio

Posted Jul 10, 2026 10:36 UTC (Fri) by neilbrown (subscriber, #359) [Link]

The number of negative dentries is not the problem. The problems are:
- iterating over positive children can be slow
- refcount on parent from negative children can exceed 32bits
- freeing a large number of (negative) dentries may not free much memory due to fragmentation, and may cause excessive memory bus traffic (if I've understood that one properly)

Reducing the number of negative dentries is a large and inappropriate hammer.

Negative dentries can be on a separate list. They can have an indirect ref on the parent. They can, on second reference, be moved to a separate pool of pages of negative dentries (negative dentries do not have ling term references so ate relatively easy to move). These pages can be freed whole, reducing fragmentation.

So we can address each actual problem rather addressing something that loosely correlates with the problems.

Positive to negative ratio

Posted Jul 7, 2026 15:29 UTC (Tue) by farnz (subscriber, #17727) [Link] (4 responses)

The motivating use case for negative dentries is something like the C include path; you write #include <stdio.h> in your source code, and your compiler searches multiple directories for stdio.h. In the case of a default Fedora 44 gcc, there's three before you add any library search paths, in the following order:
  1. Your cwd for "" includes, but not <> includes.
  2. /usr/lib/gcc/x86_64-redhat-linux/16/include - 141 files on my system
  3. /usr/local/include - empty
  4. /usr/include - 270 files.

Most header files are going to be found in /usr/include - /usr/lib/gcc/x86_64-redhat-linux/16/include is only for headers whose content is machine-specific, and /usr/local/include is for cases where you installed a package outside the system package manager's control.. On top of that, you have additional directories added by -I and similar options (including those added by things like pkg-config).

This gets worse for C++, which changes to the following list:

  1. Your cwd for "" includes, but not <> includes.
  2. /usr/lib/gcc/x86_64-redhat-linux/16/../../../../include/c++/16 - 137 files.
  3. /usr/lib/gcc/x86_64-redhat-linux/16/../../../../include/c++/16/x86_64-redhat-linux - 3 files
  4. /usr/lib/gcc/x86_64-redhat-linux/16/../../../../include/c++/16/backward - 8 files
  5. /usr/lib/gcc/x86_64-redhat-linux/16/include
  6. /usr/local/include
  7. /usr/include

So, we need something that's going to quickly return "not present" for all the directories that are earlier in the search path than /usr/include when we search for (say) stdio.h or zlib.h, or the directory vulkan, but that's not going to consume a lot of resources. Negative dentries are supposed to be that thing - so the question is how many negative dentries are reasonable to record before it'd be cheaper to just do a full lookup.

In turn, that means that the "right" number of negative dentries for directories in the search path for the C compiler before /usr/include is a function of the number of files in /usr/include, and not any function of the number of files in those directories. If you have a lot of libraries installing headers in there, then the right number can be quite large.

And related to that is cache management policy; while positive dentries are limited to the number of directory entries by definition, which dentries we should remove once we have too many dentries is itself a question that needs considering - are you better off removing the negative dentry that tells you that zlib.h is not found in /usr/lib/gcc/x86_64-redhat-linux/16/include, or the positive dentry that tells you that omp.h is found there? The right answer depends on whether you're compiling code that uses GOMP heavily, or code that uses Zlib heavily.

Positive to negative ratio

Posted Jul 7, 2026 16:01 UTC (Tue) by kleptog (subscriber, #1183) [Link] (3 responses)

ISTM what is relevant is the amount of time a dentry is in the cache. Deleting a negative dentry means the next lookup will take longer. So that's the time being saved that needs to be weighed against the extra memory usage and CPU cost of keeping the entry.

I would think that if a negative dentry hasn't been hit in the last minute you can probably toss it. The example posted above where the negative dentries are using up 1GB of memory per minute while never being referenced for me feels like the memory costs far outweighs the benefits.

Positive to negative ratio

Posted Jul 7, 2026 17:15 UTC (Tue) by farnz (subscriber, #17727) [Link]

The same applies to positive dentries, too - while they don't have the cache size explosion potential of negative dentries (being bounded by the number of entries in the directory), it seems wasteful to keep a positive dentry for omp.h that's never referenced again, when you could use the cache space for a negative dentry for limits.h that's being referenced every 90 seconds.

It does feel like the necessary change is to have a size limit on the dentry cache (so that it can't be multiple gigabytes in size), and to have a cache replacement policy that accounts for many dentries never being reused - a split LRU (like the active/inactive lists for page cache), or a LFUDA type policy.

Positive to negative ratio

Posted Jul 7, 2026 18:28 UTC (Tue) by jmgao (subscriber, #104246) [Link] (1 responses)

> I would think that if a negative dentry hasn't been hit in the last minute you can probably toss it.

The compiler include use case is going to be pretty disconnected from any wall-clock time, since the iteration time of an edit-compile-test loop is going to be highly variable.

Positive to negative ratio

Posted Jul 7, 2026 19:10 UTC (Tue) by rgmoore (✭ supporter ✭, #75) [Link]

The issue with compiling is when you have to compile many individual .c files, each of which has the same set of includes. It makes sense to cache that information so you don't have to perform the same expensive file checks again for each .c file. When you get into the test and edit steps of the loop, you can safely flush the cache. It's going to be a really long time before you need to look that information up again, and the cache will repopulate as soon as you compile one file.


Copyright © 2026, Eklektix, Inc.
This article may be redistributed under the terms of the Creative Commons CC BY-SA 4.0 license
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds