xref: /OK3568_Linux_fs/kernel/lib/btree.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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