diff options
Diffstat (limited to 'lib/idr.c')
-rw-r--r-- | lib/idr.c | 23 |
1 files changed, 14 insertions, 9 deletions
@@ -156,10 +156,12 @@ static int sub_alloc(struct idr *idp, int *starting_id, struct idr_layer **pa) | |||
156 | id = (id | ((1 << (IDR_BITS * l)) - 1)) + 1; | 156 | id = (id | ((1 << (IDR_BITS * l)) - 1)) + 1; |
157 | 157 | ||
158 | /* if already at the top layer, we need to grow */ | 158 | /* if already at the top layer, we need to grow */ |
159 | if (!(p = pa[l])) { | 159 | if (id >= 1 << (idp->layers * IDR_BITS)) { |
160 | *starting_id = id; | 160 | *starting_id = id; |
161 | return IDR_NEED_TO_GROW; | 161 | return IDR_NEED_TO_GROW; |
162 | } | 162 | } |
163 | p = pa[l]; | ||
164 | BUG_ON(!p); | ||
163 | 165 | ||
164 | /* If we need to go up one layer, continue the | 166 | /* If we need to go up one layer, continue the |
165 | * loop; otherwise, restart from the top. | 167 | * loop; otherwise, restart from the top. |
@@ -443,6 +445,7 @@ EXPORT_SYMBOL(idr_remove); | |||
443 | void idr_remove_all(struct idr *idp) | 445 | void idr_remove_all(struct idr *idp) |
444 | { | 446 | { |
445 | int n, id, max; | 447 | int n, id, max; |
448 | int bt_mask; | ||
446 | struct idr_layer *p; | 449 | struct idr_layer *p; |
447 | struct idr_layer *pa[MAX_LEVEL]; | 450 | struct idr_layer *pa[MAX_LEVEL]; |
448 | struct idr_layer **paa = &pa[0]; | 451 | struct idr_layer **paa = &pa[0]; |
@@ -460,8 +463,10 @@ void idr_remove_all(struct idr *idp) | |||
460 | p = p->ary[(id >> n) & IDR_MASK]; | 463 | p = p->ary[(id >> n) & IDR_MASK]; |
461 | } | 464 | } |
462 | 465 | ||
466 | bt_mask = id; | ||
463 | id += 1 << n; | 467 | id += 1 << n; |
464 | while (n < fls(id)) { | 468 | /* Get the highest bit that the above add changed from 0->1. */ |
469 | while (n < fls(id ^ bt_mask)) { | ||
465 | if (p) | 470 | if (p) |
466 | free_layer(p); | 471 | free_layer(p); |
467 | n += IDR_BITS; | 472 | n += IDR_BITS; |
@@ -502,7 +507,7 @@ void *idr_find(struct idr *idp, int id) | |||
502 | int n; | 507 | int n; |
503 | struct idr_layer *p; | 508 | struct idr_layer *p; |
504 | 509 | ||
505 | p = rcu_dereference(idp->top); | 510 | p = rcu_dereference_raw(idp->top); |
506 | if (!p) | 511 | if (!p) |
507 | return NULL; | 512 | return NULL; |
508 | n = (p->layer+1) * IDR_BITS; | 513 | n = (p->layer+1) * IDR_BITS; |
@@ -517,7 +522,7 @@ void *idr_find(struct idr *idp, int id) | |||
517 | while (n > 0 && p) { | 522 | while (n > 0 && p) { |
518 | n -= IDR_BITS; | 523 | n -= IDR_BITS; |
519 | BUG_ON(n != p->layer*IDR_BITS); | 524 | BUG_ON(n != p->layer*IDR_BITS); |
520 | p = rcu_dereference(p->ary[(id >> n) & IDR_MASK]); | 525 | p = rcu_dereference_raw(p->ary[(id >> n) & IDR_MASK]); |
521 | } | 526 | } |
522 | return((void *)p); | 527 | return((void *)p); |
523 | } | 528 | } |
@@ -550,7 +555,7 @@ int idr_for_each(struct idr *idp, | |||
550 | struct idr_layer **paa = &pa[0]; | 555 | struct idr_layer **paa = &pa[0]; |
551 | 556 | ||
552 | n = idp->layers * IDR_BITS; | 557 | n = idp->layers * IDR_BITS; |
553 | p = rcu_dereference(idp->top); | 558 | p = rcu_dereference_raw(idp->top); |
554 | max = 1 << n; | 559 | max = 1 << n; |
555 | 560 | ||
556 | id = 0; | 561 | id = 0; |
@@ -558,7 +563,7 @@ int idr_for_each(struct idr *idp, | |||
558 | while (n > 0 && p) { | 563 | while (n > 0 && p) { |
559 | n -= IDR_BITS; | 564 | n -= IDR_BITS; |
560 | *paa++ = p; | 565 | *paa++ = p; |
561 | p = rcu_dereference(p->ary[(id >> n) & IDR_MASK]); | 566 | p = rcu_dereference_raw(p->ary[(id >> n) & IDR_MASK]); |
562 | } | 567 | } |
563 | 568 | ||
564 | if (p) { | 569 | if (p) { |
@@ -597,7 +602,7 @@ void *idr_get_next(struct idr *idp, int *nextidp) | |||
597 | /* find first ent */ | 602 | /* find first ent */ |
598 | n = idp->layers * IDR_BITS; | 603 | n = idp->layers * IDR_BITS; |
599 | max = 1 << n; | 604 | max = 1 << n; |
600 | p = rcu_dereference(idp->top); | 605 | p = rcu_dereference_raw(idp->top); |
601 | if (!p) | 606 | if (!p) |
602 | return NULL; | 607 | return NULL; |
603 | 608 | ||
@@ -605,7 +610,7 @@ void *idr_get_next(struct idr *idp, int *nextidp) | |||
605 | while (n > 0 && p) { | 610 | while (n > 0 && p) { |
606 | n -= IDR_BITS; | 611 | n -= IDR_BITS; |
607 | *paa++ = p; | 612 | *paa++ = p; |
608 | p = rcu_dereference(p->ary[(id >> n) & IDR_MASK]); | 613 | p = rcu_dereference_raw(p->ary[(id >> n) & IDR_MASK]); |
609 | } | 614 | } |
610 | 615 | ||
611 | if (p) { | 616 | if (p) { |
@@ -621,7 +626,7 @@ void *idr_get_next(struct idr *idp, int *nextidp) | |||
621 | } | 626 | } |
622 | return NULL; | 627 | return NULL; |
623 | } | 628 | } |
624 | 629 | EXPORT_SYMBOL(idr_get_next); | |
625 | 630 | ||
626 | 631 | ||
627 | /** | 632 | /** |