--- a/fs/hfs/bfind.c +++ b/fs/hfs/bfind.c @@ -16,6 +16,9 @@ int hfs_find_init(struct hfs_btree *tree, struct hfs_find_data *fd) { void *ptr; +if (!tree || !fd) + return -EINVAL; + fd->tree = tree; fd->bnode = NULL; ptr = kzalloc(tree->max_key_len * 2 + 4, GFP_KERNEL); --- a/fs/hfs/btree.c +++ b/fs/hfs/btree.c @@ -21,8 +21,10 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp ke struct hfs_btree *tree; struct hfs_btree_header_rec *head; struct address_space *mapping; - struct page *page; +struct page *page; +struct buffer_head *bh; unsigned int size; +u16 dblock; tree = kzalloc(sizeof(*tree), GFP_KERNEL); if (!tree) @@ -75,12 +77,22 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp ke unlock_new_inode(tree->inode); mapping = tree->inode->i_mapping; - page = read_mapping_page(mapping, 0, NULL); - if (IS_ERR(page)) +page = read_mapping_page(mapping, 0, NULL); +if (IS_ERR(page)) goto free_inode; +dblock = hfs_ext_find_block(HFS_I(tree->inode)->first_extents, 0); +bh = sb_bread(sb, HFS_SB(sb)->fs_start + dblock); +if (!bh) { +pr_err("unable to read tree header\n"); +goto put_page; +} + +memcpy(kmap_local_page(page), bh->b_data, sb->s_blocksize); +brelse(bh); + /* Load the header */ - head = (struct hfs_btree_header_rec *)(kmap_local_page(page) + +head = (struct hfs_btree_header_rec *)(kmap_local_page(page) + sizeof(struct hfs_bnode_desc)); tree->root = be32_to_cpu(head->root); tree->leaf_count = be32_to_cpu(head->leaf_count); @@ -95,22 +107,22 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp ke size = tree->node_size; if (!is_power_of_2(size)) - goto fail_page; +goto fail_page; if (!tree->node_count) - goto fail_page; +goto fail_page; switch (id) { case HFS_EXT_CNID: if (tree->max_key_len != HFS_MAX_EXT_KEYLEN) { pr_err("invalid extent max_key_len %d\n", tree->max_key_len); - goto fail_page; +goto fail_page; } break; case HFS_CAT_CNID: if (tree->max_key_len != HFS_MAX_CAT_KEYLEN) { pr_err("invalid catalog max_key_len %d\n", tree->max_key_len); - goto fail_page; +goto fail_page; } break; default: @@ -121,12 +133,13 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp ke tree->pages_per_bnode = (tree->node_size + PAGE_SIZE - 1) >> PAGE_SHIFT; kunmap_local(head); - put_page(page); +put_page(page); return tree; fail_page: kunmap_local(head); - put_page(page); +put_page(page); +put_page: free_inode: tree->inode->i_mapping->a_ops = &hfs_aops; iput(tree->inode); --- a/fs/hfs/extent.c +++ b/fs/hfs/extent.c @@ -71,7 +71,7 @@ int hfs_ext_keycmp(const btree_key *key1, const btree_key *key2) * * Find a block within an extent record */ -static u16 hfs_ext_find_block(struct hfs_extent *ext, u16 off) +u16 hfs_ext_find_block(struct hfs_extent *ext, u16 off) { int i; u16 count; --- a/fs/hfs/hfs_fs.h +++ b/fs/hfs/hfs_fs.h @@ -190,6 +190,7 @@ extern const struct inode_operations hfs_dir_inode_operations; /* extent.c */ extern int hfs_ext_keycmp(const btree_key *, const btree_key *); +extern u16 hfs_ext_find_block(struct hfs_extent *ext, u16 off); extern int hfs_free_fork(struct super_block *, struct hfs_cat_file *, int); extern int hfs_ext_write_extent(struct inode *); extern int hfs_extend_file(struct inode *);