diff options
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r-- | fs/btrfs/ctree.c | 228 |
1 files changed, 138 insertions, 90 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 6f467901246f..50aea8cb653a 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -125,7 +125,6 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans, | |||
125 | u32 nritems; | 125 | u32 nritems; |
126 | int ret = 0; | 126 | int ret = 0; |
127 | int level; | 127 | int level; |
128 | struct btrfs_key first_key; | ||
129 | struct btrfs_root *new_root; | 128 | struct btrfs_root *new_root; |
130 | 129 | ||
131 | new_root = kmalloc(sizeof(*new_root), GFP_NOFS); | 130 | new_root = kmalloc(sizeof(*new_root), GFP_NOFS); |
@@ -141,18 +140,10 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans, | |||
141 | 140 | ||
142 | level = btrfs_header_level(buf); | 141 | level = btrfs_header_level(buf); |
143 | nritems = btrfs_header_nritems(buf); | 142 | nritems = btrfs_header_nritems(buf); |
144 | if (nritems) { | 143 | |
145 | if (level == 0) | 144 | cow = btrfs_alloc_free_block(trans, new_root, buf->len, 0, |
146 | btrfs_item_key_to_cpu(buf, &first_key, 0); | 145 | new_root_objectid, trans->transid, |
147 | else | 146 | level, buf->start, 0); |
148 | btrfs_node_key_to_cpu(buf, &first_key, 0); | ||
149 | } else { | ||
150 | first_key.objectid = 0; | ||
151 | } | ||
152 | cow = btrfs_alloc_free_block(trans, new_root, buf->len, | ||
153 | new_root_objectid, | ||
154 | trans->transid, first_key.objectid, | ||
155 | level, buf->start, 0); | ||
156 | if (IS_ERR(cow)) { | 147 | if (IS_ERR(cow)) { |
157 | kfree(new_root); | 148 | kfree(new_root); |
158 | return PTR_ERR(cow); | 149 | return PTR_ERR(cow); |
@@ -165,7 +156,7 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans, | |||
165 | btrfs_clear_header_flag(cow, BTRFS_HEADER_FLAG_WRITTEN); | 156 | btrfs_clear_header_flag(cow, BTRFS_HEADER_FLAG_WRITTEN); |
166 | 157 | ||
167 | WARN_ON(btrfs_header_generation(buf) > trans->transid); | 158 | WARN_ON(btrfs_header_generation(buf) > trans->transid); |
168 | ret = btrfs_inc_ref(trans, new_root, buf, 0); | 159 | ret = btrfs_inc_ref(trans, new_root, buf, cow, NULL); |
169 | kfree(new_root); | 160 | kfree(new_root); |
170 | 161 | ||
171 | if (ret) | 162 | if (ret) |
@@ -184,39 +175,31 @@ int noinline __btrfs_cow_block(struct btrfs_trans_handle *trans, | |||
184 | u64 search_start, u64 empty_size, | 175 | u64 search_start, u64 empty_size, |
185 | u64 prealloc_dest) | 176 | u64 prealloc_dest) |
186 | { | 177 | { |
187 | u64 root_gen; | 178 | u64 parent_start; |
188 | struct extent_buffer *cow; | 179 | struct extent_buffer *cow; |
189 | u32 nritems; | 180 | u32 nritems; |
190 | int ret = 0; | 181 | int ret = 0; |
191 | int different_trans = 0; | 182 | int different_trans = 0; |
192 | int level; | 183 | int level; |
193 | int unlock_orig = 0; | 184 | int unlock_orig = 0; |
194 | struct btrfs_key first_key; | ||
195 | 185 | ||
196 | if (*cow_ret == buf) | 186 | if (*cow_ret == buf) |
197 | unlock_orig = 1; | 187 | unlock_orig = 1; |
198 | 188 | ||
199 | WARN_ON(!btrfs_tree_locked(buf)); | 189 | WARN_ON(!btrfs_tree_locked(buf)); |
200 | 190 | ||
201 | if (root->ref_cows) { | 191 | if (parent) |
202 | root_gen = trans->transid; | 192 | parent_start = parent->start; |
203 | } else { | 193 | else |
204 | root_gen = 0; | 194 | parent_start = 0; |
205 | } | 195 | |
206 | WARN_ON(root->ref_cows && trans->transid != | 196 | WARN_ON(root->ref_cows && trans->transid != |
207 | root->fs_info->running_transaction->transid); | 197 | root->fs_info->running_transaction->transid); |
208 | WARN_ON(root->ref_cows && trans->transid != root->last_trans); | 198 | WARN_ON(root->ref_cows && trans->transid != root->last_trans); |
209 | 199 | ||
210 | level = btrfs_header_level(buf); | 200 | level = btrfs_header_level(buf); |
211 | nritems = btrfs_header_nritems(buf); | 201 | nritems = btrfs_header_nritems(buf); |
212 | if (nritems) { | 202 | |
213 | if (level == 0) | ||
214 | btrfs_item_key_to_cpu(buf, &first_key, 0); | ||
215 | else | ||
216 | btrfs_node_key_to_cpu(buf, &first_key, 0); | ||
217 | } else { | ||
218 | first_key.objectid = 0; | ||
219 | } | ||
220 | if (prealloc_dest) { | 203 | if (prealloc_dest) { |
221 | struct btrfs_key ins; | 204 | struct btrfs_key ins; |
222 | 205 | ||
@@ -224,19 +207,19 @@ int noinline __btrfs_cow_block(struct btrfs_trans_handle *trans, | |||
224 | ins.offset = buf->len; | 207 | ins.offset = buf->len; |
225 | ins.type = BTRFS_EXTENT_ITEM_KEY; | 208 | ins.type = BTRFS_EXTENT_ITEM_KEY; |
226 | 209 | ||
227 | ret = btrfs_alloc_reserved_extent(trans, root, | 210 | ret = btrfs_alloc_reserved_extent(trans, root, parent_start, |
228 | root->root_key.objectid, | 211 | root->root_key.objectid, |
229 | root_gen, level, | 212 | trans->transid, level, 0, |
230 | first_key.objectid, | ||
231 | &ins); | 213 | &ins); |
232 | BUG_ON(ret); | 214 | BUG_ON(ret); |
233 | cow = btrfs_init_new_buffer(trans, root, prealloc_dest, | 215 | cow = btrfs_init_new_buffer(trans, root, prealloc_dest, |
234 | buf->len); | 216 | buf->len); |
235 | } else { | 217 | } else { |
236 | cow = btrfs_alloc_free_block(trans, root, buf->len, | 218 | cow = btrfs_alloc_free_block(trans, root, buf->len, |
219 | parent_start, | ||
237 | root->root_key.objectid, | 220 | root->root_key.objectid, |
238 | root_gen, first_key.objectid, | 221 | trans->transid, level, |
239 | level, search_start, empty_size); | 222 | search_start, empty_size); |
240 | } | 223 | } |
241 | if (IS_ERR(cow)) | 224 | if (IS_ERR(cow)) |
242 | return PTR_ERR(cow); | 225 | return PTR_ERR(cow); |
@@ -249,17 +232,23 @@ int noinline __btrfs_cow_block(struct btrfs_trans_handle *trans, | |||
249 | 232 | ||
250 | WARN_ON(btrfs_header_generation(buf) > trans->transid); | 233 | WARN_ON(btrfs_header_generation(buf) > trans->transid); |
251 | if (btrfs_header_generation(buf) != trans->transid) { | 234 | if (btrfs_header_generation(buf) != trans->transid) { |
235 | u32 nr_extents; | ||
252 | different_trans = 1; | 236 | different_trans = 1; |
253 | ret = btrfs_inc_ref(trans, root, buf, 1); | 237 | ret = btrfs_inc_ref(trans, root, buf, cow, &nr_extents); |
254 | if (ret) | 238 | if (ret) |
255 | return ret; | 239 | return ret; |
240 | |||
241 | ret = btrfs_cache_ref(trans, root, buf, nr_extents); | ||
242 | WARN_ON(ret); | ||
256 | } else { | 243 | } else { |
244 | ret = btrfs_update_ref(trans, root, buf, cow, 0, nritems); | ||
245 | if (ret) | ||
246 | return ret; | ||
257 | clean_tree_block(trans, root, buf); | 247 | clean_tree_block(trans, root, buf); |
258 | } | 248 | } |
259 | 249 | ||
260 | if (buf == root->node) { | 250 | if (buf == root->node) { |
261 | WARN_ON(parent && parent != buf); | 251 | WARN_ON(parent && parent != buf); |
262 | root_gen = btrfs_header_generation(buf); | ||
263 | 252 | ||
264 | spin_lock(&root->node_lock); | 253 | spin_lock(&root->node_lock); |
265 | root->node = cow; | 254 | root->node = cow; |
@@ -268,13 +257,14 @@ int noinline __btrfs_cow_block(struct btrfs_trans_handle *trans, | |||
268 | 257 | ||
269 | if (buf != root->commit_root) { | 258 | if (buf != root->commit_root) { |
270 | btrfs_free_extent(trans, root, buf->start, | 259 | btrfs_free_extent(trans, root, buf->start, |
271 | buf->len, root->root_key.objectid, | 260 | buf->len, buf->start, |
272 | root_gen, 0, 0, 1); | 261 | root->root_key.objectid, |
262 | btrfs_header_generation(buf), | ||
263 | 0, 0, 1); | ||
273 | } | 264 | } |
274 | free_extent_buffer(buf); | 265 | free_extent_buffer(buf); |
275 | add_root_to_dirty_list(root); | 266 | add_root_to_dirty_list(root); |
276 | } else { | 267 | } else { |
277 | root_gen = btrfs_header_generation(parent); | ||
278 | btrfs_set_node_blockptr(parent, parent_slot, | 268 | btrfs_set_node_blockptr(parent, parent_slot, |
279 | cow->start); | 269 | cow->start); |
280 | WARN_ON(trans->transid == 0); | 270 | WARN_ON(trans->transid == 0); |
@@ -283,8 +273,8 @@ int noinline __btrfs_cow_block(struct btrfs_trans_handle *trans, | |||
283 | btrfs_mark_buffer_dirty(parent); | 273 | btrfs_mark_buffer_dirty(parent); |
284 | WARN_ON(btrfs_header_generation(parent) != trans->transid); | 274 | WARN_ON(btrfs_header_generation(parent) != trans->transid); |
285 | btrfs_free_extent(trans, root, buf->start, buf->len, | 275 | btrfs_free_extent(trans, root, buf->start, buf->len, |
286 | btrfs_header_owner(parent), root_gen, | 276 | parent_start, btrfs_header_owner(parent), |
287 | 0, 0, 1); | 277 | btrfs_header_generation(parent), 0, 0, 1); |
288 | } | 278 | } |
289 | if (unlock_orig) | 279 | if (unlock_orig) |
290 | btrfs_tree_unlock(buf); | 280 | btrfs_tree_unlock(buf); |
@@ -831,6 +821,12 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, | |||
831 | root->node = child; | 821 | root->node = child; |
832 | spin_unlock(&root->node_lock); | 822 | spin_unlock(&root->node_lock); |
833 | 823 | ||
824 | ret = btrfs_update_extent_ref(trans, root, child->start, | ||
825 | mid->start, child->start, | ||
826 | root->root_key.objectid, | ||
827 | trans->transid, level - 1, 0); | ||
828 | BUG_ON(ret); | ||
829 | |||
834 | add_root_to_dirty_list(root); | 830 | add_root_to_dirty_list(root); |
835 | btrfs_tree_unlock(child); | 831 | btrfs_tree_unlock(child); |
836 | path->locks[level] = 0; | 832 | path->locks[level] = 0; |
@@ -840,7 +836,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, | |||
840 | /* once for the path */ | 836 | /* once for the path */ |
841 | free_extent_buffer(mid); | 837 | free_extent_buffer(mid); |
842 | ret = btrfs_free_extent(trans, root, mid->start, mid->len, | 838 | ret = btrfs_free_extent(trans, root, mid->start, mid->len, |
843 | root->root_key.objectid, | 839 | mid->start, root->root_key.objectid, |
844 | btrfs_header_generation(mid), 0, 0, 1); | 840 | btrfs_header_generation(mid), 0, 0, 1); |
845 | /* once for the root ptr */ | 841 | /* once for the root ptr */ |
846 | free_extent_buffer(mid); | 842 | free_extent_buffer(mid); |
@@ -905,7 +901,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, | |||
905 | if (wret) | 901 | if (wret) |
906 | ret = wret; | 902 | ret = wret; |
907 | wret = btrfs_free_extent(trans, root, bytenr, | 903 | wret = btrfs_free_extent(trans, root, bytenr, |
908 | blocksize, | 904 | blocksize, parent->start, |
909 | btrfs_header_owner(parent), | 905 | btrfs_header_owner(parent), |
910 | generation, 0, 0, 1); | 906 | generation, 0, 0, 1); |
911 | if (wret) | 907 | if (wret) |
@@ -954,6 +950,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, | |||
954 | if (wret) | 950 | if (wret) |
955 | ret = wret; | 951 | ret = wret; |
956 | wret = btrfs_free_extent(trans, root, bytenr, blocksize, | 952 | wret = btrfs_free_extent(trans, root, bytenr, blocksize, |
953 | parent->start, | ||
957 | btrfs_header_owner(parent), | 954 | btrfs_header_owner(parent), |
958 | root_gen, 0, 0, 1); | 955 | root_gen, 0, 0, 1); |
959 | if (wret) | 956 | if (wret) |
@@ -1500,6 +1497,41 @@ static int fixup_low_keys(struct btrfs_trans_handle *trans, | |||
1500 | } | 1497 | } |
1501 | 1498 | ||
1502 | /* | 1499 | /* |
1500 | * update item key. | ||
1501 | * | ||
1502 | * This function isn't completely safe. It's the caller's responsibility | ||
1503 | * that the new key won't break the order | ||
1504 | */ | ||
1505 | int btrfs_set_item_key_safe(struct btrfs_trans_handle *trans, | ||
1506 | struct btrfs_root *root, struct btrfs_path *path, | ||
1507 | struct btrfs_key *new_key) | ||
1508 | { | ||
1509 | struct btrfs_disk_key disk_key; | ||
1510 | struct extent_buffer *eb; | ||
1511 | int slot; | ||
1512 | |||
1513 | eb = path->nodes[0]; | ||
1514 | slot = path->slots[0]; | ||
1515 | if (slot > 0) { | ||
1516 | btrfs_item_key(eb, &disk_key, slot - 1); | ||
1517 | if (comp_keys(&disk_key, new_key) >= 0) | ||
1518 | return -1; | ||
1519 | } | ||
1520 | if (slot < btrfs_header_nritems(eb) - 1) { | ||
1521 | btrfs_item_key(eb, &disk_key, slot + 1); | ||
1522 | if (comp_keys(&disk_key, new_key) <= 0) | ||
1523 | return -1; | ||
1524 | } | ||
1525 | |||
1526 | btrfs_cpu_key_to_disk(&disk_key, new_key); | ||
1527 | btrfs_set_item_key(eb, &disk_key, slot); | ||
1528 | btrfs_mark_buffer_dirty(eb); | ||
1529 | if (slot == 0) | ||
1530 | fixup_low_keys(trans, root, path, &disk_key, 1); | ||
1531 | return 0; | ||
1532 | } | ||
1533 | |||
1534 | /* | ||
1503 | * try to push data from one node into the next node left in the | 1535 | * try to push data from one node into the next node left in the |
1504 | * tree. | 1536 | * tree. |
1505 | * | 1537 | * |
@@ -1558,6 +1590,10 @@ static int push_node_left(struct btrfs_trans_handle *trans, | |||
1558 | btrfs_set_header_nritems(dst, dst_nritems + push_items); | 1590 | btrfs_set_header_nritems(dst, dst_nritems + push_items); |
1559 | btrfs_mark_buffer_dirty(src); | 1591 | btrfs_mark_buffer_dirty(src); |
1560 | btrfs_mark_buffer_dirty(dst); | 1592 | btrfs_mark_buffer_dirty(dst); |
1593 | |||
1594 | ret = btrfs_update_ref(trans, root, src, dst, dst_nritems, push_items); | ||
1595 | BUG_ON(ret); | ||
1596 | |||
1561 | return ret; | 1597 | return ret; |
1562 | } | 1598 | } |
1563 | 1599 | ||
@@ -1619,6 +1655,10 @@ static int balance_node_right(struct btrfs_trans_handle *trans, | |||
1619 | 1655 | ||
1620 | btrfs_mark_buffer_dirty(src); | 1656 | btrfs_mark_buffer_dirty(src); |
1621 | btrfs_mark_buffer_dirty(dst); | 1657 | btrfs_mark_buffer_dirty(dst); |
1658 | |||
1659 | ret = btrfs_update_ref(trans, root, src, dst, 0, push_items); | ||
1660 | BUG_ON(ret); | ||
1661 | |||
1622 | return ret; | 1662 | return ret; |
1623 | } | 1663 | } |
1624 | 1664 | ||
@@ -1633,30 +1673,24 @@ static int noinline insert_new_root(struct btrfs_trans_handle *trans, | |||
1633 | struct btrfs_root *root, | 1673 | struct btrfs_root *root, |
1634 | struct btrfs_path *path, int level) | 1674 | struct btrfs_path *path, int level) |
1635 | { | 1675 | { |
1636 | u64 root_gen; | ||
1637 | u64 lower_gen; | 1676 | u64 lower_gen; |
1638 | struct extent_buffer *lower; | 1677 | struct extent_buffer *lower; |
1639 | struct extent_buffer *c; | 1678 | struct extent_buffer *c; |
1640 | struct extent_buffer *old; | 1679 | struct extent_buffer *old; |
1641 | struct btrfs_disk_key lower_key; | 1680 | struct btrfs_disk_key lower_key; |
1681 | int ret; | ||
1642 | 1682 | ||
1643 | BUG_ON(path->nodes[level]); | 1683 | BUG_ON(path->nodes[level]); |
1644 | BUG_ON(path->nodes[level-1] != root->node); | 1684 | BUG_ON(path->nodes[level-1] != root->node); |
1645 | 1685 | ||
1646 | if (root->ref_cows) | ||
1647 | root_gen = trans->transid; | ||
1648 | else | ||
1649 | root_gen = 0; | ||
1650 | |||
1651 | lower = path->nodes[level-1]; | 1686 | lower = path->nodes[level-1]; |
1652 | if (level == 1) | 1687 | if (level == 1) |
1653 | btrfs_item_key(lower, &lower_key, 0); | 1688 | btrfs_item_key(lower, &lower_key, 0); |
1654 | else | 1689 | else |
1655 | btrfs_node_key(lower, &lower_key, 0); | 1690 | btrfs_node_key(lower, &lower_key, 0); |
1656 | 1691 | ||
1657 | c = btrfs_alloc_free_block(trans, root, root->nodesize, | 1692 | c = btrfs_alloc_free_block(trans, root, root->nodesize, 0, |
1658 | root->root_key.objectid, | 1693 | root->root_key.objectid, trans->transid, |
1659 | root_gen, le64_to_cpu(lower_key.objectid), | ||
1660 | level, root->node->start, 0); | 1694 | level, root->node->start, 0); |
1661 | if (IS_ERR(c)) | 1695 | if (IS_ERR(c)) |
1662 | return PTR_ERR(c); | 1696 | return PTR_ERR(c); |
@@ -1679,7 +1713,7 @@ static int noinline insert_new_root(struct btrfs_trans_handle *trans, | |||
1679 | btrfs_set_node_key(c, &lower_key, 0); | 1713 | btrfs_set_node_key(c, &lower_key, 0); |
1680 | btrfs_set_node_blockptr(c, 0, lower->start); | 1714 | btrfs_set_node_blockptr(c, 0, lower->start); |
1681 | lower_gen = btrfs_header_generation(lower); | 1715 | lower_gen = btrfs_header_generation(lower); |
1682 | WARN_ON(lower_gen == 0); | 1716 | WARN_ON(lower_gen != trans->transid); |
1683 | 1717 | ||
1684 | btrfs_set_node_ptr_generation(c, 0, lower_gen); | 1718 | btrfs_set_node_ptr_generation(c, 0, lower_gen); |
1685 | 1719 | ||
@@ -1690,6 +1724,12 @@ static int noinline insert_new_root(struct btrfs_trans_handle *trans, | |||
1690 | root->node = c; | 1724 | root->node = c; |
1691 | spin_unlock(&root->node_lock); | 1725 | spin_unlock(&root->node_lock); |
1692 | 1726 | ||
1727 | ret = btrfs_update_extent_ref(trans, root, lower->start, | ||
1728 | lower->start, c->start, | ||
1729 | root->root_key.objectid, | ||
1730 | trans->transid, level - 1, 0); | ||
1731 | BUG_ON(ret); | ||
1732 | |||
1693 | /* the super has an extra ref to root->node */ | 1733 | /* the super has an extra ref to root->node */ |
1694 | free_extent_buffer(old); | 1734 | free_extent_buffer(old); |
1695 | 1735 | ||
@@ -1698,20 +1738,6 @@ static int noinline insert_new_root(struct btrfs_trans_handle *trans, | |||
1698 | path->nodes[level] = c; | 1738 | path->nodes[level] = c; |
1699 | path->locks[level] = 1; | 1739 | path->locks[level] = 1; |
1700 | path->slots[level] = 0; | 1740 | path->slots[level] = 0; |
1701 | |||
1702 | if (root->ref_cows && lower_gen != trans->transid) { | ||
1703 | struct btrfs_path *back_path = btrfs_alloc_path(); | ||
1704 | int ret; | ||
1705 | mutex_lock(&root->fs_info->alloc_mutex); | ||
1706 | ret = btrfs_insert_extent_backref(trans, | ||
1707 | root->fs_info->extent_root, | ||
1708 | path, lower->start, | ||
1709 | root->root_key.objectid, | ||
1710 | trans->transid, 0, 0); | ||
1711 | BUG_ON(ret); | ||
1712 | mutex_unlock(&root->fs_info->alloc_mutex); | ||
1713 | btrfs_free_path(back_path); | ||
1714 | } | ||
1715 | return 0; | 1741 | return 0; |
1716 | } | 1742 | } |
1717 | 1743 | ||
@@ -1766,7 +1792,6 @@ static noinline int split_node(struct btrfs_trans_handle *trans, | |||
1766 | struct btrfs_root *root, | 1792 | struct btrfs_root *root, |
1767 | struct btrfs_path *path, int level) | 1793 | struct btrfs_path *path, int level) |
1768 | { | 1794 | { |
1769 | u64 root_gen; | ||
1770 | struct extent_buffer *c; | 1795 | struct extent_buffer *c; |
1771 | struct extent_buffer *split; | 1796 | struct extent_buffer *split; |
1772 | struct btrfs_disk_key disk_key; | 1797 | struct btrfs_disk_key disk_key; |
@@ -1793,17 +1818,11 @@ static noinline int split_node(struct btrfs_trans_handle *trans, | |||
1793 | } | 1818 | } |
1794 | 1819 | ||
1795 | c_nritems = btrfs_header_nritems(c); | 1820 | c_nritems = btrfs_header_nritems(c); |
1796 | if (root->ref_cows) | ||
1797 | root_gen = trans->transid; | ||
1798 | else | ||
1799 | root_gen = 0; | ||
1800 | 1821 | ||
1801 | btrfs_node_key(c, &disk_key, 0); | ||
1802 | split = btrfs_alloc_free_block(trans, root, root->nodesize, | 1822 | split = btrfs_alloc_free_block(trans, root, root->nodesize, |
1803 | root->root_key.objectid, | 1823 | path->nodes[level + 1]->start, |
1804 | root_gen, | 1824 | root->root_key.objectid, |
1805 | btrfs_disk_key_objectid(&disk_key), | 1825 | trans->transid, level, c->start, 0); |
1806 | level, c->start, 0); | ||
1807 | if (IS_ERR(split)) | 1826 | if (IS_ERR(split)) |
1808 | return PTR_ERR(split); | 1827 | return PTR_ERR(split); |
1809 | 1828 | ||
@@ -1840,6 +1859,9 @@ static noinline int split_node(struct btrfs_trans_handle *trans, | |||
1840 | if (wret) | 1859 | if (wret) |
1841 | ret = wret; | 1860 | ret = wret; |
1842 | 1861 | ||
1862 | ret = btrfs_update_ref(trans, root, c, split, 0, c_nritems - mid); | ||
1863 | BUG_ON(ret); | ||
1864 | |||
1843 | if (path->slots[level] >= mid) { | 1865 | if (path->slots[level] >= mid) { |
1844 | path->slots[level] -= mid; | 1866 | path->slots[level] -= mid; |
1845 | btrfs_tree_unlock(c); | 1867 | btrfs_tree_unlock(c); |
@@ -1955,10 +1977,23 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1955 | else | 1977 | else |
1956 | nr = 1; | 1978 | nr = 1; |
1957 | 1979 | ||
1980 | if (path->slots[0] >= left_nritems) | ||
1981 | push_space += data_size + sizeof(*item); | ||
1982 | |||
1958 | i = left_nritems - 1; | 1983 | i = left_nritems - 1; |
1959 | while (i >= nr) { | 1984 | while (i >= nr) { |
1960 | item = btrfs_item_nr(left, i); | 1985 | item = btrfs_item_nr(left, i); |
1961 | 1986 | ||
1987 | if (!empty && push_items > 0) { | ||
1988 | if (path->slots[0] > i) | ||
1989 | break; | ||
1990 | if (path->slots[0] == i) { | ||
1991 | int space = btrfs_leaf_free_space(root, left); | ||
1992 | if (space + push_space * 2 > free_space) | ||
1993 | break; | ||
1994 | } | ||
1995 | } | ||
1996 | |||
1962 | if (path->slots[0] == i) | 1997 | if (path->slots[0] == i) |
1963 | push_space += data_size + sizeof(*item); | 1998 | push_space += data_size + sizeof(*item); |
1964 | 1999 | ||
@@ -1973,6 +2008,7 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1973 | this_item_size = btrfs_item_size(left, item); | 2008 | this_item_size = btrfs_item_size(left, item); |
1974 | if (this_item_size + sizeof(*item) + push_space > free_space) | 2009 | if (this_item_size + sizeof(*item) + push_space > free_space) |
1975 | break; | 2010 | break; |
2011 | |||
1976 | push_items++; | 2012 | push_items++; |
1977 | push_space += this_item_size + sizeof(*item); | 2013 | push_space += this_item_size + sizeof(*item); |
1978 | if (i == 0) | 2014 | if (i == 0) |
@@ -2046,6 +2082,9 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root | |||
2046 | btrfs_mark_buffer_dirty(left); | 2082 | btrfs_mark_buffer_dirty(left); |
2047 | btrfs_mark_buffer_dirty(right); | 2083 | btrfs_mark_buffer_dirty(right); |
2048 | 2084 | ||
2085 | ret = btrfs_update_ref(trans, root, left, right, 0, push_items); | ||
2086 | BUG_ON(ret); | ||
2087 | |||
2049 | btrfs_item_key(right, &disk_key, 0); | 2088 | btrfs_item_key(right, &disk_key, 0); |
2050 | btrfs_set_node_key(upper, &disk_key, slot + 1); | 2089 | btrfs_set_node_key(upper, &disk_key, slot + 1); |
2051 | btrfs_mark_buffer_dirty(upper); | 2090 | btrfs_mark_buffer_dirty(upper); |
@@ -2147,6 +2186,16 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
2147 | KM_USER1); | 2186 | KM_USER1); |
2148 | } | 2187 | } |
2149 | 2188 | ||
2189 | if (!empty && push_items > 0) { | ||
2190 | if (path->slots[0] < i) | ||
2191 | break; | ||
2192 | if (path->slots[0] == i) { | ||
2193 | int space = btrfs_leaf_free_space(root, right); | ||
2194 | if (space + push_space * 2 > free_space) | ||
2195 | break; | ||
2196 | } | ||
2197 | } | ||
2198 | |||
2150 | if (path->slots[0] == i) | 2199 | if (path->slots[0] == i) |
2151 | push_space += data_size + sizeof(*item); | 2200 | push_space += data_size + sizeof(*item); |
2152 | 2201 | ||
@@ -2255,6 +2304,10 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
2255 | if (right_nritems) | 2304 | if (right_nritems) |
2256 | btrfs_mark_buffer_dirty(right); | 2305 | btrfs_mark_buffer_dirty(right); |
2257 | 2306 | ||
2307 | ret = btrfs_update_ref(trans, root, right, left, | ||
2308 | old_left_nritems, push_items); | ||
2309 | BUG_ON(ret); | ||
2310 | |||
2258 | btrfs_item_key(right, &disk_key, 0); | 2311 | btrfs_item_key(right, &disk_key, 0); |
2259 | wret = fixup_low_keys(trans, root, path, &disk_key, 1); | 2312 | wret = fixup_low_keys(trans, root, path, &disk_key, 1); |
2260 | if (wret) | 2313 | if (wret) |
@@ -2294,7 +2347,6 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans, | |||
2294 | struct btrfs_path *path, int data_size, | 2347 | struct btrfs_path *path, int data_size, |
2295 | int extend) | 2348 | int extend) |
2296 | { | 2349 | { |
2297 | u64 root_gen; | ||
2298 | struct extent_buffer *l; | 2350 | struct extent_buffer *l; |
2299 | u32 nritems; | 2351 | u32 nritems; |
2300 | int mid; | 2352 | int mid; |
@@ -2313,11 +2365,6 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans, | |||
2313 | if (extend) | 2365 | if (extend) |
2314 | space_needed = data_size; | 2366 | space_needed = data_size; |
2315 | 2367 | ||
2316 | if (root->ref_cows) | ||
2317 | root_gen = trans->transid; | ||
2318 | else | ||
2319 | root_gen = 0; | ||
2320 | |||
2321 | /* first try to make some room by pushing left and right */ | 2368 | /* first try to make some room by pushing left and right */ |
2322 | if (ins_key->type != BTRFS_DIR_ITEM_KEY) { | 2369 | if (ins_key->type != BTRFS_DIR_ITEM_KEY) { |
2323 | wret = push_leaf_right(trans, root, path, data_size, 0); | 2370 | wret = push_leaf_right(trans, root, path, data_size, 0); |
@@ -2348,13 +2395,10 @@ again: | |||
2348 | nritems = btrfs_header_nritems(l); | 2395 | nritems = btrfs_header_nritems(l); |
2349 | mid = (nritems + 1)/ 2; | 2396 | mid = (nritems + 1)/ 2; |
2350 | 2397 | ||
2351 | btrfs_item_key(l, &disk_key, 0); | ||
2352 | |||
2353 | right = btrfs_alloc_free_block(trans, root, root->leafsize, | 2398 | right = btrfs_alloc_free_block(trans, root, root->leafsize, |
2354 | root->root_key.objectid, | 2399 | path->nodes[1]->start, |
2355 | root_gen, | 2400 | root->root_key.objectid, |
2356 | le64_to_cpu(disk_key.objectid), | 2401 | trans->transid, 0, l->start, 0); |
2357 | 0, l->start, 0); | ||
2358 | if (IS_ERR(right)) { | 2402 | if (IS_ERR(right)) { |
2359 | BUG_ON(1); | 2403 | BUG_ON(1); |
2360 | return PTR_ERR(right); | 2404 | return PTR_ERR(right); |
@@ -2485,6 +2529,9 @@ again: | |||
2485 | btrfs_mark_buffer_dirty(l); | 2529 | btrfs_mark_buffer_dirty(l); |
2486 | BUG_ON(path->slots[0] != slot); | 2530 | BUG_ON(path->slots[0] != slot); |
2487 | 2531 | ||
2532 | ret = btrfs_update_ref(trans, root, l, right, 0, nritems); | ||
2533 | BUG_ON(ret); | ||
2534 | |||
2488 | if (mid <= slot) { | 2535 | if (mid <= slot) { |
2489 | btrfs_tree_unlock(path->nodes[0]); | 2536 | btrfs_tree_unlock(path->nodes[0]); |
2490 | free_extent_buffer(path->nodes[0]); | 2537 | free_extent_buffer(path->nodes[0]); |
@@ -2956,6 +3003,7 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
2956 | ret = wret; | 3003 | ret = wret; |
2957 | wret = btrfs_free_extent(trans, root, | 3004 | wret = btrfs_free_extent(trans, root, |
2958 | leaf->start, leaf->len, | 3005 | leaf->start, leaf->len, |
3006 | path->nodes[1]->start, | ||
2959 | btrfs_header_owner(path->nodes[1]), | 3007 | btrfs_header_owner(path->nodes[1]), |
2960 | root_gen, 0, 0, 1); | 3008 | root_gen, 0, 0, 1); |
2961 | if (wret) | 3009 | if (wret) |
@@ -3007,7 +3055,7 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
3007 | 3055 | ||
3008 | free_extent_buffer(leaf); | 3056 | free_extent_buffer(leaf); |
3009 | wret = btrfs_free_extent(trans, root, bytenr, | 3057 | wret = btrfs_free_extent(trans, root, bytenr, |
3010 | blocksize, | 3058 | blocksize, path->nodes[1]->start, |
3011 | btrfs_header_owner(path->nodes[1]), | 3059 | btrfs_header_owner(path->nodes[1]), |
3012 | root_gen, 0, 0, 1); | 3060 | root_gen, 0, 0, 1); |
3013 | if (wret) | 3061 | if (wret) |