diff options
Diffstat (limited to 'lib/idr.c')
-rw-r--r-- | lib/idr.c | 40 |
1 files changed, 15 insertions, 25 deletions
@@ -18,12 +18,6 @@ | |||
18 | * pointer or what ever, we treat it as a (void *). You can pass this | 18 | * pointer or what ever, we treat it as a (void *). You can pass this |
19 | * id to a user for him to pass back at a later time. You then pass | 19 | * id to a user for him to pass back at a later time. You then pass |
20 | * that id to this code and it returns your pointer. | 20 | * that id to this code and it returns your pointer. |
21 | |||
22 | * You can release ids at any time. When all ids are released, most of | ||
23 | * the memory is returned (we keep MAX_IDR_FREE) in a local pool so we | ||
24 | * don't need to go to the memory "store" during an id allocate, just | ||
25 | * so you don't need to be too concerned about locking and conflicts | ||
26 | * with the slab allocator. | ||
27 | */ | 21 | */ |
28 | 22 | ||
29 | #ifndef TEST // to test in user space... | 23 | #ifndef TEST // to test in user space... |
@@ -151,7 +145,7 @@ static void idr_layer_rcu_free(struct rcu_head *head) | |||
151 | 145 | ||
152 | static inline void free_layer(struct idr *idr, struct idr_layer *p) | 146 | static inline void free_layer(struct idr *idr, struct idr_layer *p) |
153 | { | 147 | { |
154 | if (idr->hint && idr->hint == p) | 148 | if (idr->hint == p) |
155 | RCU_INIT_POINTER(idr->hint, NULL); | 149 | RCU_INIT_POINTER(idr->hint, NULL); |
156 | call_rcu(&p->rcu_head, idr_layer_rcu_free); | 150 | call_rcu(&p->rcu_head, idr_layer_rcu_free); |
157 | } | 151 | } |
@@ -249,7 +243,7 @@ static int sub_alloc(struct idr *idp, int *starting_id, struct idr_layer **pa, | |||
249 | id = (id | ((1 << (IDR_BITS * l)) - 1)) + 1; | 243 | id = (id | ((1 << (IDR_BITS * l)) - 1)) + 1; |
250 | 244 | ||
251 | /* if already at the top layer, we need to grow */ | 245 | /* if already at the top layer, we need to grow */ |
252 | if (id >= 1 << (idp->layers * IDR_BITS)) { | 246 | if (id > idr_max(idp->layers)) { |
253 | *starting_id = id; | 247 | *starting_id = id; |
254 | return -EAGAIN; | 248 | return -EAGAIN; |
255 | } | 249 | } |
@@ -562,6 +556,11 @@ void idr_remove(struct idr *idp, int id) | |||
562 | if (id < 0) | 556 | if (id < 0) |
563 | return; | 557 | return; |
564 | 558 | ||
559 | if (id > idr_max(idp->layers)) { | ||
560 | idr_remove_warning(id); | ||
561 | return; | ||
562 | } | ||
563 | |||
565 | sub_remove(idp, (idp->layers - 1) * IDR_BITS, id); | 564 | sub_remove(idp, (idp->layers - 1) * IDR_BITS, id); |
566 | if (idp->top && idp->top->count == 1 && (idp->layers > 1) && | 565 | if (idp->top && idp->top->count == 1 && (idp->layers > 1) && |
567 | idp->top->ary[0]) { | 566 | idp->top->ary[0]) { |
@@ -579,16 +578,6 @@ void idr_remove(struct idr *idp, int id) | |||
579 | bitmap_clear(to_free->bitmap, 0, IDR_SIZE); | 578 | bitmap_clear(to_free->bitmap, 0, IDR_SIZE); |
580 | free_layer(idp, to_free); | 579 | free_layer(idp, to_free); |
581 | } | 580 | } |
582 | while (idp->id_free_cnt >= MAX_IDR_FREE) { | ||
583 | p = get_from_free_list(idp); | ||
584 | /* | ||
585 | * Note: we don't call the rcu callback here, since the only | ||
586 | * layers that fall into the freelist are those that have been | ||
587 | * preallocated. | ||
588 | */ | ||
589 | kmem_cache_free(idr_layer_cache, p); | ||
590 | } | ||
591 | return; | ||
592 | } | 581 | } |
593 | EXPORT_SYMBOL(idr_remove); | 582 | EXPORT_SYMBOL(idr_remove); |
594 | 583 | ||
@@ -809,14 +798,12 @@ void *idr_replace(struct idr *idp, void *ptr, int id) | |||
809 | 798 | ||
810 | p = idp->top; | 799 | p = idp->top; |
811 | if (!p) | 800 | if (!p) |
812 | return ERR_PTR(-EINVAL); | 801 | return ERR_PTR(-ENOENT); |
813 | |||
814 | n = (p->layer+1) * IDR_BITS; | ||
815 | 802 | ||
816 | if (id >= (1 << n)) | 803 | if (id > idr_max(p->layer + 1)) |
817 | return ERR_PTR(-EINVAL); | 804 | return ERR_PTR(-ENOENT); |
818 | 805 | ||
819 | n -= IDR_BITS; | 806 | n = p->layer * IDR_BITS; |
820 | while ((n > 0) && p) { | 807 | while ((n > 0) && p) { |
821 | p = p->ary[(id >> n) & IDR_MASK]; | 808 | p = p->ary[(id >> n) & IDR_MASK]; |
822 | n -= IDR_BITS; | 809 | n -= IDR_BITS; |
@@ -1027,6 +1014,9 @@ void ida_remove(struct ida *ida, int id) | |||
1027 | int n; | 1014 | int n; |
1028 | struct ida_bitmap *bitmap; | 1015 | struct ida_bitmap *bitmap; |
1029 | 1016 | ||
1017 | if (idr_id > idr_max(ida->idr.layers)) | ||
1018 | goto err; | ||
1019 | |||
1030 | /* clear full bits while looking up the leaf idr_layer */ | 1020 | /* clear full bits while looking up the leaf idr_layer */ |
1031 | while ((shift > 0) && p) { | 1021 | while ((shift > 0) && p) { |
1032 | n = (idr_id >> shift) & IDR_MASK; | 1022 | n = (idr_id >> shift) & IDR_MASK; |
@@ -1042,7 +1032,7 @@ void ida_remove(struct ida *ida, int id) | |||
1042 | __clear_bit(n, p->bitmap); | 1032 | __clear_bit(n, p->bitmap); |
1043 | 1033 | ||
1044 | bitmap = (void *)p->ary[n]; | 1034 | bitmap = (void *)p->ary[n]; |
1045 | if (!test_bit(offset, bitmap->bitmap)) | 1035 | if (!bitmap || !test_bit(offset, bitmap->bitmap)) |
1046 | goto err; | 1036 | goto err; |
1047 | 1037 | ||
1048 | /* update bitmap and remove it if empty */ | 1038 | /* update bitmap and remove it if empty */ |