From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758719AbbJIS1A (ORCPT ); Fri, 9 Oct 2015 14:27:00 -0400 Received: from e39.co.us.ibm.com ([32.97.110.160]:33817 "EHLO e39.co.us.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756241AbbJIS04 (ORCPT ); Fri, 9 Oct 2015 14:26:56 -0400 X-IBM-Helo: d03dlp03.boulder.ibm.com X-IBM-MailFrom: paulmck@linux.vnet.ibm.com X-IBM-RcptTo: linux-kernel@vger.kernel.org;linux-security-module@vger.kernel.org Date: Fri, 9 Oct 2015 11:26:38 -0700 From: "Paul E. McKenney" To: Mimi Zohar Cc: Petko Manolov , mdb@juniper.net, linux-security-module@vger.kernel.org, rostedt@goodmis.org, linux-kernel@vger.kernel.org Subject: Re: [PATCH] Introduces generic __list_splice_init_rcu(); Message-ID: <20151009182638.GX3910@linux.vnet.ibm.com> Reply-To: paulmck@linux.vnet.ibm.com References: <1443366628-19897-1-git-send-email-petkan@mip-labs.com> <1443366628-19897-2-git-send-email-petkan@mip-labs.com> <20151006183701.GQ3910@linux.vnet.ibm.com> <1444334539.2503.119.camel@linux.vnet.ibm.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1444334539.2503.119.camel@linux.vnet.ibm.com> User-Agent: Mutt/1.5.21 (2010-09-15) X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 15100918-0033-0000-0000-0000064EB812 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, Oct 08, 2015 at 04:02:19PM -0400, Mimi Zohar wrote: > On Tue, 2015-10-06 at 11:37 -0700, 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 > > > > At first glance, this looks sane. > > > > But who is using the new list_splice_tail_init_rcu() function? > > Hi, Paul. Up to now a single policy was loaded, normally in the > initramfs, and never changed. Petko is adding support to extend the > policy rules. The additional policies would be appended to the existing > list, only after verifying the new set of rules are good. > > list.h contains list_splice() and list_splice_tail(), but the RCU > equivalent functions don't exist. OK, I have queued Petko's patch, updating the subject and changelog as shown below. I added you as Cc. If testing goes well, I will submit this for v4.5 (the merge window after next). Thanx, Paul ------------------------------------------------------------------------ commit a7916adc2cc47e918ee66b9225c00d585ccd3a91 Author: Petko Manolov Date: Sun Sep 27 18:10:28 2015 +0300 Introduce generic list_splice_tail_init_rcu() The list_splice_init_rcu() can be used as a stack onto which full lists are pushed, but queue-like behavior is now needed by some security policies. This requires a list_splice_tail_init_rcu(). This commit therefore supplies a list_splice_tail_init_rcu() by pulling code common it and to list_splice_init_rcu() into a new __list_splice_init_rcu() function. This new function is based on the existing list_splice_init_rcu() implementation. Signed-off-by: Petko Manolov Cc: Mimi Zohar Signed-off-by: Paul E. McKenney diff --git a/include/linux/rculist.h b/include/linux/rculist.h index 5ed540986019..bbde2837d6be 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); } /**