/** * befs_btree_seekleaf - Find the first leafnode in the btree * @sb: Filesystem superblock * @ds: Datastream containing btree * @bt_super: Pointer to the superblock of the btree * @this_node: Buffer to return the leafnode in * @node_off: Pointer to offset of current node within datastream. Modified * by the function. * * * Helper function for btree traverse. Moves the current position to the * start of the first leaf node. * * Also checks for an empty tree. If there are no keys, returns BEFS_BT_EMPTY. */ 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) { befs_debug(sb, "---> %s", __func__); if (befs_bt_read_node(sb, ds, this_node, *node_off) != BEFS_OK) { befs_error(sb, "%s failed to read " "node at %llu", __func__, *node_off); goto error; } befs_debug(sb, "Seekleaf to root node %llu", *node_off); if (this_node->head.all_key_count == 0 && befs_leafnode(this_node)) { befs_debug(sb, "<--- %s Tree is EMPTY", __func__); return BEFS_BT_EMPTY; } while (!befs_leafnode(this_node)) { if (this_node->head.all_key_count == 0) { befs_debug(sb, "%s encountered " "an empty interior node: %llu. Using Overflow " "node: %llu", __func__, *node_off, this_node->head.overflow); *node_off = this_node->head.overflow; } else { fs64 *valarray = befs_bt_valarray(this_node); *node_off = fs64_to_cpu(sb, valarray[0]); } if (befs_bt_read_node(sb, ds, this_node, *node_off) != BEFS_OK) { befs_error(sb, "%s failed to read " "node at %llu", __func__, *node_off); goto error; } befs_debug(sb, "Seekleaf to child node %llu", *node_off); } befs_debug(sb, "Node %llu is a leaf node", *node_off); return BEFS_OK; error: befs_debug(sb, "<--- %s ERROR", __func__); return BEFS_ERR; }
/** * befs_btree_find - Find a key in a befs B+tree * @sb: Filesystem superblock * @ds: Datastream containing btree * @key: Key string to lookup in btree * @value: Value stored with @key * * On success, returns BEFS_OK and sets *@value to the value stored * with @key (usually the disk block number of an inode). * * On failure, returns BEFS_ERR or BEFS_BT_NOT_FOUND. * * Algorithm: * Read the superblock and rootnode of the b+tree. * Drill down through the interior nodes using befs_find_key(). * Once at the correct leaf node, use befs_find_key() again to get the * actuall value stored with the key. */ int befs_btree_find(struct super_block *sb, befs_data_stream * ds, const char *key, befs_off_t * value) { befs_btree_node *this_node = NULL; befs_btree_super bt_super; befs_off_t node_off; int res; befs_debug(sb, "---> befs_btree_find() Key: %s", key); if (befs_bt_read_super(sb, ds, &bt_super) != BEFS_OK) { befs_error(sb, "befs_btree_find() failed to read index superblock"); goto error; } this_node = kmalloc(sizeof (befs_btree_node), GFP_NOFS); if (!this_node) { befs_error(sb, "befs_btree_find() failed to allocate %u " "bytes of memory", sizeof (befs_btree_node)); goto error; } this_node->bh = NULL; /* read in root node */ node_off = bt_super.root_node_ptr; if (befs_bt_read_node(sb, ds, this_node, node_off) != BEFS_OK) { befs_error(sb, "befs_btree_find() failed to read " "node at %Lu", node_off); goto error_alloc; } while (!befs_leafnode(this_node)) { res = befs_find_key(sb, this_node, key, &node_off); if (res == BEFS_BT_NOT_FOUND) node_off = this_node->head.overflow; /* if no match, go to overflow node */ if (befs_bt_read_node(sb, ds, this_node, node_off) != BEFS_OK) { befs_error(sb, "befs_btree_find() failed to read " "node at %Lu", node_off); goto error_alloc; } } /* at the correct leaf node now */ res = befs_find_key(sb, this_node, key, value); brelse(this_node->bh); kfree(this_node); if (res != BEFS_BT_MATCH) { befs_debug(sb, "<--- befs_btree_find() Key %s not found", key); *value = 0; return BEFS_BT_NOT_FOUND; } befs_debug(sb, "<--- befs_btree_find() Found key %s, value %Lu", key, *value); return BEFS_OK; error_alloc: kfree(this_node); error: *value = 0; befs_debug(sb, "<--- befs_btree_find() ERROR"); return BEFS_ERR; }