Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 2 Nov 2015 23:10:07 +1100 (EST)
From:      Bruce Evans <brde@optusnet.com.au>
To:        Bruce Evans <brde@optusnet.com.au>
Cc:        fs@freebsd.org
Subject:   Re: an easy (?) question on namecache sizing
Message-ID:  <20151102224910.E2203@besplex.bde.org>
In-Reply-To: <20151102210750.S1908@besplex.bde.org>
References:  <20151102193756.L1475@besplex.bde.org> <20151102210750.S1908@besplex.bde.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Mon, 2 Nov 2015, Bruce Evans wrote:

> On Mon, 2 Nov 2015, Bruce Evans wrote:
>
>> At least in old versions before cache_changesize() (should be nc_chsize())
>> existed, the name cache is supposed to have size about 2 * desiredvnodes,
>> but its effective size seems to be only about desiredvnodes / 4?  Why is
>> this?
>> 
>> This shows up in du -s on a large directory like /usr.  Whenever the
>> directory has more than about desiredvnodes / 4 entries under it, the
>> namecache thrashes.  The number of cached vnodes is also limited to
>> about desiredvnodes / 4.
>> 
>> The problem might actually be in vnode caching.  ...
>
> This was easy to answer.  The problem is in vnode caching.  Its only
> ...
> X ....
> X SYSCTL_PROC(_kern, KERN_MAXVNODES, maxvnodes,
> X     CTLTYPE_INT | CTLFLAG_MPSAFE | CTLFLAG_RW, &desiredvnodes, 0,
> X     sysctl_update_desiredvnodes, "I", "Maximum number of vnodes");
>
> The maximum is not bogus.  Only "desired" in the name is bogus.  Note
> that the sysctl name doesn't say "desired".  But systat -v still uses
> the raw variable name (abbreviated to 'desvn").  It is important for
> understanding systat -v output and the source code to know that this
> variable is actually the maximum and not the desired number, unlike
> what its name suggests.
>
> X SYSCTL_ULONG(_kern, OID_AUTO, minvnodes, CTLFLAG_RW,
> X     &wantfreevnodes, 0, "Minimum number of vnodes (legacy)");
>
> Further obfuscations.  The desiredvnodes / 4 number number from here.
> This value really is the "wanted" or "desired" number of vnodes.
> The sysctl obfuscates it by renaming it to "minvnodes", it is not
> a minimum except in the sense that when the current number exceeds
> it, the vnrlu daemon tries (not very hard) to reduce this limit.
> The description of this sysctl as legacy is confusing.  Perhaps the
> name of this sysctl is legacy, but its value is less legacy than
> that of desiredvnodes by any name.  This is further obfuscated by
> exporting this variable twice (once here and once with its correct
> name under vfs).  See below for an example of sysctl output.
>
> X ...
> X 	wantfreevnodes = desiredvnodes / 4;
>
> This is where the length used below is initialized.

In old versions, only desiredvnodes was bogus, and the policy works
correctly.  wantfreevnodes defaulted to only 25 and the goal of
reaching that was independent of the goal of reaching the minimum
number of vnodes.  Now wantfreevnodes is ridiculously large (it is
about 1 million when desiredvnodes is 4 million on freefall), and
the goal of reaching a minimum number of vnodes is as confused in
the code as in the variable names and is only reached accidentally.

My version of some relevant code from old version (with some changes,
but only to style):

X int
X getnewvnode(tag, mp, vops, vpp)
X 	...
X 	/*
X 	 * Attempt to reuse a vnode already on the free list, allocating
X 	 * a new vnode if we can't find one or if we have not reached a
X 	 * good minimum for good LRU performance.
X 	 */
X 	if (freevnodes >= wantfreevnodes && numvnodes >= minvnodes) {

Current version:

X int
X getnewvnode(const char *tag, struct mount *mp, struct vop_vector *vops,
X     struct vnode **vpp)
X {
X 	...
X 	/*
X 	 * Lend our context to reclaim vnodes if they've exceeded the max.
X 	 */
X 	if (freevnodes > wantfreevnodes)
X 		vnlru_free(1);

This no longer attemps to reach a good minimum, and in fact only reaches
one accidentally.

Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20151102224910.E2203>