* NFS delegations behavior analysis
@ 2026-06-23 10:01 Piyush Sachdeva
2026-06-23 10:50 ` Jeff Layton
0 siblings, 1 reply; 15+ messages in thread
From: Piyush Sachdeva @ 2026-06-23 10:01 UTC (permalink / raw)
To: linux-nfs, cel, trondmy, sfrench, sprasad; +Cc: vaibsharma
Hi,
Lately I have been running micro benchmarks around the `ls` command and
reading through the code documentation of the NFS client to better
understand the client side caching behavior with and without
delegations.
Understanding so far:
Delegations (both file and directory) are granted by the server to the
client, indefinitely (until revoked or under the watermark) to cache
attributes. The caching of data is a result of the attribute
cache. Hence forth, a directory delegation will cache the directory
attributes and the names of the files in the directory, and a file
delegation will cache the attributes of the file and the file data.
Workload run:
I focused on the 2 workloads below, doing 2 passes of a large flat
directory (with close to 100K files) -
a cold pass, and warm pass using the cache from the cold pass:
- lslr - ls -lR on both runs
- lsmix - ls -R (cold) and then ls -lR (warm)
I also played with the rdirplus behavior using both the default
heuristic behavior and the `rdirplus=force` set at mount time.
Numbers:
actimeo=5s, rdirplus=force, ACLs off, flat_dir
==================================================================
| LSLR | LSMIX
| (ls -lR cold / warm) | (p1 ls -R / p2 ls -lR)
Operation | flat cold | flat warm | flat p1 | flat p2
-----------------+-------------+-----------+-------------+---------
READDIR calls | 27 | 0 | 27 | 0
READDIR recv B | 23,603,024 | 0 | 23,603,024 | 0
call type | readdirplus | -- | readdirplus | --
LOOKUP | 1 | 0 | 1 | 0
GETATTR | 3 | 100,000 | 2 | 100,001
ACCESS | 2 | 0 | 2 | 0
-----------------+-------------+-----------+-------------+---------
Elapsed (age) | ~14 s | ~62 s | ~16 s | ~63 s
Observations:
When doing `ls` or `ls -l` on a directory, due to the open(2) on the
directory, the client gets a directory delegation - caching the
directory attributes and file names. However, as we don't have file
delegations due to no open(2) calls to any of the files. Henceforth,
the cache of file attributes is governed by `actimeo`.
Now here is the interesting bit, if the next `ls -l` is issued after
the `actimeo`, a massive GETATTR storm hits the server, doing stat()
calls for every file in the directory. As a result, the performance of
this warm `ls -l` run ends up being worse than the cold pass. I am
guessing this is most likely due to the compounded "rdirplus" being more
efficient than stat() calls.
Proposal:
For large directories, this ends up being a massive problem, taking 1-2
minutes when enumerating a directory on the warm passes.
- An easier way to tackle this could be to do a rdirplus=[auto | forced]
instead of issuing the stat(2) storm to the server: When the client
notices that there are cache misses, which would be the case of file
attributes, instead of fetching file names from the directory-delegation
cache and attributes from GETATTR, the client does a READDIRPLUS to
the server, nonetheless.
- A more tedious would be the to cache file attributes as well, as a part
of the directory delegation. This would end up requiring a change in the
NFS protocol spec though.
- Bulk GETATTR calls: I am uncertain of the feasibility of this, but
what if, the client could do 1 GETATTR call for getting attributes
for multiple files.
--
Piyush
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: NFS delegations behavior analysis 2026-06-23 10:01 NFS delegations behavior analysis Piyush Sachdeva @ 2026-06-23 10:50 ` Jeff Layton 2026-06-23 11:04 ` Mkrtchyan, Tigran 0 siblings, 1 reply; 15+ messages in thread From: Jeff Layton @ 2026-06-23 10:50 UTC (permalink / raw) To: Piyush Sachdeva, linux-nfs, cel, trondmy, sfrench, sprasad; +Cc: vaibsharma On Tue, 2026-06-23 at 15:31 +0530, Piyush Sachdeva wrote: > Hi, > Lately I have been running micro benchmarks around the `ls` command and > reading through the code documentation of the NFS client to better > understand the client side caching behavior with and without > delegations. > > Understanding so far: > Delegations (both file and directory) are granted by the server to the > client, indefinitely (until revoked or under the watermark) to cache > attributes. The caching of data is a result of the attribute > cache. Hence forth, a directory delegation will cache the directory > attributes and the names of the files in the directory, and a file > delegation will cache the attributes of the file and the file data. > > Workload run: > I focused on the 2 workloads below, doing 2 passes of a large flat > directory (with close to 100K files) - > a cold pass, and warm pass using the cache from the cold pass: > - lslr - ls -lR on both runs > - lsmix - ls -R (cold) and then ls -lR (warm) > > I also played with the rdirplus behavior using both the default > heuristic behavior and the `rdirplus=force` set at mount time. > > Numbers: > actimeo=5s, rdirplus=force, ACLs off, flat_dir > ================================================================== > > | LSLR | LSMIX > | (ls -lR cold / warm) | (p1 ls -R / p2 ls -lR) > Operation | flat cold | flat warm | flat p1 | flat p2 > -----------------+-------------+-----------+-------------+--------- > READDIR calls | 27 | 0 | 27 | 0 > READDIR recv B | 23,603,024 | 0 | 23,603,024 | 0 > call type | readdirplus | -- | readdirplus | -- > LOOKUP | 1 | 0 | 1 | 0 > GETATTR | 3 | 100,000 | 2 | 100,001 > ACCESS | 2 | 0 | 2 | 0 > -----------------+-------------+-----------+-------------+--------- > Elapsed (age) | ~14 s | ~62 s | ~16 s | ~63 s > > > Observations: > When doing `ls` or `ls -l` on a directory, due to the open(2) on the > directory, the client gets a directory delegation - caching the > directory attributes and file names. However, as we don't have file > delegations due to no open(2) calls to any of the files. Henceforth, > the cache of file attributes is governed by `actimeo`. > Now here is the interesting bit, if the next `ls -l` is issued after > the `actimeo`, a massive GETATTR storm hits the server, doing stat() > calls for every file in the directory. As a result, the performance of > this warm `ls -l` run ends up being worse than the cold pass. I am > guessing this is most likely due to the compounded "rdirplus" being more > efficient than stat() calls. > > > Proposal: > For large directories, this ends up being a massive problem, taking 1-2 > minutes when enumerating a directory on the warm passes. > - An easier way to tackle this could be to do a rdirplus=[auto | forced] > instead of issuing the stat(2) storm to the server: When the client > notices that there are cache misses, which would be the case of file > attributes, instead of fetching file names from the directory-delegation > cache and attributes from GETATTR, the client does a READDIRPLUS to > the server, nonetheless. > - A more tedious would be the to cache file attributes as well, as a part > of the directory delegation. This would end up requiring a change in the > NFS protocol spec though. > - Bulk GETATTR calls: I am uncertain of the feasibility of this, but > what if, the client could do 1 GETATTR call for getting attributes > for multiple files. ls is such a hard workload to get right, because we don't really get an indication in the kernel of what userland's intentions are. It's basically a readdir() call followed by a bunch of stat()'s, but at the point where we're getting the readdir() call, we don't know if userland intends to stat() those files or not. We have to make a guess about that intention. In this case, it sounds like the directory cache was valid, so the client decided it didn't need to do a READDIR at all, but the individual files had caches that timed out. So imagine you're the kernel client and have been given that second readdir() call: Why should you decide to do a READDIRPLUS at that point instead of a regular READDIR? -- Jeff Layton <jlayton@kernel.org> ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: NFS delegations behavior analysis 2026-06-23 10:50 ` Jeff Layton @ 2026-06-23 11:04 ` Mkrtchyan, Tigran 2026-06-23 11:10 ` Jeff Layton 2026-06-23 13:11 ` Anna Schumaker 0 siblings, 2 replies; 15+ messages in thread From: Mkrtchyan, Tigran @ 2026-06-23 11:04 UTC (permalink / raw) To: Jeff Layton Cc: Piyush Sachdeva, linux-nfs, Chuck Lever, trondmy, sfrench, sprasad, vaibsharma [-- Attachment #1: Type: text/plain, Size: 5344 bytes --] ----- Original Message ----- > From: "Jeff Layton" <jlayton@kernel.org> > To: "Piyush Sachdeva" <s.piyush1024@gmail.com>, "linux-nfs" <linux-nfs@vger.kernel.org>, "Chuck Lever" <cel@kernel.org>, > "trondmy" <trondmy@kernel.org>, sfrench@samba.org, sprasad@microsoft.com > Cc: vaibsharma@microsoft.com > Sent: Tuesday, 23 June, 2026 12:50:16 > Subject: Re: NFS delegations behavior analysis > On Tue, 2026-06-23 at 15:31 +0530, Piyush Sachdeva wrote: >> Hi, >> Lately I have been running micro benchmarks around the `ls` command and >> reading through the code documentation of the NFS client to better >> understand the client side caching behavior with and without >> delegations. >> >> Understanding so far: >> Delegations (both file and directory) are granted by the server to the >> client, indefinitely (until revoked or under the watermark) to cache >> attributes. The caching of data is a result of the attribute >> cache. Hence forth, a directory delegation will cache the directory >> attributes and the names of the files in the directory, and a file >> delegation will cache the attributes of the file and the file data. >> >> Workload run: >> I focused on the 2 workloads below, doing 2 passes of a large flat >> directory (with close to 100K files) - >> a cold pass, and warm pass using the cache from the cold pass: >> - lslr - ls -lR on both runs >> - lsmix - ls -R (cold) and then ls -lR (warm) >> >> I also played with the rdirplus behavior using both the default >> heuristic behavior and the `rdirplus=force` set at mount time. >> >> Numbers: >> actimeo=5s, rdirplus=force, ACLs off, flat_dir >> ================================================================== >> >> | LSLR | LSMIX >> | (ls -lR cold / warm) | (p1 ls -R / p2 ls -lR) >> Operation | flat cold | flat warm | flat p1 | flat p2 >> -----------------+-------------+-----------+-------------+--------- >> READDIR calls | 27 | 0 | 27 | 0 >> READDIR recv B | 23,603,024 | 0 | 23,603,024 | 0 >> call type | readdirplus | -- | readdirplus | -- >> LOOKUP | 1 | 0 | 1 | 0 >> GETATTR | 3 | 100,000 | 2 | 100,001 >> ACCESS | 2 | 0 | 2 | 0 >> -----------------+-------------+-----------+-------------+--------- >> Elapsed (age) | ~14 s | ~62 s | ~16 s | ~63 s >> >> >> Observations: >> When doing `ls` or `ls -l` on a directory, due to the open(2) on the >> directory, the client gets a directory delegation - caching the >> directory attributes and file names. However, as we don't have file >> delegations due to no open(2) calls to any of the files. Henceforth, >> the cache of file attributes is governed by `actimeo`. >> Now here is the interesting bit, if the next `ls -l` is issued after >> the `actimeo`, a massive GETATTR storm hits the server, doing stat() >> calls for every file in the directory. As a result, the performance of >> this warm `ls -l` run ends up being worse than the cold pass. I am >> guessing this is most likely due to the compounded "rdirplus" being more >> efficient than stat() calls. >> >> >> Proposal: >> For large directories, this ends up being a massive problem, taking 1-2 >> minutes when enumerating a directory on the warm passes. >> - An easier way to tackle this could be to do a rdirplus=[auto | forced] >> instead of issuing the stat(2) storm to the server: When the client >> notices that there are cache misses, which would be the case of file >> attributes, instead of fetching file names from the directory-delegation >> cache and attributes from GETATTR, the client does a READDIRPLUS to >> the server, nonetheless. >> - A more tedious would be the to cache file attributes as well, as a part >> of the directory delegation. This would end up requiring a change in the >> NFS protocol spec though. >> - Bulk GETATTR calls: I am uncertain of the feasibility of this, but >> what if, the client could do 1 GETATTR call for getting attributes >> for multiple files. > > > ls is such a hard workload to get right, because we don't really get an 100% agree. And there were a couple of attempts to address this issue (second ls that is slow). > indication in the kernel of what userland's intentions are. It's > basically a readdir() call followed by a bunch of stat()'s, but at the > point where we're getting the readdir() call, we don't know if userland > intends to stat() those files or not. We have to make a guess about > that intention. > > In this case, it sounds like the directory cache was valid, so the > client decided it didn't need to do a READDIR at all, but the > individual files had caches that timed out. > > So imagine you're the kernel client and have been given that second > readdir() call: Why should you decide to do a READDIRPLUS at that point > instead of a regular READDIR? May we need some kind of client-side heuristics, like on the server side for open-delegations, where after seeing some `stats` for files in the In the same directory, the client will decide to switch to READDIR (v4) to get all attributes in one go. Best regards, Tigran. > -- > Jeff Layton <jlayton@kernel.org> [-- Attachment #2: S/MIME Cryptographic Signature --] [-- Type: application/pkcs7-signature, Size: 2309 bytes --] ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: NFS delegations behavior analysis 2026-06-23 11:04 ` Mkrtchyan, Tigran @ 2026-06-23 11:10 ` Jeff Layton 2026-06-23 13:11 ` Benjamin Coddington 2026-06-23 13:11 ` Anna Schumaker 1 sibling, 1 reply; 15+ messages in thread From: Jeff Layton @ 2026-06-23 11:10 UTC (permalink / raw) To: Mkrtchyan, Tigran, Benjamin Coddington Cc: Piyush Sachdeva, linux-nfs, Chuck Lever, trondmy, sfrench, sprasad, vaibsharma On Tue, 2026-06-23 at 13:04 +0200, Mkrtchyan, Tigran wrote: > > ----- Original Message ----- > > From: "Jeff Layton" <jlayton@kernel.org> > > To: "Piyush Sachdeva" <s.piyush1024@gmail.com>, "linux-nfs" <linux-nfs@vger.kernel.org>, "Chuck Lever" <cel@kernel.org>, > > "trondmy" <trondmy@kernel.org>, sfrench@samba.org, sprasad@microsoft.com > > Cc: vaibsharma@microsoft.com > > Sent: Tuesday, 23 June, 2026 12:50:16 > > Subject: Re: NFS delegations behavior analysis > > > On Tue, 2026-06-23 at 15:31 +0530, Piyush Sachdeva wrote: > > > Hi, > > > Lately I have been running micro benchmarks around the `ls` command and > > > reading through the code documentation of the NFS client to better > > > understand the client side caching behavior with and without > > > delegations. > > > > > > Understanding so far: > > > Delegations (both file and directory) are granted by the server to the > > > client, indefinitely (until revoked or under the watermark) to cache > > > attributes. The caching of data is a result of the attribute > > > cache. Hence forth, a directory delegation will cache the directory > > > attributes and the names of the files in the directory, and a file > > > delegation will cache the attributes of the file and the file data. > > > > > > Workload run: > > > I focused on the 2 workloads below, doing 2 passes of a large flat > > > directory (with close to 100K files) - > > > a cold pass, and warm pass using the cache from the cold pass: > > > - lslr - ls -lR on both runs > > > - lsmix - ls -R (cold) and then ls -lR (warm) > > > > > > I also played with the rdirplus behavior using both the default > > > heuristic behavior and the `rdirplus=force` set at mount time. > > > > > > Numbers: > > > actimeo=5s, rdirplus=force, ACLs off, flat_dir > > > ================================================================== > > > > > > | LSLR | LSMIX > > > | (ls -lR cold / warm) | (p1 ls -R / p2 ls -lR) > > > Operation | flat cold | flat warm | flat p1 | flat p2 > > > -----------------+-------------+-----------+-------------+--------- > > > READDIR calls | 27 | 0 | 27 | 0 > > > READDIR recv B | 23,603,024 | 0 | 23,603,024 | 0 > > > call type | readdirplus | -- | readdirplus | -- > > > LOOKUP | 1 | 0 | 1 | 0 > > > GETATTR | 3 | 100,000 | 2 | 100,001 > > > ACCESS | 2 | 0 | 2 | 0 > > > -----------------+-------------+-----------+-------------+--------- > > > Elapsed (age) | ~14 s | ~62 s | ~16 s | ~63 s > > > > > > > > > Observations: > > > When doing `ls` or `ls -l` on a directory, due to the open(2) on the > > > directory, the client gets a directory delegation - caching the > > > directory attributes and file names. However, as we don't have file > > > delegations due to no open(2) calls to any of the files. Henceforth, > > > the cache of file attributes is governed by `actimeo`. > > > Now here is the interesting bit, if the next `ls -l` is issued after > > > the `actimeo`, a massive GETATTR storm hits the server, doing stat() > > > calls for every file in the directory. As a result, the performance of > > > this warm `ls -l` run ends up being worse than the cold pass. I am > > > guessing this is most likely due to the compounded "rdirplus" being more > > > efficient than stat() calls. > > > > > > > > > Proposal: > > > For large directories, this ends up being a massive problem, taking 1-2 > > > minutes when enumerating a directory on the warm passes. > > > - An easier way to tackle this could be to do a rdirplus=[auto | forced] > > > instead of issuing the stat(2) storm to the server: When the client > > > notices that there are cache misses, which would be the case of file > > > attributes, instead of fetching file names from the directory-delegation > > > cache and attributes from GETATTR, the client does a READDIRPLUS to > > > the server, nonetheless. > > > - A more tedious would be the to cache file attributes as well, as a part > > > of the directory delegation. This would end up requiring a change in the > > > NFS protocol spec though. > > > - Bulk GETATTR calls: I am uncertain of the feasibility of this, but > > > what if, the client could do 1 GETATTR call for getting attributes > > > for multiple files. > > > > > > ls is such a hard workload to get right, because we don't really get an > > 100% agree. And there were a couple of attempts to address this issue > (second ls that is slow). > > > indication in the kernel of what userland's intentions are. It's > > basically a readdir() call followed by a bunch of stat()'s, but at the > > point where we're getting the readdir() call, we don't know if userland > > intends to stat() those files or not. We have to make a guess about > > that intention. > > > > In this case, it sounds like the directory cache was valid, so the > > client decided it didn't need to do a READDIR at all, but the > > individual files had caches that timed out. > > > > So imagine you're the kernel client and have been given that second > > readdir() call: Why should you decide to do a READDIRPLUS at that point > > instead of a regular READDIR? > > May we need some kind of client-side heuristics, like on the server side > for open-delegations, where after seeing some `stats` for files in the > In the same directory, the client will decide to switch to READDIR (v4) > to get all attributes in one go. > Yeah, we definitely do. I'm just not sure what those heuristics look like. I think Ben did the latest pass of trying to tune the heuristics here. Any thoughts on how we could do this better (and whether there are particular ls-ish workloads that we don't want to regress)? -- Jeff Layton <jlayton@kernel.org> ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: NFS delegations behavior analysis 2026-06-23 11:10 ` Jeff Layton @ 2026-06-23 13:11 ` Benjamin Coddington 2026-06-23 13:31 ` Daire Byrne ` (2 more replies) 0 siblings, 3 replies; 15+ messages in thread From: Benjamin Coddington @ 2026-06-23 13:11 UTC (permalink / raw) To: Jeff Layton Cc: Mkrtchyan, Tigran, Benjamin Coddington, Piyush Sachdeva, linux-nfs, Chuck Lever, trondmy, sfrench, sprasad, vaibsharma On 23 Jun 2026, at 7:10, Jeff Layton wrote: > I think Ben did the latest pass of trying to tune the heuristics here. > Any thoughts on how we could do this better (and whether there are > particular ls-ish workloads that we don't want to regress)? I haven't (shame) thought about READDIR in the context of directory delegations. But during my time at Red Hat we worked hard to optimize some readdir problems and I learned that almost any change we made ended up making someone's workload regress. We also found that our performance benchmarks rarely matched the most common real-world workloads. We made the mistake of trying to improve the benchmark which resulted in performance regressions for real-world users. Jeff, you've already touched on the core issue regarding fixing this with bulk GETATTR calls - the kernel doesn't know what syscall pattern the userspace process is going to use next. The `ls -l` command and `find` and friends have complex history and branching logic, they do different lookup and getattr patterns based on their own goals, and NFS cannot optimize for any one case. I think the last time we discussed additional improvements there were some ideas about teaching the readdir code to respond to fadvise flags, but then you'd also need to teach the utilities how to use them as well, and those utilities try to be filesystem-agnostic. Its a tough problem, and sometimes the simplest thing might be to just use more directories on NFS. **coffee!** .... er - so with directory delegations, can we simply re-hydrate the dentry cache from the directory page mappings if the delegation is still valid? Does the directory delegation pin the mapping? Clearly I need to look at the code.. Ben ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: NFS delegations behavior analysis 2026-06-23 13:11 ` Benjamin Coddington @ 2026-06-23 13:31 ` Daire Byrne 2026-06-23 13:32 ` Benjamin Coddington 2026-06-23 13:33 ` Jeff Layton 2 siblings, 0 replies; 15+ messages in thread From: Daire Byrne @ 2026-06-23 13:31 UTC (permalink / raw) To: Benjamin Coddington Cc: Jeff Layton, Mkrtchyan, Tigran, Piyush Sachdeva, linux-nfs, Chuck Lever, trondmy, sfrench, sprasad, vaibsharma On Tue, 23 Jun 2026 at 14:12, Benjamin Coddington <ben.coddington@hammerspace.com> wrote: > > On 23 Jun 2026, at 7:10, Jeff Layton wrote: > > > I think Ben did the latest pass of trying to tune the heuristics here. > > Any thoughts on how we could do this better (and whether there are > > particular ls-ish workloads that we don't want to regress)? > > I haven't (shame) thought about READDIR in the context of directory > delegations. > > But during my time at Red Hat we worked hard to optimize some readdir > problems and I learned that almost any change we made ended up making > someone's workload regress. We also found that our performance benchmarks > rarely matched the most common real-world workloads. We made the mistake of > trying to improve the benchmark which resulted in performance regressions > for real-world users. > > Jeff, you've already touched on the core issue regarding fixing this with > bulk GETATTR calls - the kernel doesn't know what syscall pattern the > userspace process is going to use next. The `ls -l` command and `find` and > friends have complex history and branching logic, they do different lookup > and getattr patterns based on their own goals, and NFS cannot optimize for > any one case. > > I think the last time we discussed additional improvements there were some > ideas about teaching the readdir code to respond to fadvise flags, but then > you'd also need to teach the utilities how to use them as well, and those > utilities try to be filesystem-agnostic. > > Its a tough problem, and sometimes the simplest thing might be to just use > more directories on NFS. > > **coffee!** > > .... er - so with directory delegations, can we simply re-hydrate the dentry > cache from the directory page mappings if the delegation is still valid? > Does the directory delegation pin the mapping? Clearly I need to look at > the code.. > > Ben > I have also long hoped for a way to cache or speed up "negative" lookups using something akin to directory delegations. So if you have your software (e.g. PYTHONPATH) on an NFS share, then negative lookups are a huge scalability problem. It would be nice if a client that got the directory contents could also serve negative lookups until the server told it that something had changed. But as has been explained to me multiple times before, there is no mechanism to say that a client "has the complete cache of directory contents". But I will forever live in hope! This kind of path search walking is also something that is unlikely to ever trigger readdirplus as it does a file and then tries the same file in another directory etc etc. Daire ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: NFS delegations behavior analysis 2026-06-23 13:11 ` Benjamin Coddington 2026-06-23 13:31 ` Daire Byrne @ 2026-06-23 13:32 ` Benjamin Coddington 2026-06-23 13:40 ` Jeff Layton 2026-06-23 16:29 ` Trond Myklebust 2026-06-23 13:33 ` Jeff Layton 2 siblings, 2 replies; 15+ messages in thread From: Benjamin Coddington @ 2026-06-23 13:32 UTC (permalink / raw) To: Benjamin Coddington Cc: Jeff Layton, Mkrtchyan, Tigran, Piyush Sachdeva, linux-nfs, Chuck Lever, trondmy, sfrench, sprasad, vaibsharma On 23 Jun 2026, at 9:11, Benjamin Coddington wrote: > .... er - so with directory delegations, can we simply re-hydrate the dentry > cache from the directory page mappings if the delegation is still valid? > Does the directory delegation pin the mapping? Clearly I need to look at > the code.. .. right - we don't keep the file attributes in the mappings today. And, more to the point - the directory delegation doesn't protect those file attributes either. We'd need NOTIFY4_CHANGE_CHILD_ATTRIBUTES implemented. Ben ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: NFS delegations behavior analysis 2026-06-23 13:32 ` Benjamin Coddington @ 2026-06-23 13:40 ` Jeff Layton 2026-06-23 13:59 ` Benjamin Coddington 2026-06-23 16:29 ` Trond Myklebust 1 sibling, 1 reply; 15+ messages in thread From: Jeff Layton @ 2026-06-23 13:40 UTC (permalink / raw) To: Benjamin Coddington Cc: Mkrtchyan, Tigran, Piyush Sachdeva, linux-nfs, Chuck Lever, trondmy, sfrench, sprasad, vaibsharma On Tue, 2026-06-23 at 09:32 -0400, Benjamin Coddington wrote: > On 23 Jun 2026, at 9:11, Benjamin Coddington wrote: > > > .... er - so with directory delegations, can we simply re-hydrate the dentry > > cache from the directory page mappings if the delegation is still valid? > > Does the directory delegation pin the mapping? Clearly I need to look at > > the code.. > > .. right - we don't keep the file attributes in the mappings today. And, > more to the point - the directory delegation doesn't protect those file > attributes either. We'd need NOTIFY4_CHANGE_CHILD_ATTRIBUTES implemented. > Which I think could be done, at least on the Linux server. fsnotify does support watching for child attribute changes (FS_EVENT_ON_CHILD | FS_ATTRIB). That could be very chatty though. We would need to do the work to make nfsd send callbacks >1 page in order to keep up, I imagine. -- Jeff Layton <jlayton@kernel.org> ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: NFS delegations behavior analysis 2026-06-23 13:40 ` Jeff Layton @ 2026-06-23 13:59 ` Benjamin Coddington 0 siblings, 0 replies; 15+ messages in thread From: Benjamin Coddington @ 2026-06-23 13:59 UTC (permalink / raw) To: Jeff Layton Cc: Benjamin Coddington, Mkrtchyan, Tigran, Piyush Sachdeva, linux-nfs, Chuck Lever, trondmy, sfrench, sprasad, vaibsharma On 23 Jun 2026, at 9:40, Jeff Layton wrote: > On Tue, 2026-06-23 at 09:32 -0400, Benjamin Coddington wrote: >> On 23 Jun 2026, at 9:11, Benjamin Coddington wrote: >> >>> .... er - so with directory delegations, can we simply re-hydrate the dentry >>> cache from the directory page mappings if the delegation is still valid? >>> Does the directory delegation pin the mapping? Clearly I need to look at >>> the code.. >> >> .. right - we don't keep the file attributes in the mappings today. And, >> more to the point - the directory delegation doesn't protect those file >> attributes either. We'd need NOTIFY4_CHANGE_CHILD_ATTRIBUTES implemented. >> > > Which I think could be done, at least on the Linux server. fsnotify > does support watching for child attribute changes (FS_EVENT_ON_CHILD | > FS_ATTRIB). > > That could be very chatty though. We would need to do the work to make > nfsd send callbacks >1 page in order to keep up, I imagine. I agree - it could easily end up having the opposite effect of optimizing performance by amplifying op counts for information the client might not actually use. Ben ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: NFS delegations behavior analysis 2026-06-23 13:32 ` Benjamin Coddington 2026-06-23 13:40 ` Jeff Layton @ 2026-06-23 16:29 ` Trond Myklebust 1 sibling, 0 replies; 15+ messages in thread From: Trond Myklebust @ 2026-06-23 16:29 UTC (permalink / raw) To: Benjamin Coddington Cc: Jeff Layton, Mkrtchyan, Tigran, Piyush Sachdeva, linux-nfs, Chuck Lever, sfrench, sprasad, vaibsharma On Tue, 2026-06-23 at 09:32 -0400, Benjamin Coddington wrote: > On 23 Jun 2026, at 9:11, Benjamin Coddington wrote: > > > .... er - so with directory delegations, can we simply re-hydrate > > the dentry > > cache from the directory page mappings if the delegation is still > > valid? > > Does the directory delegation pin the mapping? Clearly I need to > > look at > > the code.. > > .. right - we don't keep the file attributes in the mappings today. > And, > more to the point - the directory delegation doesn't protect those > file > attributes either. We'd need NOTIFY4_CHANGE_CHILD_ATTRIBUTES > implemented. > > Ben Unlike delegations, notifications are asynchronous by design. Upon reception of a notification, you may deduce that you should revalidate the attributes on a file. However the absence of that notification is insufficient to deduce that it is safe not to revalidate those attributes. So when it comes to informing the client whether to use READDIR or READDIRPLUS, I'm sceptical concerning the value of throwing NOTIFY4_CHANGE_CHILD_ATTRS at the problem. -- Trond Myklebust Linux NFS client maintainer, Hammerspace trondmy@kernel.org, trond.myklebust@hammerspace.com ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: NFS delegations behavior analysis 2026-06-23 13:11 ` Benjamin Coddington 2026-06-23 13:31 ` Daire Byrne 2026-06-23 13:32 ` Benjamin Coddington @ 2026-06-23 13:33 ` Jeff Layton 2 siblings, 0 replies; 15+ messages in thread From: Jeff Layton @ 2026-06-23 13:33 UTC (permalink / raw) To: Benjamin Coddington Cc: Mkrtchyan, Tigran, Piyush Sachdeva, linux-nfs, Chuck Lever, trondmy, sfrench, sprasad, vaibsharma On Tue, 2026-06-23 at 09:11 -0400, Benjamin Coddington wrote: > On 23 Jun 2026, at 7:10, Jeff Layton wrote: > > > I think Ben did the latest pass of trying to tune the heuristics here. > > Any thoughts on how we could do this better (and whether there are > > particular ls-ish workloads that we don't want to regress)? > > I haven't (shame) thought about READDIR in the context of directory > delegations. > > But during my time at Red Hat we worked hard to optimize some readdir > problems and I learned that almost any change we made ended up making > someone's workload regress. We also found that our performance benchmarks > rarely matched the most common real-world workloads. We made the mistake of > trying to improve the benchmark which resulted in performance regressions > for real-world users. > > Jeff, you've already touched on the core issue regarding fixing this with > bulk GETATTR calls - the kernel doesn't know what syscall pattern the > userspace process is going to use next. The `ls -l` command and `find` and > friends have complex history and branching logic, they do different lookup > and getattr patterns based on their own goals, and NFS cannot optimize for > any one case. > > I think the last time we discussed additional improvements there were some > ideas about teaching the readdir code to respond to fadvise flags, but then > you'd also need to teach the utilities how to use them as well, and those > utilities try to be filesystem-agnostic. > > Its a tough problem, and sometimes the simplest thing might be to just use > more directories on NFS. > > **coffee!** > > .... er - so with directory delegations, can we simply re-hydrate the dentry > cache from the directory page mappings if the delegation is still valid? > Does the directory delegation pin the mapping? Clearly I need to look at > the code.. > I think the main problem is not the dcache, but the attributes on the inodes. The first pass uses a full-attrs READDIR (aka readdirplus) and everything goes reasonably quick. Then, on the second pass, the client skips checking directory attributes before trusting the dcache because of the delegation (which is good), but the inodes those dentries point to have an attrcache timeout, and we end up doing a GETATTR for each statx() call when a readdirplus would have been cheaper. I guess after you see a few statx() calls from the same pid on the same directory in a short timeframe you could switch to doing READDIR, but that sounds horrid to get right and keep working. -- Jeff Layton <jlayton@kernel.org> ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: NFS delegations behavior analysis 2026-06-23 11:04 ` Mkrtchyan, Tigran 2026-06-23 11:10 ` Jeff Layton @ 2026-06-23 13:11 ` Anna Schumaker 2026-09-09 10:10 ` Piyush Sachdeva 1 sibling, 1 reply; 15+ messages in thread From: Anna Schumaker @ 2026-06-23 13:11 UTC (permalink / raw) To: Tigran Mkrtchyan, Jeff Layton Cc: Piyush Sachdeva, linux-nfs, Chuck Lever, Trond Myklebust, sfrench, sprasad, vaibsharma On Tue, Jun 23, 2026, at 7:04 AM, Mkrtchyan, Tigran wrote: > ----- Original Message ----- >> From: "Jeff Layton" <jlayton@kernel.org> >> To: "Piyush Sachdeva" <s.piyush1024@gmail.com>, "linux-nfs" <linux-nfs@vger.kernel.org>, "Chuck Lever" <cel@kernel.org>, >> "trondmy" <trondmy@kernel.org>, sfrench@samba.org, sprasad@microsoft.com >> Cc: vaibsharma@microsoft.com >> Sent: Tuesday, 23 June, 2026 12:50:16 >> Subject: Re: NFS delegations behavior analysis > >> On Tue, 2026-06-23 at 15:31 +0530, Piyush Sachdeva wrote: >>> Hi, >>> Lately I have been running micro benchmarks around the `ls` command and >>> reading through the code documentation of the NFS client to better >>> understand the client side caching behavior with and without >>> delegations. >>> >>> Understanding so far: >>> Delegations (both file and directory) are granted by the server to the >>> client, indefinitely (until revoked or under the watermark) to cache >>> attributes. The caching of data is a result of the attribute >>> cache. Hence forth, a directory delegation will cache the directory >>> attributes and the names of the files in the directory, and a file >>> delegation will cache the attributes of the file and the file data. >>> >>> Workload run: >>> I focused on the 2 workloads below, doing 2 passes of a large flat >>> directory (with close to 100K files) - >>> a cold pass, and warm pass using the cache from the cold pass: >>> - lslr - ls -lR on both runs >>> - lsmix - ls -R (cold) and then ls -lR (warm) >>> >>> I also played with the rdirplus behavior using both the default >>> heuristic behavior and the `rdirplus=force` set at mount time. >>> >>> Numbers: >>> actimeo=5s, rdirplus=force, ACLs off, flat_dir >>> ================================================================== >>> >>> | LSLR | LSMIX >>> | (ls -lR cold / warm) | (p1 ls -R / p2 ls -lR) >>> Operation | flat cold | flat warm | flat p1 | flat p2 >>> -----------------+-------------+-----------+-------------+--------- >>> READDIR calls | 27 | 0 | 27 | 0 >>> READDIR recv B | 23,603,024 | 0 | 23,603,024 | 0 >>> call type | readdirplus | -- | readdirplus | -- >>> LOOKUP | 1 | 0 | 1 | 0 >>> GETATTR | 3 | 100,000 | 2 | 100,001 >>> ACCESS | 2 | 0 | 2 | 0 >>> -----------------+-------------+-----------+-------------+--------- >>> Elapsed (age) | ~14 s | ~62 s | ~16 s | ~63 s >>> >>> >>> Observations: >>> When doing `ls` or `ls -l` on a directory, due to the open(2) on the >>> directory, the client gets a directory delegation - caching the >>> directory attributes and file names. However, as we don't have file >>> delegations due to no open(2) calls to any of the files. Henceforth, >>> the cache of file attributes is governed by `actimeo`. >>> Now here is the interesting bit, if the next `ls -l` is issued after >>> the `actimeo`, a massive GETATTR storm hits the server, doing stat() >>> calls for every file in the directory. As a result, the performance of >>> this warm `ls -l` run ends up being worse than the cold pass. I am >>> guessing this is most likely due to the compounded "rdirplus" being more >>> efficient than stat() calls. >>> >>> >>> Proposal: >>> For large directories, this ends up being a massive problem, taking 1-2 >>> minutes when enumerating a directory on the warm passes. >>> - An easier way to tackle this could be to do a rdirplus=[auto | forced] >>> instead of issuing the stat(2) storm to the server: When the client >>> notices that there are cache misses, which would be the case of file >>> attributes, instead of fetching file names from the directory-delegation >>> cache and attributes from GETATTR, the client does a READDIRPLUS to >>> the server, nonetheless. >>> - A more tedious would be the to cache file attributes as well, as a part >>> of the directory delegation. This would end up requiring a change in the >>> NFS protocol spec though. >>> - Bulk GETATTR calls: I am uncertain of the feasibility of this, but >>> what if, the client could do 1 GETATTR call for getting attributes >>> for multiple files. >> >> >> ls is such a hard workload to get right, because we don't really get an > > 100% agree. And there were a couple of attempts to address this issue > (second ls that is slow). > >> indication in the kernel of what userland's intentions are. It's >> basically a readdir() call followed by a bunch of stat()'s, but at the >> point where we're getting the readdir() call, we don't know if userland >> intends to stat() those files or not. We have to make a guess about >> that intention. >> >> In this case, it sounds like the directory cache was valid, so the >> client decided it didn't need to do a READDIR at all, but the >> individual files had caches that timed out. >> >> So imagine you're the kernel client and have been given that second >> readdir() call: Why should you decide to do a READDIRPLUS at that point >> instead of a regular READDIR? > > May we need some kind of client-side heuristics, like on the server side > for open-delegations, where after seeing some `stats` for files in the > In the same directory, the client will decide to switch to READDIR (v4) > to get all attributes in one go. We do something like that already. I don't think we'll ever have a readdir plus heuristic that makes everybody happy without userspace somehow telling us their intentions. I know a statx-based readdir plus system call probably sounds crazy, but something like that would go a long way to take all the guesswork out of things on our end. Anna > > Best regards, > Tigran. > >> -- >> Jeff Layton <jlayton@kernel.org> > > Attachments: > * smime.p7s ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: NFS delegations behavior analysis 2026-06-23 13:11 ` Anna Schumaker @ 2026-09-09 10:10 ` Piyush Sachdeva 2026-09-09 12:07 ` Piyush Sachdeva 2026-09-09 13:13 ` Jeff Layton 0 siblings, 2 replies; 15+ messages in thread From: Piyush Sachdeva @ 2026-09-09 10:10 UTC (permalink / raw) To: Anna Schumaker, Tigran Mkrtchyan, Jeff Layton Cc: linux-nfs, Chuck Lever, Trond Myklebust, sfrench, sprasad, vaibsharma "Anna Schumaker" <anna@nowheycreamery.com> writes: > On Tue, Jun 23, 2026, at 7:04 AM, Mkrtchyan, Tigran wrote: >> ----- Original Message ----- >>> From: "Jeff Layton" <jlayton@kernel.org> >>> To: "Piyush Sachdeva" <s.piyush1024@gmail.com>, "linux-nfs" <linux-nfs@vger.kernel.org>, "Chuck Lever" <cel@kernel.org>, >>> "trondmy" <trondmy@kernel.org>, sfrench@samba.org, sprasad@microsoft.com >>> Cc: vaibsharma@microsoft.com >>> Sent: Tuesday, 23 June, 2026 12:50:16 >>> Subject: Re: NFS delegations behavior analysis >> >>> On Tue, 2026-06-23 at 15:31 +0530, Piyush Sachdeva wrote: >>>> Hi, >>>> Lately I have been running micro benchmarks around the `ls` command and >>>> reading through the code documentation of the NFS client to better >>>> understand the client side caching behavior with and without >>>> delegations. >>>> >>>> Understanding so far: >>>> Delegations (both file and directory) are granted by the server to the >>>> client, indefinitely (until revoked or under the watermark) to cache >>>> attributes. The caching of data is a result of the attribute >>>> cache. Hence forth, a directory delegation will cache the directory >>>> attributes and the names of the files in the directory, and a file >>>> delegation will cache the attributes of the file and the file data. >>>> >>>> Workload run: >>>> I focused on the 2 workloads below, doing 2 passes of a large flat >>>> directory (with close to 100K files) - >>>> a cold pass, and warm pass using the cache from the cold pass: >>>> - lslr - ls -lR on both runs >>>> - lsmix - ls -R (cold) and then ls -lR (warm) >>>> >>>> I also played with the rdirplus behavior using both the default >>>> heuristic behavior and the `rdirplus=force` set at mount time. >>>> >>>> Numbers: >>>> actimeo=5s, rdirplus=force, ACLs off, flat_dir >>>> ================================================================== >>>> >>>> | LSLR | LSMIX >>>> | (ls -lR cold / warm) | (p1 ls -R / p2 ls -lR) >>>> Operation | flat cold | flat warm | flat p1 | flat p2 >>>> -----------------+-------------+-----------+-------------+--------- >>>> READDIR calls | 27 | 0 | 27 | 0 >>>> READDIR recv B | 23,603,024 | 0 | 23,603,024 | 0 >>>> call type | readdirplus | -- | readdirplus | -- >>>> LOOKUP | 1 | 0 | 1 | 0 >>>> GETATTR | 3 | 100,000 | 2 | 100,001 >>>> ACCESS | 2 | 0 | 2 | 0 >>>> -----------------+-------------+-----------+-------------+--------- >>>> Elapsed (age) | ~14 s | ~62 s | ~16 s | ~63 s >>>> >>>> >>>> Observations: >>>> When doing `ls` or `ls -l` on a directory, due to the open(2) on the >>>> directory, the client gets a directory delegation - caching the >>>> directory attributes and file names. However, as we don't have file >>>> delegations due to no open(2) calls to any of the files. Henceforth, >>>> the cache of file attributes is governed by `actimeo`. >>>> Now here is the interesting bit, if the next `ls -l` is issued after >>>> the `actimeo`, a massive GETATTR storm hits the server, doing stat() >>>> calls for every file in the directory. As a result, the performance of >>>> this warm `ls -l` run ends up being worse than the cold pass. I am >>>> guessing this is most likely due to the compounded "rdirplus" being more >>>> efficient than stat() calls. >>>> >>>> >>>> Proposal: >>>> For large directories, this ends up being a massive problem, taking 1-2 >>>> minutes when enumerating a directory on the warm passes. >>>> - An easier way to tackle this could be to do a rdirplus=[auto | forced] >>>> instead of issuing the stat(2) storm to the server: When the client >>>> notices that there are cache misses, which would be the case of file >>>> attributes, instead of fetching file names from the directory-delegation >>>> cache and attributes from GETATTR, the client does a READDIRPLUS to >>>> the server, nonetheless. >>>> - A more tedious would be the to cache file attributes as well, as a part >>>> of the directory delegation. This would end up requiring a change in the >>>> NFS protocol spec though. >>>> - Bulk GETATTR calls: I am uncertain of the feasibility of this, but >>>> what if, the client could do 1 GETATTR call for getting attributes >>>> for multiple files. >>> >>> >>> ls is such a hard workload to get right, because we don't really get an >> >> 100% agree. And there were a couple of attempts to address this issue >> (second ls that is slow). >> >>> indication in the kernel of what userland's intentions are. It's >>> basically a readdir() call followed by a bunch of stat()'s, but at the >>> point where we're getting the readdir() call, we don't know if userland >>> intends to stat() those files or not. We have to make a guess about >>> that intention. >>> >>> In this case, it sounds like the directory cache was valid, so the >>> client decided it didn't need to do a READDIR at all, but the >>> individual files had caches that timed out. >>> >>> So imagine you're the kernel client and have been given that second >>> readdir() call: Why should you decide to do a READDIRPLUS at that point >>> instead of a regular READDIR? >> >> May we need some kind of client-side heuristics, like on the server side >> for open-delegations, where after seeing some `stats` for files in the >> In the same directory, the client will decide to switch to READDIR (v4) >> to get all attributes in one go. > > We do something like that already. I don't think we'll ever have a readdir > plus heuristic that makes everybody happy without userspace somehow telling > us their intentions. I know a statx-based readdir plus system call probably > sounds crazy, but something like that would go a long way to take all the > guesswork out of things on our end. > > Anna > >> >> Best regards, >> Tigran. >> >>> -- >>> Jeff Layton <jlayton@kernel.org> >> >> Attachments: >> * smime.p7s Hi, I believe the problem from this discussion has been the cost associated with GETATTRs during directory enumerations, compounded by the fact that the kernel can't know whether more GETATTRs on the same directory are coming. Since the readdirplus heuristic rework in v5.18, plaing READDIRs fetching the file type in v6.8, and introduction of rdirplus=force in v6.14, the client has become quite performant especially for the ls-style workloads. find and du, still suffer from GETATTR storms for large-enough directories, as they enumerate the directory once then stat() every child. Note that nfs_getattr() already feeds the cache_hit/cache_miss counters (since v4.10), but that signal lives on the open-directory context and is consumed only inside nfs_readdir(). This is where the performance hurts the most. As a benchmark, I prototyped a solution for older kernels (v4.18, v5.14, v6.4-based distros). An eBPF-based detector recognizes GETATTR/LOOKUP storms on large flat directories and triggers a userspace helper to enumerate the directory (READDIR(PLUS), start -> EOF). The returned entries refresh the attribute/dcache so subsequent GETATTR/LOOKUP calls are served from cache. We measured directory-enumeration time and GETATTR/LOOKUP counts drop by ~50–80x on large directories, for ls, find, and du. With that as evidence, I'd like to propose exploring two in-kernel directions and get your opinion on feasibility and desirability: 1. Extend the existing getattr miss-tracking: when cache_misses on a directory cross a threshold, trigger a deferred, background READDIRPLUS to refresh that directory's child attributes. This gives the find / du case a consumer for the miss signal it already generates. 2. A batched-GETATTR path so tools like du /find can request many children's attributes in fewer round-trips. I recognize there's no batched-stat() interface today and that this spans userspace and the kernel, so I'm raising it mainly to ask whether a metadata-batching interface (or wiring stat readahead to an NFSv4 multi-GETATTR compound) is something the community would consider. I'd appreciate your thoughts on both, particularly whether (1) is best framed as an extension of the v5.18 heuristic. -- Best, Piyush Sachdeva ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: NFS delegations behavior analysis 2026-09-09 10:10 ` Piyush Sachdeva @ 2026-09-09 12:07 ` Piyush Sachdeva 2026-09-09 13:13 ` Jeff Layton 1 sibling, 0 replies; 15+ messages in thread From: Piyush Sachdeva @ 2026-09-09 12:07 UTC (permalink / raw) To: Anna Schumaker, Tigran Mkrtchyan, Jeff Layton Cc: linux-nfs, Chuck Lever, Trond Myklebust, sfrench, sprasad, vaibsharma Piyush Sachdeva <s.piyush1024@gmail.com> writes: > "Anna Schumaker" <anna@nowheycreamery.com> writes: > >> On Tue, Jun 23, 2026, at 7:04 AM, Mkrtchyan, Tigran wrote: >>> ----- Original Message ----- >>>> From: "Jeff Layton" <jlayton@kernel.org> >>>> To: "Piyush Sachdeva" <s.piyush1024@gmail.com>, "linux-nfs" <linux-nfs@vger.kernel.org>, "Chuck Lever" <cel@kernel.org>, >>>> "trondmy" <trondmy@kernel.org>, sfrench@samba.org, sprasad@microsoft.com >>>> Cc: vaibsharma@microsoft.com >>>> Sent: Tuesday, 23 June, 2026 12:50:16 >>>> Subject: Re: NFS delegations behavior analysis >>> >>>> On Tue, 2026-06-23 at 15:31 +0530, Piyush Sachdeva wrote: >>>>> Hi, >>>>> Lately I have been running micro benchmarks around the `ls` command and >>>>> reading through the code documentation of the NFS client to better >>>>> understand the client side caching behavior with and without >>>>> delegations. >>>>> >>>>> Understanding so far: >>>>> Delegations (both file and directory) are granted by the server to the >>>>> client, indefinitely (until revoked or under the watermark) to cache >>>>> attributes. The caching of data is a result of the attribute >>>>> cache. Hence forth, a directory delegation will cache the directory >>>>> attributes and the names of the files in the directory, and a file >>>>> delegation will cache the attributes of the file and the file data. >>>>> >>>>> Workload run: >>>>> I focused on the 2 workloads below, doing 2 passes of a large flat >>>>> directory (with close to 100K files) - >>>>> a cold pass, and warm pass using the cache from the cold pass: >>>>> - lslr - ls -lR on both runs >>>>> - lsmix - ls -R (cold) and then ls -lR (warm) >>>>> >>>>> I also played with the rdirplus behavior using both the default >>>>> heuristic behavior and the `rdirplus=force` set at mount time. >>>>> >>>>> Numbers: >>>>> actimeo=5s, rdirplus=force, ACLs off, flat_dir >>>>> ================================================================== >>>>> >>>>> | LSLR | LSMIX >>>>> | (ls -lR cold / warm) | (p1 ls -R / p2 ls -lR) >>>>> Operation | flat cold | flat warm | flat p1 | flat p2 >>>>> -----------------+-------------+-----------+-------------+--------- >>>>> READDIR calls | 27 | 0 | 27 | 0 >>>>> READDIR recv B | 23,603,024 | 0 | 23,603,024 | 0 >>>>> call type | readdirplus | -- | readdirplus | -- >>>>> LOOKUP | 1 | 0 | 1 | 0 >>>>> GETATTR | 3 | 100,000 | 2 | 100,001 >>>>> ACCESS | 2 | 0 | 2 | 0 >>>>> -----------------+-------------+-----------+-------------+--------- >>>>> Elapsed (age) | ~14 s | ~62 s | ~16 s | ~63 s >>>>> >>>>> >>>>> Observations: >>>>> When doing `ls` or `ls -l` on a directory, due to the open(2) on the >>>>> directory, the client gets a directory delegation - caching the >>>>> directory attributes and file names. However, as we don't have file >>>>> delegations due to no open(2) calls to any of the files. Henceforth, >>>>> the cache of file attributes is governed by `actimeo`. >>>>> Now here is the interesting bit, if the next `ls -l` is issued after >>>>> the `actimeo`, a massive GETATTR storm hits the server, doing stat() >>>>> calls for every file in the directory. As a result, the performance of >>>>> this warm `ls -l` run ends up being worse than the cold pass. I am >>>>> guessing this is most likely due to the compounded "rdirplus" being more >>>>> efficient than stat() calls. >>>>> >>>>> >>>>> Proposal: >>>>> For large directories, this ends up being a massive problem, taking 1-2 >>>>> minutes when enumerating a directory on the warm passes. >>>>> - An easier way to tackle this could be to do a rdirplus=[auto | forced] >>>>> instead of issuing the stat(2) storm to the server: When the client >>>>> notices that there are cache misses, which would be the case of file >>>>> attributes, instead of fetching file names from the directory-delegation >>>>> cache and attributes from GETATTR, the client does a READDIRPLUS to >>>>> the server, nonetheless. >>>>> - A more tedious would be the to cache file attributes as well, as a part >>>>> of the directory delegation. This would end up requiring a change in the >>>>> NFS protocol spec though. >>>>> - Bulk GETATTR calls: I am uncertain of the feasibility of this, but >>>>> what if, the client could do 1 GETATTR call for getting attributes >>>>> for multiple files. >>>> >>>> >>>> ls is such a hard workload to get right, because we don't really get an >>> >>> 100% agree. And there were a couple of attempts to address this issue >>> (second ls that is slow). >>> >>>> indication in the kernel of what userland's intentions are. It's >>>> basically a readdir() call followed by a bunch of stat()'s, but at the >>>> point where we're getting the readdir() call, we don't know if userland >>>> intends to stat() those files or not. We have to make a guess about >>>> that intention. >>>> >>>> In this case, it sounds like the directory cache was valid, so the >>>> client decided it didn't need to do a READDIR at all, but the >>>> individual files had caches that timed out. >>>> >>>> So imagine you're the kernel client and have been given that second >>>> readdir() call: Why should you decide to do a READDIRPLUS at that point >>>> instead of a regular READDIR? >>> >>> May we need some kind of client-side heuristics, like on the server side >>> for open-delegations, where after seeing some `stats` for files in the >>> In the same directory, the client will decide to switch to READDIR (v4) >>> to get all attributes in one go. >> >> We do something like that already. I don't think we'll ever have a readdir >> plus heuristic that makes everybody happy without userspace somehow telling >> us their intentions. I know a statx-based readdir plus system call probably >> sounds crazy, but something like that would go a long way to take all the >> guesswork out of things on our end. >> >> Anna >> >>> >>> Best regards, >>> Tigran. >>> >>>> -- >>>> Jeff Layton <jlayton@kernel.org> >>> >>> Attachments: >>> * smime.p7s > > Hi, > I believe the problem from this discussion has been the cost associated > with GETATTRs during directory enumerations, compounded by the fact that > the kernel can't know whether more GETATTRs on the same directory are > coming. > > Since the readdirplus heuristic rework in v5.18, plaing READDIRs > fetching the file type in v6.8, and introduction of rdirplus=force in > v6.14, the client has become quite performant especially for the > ls-style workloads. find and du, still suffer from GETATTR storms for > large-enough directories, as they enumerate the directory once then > stat() every child. Note that nfs_getattr() already feeds the > cache_hit/cache_miss counters (since v4.10), but that signal lives on > the open-directory context and is consumed only inside nfs_readdir(). > This is where the performance hurts the most. > > As a benchmark, I prototyped a solution for older kernels (v4.18, v5.14, > v6.4-based distros). An eBPF-based detector recognizes GETATTR/LOOKUP > storms on large flat directories and triggers a userspace helper to > enumerate the directory (READDIR(PLUS), start -> EOF). The returned > entries refresh the attribute/dcache so subsequent GETATTR/LOOKUP calls > are served from cache. We measured directory-enumeration time and > GETATTR/LOOKUP counts drop by ~50–80x on large directories, for ls, > find, and du. > > With that as evidence, I'd like to propose exploring two in-kernel > directions and get your opinion on feasibility and desirability: > 1. Extend the existing getattr miss-tracking: when cache_misses on a > directory cross a threshold, trigger a deferred, background > READDIRPLUS to refresh that directory's child attributes. This gives > the find / du case a consumer for the miss signal it already > generates. > 2. A batched-GETATTR path so tools like du /find can request many > children's attributes in fewer round-trips. I recognize there's no > batched-stat() interface today and that this spans userspace and the > kernel, so I'm raising it mainly to ask whether a metadata-batching > interface (or wiring stat readahead to an NFSv4 multi-GETATTR > compound) is something the community would consider. > > I'd appreciate your thoughts on both, particularly whether (1) is best > framed as an extension of the v5.18 heuristic. > > -- > Best, > Piyush Sachdeva I am posting the benchmark numbers of the directory enumeration workload both with and without the eBPF-based tool for reference. Different workloads: - ls_r: 2 iterations of - ls -R "$TARGET_DIR" - ls_lr: 2 iterations of - ls -lR "$TARGET_DIR" - lsmix: ls -R "$TARGET_DIR" followed by ls -lR "$TARGET_DIR" - find: 2 iterations of - find "$TARGET_DIR" -type f -size +0c - du: 2 iterations of - du "$TARGET_DIR" - The share gets remounted in between each workload runs. - Each workload has 2 successive iterations (no gap) - a cold run that populates the cache, and after, a warm run that re-uses the cache. - Distro(kernel): SLES 15 SP5 (v5.14) - $TARGET_DIR - Flat large directory; file count - 1 Million files - actimeo=30 Numbers: - Iteration 1 (cold) - without eBPF / with eBPF op ls_r ls_lr lsmix du find --------------- -------------------- -------------------- -------------------- ---------------------- ---------------------- READDIR calls 217 / 455 263 / 263 217 / 454 127 / 422 127 / 421 READDIR recv(B) 210,687,496 / 248,029,456 / 210,687,496 / 115,395,048 / 115,395,048 / 440,573,116 248,029,456 439,524,444 405,689,200 404,640,792 LOOKUP 30,178 / 6,161 1 / 1 30,178 / 6,691 733,573 / 19,465 733,573 / 5,837 GETATTR 61 / 5 1 / 1 63 / 5 177,623 / 5 177,622 / 4 ACCESS 2 / 2 2 / 2 2 / 2 2 / 2 2 / 2 elapsed (ms) 919,684 / 40,657 23,938 / 24,984 947,506 / 41,133 2,643,906 / 78,684 2,627,536 / 38,337 - Iteration 2 (warm) - without eBPF / with eBPF op ls_r ls_lr lsmix du find --------------- -------------------- -------------------- -------------------- ---------------------- ---------------------- READDIR calls 217 / 0 0 / 0 258 / 256 124 / 317 123 / 417 READDIR recv(B) 208,601,368 / 0 0 / 0 248,909,816 / 109,134,232 / 109,134,232 / 248,909,816 398,379,976 398,379,976 LOOKUP 0 / 0 0 / 0 0 / 0 0 / 0 0 / 0 GETATTR 301,214 / 1 1 / 1 127 / 127 822,266 / 26,329 822,267 / 25,611 ACCESS 0 / 0 0 / 0 0 / 0 0 / 0 0 / 0 elapsed (ms) 550,011 / 2,648 5,231 / 6,419 23,264 / 24,090 1,494,821 / 65,103 1,527,773 / 64,990 You can see the reduction in total time, GETATTRs and LOOKUPs. -- Best, Piyush Sachdeva <s.piyush1024@gmail.com> ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: NFS delegations behavior analysis 2026-09-09 10:10 ` Piyush Sachdeva 2026-09-09 12:07 ` Piyush Sachdeva @ 2026-09-09 13:13 ` Jeff Layton 1 sibling, 0 replies; 15+ messages in thread From: Jeff Layton @ 2026-09-09 13:13 UTC (permalink / raw) To: Piyush Sachdeva, Anna Schumaker, Tigran Mkrtchyan Cc: linux-nfs, Chuck Lever, Trond Myklebust, sfrench, sprasad, vaibsharma On Wed, 2026-09-09 at 15:40 +0530, Piyush Sachdeva wrote: > "Anna Schumaker" <anna@nowheycreamery.com> writes: > > > On Tue, Jun 23, 2026, at 7:04 AM, Mkrtchyan, Tigran wrote: > > > ----- Original Message ----- > > > > From: "Jeff Layton" <jlayton@kernel.org> > > > > To: "Piyush Sachdeva" <s.piyush1024@gmail.com>, "linux-nfs" <linux-nfs@vger.kernel.org>, "Chuck Lever" <cel@kernel.org>, > > > > "trondmy" <trondmy@kernel.org>, sfrench@samba.org, sprasad@microsoft.com > > > > Cc: vaibsharma@microsoft.com > > > > Sent: Tuesday, 23 June, 2026 12:50:16 > > > > Subject: Re: NFS delegations behavior analysis > > > > > > > On Tue, 2026-06-23 at 15:31 +0530, Piyush Sachdeva wrote: > > > > > Hi, > > > > > Lately I have been running micro benchmarks around the `ls` command and > > > > > reading through the code documentation of the NFS client to better > > > > > understand the client side caching behavior with and without > > > > > delegations. > > > > > > > > > > Understanding so far: > > > > > Delegations (both file and directory) are granted by the server to the > > > > > client, indefinitely (until revoked or under the watermark) to cache > > > > > attributes. The caching of data is a result of the attribute > > > > > cache. Hence forth, a directory delegation will cache the directory > > > > > attributes and the names of the files in the directory, and a file > > > > > delegation will cache the attributes of the file and the file data. > > > > > > > > > > Workload run: > > > > > I focused on the 2 workloads below, doing 2 passes of a large flat > > > > > directory (with close to 100K files) - > > > > > a cold pass, and warm pass using the cache from the cold pass: > > > > > - lslr - ls -lR on both runs > > > > > - lsmix - ls -R (cold) and then ls -lR (warm) > > > > > > > > > > I also played with the rdirplus behavior using both the default > > > > > heuristic behavior and the `rdirplus=force` set at mount time. > > > > > > > > > > Numbers: > > > > > actimeo=5s, rdirplus=force, ACLs off, flat_dir > > > > > ================================================================== > > > > > > > > > > | LSLR | LSMIX > > > > > | (ls -lR cold / warm) | (p1 ls -R / p2 ls -lR) > > > > > Operation | flat cold | flat warm | flat p1 | flat p2 > > > > > -----------------+-------------+-----------+-------------+--------- > > > > > READDIR calls | 27 | 0 | 27 | 0 > > > > > READDIR recv B | 23,603,024 | 0 | 23,603,024 | 0 > > > > > call type | readdirplus | -- | readdirplus | -- > > > > > LOOKUP | 1 | 0 | 1 | 0 > > > > > GETATTR | 3 | 100,000 | 2 | 100,001 > > > > > ACCESS | 2 | 0 | 2 | 0 > > > > > -----------------+-------------+-----------+-------------+--------- > > > > > Elapsed (age) | ~14 s | ~62 s | ~16 s | ~63 s > > > > > > > > > > > > > > > Observations: > > > > > When doing `ls` or `ls -l` on a directory, due to the open(2) on the > > > > > directory, the client gets a directory delegation - caching the > > > > > directory attributes and file names. However, as we don't have file > > > > > delegations due to no open(2) calls to any of the files. Henceforth, > > > > > the cache of file attributes is governed by `actimeo`. > > > > > Now here is the interesting bit, if the next `ls -l` is issued after > > > > > the `actimeo`, a massive GETATTR storm hits the server, doing stat() > > > > > calls for every file in the directory. As a result, the performance of > > > > > this warm `ls -l` run ends up being worse than the cold pass. I am > > > > > guessing this is most likely due to the compounded "rdirplus" being more > > > > > efficient than stat() calls. > > > > > > > > > > > > > > > Proposal: > > > > > For large directories, this ends up being a massive problem, taking 1-2 > > > > > minutes when enumerating a directory on the warm passes. > > > > > - An easier way to tackle this could be to do a rdirplus=[auto | forced] > > > > > instead of issuing the stat(2) storm to the server: When the client > > > > > notices that there are cache misses, which would be the case of file > > > > > attributes, instead of fetching file names from the directory-delegation > > > > > cache and attributes from GETATTR, the client does a READDIRPLUS to > > > > > the server, nonetheless. > > > > > - A more tedious would be the to cache file attributes as well, as a part > > > > > of the directory delegation. This would end up requiring a change in the > > > > > NFS protocol spec though. > > > > > - Bulk GETATTR calls: I am uncertain of the feasibility of this, but > > > > > what if, the client could do 1 GETATTR call for getting attributes > > > > > for multiple files. > > > > > > > > > > > > ls is such a hard workload to get right, because we don't really get an > > > > > > 100% agree. And there were a couple of attempts to address this issue > > > (second ls that is slow). > > > > > > > indication in the kernel of what userland's intentions are. It's > > > > basically a readdir() call followed by a bunch of stat()'s, but at the > > > > point where we're getting the readdir() call, we don't know if userland > > > > intends to stat() those files or not. We have to make a guess about > > > > that intention. > > > > > > > > In this case, it sounds like the directory cache was valid, so the > > > > client decided it didn't need to do a READDIR at all, but the > > > > individual files had caches that timed out. > > > > > > > > So imagine you're the kernel client and have been given that second > > > > readdir() call: Why should you decide to do a READDIRPLUS at that point > > > > instead of a regular READDIR? > > > > > > May we need some kind of client-side heuristics, like on the server side > > > for open-delegations, where after seeing some `stats` for files in the > > > In the same directory, the client will decide to switch to READDIR (v4) > > > to get all attributes in one go. > > > > We do something like that already. I don't think we'll ever have a readdir > > plus heuristic that makes everybody happy without userspace somehow telling > > us their intentions. I know a statx-based readdir plus system call probably > > sounds crazy, but something like that would go a long way to take all the > > guesswork out of things on our end. > > > > Anna > > > > > > > > Best regards, > > > Tigran. > > > > > > > -- > > > > Jeff Layton <jlayton@kernel.org> > > > > > > Attachments: > > > * smime.p7s > > Hi, > I believe the problem from this discussion has been the cost associated > with GETATTRs during directory enumerations, compounded by the fact that > the kernel can't know whether more GETATTRs on the same directory are > coming. > > Since the readdirplus heuristic rework in v5.18, plaing READDIRs > fetching the file type in v6.8, and introduction of rdirplus=force in > v6.14, the client has become quite performant especially for the > ls-style workloads. find and du, still suffer from GETATTR storms for > large-enough directories, as they enumerate the directory once then > stat() every child. Note that nfs_getattr() already feeds the > cache_hit/cache_miss counters (since v4.10), but that signal lives on > the open-directory context and is consumed only inside nfs_readdir(). > This is where the performance hurts the most. > > As a benchmark, I prototyped a solution for older kernels (v4.18, v5.14, > v6.4-based distros). An eBPF-based detector recognizes GETATTR/LOOKUP > storms on large flat directories and triggers a userspace helper to > enumerate the directory (READDIR(PLUS), start -> EOF). The returned > entries refresh the attribute/dcache so subsequent GETATTR/LOOKUP calls > are served from cache. We measured directory-enumeration time and > GETATTR/LOOKUP counts drop by ~50–80x on large directories, for ls, > find, and du. > > With that as evidence, I'd like to propose exploring two in-kernel > directions and get your opinion on feasibility and desirability: > 1. Extend the existing getattr miss-tracking: when cache_misses on a > directory cross a threshold, trigger a deferred, background > READDIRPLUS to refresh that directory's child attributes. This gives > the find / du case a consumer for the miss signal it already > generates. Tough call. This adds load to the server for attributes that will never be used. My gut feeling is that that might help some workloads, but hurt others. > 2. A batched-GETATTR path so tools like du /find can request many > children's attributes in fewer round-trips. I recognize there's no > batched-stat() interface today and that this spans userspace and the > kernel, so I'm raising it mainly to ask whether a metadata-batching > interface (or wiring stat readahead to an NFSv4 multi-GETATTR > compound) is something the community would consider. > > I'd appreciate your thoughts on both, particularly whether (1) is best > framed as an extension of the v5.18 heuristic. #2 sounds like a mess to get right.... What might be more reasonable is adding a real readdirplus() style- system call, like Anna mentioned. Something where userland can do a readdir() and pass down a statx() mask to tell the kernel what attributes it's interested in, and get back a list of filenames and their inodes' attributes in one shot. That too might not be accepted upstream (it has been attempted before), but that seems like it would be a fairly straightforward thing for userland, and would work well for "ls -l" and the like. -- Jeff Layton <jlayton@kernel.org> ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2026-09-09 13:13 UTC | newest] Thread overview: 15+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-06-23 10:01 NFS delegations behavior analysis Piyush Sachdeva 2026-06-23 10:50 ` Jeff Layton 2026-06-23 11:04 ` Mkrtchyan, Tigran 2026-06-23 11:10 ` Jeff Layton 2026-06-23 13:11 ` Benjamin Coddington 2026-06-23 13:31 ` Daire Byrne 2026-06-23 13:32 ` Benjamin Coddington 2026-06-23 13:40 ` Jeff Layton 2026-06-23 13:59 ` Benjamin Coddington 2026-06-23 16:29 ` Trond Myklebust 2026-06-23 13:33 ` Jeff Layton 2026-06-23 13:11 ` Anna Schumaker 2026-09-09 10:10 ` Piyush Sachdeva 2026-09-09 12:07 ` Piyush Sachdeva 2026-09-09 13:13 ` Jeff Layton
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox