On Sun, Sep 27, 2015 at 06:10:28PM +0300, Petko Manolov wrote:
> __list_splice_init_rcu() can be used to splice lists forming both stack and
> queue structures, depending on its arguments.  It is based on the initial
> list_splice_init_rcu() with a few minor modifications to help abstracting it.
> 
> Signed-off-by: Petko Manolov <[email protected]>

At first glance, this looks sane.

But who is using the new list_splice_tail_init_rcu() function?

                                                        Thanx, Paul

> ---
>  include/linux/rculist.h | 72 
> ++++++++++++++++++++++++++++++-------------------
>  1 file changed, 44 insertions(+), 28 deletions(-)
> 
> diff --git a/include/linux/rculist.h b/include/linux/rculist.h
> index 17c6b1f..4282236 100644
> --- a/include/linux/rculist.h
> +++ b/include/linux/rculist.h
> @@ -178,33 +178,13 @@ static inline void list_replace_rcu(struct list_head 
> *old,
>       old->prev = LIST_POISON2;
>  }
> 
> -/**
> - * list_splice_init_rcu - splice an RCU-protected list into an existing list.
> - * @list:    the RCU-protected list to splice
> - * @head:    the place in the list to splice the first list into
> - * @sync:    function to sync: synchronize_rcu(), synchronize_sched(), ...
> - *
> - * @head can be RCU-read traversed concurrently with this function.
> - *
> - * Note that this function blocks.
> - *
> - * Important note: the caller must take whatever action is necessary to
> - *   prevent any other updates to @head.  In principle, it is possible
> - *   to modify the list as soon as sync() begins execution.
> - *   If this sort of thing becomes necessary, an alternative version
> - *   based on call_rcu() could be created.  But only if -really-
> - *   needed -- there is no shortage of RCU API members.
> - */
> -static inline void list_splice_init_rcu(struct list_head *list,
> -                                     struct list_head *head,
> -                                     void (*sync)(void))
> +static inline void __list_splice_init_rcu(struct list_head *list,
> +                                       struct list_head *prev,
> +                                       struct list_head *next,
> +                                       void (*sync)(void))
>  {
>       struct list_head *first = list->next;
>       struct list_head *last = list->prev;
> -     struct list_head *at = head->next;
> -
> -     if (list_empty(list))
> -             return;
> 
>       /*
>        * "first" and "last" tracking list, so initialize it.  RCU readers
> @@ -231,10 +211,46 @@ static inline void list_splice_init_rcu(struct 
> list_head *list,
>        * this function.
>        */
> 
> -     last->next = at;
> -     rcu_assign_pointer(list_next_rcu(head), first);
> -     first->prev = head;
> -     at->prev = last;
> +     last->next = next;
> +     rcu_assign_pointer(list_next_rcu(prev), first);
> +     first->prev = prev;
> +     next->prev = last;
> +}
> +
> +/**
> + * list_splice_init_rcu - splice an RCU-protected list into an existing list.
> + * @list:    the RCU-protected list to splice
> + * @head:    the place in the list to splice the first list into
> + * @sync:    function to sync: synchronize_rcu(), synchronize_sched(), ...
> + *
> + * @head can be RCU-read traversed concurrently with this function.
> + *
> + * Note that this function blocks.
> + *
> + * Important note: the caller must take whatever action is necessary to
> + *   prevent any other updates to @head.  In principle, it is possible
> + *   to modify the list as soon as sync() begins execution.
> + *   If this sort of thing becomes necessary, an alternative version
> + *   based on call_rcu() could be created.  But only if -really-
> + *   needed -- there is no shortage of RCU API members.
> + */
> +static inline void list_splice_init_rcu(struct list_head *list,
> +                                     struct list_head *head,
> +                                     void (*sync)(void))
> +{
> +     if (!list_empty(list))
> +             __list_splice_init_rcu(list, head, head->next, sync);
> +}
> +
> +/**
> + * list_splice_tail_init_rcu - same as above, but creates a queue
> + */
> +static inline void list_splice_tail_init_rcu(struct list_head *list,
> +                                          struct list_head *head,
> +                                          void (*sync)(void))
> +{
> +     if (!list_empty(list))
> +             __list_splice_init_rcu(list, head->prev, head, sync);
>  }
> 
>  /**
> -- 
> 2.1.4
> 

--
To unsubscribe from this list: send the line "unsubscribe 
linux-security-module" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to