Release 4.11 fs/hfs/bfind.c
/*
* linux/fs/hfs/bfind.c
*
* Copyright (C) 2001
* Brad Boyer (flar@allandria.com)
* (C) 2003 Ardis Technologies <roman@ardistech.com>
*
* Search routines for btrees
*/
#include <linux/slab.h>
#include "btree.h"
int hfs_find_init(struct hfs_btree *tree, struct hfs_find_data *fd)
{
void *ptr;
fd->tree = tree;
fd->bnode = NULL;
ptr = kmalloc(tree->max_key_len * 2 + 4, GFP_KERNEL);
if (!ptr)
return -ENOMEM;
fd->search_key = ptr;
fd->key = ptr + tree->max_key_len + 2;
hfs_dbg(BNODE_REFS, "find_init: %d (%p)\n",
tree->cnid, __builtin_return_address(0));
mutex_lock(&tree->tree_lock);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Andrew Morton | 81 | 81.00% | 1 | 25.00% |
Linus Torvalds (pre-git) | 16 | 16.00% | 1 | 25.00% |
Joe Perches | 2 | 2.00% | 1 | 25.00% |
Thomas Gleixner | 1 | 1.00% | 1 | 25.00% |
Total | 100 | 100.00% | 4 | 100.00% |
void hfs_find_exit(struct hfs_find_data *fd)
{
hfs_bnode_put(fd->bnode);
kfree(fd->search_key);
hfs_dbg(BNODE_REFS, "find_exit: %d (%p)\n",
fd->tree->cnid, __builtin_return_address(0));
mutex_unlock(&fd->tree->tree_lock);
fd->tree = NULL;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Andrew Morton | 45 | 77.59% | 1 | 25.00% |
Linus Torvalds (pre-git) | 10 | 17.24% | 1 | 25.00% |
Joe Perches | 2 | 3.45% | 1 | 25.00% |
Thomas Gleixner | 1 | 1.72% | 1 | 25.00% |
Total | 58 | 100.00% | 4 | 100.00% |
/* Find the record in bnode that best matches key (not greater than...)*/
int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd)
{
int cmpval;
u16 off, len, keylen;
int rec;
int b, e;
int res;
b = 0;
e = bnode->num_recs - 1;
res = -ENOENT;
do {
rec = (e + b) / 2;
len = hfs_brec_lenoff(bnode, rec, &off);
keylen = hfs_brec_keylen(bnode, rec);
if (keylen == 0) {
res = -EINVAL;
goto fail;
}
hfs_bnode_read(bnode, fd->key, off, keylen);
cmpval = bnode->tree->keycmp(fd->key, fd->search_key);
if (!cmpval) {
e = rec;
res = 0;
goto done;
}
if (cmpval < 0)
b = rec + 1;
else
e = rec - 1;
} while (b <= e);
if (rec != e && e >= 0) {
len = hfs_brec_lenoff(bnode, e, &off);
keylen = hfs_brec_keylen(bnode, e);
if (keylen == 0) {
res = -EINVAL;
goto fail;
}
hfs_bnode_read(bnode, fd->key, off, keylen);
}
done:
fd->record = e;
fd->keyoffset = off;
fd->keylength = keylen;
fd->entryoffset = off + keylen;
fd->entrylength = len - keylen;
fail:
return res;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Andrew Morton | 209 | 74.64% | 1 | 25.00% |
Linus Torvalds (pre-git) | 37 | 13.21% | 1 | 25.00% |
Eric Sandeen | 34 | 12.14% | 2 | 50.00% |
Total | 280 | 100.00% | 4 | 100.00% |
/* Traverse a B*Tree from the root to a leaf finding best fit to key */
/* Return allocated copy of node found, set recnum to best record */
int hfs_brec_find(struct hfs_find_data *fd)
{
struct hfs_btree *tree;
struct hfs_bnode *bnode;
u32 nidx, parent;
__be32 data;
int height, res;
tree = fd->tree;
if (fd->bnode)
hfs_bnode_put(fd->bnode);
fd->bnode = NULL;
nidx = tree->root;
if (!nidx)
return -ENOENT;
height = tree->depth;
res = 0;
parent = 0;
for (;;) {
bnode = hfs_bnode_find(tree, nidx);
if (IS_ERR(bnode)) {
res = PTR_ERR(bnode);
bnode = NULL;
break;
}
if (bnode->height != height)
goto invalid;
if (bnode->type != (--height ? HFS_NODE_INDEX : HFS_NODE_LEAF))
goto invalid;
bnode->parent = parent;
res = __hfs_brec_find(bnode, fd);
if (!height)
break;
if (fd->record < 0)
goto release;
parent = nidx;
hfs_bnode_read(bnode, &data, fd->entryoffset, 4);
nidx = be32_to_cpu(data);
hfs_bnode_put(bnode);
}
fd->bnode = bnode;
return res;
invalid:
pr_err("inconsistency in B*Tree (%d,%d,%d,%u,%u)\n",
height, bnode->height, bnode->type, nidx, parent);
res = -EIO;
release:
hfs_bnode_put(bnode);
return res;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Andrew Morton | 172 | 66.15% | 1 | 25.00% |
Linus Torvalds (pre-git) | 83 | 31.92% | 1 | 25.00% |
Al Viro | 3 | 1.15% | 1 | 25.00% |
Joe Perches | 2 | 0.77% | 1 | 25.00% |
Total | 260 | 100.00% | 4 | 100.00% |
int hfs_brec_read(struct hfs_find_data *fd, void *rec, int rec_len)
{
int res;
res = hfs_brec_find(fd);
if (res)
return res;
if (fd->entrylength > rec_len)
return -EINVAL;
hfs_bnode_read(fd->bnode, rec, fd->entryoffset, fd->entrylength);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Andrew Morton | 50 | 75.76% | 1 | 50.00% |
Linus Torvalds (pre-git) | 16 | 24.24% | 1 | 50.00% |
Total | 66 | 100.00% | 2 | 100.00% |
int hfs_brec_goto(struct hfs_find_data *fd, int cnt)
{
struct hfs_btree *tree;
struct hfs_bnode *bnode;
int idx, res = 0;
u16 off, len, keylen;
bnode = fd->bnode;
tree = bnode->tree;
if (cnt < 0) {
cnt = -cnt;
while (cnt > fd->record) {
cnt -= fd->record + 1;
fd->record = bnode->num_recs - 1;
idx = bnode->prev;
if (!idx) {
res = -ENOENT;
goto out;
}
hfs_bnode_put(bnode);
bnode = hfs_bnode_find(tree, idx);
if (IS_ERR(bnode)) {
res = PTR_ERR(bnode);
bnode = NULL;
goto out;
}
}
fd->record -= cnt;
} else {
while (cnt >= bnode->num_recs - fd->record) {
cnt -= bnode->num_recs - fd->record;
fd->record = 0;
idx = bnode->next;
if (!idx) {
res = -ENOENT;
goto out;
}
hfs_bnode_put(bnode);
bnode = hfs_bnode_find(tree, idx);
if (IS_ERR(bnode)) {
res = PTR_ERR(bnode);
bnode = NULL;
goto out;
}
}
fd->record += cnt;
}
len = hfs_brec_lenoff(bnode, fd->record, &off);
keylen = hfs_brec_keylen(bnode, fd->record);
if (keylen == 0) {
res = -EINVAL;
goto out;
}
fd->keyoffset = off;
fd->keylength = keylen;
fd->entryoffset = off + keylen;
fd->entrylength = len - keylen;
hfs_bnode_read(bnode, fd->key, off, keylen);
out:
fd->bnode = bnode;
return res;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Andrew Morton | 235 | 68.31% | 1 | 25.00% |
Linus Torvalds (pre-git) | 93 | 27.03% | 1 | 25.00% |
Eric Sandeen | 16 | 4.65% | 2 | 50.00% |
Total | 344 | 100.00% | 4 | 100.00% |
Overall Contributors
Person | Tokens | Prop | Commits | CommitProp |
Andrew Morton | 800 | 71.56% | 1 | 12.50% |
Linus Torvalds (pre-git) | 257 | 22.99% | 1 | 12.50% |
Eric Sandeen | 50 | 4.47% | 2 | 25.00% |
Joe Perches | 6 | 0.54% | 2 | 25.00% |
Al Viro | 3 | 0.27% | 1 | 12.50% |
Thomas Gleixner | 2 | 0.18% | 1 | 12.50% |
Total | 1118 | 100.00% | 8 | 100.00% |
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.