2nd part of the fixes needed for http://bugzilla.kernel.org/show_bug.cgi?id=11796. When the idr tree is either grown or shrunk, then the update to the number of layers and the top pointer were not atomic. This race caused crashes. The attached patch fixes that by replicating the layers counter in each layer, thus idr_find doesn't need idp->layers anymore.
Unified · Split
| @@ -52,13 +52,14 @@ struct idr_layer { · 51 unmodified lines | |||
| 52 | unsigned long bitmap; /* A zero bit means "space here" */ | 52 | unsigned long bitmap; /* A zero bit means "space here" */ |
| 53 | struct idr_layer *ary[1<<IDR_BITS]; | 53 | struct idr_layer *ary[1<<IDR_BITS]; |
| 54 | int count; /* When zero, we can release it */ | 54 | int count; /* When zero, we can release it */ |
| 55 | int layer; /* distance from leaf */ | ||
| 55 | struct rcu_head rcu_head; | 56 | struct rcu_head rcu_head; |
| 56 | }; | 57 | }; |
| 57 | 58 | ||
| 58 | struct idr { | 59 | struct idr { |
| 59 | struct idr_layer *top; | 60 | struct idr_layer *top; |
| 60 | struct idr_layer *id_free; | 61 | struct idr_layer *id_free; |
| 61 | int layers; | 62 | int layers; /* only valid without concurrent changes */ |
| 62 | int id_free_cnt; | 63 | int id_free_cnt; |
| 63 | spinlock_t lock; | 64 | spinlock_t lock; |
| 64 | }; | 65 | }; |
| @@ -185,6 +185,7 @@ static int sub_alloc(struct idr *idp, int *starting_id, struct idr_layer **pa) · 184 unmodified lines | |||
| 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: · 19 unmodified lines | |||
| 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: · 21 unmodified lines | |||
| 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) · 250 unmodified lines | |||
| 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) · 72 unmodified lines | |||
| 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 | ||