1 /*
2 Unix SMB/CIFS implementation.
3
4 very efficient functions to manage mapping a id (such as a fnum) to
5 a pointer. This is used for fnum and search id allocation.
6
7 Copyright (C) Andrew Tridgell 2004
8
9 This code is derived from lib/idr.c in the 2.6 Linux kernel, which was
10 written by Jim Houston jim.houston@ccur.com, and is
11 Copyright (C) 2002 by Concurrent Computer Corporation
12
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 */
27
28 /*
29 see the section marked "public interface" below for documentation
30 */
31
32 /**
33 * @file
34 */
35
36 #include "includes.h"
37
38 #define IDR_BITS 5
39 #define IDR_FULL 0xfffffffful
40 #if 0 /* unused */
41 #define TOP_LEVEL_FULL (IDR_FULL >> 30)
42 #endif
43 #define IDR_SIZE (1 << IDR_BITS)
44 #define IDR_MASK ((1 << IDR_BITS)-1)
45 #define MAX_ID_SHIFT (sizeof(int)*8 - 1)
46 #define MAX_ID_BIT (1U << MAX_ID_SHIFT)
47 #define MAX_ID_MASK (MAX_ID_BIT - 1)
48 #define MAX_LEVEL (MAX_ID_SHIFT + IDR_BITS - 1) / IDR_BITS
49 #define IDR_FREE_MAX MAX_LEVEL + MAX_LEVEL
50
51 #define set_bit(bit, v) (v) |= (1<<(bit))
52 #define clear_bit(bit, v) (v) &= ~(1<<(bit))
53 #define test_bit(bit, v) ((v) & (1<<(bit)))
54
55 struct idr_layer {
56 uint32_t bitmap;
57 struct idr_layer *ary[IDR_SIZE];
58 int count;
59 };
60
61 struct idr_context {
62 struct idr_layer *top;
63 struct idr_layer *id_free;
64 int layers;
65 int id_free_cnt;
66 };
67
alloc_layer(struct idr_context * idp)68 static struct idr_layer *alloc_layer(struct idr_context *idp)
69 {
70 struct idr_layer *p;
71
72 if (!(p = idp->id_free))
73 return NULL;
74 idp->id_free = p->ary[0];
75 idp->id_free_cnt--;
76 p->ary[0] = NULL;
77 return p;
78 }
79
find_next_bit(uint32_t bm,int maxid,int n)80 static int find_next_bit(uint32_t bm, int maxid, int n)
81 {
82 while (n<maxid && !test_bit(n, bm)) n++;
83 return n;
84 }
85
free_layer(struct idr_context * idp,struct idr_layer * p)86 static void free_layer(struct idr_context *idp, struct idr_layer *p)
87 {
88 p->ary[0] = idp->id_free;
89 idp->id_free = p;
90 idp->id_free_cnt++;
91 }
92
idr_pre_get(struct idr_context * idp)93 static int idr_pre_get(struct idr_context *idp)
94 {
95 while (idp->id_free_cnt < IDR_FREE_MAX) {
96 struct idr_layer *new = talloc_zero(idp, struct idr_layer);
97 if(new == NULL)
98 return (0);
99 free_layer(idp, new);
100 }
101 return 1;
102 }
103
sub_alloc(struct idr_context * idp,void * ptr,int * starting_id)104 static int sub_alloc(struct idr_context *idp, void *ptr, int *starting_id)
105 {
106 int n, m, sh;
107 struct idr_layer *p, *new;
108 struct idr_layer *pa[MAX_LEVEL];
109 int l, id;
110 uint32_t bm;
111
112 memset(pa, 0, sizeof(pa));
113
114 id = *starting_id;
115 p = idp->top;
116 l = idp->layers;
117 pa[l--] = NULL;
118 while (1) {
119 /*
120 * We run around this while until we reach the leaf node...
121 */
122 n = (id >> (IDR_BITS*l)) & IDR_MASK;
123 bm = ~p->bitmap;
124 m = find_next_bit(bm, IDR_SIZE, n);
125 if (m == IDR_SIZE) {
126 /* no space available go back to previous layer. */
127 l++;
128 id = (id | ((1 << (IDR_BITS*l))-1)) + 1;
129 if (!(p = pa[l])) {
130 *starting_id = id;
131 return -2;
132 }
133 continue;
134 }
135 if (m != n) {
136 sh = IDR_BITS*l;
137 id = ((id >> sh) ^ n ^ m) << sh;
138 }
139 if ((id >= MAX_ID_BIT) || (id < 0))
140 return -1;
141 if (l == 0)
142 break;
143 /*
144 * Create the layer below if it is missing.
145 */
146 if (!p->ary[m]) {
147 if (!(new = alloc_layer(idp)))
148 return -1;
149 p->ary[m] = new;
150 p->count++;
151 }
152 pa[l--] = p;
153 p = p->ary[m];
154 }
155 /*
156 * We have reached the leaf node, plant the
157 * users pointer and return the raw id.
158 */
159 p->ary[m] = (struct idr_layer *)ptr;
160 set_bit(m, p->bitmap);
161 p->count++;
162 /*
163 * If this layer is full mark the bit in the layer above
164 * to show that this part of the radix tree is full.
165 * This may complete the layer above and require walking
166 * up the radix tree.
167 */
168 n = id;
169 while (p->bitmap == IDR_FULL) {
170 if (!(p = pa[++l]))
171 break;
172 n = n >> IDR_BITS;
173 set_bit((n & IDR_MASK), p->bitmap);
174 }
175 return(id);
176 }
177
idr_get_new_above_int(struct idr_context * idp,void * ptr,int starting_id)178 static int idr_get_new_above_int(struct idr_context *idp, void *ptr, int starting_id)
179 {
180 struct idr_layer *p, *new;
181 int layers, v, id;
182
183 idr_pre_get(idp);
184
185 id = starting_id;
186 build_up:
187 p = idp->top;
188 layers = idp->layers;
189 if (!p) {
190 if (!(p = alloc_layer(idp)))
191 return -1;
192 layers = 1;
193 }
194 /*
195 * Add a new layer to the top of the tree if the requested
196 * id is larger than the currently allocated space.
197 */
198 while ((layers < MAX_LEVEL) && (id >= (1 << (layers*IDR_BITS)))) {
199 layers++;
200 if (!p->count)
201 continue;
202 if (!(new = alloc_layer(idp))) {
203 /*
204 * The allocation failed. If we built part of
205 * the structure tear it down.
206 */
207 for (new = p; p && p != idp->top; new = p) {
208 p = p->ary[0];
209 new->ary[0] = NULL;
210 new->bitmap = new->count = 0;
211 free_layer(idp, new);
212 }
213 return -1;
214 }
215 new->ary[0] = p;
216 new->count = 1;
217 if (p->bitmap == IDR_FULL)
218 set_bit(0, new->bitmap);
219 p = new;
220 }
221 idp->top = p;
222 idp->layers = layers;
223 v = sub_alloc(idp, ptr, &id);
224 if (v == -2)
225 goto build_up;
226 return(v);
227 }
228
sub_remove(struct idr_context * idp,int shift,int id)229 static int sub_remove(struct idr_context *idp, int shift, int id)
230 {
231 struct idr_layer *p = idp->top;
232 struct idr_layer **pa[MAX_LEVEL];
233 struct idr_layer ***paa = &pa[0];
234 int n;
235
236 *paa = NULL;
237 *++paa = &idp->top;
238
239 while ((shift > 0) && p) {
240 n = (id >> shift) & IDR_MASK;
241 clear_bit(n, p->bitmap);
242 *++paa = &p->ary[n];
243 p = p->ary[n];
244 shift -= IDR_BITS;
245 }
246 n = id & IDR_MASK;
247 if (p != NULL && test_bit(n, p->bitmap)) {
248 clear_bit(n, p->bitmap);
249 p->ary[n] = NULL;
250 while(*paa && ! --((**paa)->count)){
251 free_layer(idp, **paa);
252 **paa-- = NULL;
253 }
254 if ( ! *paa )
255 idp->layers = 0;
256 return 0;
257 }
258 return -1;
259 }
260
_idr_find(struct idr_context * idp,int id)261 static void *_idr_find(struct idr_context *idp, int id)
262 {
263 int n;
264 struct idr_layer *p;
265
266 n = idp->layers * IDR_BITS;
267 p = idp->top;
268 /*
269 * This tests to see if bits outside the current tree are
270 * present. If so, tain't one of ours!
271 */
272 if ((id & ~(~0 << MAX_ID_SHIFT)) >> (n + IDR_BITS))
273 return NULL;
274
275 /* Mask off upper bits we don't use for the search. */
276 id &= MAX_ID_MASK;
277
278 while (n >= IDR_BITS && p) {
279 n -= IDR_BITS;
280 p = p->ary[(id >> n) & IDR_MASK];
281 }
282 return((void *)p);
283 }
284
_idr_remove(struct idr_context * idp,int id)285 static int _idr_remove(struct idr_context *idp, int id)
286 {
287 struct idr_layer *p;
288
289 /* Mask off upper bits we don't use for the search. */
290 id &= MAX_ID_MASK;
291
292 if (sub_remove(idp, (idp->layers - 1) * IDR_BITS, id) == -1) {
293 return -1;
294 }
295
296 if ( idp->top && idp->top->count == 1 &&
297 (idp->layers > 1) &&
298 idp->top->ary[0]) {
299 /* We can drop a layer */
300 p = idp->top->ary[0];
301 idp->top->bitmap = idp->top->count = 0;
302 free_layer(idp, idp->top);
303 idp->top = p;
304 --idp->layers;
305 }
306 while (idp->id_free_cnt >= IDR_FREE_MAX) {
307 p = alloc_layer(idp);
308 talloc_free(p);
309 }
310 return 0;
311 }
312
313 /************************************************************************
314 this is the public interface
315 **************************************************************************/
316
317 /**
318 initialise a idr tree. The context return value must be passed to
319 all subsequent idr calls. To destroy the idr tree use talloc_free()
320 on this context
321 */
idr_init(TALLOC_CTX * mem_ctx)322 _PUBLIC_ struct idr_context *idr_init(TALLOC_CTX *mem_ctx)
323 {
324 return talloc_zero(mem_ctx, struct idr_context);
325 }
326
327 /**
328 allocate the next available id, and assign 'ptr' into its slot.
329 you can retrieve later this pointer using idr_find()
330 */
idr_get_new(struct idr_context * idp,void * ptr,int limit)331 _PUBLIC_ int idr_get_new(struct idr_context *idp, void *ptr, int limit)
332 {
333 int ret = idr_get_new_above_int(idp, ptr, 0);
334 if (ret > limit) {
335 idr_remove(idp, ret);
336 return -1;
337 }
338 return ret;
339 }
340
341 /**
342 allocate a new id, giving the first available value greater than or
343 equal to the given starting id
344 */
idr_get_new_above(struct idr_context * idp,void * ptr,int starting_id,int limit)345 _PUBLIC_ int idr_get_new_above(struct idr_context *idp, void *ptr, int starting_id, int limit)
346 {
347 int ret = idr_get_new_above_int(idp, ptr, starting_id);
348 if (ret > limit) {
349 idr_remove(idp, ret);
350 return -1;
351 }
352 return ret;
353 }
354
355 /**
356 allocate a new id randomly in the given range
357 */
idr_get_new_random(struct idr_context * idp,void * ptr,int limit)358 _PUBLIC_ int idr_get_new_random(struct idr_context *idp, void *ptr, int limit)
359 {
360 int id;
361
362 /* first try a random starting point in the whole range, and if that fails,
363 then start randomly in the bottom half of the range. This can only
364 fail if the range is over half full */
365 id = idr_get_new_above(idp, ptr, 1+(generate_random() % limit), limit);
366 if (id == -1) {
367 id = idr_get_new_above(idp, ptr, 1+(generate_random()%(limit/2)), limit);
368 }
369
370 return id;
371 }
372
373 /**
374 find a pointer value previously set with idr_get_new given an id
375 */
idr_find(struct idr_context * idp,int id)376 _PUBLIC_ void *idr_find(struct idr_context *idp, int id)
377 {
378 return _idr_find(idp, id);
379 }
380
381 /**
382 remove an id from the idr tree
383 */
idr_remove(struct idr_context * idp,int id)384 _PUBLIC_ int idr_remove(struct idr_context *idp, int id)
385 {
386 int ret;
387 ret = _idr_remove((struct idr_context *)idp, id);
388 if (ret != 0) {
389 DEBUG(0,("WARNING: attempt to remove unset id %d in idtree\n", id));
390 }
391 return ret;
392 }
393