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.

Reply via email to