public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH nf,v2 1/3] rculist: add list_splice_rcu() for private lists
@ 2026-04-15 17:08 Pablo Neira Ayuso
  2026-04-15 17:39 ` Paul E. McKenney
  0 siblings, 1 reply; 3+ messages in thread
From: Pablo Neira Ayuso @ 2026-04-15 17:08 UTC (permalink / raw)
  To: netfilter-devel
  Cc: davem, netdev, kuba, pabeni, edumazet, fw, horms, joelagnelf,
	josh, boqun, urezki, rostedt, mathieu.desnoyers, jiangshanlai,
	qiang.zhang, rcu

This patch adds a helper function, list_splice_rcu(), to safely splice
a private (non-RCU-protected) list into an RCU-protected list.

The function ensures that only the pointer visible to RCU readers
(prev->next) is updated using rcu_assign_pointer(), while the rest of
the list manipulations are performed with regular assignments, as the
source list is private and not visible to concurrent RCU readers.

This is useful for moving elements from a private list into a global
RCU-protected list, ensuring safe publication for RCU readers.
Subsystems with some sort of batching mechanism from userspace can
benefit from this new function.

The function __list_splice_rcu() has been added for clarity and to
follow the same pattern as in the existing list_splice*() interfaces,
where there is a check to ensure that that the list to splice is not
empty. Note that __list_splice_rcu() has no documentation for this
reason.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: including comments by Paul McKenney.

    Except, I have deliberately keep back the suggestion to squash
    __list_splice_rcu() into list_splice_rcu(), I instead removed
    the documentation for __list_splice_rcu(). I am looking
    at other existing list_splice*() function in list.h and rculist.h
    to get this aligned with __list_splice(), which also has no users
    in the tree and no documentation. I find it easier to read with
    __list_splice(), but if this explaination is not sound so...

    @Paul: I can post v3 squashing __list_splice_rcu(), just let me
           know.

    Thanks!

 include/linux/rculist.h | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/include/linux/rculist.h b/include/linux/rculist.h
index 2abba7552605..e3bc44225692 100644
--- a/include/linux/rculist.h
+++ b/include/linux/rculist.h
@@ -261,6 +261,35 @@ static inline void list_replace_rcu(struct list_head *old,
 	old->prev = LIST_POISON2;
 }
 
+static inline void __list_splice_rcu(struct list_head *list,
+				     struct list_head *prev,
+				     struct list_head *next)
+{
+	struct list_head *first = list->next;
+	struct list_head *last = list->prev;
+
+	last->next = next;
+	first->prev = prev;
+	next->prev = last;
+	rcu_assign_pointer(list_next_rcu(prev), first);
+}
+
+/**
+ * list_splice_rcu - splice a non-RCU list into an RCU-protected list,
+ *                   designed for stacks.
+ * @list:	the non RCU-protected list to splice
+ * @head:	the place in the existing RCU-protected list to splice
+ *
+ * The list pointed to by @head can be RCU-read traversed concurrently with
+ * this function.
+ */
+static inline void list_splice_rcu(struct list_head *list,
+				   struct list_head *head)
+{
+	if (!list_empty(list))
+		__list_splice_rcu(list, head, head->next);
+}
+
 /**
  * __list_splice_init_rcu - join an RCU-protected list into an existing list.
  * @list:	the RCU-protected list to splice
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH nf,v2 1/3] rculist: add list_splice_rcu() for private lists
  2026-04-15 17:08 [PATCH nf,v2 1/3] rculist: add list_splice_rcu() for private lists Pablo Neira Ayuso
@ 2026-04-15 17:39 ` Paul E. McKenney
  2026-04-15 20:25   ` Pablo Neira Ayuso
  0 siblings, 1 reply; 3+ messages in thread
From: Paul E. McKenney @ 2026-04-15 17:39 UTC (permalink / raw)
  To: Pablo Neira Ayuso
  Cc: netfilter-devel, davem, netdev, kuba, pabeni, edumazet, fw, horms,
	joelagnelf, josh, boqun, urezki, rostedt, mathieu.desnoyers,
	jiangshanlai, qiang.zhang, rcu

On Wed, Apr 15, 2026 at 07:08:44PM +0200, Pablo Neira Ayuso wrote:
> This patch adds a helper function, list_splice_rcu(), to safely splice
> a private (non-RCU-protected) list into an RCU-protected list.
> 
> The function ensures that only the pointer visible to RCU readers
> (prev->next) is updated using rcu_assign_pointer(), while the rest of
> the list manipulations are performed with regular assignments, as the
> source list is private and not visible to concurrent RCU readers.
> 
> This is useful for moving elements from a private list into a global
> RCU-protected list, ensuring safe publication for RCU readers.
> Subsystems with some sort of batching mechanism from userspace can
> benefit from this new function.
> 
> The function __list_splice_rcu() has been added for clarity and to
> follow the same pattern as in the existing list_splice*() interfaces,
> where there is a check to ensure that that the list to splice is not
> empty. Note that __list_splice_rcu() has no documentation for this
> reason.
> 
> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
> ---
> v2: including comments by Paul McKenney.
> 
>     Except, I have deliberately keep back the suggestion to squash
>     __list_splice_rcu() into list_splice_rcu(), I instead removed
>     the documentation for __list_splice_rcu(). I am looking
>     at other existing list_splice*() function in list.h and rculist.h
>     to get this aligned with __list_splice(), which also has no users
>     in the tree and no documentation. I find it easier to read with
>     __list_splice(), but if this explaination is not sound so...
> 
>     @Paul: I can post v3 squashing __list_splice_rcu(), just let me
>            know.

Removing the comment addresses most of my concerns.  I do have a slight
but not overwhelming preference for the squashed version, but either way:

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

Or if you want this to go in via RCU, please let us know.  My guess is
that it would be easier for you to take it in with the code using it.

							Thanx, Paul

>     Thanks!
> 
>  include/linux/rculist.h | 29 +++++++++++++++++++++++++++++
>  1 file changed, 29 insertions(+)
> 
> diff --git a/include/linux/rculist.h b/include/linux/rculist.h
> index 2abba7552605..e3bc44225692 100644
> --- a/include/linux/rculist.h
> +++ b/include/linux/rculist.h
> @@ -261,6 +261,35 @@ static inline void list_replace_rcu(struct list_head *old,
>  	old->prev = LIST_POISON2;
>  }
>  
> +static inline void __list_splice_rcu(struct list_head *list,
> +				     struct list_head *prev,
> +				     struct list_head *next)
> +{
> +	struct list_head *first = list->next;
> +	struct list_head *last = list->prev;
> +
> +	last->next = next;
> +	first->prev = prev;
> +	next->prev = last;
> +	rcu_assign_pointer(list_next_rcu(prev), first);
> +}
> +
> +/**
> + * list_splice_rcu - splice a non-RCU list into an RCU-protected list,
> + *                   designed for stacks.
> + * @list:	the non RCU-protected list to splice
> + * @head:	the place in the existing RCU-protected list to splice
> + *
> + * The list pointed to by @head can be RCU-read traversed concurrently with
> + * this function.
> + */
> +static inline void list_splice_rcu(struct list_head *list,
> +				   struct list_head *head)
> +{
> +	if (!list_empty(list))
> +		__list_splice_rcu(list, head, head->next);
> +}
> +
>  /**
>   * __list_splice_init_rcu - join an RCU-protected list into an existing list.
>   * @list:	the RCU-protected list to splice
> -- 
> 2.47.3
> 
> 

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH nf,v2 1/3] rculist: add list_splice_rcu() for private lists
  2026-04-15 17:39 ` Paul E. McKenney
@ 2026-04-15 20:25   ` Pablo Neira Ayuso
  0 siblings, 0 replies; 3+ messages in thread
From: Pablo Neira Ayuso @ 2026-04-15 20:25 UTC (permalink / raw)
  To: Paul E. McKenney
  Cc: netfilter-devel, davem, netdev, kuba, pabeni, edumazet, fw, horms,
	joelagnelf, josh, boqun, urezki, rostedt, mathieu.desnoyers,
	jiangshanlai, qiang.zhang, rcu

On Wed, Apr 15, 2026 at 10:39:33AM -0700, Paul E. McKenney wrote:
> On Wed, Apr 15, 2026 at 07:08:44PM +0200, Pablo Neira Ayuso wrote:
> > This patch adds a helper function, list_splice_rcu(), to safely splice
> > a private (non-RCU-protected) list into an RCU-protected list.
> > 
> > The function ensures that only the pointer visible to RCU readers
> > (prev->next) is updated using rcu_assign_pointer(), while the rest of
> > the list manipulations are performed with regular assignments, as the
> > source list is private and not visible to concurrent RCU readers.
> > 
> > This is useful for moving elements from a private list into a global
> > RCU-protected list, ensuring safe publication for RCU readers.
> > Subsystems with some sort of batching mechanism from userspace can
> > benefit from this new function.
> > 
> > The function __list_splice_rcu() has been added for clarity and to
> > follow the same pattern as in the existing list_splice*() interfaces,
> > where there is a check to ensure that that the list to splice is not
> > empty. Note that __list_splice_rcu() has no documentation for this
> > reason.
> > 
> > Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
> > ---
> > v2: including comments by Paul McKenney.
> > 
> >     Except, I have deliberately keep back the suggestion to squash
> >     __list_splice_rcu() into list_splice_rcu(), I instead removed
> >     the documentation for __list_splice_rcu(). I am looking
> >     at other existing list_splice*() function in list.h and rculist.h
> >     to get this aligned with __list_splice(), which also has no users
> >     in the tree and no documentation. I find it easier to read with
> >     __list_splice(), but if this explaination is not sound so...
> > 
> >     @Paul: I can post v3 squashing __list_splice_rcu(), just let me
> >            know.
> 
> Removing the comment addresses most of my concerns.  I do have a slight
> but not overwhelming preference for the squashed version, but either way:
> 
> Reviewed-by: Paul E. McKenney <paulmck@kernel.org>
> 
> Or if you want this to go in via RCU, please let us know.  My guess is
> that it would be easier for you to take it in with the code using it.

I'd prefer to take it through nf.git, I need this as a fix for an
invalid use of list_splice() on a RCU-protected list.

Thanks for your quick review Paul!

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-04-15 20:25 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-15 17:08 [PATCH nf,v2 1/3] rculist: add list_splice_rcu() for private lists Pablo Neira Ayuso
2026-04-15 17:39 ` Paul E. McKenney
2026-04-15 20:25   ` Pablo Neira Ayuso

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox