Re: [RFC PATCH v2 14/14] dcache: Implement object migration

From: Al Viro
Date: Wed Apr 03 2019 - 15:05:51 EST


On Wed, Apr 03, 2019 at 07:24:54PM +0100, Al Viro wrote:

> If by "how to do it right" you mean "expedit kicking out something with
> non-zero refcount" - there's no way to do that. Nothing even remotely
> sane.
>
> If you mean "kick out everything in this page with zero refcount" - that
> can be done (see further in the thread).
>
> Look, dentries and inodes are really, really not relocatable. If they
> can be evicted by memory pressure - sure, we can do that for a given
> set (e.g. "everything in that page"). But that's it - if memory
> pressure would _not_ get rid of that one, there's nothing to be done.
> Again, all VM can do is to simulate shrinker hitting hard on given
> bunch (rather than buggering the entire cache). If filesystem (or
> something in VFS) says "it's busy", it bloody well _is_ busy and
> won't be going away until it ceases to be such.

FWIW, some theory: the only kind of long-term reference that can
be killed off by memory pressure is that from child to parent.
Anything else (e.g. an opened file, current directory, mountpoint,
etc.) is out of limits - it either won't be going away until
the thing is not pinned anymore (close, chdir, etc.) *or*
it really shouldn't be ("VM wants this mountpoint dentry freed,
so just dissolve the mount" is a bloody bad idea for obvious
reasons).

Stuff in somebody's shrink list is none of our business - somebody
else is going to try and evict it anyway; if it can be evicted,
it will be.

Anything with zero refcount that isn't in somebody else's
shrink list is fair game.

Directories with children could, in principle, be helped along -
we could try shrink_dcache_parent() on them, which might end
up leaving them with zero refcount. However, it's not cheap
and if you pick the root dentry of a filesystem, it'll try to
evict everything on it that can be evicted, be it in this page
or not. And there's no promise that it will end up evictable
after that.

So from the correctness POV
* you can kick out everything with zero refcount not
on shrink lists.
* you _might_ try shrink_dcache_parent() on directory
dentries, in hope to drive their refcount to zero. However,
that's almost certainly going to hit too hard and be too costly.
* d_invalidate() is no-go; if anything, you want something
weaker than shrink_dcache_parent(), not stronger.

For anything beyond "just kick out everything in that page that
happens to have zero refcount" I would really like to see the
stats - how much does it help, how costly it is _and_ how much
of the cache does it throw away (see above re running into a root
dentry of some filesystem and essentially trimming dcache for
that fs down to the unevictable stuff).