On 6 Dec 2022, at 9:32, Chuck Lever III wrote: >> On Dec 6, 2022, at 8:21 AM, Benjamin Coddington <bcodding@xxxxxxxxxx> wrote: >> >> On 5 Dec 2022, at 21:18, Theodor Mittermair wrote: >> >>> Hello, >> >> Hi Theodor, >> >> .. snip .. >> >>> From what i gathered around the internet and understood, there seem to be >>> heuristics involved when the client decides what operations to transmit to >>> the server. Also, the timed-out cache seems to be creating what some >>> called a "getattr storm", which i understand in theory. >> >> When `du` gathers information, it does so by switching between two syscalls: >> getdents() and stat() (or some equivalents). The getdents() syscall causes >> the NFS client to perform either READDIR or READDIRPLUS - the choice of >> which is governed by a heuristic. The heuristic can only intelligently >> determine which readdir operation to use based on whether the program is >> performing this pattern of getdents(), stat(), stat(), stat(), getdents(), >> stat(), stat(), stat(). The way it can tell is by checking if each inode's >> attributes have been cached, so the cache timeouts end up coming into play. >> >>> But why does the first request manage to be smarter about it, since it >>> gathers the same information about the exact same files? >> >> It's not smarter, it just optimistically uses READDIRPLUS on the very first >> call of getdents() for a directory, but can only do so if the directory's >> dentries have not yet been cached. If they /are/ cached, but each dentry's >> individual attributes have timed out, then the client must send an >> individual GETATTR for each entry. >> >> What is happening for you is that your attribute caches for each inode are >> timing out, but the overall directory's dentry list is not changing. >> There's no need to send /any/ readdir operations - so the heuristic doesn't >> send READDIRPLUS and you end up with one full pile of getdents() results of >> individual GETATTRs for every entry. > > Are those GETATTRs emitted one at a time sequentially, or concurrently? Sequentially, as `du` loops for each getdents() entry calling stat(). Ben