[PATCH v2 1/2] srcu: Add list_splice_init_srcu()

Paul E. McKenney paulmck at kernel.org
Wed Nov 4 09:14:12 PST 2026


On Wed, Nov 04, 2026 at 01:30:39AM -0500, Qiliang Yuan wrote:
> list_splice_init_rcu() makes a list look empty to new readers, waits for
> the current ones with the given sync function, and only then links the
> entries into the new list. The sync function takes no argument, so it
> can wait for RCU readers but not for the readers of an srcu_struct.
> 
> Passing synchronize_rcu() for a list read under SRCU still builds, but
> leaves SRCU readers on the entries while the last one's next pointer is
> moved onto the new list head. nvme_remove_namespaces() does this today.
> 
> Add list_splice_init_srcu(), which waits for the readers of the given
> srcu_struct instead.
> 
> Cc: stable at vger.kernel.org
> Suggested-by: Christoph Hellwig <hch at lst.de>
> Signed-off-by: Qiliang Yuan <odys.yuan at gmail.com>

I am not inalterably opposed to adding a list_splice_init_srcu(),
especially if quite a few more users show up, but here is what I was
expecting people to do:

	static void synchronize_my_srcu(void)
	{
		synchronize_srcu(&my_srcu);
	}

	...

	list_splice_init_rcu(l, h, synchronize_my_srcu);

We need at least six uses of the above idiom to break even on the line
of code required for introducing a list_splice_init_srcu().

							Thanx, Paul

> ---
>  include/linux/srcu.h | 36 ++++++++++++++++++++++++++++++++++++
>  1 file changed, 36 insertions(+)
> 
> diff --git a/include/linux/srcu.h b/include/linux/srcu.h
> index 1a8a465a5650d..d4dcaeb83e2b6 100644
> --- a/include/linux/srcu.h
> +++ b/include/linux/srcu.h
> @@ -18,6 +18,7 @@
>  
>  #include <linux/mutex.h>
>  #include <linux/rcupdate.h>
> +#include <linux/rculist.h>
>  #include <linux/workqueue.h>
>  #include <linux/rcu_segcblist.h>
>  
> @@ -118,6 +119,41 @@ void cleanup_srcu_struct(struct srcu_struct *ssp);
>  void synchronize_srcu(struct srcu_struct *ssp);
>  void synchronize_srcu_atomic(struct srcu_struct *ssp);
>  
> +/**
> + * list_splice_init_srcu - splice an SRCU-protected list into an existing list
> + * @list:	the SRCU-protected list to splice
> + * @head:	the place in the existing list to splice the first list into
> + * @ssp:	the srcu_struct that readers of @list use
> + *
> + * Like list_splice_init_rcu(), but wait for the SRCU readers of @list
> + * instead of RCU ones, so that none of them can follow a next pointer
> + * onto @head.
> + *
> + * Note that this function blocks, and that the caller must prevent any
> + * other updates to @list.
> + */
> +static inline void list_splice_init_srcu(struct list_head *list,
> +					 struct list_head *head,
> +					 struct srcu_struct *ssp)
> +{
> +	struct list_head *first = list->next;
> +	struct list_head *last = list->prev;
> +	struct list_head *next = head->next;
> +
> +	if (list_empty(list))
> +		return;
> +
> +	INIT_LIST_HEAD_RCU(list);
> +	synchronize_srcu(ssp);
> +	ASSERT_EXCLUSIVE_ACCESS(*first);
> +	ASSERT_EXCLUSIVE_ACCESS(*last);
> +
> +	last->next = next;
> +	rcu_assign_pointer(list_next_rcu(head), first);
> +	first->prev = head;
> +	next->prev = last;
> +}
> +
>  #define SRCU_GET_STATE_COMPLETED 0x1
>  
>  /**
> 
> -- 
> 2.43.0
> 



More information about the Linux-nvme mailing list