aboutsummaryrefslogtreecommitdiffstats
path: root/lib/idr.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/idr.c')
-rw-r--r--lib/idr.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/lib/idr.c b/lib/idr.c
index 0dc782216d4b..c1a206901761 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -445,6 +445,7 @@ EXPORT_SYMBOL(idr_remove);
445void idr_remove_all(struct idr *idp) 445void idr_remove_all(struct idr *idp)
446{ 446{
447 int n, id, max; 447 int n, id, max;
448 int bt_mask;
448 struct idr_layer *p; 449 struct idr_layer *p;
449 struct idr_layer *pa[MAX_LEVEL]; 450 struct idr_layer *pa[MAX_LEVEL];
450 struct idr_layer **paa = &pa[0]; 451 struct idr_layer **paa = &pa[0];
@@ -462,8 +463,10 @@ void idr_remove_all(struct idr *idp)
462 p = p->ary[(id >> n) & IDR_MASK]; 463 p = p->ary[(id >> n) & IDR_MASK];
463 } 464 }
464 465
466 bt_mask = id;
465 id += 1 << n; 467 id += 1 << n;
466 while (n < fls(id)) { 468 /* Get the highest bit that the above add changed from 0->1. */
469 while (n < fls(id ^ bt_mask)) {
467 if (p) 470 if (p)
468 free_layer(p); 471 free_layer(p);
469 n += IDR_BITS; 472 n += IDR_BITS;
@@ -504,7 +507,7 @@ void *idr_find(struct idr *idp, int id)
504 int n; 507 int n;
505 struct idr_layer *p; 508 struct idr_layer *p;
506 509
507 p = rcu_dereference(idp->top); 510 p = rcu_dereference_raw(idp->top);
508 if (!p) 511 if (!p)
509 return NULL; 512 return NULL;
510 n = (p->layer+1) * IDR_BITS; 513 n = (p->layer+1) * IDR_BITS;
@@ -519,7 +522,7 @@ void *idr_find(struct idr *idp, int id)
519 while (n > 0 && p) { 522 while (n > 0 && p) {
520 n -= IDR_BITS; 523 n -= IDR_BITS;
521 BUG_ON(n != p->layer*IDR_BITS); 524 BUG_ON(n != p->layer*IDR_BITS);
522 p = rcu_dereference(p->ary[(id >> n) & IDR_MASK]); 525 p = rcu_dereference_raw(p->ary[(id >> n) & IDR_MASK]);
523 } 526 }
524 return((void *)p); 527 return((void *)p);
525} 528}
@@ -552,7 +555,7 @@ int idr_for_each(struct idr *idp,
552 struct idr_layer **paa = &pa[0]; 555 struct idr_layer **paa = &pa[0];
553 556
554 n = idp->layers * IDR_BITS; 557 n = idp->layers * IDR_BITS;
555 p = rcu_dereference(idp->top); 558 p = rcu_dereference_raw(idp->top);
556 max = 1 << n; 559 max = 1 << n;
557 560
558 id = 0; 561 id = 0;
@@ -560,7 +563,7 @@ int idr_for_each(struct idr *idp,
560 while (n > 0 && p) { 563 while (n > 0 && p) {
561 n -= IDR_BITS; 564 n -= IDR_BITS;
562 *paa++ = p; 565 *paa++ = p;
563 p = rcu_dereference(p->ary[(id >> n) & IDR_MASK]); 566 p = rcu_dereference_raw(p->ary[(id >> n) & IDR_MASK]);
564 } 567 }
565 568
566 if (p) { 569 if (p) {
@@ -623,7 +626,7 @@ void *idr_get_next(struct idr *idp, int *nextidp)
623 } 626 }
624 return NULL; 627 return NULL;
625} 628}
626 629EXPORT_SYMBOL(idr_get_next);
627 630
628 631
629/** 632/**