Re: [PATCH 1/5] include/linux/rculist_nulls: add hlist_nulls_add_behind_rcu()

From: Paul E. McKenney

Date: Wed Oct 14 2026 - 19:59:50 EST


On Mon, Oct 12, 2026 at 10:54:43PM +0200, Max Kellermann wrote:
> Move some code from hlist_nulls_add_tail_rcu() to the new function
> hlist_nulls_add_behind_rcu() for callers that already know the last
> node of an `hlist_nulls` list, to allow constant-time appends.
>
> Signed-off-by: Max Kellermann <max.kellermann@xxxxxxxxx>

I am assuming that this commit should take the same path as the rest
of them. So:

Reviewed-by: Paul E. McKenney <paulmck@xxxxxxxxxx>

> ---
> include/linux/rculist_nulls.h | 36 +++++++++++++++++++++++++++++------
> 1 file changed, 30 insertions(+), 6 deletions(-)
>
> diff --git a/include/linux/rculist_nulls.h b/include/linux/rculist_nulls.h
> index a97c3bcb1656..054e477dd093 100644
> --- a/include/linux/rculist_nulls.h
> +++ b/include/linux/rculist_nulls.h
> @@ -115,6 +115,33 @@ static inline void hlist_nulls_add_head_rcu(struct hlist_nulls_node *n,
> WRITE_ONCE(first->pprev, &n->next);
> }
>
> +/**
> + * hlist_nulls_add_behind_rcu - append after the last list entry
> + * @n: the new element to add to the hash list.
> + * @last: the last element in the list.
> + *
> + * Adds the specified element after @last while permitting racing RCU
> + * traversals. @last must be the last list entry, with its next
> + * pointer holding the terminating nulls marker.
> + *
> + * The caller must take whatever precautions are necessary
> + * (such as holding appropriate locks) to avoid racing
> + * with another list-mutation primitive, such as hlist_nulls_add_head_rcu()
> + * or hlist_nulls_del_rcu(), running on this same list.
> + * However, it is perfectly legal to run concurrently with
> + * the _rcu list-traversal primitives, such as
> + * hlist_nulls_for_each_entry_rcu(), used to prevent memory-consistency
> + * problems on Alpha CPUs. Regardless of the type of CPU, the
> + * list-traversal primitive must be guarded by rcu_read_lock().
> + */
> +static inline void hlist_nulls_add_behind_rcu(struct hlist_nulls_node *n,
> + struct hlist_nulls_node *last)
> +{
> + WRITE_ONCE(n->next, last->next);
> + WRITE_ONCE(n->pprev, &last->next);
> + rcu_assign_pointer(hlist_nulls_next_rcu(last), n);
> +}
> +
> /**
> * hlist_nulls_add_tail_rcu
> * @n: the element to add to the hash list.
> @@ -143,13 +170,10 @@ static inline void hlist_nulls_add_tail_rcu(struct hlist_nulls_node *n,
> for (i = h->first; !is_a_nulls(i); i = i->next)
> last = i;
>
> - if (last) {
> - WRITE_ONCE(n->next, last->next);
> - WRITE_ONCE(n->pprev, &last->next);
> - rcu_assign_pointer(hlist_nulls_next_rcu(last), n);
> - } else {
> + if (last)
> + hlist_nulls_add_behind_rcu(n, last);
> + else
> hlist_nulls_add_head_rcu(n, h);
> - }
> }
>
> /* after that hlist_nulls_del will work */
> --
> 2.47.3
>
>