diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c index f8b5a8ae58ff..5a3e22006b76 100644 --- a/fs/hfsplus/bnode.c +++ b/fs/hfsplus/bnode.c @@ -598,12 +598,23 @@ struct hfs_bnode *hfs_bnode_find(struct hfs_btree *tree, u32 num) if (key_size >= entry_size || key_size & 1) goto node_error; } - clear_bit(HFS_BNODE_NEW, &node->flags); - wake_up(&node->lock_wq); + if (num != HFSPLUS_TREE_HEAD) { + clear_bit(HFS_BNODE_NEW, &node->flags); + wake_up(&node->lock_wq); + } return node; node_error: set_bit(HFS_BNODE_ERROR, &node->flags); + if (test_bit(HFS_BNODE_NEW, &node->flags)) { + if (num == HFSPLUS_TREE_HEAD) { + spin_lock(&tree->hash_lock); + hfs_bnode_unhash(node); + hfs_bnode_free(node); + spin_unlock(&tree->hash_lock); + return ERR_PTR(-EIO); + } + } clear_bit(HFS_BNODE_NEW, &node->flags); wake_up(&node->lock_wq); hfs_bnode_put(node); diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c index 394542a47e60..27ec484c3822 100644 --- a/fs/hfsplus/btree.c +++ b/fs/hfsplus/btree.c @@ -392,7 +392,14 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id) sb->s_flags |= SB_RDONLY; } - hfs_bnode_put(node); + if (test_bit(HFS_BNODE_NEW, &node->flags)) { + spin_lock(&tree->hash_lock); + hfs_bnode_unhash(node); + hfs_bnode_free(node); + spin_unlock(&tree->hash_lock); + } + else + hfs_bnode_put(node); return tree;