xref: /linux/fs/befs/btree.c (revision 8934827db5403eae57d4537114a9ff88b0a8460f)
1 /*
2  * linux/fs/befs/btree.c
3  *
4  * Copyright (C) 2001-2002 Will Dyson <will_dyson@pobox.com>
5  *
6  * Licensed under the GNU GPL. See the file COPYING for details.
7  *
8  * 2002-02-05: Sergey S. Kostyliov added binary search within
9  * 		btree nodes.
10  *
11  * Many thanks to:
12  *
13  * Dominic Giampaolo, author of "Practical File System
14  * Design with the Be File System", for such a helpful book.
15  *
16  * Marcus J. Ranum, author of the b+tree package in
17  * comp.sources.misc volume 10. This code is not copied from that
18  * work, but it is partially based on it.
19  *
20  * Makoto Kato, author of the original BeFS for linux filesystem
21  * driver.
22  */
23 
24 #include <linux/kernel.h>
25 #include <linux/string.h>
26 #include <linux/slab.h>
27 #include <linux/mm.h>
28 #include <linux/buffer_head.h>
29 
30 #include "befs.h"
31 #include "btree.h"
32 #include "datastream.h"
33 
34 /*
35  * The btree functions in this file are built on top of the
36  * datastream.c interface, which is in turn built on top of the
37  * io.c interface.
38  */
39 
40 /* Befs B+tree structure:
41  *
42  * The first thing in the tree is the tree superblock. It tells you
43  * all kinds of useful things about the tree, like where the rootnode
44  * is located, and the size of the nodes (always 1024 with current version
45  * of BeOS).
46  *
47  * The rest of the tree consists of a series of nodes. Nodes contain a header
48  * (struct befs_btree_nodehead), the packed key data, an array of shorts
49  * containing the ending offsets for each of the keys, and an array of
50  * befs_off_t values. In interior nodes, the keys are the ending keys for
51  * the childnode they point to, and the values are offsets into the
52  * datastream containing the tree.
53  */
54 
55 /* Note:
56  *
57  * The book states 2 confusing things about befs b+trees. First,
58  * it states that the overflow field of node headers is used by internal nodes
59  * to point to another node that "effectively continues this one". Here is what
60  * I believe that means. Each key in internal nodes points to another node that
61  * contains key values less than itself. Inspection reveals that the last key
62  * in the internal node is not the last key in the index. Keys that are
63  * greater than the last key in the internal node go into the overflow node.
64  * I imagine there is a performance reason for this.
65  *
66  * Second, it states that the header of a btree node is sufficient to
67  * distinguish internal nodes from leaf nodes. Without saying exactly how.
68  * After figuring out the first, it becomes obvious that internal nodes have
69  * overflow nodes and leafnodes do not.
70  */
71 
72 /*
73  * Currently, this code is only good for directory B+trees.
74  * In order to be used for other BFS indexes, it needs to be extended to handle
75  * duplicate keys and non-string keytypes (int32, int64, float, double).
76  */
77 
78 /*
79  * In memory structure of each btree node
80  */
81 struct befs_btree_node {
82 	befs_host_btree_nodehead head;	/* head of node converted to cpu byteorder */
83 	struct buffer_head *bh;
84 	befs_btree_nodehead *od_node;	/* on disk node */
85 };
86 
87 /* local constants */
88 static const befs_off_t BEFS_BT_INVAL = 0xffffffffffffffffULL;
89 
90 /* local functions */
91 static int befs_btree_seekleaf(struct super_block *sb, const befs_data_stream *ds,
92 			       befs_btree_super * bt_super,
93 			       struct befs_btree_node *this_node,
94 			       befs_off_t * node_off);
95 
96 static int befs_bt_read_super(struct super_block *sb, const befs_data_stream *ds,
97 			      befs_btree_super * sup);
98 
99 static int befs_bt_read_node(struct super_block *sb, const befs_data_stream *ds,
100 			     struct befs_btree_node *node,
101 			     befs_off_t node_off);
102 
103 static int befs_leafnode(struct befs_btree_node *node);
104 
105 static fs16 *befs_bt_keylen_index(struct befs_btree_node *node);
106 
107 static fs64 *befs_bt_valarray(struct befs_btree_node *node);
108 
109 static char *befs_bt_keydata(struct befs_btree_node *node);
110 
111 static int befs_find_key(struct super_block *sb,
112 			 struct befs_btree_node *node,
113 			 const char *findkey, befs_off_t * value);
114 
115 static char *befs_bt_get_key(struct super_block *sb,
116 			     struct befs_btree_node *node,
117 			     int index, u16 * keylen);
118 
119 static int befs_compare_strings(const void *key1, int keylen1,
120 				const void *key2, int keylen2);
121 
122 /**
123  * befs_bt_read_super() - read in btree superblock convert to cpu byteorder
124  * @sb:        Filesystem superblock
125  * @ds:        Datastream to read from
126  * @sup:       Buffer in which to place the btree superblock
127  *
128  * Calls befs_read_datastream to read in the btree superblock and
129  * makes sure it is in cpu byteorder, byteswapping if necessary.
130  * Return: BEFS_OK on success and if *@sup contains the btree superblock in cpu
131  * byte order. Otherwise return BEFS_ERR on error.
132  */
133 static int
befs_bt_read_super(struct super_block * sb,const befs_data_stream * ds,befs_btree_super * sup)134 befs_bt_read_super(struct super_block *sb, const befs_data_stream *ds,
135 		   befs_btree_super * sup)
136 {
137 	struct buffer_head *bh;
138 	befs_disk_btree_super *od_sup;
139 
140 	befs_debug(sb, "---> %s", __func__);
141 
142 	bh = befs_read_datastream(sb, ds, 0, NULL);
143 
144 	if (!bh) {
145 		befs_error(sb, "Couldn't read index header.");
146 		goto error;
147 	}
148 	od_sup = (befs_disk_btree_super *) bh->b_data;
149 	befs_dump_index_entry(sb, od_sup);
150 
151 	sup->magic = fs32_to_cpu(sb, od_sup->magic);
152 	sup->node_size = fs32_to_cpu(sb, od_sup->node_size);
153 	sup->max_depth = fs32_to_cpu(sb, od_sup->max_depth);
154 	sup->data_type = fs32_to_cpu(sb, od_sup->data_type);
155 	sup->root_node_ptr = fs64_to_cpu(sb, od_sup->root_node_ptr);
156 
157 	brelse(bh);
158 	if (sup->magic != BEFS_BTREE_MAGIC) {
159 		befs_error(sb, "Index header has bad magic.");
160 		goto error;
161 	}
162 
163 	befs_debug(sb, "<--- %s", __func__);
164 	return BEFS_OK;
165 
166       error:
167 	befs_debug(sb, "<--- %s ERROR", __func__);
168 	return BEFS_ERR;
169 }
170 
171 /**
172  * befs_bt_read_node - read in btree node and convert to cpu byteorder
173  * @sb: Filesystem superblock
174  * @ds: Datastream to read from
175  * @node: Buffer in which to place the btree node
176  * @node_off: Starting offset (in bytes) of the node in @ds
177  *
178  * Calls befs_read_datastream to read in the indicated btree node and
179  * makes sure its header fields are in cpu byteorder, byteswapping if
180  * necessary.
181  * Note: node->bh must be NULL when this function is called the first time.
182  * Don't forget brelse(node->bh) after last call.
183  *
184  * On success, returns BEFS_OK and *@node contains the btree node that
185  * starts at @node_off, with the node->head fields in cpu byte order.
186  *
187  * On failure, BEFS_ERR is returned.
188  */
189 
190 static int
befs_bt_read_node(struct super_block * sb,const befs_data_stream * ds,struct befs_btree_node * node,befs_off_t node_off)191 befs_bt_read_node(struct super_block *sb, const befs_data_stream *ds,
192 		  struct befs_btree_node *node, befs_off_t node_off)
193 {
194 	uint off = 0;
195 
196 	befs_debug(sb, "---> %s", __func__);
197 
198 	if (node->bh)
199 		brelse(node->bh);
200 
201 	node->bh = befs_read_datastream(sb, ds, node_off, &off);
202 	if (!node->bh) {
203 		befs_error(sb, "%s failed to read "
204 			   "node at %llu", __func__, node_off);
205 		befs_debug(sb, "<--- %s ERROR", __func__);
206 
207 		return BEFS_ERR;
208 	}
209 	node->od_node =
210 	    (befs_btree_nodehead *) ((void *) node->bh->b_data + off);
211 
212 	befs_dump_index_node(sb, node->od_node);
213 
214 	node->head.left = fs64_to_cpu(sb, node->od_node->left);
215 	node->head.right = fs64_to_cpu(sb, node->od_node->right);
216 	node->head.overflow = fs64_to_cpu(sb, node->od_node->overflow);
217 	node->head.all_key_count =
218 	    fs16_to_cpu(sb, node->od_node->all_key_count);
219 	node->head.all_key_length =
220 	    fs16_to_cpu(sb, node->od_node->all_key_length);
221 
222 	befs_debug(sb, "<--- %s", __func__);
223 	return BEFS_OK;
224 }
225 
226 /**
227  * befs_btree_find - Find a key in a befs B+tree
228  * @sb: Filesystem superblock
229  * @ds: Datastream containing btree
230  * @key: Key string to lookup in btree
231  * @value: Value stored with @key
232  *
233  * On success, returns BEFS_OK and sets *@value to the value stored
234  * with @key (usually the disk block number of an inode).
235  *
236  * On failure, returns BEFS_ERR or BEFS_BT_NOT_FOUND.
237  *
238  * Algorithm:
239  *   Read the superblock and rootnode of the b+tree.
240  *   Drill down through the interior nodes using befs_find_key().
241  *   Once at the correct leaf node, use befs_find_key() again to get the
242  *   actual value stored with the key.
243  */
244 int
befs_btree_find(struct super_block * sb,const befs_data_stream * ds,const char * key,befs_off_t * value)245 befs_btree_find(struct super_block *sb, const befs_data_stream *ds,
246 		const char *key, befs_off_t * value)
247 {
248 	struct befs_btree_node *this_node;
249 	befs_btree_super bt_super;
250 	befs_off_t node_off;
251 	int res;
252 
253 	befs_debug(sb, "---> %s Key: %s", __func__, key);
254 
255 	if (befs_bt_read_super(sb, ds, &bt_super) != BEFS_OK) {
256 		befs_error(sb,
257 			   "befs_btree_find() failed to read index superblock");
258 		goto error;
259 	}
260 
261 	this_node = kmalloc_obj(struct befs_btree_node, GFP_NOFS);
262 	if (!this_node) {
263 		befs_error(sb, "befs_btree_find() failed to allocate %zu "
264 			   "bytes of memory", sizeof(struct befs_btree_node));
265 		goto error;
266 	}
267 
268 	this_node->bh = NULL;
269 
270 	/* read in root node */
271 	node_off = bt_super.root_node_ptr;
272 	if (befs_bt_read_node(sb, ds, this_node, node_off) != BEFS_OK) {
273 		befs_error(sb, "befs_btree_find() failed to read "
274 			   "node at %llu", node_off);
275 		goto error_alloc;
276 	}
277 
278 	while (!befs_leafnode(this_node)) {
279 		res = befs_find_key(sb, this_node, key, &node_off);
280 		/* if no key set, try the overflow node */
281 		if (res == BEFS_BT_OVERFLOW)
282 			node_off = this_node->head.overflow;
283 		if (befs_bt_read_node(sb, ds, this_node, node_off) != BEFS_OK) {
284 			befs_error(sb, "befs_btree_find() failed to read "
285 				   "node at %llu", node_off);
286 			goto error_alloc;
287 		}
288 	}
289 
290 	/* at a leaf node now, check if it is correct */
291 	res = befs_find_key(sb, this_node, key, value);
292 
293 	brelse(this_node->bh);
294 	kfree(this_node);
295 
296 	if (res != BEFS_BT_MATCH) {
297 		befs_error(sb, "<--- %s Key %s not found", __func__, key);
298 		befs_debug(sb, "<--- %s ERROR", __func__);
299 		*value = 0;
300 		return BEFS_BT_NOT_FOUND;
301 	}
302 	befs_debug(sb, "<--- %s Found key %s, value %llu", __func__,
303 		   key, *value);
304 	return BEFS_OK;
305 
306       error_alloc:
307 	kfree(this_node);
308       error:
309 	*value = 0;
310 	befs_debug(sb, "<--- %s ERROR", __func__);
311 	return BEFS_ERR;
312 }
313 
314 /**
315  * befs_find_key - Search for a key within a node
316  * @sb: Filesystem superblock
317  * @node: Node to find the key within
318  * @findkey: Keystring to search for
319  * @value: If key is found, the value stored with the key is put here
320  *
321  * Finds exact match if one exists, and returns BEFS_BT_MATCH.
322  * If there is no match and node's value array is too small for key, return
323  * BEFS_BT_OVERFLOW.
324  * If no match and node should countain this key, return BEFS_BT_NOT_FOUND.
325  *
326  * Uses binary search instead of a linear.
327  */
328 static int
befs_find_key(struct super_block * sb,struct befs_btree_node * node,const char * findkey,befs_off_t * value)329 befs_find_key(struct super_block *sb, struct befs_btree_node *node,
330 	      const char *findkey, befs_off_t * value)
331 {
332 	int first, last, mid;
333 	int eq;
334 	u16 keylen;
335 	int findkey_len;
336 	char *thiskey;
337 	fs64 *valarray;
338 
339 	befs_debug(sb, "---> %s %s", __func__, findkey);
340 
341 	findkey_len = strlen(findkey);
342 
343 	/* if node can not contain key, just skip this node */
344 	last = node->head.all_key_count - 1;
345 	thiskey = befs_bt_get_key(sb, node, last, &keylen);
346 
347 	eq = befs_compare_strings(thiskey, keylen, findkey, findkey_len);
348 	if (eq < 0) {
349 		befs_debug(sb, "<--- node can't contain %s", findkey);
350 		return BEFS_BT_OVERFLOW;
351 	}
352 
353 	valarray = befs_bt_valarray(node);
354 
355 	/* simple binary search */
356 	first = 0;
357 	mid = 0;
358 	while (last >= first) {
359 		mid = (last + first) / 2;
360 		befs_debug(sb, "first: %d, last: %d, mid: %d", first, last,
361 			   mid);
362 		thiskey = befs_bt_get_key(sb, node, mid, &keylen);
363 		eq = befs_compare_strings(thiskey, keylen, findkey,
364 					  findkey_len);
365 
366 		if (eq == 0) {
367 			befs_debug(sb, "<--- %s found %s at %d",
368 				   __func__, thiskey, mid);
369 
370 			*value = fs64_to_cpu(sb, valarray[mid]);
371 			return BEFS_BT_MATCH;
372 		}
373 		if (eq > 0)
374 			last = mid - 1;
375 		else
376 			first = mid + 1;
377 	}
378 
379 	/* return an existing value so caller can arrive to a leaf node */
380 	if (eq < 0)
381 		*value = fs64_to_cpu(sb, valarray[mid + 1]);
382 	else
383 		*value = fs64_to_cpu(sb, valarray[mid]);
384 	befs_error(sb, "<--- %s %s not found", __func__, findkey);
385 	befs_debug(sb, "<--- %s ERROR", __func__);
386 	return BEFS_BT_NOT_FOUND;
387 }
388 
389 /**
390  * befs_btree_read - Traverse leafnodes of a btree
391  * @sb: Filesystem superblock
392  * @ds: Datastream containing btree
393  * @key_no: Key number (alphabetical order) of key to read
394  * @bufsize: Size of the buffer to return key in
395  * @keybuf: Pointer to a buffer to put the key in
396  * @keysize: Length of the returned key
397  * @value: Value stored with the returned key
398  *
399  * Here's how it works: Key_no is the index of the key/value pair to
400  * return in keybuf/value.
401  * Bufsize is the size of keybuf (BEFS_NAME_LEN+1 is a good size). Keysize is
402  * the number of characters in the key (just a convenience).
403  *
404  * Algorithm:
405  *   Get the first leafnode of the tree. See if the requested key is in that
406  *   node. If not, follow the node->right link to the next leafnode. Repeat
407  *   until the (key_no)th key is found or the tree is out of keys.
408  */
409 int
befs_btree_read(struct super_block * sb,const befs_data_stream * ds,loff_t key_no,size_t bufsize,char * keybuf,size_t * keysize,befs_off_t * value)410 befs_btree_read(struct super_block *sb, const befs_data_stream *ds,
411 		loff_t key_no, size_t bufsize, char *keybuf, size_t * keysize,
412 		befs_off_t * value)
413 {
414 	struct befs_btree_node *this_node;
415 	befs_btree_super bt_super;
416 	befs_off_t node_off;
417 	int cur_key;
418 	fs64 *valarray;
419 	char *keystart;
420 	u16 keylen;
421 	int res;
422 
423 	uint key_sum = 0;
424 
425 	befs_debug(sb, "---> %s", __func__);
426 
427 	if (befs_bt_read_super(sb, ds, &bt_super) != BEFS_OK) {
428 		befs_error(sb,
429 			   "befs_btree_read() failed to read index superblock");
430 		goto error;
431 	}
432 
433 	this_node = kmalloc_obj(struct befs_btree_node, GFP_NOFS);
434 	if (this_node == NULL) {
435 		befs_error(sb, "befs_btree_read() failed to allocate %zu "
436 			   "bytes of memory", sizeof(struct befs_btree_node));
437 		goto error;
438 	}
439 
440 	node_off = bt_super.root_node_ptr;
441 	this_node->bh = NULL;
442 
443 	/* seeks down to first leafnode, reads it into this_node */
444 	res = befs_btree_seekleaf(sb, ds, &bt_super, this_node, &node_off);
445 	if (res == BEFS_BT_EMPTY) {
446 		brelse(this_node->bh);
447 		kfree(this_node);
448 		*value = 0;
449 		*keysize = 0;
450 		befs_debug(sb, "<--- %s Tree is EMPTY", __func__);
451 		return BEFS_BT_EMPTY;
452 	} else if (res == BEFS_ERR) {
453 		goto error_alloc;
454 	}
455 
456 	/* find the leaf node containing the key_no key */
457 
458 	while (key_sum + this_node->head.all_key_count <= key_no) {
459 
460 		/* no more nodes to look in: key_no is too large */
461 		if (this_node->head.right == BEFS_BT_INVAL) {
462 			*keysize = 0;
463 			*value = 0;
464 			befs_debug(sb,
465 				   "<--- %s END of keys at %llu", __func__,
466 				   (unsigned long long)
467 				   key_sum + this_node->head.all_key_count);
468 			brelse(this_node->bh);
469 			kfree(this_node);
470 			return BEFS_BT_END;
471 		}
472 
473 		key_sum += this_node->head.all_key_count;
474 		node_off = this_node->head.right;
475 
476 		if (befs_bt_read_node(sb, ds, this_node, node_off) != BEFS_OK) {
477 			befs_error(sb, "%s failed to read node at %llu",
478 				  __func__, (unsigned long long)node_off);
479 			goto error_alloc;
480 		}
481 	}
482 
483 	/* how many keys into this_node is key_no */
484 	cur_key = key_no - key_sum;
485 
486 	/* get pointers to datastructures within the node body */
487 	valarray = befs_bt_valarray(this_node);
488 
489 	keystart = befs_bt_get_key(sb, this_node, cur_key, &keylen);
490 
491 	befs_debug(sb, "Read [%llu,%d]: keysize %d",
492 		   (long long unsigned int)node_off, (int)cur_key,
493 		   (int)keylen);
494 
495 	if (bufsize < keylen + 1) {
496 		befs_error(sb, "%s keybuf too small (%zu) "
497 			   "for key of size %d", __func__, bufsize, keylen);
498 		brelse(this_node->bh);
499 		goto error_alloc;
500 	}
501 
502 	strscpy(keybuf, keystart, keylen + 1);
503 	*value = fs64_to_cpu(sb, valarray[cur_key]);
504 	*keysize = keylen;
505 
506 	befs_debug(sb, "Read [%llu,%d]: Key \"%.*s\", Value %llu", node_off,
507 		   cur_key, keylen, keybuf, *value);
508 
509 	brelse(this_node->bh);
510 	kfree(this_node);
511 
512 	befs_debug(sb, "<--- %s", __func__);
513 
514 	return BEFS_OK;
515 
516       error_alloc:
517 	kfree(this_node);
518 
519       error:
520 	*keysize = 0;
521 	*value = 0;
522 	befs_debug(sb, "<--- %s ERROR", __func__);
523 	return BEFS_ERR;
524 }
525 
526 /**
527  * befs_btree_seekleaf - Find the first leafnode in the btree
528  * @sb: Filesystem superblock
529  * @ds: Datastream containing btree
530  * @bt_super: Pointer to the superblock of the btree
531  * @this_node: Buffer to return the leafnode in
532  * @node_off: Pointer to offset of current node within datastream. Modified
533  * 		by the function.
534  *
535  * Helper function for btree traverse. Moves the current position to the
536  * start of the first leaf node.
537  *
538  * Also checks for an empty tree. If there are no keys, returns BEFS_BT_EMPTY.
539  */
540 static int
befs_btree_seekleaf(struct super_block * sb,const befs_data_stream * ds,befs_btree_super * bt_super,struct befs_btree_node * this_node,befs_off_t * node_off)541 befs_btree_seekleaf(struct super_block *sb, const befs_data_stream *ds,
542 		    befs_btree_super *bt_super,
543 		    struct befs_btree_node *this_node,
544 		    befs_off_t * node_off)
545 {
546 
547 	befs_debug(sb, "---> %s", __func__);
548 
549 	if (befs_bt_read_node(sb, ds, this_node, *node_off) != BEFS_OK) {
550 		befs_error(sb, "%s failed to read "
551 			   "node at %llu", __func__, *node_off);
552 		goto error;
553 	}
554 	befs_debug(sb, "Seekleaf to root node %llu", *node_off);
555 
556 	if (this_node->head.all_key_count == 0 && befs_leafnode(this_node)) {
557 		befs_debug(sb, "<--- %s Tree is EMPTY", __func__);
558 		return BEFS_BT_EMPTY;
559 	}
560 
561 	while (!befs_leafnode(this_node)) {
562 
563 		if (this_node->head.all_key_count == 0) {
564 			befs_debug(sb, "%s encountered "
565 				   "an empty interior node: %llu. Using Overflow "
566 				   "node: %llu", __func__, *node_off,
567 				   this_node->head.overflow);
568 			*node_off = this_node->head.overflow;
569 		} else {
570 			fs64 *valarray = befs_bt_valarray(this_node);
571 			*node_off = fs64_to_cpu(sb, valarray[0]);
572 		}
573 		if (befs_bt_read_node(sb, ds, this_node, *node_off) != BEFS_OK) {
574 			befs_error(sb, "%s failed to read "
575 				   "node at %llu", __func__, *node_off);
576 			goto error;
577 		}
578 
579 		befs_debug(sb, "Seekleaf to child node %llu", *node_off);
580 	}
581 	befs_debug(sb, "Node %llu is a leaf node", *node_off);
582 
583 	return BEFS_OK;
584 
585       error:
586 	befs_debug(sb, "<--- %s ERROR", __func__);
587 	return BEFS_ERR;
588 }
589 
590 /**
591  * befs_leafnode - Determine if the btree node is a leaf node or an
592  * interior node
593  * @node: Pointer to node structure to test
594  *
595  * Return 1 if leaf, 0 if interior
596  */
597 static int
befs_leafnode(struct befs_btree_node * node)598 befs_leafnode(struct befs_btree_node *node)
599 {
600 	/* all interior nodes (and only interior nodes) have an overflow node */
601 	if (node->head.overflow == BEFS_BT_INVAL)
602 		return 1;
603 	else
604 		return 0;
605 }
606 
607 /**
608  * befs_bt_keylen_index - Finds start of keylen index in a node
609  * @node: Pointer to the node structure to find the keylen index within
610  *
611  * Returns a pointer to the start of the key length index array
612  * of the B+tree node *@node
613  *
614  * "The length of all the keys in the node is added to the size of the
615  * header and then rounded up to a multiple of four to get the beginning
616  * of the key length index" (p.88, practical filesystem design).
617  *
618  * Except that rounding up to 8 works, and rounding up to 4 doesn't.
619  */
620 static fs16 *
befs_bt_keylen_index(struct befs_btree_node * node)621 befs_bt_keylen_index(struct befs_btree_node *node)
622 {
623 	const int keylen_align = 8;
624 	unsigned long int off =
625 	    (sizeof (befs_btree_nodehead) + node->head.all_key_length);
626 	ulong tmp = off % keylen_align;
627 
628 	if (tmp)
629 		off += keylen_align - tmp;
630 
631 	return (fs16 *) ((void *) node->od_node + off);
632 }
633 
634 /**
635  * befs_bt_valarray - Finds the start of value array in a node
636  * @node: Pointer to the node structure to find the value array within
637  *
638  * Returns a pointer to the start of the value array
639  * of the node pointed to by the node header
640  */
641 static fs64 *
befs_bt_valarray(struct befs_btree_node * node)642 befs_bt_valarray(struct befs_btree_node *node)
643 {
644 	void *keylen_index_start = (void *) befs_bt_keylen_index(node);
645 	size_t keylen_index_size = node->head.all_key_count * sizeof (fs16);
646 
647 	return (fs64 *) (keylen_index_start + keylen_index_size);
648 }
649 
650 /**
651  * befs_bt_keydata - Finds start of keydata array in a node
652  * @node: Pointer to the node structure to find the keydata array within
653  *
654  * Returns a pointer to the start of the keydata array
655  * of the node pointed to by the node header
656  */
657 static char *
befs_bt_keydata(struct befs_btree_node * node)658 befs_bt_keydata(struct befs_btree_node *node)
659 {
660 	return (char *) ((void *) node->od_node + sizeof (befs_btree_nodehead));
661 }
662 
663 /**
664  * befs_bt_get_key - returns a pointer to the start of a key
665  * @sb: filesystem superblock
666  * @node: node in which to look for the key
667  * @index: the index of the key to get
668  * @keylen: modified to be the length of the key at @index
669  *
670  * Returns a valid pointer into @node on success.
671  * Returns NULL on failure (bad input) and sets *@keylen = 0
672  */
673 static char *
befs_bt_get_key(struct super_block * sb,struct befs_btree_node * node,int index,u16 * keylen)674 befs_bt_get_key(struct super_block *sb, struct befs_btree_node *node,
675 		int index, u16 * keylen)
676 {
677 	int prev_key_end;
678 	char *keystart;
679 	fs16 *keylen_index;
680 
681 	if (index < 0 || index > node->head.all_key_count) {
682 		*keylen = 0;
683 		return NULL;
684 	}
685 
686 	keystart = befs_bt_keydata(node);
687 	keylen_index = befs_bt_keylen_index(node);
688 
689 	if (index == 0)
690 		prev_key_end = 0;
691 	else
692 		prev_key_end = fs16_to_cpu(sb, keylen_index[index - 1]);
693 
694 	*keylen = fs16_to_cpu(sb, keylen_index[index]) - prev_key_end;
695 
696 	return keystart + prev_key_end;
697 }
698 
699 /**
700  * befs_compare_strings - compare two strings
701  * @key1: pointer to the first key to be compared
702  * @keylen1: length in bytes of key1
703  * @key2: pointer to the second key to be compared
704  * @keylen2: length in bytes of key2
705  *
706  * Returns 0 if @key1 and @key2 are equal.
707  * Returns >0 if @key1 is greater.
708  * Returns <0 if @key2 is greater.
709  */
710 static int
befs_compare_strings(const void * key1,int keylen1,const void * key2,int keylen2)711 befs_compare_strings(const void *key1, int keylen1,
712 		     const void *key2, int keylen2)
713 {
714 	int len = min_t(int, keylen1, keylen2);
715 	int result = strncmp(key1, key2, len);
716 	if (result == 0)
717 		result = keylen1 - keylen2;
718 	return result;
719 }
720 
721 /* These will be used for non-string keyed btrees */
722 #if 0
723 static int
724 btree_compare_int32(cont void *key1, int keylen1, const void *key2, int keylen2)
725 {
726 	return *(int32_t *) key1 - *(int32_t *) key2;
727 }
728 
729 static int
730 btree_compare_uint32(cont void *key1, int keylen1,
731 		     const void *key2, int keylen2)
732 {
733 	if (*(u_int32_t *) key1 == *(u_int32_t *) key2)
734 		return 0;
735 	else if (*(u_int32_t *) key1 > *(u_int32_t *) key2)
736 		return 1;
737 
738 	return -1;
739 }
740 static int
741 btree_compare_int64(cont void *key1, int keylen1, const void *key2, int keylen2)
742 {
743 	if (*(int64_t *) key1 == *(int64_t *) key2)
744 		return 0;
745 	else if (*(int64_t *) key1 > *(int64_t *) key2)
746 		return 1;
747 
748 	return -1;
749 }
750 
751 static int
752 btree_compare_uint64(cont void *key1, int keylen1,
753 		     const void *key2, int keylen2)
754 {
755 	if (*(u_int64_t *) key1 == *(u_int64_t *) key2)
756 		return 0;
757 	else if (*(u_int64_t *) key1 > *(u_int64_t *) key2)
758 		return 1;
759 
760 	return -1;
761 }
762 
763 static int
764 btree_compare_float(cont void *key1, int keylen1, const void *key2, int keylen2)
765 {
766 	float result = *(float *) key1 - *(float *) key2;
767 	if (result == 0.0f)
768 		return 0;
769 
770 	return (result < 0.0f) ? -1 : 1;
771 }
772 
773 static int
774 btree_compare_double(cont void *key1, int keylen1,
775 		     const void *key2, int keylen2)
776 {
777 	double result = *(double *) key1 - *(double *) key2;
778 	if (result == 0.0)
779 		return 0;
780 
781 	return (result < 0.0) ? -1 : 1;
782 }
783 #endif				//0
784