Re: [RFC PATCH v2 4/4] get rid of busy-waiting in shrink_dcache_tree()

Al Viro
2026-04-04T18:51:05Z

On Fri, Apr 03, 2026 at 05:04:26PM -0700, Linus Torvalds wrote:
> On Fri, 3 Apr 2026 at 16:58, Al Viro <viro@zeniv.linux.org.uk> wrote:
> >
> > FWIW, I wonder if we would be better off with something like
> >
> > struct completion_list {
> > struct completion completion;
> > struct completion_list *next;
> > };
> >
> > embedded into select_data, with dentry->waiters being a pointer
> > to that. It's just that dragging struct select_data into that,
> > even as an opaque pointer, tastes wrong ;-/
> >
> > Preferences?
>
> I have no strong preferences in this area.
>
> The opaque pointer is fine by me, because it's type-safe without
> exposing internal implementation or having people being able to much
> around with the fields.
>
> But if you prefer a completion list, i don't see that being a problem
> either. So entirely up to you.

BTW, how much would you hate something like

/*
* Check if dentry is already dying and if it is arrange to be notified
* once it's gone.
*
* caller must hold rcu_read_lock and dentry->d_lock
*/
static bool d_deathwatch(struct dentry *dentry, struct completion_list *node)
{
if (dentry->d_lockref.count >= 0)
return false; // it's not dying yet

init_completion(&node->completion);
if (unlikely(dentry->d_flags & DCACHE_DENTRY_KILLED)) {
// it's already gone
complete(&node->completion);
return true;
}
node->next = dentry->waiters;
dentry->waiters = node;
return true;
}

with
if (data.victim) {
struct dentry *v = data.victim;
struct completion_list wait;

spin_lock(&v->d_lock);
if (d_deathwatch(v, &wait)) {
// Another thread got around to killing it.
// if there's something else to evict, do so
// then wait for the victim to be gone
spin_unlock(&v->d_lock);
rcu_read_unlock();
if (!list_empty(&data.dispose))
shrink_dentry_list(&data.dispose);
wait_for_completion(&wait.completion);
continue;
}
if (!lock_for_kill(v)) {
spin_unlock(&v->d_lock);
rcu_read_unlock();
} else {
shrink_kill(v);
}
}

in shrink_dentry_tree()?