[PATCH] radix-tree reinitialisation fix
[linux-flexiantxendom0-3.2.10.git] / lib / radix-tree.c
1 /*
2  * Copyright (C) 2001 Momchil Velikov
3  * Portions Copyright (C) 2001 Christoph Hellwig
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2, or (at
8  * your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19
20 #include <linux/errno.h>
21 #include <linux/init.h>
22 #include <linux/kernel.h>
23 #include <linux/mempool.h>
24 #include <linux/module.h>
25 #include <linux/radix-tree.h>
26 #include <linux/slab.h>
27 #include <linux/string.h>
28
29 /*
30  * Radix tree node definition.
31  */
32 #define RADIX_TREE_MAP_SHIFT  6
33 #define RADIX_TREE_MAP_SIZE  (1UL << RADIX_TREE_MAP_SHIFT)
34 #define RADIX_TREE_MAP_MASK  (RADIX_TREE_MAP_SIZE-1)
35
36 struct radix_tree_node {
37         unsigned int    count;
38         void            *slots[RADIX_TREE_MAP_SIZE];
39 };
40
41 struct radix_tree_path {
42         struct radix_tree_node *node, **slot;
43 };
44
45 #define RADIX_TREE_INDEX_BITS  (8 /* CHAR_BIT */ * sizeof(unsigned long))
46 #define RADIX_TREE_MAX_PATH (RADIX_TREE_INDEX_BITS/RADIX_TREE_MAP_SHIFT + 2)
47
48 /*
49  * Radix tree node cache.
50  */
51 static kmem_cache_t *radix_tree_node_cachep;
52 static mempool_t *radix_tree_node_pool;
53
54 static inline struct radix_tree_node *
55 radix_tree_node_alloc(struct radix_tree_root *root)
56 {
57         return mempool_alloc(radix_tree_node_pool, root->gfp_mask);
58 }
59
60 static inline void
61 radix_tree_node_free(struct radix_tree_node *node)
62 {
63         mempool_free(node, radix_tree_node_pool);
64 }
65
66 /*
67  *      Return the maximum key which can be store into a
68  *      radix tree with height HEIGHT.
69  */
70 static inline unsigned long radix_tree_maxindex(unsigned int height)
71 {
72         unsigned int tmp = height * RADIX_TREE_MAP_SHIFT;
73         unsigned long index = (~0UL >> (RADIX_TREE_INDEX_BITS - tmp - 1)) >> 1;
74
75         if (tmp >= RADIX_TREE_INDEX_BITS)
76                 index = ~0UL;
77         return index;
78 }
79
80 /*
81  *      Extend a radix tree so it can store key @index.
82  */
83 static int radix_tree_extend(struct radix_tree_root *root, unsigned long index)
84 {
85         struct radix_tree_node *node;
86         unsigned int height;
87
88         /* Figure out what the height should be.  */
89         height = root->height + 1;
90         while (index > radix_tree_maxindex(height))
91                 height++;
92
93         if (root->rnode) {
94                 do {
95                         if (!(node = radix_tree_node_alloc(root)))
96                                 return -ENOMEM;
97
98                         /* Increase the height.  */
99                         node->slots[0] = root->rnode;
100                         if (root->rnode)
101                                 node->count = 1;
102                         root->rnode = node;
103                         root->height++;
104                 } while (height > root->height);
105         } else 
106                 root->height = height;
107
108         return 0;
109 }
110
111 /**
112  *      radix_tree_insert    -    insert into a radix tree
113  *      @root:          radix tree root
114  *      @index:         index key
115  *      @item:          item to insert
116  *
117  *      Insert an item into the radix tree at position @index.
118  */
119 int radix_tree_insert(struct radix_tree_root *root, unsigned long index, void *item)
120 {
121         struct radix_tree_node *node = NULL, *tmp, **slot;
122         unsigned int height, shift;
123         int error;
124
125         /* Make sure the tree is high enough.  */
126         if (index > radix_tree_maxindex(root->height)) {
127                 error = radix_tree_extend(root, index);
128                 if (error)
129                         return error;
130         }
131     
132         slot = &root->rnode;
133         height = root->height;
134         shift = (height-1) * RADIX_TREE_MAP_SHIFT;
135
136         while (height > 0) {
137                 if (*slot == NULL) {
138                         /* Have to add a child node.  */
139                         if (!(tmp = radix_tree_node_alloc(root)))
140                                 return -ENOMEM;
141                         *slot = tmp;
142                         if (node)
143                                 node->count++;
144                 }
145
146                 /* Go a level down.  */
147                 node = *slot;
148                 slot = (struct radix_tree_node **)
149                         (node->slots + ((index >> shift) & RADIX_TREE_MAP_MASK));
150                 shift -= RADIX_TREE_MAP_SHIFT;
151                 height--;
152         }
153
154         if (*slot != NULL)
155                 return -EEXIST;
156         if (node)
157                 node->count++;
158
159         *slot = item;
160         return 0;
161 }
162 EXPORT_SYMBOL(radix_tree_insert);
163
164 /**
165  *      radix_tree_lookup    -    perform lookup operation on a radix tree
166  *      @root:          radix tree root
167  *      @index:         index key
168  *
169  *      Lookup them item at the position @index in the radix tree @root.
170  */
171 void *radix_tree_lookup(struct radix_tree_root *root, unsigned long index)
172 {
173         unsigned int height, shift;
174         struct radix_tree_node **slot;
175
176         height = root->height;
177         if (index > radix_tree_maxindex(height))
178                 return NULL;
179
180         shift = (height-1) * RADIX_TREE_MAP_SHIFT;
181         slot = &root->rnode;
182
183         while (height > 0) {
184                 if (*slot == NULL)
185                         return NULL;
186
187                 slot = (struct radix_tree_node **)
188                         ((*slot)->slots + ((index >> shift) & RADIX_TREE_MAP_MASK));
189                 shift -= RADIX_TREE_MAP_SHIFT;
190                 height--;
191         }
192
193         return (void *) *slot;
194 }
195 EXPORT_SYMBOL(radix_tree_lookup);
196
197 static /* inline */ unsigned int
198 __lookup(struct radix_tree_root *root, void **results, unsigned long index,
199         unsigned int max_items, unsigned long *next_index,
200         unsigned long max_index)
201 {
202         unsigned int nr_found = 0;
203         unsigned int shift;
204         unsigned int height = root->height;
205         struct radix_tree_node *slot;
206
207         shift = (height-1) * RADIX_TREE_MAP_SHIFT;
208         slot = root->rnode;
209
210         while (height > 0) {
211                 unsigned long i = (index >> shift) & RADIX_TREE_MAP_MASK;
212                 for ( ; i < RADIX_TREE_MAP_SIZE; i++) {
213                         if (slot->slots[i] != NULL)
214                                 break;
215                         index &= ~((1 << shift) - 1);
216                         index += 1 << shift;
217                 }
218                 if (i == RADIX_TREE_MAP_SIZE)
219                         goto out;
220                 height--;
221                 shift -= RADIX_TREE_MAP_SHIFT;
222                 if (height == 0) {
223                         /* Bottom level: grab some items */
224                         unsigned long j;
225
226                         BUG_ON((shift + RADIX_TREE_MAP_SHIFT) != 0);
227                         
228                         j = index & RADIX_TREE_MAP_MASK;
229                         for ( ; j < RADIX_TREE_MAP_SIZE; j++) {
230                                 index++;
231                                 if (slot->slots[j]) {
232                                         results[nr_found++] = slot->slots[j];
233                                         if (nr_found == max_items)
234                                                 goto out;
235                                 }
236                         }
237                 }
238                 slot = slot->slots[i];
239         }
240 out:
241         *next_index = index;
242         return nr_found;
243 }
244
245 /**
246  *      radix_tree_gang_lookup - perform multiple lookup on a radix tree
247  *      @root:          radix tree root
248  *      @results:       where the results of the lookup are placed
249  *      @first_index:   start the lookup from this key
250  *      @max_items:     place up to this many items at *results
251  *
252  *      Performs an index-ascending scan of the tree for present items.  Places
253  *      them at *@results and returns the number of items which were placed at
254  *      *@results.
255  *
256  *      The implementation is naive.
257  */
258 unsigned int
259 radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
260                         unsigned long first_index, unsigned int max_items)
261 {
262         const unsigned long max_index = radix_tree_maxindex(root->height);
263         unsigned long cur_index = first_index;
264         unsigned int ret = 0;
265
266         if (root->rnode == NULL)
267                 goto out;
268         if (max_index == 0) {                   /* Bah.  Special case */
269                 if (first_index == 0) {
270                         if (max_items > 0) {
271                                 *results = root->rnode;
272                                 ret = 1;
273                         }
274                 }
275                 goto out;
276         }
277         while (ret < max_items) {
278                 unsigned int nr_found;
279                 unsigned long next_index;       /* Index of next search */
280
281                 if (cur_index > max_index)
282                         break;
283                 nr_found = __lookup(root, results + ret, cur_index,
284                                 max_items - ret, &next_index, max_index);
285                 ret += nr_found;
286                 if (next_index == max_index)
287                         break;
288                 cur_index = next_index;
289         }
290 out:
291         return ret;
292 }
293 EXPORT_SYMBOL(radix_tree_gang_lookup);
294
295 /**
296  *      radix_tree_delete    -    delete an item from a radix tree
297  *      @root:          radix tree root
298  *      @index:         index key
299  *
300  *      Remove the item at @index from the radix tree rooted at @root.
301  */
302 int radix_tree_delete(struct radix_tree_root *root, unsigned long index)
303 {
304         struct radix_tree_path path[RADIX_TREE_MAX_PATH], *pathp = path;
305         unsigned int height, shift;
306
307         height = root->height;
308         if (index > radix_tree_maxindex(height))
309                 return -ENOENT;
310
311         shift = (height-1) * RADIX_TREE_MAP_SHIFT;
312         pathp->node = NULL;
313         pathp->slot = &root->rnode;
314
315         while (height > 0) {
316                 if (*pathp->slot == NULL)
317                         return -ENOENT;
318
319                 pathp[1].node = *pathp[0].slot;
320                 pathp[1].slot = (struct radix_tree_node **)
321                     (pathp[1].node->slots + ((index >> shift) & RADIX_TREE_MAP_MASK));
322                 pathp++;
323                 shift -= RADIX_TREE_MAP_SHIFT;
324                 height--;
325         }
326
327         if (*pathp[0].slot == NULL)
328                 return -ENOENT;
329
330         *pathp[0].slot = NULL;
331         while (pathp[0].node && --pathp[0].node->count == 0) {
332                 pathp--;
333                 *pathp[0].slot = NULL;
334                 radix_tree_node_free(pathp[1].node);
335         }
336
337         if (root->rnode == NULL)
338                 root->height = 0;  /* Empty tree, we can reset the height */
339
340         return 0;
341 }
342 EXPORT_SYMBOL(radix_tree_delete);
343
344 static void radix_tree_node_ctor(void *node, kmem_cache_t *cachep, unsigned long flags)
345 {
346         memset(node, 0, sizeof(struct radix_tree_node));
347 }
348
349 static void *radix_tree_node_pool_alloc(int gfp_mask, void *data)
350 {
351         return kmem_cache_alloc(radix_tree_node_cachep, gfp_mask);
352 }
353
354 static void radix_tree_node_pool_free(void *node, void *data)
355 {
356         kmem_cache_free(radix_tree_node_cachep, node);
357 }
358
359 /*
360  * FIXME!  512 nodes is 200-300k of memory.  This needs to be
361  * scaled by the amount of available memory, and hopefully
362  * reduced also.
363  */
364 void __init radix_tree_init(void)
365 {
366         radix_tree_node_cachep = kmem_cache_create("radix_tree_node",
367                         sizeof(struct radix_tree_node), 0,
368                         SLAB_HWCACHE_ALIGN, radix_tree_node_ctor, NULL);
369         if (!radix_tree_node_cachep)
370                 panic ("Failed to create radix_tree_node cache\n");
371         radix_tree_node_pool = mempool_create(512, radix_tree_node_pool_alloc,
372                         radix_tree_node_pool_free, NULL);
373         if (!radix_tree_node_pool)
374                 panic ("Failed to create radix_tree_node pool\n");
375 }