aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2010-04-02 09:20:18 -0400
committerChris Mason <chris.mason@oracle.com>2010-04-05 14:42:01 -0400
commit109f6aef5fc436f355ad027f4d97bd696df2049a (patch)
tree645cf1752f2c62579f6dfe028d8a5d918c6b6f45
parent6bdb72ded1e281cd8844918c39d00cdd0e59f655 (diff)
Btrfs: add check for changed leaves in setup_leaf_for_split
setup_leaf_for_split needs to drop the path and search again, and has checks to see if the item we want to split changed size. But, it misses the case where the leaf changed and now has enough room for the item we want to insert. This adds an extra check to make sure the leaf really needs splitting before we call btrfs_split_leaf(), which keeps us from trying to split a leaf with a single item. btrfs_split_leaf() will blindly split the single item leaf, leaving us with one good leaf and one empty leaf and then a crash. Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r--fs/btrfs/ctree.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index c4bc570a396e..babf7fbaec84 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -3040,6 +3040,10 @@ static noinline int setup_leaf_for_split(struct btrfs_trans_handle *trans,
3040 if (ret > 0 || item_size != btrfs_item_size_nr(leaf, path->slots[0])) 3040 if (ret > 0 || item_size != btrfs_item_size_nr(leaf, path->slots[0]))
3041 goto err; 3041 goto err;
3042 3042
3043 /* the leaf has changed, it now has room. return now */
3044 if (btrfs_leaf_free_space(root, path->nodes[0]) >= ins_len)
3045 goto err;
3046
3043 if (key.type == BTRFS_EXTENT_DATA_KEY) { 3047 if (key.type == BTRFS_EXTENT_DATA_KEY) {
3044 fi = btrfs_item_ptr(leaf, path->slots[0], 3048 fi = btrfs_item_ptr(leaf, path->slots[0],
3045 struct btrfs_file_extent_item); 3049 struct btrfs_file_extent_item);