diff options
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r-- | fs/btrfs/ctree.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index bef61ee883e1..f691542dfa15 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -1766,8 +1766,9 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1766 | 1766 | ||
1767 | /* first try to make some room by pushing left and right */ | 1767 | /* first try to make some room by pushing left and right */ |
1768 | wret = push_leaf_left(trans, root, path, data_size); | 1768 | wret = push_leaf_left(trans, root, path, data_size); |
1769 | if (wret < 0) | 1769 | if (wret < 0) { |
1770 | return wret; | 1770 | return wret; |
1771 | } | ||
1771 | if (wret) { | 1772 | if (wret) { |
1772 | wret = push_leaf_right(trans, root, path, data_size); | 1773 | wret = push_leaf_right(trans, root, path, data_size); |
1773 | if (wret < 0) | 1774 | if (wret < 0) |
@@ -1777,8 +1778,9 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1777 | 1778 | ||
1778 | /* did the pushes work? */ | 1779 | /* did the pushes work? */ |
1779 | if (btrfs_leaf_free_space(root, l) >= | 1780 | if (btrfs_leaf_free_space(root, l) >= |
1780 | sizeof(struct btrfs_item) + data_size) | 1781 | sizeof(struct btrfs_item) + data_size) { |
1781 | return 0; | 1782 | return 0; |
1783 | } | ||
1782 | 1784 | ||
1783 | if (!path->nodes[1]) { | 1785 | if (!path->nodes[1]) { |
1784 | ret = insert_new_root(trans, root, path, 1); | 1786 | ret = insert_new_root(trans, root, path, 1); |
@@ -1822,7 +1824,11 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1822 | return ret; | 1824 | return ret; |
1823 | } | 1825 | } |
1824 | mid = slot; | 1826 | mid = slot; |
1825 | double_split = 1; | 1827 | if (mid != nritems && |
1828 | leaf_space_used(l, mid, nritems - mid) + | ||
1829 | space_needed > BTRFS_LEAF_DATA_SIZE(root)) { | ||
1830 | double_split = 1; | ||
1831 | } | ||
1826 | } | 1832 | } |
1827 | } else { | 1833 | } else { |
1828 | if (leaf_space_used(l, 0, mid + 1) + space_needed > | 1834 | if (leaf_space_used(l, 0, mid + 1) + space_needed > |
@@ -1910,8 +1916,9 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1910 | 1916 | ||
1911 | BUG_ON(path->slots[0] < 0); | 1917 | BUG_ON(path->slots[0] < 0); |
1912 | 1918 | ||
1913 | if (!double_split) | 1919 | if (!double_split) { |
1914 | return ret; | 1920 | return ret; |
1921 | } | ||
1915 | 1922 | ||
1916 | right = btrfs_alloc_free_block(trans, root, root->leafsize, | 1923 | right = btrfs_alloc_free_block(trans, root, root->leafsize, |
1917 | l->start, 0); | 1924 | l->start, 0); |
@@ -2048,7 +2055,11 @@ int btrfs_extend_item(struct btrfs_trans_handle *trans, | |||
2048 | old_data = btrfs_item_end_nr(leaf, slot); | 2055 | old_data = btrfs_item_end_nr(leaf, slot); |
2049 | 2056 | ||
2050 | BUG_ON(slot < 0); | 2057 | BUG_ON(slot < 0); |
2051 | BUG_ON(slot >= nritems); | 2058 | if (slot >= nritems) { |
2059 | btrfs_print_leaf(root, leaf); | ||
2060 | printk("slot %d too large, nritems %d\n", slot, nritems); | ||
2061 | BUG_ON(1); | ||
2062 | } | ||
2052 | 2063 | ||
2053 | /* | 2064 | /* |
2054 | * item0..itemN ... dataN.offset..dataN.size .. data0.size | 2065 | * item0..itemN ... dataN.offset..dataN.size .. data0.size |
@@ -2132,6 +2143,9 @@ int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, | |||
2132 | 2143 | ||
2133 | if (btrfs_leaf_free_space(root, leaf) < | 2144 | if (btrfs_leaf_free_space(root, leaf) < |
2134 | sizeof(struct btrfs_item) + data_size) { | 2145 | sizeof(struct btrfs_item) + data_size) { |
2146 | btrfs_print_leaf(root, leaf); | ||
2147 | printk("not enough freespace need %u have %d\n", | ||
2148 | data_size, btrfs_leaf_free_space(root, leaf)); | ||
2135 | BUG(); | 2149 | BUG(); |
2136 | } | 2150 | } |
2137 | 2151 | ||