diff options
Diffstat (limited to 'lib/idr.c')
| -rw-r--r-- | lib/idr.c | 14 |
1 files changed, 12 insertions, 2 deletions
| @@ -185,6 +185,7 @@ static int sub_alloc(struct idr *idp, int *starting_id, struct idr_layer **pa) | |||
| 185 | new = get_from_free_list(idp); | 185 | new = get_from_free_list(idp); |
| 186 | if (!new) | 186 | if (!new) |
| 187 | return -1; | 187 | return -1; |
| 188 | new->layer = l-1; | ||
| 188 | rcu_assign_pointer(p->ary[m], new); | 189 | rcu_assign_pointer(p->ary[m], new); |
| 189 | p->count++; | 190 | p->count++; |
| 190 | } | 191 | } |
| @@ -210,6 +211,7 @@ build_up: | |||
| 210 | if (unlikely(!p)) { | 211 | if (unlikely(!p)) { |
| 211 | if (!(p = get_from_free_list(idp))) | 212 | if (!(p = get_from_free_list(idp))) |
| 212 | return -1; | 213 | return -1; |
| 214 | p->layer = 0; | ||
| 213 | layers = 1; | 215 | layers = 1; |
| 214 | } | 216 | } |
| 215 | /* | 217 | /* |
| @@ -237,6 +239,7 @@ build_up: | |||
| 237 | } | 239 | } |
| 238 | new->ary[0] = p; | 240 | new->ary[0] = p; |
| 239 | new->count = 1; | 241 | new->count = 1; |
| 242 | new->layer = layers-1; | ||
| 240 | if (p->bitmap == IDR_FULL) | 243 | if (p->bitmap == IDR_FULL) |
| 241 | __set_bit(0, &new->bitmap); | 244 | __set_bit(0, &new->bitmap); |
| 242 | p = new; | 245 | p = new; |
| @@ -493,17 +496,21 @@ void *idr_find(struct idr *idp, int id) | |||
| 493 | int n; | 496 | int n; |
| 494 | struct idr_layer *p; | 497 | struct idr_layer *p; |
| 495 | 498 | ||
| 496 | n = idp->layers * IDR_BITS; | ||
| 497 | p = rcu_dereference(idp->top); | 499 | p = rcu_dereference(idp->top); |
| 500 | if (!p) | ||
| 501 | return NULL; | ||
| 502 | n = (p->layer+1) * IDR_BITS; | ||
| 498 | 503 | ||
| 499 | /* Mask off upper bits we don't use for the search. */ | 504 | /* Mask off upper bits we don't use for the search. */ |
| 500 | id &= MAX_ID_MASK; | 505 | id &= MAX_ID_MASK; |
| 501 | 506 | ||
| 502 | if (id >= (1 << n)) | 507 | if (id >= (1 << n)) |
| 503 | return NULL; | 508 | return NULL; |
| 509 | BUG_ON(n == 0); | ||
| 504 | 510 | ||
| 505 | while (n > 0 && p) { | 511 | while (n > 0 && p) { |
| 506 | n -= IDR_BITS; | 512 | n -= IDR_BITS; |
| 513 | BUG_ON(n != p->layer*IDR_BITS); | ||
| 507 | p = rcu_dereference(p->ary[(id >> n) & IDR_MASK]); | 514 | p = rcu_dereference(p->ary[(id >> n) & IDR_MASK]); |
| 508 | } | 515 | } |
| 509 | return((void *)p); | 516 | return((void *)p); |
| @@ -582,8 +589,11 @@ void *idr_replace(struct idr *idp, void *ptr, int id) | |||
| 582 | int n; | 589 | int n; |
| 583 | struct idr_layer *p, *old_p; | 590 | struct idr_layer *p, *old_p; |
| 584 | 591 | ||
| 585 | n = idp->layers * IDR_BITS; | ||
| 586 | p = idp->top; | 592 | p = idp->top; |
| 593 | if (!p) | ||
| 594 | return ERR_PTR(-EINVAL); | ||
| 595 | |||
| 596 | n = (p->layer+1) * IDR_BITS; | ||
| 587 | 597 | ||
| 588 | id &= MAX_ID_MASK; | 598 | id &= MAX_ID_MASK; |
| 589 | 599 | ||
