diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/idr.c | 71 |
1 files changed, 46 insertions, 25 deletions
@@ -70,6 +70,26 @@ static void free_layer(struct idr *idp, struct idr_layer *p) | |||
70 | spin_unlock_irqrestore(&idp->lock, flags); | 70 | spin_unlock_irqrestore(&idp->lock, flags); |
71 | } | 71 | } |
72 | 72 | ||
73 | static void idr_mark_full(struct idr_layer **pa, int id) | ||
74 | { | ||
75 | struct idr_layer *p = pa[0]; | ||
76 | int l = 0; | ||
77 | |||
78 | __set_bit(id & IDR_MASK, &p->bitmap); | ||
79 | /* | ||
80 | * If this layer is full mark the bit in the layer above to | ||
81 | * show that this part of the radix tree is full. This may | ||
82 | * complete the layer above and require walking up the radix | ||
83 | * tree. | ||
84 | */ | ||
85 | while (p->bitmap == IDR_FULL) { | ||
86 | if (!(p = pa[++l])) | ||
87 | break; | ||
88 | id = id >> IDR_BITS; | ||
89 | __set_bit((id & IDR_MASK), &p->bitmap); | ||
90 | } | ||
91 | } | ||
92 | |||
73 | /** | 93 | /** |
74 | * idr_pre_get - reserver resources for idr allocation | 94 | * idr_pre_get - reserver resources for idr allocation |
75 | * @idp: idr handle | 95 | * @idp: idr handle |
@@ -95,11 +115,10 @@ int idr_pre_get(struct idr *idp, gfp_t gfp_mask) | |||
95 | } | 115 | } |
96 | EXPORT_SYMBOL(idr_pre_get); | 116 | EXPORT_SYMBOL(idr_pre_get); |
97 | 117 | ||
98 | static int sub_alloc(struct idr *idp, void *ptr, int *starting_id) | 118 | static int sub_alloc(struct idr *idp, int *starting_id, struct idr_layer **pa) |
99 | { | 119 | { |
100 | int n, m, sh; | 120 | int n, m, sh; |
101 | struct idr_layer *p, *new; | 121 | struct idr_layer *p, *new; |
102 | struct idr_layer *pa[MAX_LEVEL]; | ||
103 | int l, id, oid; | 122 | int l, id, oid; |
104 | long bm; | 123 | long bm; |
105 | 124 | ||
@@ -156,30 +175,13 @@ static int sub_alloc(struct idr *idp, void *ptr, int *starting_id) | |||
156 | pa[l--] = p; | 175 | pa[l--] = p; |
157 | p = p->ary[m]; | 176 | p = p->ary[m]; |
158 | } | 177 | } |
159 | /* | 178 | |
160 | * We have reached the leaf node, plant the | 179 | pa[l] = p; |
161 | * users pointer and return the raw id. | 180 | return id; |
162 | */ | ||
163 | p->ary[m] = (struct idr_layer *)ptr; | ||
164 | __set_bit(m, &p->bitmap); | ||
165 | p->count++; | ||
166 | /* | ||
167 | * If this layer is full mark the bit in the layer above | ||
168 | * to show that this part of the radix tree is full. | ||
169 | * This may complete the layer above and require walking | ||
170 | * up the radix tree. | ||
171 | */ | ||
172 | n = id; | ||
173 | while (p->bitmap == IDR_FULL) { | ||
174 | if (!(p = pa[++l])) | ||
175 | break; | ||
176 | n = n >> IDR_BITS; | ||
177 | __set_bit((n & IDR_MASK), &p->bitmap); | ||
178 | } | ||
179 | return(id); | ||
180 | } | 181 | } |
181 | 182 | ||
182 | static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id) | 183 | static int idr_get_empty_slot(struct idr *idp, int starting_id, |
184 | struct idr_layer **pa) | ||
183 | { | 185 | { |
184 | struct idr_layer *p, *new; | 186 | struct idr_layer *p, *new; |
185 | int layers, v, id; | 187 | int layers, v, id; |
@@ -225,12 +227,31 @@ build_up: | |||
225 | } | 227 | } |
226 | idp->top = p; | 228 | idp->top = p; |
227 | idp->layers = layers; | 229 | idp->layers = layers; |
228 | v = sub_alloc(idp, ptr, &id); | 230 | v = sub_alloc(idp, &id, pa); |
229 | if (v == -2) | 231 | if (v == -2) |
230 | goto build_up; | 232 | goto build_up; |
231 | return(v); | 233 | return(v); |
232 | } | 234 | } |
233 | 235 | ||
236 | static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id) | ||
237 | { | ||
238 | struct idr_layer *pa[MAX_LEVEL]; | ||
239 | int id; | ||
240 | |||
241 | id = idr_get_empty_slot(idp, starting_id, pa); | ||
242 | if (id >= 0) { | ||
243 | /* | ||
244 | * Successfully found an empty slot. Install the user | ||
245 | * pointer and mark the slot full. | ||
246 | */ | ||
247 | pa[0]->ary[id & IDR_MASK] = (struct idr_layer *)ptr; | ||
248 | pa[0]->count++; | ||
249 | idr_mark_full(pa, id); | ||
250 | } | ||
251 | |||
252 | return id; | ||
253 | } | ||
254 | |||
234 | /** | 255 | /** |
235 | * idr_get_new_above - allocate new idr entry above or equal to a start id | 256 | * idr_get_new_above - allocate new idr entry above or equal to a start id |
236 | * @idp: idr handle | 257 | * @idp: idr handle |