1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * lib/btree.c - Simple In-memory B+Tree
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (c) 2007-2008 Joern Engel <joern@purestorage.com>
6*4882a593Smuzhiyun * Bits and pieces stolen from Peter Zijlstra's code, which is
7*4882a593Smuzhiyun * Copyright 2007, Red Hat Inc. Peter Zijlstra
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * see http://programming.kicks-ass.net/kernel-patches/vma_lookup/btree.patch
10*4882a593Smuzhiyun *
11*4882a593Smuzhiyun * A relatively simple B+Tree implementation. I have written it as a learning
12*4882a593Smuzhiyun * exercise to understand how B+Trees work. Turned out to be useful as well.
13*4882a593Smuzhiyun *
14*4882a593Smuzhiyun * B+Trees can be used similar to Linux radix trees (which don't have anything
15*4882a593Smuzhiyun * in common with textbook radix trees, beware). Prerequisite for them working
16*4882a593Smuzhiyun * well is that access to a random tree node is much faster than a large number
17*4882a593Smuzhiyun * of operations within each node.
18*4882a593Smuzhiyun *
19*4882a593Smuzhiyun * Disks have fulfilled the prerequisite for a long time. More recently DRAM
20*4882a593Smuzhiyun * has gained similar properties, as memory access times, when measured in cpu
21*4882a593Smuzhiyun * cycles, have increased. Cacheline sizes have increased as well, which also
22*4882a593Smuzhiyun * helps B+Trees.
23*4882a593Smuzhiyun *
24*4882a593Smuzhiyun * Compared to radix trees, B+Trees are more efficient when dealing with a
25*4882a593Smuzhiyun * sparsely populated address space. Between 25% and 50% of the memory is
26*4882a593Smuzhiyun * occupied with valid pointers. When densely populated, radix trees contain
27*4882a593Smuzhiyun * ~98% pointers - hard to beat. Very sparse radix trees contain only ~2%
28*4882a593Smuzhiyun * pointers.
29*4882a593Smuzhiyun *
30*4882a593Smuzhiyun * This particular implementation stores pointers identified by a long value.
31*4882a593Smuzhiyun * Storing NULL pointers is illegal, lookup will return NULL when no entry
32*4882a593Smuzhiyun * was found.
33*4882a593Smuzhiyun *
34*4882a593Smuzhiyun * A tricks was used that is not commonly found in textbooks. The lowest
35*4882a593Smuzhiyun * values are to the right, not to the left. All used slots within a node
36*4882a593Smuzhiyun * are on the left, all unused slots contain NUL values. Most operations
37*4882a593Smuzhiyun * simply loop once over all slots and terminate on the first NUL.
38*4882a593Smuzhiyun */
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun #include <linux/btree.h>
41*4882a593Smuzhiyun #include <linux/cache.h>
42*4882a593Smuzhiyun #include <linux/kernel.h>
43*4882a593Smuzhiyun #include <linux/slab.h>
44*4882a593Smuzhiyun #include <linux/module.h>
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun #define MAX(a, b) ((a) > (b) ? (a) : (b))
47*4882a593Smuzhiyun #define NODESIZE MAX(L1_CACHE_BYTES, 128)
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun struct btree_geo {
50*4882a593Smuzhiyun int keylen;
51*4882a593Smuzhiyun int no_pairs;
52*4882a593Smuzhiyun int no_longs;
53*4882a593Smuzhiyun };
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun struct btree_geo btree_geo32 = {
56*4882a593Smuzhiyun .keylen = 1,
57*4882a593Smuzhiyun .no_pairs = NODESIZE / sizeof(long) / 2,
58*4882a593Smuzhiyun .no_longs = NODESIZE / sizeof(long) / 2,
59*4882a593Smuzhiyun };
60*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(btree_geo32);
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun #define LONG_PER_U64 (64 / BITS_PER_LONG)
63*4882a593Smuzhiyun struct btree_geo btree_geo64 = {
64*4882a593Smuzhiyun .keylen = LONG_PER_U64,
65*4882a593Smuzhiyun .no_pairs = NODESIZE / sizeof(long) / (1 + LONG_PER_U64),
66*4882a593Smuzhiyun .no_longs = LONG_PER_U64 * (NODESIZE / sizeof(long) / (1 + LONG_PER_U64)),
67*4882a593Smuzhiyun };
68*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(btree_geo64);
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun struct btree_geo btree_geo128 = {
71*4882a593Smuzhiyun .keylen = 2 * LONG_PER_U64,
72*4882a593Smuzhiyun .no_pairs = NODESIZE / sizeof(long) / (1 + 2 * LONG_PER_U64),
73*4882a593Smuzhiyun .no_longs = 2 * LONG_PER_U64 * (NODESIZE / sizeof(long) / (1 + 2 * LONG_PER_U64)),
74*4882a593Smuzhiyun };
75*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(btree_geo128);
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun #define MAX_KEYLEN (2 * LONG_PER_U64)
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun static struct kmem_cache *btree_cachep;
80*4882a593Smuzhiyun
btree_alloc(gfp_t gfp_mask,void * pool_data)81*4882a593Smuzhiyun void *btree_alloc(gfp_t gfp_mask, void *pool_data)
82*4882a593Smuzhiyun {
83*4882a593Smuzhiyun return kmem_cache_alloc(btree_cachep, gfp_mask);
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(btree_alloc);
86*4882a593Smuzhiyun
btree_free(void * element,void * pool_data)87*4882a593Smuzhiyun void btree_free(void *element, void *pool_data)
88*4882a593Smuzhiyun {
89*4882a593Smuzhiyun kmem_cache_free(btree_cachep, element);
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(btree_free);
92*4882a593Smuzhiyun
btree_node_alloc(struct btree_head * head,gfp_t gfp)93*4882a593Smuzhiyun static unsigned long *btree_node_alloc(struct btree_head *head, gfp_t gfp)
94*4882a593Smuzhiyun {
95*4882a593Smuzhiyun unsigned long *node;
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun node = mempool_alloc(head->mempool, gfp);
98*4882a593Smuzhiyun if (likely(node))
99*4882a593Smuzhiyun memset(node, 0, NODESIZE);
100*4882a593Smuzhiyun return node;
101*4882a593Smuzhiyun }
102*4882a593Smuzhiyun
longcmp(const unsigned long * l1,const unsigned long * l2,size_t n)103*4882a593Smuzhiyun static int longcmp(const unsigned long *l1, const unsigned long *l2, size_t n)
104*4882a593Smuzhiyun {
105*4882a593Smuzhiyun size_t i;
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun for (i = 0; i < n; i++) {
108*4882a593Smuzhiyun if (l1[i] < l2[i])
109*4882a593Smuzhiyun return -1;
110*4882a593Smuzhiyun if (l1[i] > l2[i])
111*4882a593Smuzhiyun return 1;
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun return 0;
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun
longcpy(unsigned long * dest,const unsigned long * src,size_t n)116*4882a593Smuzhiyun static unsigned long *longcpy(unsigned long *dest, const unsigned long *src,
117*4882a593Smuzhiyun size_t n)
118*4882a593Smuzhiyun {
119*4882a593Smuzhiyun size_t i;
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun for (i = 0; i < n; i++)
122*4882a593Smuzhiyun dest[i] = src[i];
123*4882a593Smuzhiyun return dest;
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun
longset(unsigned long * s,unsigned long c,size_t n)126*4882a593Smuzhiyun static unsigned long *longset(unsigned long *s, unsigned long c, size_t n)
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun size_t i;
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun for (i = 0; i < n; i++)
131*4882a593Smuzhiyun s[i] = c;
132*4882a593Smuzhiyun return s;
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun
dec_key(struct btree_geo * geo,unsigned long * key)135*4882a593Smuzhiyun static void dec_key(struct btree_geo *geo, unsigned long *key)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun unsigned long val;
138*4882a593Smuzhiyun int i;
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun for (i = geo->keylen - 1; i >= 0; i--) {
141*4882a593Smuzhiyun val = key[i];
142*4882a593Smuzhiyun key[i] = val - 1;
143*4882a593Smuzhiyun if (val)
144*4882a593Smuzhiyun break;
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun
bkey(struct btree_geo * geo,unsigned long * node,int n)148*4882a593Smuzhiyun static unsigned long *bkey(struct btree_geo *geo, unsigned long *node, int n)
149*4882a593Smuzhiyun {
150*4882a593Smuzhiyun return &node[n * geo->keylen];
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun
bval(struct btree_geo * geo,unsigned long * node,int n)153*4882a593Smuzhiyun static void *bval(struct btree_geo *geo, unsigned long *node, int n)
154*4882a593Smuzhiyun {
155*4882a593Smuzhiyun return (void *)node[geo->no_longs + n];
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
setkey(struct btree_geo * geo,unsigned long * node,int n,unsigned long * key)158*4882a593Smuzhiyun static void setkey(struct btree_geo *geo, unsigned long *node, int n,
159*4882a593Smuzhiyun unsigned long *key)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun longcpy(bkey(geo, node, n), key, geo->keylen);
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun
setval(struct btree_geo * geo,unsigned long * node,int n,void * val)164*4882a593Smuzhiyun static void setval(struct btree_geo *geo, unsigned long *node, int n,
165*4882a593Smuzhiyun void *val)
166*4882a593Smuzhiyun {
167*4882a593Smuzhiyun node[geo->no_longs + n] = (unsigned long) val;
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun
clearpair(struct btree_geo * geo,unsigned long * node,int n)170*4882a593Smuzhiyun static void clearpair(struct btree_geo *geo, unsigned long *node, int n)
171*4882a593Smuzhiyun {
172*4882a593Smuzhiyun longset(bkey(geo, node, n), 0, geo->keylen);
173*4882a593Smuzhiyun node[geo->no_longs + n] = 0;
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun
__btree_init(struct btree_head * head)176*4882a593Smuzhiyun static inline void __btree_init(struct btree_head *head)
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun head->node = NULL;
179*4882a593Smuzhiyun head->height = 0;
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun
btree_init_mempool(struct btree_head * head,mempool_t * mempool)182*4882a593Smuzhiyun void btree_init_mempool(struct btree_head *head, mempool_t *mempool)
183*4882a593Smuzhiyun {
184*4882a593Smuzhiyun __btree_init(head);
185*4882a593Smuzhiyun head->mempool = mempool;
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(btree_init_mempool);
188*4882a593Smuzhiyun
btree_init(struct btree_head * head)189*4882a593Smuzhiyun int btree_init(struct btree_head *head)
190*4882a593Smuzhiyun {
191*4882a593Smuzhiyun __btree_init(head);
192*4882a593Smuzhiyun head->mempool = mempool_create(0, btree_alloc, btree_free, NULL);
193*4882a593Smuzhiyun if (!head->mempool)
194*4882a593Smuzhiyun return -ENOMEM;
195*4882a593Smuzhiyun return 0;
196*4882a593Smuzhiyun }
197*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(btree_init);
198*4882a593Smuzhiyun
btree_destroy(struct btree_head * head)199*4882a593Smuzhiyun void btree_destroy(struct btree_head *head)
200*4882a593Smuzhiyun {
201*4882a593Smuzhiyun mempool_free(head->node, head->mempool);
202*4882a593Smuzhiyun mempool_destroy(head->mempool);
203*4882a593Smuzhiyun head->mempool = NULL;
204*4882a593Smuzhiyun }
205*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(btree_destroy);
206*4882a593Smuzhiyun
btree_last(struct btree_head * head,struct btree_geo * geo,unsigned long * key)207*4882a593Smuzhiyun void *btree_last(struct btree_head *head, struct btree_geo *geo,
208*4882a593Smuzhiyun unsigned long *key)
209*4882a593Smuzhiyun {
210*4882a593Smuzhiyun int height = head->height;
211*4882a593Smuzhiyun unsigned long *node = head->node;
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun if (height == 0)
214*4882a593Smuzhiyun return NULL;
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun for ( ; height > 1; height--)
217*4882a593Smuzhiyun node = bval(geo, node, 0);
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun longcpy(key, bkey(geo, node, 0), geo->keylen);
220*4882a593Smuzhiyun return bval(geo, node, 0);
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(btree_last);
223*4882a593Smuzhiyun
keycmp(struct btree_geo * geo,unsigned long * node,int pos,unsigned long * key)224*4882a593Smuzhiyun static int keycmp(struct btree_geo *geo, unsigned long *node, int pos,
225*4882a593Smuzhiyun unsigned long *key)
226*4882a593Smuzhiyun {
227*4882a593Smuzhiyun return longcmp(bkey(geo, node, pos), key, geo->keylen);
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun
keyzero(struct btree_geo * geo,unsigned long * key)230*4882a593Smuzhiyun static int keyzero(struct btree_geo *geo, unsigned long *key)
231*4882a593Smuzhiyun {
232*4882a593Smuzhiyun int i;
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun for (i = 0; i < geo->keylen; i++)
235*4882a593Smuzhiyun if (key[i])
236*4882a593Smuzhiyun return 0;
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun return 1;
239*4882a593Smuzhiyun }
240*4882a593Smuzhiyun
btree_lookup(struct btree_head * head,struct btree_geo * geo,unsigned long * key)241*4882a593Smuzhiyun void *btree_lookup(struct btree_head *head, struct btree_geo *geo,
242*4882a593Smuzhiyun unsigned long *key)
243*4882a593Smuzhiyun {
244*4882a593Smuzhiyun int i, height = head->height;
245*4882a593Smuzhiyun unsigned long *node = head->node;
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun if (height == 0)
248*4882a593Smuzhiyun return NULL;
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun for ( ; height > 1; height--) {
251*4882a593Smuzhiyun for (i = 0; i < geo->no_pairs; i++)
252*4882a593Smuzhiyun if (keycmp(geo, node, i, key) <= 0)
253*4882a593Smuzhiyun break;
254*4882a593Smuzhiyun if (i == geo->no_pairs)
255*4882a593Smuzhiyun return NULL;
256*4882a593Smuzhiyun node = bval(geo, node, i);
257*4882a593Smuzhiyun if (!node)
258*4882a593Smuzhiyun return NULL;
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun if (!node)
262*4882a593Smuzhiyun return NULL;
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun for (i = 0; i < geo->no_pairs; i++)
265*4882a593Smuzhiyun if (keycmp(geo, node, i, key) == 0)
266*4882a593Smuzhiyun return bval(geo, node, i);
267*4882a593Smuzhiyun return NULL;
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(btree_lookup);
270*4882a593Smuzhiyun
btree_update(struct btree_head * head,struct btree_geo * geo,unsigned long * key,void * val)271*4882a593Smuzhiyun int btree_update(struct btree_head *head, struct btree_geo *geo,
272*4882a593Smuzhiyun unsigned long *key, void *val)
273*4882a593Smuzhiyun {
274*4882a593Smuzhiyun int i, height = head->height;
275*4882a593Smuzhiyun unsigned long *node = head->node;
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun if (height == 0)
278*4882a593Smuzhiyun return -ENOENT;
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun for ( ; height > 1; height--) {
281*4882a593Smuzhiyun for (i = 0; i < geo->no_pairs; i++)
282*4882a593Smuzhiyun if (keycmp(geo, node, i, key) <= 0)
283*4882a593Smuzhiyun break;
284*4882a593Smuzhiyun if (i == geo->no_pairs)
285*4882a593Smuzhiyun return -ENOENT;
286*4882a593Smuzhiyun node = bval(geo, node, i);
287*4882a593Smuzhiyun if (!node)
288*4882a593Smuzhiyun return -ENOENT;
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun if (!node)
292*4882a593Smuzhiyun return -ENOENT;
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun for (i = 0; i < geo->no_pairs; i++)
295*4882a593Smuzhiyun if (keycmp(geo, node, i, key) == 0) {
296*4882a593Smuzhiyun setval(geo, node, i, val);
297*4882a593Smuzhiyun return 0;
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun return -ENOENT;
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(btree_update);
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun /*
304*4882a593Smuzhiyun * Usually this function is quite similar to normal lookup. But the key of
305*4882a593Smuzhiyun * a parent node may be smaller than the smallest key of all its siblings.
306*4882a593Smuzhiyun * In such a case we cannot just return NULL, as we have only proven that no
307*4882a593Smuzhiyun * key smaller than __key, but larger than this parent key exists.
308*4882a593Smuzhiyun * So we set __key to the parent key and retry. We have to use the smallest
309*4882a593Smuzhiyun * such parent key, which is the last parent key we encountered.
310*4882a593Smuzhiyun */
btree_get_prev(struct btree_head * head,struct btree_geo * geo,unsigned long * __key)311*4882a593Smuzhiyun void *btree_get_prev(struct btree_head *head, struct btree_geo *geo,
312*4882a593Smuzhiyun unsigned long *__key)
313*4882a593Smuzhiyun {
314*4882a593Smuzhiyun int i, height;
315*4882a593Smuzhiyun unsigned long *node, *oldnode;
316*4882a593Smuzhiyun unsigned long *retry_key = NULL, key[MAX_KEYLEN];
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun if (keyzero(geo, __key))
319*4882a593Smuzhiyun return NULL;
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun if (head->height == 0)
322*4882a593Smuzhiyun return NULL;
323*4882a593Smuzhiyun longcpy(key, __key, geo->keylen);
324*4882a593Smuzhiyun retry:
325*4882a593Smuzhiyun dec_key(geo, key);
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun node = head->node;
328*4882a593Smuzhiyun for (height = head->height ; height > 1; height--) {
329*4882a593Smuzhiyun for (i = 0; i < geo->no_pairs; i++)
330*4882a593Smuzhiyun if (keycmp(geo, node, i, key) <= 0)
331*4882a593Smuzhiyun break;
332*4882a593Smuzhiyun if (i == geo->no_pairs)
333*4882a593Smuzhiyun goto miss;
334*4882a593Smuzhiyun oldnode = node;
335*4882a593Smuzhiyun node = bval(geo, node, i);
336*4882a593Smuzhiyun if (!node)
337*4882a593Smuzhiyun goto miss;
338*4882a593Smuzhiyun retry_key = bkey(geo, oldnode, i);
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun if (!node)
342*4882a593Smuzhiyun goto miss;
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun for (i = 0; i < geo->no_pairs; i++) {
345*4882a593Smuzhiyun if (keycmp(geo, node, i, key) <= 0) {
346*4882a593Smuzhiyun if (bval(geo, node, i)) {
347*4882a593Smuzhiyun longcpy(__key, bkey(geo, node, i), geo->keylen);
348*4882a593Smuzhiyun return bval(geo, node, i);
349*4882a593Smuzhiyun } else
350*4882a593Smuzhiyun goto miss;
351*4882a593Smuzhiyun }
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun miss:
354*4882a593Smuzhiyun if (retry_key) {
355*4882a593Smuzhiyun longcpy(key, retry_key, geo->keylen);
356*4882a593Smuzhiyun retry_key = NULL;
357*4882a593Smuzhiyun goto retry;
358*4882a593Smuzhiyun }
359*4882a593Smuzhiyun return NULL;
360*4882a593Smuzhiyun }
361*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(btree_get_prev);
362*4882a593Smuzhiyun
getpos(struct btree_geo * geo,unsigned long * node,unsigned long * key)363*4882a593Smuzhiyun static int getpos(struct btree_geo *geo, unsigned long *node,
364*4882a593Smuzhiyun unsigned long *key)
365*4882a593Smuzhiyun {
366*4882a593Smuzhiyun int i;
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun for (i = 0; i < geo->no_pairs; i++) {
369*4882a593Smuzhiyun if (keycmp(geo, node, i, key) <= 0)
370*4882a593Smuzhiyun break;
371*4882a593Smuzhiyun }
372*4882a593Smuzhiyun return i;
373*4882a593Smuzhiyun }
374*4882a593Smuzhiyun
getfill(struct btree_geo * geo,unsigned long * node,int start)375*4882a593Smuzhiyun static int getfill(struct btree_geo *geo, unsigned long *node, int start)
376*4882a593Smuzhiyun {
377*4882a593Smuzhiyun int i;
378*4882a593Smuzhiyun
379*4882a593Smuzhiyun for (i = start; i < geo->no_pairs; i++)
380*4882a593Smuzhiyun if (!bval(geo, node, i))
381*4882a593Smuzhiyun break;
382*4882a593Smuzhiyun return i;
383*4882a593Smuzhiyun }
384*4882a593Smuzhiyun
385*4882a593Smuzhiyun /*
386*4882a593Smuzhiyun * locate the correct leaf node in the btree
387*4882a593Smuzhiyun */
find_level(struct btree_head * head,struct btree_geo * geo,unsigned long * key,int level)388*4882a593Smuzhiyun static unsigned long *find_level(struct btree_head *head, struct btree_geo *geo,
389*4882a593Smuzhiyun unsigned long *key, int level)
390*4882a593Smuzhiyun {
391*4882a593Smuzhiyun unsigned long *node = head->node;
392*4882a593Smuzhiyun int i, height;
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun for (height = head->height; height > level; height--) {
395*4882a593Smuzhiyun for (i = 0; i < geo->no_pairs; i++)
396*4882a593Smuzhiyun if (keycmp(geo, node, i, key) <= 0)
397*4882a593Smuzhiyun break;
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun if ((i == geo->no_pairs) || !bval(geo, node, i)) {
400*4882a593Smuzhiyun /* right-most key is too large, update it */
401*4882a593Smuzhiyun /* FIXME: If the right-most key on higher levels is
402*4882a593Smuzhiyun * always zero, this wouldn't be necessary. */
403*4882a593Smuzhiyun i--;
404*4882a593Smuzhiyun setkey(geo, node, i, key);
405*4882a593Smuzhiyun }
406*4882a593Smuzhiyun BUG_ON(i < 0);
407*4882a593Smuzhiyun node = bval(geo, node, i);
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun BUG_ON(!node);
410*4882a593Smuzhiyun return node;
411*4882a593Smuzhiyun }
412*4882a593Smuzhiyun
btree_grow(struct btree_head * head,struct btree_geo * geo,gfp_t gfp)413*4882a593Smuzhiyun static int btree_grow(struct btree_head *head, struct btree_geo *geo,
414*4882a593Smuzhiyun gfp_t gfp)
415*4882a593Smuzhiyun {
416*4882a593Smuzhiyun unsigned long *node;
417*4882a593Smuzhiyun int fill;
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun node = btree_node_alloc(head, gfp);
420*4882a593Smuzhiyun if (!node)
421*4882a593Smuzhiyun return -ENOMEM;
422*4882a593Smuzhiyun if (head->node) {
423*4882a593Smuzhiyun fill = getfill(geo, head->node, 0);
424*4882a593Smuzhiyun setkey(geo, node, 0, bkey(geo, head->node, fill - 1));
425*4882a593Smuzhiyun setval(geo, node, 0, head->node);
426*4882a593Smuzhiyun }
427*4882a593Smuzhiyun head->node = node;
428*4882a593Smuzhiyun head->height++;
429*4882a593Smuzhiyun return 0;
430*4882a593Smuzhiyun }
431*4882a593Smuzhiyun
btree_shrink(struct btree_head * head,struct btree_geo * geo)432*4882a593Smuzhiyun static void btree_shrink(struct btree_head *head, struct btree_geo *geo)
433*4882a593Smuzhiyun {
434*4882a593Smuzhiyun unsigned long *node;
435*4882a593Smuzhiyun int fill;
436*4882a593Smuzhiyun
437*4882a593Smuzhiyun if (head->height <= 1)
438*4882a593Smuzhiyun return;
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun node = head->node;
441*4882a593Smuzhiyun fill = getfill(geo, node, 0);
442*4882a593Smuzhiyun BUG_ON(fill > 1);
443*4882a593Smuzhiyun head->node = bval(geo, node, 0);
444*4882a593Smuzhiyun head->height--;
445*4882a593Smuzhiyun mempool_free(node, head->mempool);
446*4882a593Smuzhiyun }
447*4882a593Smuzhiyun
btree_insert_level(struct btree_head * head,struct btree_geo * geo,unsigned long * key,void * val,int level,gfp_t gfp)448*4882a593Smuzhiyun static int btree_insert_level(struct btree_head *head, struct btree_geo *geo,
449*4882a593Smuzhiyun unsigned long *key, void *val, int level,
450*4882a593Smuzhiyun gfp_t gfp)
451*4882a593Smuzhiyun {
452*4882a593Smuzhiyun unsigned long *node;
453*4882a593Smuzhiyun int i, pos, fill, err;
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun BUG_ON(!val);
456*4882a593Smuzhiyun if (head->height < level) {
457*4882a593Smuzhiyun err = btree_grow(head, geo, gfp);
458*4882a593Smuzhiyun if (err)
459*4882a593Smuzhiyun return err;
460*4882a593Smuzhiyun }
461*4882a593Smuzhiyun
462*4882a593Smuzhiyun retry:
463*4882a593Smuzhiyun node = find_level(head, geo, key, level);
464*4882a593Smuzhiyun pos = getpos(geo, node, key);
465*4882a593Smuzhiyun fill = getfill(geo, node, pos);
466*4882a593Smuzhiyun /* two identical keys are not allowed */
467*4882a593Smuzhiyun BUG_ON(pos < fill && keycmp(geo, node, pos, key) == 0);
468*4882a593Smuzhiyun
469*4882a593Smuzhiyun if (fill == geo->no_pairs) {
470*4882a593Smuzhiyun /* need to split node */
471*4882a593Smuzhiyun unsigned long *new;
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun new = btree_node_alloc(head, gfp);
474*4882a593Smuzhiyun if (!new)
475*4882a593Smuzhiyun return -ENOMEM;
476*4882a593Smuzhiyun err = btree_insert_level(head, geo,
477*4882a593Smuzhiyun bkey(geo, node, fill / 2 - 1),
478*4882a593Smuzhiyun new, level + 1, gfp);
479*4882a593Smuzhiyun if (err) {
480*4882a593Smuzhiyun mempool_free(new, head->mempool);
481*4882a593Smuzhiyun return err;
482*4882a593Smuzhiyun }
483*4882a593Smuzhiyun for (i = 0; i < fill / 2; i++) {
484*4882a593Smuzhiyun setkey(geo, new, i, bkey(geo, node, i));
485*4882a593Smuzhiyun setval(geo, new, i, bval(geo, node, i));
486*4882a593Smuzhiyun setkey(geo, node, i, bkey(geo, node, i + fill / 2));
487*4882a593Smuzhiyun setval(geo, node, i, bval(geo, node, i + fill / 2));
488*4882a593Smuzhiyun clearpair(geo, node, i + fill / 2);
489*4882a593Smuzhiyun }
490*4882a593Smuzhiyun if (fill & 1) {
491*4882a593Smuzhiyun setkey(geo, node, i, bkey(geo, node, fill - 1));
492*4882a593Smuzhiyun setval(geo, node, i, bval(geo, node, fill - 1));
493*4882a593Smuzhiyun clearpair(geo, node, fill - 1);
494*4882a593Smuzhiyun }
495*4882a593Smuzhiyun goto retry;
496*4882a593Smuzhiyun }
497*4882a593Smuzhiyun BUG_ON(fill >= geo->no_pairs);
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun /* shift and insert */
500*4882a593Smuzhiyun for (i = fill; i > pos; i--) {
501*4882a593Smuzhiyun setkey(geo, node, i, bkey(geo, node, i - 1));
502*4882a593Smuzhiyun setval(geo, node, i, bval(geo, node, i - 1));
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun setkey(geo, node, pos, key);
505*4882a593Smuzhiyun setval(geo, node, pos, val);
506*4882a593Smuzhiyun
507*4882a593Smuzhiyun return 0;
508*4882a593Smuzhiyun }
509*4882a593Smuzhiyun
btree_insert(struct btree_head * head,struct btree_geo * geo,unsigned long * key,void * val,gfp_t gfp)510*4882a593Smuzhiyun int btree_insert(struct btree_head *head, struct btree_geo *geo,
511*4882a593Smuzhiyun unsigned long *key, void *val, gfp_t gfp)
512*4882a593Smuzhiyun {
513*4882a593Smuzhiyun BUG_ON(!val);
514*4882a593Smuzhiyun return btree_insert_level(head, geo, key, val, 1, gfp);
515*4882a593Smuzhiyun }
516*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(btree_insert);
517*4882a593Smuzhiyun
518*4882a593Smuzhiyun static void *btree_remove_level(struct btree_head *head, struct btree_geo *geo,
519*4882a593Smuzhiyun unsigned long *key, int level);
merge(struct btree_head * head,struct btree_geo * geo,int level,unsigned long * left,int lfill,unsigned long * right,int rfill,unsigned long * parent,int lpos)520*4882a593Smuzhiyun static void merge(struct btree_head *head, struct btree_geo *geo, int level,
521*4882a593Smuzhiyun unsigned long *left, int lfill,
522*4882a593Smuzhiyun unsigned long *right, int rfill,
523*4882a593Smuzhiyun unsigned long *parent, int lpos)
524*4882a593Smuzhiyun {
525*4882a593Smuzhiyun int i;
526*4882a593Smuzhiyun
527*4882a593Smuzhiyun for (i = 0; i < rfill; i++) {
528*4882a593Smuzhiyun /* Move all keys to the left */
529*4882a593Smuzhiyun setkey(geo, left, lfill + i, bkey(geo, right, i));
530*4882a593Smuzhiyun setval(geo, left, lfill + i, bval(geo, right, i));
531*4882a593Smuzhiyun }
532*4882a593Smuzhiyun /* Exchange left and right child in parent */
533*4882a593Smuzhiyun setval(geo, parent, lpos, right);
534*4882a593Smuzhiyun setval(geo, parent, lpos + 1, left);
535*4882a593Smuzhiyun /* Remove left (formerly right) child from parent */
536*4882a593Smuzhiyun btree_remove_level(head, geo, bkey(geo, parent, lpos), level + 1);
537*4882a593Smuzhiyun mempool_free(right, head->mempool);
538*4882a593Smuzhiyun }
539*4882a593Smuzhiyun
rebalance(struct btree_head * head,struct btree_geo * geo,unsigned long * key,int level,unsigned long * child,int fill)540*4882a593Smuzhiyun static void rebalance(struct btree_head *head, struct btree_geo *geo,
541*4882a593Smuzhiyun unsigned long *key, int level, unsigned long *child, int fill)
542*4882a593Smuzhiyun {
543*4882a593Smuzhiyun unsigned long *parent, *left = NULL, *right = NULL;
544*4882a593Smuzhiyun int i, no_left, no_right;
545*4882a593Smuzhiyun
546*4882a593Smuzhiyun if (fill == 0) {
547*4882a593Smuzhiyun /* Because we don't steal entries from a neighbour, this case
548*4882a593Smuzhiyun * can happen. Parent node contains a single child, this
549*4882a593Smuzhiyun * node, so merging with a sibling never happens.
550*4882a593Smuzhiyun */
551*4882a593Smuzhiyun btree_remove_level(head, geo, key, level + 1);
552*4882a593Smuzhiyun mempool_free(child, head->mempool);
553*4882a593Smuzhiyun return;
554*4882a593Smuzhiyun }
555*4882a593Smuzhiyun
556*4882a593Smuzhiyun parent = find_level(head, geo, key, level + 1);
557*4882a593Smuzhiyun i = getpos(geo, parent, key);
558*4882a593Smuzhiyun BUG_ON(bval(geo, parent, i) != child);
559*4882a593Smuzhiyun
560*4882a593Smuzhiyun if (i > 0) {
561*4882a593Smuzhiyun left = bval(geo, parent, i - 1);
562*4882a593Smuzhiyun no_left = getfill(geo, left, 0);
563*4882a593Smuzhiyun if (fill + no_left <= geo->no_pairs) {
564*4882a593Smuzhiyun merge(head, geo, level,
565*4882a593Smuzhiyun left, no_left,
566*4882a593Smuzhiyun child, fill,
567*4882a593Smuzhiyun parent, i - 1);
568*4882a593Smuzhiyun return;
569*4882a593Smuzhiyun }
570*4882a593Smuzhiyun }
571*4882a593Smuzhiyun if (i + 1 < getfill(geo, parent, i)) {
572*4882a593Smuzhiyun right = bval(geo, parent, i + 1);
573*4882a593Smuzhiyun no_right = getfill(geo, right, 0);
574*4882a593Smuzhiyun if (fill + no_right <= geo->no_pairs) {
575*4882a593Smuzhiyun merge(head, geo, level,
576*4882a593Smuzhiyun child, fill,
577*4882a593Smuzhiyun right, no_right,
578*4882a593Smuzhiyun parent, i);
579*4882a593Smuzhiyun return;
580*4882a593Smuzhiyun }
581*4882a593Smuzhiyun }
582*4882a593Smuzhiyun /*
583*4882a593Smuzhiyun * We could also try to steal one entry from the left or right
584*4882a593Smuzhiyun * neighbor. By not doing so we changed the invariant from
585*4882a593Smuzhiyun * "all nodes are at least half full" to "no two neighboring
586*4882a593Smuzhiyun * nodes can be merged". Which means that the average fill of
587*4882a593Smuzhiyun * all nodes is still half or better.
588*4882a593Smuzhiyun */
589*4882a593Smuzhiyun }
590*4882a593Smuzhiyun
btree_remove_level(struct btree_head * head,struct btree_geo * geo,unsigned long * key,int level)591*4882a593Smuzhiyun static void *btree_remove_level(struct btree_head *head, struct btree_geo *geo,
592*4882a593Smuzhiyun unsigned long *key, int level)
593*4882a593Smuzhiyun {
594*4882a593Smuzhiyun unsigned long *node;
595*4882a593Smuzhiyun int i, pos, fill;
596*4882a593Smuzhiyun void *ret;
597*4882a593Smuzhiyun
598*4882a593Smuzhiyun if (level > head->height) {
599*4882a593Smuzhiyun /* we recursed all the way up */
600*4882a593Smuzhiyun head->height = 0;
601*4882a593Smuzhiyun head->node = NULL;
602*4882a593Smuzhiyun return NULL;
603*4882a593Smuzhiyun }
604*4882a593Smuzhiyun
605*4882a593Smuzhiyun node = find_level(head, geo, key, level);
606*4882a593Smuzhiyun pos = getpos(geo, node, key);
607*4882a593Smuzhiyun fill = getfill(geo, node, pos);
608*4882a593Smuzhiyun if ((level == 1) && (keycmp(geo, node, pos, key) != 0))
609*4882a593Smuzhiyun return NULL;
610*4882a593Smuzhiyun ret = bval(geo, node, pos);
611*4882a593Smuzhiyun
612*4882a593Smuzhiyun /* remove and shift */
613*4882a593Smuzhiyun for (i = pos; i < fill - 1; i++) {
614*4882a593Smuzhiyun setkey(geo, node, i, bkey(geo, node, i + 1));
615*4882a593Smuzhiyun setval(geo, node, i, bval(geo, node, i + 1));
616*4882a593Smuzhiyun }
617*4882a593Smuzhiyun clearpair(geo, node, fill - 1);
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun if (fill - 1 < geo->no_pairs / 2) {
620*4882a593Smuzhiyun if (level < head->height)
621*4882a593Smuzhiyun rebalance(head, geo, key, level, node, fill - 1);
622*4882a593Smuzhiyun else if (fill - 1 == 1)
623*4882a593Smuzhiyun btree_shrink(head, geo);
624*4882a593Smuzhiyun }
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun return ret;
627*4882a593Smuzhiyun }
628*4882a593Smuzhiyun
btree_remove(struct btree_head * head,struct btree_geo * geo,unsigned long * key)629*4882a593Smuzhiyun void *btree_remove(struct btree_head *head, struct btree_geo *geo,
630*4882a593Smuzhiyun unsigned long *key)
631*4882a593Smuzhiyun {
632*4882a593Smuzhiyun if (head->height == 0)
633*4882a593Smuzhiyun return NULL;
634*4882a593Smuzhiyun
635*4882a593Smuzhiyun return btree_remove_level(head, geo, key, 1);
636*4882a593Smuzhiyun }
637*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(btree_remove);
638*4882a593Smuzhiyun
btree_merge(struct btree_head * target,struct btree_head * victim,struct btree_geo * geo,gfp_t gfp)639*4882a593Smuzhiyun int btree_merge(struct btree_head *target, struct btree_head *victim,
640*4882a593Smuzhiyun struct btree_geo *geo, gfp_t gfp)
641*4882a593Smuzhiyun {
642*4882a593Smuzhiyun unsigned long key[MAX_KEYLEN];
643*4882a593Smuzhiyun unsigned long dup[MAX_KEYLEN];
644*4882a593Smuzhiyun void *val;
645*4882a593Smuzhiyun int err;
646*4882a593Smuzhiyun
647*4882a593Smuzhiyun BUG_ON(target == victim);
648*4882a593Smuzhiyun
649*4882a593Smuzhiyun if (!(target->node)) {
650*4882a593Smuzhiyun /* target is empty, just copy fields over */
651*4882a593Smuzhiyun target->node = victim->node;
652*4882a593Smuzhiyun target->height = victim->height;
653*4882a593Smuzhiyun __btree_init(victim);
654*4882a593Smuzhiyun return 0;
655*4882a593Smuzhiyun }
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun /* TODO: This needs some optimizations. Currently we do three tree
658*4882a593Smuzhiyun * walks to remove a single object from the victim.
659*4882a593Smuzhiyun */
660*4882a593Smuzhiyun for (;;) {
661*4882a593Smuzhiyun if (!btree_last(victim, geo, key))
662*4882a593Smuzhiyun break;
663*4882a593Smuzhiyun val = btree_lookup(victim, geo, key);
664*4882a593Smuzhiyun err = btree_insert(target, geo, key, val, gfp);
665*4882a593Smuzhiyun if (err)
666*4882a593Smuzhiyun return err;
667*4882a593Smuzhiyun /* We must make a copy of the key, as the original will get
668*4882a593Smuzhiyun * mangled inside btree_remove. */
669*4882a593Smuzhiyun longcpy(dup, key, geo->keylen);
670*4882a593Smuzhiyun btree_remove(victim, geo, dup);
671*4882a593Smuzhiyun }
672*4882a593Smuzhiyun return 0;
673*4882a593Smuzhiyun }
674*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(btree_merge);
675*4882a593Smuzhiyun
__btree_for_each(struct btree_head * head,struct btree_geo * geo,unsigned long * node,unsigned long opaque,void (* func)(void * elem,unsigned long opaque,unsigned long * key,size_t index,void * func2),void * func2,int reap,int height,size_t count)676*4882a593Smuzhiyun static size_t __btree_for_each(struct btree_head *head, struct btree_geo *geo,
677*4882a593Smuzhiyun unsigned long *node, unsigned long opaque,
678*4882a593Smuzhiyun void (*func)(void *elem, unsigned long opaque,
679*4882a593Smuzhiyun unsigned long *key, size_t index,
680*4882a593Smuzhiyun void *func2),
681*4882a593Smuzhiyun void *func2, int reap, int height, size_t count)
682*4882a593Smuzhiyun {
683*4882a593Smuzhiyun int i;
684*4882a593Smuzhiyun unsigned long *child;
685*4882a593Smuzhiyun
686*4882a593Smuzhiyun for (i = 0; i < geo->no_pairs; i++) {
687*4882a593Smuzhiyun child = bval(geo, node, i);
688*4882a593Smuzhiyun if (!child)
689*4882a593Smuzhiyun break;
690*4882a593Smuzhiyun if (height > 1)
691*4882a593Smuzhiyun count = __btree_for_each(head, geo, child, opaque,
692*4882a593Smuzhiyun func, func2, reap, height - 1, count);
693*4882a593Smuzhiyun else
694*4882a593Smuzhiyun func(child, opaque, bkey(geo, node, i), count++,
695*4882a593Smuzhiyun func2);
696*4882a593Smuzhiyun }
697*4882a593Smuzhiyun if (reap)
698*4882a593Smuzhiyun mempool_free(node, head->mempool);
699*4882a593Smuzhiyun return count;
700*4882a593Smuzhiyun }
701*4882a593Smuzhiyun
empty(void * elem,unsigned long opaque,unsigned long * key,size_t index,void * func2)702*4882a593Smuzhiyun static void empty(void *elem, unsigned long opaque, unsigned long *key,
703*4882a593Smuzhiyun size_t index, void *func2)
704*4882a593Smuzhiyun {
705*4882a593Smuzhiyun }
706*4882a593Smuzhiyun
visitorl(void * elem,unsigned long opaque,unsigned long * key,size_t index,void * __func)707*4882a593Smuzhiyun void visitorl(void *elem, unsigned long opaque, unsigned long *key,
708*4882a593Smuzhiyun size_t index, void *__func)
709*4882a593Smuzhiyun {
710*4882a593Smuzhiyun visitorl_t func = __func;
711*4882a593Smuzhiyun
712*4882a593Smuzhiyun func(elem, opaque, *key, index);
713*4882a593Smuzhiyun }
714*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(visitorl);
715*4882a593Smuzhiyun
visitor32(void * elem,unsigned long opaque,unsigned long * __key,size_t index,void * __func)716*4882a593Smuzhiyun void visitor32(void *elem, unsigned long opaque, unsigned long *__key,
717*4882a593Smuzhiyun size_t index, void *__func)
718*4882a593Smuzhiyun {
719*4882a593Smuzhiyun visitor32_t func = __func;
720*4882a593Smuzhiyun u32 *key = (void *)__key;
721*4882a593Smuzhiyun
722*4882a593Smuzhiyun func(elem, opaque, *key, index);
723*4882a593Smuzhiyun }
724*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(visitor32);
725*4882a593Smuzhiyun
visitor64(void * elem,unsigned long opaque,unsigned long * __key,size_t index,void * __func)726*4882a593Smuzhiyun void visitor64(void *elem, unsigned long opaque, unsigned long *__key,
727*4882a593Smuzhiyun size_t index, void *__func)
728*4882a593Smuzhiyun {
729*4882a593Smuzhiyun visitor64_t func = __func;
730*4882a593Smuzhiyun u64 *key = (void *)__key;
731*4882a593Smuzhiyun
732*4882a593Smuzhiyun func(elem, opaque, *key, index);
733*4882a593Smuzhiyun }
734*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(visitor64);
735*4882a593Smuzhiyun
visitor128(void * elem,unsigned long opaque,unsigned long * __key,size_t index,void * __func)736*4882a593Smuzhiyun void visitor128(void *elem, unsigned long opaque, unsigned long *__key,
737*4882a593Smuzhiyun size_t index, void *__func)
738*4882a593Smuzhiyun {
739*4882a593Smuzhiyun visitor128_t func = __func;
740*4882a593Smuzhiyun u64 *key = (void *)__key;
741*4882a593Smuzhiyun
742*4882a593Smuzhiyun func(elem, opaque, key[0], key[1], index);
743*4882a593Smuzhiyun }
744*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(visitor128);
745*4882a593Smuzhiyun
btree_visitor(struct btree_head * head,struct btree_geo * geo,unsigned long opaque,void (* func)(void * elem,unsigned long opaque,unsigned long * key,size_t index,void * func2),void * func2)746*4882a593Smuzhiyun size_t btree_visitor(struct btree_head *head, struct btree_geo *geo,
747*4882a593Smuzhiyun unsigned long opaque,
748*4882a593Smuzhiyun void (*func)(void *elem, unsigned long opaque,
749*4882a593Smuzhiyun unsigned long *key,
750*4882a593Smuzhiyun size_t index, void *func2),
751*4882a593Smuzhiyun void *func2)
752*4882a593Smuzhiyun {
753*4882a593Smuzhiyun size_t count = 0;
754*4882a593Smuzhiyun
755*4882a593Smuzhiyun if (!func2)
756*4882a593Smuzhiyun func = empty;
757*4882a593Smuzhiyun if (head->node)
758*4882a593Smuzhiyun count = __btree_for_each(head, geo, head->node, opaque, func,
759*4882a593Smuzhiyun func2, 0, head->height, 0);
760*4882a593Smuzhiyun return count;
761*4882a593Smuzhiyun }
762*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(btree_visitor);
763*4882a593Smuzhiyun
btree_grim_visitor(struct btree_head * head,struct btree_geo * geo,unsigned long opaque,void (* func)(void * elem,unsigned long opaque,unsigned long * key,size_t index,void * func2),void * func2)764*4882a593Smuzhiyun size_t btree_grim_visitor(struct btree_head *head, struct btree_geo *geo,
765*4882a593Smuzhiyun unsigned long opaque,
766*4882a593Smuzhiyun void (*func)(void *elem, unsigned long opaque,
767*4882a593Smuzhiyun unsigned long *key,
768*4882a593Smuzhiyun size_t index, void *func2),
769*4882a593Smuzhiyun void *func2)
770*4882a593Smuzhiyun {
771*4882a593Smuzhiyun size_t count = 0;
772*4882a593Smuzhiyun
773*4882a593Smuzhiyun if (!func2)
774*4882a593Smuzhiyun func = empty;
775*4882a593Smuzhiyun if (head->node)
776*4882a593Smuzhiyun count = __btree_for_each(head, geo, head->node, opaque, func,
777*4882a593Smuzhiyun func2, 1, head->height, 0);
778*4882a593Smuzhiyun __btree_init(head);
779*4882a593Smuzhiyun return count;
780*4882a593Smuzhiyun }
781*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(btree_grim_visitor);
782*4882a593Smuzhiyun
btree_module_init(void)783*4882a593Smuzhiyun static int __init btree_module_init(void)
784*4882a593Smuzhiyun {
785*4882a593Smuzhiyun btree_cachep = kmem_cache_create("btree_node", NODESIZE, 0,
786*4882a593Smuzhiyun SLAB_HWCACHE_ALIGN, NULL);
787*4882a593Smuzhiyun return 0;
788*4882a593Smuzhiyun }
789*4882a593Smuzhiyun
btree_module_exit(void)790*4882a593Smuzhiyun static void __exit btree_module_exit(void)
791*4882a593Smuzhiyun {
792*4882a593Smuzhiyun kmem_cache_destroy(btree_cachep);
793*4882a593Smuzhiyun }
794*4882a593Smuzhiyun
795*4882a593Smuzhiyun /* If core code starts using btree, initialization should happen even earlier */
796*4882a593Smuzhiyun module_init(btree_module_init);
797*4882a593Smuzhiyun module_exit(btree_module_exit);
798*4882a593Smuzhiyun
799*4882a593Smuzhiyun MODULE_AUTHOR("Joern Engel <joern@logfs.org>");
800*4882a593Smuzhiyun MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
801*4882a593Smuzhiyun MODULE_LICENSE("GPL");
802