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