diff options
author | Chris Mason <chris.mason@oracle.com> | 2010-04-02 09:20:18 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2010-04-05 14:42:01 -0400 |
commit | 109f6aef5fc436f355ad027f4d97bd696df2049a (patch) | |
tree | 645cf1752f2c62579f6dfe028d8a5d918c6b6f45 | |
parent | 6bdb72ded1e281cd8844918c39d00cdd0e59f655 (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.c | 4 |
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); |