summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorNadia Derbey <Nadia.Derbey@bull.net>2008-07-25 01:48:01 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-25 10:53:42 -0700
commitf9c46d6ea5ce138a886c3a0f10a46130afab75f5 (patch)
tree1eedc2428866fb0b3f9f864e52ffb6eaf00911a4 /lib
parent3219b3b7456d5cf15ba7b1fe7b1bcf15ce8840e2 (diff)
downloadlinux-stable-f9c46d6ea5ce138a886c3a0f10a46130afab75f5.tar.gz
linux-stable-f9c46d6ea5ce138a886c3a0f10a46130afab75f5.tar.bz2
linux-stable-f9c46d6ea5ce138a886c3a0f10a46130afab75f5.zip
idr: make idr_find rcu-safe
Make idr_find rcu-safe: it can now be called inside an rcu_read critical section. Signed-off-by: Nadia Derbey <Nadia.Derbey@bull.net> Reviewed-by: "Paul E. McKenney" <paulmck@us.ibm.com> Cc: Manfred Spraul <manfred@colorfullife.com> Cc: Jim Houston <jim.houston@comcast.net> Cc: Pierre Peiffer <peifferp@gmail.com> Acked-by: Rik van Riel <riel@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/idr.c11
1 files changed, 6 insertions, 5 deletions
diff --git a/lib/idr.c b/lib/idr.c
index 44ab3b2a4eba..21e12af1f231 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -456,7 +456,8 @@ EXPORT_SYMBOL(idr_destroy);
* return indicates that @id is not valid or you passed %NULL in
* idr_get_new().
*
- * The caller must serialize idr_find() vs idr_get_new() and idr_remove().
+ * This function can be called under rcu_read_lock(), given that the leaf
+ * pointers lifetimes are correctly managed.
*/
void *idr_find(struct idr *idp, int id)
{
@@ -464,7 +465,7 @@ void *idr_find(struct idr *idp, int id)
struct idr_layer *p;
n = idp->layers * IDR_BITS;
- p = idp->top;
+ p = rcu_dereference(idp->top);
/* Mask off upper bits we don't use for the search. */
id &= MAX_ID_MASK;
@@ -474,7 +475,7 @@ void *idr_find(struct idr *idp, int id)
while (n > 0 && p) {
n -= IDR_BITS;
- p = p->ary[(id >> n) & IDR_MASK];
+ p = rcu_dereference(p->ary[(id >> n) & IDR_MASK]);
}
return((void *)p);
}
@@ -507,7 +508,7 @@ int idr_for_each(struct idr *idp,
struct idr_layer **paa = &pa[0];
n = idp->layers * IDR_BITS;
- p = idp->top;
+ p = rcu_dereference(idp->top);
max = 1 << n;
id = 0;
@@ -515,7 +516,7 @@ int idr_for_each(struct idr *idp,
while (n > 0 && p) {
n -= IDR_BITS;
*paa++ = p;
- p = p->ary[(id >> n) & IDR_MASK];
+ p = rcu_dereference(p->ary[(id >> n) & IDR_MASK]);
}
if (p) {