]> git.ipfire.org Git - thirdparty/linux.git/commit
don't try to cut corners in shrink_lock_dentry()
authorAl Viro <viro@zeniv.linux.org.uk>
Tue, 31 Oct 2023 05:23:47 +0000 (01:23 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Sat, 25 Nov 2023 07:34:12 +0000 (02:34 -0500)
commit339e9e13530ba750fe0868c5e51bc23be07fd1f1
tree6936f6a70e89b72d8ada5bbabcd00630556372f1
parentf05441c7e16e6a720cf24e08999661a76ff77478
don't try to cut corners in shrink_lock_dentry()

That is to say, do *not* treat the ->d_inode or ->d_parent changes
as "it's hard, return false; somebody must have grabbed it, so
even if has zero refcount, we don't need to bother killing it -
final dput() from whoever grabbed it would've done everything".

First of all, that is not guaranteed.  It might have been dropped
by shrink_kill() handling of victim's parent, which would've found
it already on a shrink list (ours) and decided that they don't need
to put it on their shrink list.

What's more, dentry_kill() is doing pretty much the same thing,
cutting its own set of corners (it assumes that dentry can't
go from positive to negative, so its inode can change but only once
and only in one direction).

Doing that right allows to get rid of that not-quite-duplication
and removes the only reason for re-incrementing refcount before
the call of dentry_kill().

Replacement is called lock_for_kill(); called under rcu_read_lock
and with ->d_lock held.  If it returns false, dentry has non-zero
refcount and the same locks are held.  If it returns true,
dentry has zero refcount and all locks required by __dentry_kill()
are taken.

Part of __lock_parent() had been lifted into lock_parent() to
allow its reuse.  Now it's called with rcu_read_lock already
held and dentry already unlocked.

Note that this is not the final change - locking requirements for
__dentry_kill() are going to change later in the series and the
set of locks taken by lock_for_kill() will be adjusted.  Both
lock_parent() and __lock_parent() will be gone once that happens.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/dcache.c