1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#ifndef TEST
28#include <linux/slab.h>
29#include <linux/init.h>
30#include <linux/module.h>
31#endif
32#include <linux/err.h>
33#include <linux/string.h>
34#include <linux/idr.h>
35
36static kmem_cache_t *idr_layer_cache;
37
38static struct idr_layer *alloc_layer(struct idr *idp)
39{
40 struct idr_layer *p;
41
42 spin_lock(&idp->lock);
43 if (!(p = idp->id_free)) {
44 spin_unlock(&idp->lock);
45 return NULL;
46 }
47 idp->id_free = p->ary[0];
48 idp->id_free_cnt--;
49 p->ary[0] = NULL;
50 spin_unlock(&idp->lock);
51 return(p);
52}
53
54static void free_layer(struct idr *idp, struct idr_layer *p)
55{
56
57
58
59 spin_lock(&idp->lock);
60 p->ary[0] = idp->id_free;
61 idp->id_free = p;
62 idp->id_free_cnt++;
63 spin_unlock(&idp->lock);
64}
65
66
67
68
69
70
71
72
73
74
75
76
77
78int idr_pre_get(struct idr *idp, unsigned gfp_mask)
79{
80 while (idp->id_free_cnt < IDR_FREE_MAX) {
81 struct idr_layer *new;
82 new = kmem_cache_alloc(idr_layer_cache, gfp_mask);
83 if(new == NULL)
84 return (0);
85 free_layer(idp, new);
86 }
87 return 1;
88}
89EXPORT_SYMBOL(idr_pre_get);
90
91static int sub_alloc(struct idr *idp, void *ptr, int *starting_id)
92{
93 int n, m, sh;
94 struct idr_layer *p, *new;
95 struct idr_layer *pa[MAX_LEVEL];
96 int l, id;
97 long bm;
98
99 id = *starting_id;
100 p = idp->top;
101 l = idp->layers;
102 pa[l--] = NULL;
103 while (1) {
104
105
106
107 n = (id >> (IDR_BITS*l)) & IDR_MASK;
108 bm = ~p->bitmap;
109 m = find_next_bit(&bm, IDR_SIZE, n);
110 if (m == IDR_SIZE) {
111
112 l++;
113 id = (id | ((1 << (IDR_BITS*l))-1)) + 1;
114 if (!(p = pa[l])) {
115 *starting_id = id;
116 return -2;
117 }
118 continue;
119 }
120 if (m != n) {
121 sh = IDR_BITS*l;
122 id = ((id >> sh) ^ n ^ m) << sh;
123 }
124 if ((id >= MAX_ID_BIT) || (id < 0))
125 return -3;
126 if (l == 0)
127 break;
128
129
130
131 if (!p->ary[m]) {
132 if (!(new = alloc_layer(idp)))
133 return -1;
134 p->ary[m] = new;
135 p->count++;
136 }
137 pa[l--] = p;
138 p = p->ary[m];
139 }
140
141
142
143
144 p->ary[m] = (struct idr_layer *)ptr;
145 __set_bit(m, &p->bitmap);
146 p->count++;
147
148
149
150
151
152
153 n = id;
154 while (p->bitmap == IDR_FULL) {
155 if (!(p = pa[++l]))
156 break;
157 n = n >> IDR_BITS;
158 __set_bit((n & IDR_MASK), &p->bitmap);
159 }
160 return(id);
161}
162
163static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id)
164{
165 struct idr_layer *p, *new;
166 int layers, v, id;
167
168 id = starting_id;
169build_up:
170 p = idp->top;
171 layers = idp->layers;
172 if (unlikely(!p)) {
173 if (!(p = alloc_layer(idp)))
174 return -1;
175 layers = 1;
176 }
177
178
179
180
181 while ((layers < MAX_LEVEL) && (id >= (1 << (layers*IDR_BITS)))) {
182 layers++;
183 if (!p->count)
184 continue;
185 if (!(new = alloc_layer(idp))) {
186
187
188
189
190 for (new = p; p && p != idp->top; new = p) {
191 p = p->ary[0];
192 new->ary[0] = NULL;
193 new->bitmap = new->count = 0;
194 free_layer(idp, new);
195 }
196 return -1;
197 }
198 new->ary[0] = p;
199 new->count = 1;
200 if (p->bitmap == IDR_FULL)
201 __set_bit(0, &new->bitmap);
202 p = new;
203 }
204 idp->top = p;
205 idp->layers = layers;
206 v = sub_alloc(idp, ptr, &id);
207 if (v == -2)
208 goto build_up;
209 return(v);
210}
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id)
229{
230 int rv;
231 rv = idr_get_new_above_int(idp, ptr, starting_id);
232
233
234
235
236 if (rv < 0) {
237 if (rv == -1)
238 return -EAGAIN;
239 else
240 return -ENOSPC;
241 }
242 *id = rv;
243 return 0;
244}
245EXPORT_SYMBOL(idr_get_new_above);
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262int idr_get_new(struct idr *idp, void *ptr, int *id)
263{
264 int rv;
265 rv = idr_get_new_above_int(idp, ptr, 0);
266
267
268
269
270 if (rv < 0) {
271 if (rv == -1)
272 return -EAGAIN;
273 else
274 return -ENOSPC;
275 }
276 *id = rv;
277 return 0;
278}
279EXPORT_SYMBOL(idr_get_new);
280
281static void sub_remove(struct idr *idp, int shift, int id)
282{
283 struct idr_layer *p = idp->top;
284 struct idr_layer **pa[MAX_LEVEL];
285 struct idr_layer ***paa = &pa[0];
286
287 *paa = NULL;
288 *++paa = &idp->top;
289
290 while ((shift > 0) && p) {
291 int n = (id >> shift) & IDR_MASK;
292 __clear_bit(n, &p->bitmap);
293 *++paa = &p->ary[n];
294 p = p->ary[n];
295 shift -= IDR_BITS;
296 }
297 if (likely(p != NULL)){
298 int n = id & IDR_MASK;
299 __clear_bit(n, &p->bitmap);
300 p->ary[n] = NULL;
301 while(*paa && ! --((**paa)->count)){
302 free_layer(idp, **paa);
303 **paa-- = NULL;
304 }
305 if ( ! *paa )
306 idp->layers = 0;
307 }
308}
309
310
311
312
313
314
315void idr_remove(struct idr *idp, int id)
316{
317 struct idr_layer *p;
318
319
320 id &= MAX_ID_MASK;
321
322 sub_remove(idp, (idp->layers - 1) * IDR_BITS, id);
323 if ( idp->top && idp->top->count == 1 &&
324 (idp->layers > 1) &&
325 idp->top->ary[0]){
326
327 p = idp->top->ary[0];
328 idp->top->bitmap = idp->top->count = 0;
329 free_layer(idp, idp->top);
330 idp->top = p;
331 --idp->layers;
332 }
333 while (idp->id_free_cnt >= IDR_FREE_MAX) {
334
335 p = alloc_layer(idp);
336 kmem_cache_free(idr_layer_cache, p);
337 return;
338 }
339}
340EXPORT_SYMBOL(idr_remove);
341
342
343
344
345
346
347
348
349
350
351
352
353void *idr_find(struct idr *idp, int id)
354{
355 int n;
356 struct idr_layer *p;
357
358 n = idp->layers * IDR_BITS;
359 p = idp->top;
360
361
362 id &= MAX_ID_MASK;
363
364 if (id >= (1 << n))
365 return NULL;
366
367 while (n > 0 && p) {
368 n -= IDR_BITS;
369 p = p->ary[(id >> n) & IDR_MASK];
370 }
371 return((void *)p);
372}
373EXPORT_SYMBOL(idr_find);
374
375
376
377
378
379
380
381
382
383
384
385
386
387void *idr_replace(struct idr *idp, void *ptr, int id)
388{
389 int n;
390 struct idr_layer *p, *old_p;
391
392 n = idp->layers * IDR_BITS;
393 p = idp->top;
394
395 id &= MAX_ID_MASK;
396
397 if (id >= (1 << n))
398 return ERR_PTR(-EINVAL);
399
400 n -= IDR_BITS;
401 while ((n > 0) && p) {
402 p = p->ary[(id >> n) & IDR_MASK];
403 n -= IDR_BITS;
404 }
405
406 n = id & IDR_MASK;
407 if (unlikely(p == NULL || !test_bit(n, &p->bitmap)))
408 return ERR_PTR(-ENOENT);
409
410 old_p = p->ary[n];
411 p->ary[n] = ptr;
412
413 return (void *)old_p;
414}
415EXPORT_SYMBOL(idr_replace);
416
417static void idr_cache_ctor(void * idr_layer,
418 kmem_cache_t *idr_layer_cache, unsigned long flags)
419{
420 memset(idr_layer, 0, sizeof(struct idr_layer));
421}
422
423static int init_id_cache(void)
424{
425 if (!idr_layer_cache)
426 idr_layer_cache = kmem_cache_create("idr_layer_cache",
427 sizeof(struct idr_layer), 0, 0, idr_cache_ctor, NULL);
428 return 0;
429}
430
431
432
433
434
435
436
437
438void idr_init(struct idr *idp)
439{
440 init_id_cache();
441 memset(idp, 0, sizeof(struct idr));
442 spin_lock_init(&idp->lock);
443}
444EXPORT_SYMBOL(idr_init);
445