On 15-10-06 11:37:01, Paul E. McKenney wrote:
> 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.

I hope so.

> But who is using the new list_splice_tail_init_rcu() function?

For now the sole user is code in .../security/integrity/ima/ima_policy.c which 
splices two lists in order to form a queue.  The patches that convert (among 
other things) mutexes to RCU locks are already in Mimi's pipeline and scheduled 
for 4.4.

BTW, if you are at the ELC in Dublin i can find you and quickly explain the 
whole thing in person.


cheers,
Petko


> > ---
> >  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
--
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