2 * linux/fs/hfsplus/bfind.c
5 * Brad Boyer (flar@allandria.com)
6 * (C) 2003 Ardis Technologies <roman@ardistech.com>
8 * Search routines for btrees
11 #include <linux/slab.h>
12 #include "hfsplus_fs.h"
14 /* Find the record in bnode that best matches key (not greater than...)*/
15 void hfsplus_find_rec(hfsplus_bnode *bnode, struct hfsplus_find_data *fd)
23 e = bnode->num_recs - 1;
26 len = hfsplus_brec_lenoff(bnode, rec, &off);
27 keylen = hfsplus_brec_keylen(bnode, rec);
28 hfsplus_bnode_readbytes(bnode, fd->key, off, keylen);
29 cmpval = bnode->tree->keycmp(fd->key, fd->search_key);
40 //printk("%d: %d,%d,%d\n", bnode->this, b, e, rec);
41 if (rec != e && e >= 0) {
42 len = hfsplus_brec_lenoff(bnode, e, &off);
43 keylen = hfsplus_brec_keylen(bnode, e);
44 hfsplus_bnode_readbytes(bnode, fd->key, off, keylen);
48 fd->keylength = keylen;
49 fd->entryoffset = off + keylen;
50 fd->entrylength = len - keylen;
53 /* Traverse a B*Tree from the root to a leaf finding best fit to key */
54 /* Return allocated copy of node found, set recnum to best record */
55 int hfsplus_btree_find(struct hfsplus_find_data *fd)
59 u32 data, nidx, parent;
64 hfsplus_put_bnode(fd->bnode);
74 bnode = hfsplus_find_bnode(tree, nidx);
79 if (bnode->height != height)
81 if (bnode->kind != (--height ? HFSPLUS_NODE_NDX : HFSPLUS_NODE_LEAF))
83 bnode->parent = parent;
85 hfsplus_find_rec(bnode, fd);
97 hfsplus_bnode_readbytes(bnode, &data, fd->entryoffset, 4);
98 nidx = be32_to_cpu(data);
99 hfsplus_put_bnode(bnode);
105 printk("HFS+-fs: inconsistency in B*Tree\n");
108 hfsplus_put_bnode(bnode);
112 int hfsplus_btree_find_entry(struct hfsplus_find_data *fd,
113 void *entry, int entry_len)
117 res = hfsplus_btree_find(fd);
120 if (fd->entrylength > entry_len)
122 hfsplus_bnode_readbytes(fd->bnode, entry, fd->entryoffset, fd->entrylength);
126 int hfsplus_btree_move(struct hfsplus_find_data *fd, int cnt)
128 struct hfsplus_btree *tree;
129 hfsplus_bnode *bnode;
131 u16 off, len, keylen;
136 if (cnt < -0xFFFF || cnt > 0xFFFF)
141 while (cnt > fd->record) {
142 cnt -= fd->record + 1;
143 fd->record = bnode->num_recs - 1;
149 hfsplus_put_bnode(bnode);
150 bnode = hfsplus_find_bnode(tree, idx);
158 while (cnt >= bnode->num_recs - fd->record) {
159 cnt -= bnode->num_recs - fd->record;
166 hfsplus_put_bnode(bnode);
167 bnode = hfsplus_find_bnode(tree, idx);
176 len = hfsplus_brec_lenoff(bnode, fd->record, &off);
177 keylen = hfsplus_brec_keylen(bnode, fd->record);
179 fd->keylength = keylen;
180 fd->entryoffset = off + keylen;
181 fd->entrylength = len - keylen;
182 hfsplus_bnode_readbytes(bnode, fd->key, off, keylen);
188 int hfsplus_find_init(hfsplus_btree *tree, struct hfsplus_find_data *fd)
192 fd->search_key = kmalloc(tree->max_key_len + 2, GFP_KERNEL);
195 fd->key = kmalloc(tree->max_key_len + 2, GFP_KERNEL);
197 kfree(fd->search_key);
200 dprint(DBG_BNODE_REFS, "find_init: %d (%p)\n", tree->cnid, __builtin_return_address(0));
201 down(&tree->tree_lock);
205 void hfsplus_find_exit(struct hfsplus_find_data *fd)
207 hfsplus_put_bnode(fd->bnode);
208 kfree(fd->search_key);
210 dprint(DBG_BNODE_REFS, "find_exit: %d (%p)\n", fd->tree->cnid, __builtin_return_address(0));
211 up(&fd->tree->tree_lock);