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