Re: [PATCH RFC 1/6] dcache: sweep cached negative dentries to the end of list of siblings

From: Al Viro
Date: Thu Apr 15 2021 - 12:25:13 EST


On Wed, Apr 14, 2021 at 03:41:10AM +0000, Al Viro wrote:

> > + if (!d_is_tail_negative(dentry)) {
> > + parent = lock_parent(dentry);
> > + if (!parent)
> > + return;
>
> Wait a minute. It's not a good environment for calling lock_parent().
> Who said that dentry won't get freed right under it?

[snip]

FWIW, in that state (dentry->d_lock held) we have
* stable ->d_flags
* stable ->d_count
* stable ->d_inode
IOW, we can bloody well check ->d_count *before* bothering with lock_parent().
It does not get rid of the problems with lifetimes, though. We could
do something along the lines of

rcu_read_lock()
if retain_dentry()
parent = NULL
if that dentry might need to be moved in list
parent = lock_parent()
// if reached __dentry_kill(), d_count() will be -128,
// so the check below will exclude those
if that dentry does need to be moved
move it to the end of list
unlock dentry and parent (if any)
rcu_read_unlock()
return
here, but your other uses of lock_parent() also need attention. And
recursive call of dput() in trim_negative() (#6/6) is really asking
for trouble.