diff options
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r-- | fs/btrfs/ctree.c | 229 |
1 files changed, 182 insertions, 47 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index cdfb4c49a806..eea5da7a2b9a 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -38,8 +38,7 @@ static int balance_node_right(struct btrfs_trans_handle *trans, | |||
38 | struct extent_buffer *dst_buf, | 38 | struct extent_buffer *dst_buf, |
39 | struct extent_buffer *src_buf); | 39 | struct extent_buffer *src_buf); |
40 | static void del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 40 | static void del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
41 | struct btrfs_path *path, int level, int slot, | 41 | struct btrfs_path *path, int level, int slot); |
42 | int tree_mod_log); | ||
43 | static void tree_mod_log_free_eb(struct btrfs_fs_info *fs_info, | 42 | static void tree_mod_log_free_eb(struct btrfs_fs_info *fs_info, |
44 | struct extent_buffer *eb); | 43 | struct extent_buffer *eb); |
45 | struct extent_buffer *read_old_tree_block(struct btrfs_root *root, u64 bytenr, | 44 | struct extent_buffer *read_old_tree_block(struct btrfs_root *root, u64 bytenr, |
@@ -776,8 +775,7 @@ tree_mod_log_eb_move(struct btrfs_fs_info *fs_info, struct extent_buffer *dst, | |||
776 | 775 | ||
777 | static noinline void | 776 | static noinline void |
778 | tree_mod_log_set_node_key(struct btrfs_fs_info *fs_info, | 777 | tree_mod_log_set_node_key(struct btrfs_fs_info *fs_info, |
779 | struct extent_buffer *eb, | 778 | struct extent_buffer *eb, int slot, int atomic) |
780 | struct btrfs_disk_key *disk_key, int slot, int atomic) | ||
781 | { | 779 | { |
782 | int ret; | 780 | int ret; |
783 | 781 | ||
@@ -1361,19 +1359,16 @@ noinline int btrfs_cow_block(struct btrfs_trans_handle *trans, | |||
1361 | u64 search_start; | 1359 | u64 search_start; |
1362 | int ret; | 1360 | int ret; |
1363 | 1361 | ||
1364 | if (trans->transaction != root->fs_info->running_transaction) { | 1362 | if (trans->transaction != root->fs_info->running_transaction) |
1365 | printk(KERN_CRIT "trans %llu running %llu\n", | 1363 | WARN(1, KERN_CRIT "trans %llu running %llu\n", |
1366 | (unsigned long long)trans->transid, | 1364 | (unsigned long long)trans->transid, |
1367 | (unsigned long long) | 1365 | (unsigned long long) |
1368 | root->fs_info->running_transaction->transid); | 1366 | root->fs_info->running_transaction->transid); |
1369 | WARN_ON(1); | 1367 | |
1370 | } | 1368 | if (trans->transid != root->fs_info->generation) |
1371 | if (trans->transid != root->fs_info->generation) { | 1369 | WARN(1, KERN_CRIT "trans %llu running %llu\n", |
1372 | printk(KERN_CRIT "trans %llu running %llu\n", | ||
1373 | (unsigned long long)trans->transid, | 1370 | (unsigned long long)trans->transid, |
1374 | (unsigned long long)root->fs_info->generation); | 1371 | (unsigned long long)root->fs_info->generation); |
1375 | WARN_ON(1); | ||
1376 | } | ||
1377 | 1372 | ||
1378 | if (!should_cow_block(trans, root, buf)) { | 1373 | if (!should_cow_block(trans, root, buf)) { |
1379 | *cow_ret = buf; | 1374 | *cow_ret = buf; |
@@ -1469,10 +1464,8 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, | |||
1469 | if (cache_only && parent_level != 1) | 1464 | if (cache_only && parent_level != 1) |
1470 | return 0; | 1465 | return 0; |
1471 | 1466 | ||
1472 | if (trans->transaction != root->fs_info->running_transaction) | 1467 | WARN_ON(trans->transaction != root->fs_info->running_transaction); |
1473 | WARN_ON(1); | 1468 | WARN_ON(trans->transid != root->fs_info->generation); |
1474 | if (trans->transid != root->fs_info->generation) | ||
1475 | WARN_ON(1); | ||
1476 | 1469 | ||
1477 | parent_nritems = btrfs_header_nritems(parent); | 1470 | parent_nritems = btrfs_header_nritems(parent); |
1478 | blocksize = btrfs_level_size(root, parent_level - 1); | 1471 | blocksize = btrfs_level_size(root, parent_level - 1); |
@@ -1827,7 +1820,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, | |||
1827 | if (btrfs_header_nritems(right) == 0) { | 1820 | if (btrfs_header_nritems(right) == 0) { |
1828 | clean_tree_block(trans, root, right); | 1821 | clean_tree_block(trans, root, right); |
1829 | btrfs_tree_unlock(right); | 1822 | btrfs_tree_unlock(right); |
1830 | del_ptr(trans, root, path, level + 1, pslot + 1, 1); | 1823 | del_ptr(trans, root, path, level + 1, pslot + 1); |
1831 | root_sub_used(root, right->len); | 1824 | root_sub_used(root, right->len); |
1832 | btrfs_free_tree_block(trans, root, right, 0, 1); | 1825 | btrfs_free_tree_block(trans, root, right, 0, 1); |
1833 | free_extent_buffer_stale(right); | 1826 | free_extent_buffer_stale(right); |
@@ -1836,7 +1829,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, | |||
1836 | struct btrfs_disk_key right_key; | 1829 | struct btrfs_disk_key right_key; |
1837 | btrfs_node_key(right, &right_key, 0); | 1830 | btrfs_node_key(right, &right_key, 0); |
1838 | tree_mod_log_set_node_key(root->fs_info, parent, | 1831 | tree_mod_log_set_node_key(root->fs_info, parent, |
1839 | &right_key, pslot + 1, 0); | 1832 | pslot + 1, 0); |
1840 | btrfs_set_node_key(parent, &right_key, pslot + 1); | 1833 | btrfs_set_node_key(parent, &right_key, pslot + 1); |
1841 | btrfs_mark_buffer_dirty(parent); | 1834 | btrfs_mark_buffer_dirty(parent); |
1842 | } | 1835 | } |
@@ -1871,7 +1864,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, | |||
1871 | if (btrfs_header_nritems(mid) == 0) { | 1864 | if (btrfs_header_nritems(mid) == 0) { |
1872 | clean_tree_block(trans, root, mid); | 1865 | clean_tree_block(trans, root, mid); |
1873 | btrfs_tree_unlock(mid); | 1866 | btrfs_tree_unlock(mid); |
1874 | del_ptr(trans, root, path, level + 1, pslot, 1); | 1867 | del_ptr(trans, root, path, level + 1, pslot); |
1875 | root_sub_used(root, mid->len); | 1868 | root_sub_used(root, mid->len); |
1876 | btrfs_free_tree_block(trans, root, mid, 0, 1); | 1869 | btrfs_free_tree_block(trans, root, mid, 0, 1); |
1877 | free_extent_buffer_stale(mid); | 1870 | free_extent_buffer_stale(mid); |
@@ -1880,7 +1873,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, | |||
1880 | /* update the parent key to reflect our changes */ | 1873 | /* update the parent key to reflect our changes */ |
1881 | struct btrfs_disk_key mid_key; | 1874 | struct btrfs_disk_key mid_key; |
1882 | btrfs_node_key(mid, &mid_key, 0); | 1875 | btrfs_node_key(mid, &mid_key, 0); |
1883 | tree_mod_log_set_node_key(root->fs_info, parent, &mid_key, | 1876 | tree_mod_log_set_node_key(root->fs_info, parent, |
1884 | pslot, 0); | 1877 | pslot, 0); |
1885 | btrfs_set_node_key(parent, &mid_key, pslot); | 1878 | btrfs_set_node_key(parent, &mid_key, pslot); |
1886 | btrfs_mark_buffer_dirty(parent); | 1879 | btrfs_mark_buffer_dirty(parent); |
@@ -1980,7 +1973,7 @@ static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans, | |||
1980 | orig_slot += left_nr; | 1973 | orig_slot += left_nr; |
1981 | btrfs_node_key(mid, &disk_key, 0); | 1974 | btrfs_node_key(mid, &disk_key, 0); |
1982 | tree_mod_log_set_node_key(root->fs_info, parent, | 1975 | tree_mod_log_set_node_key(root->fs_info, parent, |
1983 | &disk_key, pslot, 0); | 1976 | pslot, 0); |
1984 | btrfs_set_node_key(parent, &disk_key, pslot); | 1977 | btrfs_set_node_key(parent, &disk_key, pslot); |
1985 | btrfs_mark_buffer_dirty(parent); | 1978 | btrfs_mark_buffer_dirty(parent); |
1986 | if (btrfs_header_nritems(left) > orig_slot) { | 1979 | if (btrfs_header_nritems(left) > orig_slot) { |
@@ -2033,7 +2026,7 @@ static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans, | |||
2033 | 2026 | ||
2034 | btrfs_node_key(right, &disk_key, 0); | 2027 | btrfs_node_key(right, &disk_key, 0); |
2035 | tree_mod_log_set_node_key(root->fs_info, parent, | 2028 | tree_mod_log_set_node_key(root->fs_info, parent, |
2036 | &disk_key, pslot + 1, 0); | 2029 | pslot + 1, 0); |
2037 | btrfs_set_node_key(parent, &disk_key, pslot + 1); | 2030 | btrfs_set_node_key(parent, &disk_key, pslot + 1); |
2038 | btrfs_mark_buffer_dirty(parent); | 2031 | btrfs_mark_buffer_dirty(parent); |
2039 | 2032 | ||
@@ -2219,6 +2212,9 @@ static noinline void unlock_up(struct btrfs_path *path, int level, | |||
2219 | int no_skips = 0; | 2212 | int no_skips = 0; |
2220 | struct extent_buffer *t; | 2213 | struct extent_buffer *t; |
2221 | 2214 | ||
2215 | if (path->really_keep_locks) | ||
2216 | return; | ||
2217 | |||
2222 | for (i = level; i < BTRFS_MAX_LEVEL; i++) { | 2218 | for (i = level; i < BTRFS_MAX_LEVEL; i++) { |
2223 | if (!path->nodes[i]) | 2219 | if (!path->nodes[i]) |
2224 | break; | 2220 | break; |
@@ -2266,7 +2262,7 @@ noinline void btrfs_unlock_up_safe(struct btrfs_path *path, int level) | |||
2266 | { | 2262 | { |
2267 | int i; | 2263 | int i; |
2268 | 2264 | ||
2269 | if (path->keep_locks) | 2265 | if (path->keep_locks || path->really_keep_locks) |
2270 | return; | 2266 | return; |
2271 | 2267 | ||
2272 | for (i = level; i < BTRFS_MAX_LEVEL; i++) { | 2268 | for (i = level; i < BTRFS_MAX_LEVEL; i++) { |
@@ -2499,7 +2495,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root | |||
2499 | if (!cow) | 2495 | if (!cow) |
2500 | write_lock_level = -1; | 2496 | write_lock_level = -1; |
2501 | 2497 | ||
2502 | if (cow && (p->keep_locks || p->lowest_level)) | 2498 | if (cow && (p->really_keep_locks || p->keep_locks || p->lowest_level)) |
2503 | write_lock_level = BTRFS_MAX_LEVEL; | 2499 | write_lock_level = BTRFS_MAX_LEVEL; |
2504 | 2500 | ||
2505 | min_write_lock_level = write_lock_level; | 2501 | min_write_lock_level = write_lock_level; |
@@ -2568,7 +2564,10 @@ again: | |||
2568 | * must have write locks on this node and the | 2564 | * must have write locks on this node and the |
2569 | * parent | 2565 | * parent |
2570 | */ | 2566 | */ |
2571 | if (level + 1 > write_lock_level) { | 2567 | if (level > write_lock_level || |
2568 | (level + 1 > write_lock_level && | ||
2569 | level + 1 < BTRFS_MAX_LEVEL && | ||
2570 | p->nodes[level + 1])) { | ||
2572 | write_lock_level = level + 1; | 2571 | write_lock_level = level + 1; |
2573 | btrfs_release_path(p); | 2572 | btrfs_release_path(p); |
2574 | goto again; | 2573 | goto again; |
@@ -2917,7 +2916,7 @@ static void fixup_low_keys(struct btrfs_trans_handle *trans, | |||
2917 | if (!path->nodes[i]) | 2916 | if (!path->nodes[i]) |
2918 | break; | 2917 | break; |
2919 | t = path->nodes[i]; | 2918 | t = path->nodes[i]; |
2920 | tree_mod_log_set_node_key(root->fs_info, t, key, tslot, 1); | 2919 | tree_mod_log_set_node_key(root->fs_info, t, tslot, 1); |
2921 | btrfs_set_node_key(t, key, tslot); | 2920 | btrfs_set_node_key(t, key, tslot); |
2922 | btrfs_mark_buffer_dirty(path->nodes[i]); | 2921 | btrfs_mark_buffer_dirty(path->nodes[i]); |
2923 | if (tslot != 0) | 2922 | if (tslot != 0) |
@@ -3302,14 +3301,21 @@ static noinline int split_node(struct btrfs_trans_handle *trans, | |||
3302 | */ | 3301 | */ |
3303 | static int leaf_space_used(struct extent_buffer *l, int start, int nr) | 3302 | static int leaf_space_used(struct extent_buffer *l, int start, int nr) |
3304 | { | 3303 | { |
3304 | struct btrfs_item *start_item; | ||
3305 | struct btrfs_item *end_item; | ||
3306 | struct btrfs_map_token token; | ||
3305 | int data_len; | 3307 | int data_len; |
3306 | int nritems = btrfs_header_nritems(l); | 3308 | int nritems = btrfs_header_nritems(l); |
3307 | int end = min(nritems, start + nr) - 1; | 3309 | int end = min(nritems, start + nr) - 1; |
3308 | 3310 | ||
3309 | if (!nr) | 3311 | if (!nr) |
3310 | return 0; | 3312 | return 0; |
3311 | data_len = btrfs_item_end_nr(l, start); | 3313 | btrfs_init_map_token(&token); |
3312 | data_len = data_len - btrfs_item_offset_nr(l, end); | 3314 | start_item = btrfs_item_nr(l, start); |
3315 | end_item = btrfs_item_nr(l, end); | ||
3316 | data_len = btrfs_token_item_offset(l, start_item, &token) + | ||
3317 | btrfs_token_item_size(l, start_item, &token); | ||
3318 | data_len = data_len - btrfs_token_item_offset(l, end_item, &token); | ||
3313 | data_len += sizeof(struct btrfs_item) * nr; | 3319 | data_len += sizeof(struct btrfs_item) * nr; |
3314 | WARN_ON(data_len < 0); | 3320 | WARN_ON(data_len < 0); |
3315 | return data_len; | 3321 | return data_len; |
@@ -3403,8 +3409,7 @@ static noinline int __push_leaf_right(struct btrfs_trans_handle *trans, | |||
3403 | if (push_items == 0) | 3409 | if (push_items == 0) |
3404 | goto out_unlock; | 3410 | goto out_unlock; |
3405 | 3411 | ||
3406 | if (!empty && push_items == left_nritems) | 3412 | WARN_ON(!empty && push_items == left_nritems); |
3407 | WARN_ON(1); | ||
3408 | 3413 | ||
3409 | /* push left to right */ | 3414 | /* push left to right */ |
3410 | right_nritems = btrfs_header_nritems(right); | 3415 | right_nritems = btrfs_header_nritems(right); |
@@ -3642,11 +3647,9 @@ static noinline int __push_leaf_left(struct btrfs_trans_handle *trans, | |||
3642 | btrfs_set_header_nritems(left, old_left_nritems + push_items); | 3647 | btrfs_set_header_nritems(left, old_left_nritems + push_items); |
3643 | 3648 | ||
3644 | /* fixup right node */ | 3649 | /* fixup right node */ |
3645 | if (push_items > right_nritems) { | 3650 | if (push_items > right_nritems) |
3646 | printk(KERN_CRIT "push items %d nr %u\n", push_items, | 3651 | WARN(1, KERN_CRIT "push items %d nr %u\n", push_items, |
3647 | right_nritems); | 3652 | right_nritems); |
3648 | WARN_ON(1); | ||
3649 | } | ||
3650 | 3653 | ||
3651 | if (push_items < right_nritems) { | 3654 | if (push_items < right_nritems) { |
3652 | push_space = btrfs_item_offset_nr(right, push_items - 1) - | 3655 | push_space = btrfs_item_offset_nr(right, push_items - 1) - |
@@ -4602,8 +4605,7 @@ int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
4602 | * empty a node. | 4605 | * empty a node. |
4603 | */ | 4606 | */ |
4604 | static void del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 4607 | static void del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
4605 | struct btrfs_path *path, int level, int slot, | 4608 | struct btrfs_path *path, int level, int slot) |
4606 | int tree_mod_log) | ||
4607 | { | 4609 | { |
4608 | struct extent_buffer *parent = path->nodes[level]; | 4610 | struct extent_buffer *parent = path->nodes[level]; |
4609 | u32 nritems; | 4611 | u32 nritems; |
@@ -4611,7 +4613,7 @@ static void del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
4611 | 4613 | ||
4612 | nritems = btrfs_header_nritems(parent); | 4614 | nritems = btrfs_header_nritems(parent); |
4613 | if (slot != nritems - 1) { | 4615 | if (slot != nritems - 1) { |
4614 | if (tree_mod_log && level) | 4616 | if (level) |
4615 | tree_mod_log_eb_move(root->fs_info, parent, slot, | 4617 | tree_mod_log_eb_move(root->fs_info, parent, slot, |
4616 | slot + 1, nritems - slot - 1); | 4618 | slot + 1, nritems - slot - 1); |
4617 | memmove_extent_buffer(parent, | 4619 | memmove_extent_buffer(parent, |
@@ -4619,7 +4621,7 @@ static void del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
4619 | btrfs_node_key_ptr_offset(slot + 1), | 4621 | btrfs_node_key_ptr_offset(slot + 1), |
4620 | sizeof(struct btrfs_key_ptr) * | 4622 | sizeof(struct btrfs_key_ptr) * |
4621 | (nritems - slot - 1)); | 4623 | (nritems - slot - 1)); |
4622 | } else if (tree_mod_log && level) { | 4624 | } else if (level) { |
4623 | ret = tree_mod_log_insert_key(root->fs_info, parent, slot, | 4625 | ret = tree_mod_log_insert_key(root->fs_info, parent, slot, |
4624 | MOD_LOG_KEY_REMOVE); | 4626 | MOD_LOG_KEY_REMOVE); |
4625 | BUG_ON(ret < 0); | 4627 | BUG_ON(ret < 0); |
@@ -4656,7 +4658,7 @@ static noinline void btrfs_del_leaf(struct btrfs_trans_handle *trans, | |||
4656 | struct extent_buffer *leaf) | 4658 | struct extent_buffer *leaf) |
4657 | { | 4659 | { |
4658 | WARN_ON(btrfs_header_generation(leaf) != trans->transid); | 4660 | WARN_ON(btrfs_header_generation(leaf) != trans->transid); |
4659 | del_ptr(trans, root, path, 1, path->slots[1], 1); | 4661 | del_ptr(trans, root, path, 1, path->slots[1]); |
4660 | 4662 | ||
4661 | /* | 4663 | /* |
4662 | * btrfs_free_extent is expensive, we want to make sure we | 4664 | * btrfs_free_extent is expensive, we want to make sure we |
@@ -5123,13 +5125,13 @@ int btrfs_compare_trees(struct btrfs_root *left_root, | |||
5123 | right_path->search_commit_root = 1; | 5125 | right_path->search_commit_root = 1; |
5124 | right_path->skip_locking = 1; | 5126 | right_path->skip_locking = 1; |
5125 | 5127 | ||
5126 | spin_lock(&left_root->root_times_lock); | 5128 | spin_lock(&left_root->root_item_lock); |
5127 | left_start_ctransid = btrfs_root_ctransid(&left_root->root_item); | 5129 | left_start_ctransid = btrfs_root_ctransid(&left_root->root_item); |
5128 | spin_unlock(&left_root->root_times_lock); | 5130 | spin_unlock(&left_root->root_item_lock); |
5129 | 5131 | ||
5130 | spin_lock(&right_root->root_times_lock); | 5132 | spin_lock(&right_root->root_item_lock); |
5131 | right_start_ctransid = btrfs_root_ctransid(&right_root->root_item); | 5133 | right_start_ctransid = btrfs_root_ctransid(&right_root->root_item); |
5132 | spin_unlock(&right_root->root_times_lock); | 5134 | spin_unlock(&right_root->root_item_lock); |
5133 | 5135 | ||
5134 | trans = btrfs_join_transaction(left_root); | 5136 | trans = btrfs_join_transaction(left_root); |
5135 | if (IS_ERR(trans)) { | 5137 | if (IS_ERR(trans)) { |
@@ -5224,15 +5226,15 @@ int btrfs_compare_trees(struct btrfs_root *left_root, | |||
5224 | goto out; | 5226 | goto out; |
5225 | } | 5227 | } |
5226 | 5228 | ||
5227 | spin_lock(&left_root->root_times_lock); | 5229 | spin_lock(&left_root->root_item_lock); |
5228 | ctransid = btrfs_root_ctransid(&left_root->root_item); | 5230 | ctransid = btrfs_root_ctransid(&left_root->root_item); |
5229 | spin_unlock(&left_root->root_times_lock); | 5231 | spin_unlock(&left_root->root_item_lock); |
5230 | if (ctransid != left_start_ctransid) | 5232 | if (ctransid != left_start_ctransid) |
5231 | left_start_ctransid = 0; | 5233 | left_start_ctransid = 0; |
5232 | 5234 | ||
5233 | spin_lock(&right_root->root_times_lock); | 5235 | spin_lock(&right_root->root_item_lock); |
5234 | ctransid = btrfs_root_ctransid(&right_root->root_item); | 5236 | ctransid = btrfs_root_ctransid(&right_root->root_item); |
5235 | spin_unlock(&right_root->root_times_lock); | 5237 | spin_unlock(&right_root->root_item_lock); |
5236 | if (ctransid != right_start_ctransid) | 5238 | if (ctransid != right_start_ctransid) |
5237 | right_start_ctransid = 0; | 5239 | right_start_ctransid = 0; |
5238 | 5240 | ||
@@ -5496,6 +5498,139 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path) | |||
5496 | return btrfs_next_old_leaf(root, path, 0); | 5498 | return btrfs_next_old_leaf(root, path, 0); |
5497 | } | 5499 | } |
5498 | 5500 | ||
5501 | /* Release the path up to but not including the given level */ | ||
5502 | static void btrfs_release_level(struct btrfs_path *path, int level) | ||
5503 | { | ||
5504 | int i; | ||
5505 | |||
5506 | for (i = 0; i < level; i++) { | ||
5507 | path->slots[i] = 0; | ||
5508 | if (!path->nodes[i]) | ||
5509 | continue; | ||
5510 | if (path->locks[i]) { | ||
5511 | btrfs_tree_unlock_rw(path->nodes[i], path->locks[i]); | ||
5512 | path->locks[i] = 0; | ||
5513 | } | ||
5514 | free_extent_buffer(path->nodes[i]); | ||
5515 | path->nodes[i] = NULL; | ||
5516 | } | ||
5517 | } | ||
5518 | |||
5519 | /* | ||
5520 | * This function assumes 2 things | ||
5521 | * | ||
5522 | * 1) You are using path->keep_locks | ||
5523 | * 2) You are not inserting items. | ||
5524 | * | ||
5525 | * If either of these are not true do not use this function. If you need a next | ||
5526 | * leaf with either of these not being true then this function can be easily | ||
5527 | * adapted to do that, but at the moment these are the limitations. | ||
5528 | */ | ||
5529 | int btrfs_next_leaf_write(struct btrfs_trans_handle *trans, | ||
5530 | struct btrfs_root *root, struct btrfs_path *path, | ||
5531 | int del) | ||
5532 | { | ||
5533 | struct extent_buffer *b; | ||
5534 | struct btrfs_key key; | ||
5535 | u32 nritems; | ||
5536 | int level = 1; | ||
5537 | int slot; | ||
5538 | int ret = 1; | ||
5539 | int write_lock_level = BTRFS_MAX_LEVEL; | ||
5540 | int ins_len = del ? -1 : 0; | ||
5541 | |||
5542 | WARN_ON(!(path->keep_locks || path->really_keep_locks)); | ||
5543 | |||
5544 | nritems = btrfs_header_nritems(path->nodes[0]); | ||
5545 | btrfs_item_key_to_cpu(path->nodes[0], &key, nritems - 1); | ||
5546 | |||
5547 | while (path->nodes[level]) { | ||
5548 | nritems = btrfs_header_nritems(path->nodes[level]); | ||
5549 | if (!(path->locks[level] & BTRFS_WRITE_LOCK)) { | ||
5550 | search: | ||
5551 | btrfs_release_path(path); | ||
5552 | ret = btrfs_search_slot(trans, root, &key, path, | ||
5553 | ins_len, 1); | ||
5554 | if (ret < 0) | ||
5555 | goto out; | ||
5556 | level = 1; | ||
5557 | continue; | ||
5558 | } | ||
5559 | |||
5560 | if (path->slots[level] >= nritems - 1) { | ||
5561 | level++; | ||
5562 | continue; | ||
5563 | } | ||
5564 | |||
5565 | btrfs_release_level(path, level); | ||
5566 | break; | ||
5567 | } | ||
5568 | |||
5569 | if (!path->nodes[level]) { | ||
5570 | ret = 1; | ||
5571 | goto out; | ||
5572 | } | ||
5573 | |||
5574 | path->slots[level]++; | ||
5575 | b = path->nodes[level]; | ||
5576 | |||
5577 | while (b) { | ||
5578 | level = btrfs_header_level(b); | ||
5579 | |||
5580 | if (!should_cow_block(trans, root, b)) | ||
5581 | goto cow_done; | ||
5582 | |||
5583 | btrfs_set_path_blocking(path); | ||
5584 | ret = btrfs_cow_block(trans, root, b, | ||
5585 | path->nodes[level + 1], | ||
5586 | path->slots[level + 1], &b); | ||
5587 | if (ret) | ||
5588 | goto out; | ||
5589 | cow_done: | ||
5590 | path->nodes[level] = b; | ||
5591 | btrfs_clear_path_blocking(path, NULL, 0); | ||
5592 | if (level != 0) { | ||
5593 | ret = setup_nodes_for_search(trans, root, path, b, | ||
5594 | level, ins_len, | ||
5595 | &write_lock_level); | ||
5596 | if (ret == -EAGAIN) | ||
5597 | goto search; | ||
5598 | if (ret) | ||
5599 | goto out; | ||
5600 | |||
5601 | b = path->nodes[level]; | ||
5602 | slot = path->slots[level]; | ||
5603 | |||
5604 | ret = read_block_for_search(trans, root, path, | ||
5605 | &b, level, slot, &key, 0); | ||
5606 | if (ret == -EAGAIN) | ||
5607 | goto search; | ||
5608 | if (ret) | ||
5609 | goto out; | ||
5610 | level = btrfs_header_level(b); | ||
5611 | if (!btrfs_try_tree_write_lock(b)) { | ||
5612 | btrfs_set_path_blocking(path); | ||
5613 | btrfs_tree_lock(b); | ||
5614 | btrfs_clear_path_blocking(path, b, | ||
5615 | BTRFS_WRITE_LOCK); | ||
5616 | } | ||
5617 | path->locks[level] = BTRFS_WRITE_LOCK; | ||
5618 | path->nodes[level] = b; | ||
5619 | path->slots[level] = 0; | ||
5620 | } else { | ||
5621 | path->slots[level] = 0; | ||
5622 | ret = 0; | ||
5623 | break; | ||
5624 | } | ||
5625 | } | ||
5626 | |||
5627 | out: | ||
5628 | if (ret) | ||
5629 | btrfs_release_path(path); | ||
5630 | |||
5631 | return ret; | ||
5632 | } | ||
5633 | |||
5499 | int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path, | 5634 | int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path, |
5500 | u64 time_seq) | 5635 | u64 time_seq) |
5501 | { | 5636 | { |