aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorNadia Derbey <Nadia.Derbey@bull.net>2008-07-25 04:48:01 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-25 13:53:42 -0400
commitf9c46d6ea5ce138a886c3a0f10a46130afab75f5 (patch)
tree1eedc2428866fb0b3f9f864e52ffb6eaf00911a4 /lib
parent3219b3b7456d5cf15ba7b1fe7b1bcf15ce8840e2 (diff)
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);
456 * return indicates that @id is not valid or you passed %NULL in 456 * return indicates that @id is not valid or you passed %NULL in
457 * idr_get_new(). 457 * idr_get_new().
458 * 458 *
459 * The caller must serialize idr_find() vs idr_get_new() and idr_remove(). 459 * This function can be called under rcu_read_lock(), given that the leaf
460 * pointers lifetimes are correctly managed.
460 */ 461 */
461void *idr_find(struct idr *idp, int id) 462void *idr_find(struct idr *idp, int id)
462{ 463{
@@ -464,7 +465,7 @@ void *idr_find(struct idr *idp, int id)
464 struct idr_layer *p; 465 struct idr_layer *p;
465 466
466 n = idp->layers * IDR_BITS; 467 n = idp->layers * IDR_BITS;
467 p = idp->top; 468 p = rcu_dereference(idp->top);
468 469
469 /* Mask off upper bits we don't use for the search. */ 470 /* Mask off upper bits we don't use for the search. */
470 id &= MAX_ID_MASK; 471 id &= MAX_ID_MASK;
@@ -474,7 +475,7 @@ void *idr_find(struct idr *idp, int id)
474 475
475 while (n > 0 && p) { 476 while (n > 0 && p) {
476 n -= IDR_BITS; 477 n -= IDR_BITS;
477 p = p->ary[(id >> n) & IDR_MASK]; 478 p = rcu_dereference(p->ary[(id >> n) & IDR_MASK]);
478 } 479 }
479 return((void *)p); 480 return((void *)p);
480} 481}
@@ -507,7 +508,7 @@ int idr_for_each(struct idr *idp,
507 struct idr_layer **paa = &pa[0]; 508 struct idr_layer **paa = &pa[0];
508 509
509 n = idp->layers * IDR_BITS; 510 n = idp->layers * IDR_BITS;
510 p = idp->top; 511 p = rcu_dereference(idp->top);
511 max = 1 << n; 512 max = 1 << n;
512 513
513 id = 0; 514 id = 0;
@@ -515,7 +516,7 @@ int idr_for_each(struct idr *idp,
515 while (n > 0 && p) { 516 while (n > 0 && p) {
516 n -= IDR_BITS; 517 n -= IDR_BITS;
517 *paa++ = p; 518 *paa++ = p;
518 p = p->ary[(id >> n) & IDR_MASK]; 519 p = rcu_dereference(p->ary[(id >> n) & IDR_MASK]);
519 } 520 }
520 521
521 if (p) { 522 if (p) {