From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
To: Christoph Hellwig <hch@infradead.org>,
Corey Minyard <minyard@acm.org>, Andrew Morton <akpm@osdl.org>,
Linux Kernel <linux-kernel@vger.kernel.org>,
Carol Hebert <cah@us.ibm.com>,
OpenIPMI Developers <openipmi-developer@lists.sourceforge.net>
Subject: Re: [PATCH] IPMI: fix some RCU problems
Date: Thu, 28 Dec 2006 11:55:04 -0800 [thread overview]
Message-ID: <20061228195504.GC4501@linux.vnet.ibm.com> (raw)
In-Reply-To: <20061228183101.GA2412@infradead.org>
On Thu, Dec 28, 2006 at 06:31:01PM +0000, Christoph Hellwig wrote:
> > + if (list_empty(&intf->cmd_rcvrs))
> > + INIT_LIST_HEAD(&list);
> > + else {
> > + list.next = intf->cmd_rcvrs.next;
> > + list.prev = intf->cmd_rcvrs.prev;
> > + INIT_LIST_HEAD(&intf->cmd_rcvrs);
> > +
> > + /*
> > + * At this point the list body still points to
> > + * intf->cmd_rcvrs. Wait for any readers to finish
> > + * using the list before we switch the list body over
> > + * to the new list.
> > + */
> > + synchronize_rcu();
> > +
> > + /* Ready the list for use. */
> > + list.next->prev = &list;
> > + list.prev->next = &list;
> > + }
>
> This kind of thing must not be opencoded in drivers. Please add
> a new list_splice_rcu helper to list.h
I must admit that this sounds better than list_privatize_rcu(). But since
the source list gets initialized, so how about list_splice_init_rcu()?
Patch below, untested, probably does not compile. This takes the sync
function as an argument, so one would do something like:
INIT_LIST_HEAD(&list);
list_splice_init_rcu(&intf->cmdrcvrs, &list, synchronize_rcu);
The idea being to keep the RCU API proliferation down to a dull roar.
Thoughts?
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
list.h | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 58 insertions(+)
diff -urpNa -X dontdiff linux-2.6.19/include/linux/list.h linux-2.6.19-lpr/include/linux/list.h
--- linux-2.6.19/include/linux/list.h 2006-11-29 13:57:37.000000000 -0800
+++ linux-2.6.19-lpr/include/linux/list.h 2006-12-28 11:48:31.000000000 -0800
@@ -360,6 +360,64 @@ static inline void list_splice_init(stru
}
/**
+ * 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))
+{
+ struct list_head *first = list->next;
+ struct list_head *last = list->prev;
+ struct list_head *at = head->next;
+
+ might_sleep();
+ if (list_empty(head)) {
+ return;
+ }
+
+ /* "first" and "last" tracking list, so initialize it. */
+
+ INIT_LIST_HEAD(list);
+
+ /*
+ * At this point, the list body still points to the source list.
+ * Wait for any readers to finish using the list before splicing
+ * the list body into the new list. Any new readers will see
+ * an empty list.
+ */
+
+ sync();
+
+ /*
+ * Readers are finished with the source list, so perform splice.
+ * The order is important if the new list is global and accessible
+ * to concurrent RCU readers. Note that RCU readers are not
+ * permitted to traverse the prev pointers without excluding
+ * this function.
+ */
+
+ last->next = at;
+ smp_wmb();
+ head->next = first;
+ first->prev = head;
+ at->prev = last;
+}
+
+/**
* list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer.
* @type: the type of the struct this is embedded in.
next prev parent reply other threads:[~2006-12-28 19:55 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-12-28 18:24 [PATCH] IPMI: fix some RCU problems Corey Minyard
2006-12-28 18:31 ` Christoph Hellwig
2006-12-28 19:55 ` Paul E. McKenney [this message]
2006-12-28 20:24 ` Randy Dunlap
2006-12-28 22:23 ` Paul E. McKenney
-- strict thread matches above, loose matches on Subject: below --
2007-01-03 15:31 [PATCH] IPMI: Fix " Corey Minyard
2007-01-03 21:22 ` Andrew Morton
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20061228195504.GC4501@linux.vnet.ibm.com \
--to=paulmck@linux.vnet.ibm.com \
--cc=akpm@osdl.org \
--cc=cah@us.ibm.com \
--cc=hch@infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=minyard@acm.org \
--cc=openipmi-developer@lists.sourceforge.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.