| .. | .. |
|---|
| 12 | 12 | #include "transaction.h" |
|---|
| 13 | 13 | #include "print-tree.h" |
|---|
| 14 | 14 | #include "locking.h" |
|---|
| 15 | +#include "volumes.h" |
|---|
| 16 | +#include "qgroup.h" |
|---|
| 15 | 17 | |
|---|
| 16 | 18 | static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root |
|---|
| 17 | 19 | *root, struct btrfs_path *path, int level); |
|---|
| .. | .. |
|---|
| 19 | 21 | const struct btrfs_key *ins_key, struct btrfs_path *path, |
|---|
| 20 | 22 | int data_size, int extend); |
|---|
| 21 | 23 | static int push_node_left(struct btrfs_trans_handle *trans, |
|---|
| 22 | | - struct btrfs_fs_info *fs_info, |
|---|
| 23 | 24 | struct extent_buffer *dst, |
|---|
| 24 | 25 | struct extent_buffer *src, int empty); |
|---|
| 25 | 26 | static int balance_node_right(struct btrfs_trans_handle *trans, |
|---|
| 26 | | - struct btrfs_fs_info *fs_info, |
|---|
| 27 | 27 | struct extent_buffer *dst_buf, |
|---|
| 28 | 28 | struct extent_buffer *src_buf); |
|---|
| 29 | 29 | static void del_ptr(struct btrfs_root *root, struct btrfs_path *path, |
|---|
| 30 | 30 | int level, int slot); |
|---|
| 31 | 31 | |
|---|
| 32 | +static const struct btrfs_csums { |
|---|
| 33 | + u16 size; |
|---|
| 34 | + const char name[10]; |
|---|
| 35 | + const char driver[12]; |
|---|
| 36 | +} btrfs_csums[] = { |
|---|
| 37 | + [BTRFS_CSUM_TYPE_CRC32] = { .size = 4, .name = "crc32c" }, |
|---|
| 38 | + [BTRFS_CSUM_TYPE_XXHASH] = { .size = 8, .name = "xxhash64" }, |
|---|
| 39 | + [BTRFS_CSUM_TYPE_SHA256] = { .size = 32, .name = "sha256" }, |
|---|
| 40 | + [BTRFS_CSUM_TYPE_BLAKE2] = { .size = 32, .name = "blake2b", |
|---|
| 41 | + .driver = "blake2b-256" }, |
|---|
| 42 | +}; |
|---|
| 43 | + |
|---|
| 44 | +int btrfs_super_csum_size(const struct btrfs_super_block *s) |
|---|
| 45 | +{ |
|---|
| 46 | + u16 t = btrfs_super_csum_type(s); |
|---|
| 47 | + /* |
|---|
| 48 | + * csum type is validated at mount time |
|---|
| 49 | + */ |
|---|
| 50 | + return btrfs_csums[t].size; |
|---|
| 51 | +} |
|---|
| 52 | + |
|---|
| 53 | +const char *btrfs_super_csum_name(u16 csum_type) |
|---|
| 54 | +{ |
|---|
| 55 | + /* csum type is validated at mount time */ |
|---|
| 56 | + return btrfs_csums[csum_type].name; |
|---|
| 57 | +} |
|---|
| 58 | + |
|---|
| 59 | +/* |
|---|
| 60 | + * Return driver name if defined, otherwise the name that's also a valid driver |
|---|
| 61 | + * name |
|---|
| 62 | + */ |
|---|
| 63 | +const char *btrfs_super_csum_driver(u16 csum_type) |
|---|
| 64 | +{ |
|---|
| 65 | + /* csum type is validated at mount time */ |
|---|
| 66 | + return btrfs_csums[csum_type].driver[0] ? |
|---|
| 67 | + btrfs_csums[csum_type].driver : |
|---|
| 68 | + btrfs_csums[csum_type].name; |
|---|
| 69 | +} |
|---|
| 70 | + |
|---|
| 71 | +size_t __attribute_const__ btrfs_get_num_csums(void) |
|---|
| 72 | +{ |
|---|
| 73 | + return ARRAY_SIZE(btrfs_csums); |
|---|
| 74 | +} |
|---|
| 75 | + |
|---|
| 32 | 76 | struct btrfs_path *btrfs_alloc_path(void) |
|---|
| 33 | 77 | { |
|---|
| 34 | 78 | return kmem_cache_zalloc(btrfs_path_cachep, GFP_NOFS); |
|---|
| 35 | | -} |
|---|
| 36 | | - |
|---|
| 37 | | -/* |
|---|
| 38 | | - * set all locked nodes in the path to blocking locks. This should |
|---|
| 39 | | - * be done before scheduling |
|---|
| 40 | | - */ |
|---|
| 41 | | -noinline void btrfs_set_path_blocking(struct btrfs_path *p) |
|---|
| 42 | | -{ |
|---|
| 43 | | - int i; |
|---|
| 44 | | - for (i = 0; i < BTRFS_MAX_LEVEL; i++) { |
|---|
| 45 | | - if (!p->nodes[i] || !p->locks[i]) |
|---|
| 46 | | - continue; |
|---|
| 47 | | - btrfs_set_lock_blocking_rw(p->nodes[i], p->locks[i]); |
|---|
| 48 | | - if (p->locks[i] == BTRFS_READ_LOCK) |
|---|
| 49 | | - p->locks[i] = BTRFS_READ_LOCK_BLOCKING; |
|---|
| 50 | | - else if (p->locks[i] == BTRFS_WRITE_LOCK) |
|---|
| 51 | | - p->locks[i] = BTRFS_WRITE_LOCK_BLOCKING; |
|---|
| 52 | | - } |
|---|
| 53 | | -} |
|---|
| 54 | | - |
|---|
| 55 | | -/* |
|---|
| 56 | | - * reset all the locked nodes in the patch to spinning locks. |
|---|
| 57 | | - * |
|---|
| 58 | | - * held is used to keep lockdep happy, when lockdep is enabled |
|---|
| 59 | | - * we set held to a blocking lock before we go around and |
|---|
| 60 | | - * retake all the spinlocks in the path. You can safely use NULL |
|---|
| 61 | | - * for held |
|---|
| 62 | | - */ |
|---|
| 63 | | -noinline void btrfs_clear_path_blocking(struct btrfs_path *p, |
|---|
| 64 | | - struct extent_buffer *held, int held_rw) |
|---|
| 65 | | -{ |
|---|
| 66 | | - int i; |
|---|
| 67 | | - |
|---|
| 68 | | - if (held) { |
|---|
| 69 | | - btrfs_set_lock_blocking_rw(held, held_rw); |
|---|
| 70 | | - if (held_rw == BTRFS_WRITE_LOCK) |
|---|
| 71 | | - held_rw = BTRFS_WRITE_LOCK_BLOCKING; |
|---|
| 72 | | - else if (held_rw == BTRFS_READ_LOCK) |
|---|
| 73 | | - held_rw = BTRFS_READ_LOCK_BLOCKING; |
|---|
| 74 | | - } |
|---|
| 75 | | - btrfs_set_path_blocking(p); |
|---|
| 76 | | - |
|---|
| 77 | | - for (i = BTRFS_MAX_LEVEL - 1; i >= 0; i--) { |
|---|
| 78 | | - if (p->nodes[i] && p->locks[i]) { |
|---|
| 79 | | - btrfs_clear_lock_blocking_rw(p->nodes[i], p->locks[i]); |
|---|
| 80 | | - if (p->locks[i] == BTRFS_WRITE_LOCK_BLOCKING) |
|---|
| 81 | | - p->locks[i] = BTRFS_WRITE_LOCK; |
|---|
| 82 | | - else if (p->locks[i] == BTRFS_READ_LOCK_BLOCKING) |
|---|
| 83 | | - p->locks[i] = BTRFS_READ_LOCK; |
|---|
| 84 | | - } |
|---|
| 85 | | - } |
|---|
| 86 | | - |
|---|
| 87 | | - if (held) |
|---|
| 88 | | - btrfs_clear_lock_blocking_rw(held, held_rw); |
|---|
| 89 | 79 | } |
|---|
| 90 | 80 | |
|---|
| 91 | 81 | /* this also releases the path */ |
|---|
| .. | .. |
|---|
| 154 | 144 | return eb; |
|---|
| 155 | 145 | } |
|---|
| 156 | 146 | |
|---|
| 157 | | -/* loop around taking references on and locking the root node of the |
|---|
| 158 | | - * tree until you end up with a lock on the root. A locked buffer |
|---|
| 159 | | - * is returned, with a reference held. |
|---|
| 160 | | - */ |
|---|
| 161 | | -struct extent_buffer *btrfs_lock_root_node(struct btrfs_root *root) |
|---|
| 162 | | -{ |
|---|
| 163 | | - struct extent_buffer *eb; |
|---|
| 164 | | - |
|---|
| 165 | | - while (1) { |
|---|
| 166 | | - eb = btrfs_root_node(root); |
|---|
| 167 | | - btrfs_tree_lock(eb); |
|---|
| 168 | | - if (eb == root->node) |
|---|
| 169 | | - break; |
|---|
| 170 | | - btrfs_tree_unlock(eb); |
|---|
| 171 | | - free_extent_buffer(eb); |
|---|
| 172 | | - } |
|---|
| 173 | | - return eb; |
|---|
| 174 | | -} |
|---|
| 175 | | - |
|---|
| 176 | | -/* loop around taking references on and locking the root node of the |
|---|
| 177 | | - * tree until you end up with a lock on the root. A locked buffer |
|---|
| 178 | | - * is returned, with a reference held. |
|---|
| 179 | | - */ |
|---|
| 180 | | -struct extent_buffer *btrfs_read_lock_root_node(struct btrfs_root *root) |
|---|
| 181 | | -{ |
|---|
| 182 | | - struct extent_buffer *eb; |
|---|
| 183 | | - |
|---|
| 184 | | - while (1) { |
|---|
| 185 | | - eb = btrfs_root_node(root); |
|---|
| 186 | | - btrfs_tree_read_lock(eb); |
|---|
| 187 | | - if (eb == root->node) |
|---|
| 188 | | - break; |
|---|
| 189 | | - btrfs_tree_read_unlock(eb); |
|---|
| 190 | | - free_extent_buffer(eb); |
|---|
| 191 | | - } |
|---|
| 192 | | - return eb; |
|---|
| 193 | | -} |
|---|
| 194 | | - |
|---|
| 195 | | -/* cowonly root (everything not a reference counted cow subvolume), just get |
|---|
| 196 | | - * put onto a simple dirty list. transaction.c walks this to make sure they |
|---|
| 197 | | - * get properly updated on disk. |
|---|
| 147 | +/* |
|---|
| 148 | + * Cowonly root (not-shareable trees, everything not subvolume or reloc roots), |
|---|
| 149 | + * just get put onto a simple dirty list. Transaction walks this list to make |
|---|
| 150 | + * sure they get properly updated on disk. |
|---|
| 198 | 151 | */ |
|---|
| 199 | 152 | static void add_root_to_dirty_list(struct btrfs_root *root) |
|---|
| 200 | 153 | { |
|---|
| .. | .. |
|---|
| 207 | 160 | spin_lock(&fs_info->trans_lock); |
|---|
| 208 | 161 | if (!test_and_set_bit(BTRFS_ROOT_DIRTY, &root->state)) { |
|---|
| 209 | 162 | /* Want the extent tree to be the last on the list */ |
|---|
| 210 | | - if (root->objectid == BTRFS_EXTENT_TREE_OBJECTID) |
|---|
| 163 | + if (root->root_key.objectid == BTRFS_EXTENT_TREE_OBJECTID) |
|---|
| 211 | 164 | list_move_tail(&root->dirty_list, |
|---|
| 212 | 165 | &fs_info->dirty_cowonly_roots); |
|---|
| 213 | 166 | else |
|---|
| .. | .. |
|---|
| 233 | 186 | int level; |
|---|
| 234 | 187 | struct btrfs_disk_key disk_key; |
|---|
| 235 | 188 | |
|---|
| 236 | | - WARN_ON(test_bit(BTRFS_ROOT_REF_COWS, &root->state) && |
|---|
| 189 | + WARN_ON(test_bit(BTRFS_ROOT_SHAREABLE, &root->state) && |
|---|
| 237 | 190 | trans->transid != fs_info->running_transaction->transid); |
|---|
| 238 | | - WARN_ON(test_bit(BTRFS_ROOT_REF_COWS, &root->state) && |
|---|
| 191 | + WARN_ON(test_bit(BTRFS_ROOT_SHAREABLE, &root->state) && |
|---|
| 239 | 192 | trans->transid != root->last_trans); |
|---|
| 240 | 193 | |
|---|
| 241 | 194 | level = btrfs_header_level(buf); |
|---|
| .. | .. |
|---|
| 245 | 198 | btrfs_node_key(buf, &disk_key, 0); |
|---|
| 246 | 199 | |
|---|
| 247 | 200 | cow = btrfs_alloc_tree_block(trans, root, 0, new_root_objectid, |
|---|
| 248 | | - &disk_key, level, buf->start, 0); |
|---|
| 201 | + &disk_key, level, buf->start, 0, |
|---|
| 202 | + BTRFS_NESTING_NEW_ROOT); |
|---|
| 249 | 203 | if (IS_ERR(cow)) |
|---|
| 250 | 204 | return PTR_ERR(cow); |
|---|
| 251 | 205 | |
|---|
| .. | .. |
|---|
| 260 | 214 | else |
|---|
| 261 | 215 | btrfs_set_header_owner(cow, new_root_objectid); |
|---|
| 262 | 216 | |
|---|
| 263 | | - write_extent_buffer_fsid(cow, fs_info->fsid); |
|---|
| 217 | + write_extent_buffer_fsid(cow, fs_info->fs_devices->metadata_uuid); |
|---|
| 264 | 218 | |
|---|
| 265 | 219 | WARN_ON(btrfs_header_generation(buf) > trans->transid); |
|---|
| 266 | 220 | if (new_root_objectid == BTRFS_TREE_RELOC_OBJECTID) |
|---|
| .. | .. |
|---|
| 355 | 309 | struct rb_root *tm_root; |
|---|
| 356 | 310 | struct rb_node *node; |
|---|
| 357 | 311 | struct rb_node *next; |
|---|
| 358 | | - struct seq_list *cur_elem; |
|---|
| 359 | 312 | struct tree_mod_elem *tm; |
|---|
| 360 | 313 | u64 min_seq = (u64)-1; |
|---|
| 361 | 314 | u64 seq_putting = elem->seq; |
|---|
| .. | .. |
|---|
| 367 | 320 | list_del(&elem->list); |
|---|
| 368 | 321 | elem->seq = 0; |
|---|
| 369 | 322 | |
|---|
| 370 | | - list_for_each_entry(cur_elem, &fs_info->tree_mod_seq_list, list) { |
|---|
| 371 | | - if (cur_elem->seq < min_seq) { |
|---|
| 372 | | - if (seq_putting > cur_elem->seq) { |
|---|
| 373 | | - /* |
|---|
| 374 | | - * blocker with lower sequence number exists, we |
|---|
| 375 | | - * cannot remove anything from the log |
|---|
| 376 | | - */ |
|---|
| 377 | | - write_unlock(&fs_info->tree_mod_log_lock); |
|---|
| 378 | | - return; |
|---|
| 379 | | - } |
|---|
| 380 | | - min_seq = cur_elem->seq; |
|---|
| 323 | + if (!list_empty(&fs_info->tree_mod_seq_list)) { |
|---|
| 324 | + struct seq_list *first; |
|---|
| 325 | + |
|---|
| 326 | + first = list_first_entry(&fs_info->tree_mod_seq_list, |
|---|
| 327 | + struct seq_list, list); |
|---|
| 328 | + if (seq_putting > first->seq) { |
|---|
| 329 | + /* |
|---|
| 330 | + * Blocker with lower sequence number exists, we |
|---|
| 331 | + * cannot remove anything from the log. |
|---|
| 332 | + */ |
|---|
| 333 | + write_unlock(&fs_info->tree_mod_log_lock); |
|---|
| 334 | + return; |
|---|
| 381 | 335 | } |
|---|
| 336 | + min_seq = first->seq; |
|---|
| 382 | 337 | } |
|---|
| 383 | 338 | |
|---|
| 384 | 339 | /* |
|---|
| .. | .. |
|---|
| 404 | 359 | * The 'start address' is the logical address of the *new* root node |
|---|
| 405 | 360 | * for root replace operations, or the logical address of the affected |
|---|
| 406 | 361 | * block for all other operations. |
|---|
| 407 | | - * |
|---|
| 408 | | - * Note: must be called with write lock for fs_info::tree_mod_log_lock. |
|---|
| 409 | 362 | */ |
|---|
| 410 | 363 | static noinline int |
|---|
| 411 | 364 | __tree_mod_log_insert(struct btrfs_fs_info *fs_info, struct tree_mod_elem *tm) |
|---|
| .. | .. |
|---|
| 414 | 367 | struct rb_node **new; |
|---|
| 415 | 368 | struct rb_node *parent = NULL; |
|---|
| 416 | 369 | struct tree_mod_elem *cur; |
|---|
| 370 | + |
|---|
| 371 | + lockdep_assert_held_write(&fs_info->tree_mod_log_lock); |
|---|
| 417 | 372 | |
|---|
| 418 | 373 | tm->seq = btrfs_inc_tree_mod_seq(fs_info); |
|---|
| 419 | 374 | |
|---|
| .. | .. |
|---|
| 752 | 707 | return __tree_mod_log_search(fs_info, start, min_seq, 0); |
|---|
| 753 | 708 | } |
|---|
| 754 | 709 | |
|---|
| 755 | | -static noinline int |
|---|
| 756 | | -tree_mod_log_eb_copy(struct btrfs_fs_info *fs_info, struct extent_buffer *dst, |
|---|
| 710 | +static noinline int tree_mod_log_eb_copy(struct extent_buffer *dst, |
|---|
| 757 | 711 | struct extent_buffer *src, unsigned long dst_offset, |
|---|
| 758 | 712 | unsigned long src_offset, int nr_items) |
|---|
| 759 | 713 | { |
|---|
| 714 | + struct btrfs_fs_info *fs_info = dst->fs_info; |
|---|
| 760 | 715 | int ret = 0; |
|---|
| 761 | 716 | struct tree_mod_elem **tm_list = NULL; |
|---|
| 762 | 717 | struct tree_mod_elem **tm_list_add, **tm_list_rem; |
|---|
| .. | .. |
|---|
| 876 | 831 | struct extent_buffer *buf) |
|---|
| 877 | 832 | { |
|---|
| 878 | 833 | /* |
|---|
| 879 | | - * Tree blocks not in reference counted trees and tree roots |
|---|
| 880 | | - * are never shared. If a block was allocated after the last |
|---|
| 881 | | - * snapshot and the block was not allocated by tree relocation, |
|---|
| 882 | | - * we know the block is not shared. |
|---|
| 834 | + * Tree blocks not in shareable trees and tree roots are never shared. |
|---|
| 835 | + * If a block was allocated after the last snapshot and the block was |
|---|
| 836 | + * not allocated by tree relocation, we know the block is not shared. |
|---|
| 883 | 837 | */ |
|---|
| 884 | | - if (test_bit(BTRFS_ROOT_REF_COWS, &root->state) && |
|---|
| 838 | + if (test_bit(BTRFS_ROOT_SHAREABLE, &root->state) && |
|---|
| 885 | 839 | buf != root->node && buf != root->commit_root && |
|---|
| 886 | 840 | (btrfs_header_generation(buf) <= |
|---|
| 887 | 841 | btrfs_root_last_snapshot(&root->root_item) || |
|---|
| .. | .. |
|---|
| 976 | 930 | if (new_flags != 0) { |
|---|
| 977 | 931 | int level = btrfs_header_level(buf); |
|---|
| 978 | 932 | |
|---|
| 979 | | - ret = btrfs_set_disk_extent_flags(trans, fs_info, |
|---|
| 980 | | - buf->start, |
|---|
| 981 | | - buf->len, |
|---|
| 933 | + ret = btrfs_set_disk_extent_flags(trans, buf, |
|---|
| 982 | 934 | new_flags, level, 0); |
|---|
| 983 | 935 | if (ret) |
|---|
| 984 | 936 | return ret; |
|---|
| .. | .. |
|---|
| 996 | 948 | if (ret) |
|---|
| 997 | 949 | return ret; |
|---|
| 998 | 950 | } |
|---|
| 999 | | - clean_tree_block(fs_info, buf); |
|---|
| 951 | + btrfs_clean_tree_block(buf); |
|---|
| 1000 | 952 | *last_ref = 1; |
|---|
| 1001 | 953 | } |
|---|
| 1002 | 954 | return 0; |
|---|
| .. | .. |
|---|
| 1009 | 961 | const struct btrfs_disk_key *disk_key, |
|---|
| 1010 | 962 | int level, |
|---|
| 1011 | 963 | u64 hint, |
|---|
| 1012 | | - u64 empty_size) |
|---|
| 964 | + u64 empty_size, |
|---|
| 965 | + enum btrfs_lock_nesting nest) |
|---|
| 1013 | 966 | { |
|---|
| 1014 | 967 | struct btrfs_fs_info *fs_info = root->fs_info; |
|---|
| 1015 | 968 | struct extent_buffer *ret; |
|---|
| .. | .. |
|---|
| 1038 | 991 | |
|---|
| 1039 | 992 | ret = btrfs_alloc_tree_block(trans, root, parent_start, |
|---|
| 1040 | 993 | root->root_key.objectid, disk_key, level, |
|---|
| 1041 | | - hint, empty_size); |
|---|
| 994 | + hint, empty_size, nest); |
|---|
| 1042 | 995 | trans->can_flush_pending_bgs = true; |
|---|
| 1043 | 996 | |
|---|
| 1044 | 997 | return ret; |
|---|
| .. | .. |
|---|
| 1061 | 1014 | struct extent_buffer *buf, |
|---|
| 1062 | 1015 | struct extent_buffer *parent, int parent_slot, |
|---|
| 1063 | 1016 | struct extent_buffer **cow_ret, |
|---|
| 1064 | | - u64 search_start, u64 empty_size) |
|---|
| 1017 | + u64 search_start, u64 empty_size, |
|---|
| 1018 | + enum btrfs_lock_nesting nest) |
|---|
| 1065 | 1019 | { |
|---|
| 1066 | 1020 | struct btrfs_fs_info *fs_info = root->fs_info; |
|---|
| 1067 | 1021 | struct btrfs_disk_key disk_key; |
|---|
| .. | .. |
|---|
| 1076 | 1030 | |
|---|
| 1077 | 1031 | btrfs_assert_tree_locked(buf); |
|---|
| 1078 | 1032 | |
|---|
| 1079 | | - WARN_ON(test_bit(BTRFS_ROOT_REF_COWS, &root->state) && |
|---|
| 1033 | + WARN_ON(test_bit(BTRFS_ROOT_SHAREABLE, &root->state) && |
|---|
| 1080 | 1034 | trans->transid != fs_info->running_transaction->transid); |
|---|
| 1081 | | - WARN_ON(test_bit(BTRFS_ROOT_REF_COWS, &root->state) && |
|---|
| 1035 | + WARN_ON(test_bit(BTRFS_ROOT_SHAREABLE, &root->state) && |
|---|
| 1082 | 1036 | trans->transid != root->last_trans); |
|---|
| 1083 | 1037 | |
|---|
| 1084 | 1038 | level = btrfs_header_level(buf); |
|---|
| .. | .. |
|---|
| 1092 | 1046 | parent_start = parent->start; |
|---|
| 1093 | 1047 | |
|---|
| 1094 | 1048 | cow = alloc_tree_block_no_bg_flush(trans, root, parent_start, &disk_key, |
|---|
| 1095 | | - level, search_start, empty_size); |
|---|
| 1049 | + level, search_start, empty_size, nest); |
|---|
| 1096 | 1050 | if (IS_ERR(cow)) |
|---|
| 1097 | 1051 | return PTR_ERR(cow); |
|---|
| 1098 | 1052 | |
|---|
| .. | .. |
|---|
| 1109 | 1063 | else |
|---|
| 1110 | 1064 | btrfs_set_header_owner(cow, root->root_key.objectid); |
|---|
| 1111 | 1065 | |
|---|
| 1112 | | - write_extent_buffer_fsid(cow, fs_info->fsid); |
|---|
| 1066 | + write_extent_buffer_fsid(cow, fs_info->fs_devices->metadata_uuid); |
|---|
| 1113 | 1067 | |
|---|
| 1114 | 1068 | ret = update_ref_for_cow(trans, root, buf, cow, &last_ref); |
|---|
| 1115 | 1069 | if (ret) { |
|---|
| .. | .. |
|---|
| 1119 | 1073 | return ret; |
|---|
| 1120 | 1074 | } |
|---|
| 1121 | 1075 | |
|---|
| 1122 | | - if (test_bit(BTRFS_ROOT_REF_COWS, &root->state)) { |
|---|
| 1076 | + if (test_bit(BTRFS_ROOT_SHAREABLE, &root->state)) { |
|---|
| 1123 | 1077 | ret = btrfs_reloc_cow_block(trans, root, buf, cow); |
|---|
| 1124 | 1078 | if (ret) { |
|---|
| 1125 | 1079 | btrfs_tree_unlock(cow); |
|---|
| .. | .. |
|---|
| 1135 | 1089 | btrfs_header_backref_rev(buf) < BTRFS_MIXED_BACKREF_REV) |
|---|
| 1136 | 1090 | parent_start = buf->start; |
|---|
| 1137 | 1091 | |
|---|
| 1138 | | - extent_buffer_get(cow); |
|---|
| 1092 | + atomic_inc(&cow->refs); |
|---|
| 1139 | 1093 | ret = tree_mod_log_insert_root(root->node, cow, 1); |
|---|
| 1140 | 1094 | BUG_ON(ret < 0); |
|---|
| 1141 | 1095 | rcu_assign_pointer(root->node, cow); |
|---|
| .. | .. |
|---|
| 1254 | 1208 | switch (tm->op) { |
|---|
| 1255 | 1209 | case MOD_LOG_KEY_REMOVE_WHILE_FREEING: |
|---|
| 1256 | 1210 | BUG_ON(tm->slot < n); |
|---|
| 1257 | | - /* Fallthrough */ |
|---|
| 1211 | + fallthrough; |
|---|
| 1258 | 1212 | case MOD_LOG_KEY_REMOVE_WHILE_MOVING: |
|---|
| 1259 | 1213 | case MOD_LOG_KEY_REMOVE: |
|---|
| 1260 | 1214 | btrfs_set_node_key(eb, &tm->key, tm->slot); |
|---|
| .. | .. |
|---|
| 1328 | 1282 | return eb; |
|---|
| 1329 | 1283 | |
|---|
| 1330 | 1284 | btrfs_set_path_blocking(path); |
|---|
| 1331 | | - btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK); |
|---|
| 1285 | + btrfs_set_lock_blocking_read(eb); |
|---|
| 1332 | 1286 | |
|---|
| 1333 | 1287 | if (tm->op == MOD_LOG_KEY_REMOVE_WHILE_FREEING) { |
|---|
| 1334 | 1288 | BUG_ON(tm->slot != 0); |
|---|
| .. | .. |
|---|
| 1352 | 1306 | } |
|---|
| 1353 | 1307 | } |
|---|
| 1354 | 1308 | |
|---|
| 1355 | | - btrfs_clear_path_blocking(path, NULL, BTRFS_READ_LOCK); |
|---|
| 1356 | 1309 | btrfs_tree_read_unlock_blocking(eb); |
|---|
| 1357 | 1310 | free_extent_buffer(eb); |
|---|
| 1358 | 1311 | |
|---|
| .. | .. |
|---|
| 1445 | 1398 | free_extent_buffer(eb_root); |
|---|
| 1446 | 1399 | eb = alloc_dummy_extent_buffer(fs_info, logical); |
|---|
| 1447 | 1400 | } else { |
|---|
| 1448 | | - btrfs_set_lock_blocking_rw(eb_root, BTRFS_READ_LOCK); |
|---|
| 1401 | + btrfs_set_lock_blocking_read(eb_root); |
|---|
| 1449 | 1402 | eb = btrfs_clone_extent_buffer(eb_root); |
|---|
| 1450 | 1403 | btrfs_tree_read_unlock_blocking(eb_root); |
|---|
| 1451 | 1404 | free_extent_buffer(eb_root); |
|---|
| .. | .. |
|---|
| 1507 | 1460 | * |
|---|
| 1508 | 1461 | * What is forced COW: |
|---|
| 1509 | 1462 | * when we create snapshot during committing the transaction, |
|---|
| 1510 | | - * after we've finished coping src root, we must COW the shared |
|---|
| 1463 | + * after we've finished copying src root, we must COW the shared |
|---|
| 1511 | 1464 | * block to ensure the metadata consistency. |
|---|
| 1512 | 1465 | */ |
|---|
| 1513 | 1466 | if (btrfs_header_generation(buf) == trans->transid && |
|---|
| .. | .. |
|---|
| 1527 | 1480 | noinline int btrfs_cow_block(struct btrfs_trans_handle *trans, |
|---|
| 1528 | 1481 | struct btrfs_root *root, struct extent_buffer *buf, |
|---|
| 1529 | 1482 | struct extent_buffer *parent, int parent_slot, |
|---|
| 1530 | | - struct extent_buffer **cow_ret) |
|---|
| 1483 | + struct extent_buffer **cow_ret, |
|---|
| 1484 | + enum btrfs_lock_nesting nest) |
|---|
| 1531 | 1485 | { |
|---|
| 1532 | 1486 | struct btrfs_fs_info *fs_info = root->fs_info; |
|---|
| 1533 | 1487 | u64 search_start; |
|---|
| 1534 | 1488 | int ret; |
|---|
| 1489 | + |
|---|
| 1490 | + if (test_bit(BTRFS_ROOT_DELETING, &root->state)) |
|---|
| 1491 | + btrfs_err(fs_info, |
|---|
| 1492 | + "COW'ing blocks on a fs root that's being dropped"); |
|---|
| 1535 | 1493 | |
|---|
| 1536 | 1494 | if (trans->transaction != fs_info->running_transaction) |
|---|
| 1537 | 1495 | WARN(1, KERN_CRIT "trans %llu running %llu\n", |
|---|
| .. | .. |
|---|
| 1551 | 1509 | search_start = buf->start & ~((u64)SZ_1G - 1); |
|---|
| 1552 | 1510 | |
|---|
| 1553 | 1511 | if (parent) |
|---|
| 1554 | | - btrfs_set_lock_blocking(parent); |
|---|
| 1555 | | - btrfs_set_lock_blocking(buf); |
|---|
| 1512 | + btrfs_set_lock_blocking_write(parent); |
|---|
| 1513 | + btrfs_set_lock_blocking_write(buf); |
|---|
| 1556 | 1514 | |
|---|
| 1515 | + /* |
|---|
| 1516 | + * Before CoWing this block for later modification, check if it's |
|---|
| 1517 | + * the subtree root and do the delayed subtree trace if needed. |
|---|
| 1518 | + * |
|---|
| 1519 | + * Also We don't care about the error, as it's handled internally. |
|---|
| 1520 | + */ |
|---|
| 1521 | + btrfs_qgroup_trace_subtree_after_cow(trans, root, buf); |
|---|
| 1557 | 1522 | ret = __btrfs_cow_block(trans, root, buf, parent, |
|---|
| 1558 | | - parent_slot, cow_ret, search_start, 0); |
|---|
| 1523 | + parent_slot, cow_ret, search_start, 0, nest); |
|---|
| 1559 | 1524 | |
|---|
| 1560 | 1525 | trace_btrfs_cow_block(root, buf, *cow_ret); |
|---|
| 1561 | 1526 | |
|---|
| .. | .. |
|---|
| 1575 | 1540 | return 0; |
|---|
| 1576 | 1541 | } |
|---|
| 1577 | 1542 | |
|---|
| 1543 | +#ifdef __LITTLE_ENDIAN |
|---|
| 1544 | + |
|---|
| 1545 | +/* |
|---|
| 1546 | + * Compare two keys, on little-endian the disk order is same as CPU order and |
|---|
| 1547 | + * we can avoid the conversion. |
|---|
| 1548 | + */ |
|---|
| 1549 | +static int comp_keys(const struct btrfs_disk_key *disk_key, |
|---|
| 1550 | + const struct btrfs_key *k2) |
|---|
| 1551 | +{ |
|---|
| 1552 | + const struct btrfs_key *k1 = (const struct btrfs_key *)disk_key; |
|---|
| 1553 | + |
|---|
| 1554 | + return btrfs_comp_cpu_keys(k1, k2); |
|---|
| 1555 | +} |
|---|
| 1556 | + |
|---|
| 1557 | +#else |
|---|
| 1558 | + |
|---|
| 1578 | 1559 | /* |
|---|
| 1579 | 1560 | * compare two keys in a memcmp fashion |
|---|
| 1580 | 1561 | */ |
|---|
| .. | .. |
|---|
| 1587 | 1568 | |
|---|
| 1588 | 1569 | return btrfs_comp_cpu_keys(&k1, k2); |
|---|
| 1589 | 1570 | } |
|---|
| 1571 | +#endif |
|---|
| 1590 | 1572 | |
|---|
| 1591 | 1573 | /* |
|---|
| 1592 | 1574 | * same as comp_keys only with two btrfs_key's |
|---|
| 1593 | 1575 | */ |
|---|
| 1594 | | -int btrfs_comp_cpu_keys(const struct btrfs_key *k1, const struct btrfs_key *k2) |
|---|
| 1576 | +int __pure btrfs_comp_cpu_keys(const struct btrfs_key *k1, const struct btrfs_key *k2) |
|---|
| 1595 | 1577 | { |
|---|
| 1596 | 1578 | if (k1->objectid > k2->objectid) |
|---|
| 1597 | 1579 | return 1; |
|---|
| .. | .. |
|---|
| 1647 | 1629 | if (parent_nritems <= 1) |
|---|
| 1648 | 1630 | return 0; |
|---|
| 1649 | 1631 | |
|---|
| 1650 | | - btrfs_set_lock_blocking(parent); |
|---|
| 1632 | + btrfs_set_lock_blocking_write(parent); |
|---|
| 1651 | 1633 | |
|---|
| 1652 | 1634 | for (i = start_slot; i <= end_slot; i++) { |
|---|
| 1653 | 1635 | struct btrfs_key first_key; |
|---|
| .. | .. |
|---|
| 1706 | 1688 | search_start = last_block; |
|---|
| 1707 | 1689 | |
|---|
| 1708 | 1690 | btrfs_tree_lock(cur); |
|---|
| 1709 | | - btrfs_set_lock_blocking(cur); |
|---|
| 1691 | + btrfs_set_lock_blocking_write(cur); |
|---|
| 1710 | 1692 | err = __btrfs_cow_block(trans, root, cur, parent, i, |
|---|
| 1711 | 1693 | &cur, search_start, |
|---|
| 1712 | 1694 | min(16 * blocksize, |
|---|
| 1713 | | - (end_slot - i) * blocksize)); |
|---|
| 1695 | + (end_slot - i) * blocksize), |
|---|
| 1696 | + BTRFS_NESTING_COW); |
|---|
| 1714 | 1697 | if (err) { |
|---|
| 1715 | 1698 | btrfs_tree_unlock(cur); |
|---|
| 1716 | 1699 | free_extent_buffer(cur); |
|---|
| .. | .. |
|---|
| 1742 | 1725 | { |
|---|
| 1743 | 1726 | int low = 0; |
|---|
| 1744 | 1727 | int high = max; |
|---|
| 1745 | | - int mid; |
|---|
| 1746 | 1728 | int ret; |
|---|
| 1747 | | - struct btrfs_disk_key *tmp = NULL; |
|---|
| 1748 | | - struct btrfs_disk_key unaligned; |
|---|
| 1749 | | - unsigned long offset; |
|---|
| 1750 | | - char *kaddr = NULL; |
|---|
| 1751 | | - unsigned long map_start = 0; |
|---|
| 1752 | | - unsigned long map_len = 0; |
|---|
| 1753 | | - int err; |
|---|
| 1729 | + const int key_size = sizeof(struct btrfs_disk_key); |
|---|
| 1754 | 1730 | |
|---|
| 1755 | 1731 | if (low > high) { |
|---|
| 1756 | 1732 | btrfs_err(eb->fs_info, |
|---|
| .. | .. |
|---|
| 1761 | 1737 | } |
|---|
| 1762 | 1738 | |
|---|
| 1763 | 1739 | while (low < high) { |
|---|
| 1740 | + unsigned long oip; |
|---|
| 1741 | + unsigned long offset; |
|---|
| 1742 | + struct btrfs_disk_key *tmp; |
|---|
| 1743 | + struct btrfs_disk_key unaligned; |
|---|
| 1744 | + int mid; |
|---|
| 1745 | + |
|---|
| 1764 | 1746 | mid = (low + high) / 2; |
|---|
| 1765 | 1747 | offset = p + mid * item_size; |
|---|
| 1748 | + oip = offset_in_page(offset); |
|---|
| 1766 | 1749 | |
|---|
| 1767 | | - if (!kaddr || offset < map_start || |
|---|
| 1768 | | - (offset + sizeof(struct btrfs_disk_key)) > |
|---|
| 1769 | | - map_start + map_len) { |
|---|
| 1750 | + if (oip + key_size <= PAGE_SIZE) { |
|---|
| 1751 | + const unsigned long idx = offset >> PAGE_SHIFT; |
|---|
| 1752 | + char *kaddr = page_address(eb->pages[idx]); |
|---|
| 1770 | 1753 | |
|---|
| 1771 | | - err = map_private_extent_buffer(eb, offset, |
|---|
| 1772 | | - sizeof(struct btrfs_disk_key), |
|---|
| 1773 | | - &kaddr, &map_start, &map_len); |
|---|
| 1774 | | - |
|---|
| 1775 | | - if (!err) { |
|---|
| 1776 | | - tmp = (struct btrfs_disk_key *)(kaddr + offset - |
|---|
| 1777 | | - map_start); |
|---|
| 1778 | | - } else if (err == 1) { |
|---|
| 1779 | | - read_extent_buffer(eb, &unaligned, |
|---|
| 1780 | | - offset, sizeof(unaligned)); |
|---|
| 1781 | | - tmp = &unaligned; |
|---|
| 1782 | | - } else { |
|---|
| 1783 | | - return err; |
|---|
| 1784 | | - } |
|---|
| 1785 | | - |
|---|
| 1754 | + tmp = (struct btrfs_disk_key *)(kaddr + oip); |
|---|
| 1786 | 1755 | } else { |
|---|
| 1787 | | - tmp = (struct btrfs_disk_key *)(kaddr + offset - |
|---|
| 1788 | | - map_start); |
|---|
| 1756 | + read_extent_buffer(eb, &unaligned, offset, key_size); |
|---|
| 1757 | + tmp = &unaligned; |
|---|
| 1789 | 1758 | } |
|---|
| 1759 | + |
|---|
| 1790 | 1760 | ret = comp_keys(tmp, key); |
|---|
| 1791 | 1761 | |
|---|
| 1792 | 1762 | if (ret < 0) |
|---|
| .. | .. |
|---|
| 1807 | 1777 | * leaves vs nodes |
|---|
| 1808 | 1778 | */ |
|---|
| 1809 | 1779 | int btrfs_bin_search(struct extent_buffer *eb, const struct btrfs_key *key, |
|---|
| 1810 | | - int level, int *slot) |
|---|
| 1780 | + int *slot) |
|---|
| 1811 | 1781 | { |
|---|
| 1812 | | - if (level == 0) |
|---|
| 1782 | + if (btrfs_header_level(eb) == 0) |
|---|
| 1813 | 1783 | return generic_bin_search(eb, |
|---|
| 1814 | 1784 | offsetof(struct btrfs_leaf, items), |
|---|
| 1815 | 1785 | sizeof(struct btrfs_item), |
|---|
| .. | .. |
|---|
| 1842 | 1812 | /* given a node and slot number, this reads the blocks it points to. The |
|---|
| 1843 | 1813 | * extent buffer is returned with a reference taken (but unlocked). |
|---|
| 1844 | 1814 | */ |
|---|
| 1845 | | -static noinline struct extent_buffer * |
|---|
| 1846 | | -read_node_slot(struct btrfs_fs_info *fs_info, struct extent_buffer *parent, |
|---|
| 1847 | | - int slot) |
|---|
| 1815 | +struct extent_buffer *btrfs_read_node_slot(struct extent_buffer *parent, |
|---|
| 1816 | + int slot) |
|---|
| 1848 | 1817 | { |
|---|
| 1849 | 1818 | int level = btrfs_header_level(parent); |
|---|
| 1850 | 1819 | struct extent_buffer *eb; |
|---|
| .. | .. |
|---|
| 1856 | 1825 | BUG_ON(level == 0); |
|---|
| 1857 | 1826 | |
|---|
| 1858 | 1827 | btrfs_node_key_to_cpu(parent, &first_key, slot); |
|---|
| 1859 | | - eb = read_tree_block(fs_info, btrfs_node_blockptr(parent, slot), |
|---|
| 1828 | + eb = read_tree_block(parent->fs_info, btrfs_node_blockptr(parent, slot), |
|---|
| 1860 | 1829 | btrfs_node_ptr_generation(parent, slot), |
|---|
| 1861 | 1830 | level - 1, &first_key); |
|---|
| 1862 | 1831 | if (!IS_ERR(eb) && !extent_buffer_uptodate(eb)) { |
|---|
| .. | .. |
|---|
| 1887 | 1856 | int orig_slot = path->slots[level]; |
|---|
| 1888 | 1857 | u64 orig_ptr; |
|---|
| 1889 | 1858 | |
|---|
| 1890 | | - if (level == 0) |
|---|
| 1891 | | - return 0; |
|---|
| 1859 | + ASSERT(level > 0); |
|---|
| 1892 | 1860 | |
|---|
| 1893 | 1861 | mid = path->nodes[level]; |
|---|
| 1894 | 1862 | |
|---|
| .. | .. |
|---|
| 1914 | 1882 | return 0; |
|---|
| 1915 | 1883 | |
|---|
| 1916 | 1884 | /* promote the child to a root */ |
|---|
| 1917 | | - child = read_node_slot(fs_info, mid, 0); |
|---|
| 1885 | + child = btrfs_read_node_slot(mid, 0); |
|---|
| 1918 | 1886 | if (IS_ERR(child)) { |
|---|
| 1919 | 1887 | ret = PTR_ERR(child); |
|---|
| 1920 | 1888 | btrfs_handle_fs_error(fs_info, ret, NULL); |
|---|
| .. | .. |
|---|
| 1922 | 1890 | } |
|---|
| 1923 | 1891 | |
|---|
| 1924 | 1892 | btrfs_tree_lock(child); |
|---|
| 1925 | | - btrfs_set_lock_blocking(child); |
|---|
| 1926 | | - ret = btrfs_cow_block(trans, root, child, mid, 0, &child); |
|---|
| 1893 | + btrfs_set_lock_blocking_write(child); |
|---|
| 1894 | + ret = btrfs_cow_block(trans, root, child, mid, 0, &child, |
|---|
| 1895 | + BTRFS_NESTING_COW); |
|---|
| 1927 | 1896 | if (ret) { |
|---|
| 1928 | 1897 | btrfs_tree_unlock(child); |
|---|
| 1929 | 1898 | free_extent_buffer(child); |
|---|
| .. | .. |
|---|
| 1939 | 1908 | |
|---|
| 1940 | 1909 | path->locks[level] = 0; |
|---|
| 1941 | 1910 | path->nodes[level] = NULL; |
|---|
| 1942 | | - clean_tree_block(fs_info, mid); |
|---|
| 1911 | + btrfs_clean_tree_block(mid); |
|---|
| 1943 | 1912 | btrfs_tree_unlock(mid); |
|---|
| 1944 | 1913 | /* once for the path */ |
|---|
| 1945 | 1914 | free_extent_buffer(mid); |
|---|
| .. | .. |
|---|
| 1954 | 1923 | BTRFS_NODEPTRS_PER_BLOCK(fs_info) / 4) |
|---|
| 1955 | 1924 | return 0; |
|---|
| 1956 | 1925 | |
|---|
| 1957 | | - left = read_node_slot(fs_info, parent, pslot - 1); |
|---|
| 1926 | + left = btrfs_read_node_slot(parent, pslot - 1); |
|---|
| 1958 | 1927 | if (IS_ERR(left)) |
|---|
| 1959 | 1928 | left = NULL; |
|---|
| 1960 | 1929 | |
|---|
| 1961 | 1930 | if (left) { |
|---|
| 1962 | | - btrfs_tree_lock(left); |
|---|
| 1963 | | - btrfs_set_lock_blocking(left); |
|---|
| 1931 | + __btrfs_tree_lock(left, BTRFS_NESTING_LEFT); |
|---|
| 1932 | + btrfs_set_lock_blocking_write(left); |
|---|
| 1964 | 1933 | wret = btrfs_cow_block(trans, root, left, |
|---|
| 1965 | | - parent, pslot - 1, &left); |
|---|
| 1934 | + parent, pslot - 1, &left, |
|---|
| 1935 | + BTRFS_NESTING_LEFT_COW); |
|---|
| 1966 | 1936 | if (wret) { |
|---|
| 1967 | 1937 | ret = wret; |
|---|
| 1968 | 1938 | goto enospc; |
|---|
| 1969 | 1939 | } |
|---|
| 1970 | 1940 | } |
|---|
| 1971 | 1941 | |
|---|
| 1972 | | - right = read_node_slot(fs_info, parent, pslot + 1); |
|---|
| 1942 | + right = btrfs_read_node_slot(parent, pslot + 1); |
|---|
| 1973 | 1943 | if (IS_ERR(right)) |
|---|
| 1974 | 1944 | right = NULL; |
|---|
| 1975 | 1945 | |
|---|
| 1976 | 1946 | if (right) { |
|---|
| 1977 | | - btrfs_tree_lock(right); |
|---|
| 1978 | | - btrfs_set_lock_blocking(right); |
|---|
| 1947 | + __btrfs_tree_lock(right, BTRFS_NESTING_RIGHT); |
|---|
| 1948 | + btrfs_set_lock_blocking_write(right); |
|---|
| 1979 | 1949 | wret = btrfs_cow_block(trans, root, right, |
|---|
| 1980 | | - parent, pslot + 1, &right); |
|---|
| 1950 | + parent, pslot + 1, &right, |
|---|
| 1951 | + BTRFS_NESTING_RIGHT_COW); |
|---|
| 1981 | 1952 | if (wret) { |
|---|
| 1982 | 1953 | ret = wret; |
|---|
| 1983 | 1954 | goto enospc; |
|---|
| .. | .. |
|---|
| 1987 | 1958 | /* first, try to make some room in the middle buffer */ |
|---|
| 1988 | 1959 | if (left) { |
|---|
| 1989 | 1960 | orig_slot += btrfs_header_nritems(left); |
|---|
| 1990 | | - wret = push_node_left(trans, fs_info, left, mid, 1); |
|---|
| 1961 | + wret = push_node_left(trans, left, mid, 1); |
|---|
| 1991 | 1962 | if (wret < 0) |
|---|
| 1992 | 1963 | ret = wret; |
|---|
| 1993 | 1964 | } |
|---|
| .. | .. |
|---|
| 1996 | 1967 | * then try to empty the right most buffer into the middle |
|---|
| 1997 | 1968 | */ |
|---|
| 1998 | 1969 | if (right) { |
|---|
| 1999 | | - wret = push_node_left(trans, fs_info, mid, right, 1); |
|---|
| 1970 | + wret = push_node_left(trans, mid, right, 1); |
|---|
| 2000 | 1971 | if (wret < 0 && wret != -ENOSPC) |
|---|
| 2001 | 1972 | ret = wret; |
|---|
| 2002 | 1973 | if (btrfs_header_nritems(right) == 0) { |
|---|
| 2003 | | - clean_tree_block(fs_info, right); |
|---|
| 1974 | + btrfs_clean_tree_block(right); |
|---|
| 2004 | 1975 | btrfs_tree_unlock(right); |
|---|
| 2005 | 1976 | del_ptr(root, path, level + 1, pslot + 1); |
|---|
| 2006 | 1977 | root_sub_used(root, right->len); |
|---|
| .. | .. |
|---|
| 2032 | 2003 | btrfs_handle_fs_error(fs_info, ret, NULL); |
|---|
| 2033 | 2004 | goto enospc; |
|---|
| 2034 | 2005 | } |
|---|
| 2035 | | - wret = balance_node_right(trans, fs_info, mid, left); |
|---|
| 2006 | + wret = balance_node_right(trans, mid, left); |
|---|
| 2036 | 2007 | if (wret < 0) { |
|---|
| 2037 | 2008 | ret = wret; |
|---|
| 2038 | 2009 | goto enospc; |
|---|
| 2039 | 2010 | } |
|---|
| 2040 | 2011 | if (wret == 1) { |
|---|
| 2041 | | - wret = push_node_left(trans, fs_info, left, mid, 1); |
|---|
| 2012 | + wret = push_node_left(trans, left, mid, 1); |
|---|
| 2042 | 2013 | if (wret < 0) |
|---|
| 2043 | 2014 | ret = wret; |
|---|
| 2044 | 2015 | } |
|---|
| 2045 | 2016 | BUG_ON(wret == 1); |
|---|
| 2046 | 2017 | } |
|---|
| 2047 | 2018 | if (btrfs_header_nritems(mid) == 0) { |
|---|
| 2048 | | - clean_tree_block(fs_info, mid); |
|---|
| 2019 | + btrfs_clean_tree_block(mid); |
|---|
| 2049 | 2020 | btrfs_tree_unlock(mid); |
|---|
| 2050 | 2021 | del_ptr(root, path, level + 1, pslot); |
|---|
| 2051 | 2022 | root_sub_used(root, mid->len); |
|---|
| .. | .. |
|---|
| 2066 | 2037 | /* update the path */ |
|---|
| 2067 | 2038 | if (left) { |
|---|
| 2068 | 2039 | if (btrfs_header_nritems(left) > orig_slot) { |
|---|
| 2069 | | - extent_buffer_get(left); |
|---|
| 2040 | + atomic_inc(&left->refs); |
|---|
| 2070 | 2041 | /* left was locked after cow */ |
|---|
| 2071 | 2042 | path->nodes[level] = left; |
|---|
| 2072 | 2043 | path->slots[level + 1] -= 1; |
|---|
| .. | .. |
|---|
| 2129 | 2100 | if (!parent) |
|---|
| 2130 | 2101 | return 1; |
|---|
| 2131 | 2102 | |
|---|
| 2132 | | - left = read_node_slot(fs_info, parent, pslot - 1); |
|---|
| 2103 | + left = btrfs_read_node_slot(parent, pslot - 1); |
|---|
| 2133 | 2104 | if (IS_ERR(left)) |
|---|
| 2134 | 2105 | left = NULL; |
|---|
| 2135 | 2106 | |
|---|
| .. | .. |
|---|
| 2137 | 2108 | if (left) { |
|---|
| 2138 | 2109 | u32 left_nr; |
|---|
| 2139 | 2110 | |
|---|
| 2140 | | - btrfs_tree_lock(left); |
|---|
| 2141 | | - btrfs_set_lock_blocking(left); |
|---|
| 2111 | + __btrfs_tree_lock(left, BTRFS_NESTING_LEFT); |
|---|
| 2112 | + btrfs_set_lock_blocking_write(left); |
|---|
| 2142 | 2113 | |
|---|
| 2143 | 2114 | left_nr = btrfs_header_nritems(left); |
|---|
| 2144 | 2115 | if (left_nr >= BTRFS_NODEPTRS_PER_BLOCK(fs_info) - 1) { |
|---|
| 2145 | 2116 | wret = 1; |
|---|
| 2146 | 2117 | } else { |
|---|
| 2147 | 2118 | ret = btrfs_cow_block(trans, root, left, parent, |
|---|
| 2148 | | - pslot - 1, &left); |
|---|
| 2119 | + pslot - 1, &left, |
|---|
| 2120 | + BTRFS_NESTING_LEFT_COW); |
|---|
| 2149 | 2121 | if (ret) |
|---|
| 2150 | 2122 | wret = 1; |
|---|
| 2151 | 2123 | else { |
|---|
| 2152 | | - wret = push_node_left(trans, fs_info, |
|---|
| 2153 | | - left, mid, 0); |
|---|
| 2124 | + wret = push_node_left(trans, left, mid, 0); |
|---|
| 2154 | 2125 | } |
|---|
| 2155 | 2126 | } |
|---|
| 2156 | 2127 | if (wret < 0) |
|---|
| .. | .. |
|---|
| 2182 | 2153 | btrfs_tree_unlock(left); |
|---|
| 2183 | 2154 | free_extent_buffer(left); |
|---|
| 2184 | 2155 | } |
|---|
| 2185 | | - right = read_node_slot(fs_info, parent, pslot + 1); |
|---|
| 2156 | + right = btrfs_read_node_slot(parent, pslot + 1); |
|---|
| 2186 | 2157 | if (IS_ERR(right)) |
|---|
| 2187 | 2158 | right = NULL; |
|---|
| 2188 | 2159 | |
|---|
| .. | .. |
|---|
| 2192 | 2163 | if (right) { |
|---|
| 2193 | 2164 | u32 right_nr; |
|---|
| 2194 | 2165 | |
|---|
| 2195 | | - btrfs_tree_lock(right); |
|---|
| 2196 | | - btrfs_set_lock_blocking(right); |
|---|
| 2166 | + __btrfs_tree_lock(right, BTRFS_NESTING_RIGHT); |
|---|
| 2167 | + btrfs_set_lock_blocking_write(right); |
|---|
| 2197 | 2168 | |
|---|
| 2198 | 2169 | right_nr = btrfs_header_nritems(right); |
|---|
| 2199 | 2170 | if (right_nr >= BTRFS_NODEPTRS_PER_BLOCK(fs_info) - 1) { |
|---|
| .. | .. |
|---|
| 2201 | 2172 | } else { |
|---|
| 2202 | 2173 | ret = btrfs_cow_block(trans, root, right, |
|---|
| 2203 | 2174 | parent, pslot + 1, |
|---|
| 2204 | | - &right); |
|---|
| 2175 | + &right, BTRFS_NESTING_RIGHT_COW); |
|---|
| 2205 | 2176 | if (ret) |
|---|
| 2206 | 2177 | wret = 1; |
|---|
| 2207 | 2178 | else { |
|---|
| 2208 | | - wret = balance_node_right(trans, fs_info, |
|---|
| 2209 | | - right, mid); |
|---|
| 2179 | + wret = balance_node_right(trans, right, mid); |
|---|
| 2210 | 2180 | } |
|---|
| 2211 | 2181 | } |
|---|
| 2212 | 2182 | if (wret < 0) |
|---|
| .. | .. |
|---|
| 2411 | 2381 | } |
|---|
| 2412 | 2382 | |
|---|
| 2413 | 2383 | /* |
|---|
| 2414 | | - * This releases any locks held in the path starting at level and |
|---|
| 2415 | | - * going all the way up to the root. |
|---|
| 2416 | | - * |
|---|
| 2417 | | - * btrfs_search_slot will keep the lock held on higher nodes in a few |
|---|
| 2418 | | - * corner cases, such as COW of the block at slot zero in the node. This |
|---|
| 2419 | | - * ignores those rules, and it should only be called when there are no |
|---|
| 2420 | | - * more updates to be done higher up in the tree. |
|---|
| 2421 | | - */ |
|---|
| 2422 | | -noinline void btrfs_unlock_up_safe(struct btrfs_path *path, int level) |
|---|
| 2423 | | -{ |
|---|
| 2424 | | - int i; |
|---|
| 2425 | | - |
|---|
| 2426 | | - if (path->keep_locks) |
|---|
| 2427 | | - return; |
|---|
| 2428 | | - |
|---|
| 2429 | | - for (i = level; i < BTRFS_MAX_LEVEL; i++) { |
|---|
| 2430 | | - if (!path->nodes[i]) |
|---|
| 2431 | | - continue; |
|---|
| 2432 | | - if (!path->locks[i]) |
|---|
| 2433 | | - continue; |
|---|
| 2434 | | - btrfs_tree_unlock_rw(path->nodes[i], path->locks[i]); |
|---|
| 2435 | | - path->locks[i] = 0; |
|---|
| 2436 | | - } |
|---|
| 2437 | | -} |
|---|
| 2438 | | - |
|---|
| 2439 | | -/* |
|---|
| 2440 | 2384 | * helper function for btrfs_search_slot. The goal is to find a block |
|---|
| 2441 | 2385 | * in cache without setting the path to blocking. If we find the block |
|---|
| 2442 | 2386 | * we return zero and the path is unchanged. |
|---|
| .. | .. |
|---|
| 2452 | 2396 | struct btrfs_fs_info *fs_info = root->fs_info; |
|---|
| 2453 | 2397 | u64 blocknr; |
|---|
| 2454 | 2398 | u64 gen; |
|---|
| 2455 | | - struct extent_buffer *b = *eb_ret; |
|---|
| 2456 | 2399 | struct extent_buffer *tmp; |
|---|
| 2457 | 2400 | struct btrfs_key first_key; |
|---|
| 2458 | 2401 | int ret; |
|---|
| 2459 | 2402 | int parent_level; |
|---|
| 2460 | 2403 | |
|---|
| 2461 | | - blocknr = btrfs_node_blockptr(b, slot); |
|---|
| 2462 | | - gen = btrfs_node_ptr_generation(b, slot); |
|---|
| 2463 | | - parent_level = btrfs_header_level(b); |
|---|
| 2464 | | - btrfs_node_key_to_cpu(b, &first_key, slot); |
|---|
| 2404 | + blocknr = btrfs_node_blockptr(*eb_ret, slot); |
|---|
| 2405 | + gen = btrfs_node_ptr_generation(*eb_ret, slot); |
|---|
| 2406 | + parent_level = btrfs_header_level(*eb_ret); |
|---|
| 2407 | + btrfs_node_key_to_cpu(*eb_ret, &first_key, slot); |
|---|
| 2465 | 2408 | |
|---|
| 2466 | 2409 | tmp = find_extent_buffer(fs_info, blocknr); |
|---|
| 2467 | 2410 | if (tmp) { |
|---|
| .. | .. |
|---|
| 2472 | 2415 | * being cached, read from scrub, or have multiple |
|---|
| 2473 | 2416 | * parents (shared tree blocks). |
|---|
| 2474 | 2417 | */ |
|---|
| 2475 | | - if (btrfs_verify_level_key(fs_info, tmp, |
|---|
| 2418 | + if (btrfs_verify_level_key(tmp, |
|---|
| 2476 | 2419 | parent_level - 1, &first_key, gen)) { |
|---|
| 2477 | 2420 | free_extent_buffer(tmp); |
|---|
| 2478 | 2421 | return -EUCLEAN; |
|---|
| .. | .. |
|---|
| 2565 | 2508 | btrfs_set_path_blocking(p); |
|---|
| 2566 | 2509 | reada_for_balance(fs_info, p, level); |
|---|
| 2567 | 2510 | sret = split_node(trans, root, p, level); |
|---|
| 2568 | | - btrfs_clear_path_blocking(p, NULL, 0); |
|---|
| 2569 | 2511 | |
|---|
| 2570 | 2512 | BUG_ON(sret > 0); |
|---|
| 2571 | 2513 | if (sret) { |
|---|
| .. | .. |
|---|
| 2586 | 2528 | btrfs_set_path_blocking(p); |
|---|
| 2587 | 2529 | reada_for_balance(fs_info, p, level); |
|---|
| 2588 | 2530 | sret = balance_level(trans, root, p, level); |
|---|
| 2589 | | - btrfs_clear_path_blocking(p, NULL, 0); |
|---|
| 2590 | 2531 | |
|---|
| 2591 | 2532 | if (sret) { |
|---|
| 2592 | 2533 | ret = sret; |
|---|
| .. | .. |
|---|
| 2605 | 2546 | ret = -EAGAIN; |
|---|
| 2606 | 2547 | done: |
|---|
| 2607 | 2548 | return ret; |
|---|
| 2608 | | -} |
|---|
| 2609 | | - |
|---|
| 2610 | | -static void key_search_validate(struct extent_buffer *b, |
|---|
| 2611 | | - const struct btrfs_key *key, |
|---|
| 2612 | | - int level) |
|---|
| 2613 | | -{ |
|---|
| 2614 | | -#ifdef CONFIG_BTRFS_ASSERT |
|---|
| 2615 | | - struct btrfs_disk_key disk_key; |
|---|
| 2616 | | - |
|---|
| 2617 | | - btrfs_cpu_key_to_disk(&disk_key, key); |
|---|
| 2618 | | - |
|---|
| 2619 | | - if (level == 0) |
|---|
| 2620 | | - ASSERT(!memcmp_extent_buffer(b, &disk_key, |
|---|
| 2621 | | - offsetof(struct btrfs_leaf, items[0].key), |
|---|
| 2622 | | - sizeof(disk_key))); |
|---|
| 2623 | | - else |
|---|
| 2624 | | - ASSERT(!memcmp_extent_buffer(b, &disk_key, |
|---|
| 2625 | | - offsetof(struct btrfs_node, ptrs[0].key), |
|---|
| 2626 | | - sizeof(disk_key))); |
|---|
| 2627 | | -#endif |
|---|
| 2628 | | -} |
|---|
| 2629 | | - |
|---|
| 2630 | | -static int key_search(struct extent_buffer *b, const struct btrfs_key *key, |
|---|
| 2631 | | - int level, int *prev_cmp, int *slot) |
|---|
| 2632 | | -{ |
|---|
| 2633 | | - if (*prev_cmp != 0) { |
|---|
| 2634 | | - *prev_cmp = btrfs_bin_search(b, key, level, slot); |
|---|
| 2635 | | - return *prev_cmp; |
|---|
| 2636 | | - } |
|---|
| 2637 | | - |
|---|
| 2638 | | - key_search_validate(b, key, level); |
|---|
| 2639 | | - *slot = 0; |
|---|
| 2640 | | - |
|---|
| 2641 | | - return 0; |
|---|
| 2642 | 2549 | } |
|---|
| 2643 | 2550 | |
|---|
| 2644 | 2551 | int btrfs_find_item(struct btrfs_root *fs_root, struct btrfs_path *path, |
|---|
| .. | .. |
|---|
| 2682 | 2589 | { |
|---|
| 2683 | 2590 | struct btrfs_fs_info *fs_info = root->fs_info; |
|---|
| 2684 | 2591 | struct extent_buffer *b; |
|---|
| 2685 | | - int root_lock; |
|---|
| 2592 | + int root_lock = 0; |
|---|
| 2686 | 2593 | int level = 0; |
|---|
| 2687 | | - |
|---|
| 2688 | | - /* We try very hard to do read locks on the root */ |
|---|
| 2689 | | - root_lock = BTRFS_READ_LOCK; |
|---|
| 2690 | 2594 | |
|---|
| 2691 | 2595 | if (p->search_commit_root) { |
|---|
| 2692 | 2596 | /* |
|---|
| .. | .. |
|---|
| 2707 | 2611 | |
|---|
| 2708 | 2612 | } else { |
|---|
| 2709 | 2613 | b = root->commit_root; |
|---|
| 2710 | | - extent_buffer_get(b); |
|---|
| 2614 | + atomic_inc(&b->refs); |
|---|
| 2711 | 2615 | } |
|---|
| 2712 | 2616 | level = btrfs_header_level(b); |
|---|
| 2713 | 2617 | /* |
|---|
| .. | .. |
|---|
| 2725 | 2629 | goto out; |
|---|
| 2726 | 2630 | } |
|---|
| 2727 | 2631 | |
|---|
| 2632 | + /* We try very hard to do read locks on the root */ |
|---|
| 2633 | + root_lock = BTRFS_READ_LOCK; |
|---|
| 2634 | + |
|---|
| 2728 | 2635 | /* |
|---|
| 2729 | 2636 | * If the level is set to maximum, we can skip trying to get the read |
|---|
| 2730 | 2637 | * lock. |
|---|
| .. | .. |
|---|
| 2734 | 2641 | * We don't know the level of the root node until we actually |
|---|
| 2735 | 2642 | * have it read locked |
|---|
| 2736 | 2643 | */ |
|---|
| 2737 | | - b = btrfs_read_lock_root_node(root); |
|---|
| 2644 | + b = __btrfs_read_lock_root_node(root, p->recurse); |
|---|
| 2738 | 2645 | level = btrfs_header_level(b); |
|---|
| 2739 | 2646 | if (level > write_lock_level) |
|---|
| 2740 | 2647 | goto out; |
|---|
| .. | .. |
|---|
| 2751 | 2658 | level = btrfs_header_level(b); |
|---|
| 2752 | 2659 | |
|---|
| 2753 | 2660 | out: |
|---|
| 2661 | + /* |
|---|
| 2662 | + * The root may have failed to write out at some point, and thus is no |
|---|
| 2663 | + * longer valid, return an error in this case. |
|---|
| 2664 | + */ |
|---|
| 2665 | + if (!extent_buffer_uptodate(b)) { |
|---|
| 2666 | + if (root_lock) |
|---|
| 2667 | + btrfs_tree_unlock_rw(b, root_lock); |
|---|
| 2668 | + free_extent_buffer(b); |
|---|
| 2669 | + return ERR_PTR(-EIO); |
|---|
| 2670 | + } |
|---|
| 2671 | + |
|---|
| 2754 | 2672 | p->nodes[level] = b; |
|---|
| 2755 | 2673 | if (!p->skip_locking) |
|---|
| 2756 | 2674 | p->locks[level] = root_lock; |
|---|
| .. | .. |
|---|
| 2790 | 2708 | const struct btrfs_key *key, struct btrfs_path *p, |
|---|
| 2791 | 2709 | int ins_len, int cow) |
|---|
| 2792 | 2710 | { |
|---|
| 2793 | | - struct btrfs_fs_info *fs_info = root->fs_info; |
|---|
| 2794 | 2711 | struct extent_buffer *b; |
|---|
| 2795 | 2712 | int slot; |
|---|
| 2796 | 2713 | int ret; |
|---|
| .. | .. |
|---|
| 2841 | 2758 | } |
|---|
| 2842 | 2759 | |
|---|
| 2843 | 2760 | while (b) { |
|---|
| 2761 | + int dec = 0; |
|---|
| 2762 | + |
|---|
| 2844 | 2763 | level = btrfs_header_level(b); |
|---|
| 2845 | 2764 | |
|---|
| 2846 | | - /* |
|---|
| 2847 | | - * setup the path here so we can release it under lock |
|---|
| 2848 | | - * contention with the cow code |
|---|
| 2849 | | - */ |
|---|
| 2850 | 2765 | if (cow) { |
|---|
| 2851 | 2766 | bool last_level = (level == (BTRFS_MAX_LEVEL - 1)); |
|---|
| 2852 | 2767 | |
|---|
| .. | .. |
|---|
| 2876 | 2791 | btrfs_set_path_blocking(p); |
|---|
| 2877 | 2792 | if (last_level) |
|---|
| 2878 | 2793 | err = btrfs_cow_block(trans, root, b, NULL, 0, |
|---|
| 2879 | | - &b); |
|---|
| 2794 | + &b, |
|---|
| 2795 | + BTRFS_NESTING_COW); |
|---|
| 2880 | 2796 | else |
|---|
| 2881 | 2797 | err = btrfs_cow_block(trans, root, b, |
|---|
| 2882 | 2798 | p->nodes[level + 1], |
|---|
| 2883 | | - p->slots[level + 1], &b); |
|---|
| 2799 | + p->slots[level + 1], &b, |
|---|
| 2800 | + BTRFS_NESTING_COW); |
|---|
| 2884 | 2801 | if (err) { |
|---|
| 2885 | 2802 | ret = err; |
|---|
| 2886 | 2803 | goto done; |
|---|
| .. | .. |
|---|
| 2888 | 2805 | } |
|---|
| 2889 | 2806 | cow_done: |
|---|
| 2890 | 2807 | p->nodes[level] = b; |
|---|
| 2891 | | - btrfs_clear_path_blocking(p, NULL, 0); |
|---|
| 2808 | + /* |
|---|
| 2809 | + * Leave path with blocking locks to avoid massive |
|---|
| 2810 | + * lock context switch, this is made on purpose. |
|---|
| 2811 | + */ |
|---|
| 2892 | 2812 | |
|---|
| 2893 | 2813 | /* |
|---|
| 2894 | 2814 | * we have a lock on b and as long as we aren't changing |
|---|
| .. | .. |
|---|
| 2910 | 2830 | } |
|---|
| 2911 | 2831 | } |
|---|
| 2912 | 2832 | |
|---|
| 2913 | | - ret = key_search(b, key, level, &prev_cmp, &slot); |
|---|
| 2914 | | - if (ret < 0) |
|---|
| 2915 | | - goto done; |
|---|
| 2916 | | - |
|---|
| 2917 | | - if (level != 0) { |
|---|
| 2918 | | - int dec = 0; |
|---|
| 2919 | | - if (ret && slot > 0) { |
|---|
| 2920 | | - dec = 1; |
|---|
| 2921 | | - slot -= 1; |
|---|
| 2922 | | - } |
|---|
| 2923 | | - p->slots[level] = slot; |
|---|
| 2924 | | - err = setup_nodes_for_search(trans, root, p, b, level, |
|---|
| 2925 | | - ins_len, &write_lock_level); |
|---|
| 2926 | | - if (err == -EAGAIN) |
|---|
| 2927 | | - goto again; |
|---|
| 2928 | | - if (err) { |
|---|
| 2929 | | - ret = err; |
|---|
| 2930 | | - goto done; |
|---|
| 2931 | | - } |
|---|
| 2932 | | - b = p->nodes[level]; |
|---|
| 2933 | | - slot = p->slots[level]; |
|---|
| 2934 | | - |
|---|
| 2935 | | - /* |
|---|
| 2936 | | - * slot 0 is special, if we change the key |
|---|
| 2937 | | - * we have to update the parent pointer |
|---|
| 2938 | | - * which means we must have a write lock |
|---|
| 2939 | | - * on the parent |
|---|
| 2940 | | - */ |
|---|
| 2941 | | - if (slot == 0 && ins_len && |
|---|
| 2942 | | - write_lock_level < level + 1) { |
|---|
| 2943 | | - write_lock_level = level + 1; |
|---|
| 2944 | | - btrfs_release_path(p); |
|---|
| 2945 | | - goto again; |
|---|
| 2946 | | - } |
|---|
| 2947 | | - |
|---|
| 2948 | | - unlock_up(p, level, lowest_unlock, |
|---|
| 2949 | | - min_write_lock_level, &write_lock_level); |
|---|
| 2950 | | - |
|---|
| 2951 | | - if (level == lowest_level) { |
|---|
| 2952 | | - if (dec) |
|---|
| 2953 | | - p->slots[level]++; |
|---|
| 2954 | | - goto done; |
|---|
| 2955 | | - } |
|---|
| 2956 | | - |
|---|
| 2957 | | - err = read_block_for_search(root, p, &b, level, |
|---|
| 2958 | | - slot, key); |
|---|
| 2959 | | - if (err == -EAGAIN) |
|---|
| 2960 | | - goto again; |
|---|
| 2961 | | - if (err) { |
|---|
| 2962 | | - ret = err; |
|---|
| 2963 | | - goto done; |
|---|
| 2964 | | - } |
|---|
| 2965 | | - |
|---|
| 2966 | | - if (!p->skip_locking) { |
|---|
| 2967 | | - level = btrfs_header_level(b); |
|---|
| 2968 | | - if (level <= write_lock_level) { |
|---|
| 2969 | | - err = btrfs_try_tree_write_lock(b); |
|---|
| 2970 | | - if (!err) { |
|---|
| 2971 | | - btrfs_set_path_blocking(p); |
|---|
| 2972 | | - btrfs_tree_lock(b); |
|---|
| 2973 | | - btrfs_clear_path_blocking(p, b, |
|---|
| 2974 | | - BTRFS_WRITE_LOCK); |
|---|
| 2975 | | - } |
|---|
| 2976 | | - p->locks[level] = BTRFS_WRITE_LOCK; |
|---|
| 2977 | | - } else { |
|---|
| 2978 | | - err = btrfs_tree_read_lock_atomic(b); |
|---|
| 2979 | | - if (!err) { |
|---|
| 2980 | | - btrfs_set_path_blocking(p); |
|---|
| 2981 | | - btrfs_tree_read_lock(b); |
|---|
| 2982 | | - btrfs_clear_path_blocking(p, b, |
|---|
| 2983 | | - BTRFS_READ_LOCK); |
|---|
| 2984 | | - } |
|---|
| 2985 | | - p->locks[level] = BTRFS_READ_LOCK; |
|---|
| 2986 | | - } |
|---|
| 2987 | | - p->nodes[level] = b; |
|---|
| 2988 | | - } |
|---|
| 2833 | + /* |
|---|
| 2834 | + * If btrfs_bin_search returns an exact match (prev_cmp == 0) |
|---|
| 2835 | + * we can safely assume the target key will always be in slot 0 |
|---|
| 2836 | + * on lower levels due to the invariants BTRFS' btree provides, |
|---|
| 2837 | + * namely that a btrfs_key_ptr entry always points to the |
|---|
| 2838 | + * lowest key in the child node, thus we can skip searching |
|---|
| 2839 | + * lower levels |
|---|
| 2840 | + */ |
|---|
| 2841 | + if (prev_cmp == 0) { |
|---|
| 2842 | + slot = 0; |
|---|
| 2843 | + ret = 0; |
|---|
| 2989 | 2844 | } else { |
|---|
| 2845 | + ret = btrfs_bin_search(b, key, &slot); |
|---|
| 2846 | + prev_cmp = ret; |
|---|
| 2847 | + if (ret < 0) |
|---|
| 2848 | + goto done; |
|---|
| 2849 | + } |
|---|
| 2850 | + |
|---|
| 2851 | + if (level == 0) { |
|---|
| 2990 | 2852 | p->slots[level] = slot; |
|---|
| 2991 | 2853 | if (ins_len > 0 && |
|---|
| 2992 | | - btrfs_leaf_free_space(fs_info, b) < ins_len) { |
|---|
| 2854 | + btrfs_leaf_free_space(b) < ins_len) { |
|---|
| 2993 | 2855 | if (write_lock_level < 1) { |
|---|
| 2994 | 2856 | write_lock_level = 1; |
|---|
| 2995 | 2857 | btrfs_release_path(p); |
|---|
| .. | .. |
|---|
| 2999 | 2861 | btrfs_set_path_blocking(p); |
|---|
| 3000 | 2862 | err = split_leaf(trans, root, key, |
|---|
| 3001 | 2863 | p, ins_len, ret == 0); |
|---|
| 3002 | | - btrfs_clear_path_blocking(p, NULL, 0); |
|---|
| 3003 | 2864 | |
|---|
| 3004 | 2865 | BUG_ON(err > 0); |
|---|
| 3005 | 2866 | if (err) { |
|---|
| .. | .. |
|---|
| 3009 | 2870 | } |
|---|
| 3010 | 2871 | if (!p->search_for_split) |
|---|
| 3011 | 2872 | unlock_up(p, level, lowest_unlock, |
|---|
| 3012 | | - min_write_lock_level, &write_lock_level); |
|---|
| 2873 | + min_write_lock_level, NULL); |
|---|
| 3013 | 2874 | goto done; |
|---|
| 2875 | + } |
|---|
| 2876 | + if (ret && slot > 0) { |
|---|
| 2877 | + dec = 1; |
|---|
| 2878 | + slot--; |
|---|
| 2879 | + } |
|---|
| 2880 | + p->slots[level] = slot; |
|---|
| 2881 | + err = setup_nodes_for_search(trans, root, p, b, level, ins_len, |
|---|
| 2882 | + &write_lock_level); |
|---|
| 2883 | + if (err == -EAGAIN) |
|---|
| 2884 | + goto again; |
|---|
| 2885 | + if (err) { |
|---|
| 2886 | + ret = err; |
|---|
| 2887 | + goto done; |
|---|
| 2888 | + } |
|---|
| 2889 | + b = p->nodes[level]; |
|---|
| 2890 | + slot = p->slots[level]; |
|---|
| 2891 | + |
|---|
| 2892 | + /* |
|---|
| 2893 | + * Slot 0 is special, if we change the key we have to update |
|---|
| 2894 | + * the parent pointer which means we must have a write lock on |
|---|
| 2895 | + * the parent |
|---|
| 2896 | + */ |
|---|
| 2897 | + if (slot == 0 && ins_len && write_lock_level < level + 1) { |
|---|
| 2898 | + write_lock_level = level + 1; |
|---|
| 2899 | + btrfs_release_path(p); |
|---|
| 2900 | + goto again; |
|---|
| 2901 | + } |
|---|
| 2902 | + |
|---|
| 2903 | + unlock_up(p, level, lowest_unlock, min_write_lock_level, |
|---|
| 2904 | + &write_lock_level); |
|---|
| 2905 | + |
|---|
| 2906 | + if (level == lowest_level) { |
|---|
| 2907 | + if (dec) |
|---|
| 2908 | + p->slots[level]++; |
|---|
| 2909 | + goto done; |
|---|
| 2910 | + } |
|---|
| 2911 | + |
|---|
| 2912 | + err = read_block_for_search(root, p, &b, level, slot, key); |
|---|
| 2913 | + if (err == -EAGAIN) |
|---|
| 2914 | + goto again; |
|---|
| 2915 | + if (err) { |
|---|
| 2916 | + ret = err; |
|---|
| 2917 | + goto done; |
|---|
| 2918 | + } |
|---|
| 2919 | + |
|---|
| 2920 | + if (!p->skip_locking) { |
|---|
| 2921 | + level = btrfs_header_level(b); |
|---|
| 2922 | + if (level <= write_lock_level) { |
|---|
| 2923 | + if (!btrfs_try_tree_write_lock(b)) { |
|---|
| 2924 | + btrfs_set_path_blocking(p); |
|---|
| 2925 | + btrfs_tree_lock(b); |
|---|
| 2926 | + } |
|---|
| 2927 | + p->locks[level] = BTRFS_WRITE_LOCK; |
|---|
| 2928 | + } else { |
|---|
| 2929 | + if (!btrfs_tree_read_lock_atomic(b)) { |
|---|
| 2930 | + btrfs_set_path_blocking(p); |
|---|
| 2931 | + __btrfs_tree_read_lock(b, BTRFS_NESTING_NORMAL, |
|---|
| 2932 | + p->recurse); |
|---|
| 2933 | + } |
|---|
| 2934 | + p->locks[level] = BTRFS_READ_LOCK; |
|---|
| 2935 | + } |
|---|
| 2936 | + p->nodes[level] = b; |
|---|
| 3014 | 2937 | } |
|---|
| 3015 | 2938 | } |
|---|
| 3016 | 2939 | ret = 1; |
|---|
| .. | .. |
|---|
| 3048 | 2971 | int level; |
|---|
| 3049 | 2972 | int lowest_unlock = 1; |
|---|
| 3050 | 2973 | u8 lowest_level = 0; |
|---|
| 3051 | | - int prev_cmp = -1; |
|---|
| 3052 | 2974 | |
|---|
| 3053 | 2975 | lowest_level = p->lowest_level; |
|---|
| 3054 | 2976 | WARN_ON(p->nodes[0] != NULL); |
|---|
| .. | .. |
|---|
| 3068 | 2990 | p->locks[level] = BTRFS_READ_LOCK; |
|---|
| 3069 | 2991 | |
|---|
| 3070 | 2992 | while (b) { |
|---|
| 2993 | + int dec = 0; |
|---|
| 2994 | + |
|---|
| 3071 | 2995 | level = btrfs_header_level(b); |
|---|
| 3072 | 2996 | p->nodes[level] = b; |
|---|
| 3073 | | - btrfs_clear_path_blocking(p, NULL, 0); |
|---|
| 3074 | 2997 | |
|---|
| 3075 | 2998 | /* |
|---|
| 3076 | 2999 | * we have a lock on b and as long as we aren't changing |
|---|
| .. | .. |
|---|
| 3080 | 3003 | */ |
|---|
| 3081 | 3004 | btrfs_unlock_up_safe(p, level + 1); |
|---|
| 3082 | 3005 | |
|---|
| 3083 | | - /* |
|---|
| 3084 | | - * Since we can unwind ebs we want to do a real search every |
|---|
| 3085 | | - * time. |
|---|
| 3086 | | - */ |
|---|
| 3087 | | - prev_cmp = -1; |
|---|
| 3088 | | - ret = key_search(b, key, level, &prev_cmp, &slot); |
|---|
| 3006 | + ret = btrfs_bin_search(b, key, &slot); |
|---|
| 3007 | + if (ret < 0) |
|---|
| 3008 | + goto done; |
|---|
| 3089 | 3009 | |
|---|
| 3090 | | - if (level != 0) { |
|---|
| 3091 | | - int dec = 0; |
|---|
| 3092 | | - if (ret && slot > 0) { |
|---|
| 3093 | | - dec = 1; |
|---|
| 3094 | | - slot -= 1; |
|---|
| 3095 | | - } |
|---|
| 3096 | | - p->slots[level] = slot; |
|---|
| 3097 | | - unlock_up(p, level, lowest_unlock, 0, NULL); |
|---|
| 3098 | | - |
|---|
| 3099 | | - if (level == lowest_level) { |
|---|
| 3100 | | - if (dec) |
|---|
| 3101 | | - p->slots[level]++; |
|---|
| 3102 | | - goto done; |
|---|
| 3103 | | - } |
|---|
| 3104 | | - |
|---|
| 3105 | | - err = read_block_for_search(root, p, &b, level, |
|---|
| 3106 | | - slot, key); |
|---|
| 3107 | | - if (err == -EAGAIN) |
|---|
| 3108 | | - goto again; |
|---|
| 3109 | | - if (err) { |
|---|
| 3110 | | - ret = err; |
|---|
| 3111 | | - goto done; |
|---|
| 3112 | | - } |
|---|
| 3113 | | - |
|---|
| 3114 | | - level = btrfs_header_level(b); |
|---|
| 3115 | | - err = btrfs_tree_read_lock_atomic(b); |
|---|
| 3116 | | - if (!err) { |
|---|
| 3117 | | - btrfs_set_path_blocking(p); |
|---|
| 3118 | | - btrfs_tree_read_lock(b); |
|---|
| 3119 | | - btrfs_clear_path_blocking(p, b, |
|---|
| 3120 | | - BTRFS_READ_LOCK); |
|---|
| 3121 | | - } |
|---|
| 3122 | | - b = tree_mod_log_rewind(fs_info, p, b, time_seq); |
|---|
| 3123 | | - if (!b) { |
|---|
| 3124 | | - ret = -ENOMEM; |
|---|
| 3125 | | - goto done; |
|---|
| 3126 | | - } |
|---|
| 3127 | | - p->locks[level] = BTRFS_READ_LOCK; |
|---|
| 3128 | | - p->nodes[level] = b; |
|---|
| 3129 | | - } else { |
|---|
| 3010 | + if (level == 0) { |
|---|
| 3130 | 3011 | p->slots[level] = slot; |
|---|
| 3131 | 3012 | unlock_up(p, level, lowest_unlock, 0, NULL); |
|---|
| 3132 | 3013 | goto done; |
|---|
| 3133 | 3014 | } |
|---|
| 3015 | + |
|---|
| 3016 | + if (ret && slot > 0) { |
|---|
| 3017 | + dec = 1; |
|---|
| 3018 | + slot--; |
|---|
| 3019 | + } |
|---|
| 3020 | + p->slots[level] = slot; |
|---|
| 3021 | + unlock_up(p, level, lowest_unlock, 0, NULL); |
|---|
| 3022 | + |
|---|
| 3023 | + if (level == lowest_level) { |
|---|
| 3024 | + if (dec) |
|---|
| 3025 | + p->slots[level]++; |
|---|
| 3026 | + goto done; |
|---|
| 3027 | + } |
|---|
| 3028 | + |
|---|
| 3029 | + err = read_block_for_search(root, p, &b, level, slot, key); |
|---|
| 3030 | + if (err == -EAGAIN) |
|---|
| 3031 | + goto again; |
|---|
| 3032 | + if (err) { |
|---|
| 3033 | + ret = err; |
|---|
| 3034 | + goto done; |
|---|
| 3035 | + } |
|---|
| 3036 | + |
|---|
| 3037 | + level = btrfs_header_level(b); |
|---|
| 3038 | + if (!btrfs_tree_read_lock_atomic(b)) { |
|---|
| 3039 | + btrfs_set_path_blocking(p); |
|---|
| 3040 | + btrfs_tree_read_lock(b); |
|---|
| 3041 | + } |
|---|
| 3042 | + b = tree_mod_log_rewind(fs_info, p, b, time_seq); |
|---|
| 3043 | + if (!b) { |
|---|
| 3044 | + ret = -ENOMEM; |
|---|
| 3045 | + goto done; |
|---|
| 3046 | + } |
|---|
| 3047 | + p->locks[level] = BTRFS_READ_LOCK; |
|---|
| 3048 | + p->nodes[level] = b; |
|---|
| 3134 | 3049 | } |
|---|
| 3135 | 3050 | ret = 1; |
|---|
| 3136 | 3051 | done: |
|---|
| .. | .. |
|---|
| 3268 | 3183 | slot = path->slots[0]; |
|---|
| 3269 | 3184 | if (slot > 0) { |
|---|
| 3270 | 3185 | btrfs_item_key(eb, &disk_key, slot - 1); |
|---|
| 3271 | | - BUG_ON(comp_keys(&disk_key, new_key) >= 0); |
|---|
| 3186 | + if (unlikely(comp_keys(&disk_key, new_key) >= 0)) { |
|---|
| 3187 | + btrfs_crit(fs_info, |
|---|
| 3188 | + "slot %u key (%llu %u %llu) new key (%llu %u %llu)", |
|---|
| 3189 | + slot, btrfs_disk_key_objectid(&disk_key), |
|---|
| 3190 | + btrfs_disk_key_type(&disk_key), |
|---|
| 3191 | + btrfs_disk_key_offset(&disk_key), |
|---|
| 3192 | + new_key->objectid, new_key->type, |
|---|
| 3193 | + new_key->offset); |
|---|
| 3194 | + btrfs_print_leaf(eb); |
|---|
| 3195 | + BUG(); |
|---|
| 3196 | + } |
|---|
| 3272 | 3197 | } |
|---|
| 3273 | 3198 | if (slot < btrfs_header_nritems(eb) - 1) { |
|---|
| 3274 | 3199 | btrfs_item_key(eb, &disk_key, slot + 1); |
|---|
| 3275 | | - BUG_ON(comp_keys(&disk_key, new_key) <= 0); |
|---|
| 3200 | + if (unlikely(comp_keys(&disk_key, new_key) <= 0)) { |
|---|
| 3201 | + btrfs_crit(fs_info, |
|---|
| 3202 | + "slot %u key (%llu %u %llu) new key (%llu %u %llu)", |
|---|
| 3203 | + slot, btrfs_disk_key_objectid(&disk_key), |
|---|
| 3204 | + btrfs_disk_key_type(&disk_key), |
|---|
| 3205 | + btrfs_disk_key_offset(&disk_key), |
|---|
| 3206 | + new_key->objectid, new_key->type, |
|---|
| 3207 | + new_key->offset); |
|---|
| 3208 | + btrfs_print_leaf(eb); |
|---|
| 3209 | + BUG(); |
|---|
| 3210 | + } |
|---|
| 3276 | 3211 | } |
|---|
| 3277 | 3212 | |
|---|
| 3278 | 3213 | btrfs_cpu_key_to_disk(&disk_key, new_key); |
|---|
| .. | .. |
|---|
| 3283 | 3218 | } |
|---|
| 3284 | 3219 | |
|---|
| 3285 | 3220 | /* |
|---|
| 3221 | + * Check key order of two sibling extent buffers. |
|---|
| 3222 | + * |
|---|
| 3223 | + * Return true if something is wrong. |
|---|
| 3224 | + * Return false if everything is fine. |
|---|
| 3225 | + * |
|---|
| 3226 | + * Tree-checker only works inside one tree block, thus the following |
|---|
| 3227 | + * corruption can not be detected by tree-checker: |
|---|
| 3228 | + * |
|---|
| 3229 | + * Leaf @left | Leaf @right |
|---|
| 3230 | + * -------------------------------------------------------------- |
|---|
| 3231 | + * | 1 | 2 | 3 | 4 | 5 | f6 | | 7 | 8 | |
|---|
| 3232 | + * |
|---|
| 3233 | + * Key f6 in leaf @left itself is valid, but not valid when the next |
|---|
| 3234 | + * key in leaf @right is 7. |
|---|
| 3235 | + * This can only be checked at tree block merge time. |
|---|
| 3236 | + * And since tree checker has ensured all key order in each tree block |
|---|
| 3237 | + * is correct, we only need to bother the last key of @left and the first |
|---|
| 3238 | + * key of @right. |
|---|
| 3239 | + */ |
|---|
| 3240 | +static bool check_sibling_keys(struct extent_buffer *left, |
|---|
| 3241 | + struct extent_buffer *right) |
|---|
| 3242 | +{ |
|---|
| 3243 | + struct btrfs_key left_last; |
|---|
| 3244 | + struct btrfs_key right_first; |
|---|
| 3245 | + int level = btrfs_header_level(left); |
|---|
| 3246 | + int nr_left = btrfs_header_nritems(left); |
|---|
| 3247 | + int nr_right = btrfs_header_nritems(right); |
|---|
| 3248 | + |
|---|
| 3249 | + /* No key to check in one of the tree blocks */ |
|---|
| 3250 | + if (!nr_left || !nr_right) |
|---|
| 3251 | + return false; |
|---|
| 3252 | + |
|---|
| 3253 | + if (level) { |
|---|
| 3254 | + btrfs_node_key_to_cpu(left, &left_last, nr_left - 1); |
|---|
| 3255 | + btrfs_node_key_to_cpu(right, &right_first, 0); |
|---|
| 3256 | + } else { |
|---|
| 3257 | + btrfs_item_key_to_cpu(left, &left_last, nr_left - 1); |
|---|
| 3258 | + btrfs_item_key_to_cpu(right, &right_first, 0); |
|---|
| 3259 | + } |
|---|
| 3260 | + |
|---|
| 3261 | + if (btrfs_comp_cpu_keys(&left_last, &right_first) >= 0) { |
|---|
| 3262 | + btrfs_crit(left->fs_info, |
|---|
| 3263 | +"bad key order, sibling blocks, left last (%llu %u %llu) right first (%llu %u %llu)", |
|---|
| 3264 | + left_last.objectid, left_last.type, |
|---|
| 3265 | + left_last.offset, right_first.objectid, |
|---|
| 3266 | + right_first.type, right_first.offset); |
|---|
| 3267 | + return true; |
|---|
| 3268 | + } |
|---|
| 3269 | + return false; |
|---|
| 3270 | +} |
|---|
| 3271 | + |
|---|
| 3272 | +/* |
|---|
| 3286 | 3273 | * try to push data from one node into the next node left in the |
|---|
| 3287 | 3274 | * tree. |
|---|
| 3288 | 3275 | * |
|---|
| .. | .. |
|---|
| 3290 | 3277 | * error, and > 0 if there was no room in the left hand block. |
|---|
| 3291 | 3278 | */ |
|---|
| 3292 | 3279 | static int push_node_left(struct btrfs_trans_handle *trans, |
|---|
| 3293 | | - struct btrfs_fs_info *fs_info, |
|---|
| 3294 | 3280 | struct extent_buffer *dst, |
|---|
| 3295 | 3281 | struct extent_buffer *src, int empty) |
|---|
| 3296 | 3282 | { |
|---|
| 3283 | + struct btrfs_fs_info *fs_info = trans->fs_info; |
|---|
| 3297 | 3284 | int push_items = 0; |
|---|
| 3298 | 3285 | int src_nritems; |
|---|
| 3299 | 3286 | int dst_nritems; |
|---|
| .. | .. |
|---|
| 3326 | 3313 | } else |
|---|
| 3327 | 3314 | push_items = min(src_nritems - 8, push_items); |
|---|
| 3328 | 3315 | |
|---|
| 3329 | | - ret = tree_mod_log_eb_copy(fs_info, dst, src, dst_nritems, 0, |
|---|
| 3330 | | - push_items); |
|---|
| 3316 | + /* dst is the left eb, src is the middle eb */ |
|---|
| 3317 | + if (check_sibling_keys(dst, src)) { |
|---|
| 3318 | + ret = -EUCLEAN; |
|---|
| 3319 | + btrfs_abort_transaction(trans, ret); |
|---|
| 3320 | + return ret; |
|---|
| 3321 | + } |
|---|
| 3322 | + ret = tree_mod_log_eb_copy(dst, src, dst_nritems, 0, push_items); |
|---|
| 3331 | 3323 | if (ret) { |
|---|
| 3332 | 3324 | btrfs_abort_transaction(trans, ret); |
|---|
| 3333 | 3325 | return ret; |
|---|
| .. | .. |
|---|
| 3365 | 3357 | * this will only push up to 1/2 the contents of the left node over |
|---|
| 3366 | 3358 | */ |
|---|
| 3367 | 3359 | static int balance_node_right(struct btrfs_trans_handle *trans, |
|---|
| 3368 | | - struct btrfs_fs_info *fs_info, |
|---|
| 3369 | 3360 | struct extent_buffer *dst, |
|---|
| 3370 | 3361 | struct extent_buffer *src) |
|---|
| 3371 | 3362 | { |
|---|
| 3363 | + struct btrfs_fs_info *fs_info = trans->fs_info; |
|---|
| 3372 | 3364 | int push_items = 0; |
|---|
| 3373 | 3365 | int max_push; |
|---|
| 3374 | 3366 | int src_nritems; |
|---|
| .. | .. |
|---|
| 3395 | 3387 | if (max_push < push_items) |
|---|
| 3396 | 3388 | push_items = max_push; |
|---|
| 3397 | 3389 | |
|---|
| 3390 | + /* dst is the right eb, src is the middle eb */ |
|---|
| 3391 | + if (check_sibling_keys(src, dst)) { |
|---|
| 3392 | + ret = -EUCLEAN; |
|---|
| 3393 | + btrfs_abort_transaction(trans, ret); |
|---|
| 3394 | + return ret; |
|---|
| 3395 | + } |
|---|
| 3398 | 3396 | ret = tree_mod_log_insert_move(dst, push_items, 0, dst_nritems); |
|---|
| 3399 | 3397 | BUG_ON(ret < 0); |
|---|
| 3400 | 3398 | memmove_extent_buffer(dst, btrfs_node_key_ptr_offset(push_items), |
|---|
| .. | .. |
|---|
| 3402 | 3400 | (dst_nritems) * |
|---|
| 3403 | 3401 | sizeof(struct btrfs_key_ptr)); |
|---|
| 3404 | 3402 | |
|---|
| 3405 | | - ret = tree_mod_log_eb_copy(fs_info, dst, src, 0, |
|---|
| 3406 | | - src_nritems - push_items, push_items); |
|---|
| 3403 | + ret = tree_mod_log_eb_copy(dst, src, 0, src_nritems - push_items, |
|---|
| 3404 | + push_items); |
|---|
| 3407 | 3405 | if (ret) { |
|---|
| 3408 | 3406 | btrfs_abort_transaction(trans, ret); |
|---|
| 3409 | 3407 | return ret; |
|---|
| .. | .. |
|---|
| 3451 | 3449 | btrfs_node_key(lower, &lower_key, 0); |
|---|
| 3452 | 3450 | |
|---|
| 3453 | 3451 | c = alloc_tree_block_no_bg_flush(trans, root, 0, &lower_key, level, |
|---|
| 3454 | | - root->node->start, 0); |
|---|
| 3452 | + root->node->start, 0, |
|---|
| 3453 | + BTRFS_NESTING_NEW_ROOT); |
|---|
| 3455 | 3454 | if (IS_ERR(c)) |
|---|
| 3456 | 3455 | return PTR_ERR(c); |
|---|
| 3457 | 3456 | |
|---|
| .. | .. |
|---|
| 3476 | 3475 | free_extent_buffer(old); |
|---|
| 3477 | 3476 | |
|---|
| 3478 | 3477 | add_root_to_dirty_list(root); |
|---|
| 3479 | | - extent_buffer_get(c); |
|---|
| 3478 | + atomic_inc(&c->refs); |
|---|
| 3480 | 3479 | path->nodes[level] = c; |
|---|
| 3481 | 3480 | path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING; |
|---|
| 3482 | 3481 | path->slots[level] = 0; |
|---|
| .. | .. |
|---|
| 3491 | 3490 | * blocknr is the block the key points to. |
|---|
| 3492 | 3491 | */ |
|---|
| 3493 | 3492 | static void insert_ptr(struct btrfs_trans_handle *trans, |
|---|
| 3494 | | - struct btrfs_fs_info *fs_info, struct btrfs_path *path, |
|---|
| 3493 | + struct btrfs_path *path, |
|---|
| 3495 | 3494 | struct btrfs_disk_key *key, u64 bytenr, |
|---|
| 3496 | 3495 | int slot, int level) |
|---|
| 3497 | 3496 | { |
|---|
| .. | .. |
|---|
| 3504 | 3503 | lower = path->nodes[level]; |
|---|
| 3505 | 3504 | nritems = btrfs_header_nritems(lower); |
|---|
| 3506 | 3505 | BUG_ON(slot > nritems); |
|---|
| 3507 | | - BUG_ON(nritems == BTRFS_NODEPTRS_PER_BLOCK(fs_info)); |
|---|
| 3506 | + BUG_ON(nritems == BTRFS_NODEPTRS_PER_BLOCK(trans->fs_info)); |
|---|
| 3508 | 3507 | if (slot != nritems) { |
|---|
| 3509 | 3508 | if (level) { |
|---|
| 3510 | 3509 | ret = tree_mod_log_insert_move(lower, slot + 1, slot, |
|---|
| .. | .. |
|---|
| 3581 | 3580 | btrfs_node_key(c, &disk_key, mid); |
|---|
| 3582 | 3581 | |
|---|
| 3583 | 3582 | split = alloc_tree_block_no_bg_flush(trans, root, 0, &disk_key, level, |
|---|
| 3584 | | - c->start, 0); |
|---|
| 3583 | + c->start, 0, BTRFS_NESTING_SPLIT); |
|---|
| 3585 | 3584 | if (IS_ERR(split)) |
|---|
| 3586 | 3585 | return PTR_ERR(split); |
|---|
| 3587 | 3586 | |
|---|
| 3588 | 3587 | root_add_used(root, fs_info->nodesize); |
|---|
| 3589 | 3588 | ASSERT(btrfs_header_level(c) == level); |
|---|
| 3590 | 3589 | |
|---|
| 3591 | | - ret = tree_mod_log_eb_copy(fs_info, split, c, 0, mid, c_nritems - mid); |
|---|
| 3590 | + ret = tree_mod_log_eb_copy(split, c, 0, mid, c_nritems - mid); |
|---|
| 3592 | 3591 | if (ret) { |
|---|
| 3593 | 3592 | btrfs_abort_transaction(trans, ret); |
|---|
| 3594 | 3593 | return ret; |
|---|
| .. | .. |
|---|
| 3604 | 3603 | btrfs_mark_buffer_dirty(c); |
|---|
| 3605 | 3604 | btrfs_mark_buffer_dirty(split); |
|---|
| 3606 | 3605 | |
|---|
| 3607 | | - insert_ptr(trans, fs_info, path, &disk_key, split->start, |
|---|
| 3606 | + insert_ptr(trans, path, &disk_key, split->start, |
|---|
| 3608 | 3607 | path->slots[level + 1] + 1, level + 1); |
|---|
| 3609 | 3608 | |
|---|
| 3610 | 3609 | if (path->slots[level] >= mid) { |
|---|
| .. | .. |
|---|
| 3629 | 3628 | { |
|---|
| 3630 | 3629 | struct btrfs_item *start_item; |
|---|
| 3631 | 3630 | struct btrfs_item *end_item; |
|---|
| 3632 | | - struct btrfs_map_token token; |
|---|
| 3633 | 3631 | int data_len; |
|---|
| 3634 | 3632 | int nritems = btrfs_header_nritems(l); |
|---|
| 3635 | 3633 | int end = min(nritems, start + nr) - 1; |
|---|
| 3636 | 3634 | |
|---|
| 3637 | 3635 | if (!nr) |
|---|
| 3638 | 3636 | return 0; |
|---|
| 3639 | | - btrfs_init_map_token(&token); |
|---|
| 3640 | 3637 | start_item = btrfs_item_nr(start); |
|---|
| 3641 | 3638 | end_item = btrfs_item_nr(end); |
|---|
| 3642 | | - data_len = btrfs_token_item_offset(l, start_item, &token) + |
|---|
| 3643 | | - btrfs_token_item_size(l, start_item, &token); |
|---|
| 3644 | | - data_len = data_len - btrfs_token_item_offset(l, end_item, &token); |
|---|
| 3639 | + data_len = btrfs_item_offset(l, start_item) + |
|---|
| 3640 | + btrfs_item_size(l, start_item); |
|---|
| 3641 | + data_len = data_len - btrfs_item_offset(l, end_item); |
|---|
| 3645 | 3642 | data_len += sizeof(struct btrfs_item) * nr; |
|---|
| 3646 | 3643 | WARN_ON(data_len < 0); |
|---|
| 3647 | 3644 | return data_len; |
|---|
| .. | .. |
|---|
| 3652 | 3649 | * the start of the leaf data. IOW, how much room |
|---|
| 3653 | 3650 | * the leaf has left for both items and data |
|---|
| 3654 | 3651 | */ |
|---|
| 3655 | | -noinline int btrfs_leaf_free_space(struct btrfs_fs_info *fs_info, |
|---|
| 3656 | | - struct extent_buffer *leaf) |
|---|
| 3652 | +noinline int btrfs_leaf_free_space(struct extent_buffer *leaf) |
|---|
| 3657 | 3653 | { |
|---|
| 3654 | + struct btrfs_fs_info *fs_info = leaf->fs_info; |
|---|
| 3658 | 3655 | int nritems = btrfs_header_nritems(leaf); |
|---|
| 3659 | 3656 | int ret; |
|---|
| 3660 | 3657 | |
|---|
| .. | .. |
|---|
| 3673 | 3670 | * min slot controls the lowest index we're willing to push to the |
|---|
| 3674 | 3671 | * right. We'll push up to and including min_slot, but no lower |
|---|
| 3675 | 3672 | */ |
|---|
| 3676 | | -static noinline int __push_leaf_right(struct btrfs_fs_info *fs_info, |
|---|
| 3677 | | - struct btrfs_path *path, |
|---|
| 3673 | +static noinline int __push_leaf_right(struct btrfs_path *path, |
|---|
| 3678 | 3674 | int data_size, int empty, |
|---|
| 3679 | 3675 | struct extent_buffer *right, |
|---|
| 3680 | 3676 | int free_space, u32 left_nritems, |
|---|
| 3681 | 3677 | u32 min_slot) |
|---|
| 3682 | 3678 | { |
|---|
| 3679 | + struct btrfs_fs_info *fs_info = right->fs_info; |
|---|
| 3683 | 3680 | struct extent_buffer *left = path->nodes[0]; |
|---|
| 3684 | 3681 | struct extent_buffer *upper = path->nodes[1]; |
|---|
| 3685 | 3682 | struct btrfs_map_token token; |
|---|
| .. | .. |
|---|
| 3693 | 3690 | u32 right_nritems; |
|---|
| 3694 | 3691 | u32 data_end; |
|---|
| 3695 | 3692 | u32 this_item_size; |
|---|
| 3696 | | - |
|---|
| 3697 | | - btrfs_init_map_token(&token); |
|---|
| 3698 | 3693 | |
|---|
| 3699 | 3694 | if (empty) |
|---|
| 3700 | 3695 | nr = 0; |
|---|
| .. | .. |
|---|
| 3713 | 3708 | if (path->slots[0] > i) |
|---|
| 3714 | 3709 | break; |
|---|
| 3715 | 3710 | if (path->slots[0] == i) { |
|---|
| 3716 | | - int space = btrfs_leaf_free_space(fs_info, left); |
|---|
| 3711 | + int space = btrfs_leaf_free_space(left); |
|---|
| 3712 | + |
|---|
| 3717 | 3713 | if (space + push_space * 2 > free_space) |
|---|
| 3718 | 3714 | break; |
|---|
| 3719 | 3715 | } |
|---|
| .. | .. |
|---|
| 3742 | 3738 | right_nritems = btrfs_header_nritems(right); |
|---|
| 3743 | 3739 | |
|---|
| 3744 | 3740 | push_space = btrfs_item_end_nr(left, left_nritems - push_items); |
|---|
| 3745 | | - push_space -= leaf_data_end(fs_info, left); |
|---|
| 3741 | + push_space -= leaf_data_end(left); |
|---|
| 3746 | 3742 | |
|---|
| 3747 | 3743 | /* make room in the right data area */ |
|---|
| 3748 | | - data_end = leaf_data_end(fs_info, right); |
|---|
| 3744 | + data_end = leaf_data_end(right); |
|---|
| 3749 | 3745 | memmove_extent_buffer(right, |
|---|
| 3750 | 3746 | BTRFS_LEAF_DATA_OFFSET + data_end - push_space, |
|---|
| 3751 | 3747 | BTRFS_LEAF_DATA_OFFSET + data_end, |
|---|
| .. | .. |
|---|
| 3754 | 3750 | /* copy from the left data area */ |
|---|
| 3755 | 3751 | copy_extent_buffer(right, left, BTRFS_LEAF_DATA_OFFSET + |
|---|
| 3756 | 3752 | BTRFS_LEAF_DATA_SIZE(fs_info) - push_space, |
|---|
| 3757 | | - BTRFS_LEAF_DATA_OFFSET + leaf_data_end(fs_info, left), |
|---|
| 3753 | + BTRFS_LEAF_DATA_OFFSET + leaf_data_end(left), |
|---|
| 3758 | 3754 | push_space); |
|---|
| 3759 | 3755 | |
|---|
| 3760 | 3756 | memmove_extent_buffer(right, btrfs_item_nr_offset(push_items), |
|---|
| .. | .. |
|---|
| 3767 | 3763 | push_items * sizeof(struct btrfs_item)); |
|---|
| 3768 | 3764 | |
|---|
| 3769 | 3765 | /* update the item pointers */ |
|---|
| 3766 | + btrfs_init_map_token(&token, right); |
|---|
| 3770 | 3767 | right_nritems += push_items; |
|---|
| 3771 | 3768 | btrfs_set_header_nritems(right, right_nritems); |
|---|
| 3772 | 3769 | push_space = BTRFS_LEAF_DATA_SIZE(fs_info); |
|---|
| 3773 | 3770 | for (i = 0; i < right_nritems; i++) { |
|---|
| 3774 | 3771 | item = btrfs_item_nr(i); |
|---|
| 3775 | | - push_space -= btrfs_token_item_size(right, item, &token); |
|---|
| 3776 | | - btrfs_set_token_item_offset(right, item, push_space, &token); |
|---|
| 3772 | + push_space -= btrfs_token_item_size(&token, item); |
|---|
| 3773 | + btrfs_set_token_item_offset(&token, item, push_space); |
|---|
| 3777 | 3774 | } |
|---|
| 3778 | 3775 | |
|---|
| 3779 | 3776 | left_nritems -= push_items; |
|---|
| .. | .. |
|---|
| 3782 | 3779 | if (left_nritems) |
|---|
| 3783 | 3780 | btrfs_mark_buffer_dirty(left); |
|---|
| 3784 | 3781 | else |
|---|
| 3785 | | - clean_tree_block(fs_info, left); |
|---|
| 3782 | + btrfs_clean_tree_block(left); |
|---|
| 3786 | 3783 | |
|---|
| 3787 | 3784 | btrfs_mark_buffer_dirty(right); |
|---|
| 3788 | 3785 | |
|---|
| .. | .. |
|---|
| 3794 | 3791 | if (path->slots[0] >= left_nritems) { |
|---|
| 3795 | 3792 | path->slots[0] -= left_nritems; |
|---|
| 3796 | 3793 | if (btrfs_header_nritems(path->nodes[0]) == 0) |
|---|
| 3797 | | - clean_tree_block(fs_info, path->nodes[0]); |
|---|
| 3794 | + btrfs_clean_tree_block(path->nodes[0]); |
|---|
| 3798 | 3795 | btrfs_tree_unlock(path->nodes[0]); |
|---|
| 3799 | 3796 | free_extent_buffer(path->nodes[0]); |
|---|
| 3800 | 3797 | path->nodes[0] = right; |
|---|
| .. | .. |
|---|
| 3826 | 3823 | int min_data_size, int data_size, |
|---|
| 3827 | 3824 | int empty, u32 min_slot) |
|---|
| 3828 | 3825 | { |
|---|
| 3829 | | - struct btrfs_fs_info *fs_info = root->fs_info; |
|---|
| 3830 | 3826 | struct extent_buffer *left = path->nodes[0]; |
|---|
| 3831 | 3827 | struct extent_buffer *right; |
|---|
| 3832 | 3828 | struct extent_buffer *upper; |
|---|
| .. | .. |
|---|
| 3845 | 3841 | |
|---|
| 3846 | 3842 | btrfs_assert_tree_locked(path->nodes[1]); |
|---|
| 3847 | 3843 | |
|---|
| 3848 | | - right = read_node_slot(fs_info, upper, slot + 1); |
|---|
| 3844 | + right = btrfs_read_node_slot(upper, slot + 1); |
|---|
| 3849 | 3845 | /* |
|---|
| 3850 | 3846 | * slot + 1 is not valid or we fail to read the right node, |
|---|
| 3851 | 3847 | * no big deal, just return. |
|---|
| .. | .. |
|---|
| 3853 | 3849 | if (IS_ERR(right)) |
|---|
| 3854 | 3850 | return 1; |
|---|
| 3855 | 3851 | |
|---|
| 3856 | | - btrfs_tree_lock(right); |
|---|
| 3857 | | - btrfs_set_lock_blocking(right); |
|---|
| 3852 | + __btrfs_tree_lock(right, BTRFS_NESTING_RIGHT); |
|---|
| 3853 | + btrfs_set_lock_blocking_write(right); |
|---|
| 3858 | 3854 | |
|---|
| 3859 | | - free_space = btrfs_leaf_free_space(fs_info, right); |
|---|
| 3855 | + free_space = btrfs_leaf_free_space(right); |
|---|
| 3860 | 3856 | if (free_space < data_size) |
|---|
| 3861 | 3857 | goto out_unlock; |
|---|
| 3862 | 3858 | |
|---|
| 3863 | 3859 | /* cow and double check */ |
|---|
| 3864 | 3860 | ret = btrfs_cow_block(trans, root, right, upper, |
|---|
| 3865 | | - slot + 1, &right); |
|---|
| 3861 | + slot + 1, &right, BTRFS_NESTING_RIGHT_COW); |
|---|
| 3866 | 3862 | if (ret) |
|---|
| 3867 | 3863 | goto out_unlock; |
|---|
| 3868 | 3864 | |
|---|
| 3869 | | - free_space = btrfs_leaf_free_space(fs_info, right); |
|---|
| 3865 | + free_space = btrfs_leaf_free_space(right); |
|---|
| 3870 | 3866 | if (free_space < data_size) |
|---|
| 3871 | 3867 | goto out_unlock; |
|---|
| 3872 | 3868 | |
|---|
| .. | .. |
|---|
| 3874 | 3870 | if (left_nritems == 0) |
|---|
| 3875 | 3871 | goto out_unlock; |
|---|
| 3876 | 3872 | |
|---|
| 3873 | + if (check_sibling_keys(left, right)) { |
|---|
| 3874 | + ret = -EUCLEAN; |
|---|
| 3875 | + btrfs_tree_unlock(right); |
|---|
| 3876 | + free_extent_buffer(right); |
|---|
| 3877 | + return ret; |
|---|
| 3878 | + } |
|---|
| 3877 | 3879 | if (path->slots[0] == left_nritems && !empty) { |
|---|
| 3878 | 3880 | /* Key greater than all keys in the leaf, right neighbor has |
|---|
| 3879 | 3881 | * enough room for it and we're not emptying our leaf to delete |
|---|
| 3880 | 3882 | * it, therefore use right neighbor to insert the new item and |
|---|
| 3881 | | - * no need to touch/dirty our left leaft. */ |
|---|
| 3883 | + * no need to touch/dirty our left leaf. */ |
|---|
| 3882 | 3884 | btrfs_tree_unlock(left); |
|---|
| 3883 | 3885 | free_extent_buffer(left); |
|---|
| 3884 | 3886 | path->nodes[0] = right; |
|---|
| .. | .. |
|---|
| 3887 | 3889 | return 0; |
|---|
| 3888 | 3890 | } |
|---|
| 3889 | 3891 | |
|---|
| 3890 | | - return __push_leaf_right(fs_info, path, min_data_size, empty, |
|---|
| 3892 | + return __push_leaf_right(path, min_data_size, empty, |
|---|
| 3891 | 3893 | right, free_space, left_nritems, min_slot); |
|---|
| 3892 | 3894 | out_unlock: |
|---|
| 3893 | 3895 | btrfs_tree_unlock(right); |
|---|
| .. | .. |
|---|
| 3903 | 3905 | * item at 'max_slot' won't be touched. Use (u32)-1 to make us do all the |
|---|
| 3904 | 3906 | * items |
|---|
| 3905 | 3907 | */ |
|---|
| 3906 | | -static noinline int __push_leaf_left(struct btrfs_fs_info *fs_info, |
|---|
| 3907 | | - struct btrfs_path *path, int data_size, |
|---|
| 3908 | +static noinline int __push_leaf_left(struct btrfs_path *path, int data_size, |
|---|
| 3908 | 3909 | int empty, struct extent_buffer *left, |
|---|
| 3909 | 3910 | int free_space, u32 right_nritems, |
|---|
| 3910 | 3911 | u32 max_slot) |
|---|
| 3911 | 3912 | { |
|---|
| 3913 | + struct btrfs_fs_info *fs_info = left->fs_info; |
|---|
| 3912 | 3914 | struct btrfs_disk_key disk_key; |
|---|
| 3913 | 3915 | struct extent_buffer *right = path->nodes[0]; |
|---|
| 3914 | 3916 | int i; |
|---|
| .. | .. |
|---|
| 3922 | 3924 | u32 old_left_item_size; |
|---|
| 3923 | 3925 | struct btrfs_map_token token; |
|---|
| 3924 | 3926 | |
|---|
| 3925 | | - btrfs_init_map_token(&token); |
|---|
| 3926 | | - |
|---|
| 3927 | 3927 | if (empty) |
|---|
| 3928 | 3928 | nr = min(right_nritems, max_slot); |
|---|
| 3929 | 3929 | else |
|---|
| .. | .. |
|---|
| 3936 | 3936 | if (path->slots[0] < i) |
|---|
| 3937 | 3937 | break; |
|---|
| 3938 | 3938 | if (path->slots[0] == i) { |
|---|
| 3939 | | - int space = btrfs_leaf_free_space(fs_info, right); |
|---|
| 3939 | + int space = btrfs_leaf_free_space(right); |
|---|
| 3940 | + |
|---|
| 3940 | 3941 | if (space + push_space * 2 > free_space) |
|---|
| 3941 | 3942 | break; |
|---|
| 3942 | 3943 | } |
|---|
| .. | .. |
|---|
| 3969 | 3970 | btrfs_item_offset_nr(right, push_items - 1); |
|---|
| 3970 | 3971 | |
|---|
| 3971 | 3972 | copy_extent_buffer(left, right, BTRFS_LEAF_DATA_OFFSET + |
|---|
| 3972 | | - leaf_data_end(fs_info, left) - push_space, |
|---|
| 3973 | + leaf_data_end(left) - push_space, |
|---|
| 3973 | 3974 | BTRFS_LEAF_DATA_OFFSET + |
|---|
| 3974 | 3975 | btrfs_item_offset_nr(right, push_items - 1), |
|---|
| 3975 | 3976 | push_space); |
|---|
| 3976 | 3977 | old_left_nritems = btrfs_header_nritems(left); |
|---|
| 3977 | 3978 | BUG_ON(old_left_nritems <= 0); |
|---|
| 3978 | 3979 | |
|---|
| 3980 | + btrfs_init_map_token(&token, left); |
|---|
| 3979 | 3981 | old_left_item_size = btrfs_item_offset_nr(left, old_left_nritems - 1); |
|---|
| 3980 | 3982 | for (i = old_left_nritems; i < old_left_nritems + push_items; i++) { |
|---|
| 3981 | 3983 | u32 ioff; |
|---|
| 3982 | 3984 | |
|---|
| 3983 | 3985 | item = btrfs_item_nr(i); |
|---|
| 3984 | 3986 | |
|---|
| 3985 | | - ioff = btrfs_token_item_offset(left, item, &token); |
|---|
| 3986 | | - btrfs_set_token_item_offset(left, item, |
|---|
| 3987 | | - ioff - (BTRFS_LEAF_DATA_SIZE(fs_info) - old_left_item_size), |
|---|
| 3988 | | - &token); |
|---|
| 3987 | + ioff = btrfs_token_item_offset(&token, item); |
|---|
| 3988 | + btrfs_set_token_item_offset(&token, item, |
|---|
| 3989 | + ioff - (BTRFS_LEAF_DATA_SIZE(fs_info) - old_left_item_size)); |
|---|
| 3989 | 3990 | } |
|---|
| 3990 | 3991 | btrfs_set_header_nritems(left, old_left_nritems + push_items); |
|---|
| 3991 | 3992 | |
|---|
| .. | .. |
|---|
| 3996 | 3997 | |
|---|
| 3997 | 3998 | if (push_items < right_nritems) { |
|---|
| 3998 | 3999 | push_space = btrfs_item_offset_nr(right, push_items - 1) - |
|---|
| 3999 | | - leaf_data_end(fs_info, right); |
|---|
| 4000 | + leaf_data_end(right); |
|---|
| 4000 | 4001 | memmove_extent_buffer(right, BTRFS_LEAF_DATA_OFFSET + |
|---|
| 4001 | 4002 | BTRFS_LEAF_DATA_SIZE(fs_info) - push_space, |
|---|
| 4002 | 4003 | BTRFS_LEAF_DATA_OFFSET + |
|---|
| 4003 | | - leaf_data_end(fs_info, right), push_space); |
|---|
| 4004 | + leaf_data_end(right), push_space); |
|---|
| 4004 | 4005 | |
|---|
| 4005 | 4006 | memmove_extent_buffer(right, btrfs_item_nr_offset(0), |
|---|
| 4006 | 4007 | btrfs_item_nr_offset(push_items), |
|---|
| 4007 | 4008 | (btrfs_header_nritems(right) - push_items) * |
|---|
| 4008 | 4009 | sizeof(struct btrfs_item)); |
|---|
| 4009 | 4010 | } |
|---|
| 4011 | + |
|---|
| 4012 | + btrfs_init_map_token(&token, right); |
|---|
| 4010 | 4013 | right_nritems -= push_items; |
|---|
| 4011 | 4014 | btrfs_set_header_nritems(right, right_nritems); |
|---|
| 4012 | 4015 | push_space = BTRFS_LEAF_DATA_SIZE(fs_info); |
|---|
| 4013 | 4016 | for (i = 0; i < right_nritems; i++) { |
|---|
| 4014 | 4017 | item = btrfs_item_nr(i); |
|---|
| 4015 | 4018 | |
|---|
| 4016 | | - push_space = push_space - btrfs_token_item_size(right, |
|---|
| 4017 | | - item, &token); |
|---|
| 4018 | | - btrfs_set_token_item_offset(right, item, push_space, &token); |
|---|
| 4019 | + push_space = push_space - btrfs_token_item_size(&token, item); |
|---|
| 4020 | + btrfs_set_token_item_offset(&token, item, push_space); |
|---|
| 4019 | 4021 | } |
|---|
| 4020 | 4022 | |
|---|
| 4021 | 4023 | btrfs_mark_buffer_dirty(left); |
|---|
| 4022 | 4024 | if (right_nritems) |
|---|
| 4023 | 4025 | btrfs_mark_buffer_dirty(right); |
|---|
| 4024 | 4026 | else |
|---|
| 4025 | | - clean_tree_block(fs_info, right); |
|---|
| 4027 | + btrfs_clean_tree_block(right); |
|---|
| 4026 | 4028 | |
|---|
| 4027 | 4029 | btrfs_item_key(right, &disk_key, 0); |
|---|
| 4028 | 4030 | fixup_low_keys(path, &disk_key, 1); |
|---|
| .. | .. |
|---|
| 4059 | 4061 | *root, struct btrfs_path *path, int min_data_size, |
|---|
| 4060 | 4062 | int data_size, int empty, u32 max_slot) |
|---|
| 4061 | 4063 | { |
|---|
| 4062 | | - struct btrfs_fs_info *fs_info = root->fs_info; |
|---|
| 4063 | 4064 | struct extent_buffer *right = path->nodes[0]; |
|---|
| 4064 | 4065 | struct extent_buffer *left; |
|---|
| 4065 | 4066 | int slot; |
|---|
| .. | .. |
|---|
| 4079 | 4080 | |
|---|
| 4080 | 4081 | btrfs_assert_tree_locked(path->nodes[1]); |
|---|
| 4081 | 4082 | |
|---|
| 4082 | | - left = read_node_slot(fs_info, path->nodes[1], slot - 1); |
|---|
| 4083 | + left = btrfs_read_node_slot(path->nodes[1], slot - 1); |
|---|
| 4083 | 4084 | /* |
|---|
| 4084 | 4085 | * slot - 1 is not valid or we fail to read the left node, |
|---|
| 4085 | 4086 | * no big deal, just return. |
|---|
| .. | .. |
|---|
| 4087 | 4088 | if (IS_ERR(left)) |
|---|
| 4088 | 4089 | return 1; |
|---|
| 4089 | 4090 | |
|---|
| 4090 | | - btrfs_tree_lock(left); |
|---|
| 4091 | | - btrfs_set_lock_blocking(left); |
|---|
| 4091 | + __btrfs_tree_lock(left, BTRFS_NESTING_LEFT); |
|---|
| 4092 | + btrfs_set_lock_blocking_write(left); |
|---|
| 4092 | 4093 | |
|---|
| 4093 | | - free_space = btrfs_leaf_free_space(fs_info, left); |
|---|
| 4094 | + free_space = btrfs_leaf_free_space(left); |
|---|
| 4094 | 4095 | if (free_space < data_size) { |
|---|
| 4095 | 4096 | ret = 1; |
|---|
| 4096 | 4097 | goto out; |
|---|
| .. | .. |
|---|
| 4098 | 4099 | |
|---|
| 4099 | 4100 | /* cow and double check */ |
|---|
| 4100 | 4101 | ret = btrfs_cow_block(trans, root, left, |
|---|
| 4101 | | - path->nodes[1], slot - 1, &left); |
|---|
| 4102 | + path->nodes[1], slot - 1, &left, |
|---|
| 4103 | + BTRFS_NESTING_LEFT_COW); |
|---|
| 4102 | 4104 | if (ret) { |
|---|
| 4103 | 4105 | /* we hit -ENOSPC, but it isn't fatal here */ |
|---|
| 4104 | 4106 | if (ret == -ENOSPC) |
|---|
| .. | .. |
|---|
| 4106 | 4108 | goto out; |
|---|
| 4107 | 4109 | } |
|---|
| 4108 | 4110 | |
|---|
| 4109 | | - free_space = btrfs_leaf_free_space(fs_info, left); |
|---|
| 4111 | + free_space = btrfs_leaf_free_space(left); |
|---|
| 4110 | 4112 | if (free_space < data_size) { |
|---|
| 4111 | 4113 | ret = 1; |
|---|
| 4112 | 4114 | goto out; |
|---|
| 4113 | 4115 | } |
|---|
| 4114 | 4116 | |
|---|
| 4115 | | - return __push_leaf_left(fs_info, path, min_data_size, |
|---|
| 4117 | + if (check_sibling_keys(left, right)) { |
|---|
| 4118 | + ret = -EUCLEAN; |
|---|
| 4119 | + goto out; |
|---|
| 4120 | + } |
|---|
| 4121 | + return __push_leaf_left(path, min_data_size, |
|---|
| 4116 | 4122 | empty, left, free_space, right_nritems, |
|---|
| 4117 | 4123 | max_slot); |
|---|
| 4118 | 4124 | out: |
|---|
| .. | .. |
|---|
| 4126 | 4132 | * available for the resulting leaf level of the path. |
|---|
| 4127 | 4133 | */ |
|---|
| 4128 | 4134 | static noinline void copy_for_split(struct btrfs_trans_handle *trans, |
|---|
| 4129 | | - struct btrfs_fs_info *fs_info, |
|---|
| 4130 | 4135 | struct btrfs_path *path, |
|---|
| 4131 | 4136 | struct extent_buffer *l, |
|---|
| 4132 | 4137 | struct extent_buffer *right, |
|---|
| 4133 | 4138 | int slot, int mid, int nritems) |
|---|
| 4134 | 4139 | { |
|---|
| 4140 | + struct btrfs_fs_info *fs_info = trans->fs_info; |
|---|
| 4135 | 4141 | int data_copy_size; |
|---|
| 4136 | 4142 | int rt_data_off; |
|---|
| 4137 | 4143 | int i; |
|---|
| 4138 | 4144 | struct btrfs_disk_key disk_key; |
|---|
| 4139 | 4145 | struct btrfs_map_token token; |
|---|
| 4140 | 4146 | |
|---|
| 4141 | | - btrfs_init_map_token(&token); |
|---|
| 4142 | | - |
|---|
| 4143 | 4147 | nritems = nritems - mid; |
|---|
| 4144 | 4148 | btrfs_set_header_nritems(right, nritems); |
|---|
| 4145 | | - data_copy_size = btrfs_item_end_nr(l, mid) - leaf_data_end(fs_info, l); |
|---|
| 4149 | + data_copy_size = btrfs_item_end_nr(l, mid) - leaf_data_end(l); |
|---|
| 4146 | 4150 | |
|---|
| 4147 | 4151 | copy_extent_buffer(right, l, btrfs_item_nr_offset(0), |
|---|
| 4148 | 4152 | btrfs_item_nr_offset(mid), |
|---|
| .. | .. |
|---|
| 4151 | 4155 | copy_extent_buffer(right, l, |
|---|
| 4152 | 4156 | BTRFS_LEAF_DATA_OFFSET + BTRFS_LEAF_DATA_SIZE(fs_info) - |
|---|
| 4153 | 4157 | data_copy_size, BTRFS_LEAF_DATA_OFFSET + |
|---|
| 4154 | | - leaf_data_end(fs_info, l), data_copy_size); |
|---|
| 4158 | + leaf_data_end(l), data_copy_size); |
|---|
| 4155 | 4159 | |
|---|
| 4156 | 4160 | rt_data_off = BTRFS_LEAF_DATA_SIZE(fs_info) - btrfs_item_end_nr(l, mid); |
|---|
| 4157 | 4161 | |
|---|
| 4162 | + btrfs_init_map_token(&token, right); |
|---|
| 4158 | 4163 | for (i = 0; i < nritems; i++) { |
|---|
| 4159 | 4164 | struct btrfs_item *item = btrfs_item_nr(i); |
|---|
| 4160 | 4165 | u32 ioff; |
|---|
| 4161 | 4166 | |
|---|
| 4162 | | - ioff = btrfs_token_item_offset(right, item, &token); |
|---|
| 4163 | | - btrfs_set_token_item_offset(right, item, |
|---|
| 4164 | | - ioff + rt_data_off, &token); |
|---|
| 4167 | + ioff = btrfs_token_item_offset(&token, item); |
|---|
| 4168 | + btrfs_set_token_item_offset(&token, item, ioff + rt_data_off); |
|---|
| 4165 | 4169 | } |
|---|
| 4166 | 4170 | |
|---|
| 4167 | 4171 | btrfs_set_header_nritems(l, mid); |
|---|
| 4168 | 4172 | btrfs_item_key(right, &disk_key, 0); |
|---|
| 4169 | | - insert_ptr(trans, fs_info, path, &disk_key, right->start, |
|---|
| 4170 | | - path->slots[1] + 1, 1); |
|---|
| 4173 | + insert_ptr(trans, path, &disk_key, right->start, path->slots[1] + 1, 1); |
|---|
| 4171 | 4174 | |
|---|
| 4172 | 4175 | btrfs_mark_buffer_dirty(right); |
|---|
| 4173 | 4176 | btrfs_mark_buffer_dirty(l); |
|---|
| .. | .. |
|---|
| 4202 | 4205 | struct btrfs_path *path, |
|---|
| 4203 | 4206 | int data_size) |
|---|
| 4204 | 4207 | { |
|---|
| 4205 | | - struct btrfs_fs_info *fs_info = root->fs_info; |
|---|
| 4206 | 4208 | int ret; |
|---|
| 4207 | 4209 | int progress = 0; |
|---|
| 4208 | 4210 | int slot; |
|---|
| .. | .. |
|---|
| 4211 | 4213 | |
|---|
| 4212 | 4214 | slot = path->slots[0]; |
|---|
| 4213 | 4215 | if (slot < btrfs_header_nritems(path->nodes[0])) |
|---|
| 4214 | | - space_needed -= btrfs_leaf_free_space(fs_info, path->nodes[0]); |
|---|
| 4216 | + space_needed -= btrfs_leaf_free_space(path->nodes[0]); |
|---|
| 4215 | 4217 | |
|---|
| 4216 | 4218 | /* |
|---|
| 4217 | 4219 | * try to push all the items after our slot into the |
|---|
| .. | .. |
|---|
| 4232 | 4234 | if (path->slots[0] == 0 || path->slots[0] == nritems) |
|---|
| 4233 | 4235 | return 0; |
|---|
| 4234 | 4236 | |
|---|
| 4235 | | - if (btrfs_leaf_free_space(fs_info, path->nodes[0]) >= data_size) |
|---|
| 4237 | + if (btrfs_leaf_free_space(path->nodes[0]) >= data_size) |
|---|
| 4236 | 4238 | return 0; |
|---|
| 4237 | 4239 | |
|---|
| 4238 | 4240 | /* try to push all the items before our slot into the next leaf */ |
|---|
| 4239 | 4241 | slot = path->slots[0]; |
|---|
| 4240 | 4242 | space_needed = data_size; |
|---|
| 4241 | 4243 | if (slot > 0) |
|---|
| 4242 | | - space_needed -= btrfs_leaf_free_space(fs_info, path->nodes[0]); |
|---|
| 4244 | + space_needed -= btrfs_leaf_free_space(path->nodes[0]); |
|---|
| 4243 | 4245 | ret = push_leaf_left(trans, root, path, 1, space_needed, 0, slot); |
|---|
| 4244 | 4246 | if (ret < 0) |
|---|
| 4245 | 4247 | return ret; |
|---|
| .. | .. |
|---|
| 4288 | 4290 | int space_needed = data_size; |
|---|
| 4289 | 4291 | |
|---|
| 4290 | 4292 | if (slot < btrfs_header_nritems(l)) |
|---|
| 4291 | | - space_needed -= btrfs_leaf_free_space(fs_info, l); |
|---|
| 4293 | + space_needed -= btrfs_leaf_free_space(l); |
|---|
| 4292 | 4294 | |
|---|
| 4293 | 4295 | wret = push_leaf_right(trans, root, path, space_needed, |
|---|
| 4294 | 4296 | space_needed, 0, 0); |
|---|
| .. | .. |
|---|
| 4297 | 4299 | if (wret) { |
|---|
| 4298 | 4300 | space_needed = data_size; |
|---|
| 4299 | 4301 | if (slot > 0) |
|---|
| 4300 | | - space_needed -= btrfs_leaf_free_space(fs_info, |
|---|
| 4301 | | - l); |
|---|
| 4302 | + space_needed -= btrfs_leaf_free_space(l); |
|---|
| 4302 | 4303 | wret = push_leaf_left(trans, root, path, space_needed, |
|---|
| 4303 | 4304 | space_needed, 0, (u32)-1); |
|---|
| 4304 | 4305 | if (wret < 0) |
|---|
| .. | .. |
|---|
| 4307 | 4308 | l = path->nodes[0]; |
|---|
| 4308 | 4309 | |
|---|
| 4309 | 4310 | /* did the pushes work? */ |
|---|
| 4310 | | - if (btrfs_leaf_free_space(fs_info, l) >= data_size) |
|---|
| 4311 | + if (btrfs_leaf_free_space(l) >= data_size) |
|---|
| 4311 | 4312 | return 0; |
|---|
| 4312 | 4313 | } |
|---|
| 4313 | 4314 | |
|---|
| .. | .. |
|---|
| 4365 | 4366 | else |
|---|
| 4366 | 4367 | btrfs_item_key(l, &disk_key, mid); |
|---|
| 4367 | 4368 | |
|---|
| 4369 | + /* |
|---|
| 4370 | + * We have to about BTRFS_NESTING_NEW_ROOT here if we've done a double |
|---|
| 4371 | + * split, because we're only allowed to have MAX_LOCKDEP_SUBCLASSES |
|---|
| 4372 | + * subclasses, which is 8 at the time of this patch, and we've maxed it |
|---|
| 4373 | + * out. In the future we could add a |
|---|
| 4374 | + * BTRFS_NESTING_SPLIT_THE_SPLITTENING if we need to, but for now just |
|---|
| 4375 | + * use BTRFS_NESTING_NEW_ROOT. |
|---|
| 4376 | + */ |
|---|
| 4368 | 4377 | right = alloc_tree_block_no_bg_flush(trans, root, 0, &disk_key, 0, |
|---|
| 4369 | | - l->start, 0); |
|---|
| 4378 | + l->start, 0, num_doubles ? |
|---|
| 4379 | + BTRFS_NESTING_NEW_ROOT : |
|---|
| 4380 | + BTRFS_NESTING_SPLIT); |
|---|
| 4370 | 4381 | if (IS_ERR(right)) |
|---|
| 4371 | 4382 | return PTR_ERR(right); |
|---|
| 4372 | 4383 | |
|---|
| .. | .. |
|---|
| 4375 | 4386 | if (split == 0) { |
|---|
| 4376 | 4387 | if (mid <= slot) { |
|---|
| 4377 | 4388 | btrfs_set_header_nritems(right, 0); |
|---|
| 4378 | | - insert_ptr(trans, fs_info, path, &disk_key, |
|---|
| 4389 | + insert_ptr(trans, path, &disk_key, |
|---|
| 4379 | 4390 | right->start, path->slots[1] + 1, 1); |
|---|
| 4380 | 4391 | btrfs_tree_unlock(path->nodes[0]); |
|---|
| 4381 | 4392 | free_extent_buffer(path->nodes[0]); |
|---|
| .. | .. |
|---|
| 4384 | 4395 | path->slots[1] += 1; |
|---|
| 4385 | 4396 | } else { |
|---|
| 4386 | 4397 | btrfs_set_header_nritems(right, 0); |
|---|
| 4387 | | - insert_ptr(trans, fs_info, path, &disk_key, |
|---|
| 4398 | + insert_ptr(trans, path, &disk_key, |
|---|
| 4388 | 4399 | right->start, path->slots[1], 1); |
|---|
| 4389 | 4400 | btrfs_tree_unlock(path->nodes[0]); |
|---|
| 4390 | 4401 | free_extent_buffer(path->nodes[0]); |
|---|
| .. | .. |
|---|
| 4401 | 4412 | return ret; |
|---|
| 4402 | 4413 | } |
|---|
| 4403 | 4414 | |
|---|
| 4404 | | - copy_for_split(trans, fs_info, path, l, right, slot, mid, nritems); |
|---|
| 4415 | + copy_for_split(trans, path, l, right, slot, mid, nritems); |
|---|
| 4405 | 4416 | |
|---|
| 4406 | 4417 | if (split == 2) { |
|---|
| 4407 | 4418 | BUG_ON(num_doubles != 0); |
|---|
| .. | .. |
|---|
| 4414 | 4425 | push_for_double: |
|---|
| 4415 | 4426 | push_for_double_split(trans, root, path, data_size); |
|---|
| 4416 | 4427 | tried_avoid_double = 1; |
|---|
| 4417 | | - if (btrfs_leaf_free_space(fs_info, path->nodes[0]) >= data_size) |
|---|
| 4428 | + if (btrfs_leaf_free_space(path->nodes[0]) >= data_size) |
|---|
| 4418 | 4429 | return 0; |
|---|
| 4419 | 4430 | goto again; |
|---|
| 4420 | 4431 | } |
|---|
| .. | .. |
|---|
| 4423 | 4434 | struct btrfs_root *root, |
|---|
| 4424 | 4435 | struct btrfs_path *path, int ins_len) |
|---|
| 4425 | 4436 | { |
|---|
| 4426 | | - struct btrfs_fs_info *fs_info = root->fs_info; |
|---|
| 4427 | 4437 | struct btrfs_key key; |
|---|
| 4428 | 4438 | struct extent_buffer *leaf; |
|---|
| 4429 | 4439 | struct btrfs_file_extent_item *fi; |
|---|
| .. | .. |
|---|
| 4437 | 4447 | BUG_ON(key.type != BTRFS_EXTENT_DATA_KEY && |
|---|
| 4438 | 4448 | key.type != BTRFS_EXTENT_CSUM_KEY); |
|---|
| 4439 | 4449 | |
|---|
| 4440 | | - if (btrfs_leaf_free_space(fs_info, leaf) >= ins_len) |
|---|
| 4450 | + if (btrfs_leaf_free_space(leaf) >= ins_len) |
|---|
| 4441 | 4451 | return 0; |
|---|
| 4442 | 4452 | |
|---|
| 4443 | 4453 | item_size = btrfs_item_size_nr(leaf, path->slots[0]); |
|---|
| .. | .. |
|---|
| 4464 | 4474 | goto err; |
|---|
| 4465 | 4475 | |
|---|
| 4466 | 4476 | /* the leaf has changed, it now has room. return now */ |
|---|
| 4467 | | - if (btrfs_leaf_free_space(fs_info, path->nodes[0]) >= ins_len) |
|---|
| 4477 | + if (btrfs_leaf_free_space(path->nodes[0]) >= ins_len) |
|---|
| 4468 | 4478 | goto err; |
|---|
| 4469 | 4479 | |
|---|
| 4470 | 4480 | if (key.type == BTRFS_EXTENT_DATA_KEY) { |
|---|
| .. | .. |
|---|
| 4487 | 4497 | return ret; |
|---|
| 4488 | 4498 | } |
|---|
| 4489 | 4499 | |
|---|
| 4490 | | -static noinline int split_item(struct btrfs_fs_info *fs_info, |
|---|
| 4491 | | - struct btrfs_path *path, |
|---|
| 4500 | +static noinline int split_item(struct btrfs_path *path, |
|---|
| 4492 | 4501 | const struct btrfs_key *new_key, |
|---|
| 4493 | 4502 | unsigned long split_offset) |
|---|
| 4494 | 4503 | { |
|---|
| .. | .. |
|---|
| 4503 | 4512 | struct btrfs_disk_key disk_key; |
|---|
| 4504 | 4513 | |
|---|
| 4505 | 4514 | leaf = path->nodes[0]; |
|---|
| 4506 | | - BUG_ON(btrfs_leaf_free_space(fs_info, leaf) < sizeof(struct btrfs_item)); |
|---|
| 4515 | + BUG_ON(btrfs_leaf_free_space(leaf) < sizeof(struct btrfs_item)); |
|---|
| 4507 | 4516 | |
|---|
| 4508 | 4517 | btrfs_set_path_blocking(path); |
|---|
| 4509 | 4518 | |
|---|
| .. | .. |
|---|
| 4552 | 4561 | item_size - split_offset); |
|---|
| 4553 | 4562 | btrfs_mark_buffer_dirty(leaf); |
|---|
| 4554 | 4563 | |
|---|
| 4555 | | - BUG_ON(btrfs_leaf_free_space(fs_info, leaf) < 0); |
|---|
| 4564 | + BUG_ON(btrfs_leaf_free_space(leaf) < 0); |
|---|
| 4556 | 4565 | kfree(buf); |
|---|
| 4557 | 4566 | return 0; |
|---|
| 4558 | 4567 | } |
|---|
| .. | .. |
|---|
| 4584 | 4593 | if (ret) |
|---|
| 4585 | 4594 | return ret; |
|---|
| 4586 | 4595 | |
|---|
| 4587 | | - ret = split_item(root->fs_info, path, new_key, split_offset); |
|---|
| 4596 | + ret = split_item(path, new_key, split_offset); |
|---|
| 4588 | 4597 | return ret; |
|---|
| 4589 | 4598 | } |
|---|
| 4590 | 4599 | |
|---|
| .. | .. |
|---|
| 4613 | 4622 | return ret; |
|---|
| 4614 | 4623 | |
|---|
| 4615 | 4624 | path->slots[0]++; |
|---|
| 4616 | | - setup_items_for_insert(root, path, new_key, &item_size, |
|---|
| 4617 | | - item_size, item_size + |
|---|
| 4618 | | - sizeof(struct btrfs_item), 1); |
|---|
| 4625 | + setup_items_for_insert(root, path, new_key, &item_size, 1); |
|---|
| 4619 | 4626 | leaf = path->nodes[0]; |
|---|
| 4620 | 4627 | memcpy_extent_buffer(leaf, |
|---|
| 4621 | 4628 | btrfs_item_ptr_offset(leaf, path->slots[0]), |
|---|
| .. | .. |
|---|
| 4630 | 4637 | * off the end of the item or if we shift the item to chop bytes off |
|---|
| 4631 | 4638 | * the front. |
|---|
| 4632 | 4639 | */ |
|---|
| 4633 | | -void btrfs_truncate_item(struct btrfs_fs_info *fs_info, |
|---|
| 4634 | | - struct btrfs_path *path, u32 new_size, int from_end) |
|---|
| 4640 | +void btrfs_truncate_item(struct btrfs_path *path, u32 new_size, int from_end) |
|---|
| 4635 | 4641 | { |
|---|
| 4636 | 4642 | int slot; |
|---|
| 4637 | 4643 | struct extent_buffer *leaf; |
|---|
| .. | .. |
|---|
| 4644 | 4650 | int i; |
|---|
| 4645 | 4651 | struct btrfs_map_token token; |
|---|
| 4646 | 4652 | |
|---|
| 4647 | | - btrfs_init_map_token(&token); |
|---|
| 4648 | | - |
|---|
| 4649 | 4653 | leaf = path->nodes[0]; |
|---|
| 4650 | 4654 | slot = path->slots[0]; |
|---|
| 4651 | 4655 | |
|---|
| .. | .. |
|---|
| 4654 | 4658 | return; |
|---|
| 4655 | 4659 | |
|---|
| 4656 | 4660 | nritems = btrfs_header_nritems(leaf); |
|---|
| 4657 | | - data_end = leaf_data_end(fs_info, leaf); |
|---|
| 4661 | + data_end = leaf_data_end(leaf); |
|---|
| 4658 | 4662 | |
|---|
| 4659 | 4663 | old_data_start = btrfs_item_offset_nr(leaf, slot); |
|---|
| 4660 | 4664 | |
|---|
| .. | .. |
|---|
| 4667 | 4671 | * item0..itemN ... dataN.offset..dataN.size .. data0.size |
|---|
| 4668 | 4672 | */ |
|---|
| 4669 | 4673 | /* first correct the data pointers */ |
|---|
| 4674 | + btrfs_init_map_token(&token, leaf); |
|---|
| 4670 | 4675 | for (i = slot; i < nritems; i++) { |
|---|
| 4671 | 4676 | u32 ioff; |
|---|
| 4672 | 4677 | item = btrfs_item_nr(i); |
|---|
| 4673 | 4678 | |
|---|
| 4674 | | - ioff = btrfs_token_item_offset(leaf, item, &token); |
|---|
| 4675 | | - btrfs_set_token_item_offset(leaf, item, |
|---|
| 4676 | | - ioff + size_diff, &token); |
|---|
| 4679 | + ioff = btrfs_token_item_offset(&token, item); |
|---|
| 4680 | + btrfs_set_token_item_offset(&token, item, ioff + size_diff); |
|---|
| 4677 | 4681 | } |
|---|
| 4678 | 4682 | |
|---|
| 4679 | 4683 | /* shift the data */ |
|---|
| .. | .. |
|---|
| 4720 | 4724 | btrfs_set_item_size(leaf, item, new_size); |
|---|
| 4721 | 4725 | btrfs_mark_buffer_dirty(leaf); |
|---|
| 4722 | 4726 | |
|---|
| 4723 | | - if (btrfs_leaf_free_space(fs_info, leaf) < 0) { |
|---|
| 4727 | + if (btrfs_leaf_free_space(leaf) < 0) { |
|---|
| 4724 | 4728 | btrfs_print_leaf(leaf); |
|---|
| 4725 | 4729 | BUG(); |
|---|
| 4726 | 4730 | } |
|---|
| .. | .. |
|---|
| 4729 | 4733 | /* |
|---|
| 4730 | 4734 | * make the item pointed to by the path bigger, data_size is the added size. |
|---|
| 4731 | 4735 | */ |
|---|
| 4732 | | -void btrfs_extend_item(struct btrfs_fs_info *fs_info, struct btrfs_path *path, |
|---|
| 4733 | | - u32 data_size) |
|---|
| 4736 | +void btrfs_extend_item(struct btrfs_path *path, u32 data_size) |
|---|
| 4734 | 4737 | { |
|---|
| 4735 | 4738 | int slot; |
|---|
| 4736 | 4739 | struct extent_buffer *leaf; |
|---|
| .. | .. |
|---|
| 4742 | 4745 | int i; |
|---|
| 4743 | 4746 | struct btrfs_map_token token; |
|---|
| 4744 | 4747 | |
|---|
| 4745 | | - btrfs_init_map_token(&token); |
|---|
| 4746 | | - |
|---|
| 4747 | 4748 | leaf = path->nodes[0]; |
|---|
| 4748 | 4749 | |
|---|
| 4749 | 4750 | nritems = btrfs_header_nritems(leaf); |
|---|
| 4750 | | - data_end = leaf_data_end(fs_info, leaf); |
|---|
| 4751 | + data_end = leaf_data_end(leaf); |
|---|
| 4751 | 4752 | |
|---|
| 4752 | | - if (btrfs_leaf_free_space(fs_info, leaf) < data_size) { |
|---|
| 4753 | + if (btrfs_leaf_free_space(leaf) < data_size) { |
|---|
| 4753 | 4754 | btrfs_print_leaf(leaf); |
|---|
| 4754 | 4755 | BUG(); |
|---|
| 4755 | 4756 | } |
|---|
| .. | .. |
|---|
| 4759 | 4760 | BUG_ON(slot < 0); |
|---|
| 4760 | 4761 | if (slot >= nritems) { |
|---|
| 4761 | 4762 | btrfs_print_leaf(leaf); |
|---|
| 4762 | | - btrfs_crit(fs_info, "slot %d too large, nritems %d", |
|---|
| 4763 | + btrfs_crit(leaf->fs_info, "slot %d too large, nritems %d", |
|---|
| 4763 | 4764 | slot, nritems); |
|---|
| 4764 | | - BUG_ON(1); |
|---|
| 4765 | + BUG(); |
|---|
| 4765 | 4766 | } |
|---|
| 4766 | 4767 | |
|---|
| 4767 | 4768 | /* |
|---|
| 4768 | 4769 | * item0..itemN ... dataN.offset..dataN.size .. data0.size |
|---|
| 4769 | 4770 | */ |
|---|
| 4770 | 4771 | /* first correct the data pointers */ |
|---|
| 4772 | + btrfs_init_map_token(&token, leaf); |
|---|
| 4771 | 4773 | for (i = slot; i < nritems; i++) { |
|---|
| 4772 | 4774 | u32 ioff; |
|---|
| 4773 | 4775 | item = btrfs_item_nr(i); |
|---|
| 4774 | 4776 | |
|---|
| 4775 | | - ioff = btrfs_token_item_offset(leaf, item, &token); |
|---|
| 4776 | | - btrfs_set_token_item_offset(leaf, item, |
|---|
| 4777 | | - ioff - data_size, &token); |
|---|
| 4777 | + ioff = btrfs_token_item_offset(&token, item); |
|---|
| 4778 | + btrfs_set_token_item_offset(&token, item, ioff - data_size); |
|---|
| 4778 | 4779 | } |
|---|
| 4779 | 4780 | |
|---|
| 4780 | 4781 | /* shift the data */ |
|---|
| .. | .. |
|---|
| 4788 | 4789 | btrfs_set_item_size(leaf, item, old_size + data_size); |
|---|
| 4789 | 4790 | btrfs_mark_buffer_dirty(leaf); |
|---|
| 4790 | 4791 | |
|---|
| 4791 | | - if (btrfs_leaf_free_space(fs_info, leaf) < 0) { |
|---|
| 4792 | + if (btrfs_leaf_free_space(leaf) < 0) { |
|---|
| 4792 | 4793 | btrfs_print_leaf(leaf); |
|---|
| 4793 | 4794 | BUG(); |
|---|
| 4794 | 4795 | } |
|---|
| 4795 | 4796 | } |
|---|
| 4796 | 4797 | |
|---|
| 4797 | | -/* |
|---|
| 4798 | | - * this is a helper for btrfs_insert_empty_items, the main goal here is |
|---|
| 4799 | | - * to save stack depth by doing the bulk of the work in a function |
|---|
| 4800 | | - * that doesn't call btrfs_search_slot |
|---|
| 4798 | +/** |
|---|
| 4799 | + * setup_items_for_insert - Helper called before inserting one or more items |
|---|
| 4800 | + * to a leaf. Main purpose is to save stack depth by doing the bulk of the work |
|---|
| 4801 | + * in a function that doesn't call btrfs_search_slot |
|---|
| 4802 | + * |
|---|
| 4803 | + * @root: root we are inserting items to |
|---|
| 4804 | + * @path: points to the leaf/slot where we are going to insert new items |
|---|
| 4805 | + * @cpu_key: array of keys for items to be inserted |
|---|
| 4806 | + * @data_size: size of the body of each item we are going to insert |
|---|
| 4807 | + * @nr: size of @cpu_key/@data_size arrays |
|---|
| 4801 | 4808 | */ |
|---|
| 4802 | 4809 | void setup_items_for_insert(struct btrfs_root *root, struct btrfs_path *path, |
|---|
| 4803 | 4810 | const struct btrfs_key *cpu_key, u32 *data_size, |
|---|
| 4804 | | - u32 total_data, u32 total_size, int nr) |
|---|
| 4811 | + int nr) |
|---|
| 4805 | 4812 | { |
|---|
| 4806 | 4813 | struct btrfs_fs_info *fs_info = root->fs_info; |
|---|
| 4807 | 4814 | struct btrfs_item *item; |
|---|
| .. | .. |
|---|
| 4812 | 4819 | struct extent_buffer *leaf; |
|---|
| 4813 | 4820 | int slot; |
|---|
| 4814 | 4821 | struct btrfs_map_token token; |
|---|
| 4822 | + u32 total_size; |
|---|
| 4823 | + u32 total_data = 0; |
|---|
| 4824 | + |
|---|
| 4825 | + for (i = 0; i < nr; i++) |
|---|
| 4826 | + total_data += data_size[i]; |
|---|
| 4827 | + total_size = total_data + (nr * sizeof(struct btrfs_item)); |
|---|
| 4815 | 4828 | |
|---|
| 4816 | 4829 | if (path->slots[0] == 0) { |
|---|
| 4817 | 4830 | btrfs_cpu_key_to_disk(&disk_key, cpu_key); |
|---|
| .. | .. |
|---|
| 4819 | 4832 | } |
|---|
| 4820 | 4833 | btrfs_unlock_up_safe(path, 1); |
|---|
| 4821 | 4834 | |
|---|
| 4822 | | - btrfs_init_map_token(&token); |
|---|
| 4823 | | - |
|---|
| 4824 | 4835 | leaf = path->nodes[0]; |
|---|
| 4825 | 4836 | slot = path->slots[0]; |
|---|
| 4826 | 4837 | |
|---|
| 4827 | 4838 | nritems = btrfs_header_nritems(leaf); |
|---|
| 4828 | | - data_end = leaf_data_end(fs_info, leaf); |
|---|
| 4839 | + data_end = leaf_data_end(leaf); |
|---|
| 4829 | 4840 | |
|---|
| 4830 | | - if (btrfs_leaf_free_space(fs_info, leaf) < total_size) { |
|---|
| 4841 | + if (btrfs_leaf_free_space(leaf) < total_size) { |
|---|
| 4831 | 4842 | btrfs_print_leaf(leaf); |
|---|
| 4832 | 4843 | btrfs_crit(fs_info, "not enough freespace need %u have %d", |
|---|
| 4833 | | - total_size, btrfs_leaf_free_space(fs_info, leaf)); |
|---|
| 4844 | + total_size, btrfs_leaf_free_space(leaf)); |
|---|
| 4834 | 4845 | BUG(); |
|---|
| 4835 | 4846 | } |
|---|
| 4836 | 4847 | |
|---|
| 4848 | + btrfs_init_map_token(&token, leaf); |
|---|
| 4837 | 4849 | if (slot != nritems) { |
|---|
| 4838 | 4850 | unsigned int old_data = btrfs_item_end_nr(leaf, slot); |
|---|
| 4839 | 4851 | |
|---|
| 4840 | 4852 | if (old_data < data_end) { |
|---|
| 4841 | 4853 | btrfs_print_leaf(leaf); |
|---|
| 4842 | | - btrfs_crit(fs_info, "slot %d old_data %d data_end %d", |
|---|
| 4854 | + btrfs_crit(fs_info, |
|---|
| 4855 | + "item at slot %d with data offset %u beyond data end of leaf %u", |
|---|
| 4843 | 4856 | slot, old_data, data_end); |
|---|
| 4844 | | - BUG_ON(1); |
|---|
| 4857 | + BUG(); |
|---|
| 4845 | 4858 | } |
|---|
| 4846 | 4859 | /* |
|---|
| 4847 | 4860 | * item0..itemN ... dataN.offset..dataN.size .. data0.size |
|---|
| .. | .. |
|---|
| 4851 | 4864 | u32 ioff; |
|---|
| 4852 | 4865 | |
|---|
| 4853 | 4866 | item = btrfs_item_nr(i); |
|---|
| 4854 | | - ioff = btrfs_token_item_offset(leaf, item, &token); |
|---|
| 4855 | | - btrfs_set_token_item_offset(leaf, item, |
|---|
| 4856 | | - ioff - total_data, &token); |
|---|
| 4867 | + ioff = btrfs_token_item_offset(&token, item); |
|---|
| 4868 | + btrfs_set_token_item_offset(&token, item, |
|---|
| 4869 | + ioff - total_data); |
|---|
| 4857 | 4870 | } |
|---|
| 4858 | 4871 | /* shift the items */ |
|---|
| 4859 | 4872 | memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot + nr), |
|---|
| .. | .. |
|---|
| 4872 | 4885 | btrfs_cpu_key_to_disk(&disk_key, cpu_key + i); |
|---|
| 4873 | 4886 | btrfs_set_item_key(leaf, &disk_key, slot + i); |
|---|
| 4874 | 4887 | item = btrfs_item_nr(slot + i); |
|---|
| 4875 | | - btrfs_set_token_item_offset(leaf, item, |
|---|
| 4876 | | - data_end - data_size[i], &token); |
|---|
| 4877 | 4888 | data_end -= data_size[i]; |
|---|
| 4878 | | - btrfs_set_token_item_size(leaf, item, data_size[i], &token); |
|---|
| 4889 | + btrfs_set_token_item_offset(&token, item, data_end); |
|---|
| 4890 | + btrfs_set_token_item_size(&token, item, data_size[i]); |
|---|
| 4879 | 4891 | } |
|---|
| 4880 | 4892 | |
|---|
| 4881 | 4893 | btrfs_set_header_nritems(leaf, nritems + nr); |
|---|
| 4882 | 4894 | btrfs_mark_buffer_dirty(leaf); |
|---|
| 4883 | 4895 | |
|---|
| 4884 | | - if (btrfs_leaf_free_space(fs_info, leaf) < 0) { |
|---|
| 4896 | + if (btrfs_leaf_free_space(leaf) < 0) { |
|---|
| 4885 | 4897 | btrfs_print_leaf(leaf); |
|---|
| 4886 | 4898 | BUG(); |
|---|
| 4887 | 4899 | } |
|---|
| .. | .. |
|---|
| 4916 | 4928 | slot = path->slots[0]; |
|---|
| 4917 | 4929 | BUG_ON(slot < 0); |
|---|
| 4918 | 4930 | |
|---|
| 4919 | | - setup_items_for_insert(root, path, cpu_key, data_size, |
|---|
| 4920 | | - total_data, total_size, nr); |
|---|
| 4931 | + setup_items_for_insert(root, path, cpu_key, data_size, nr); |
|---|
| 4921 | 4932 | return 0; |
|---|
| 4922 | 4933 | } |
|---|
| 4923 | 4934 | |
|---|
| .. | .. |
|---|
| 5020 | 5031 | |
|---|
| 5021 | 5032 | root_sub_used(root, leaf->len); |
|---|
| 5022 | 5033 | |
|---|
| 5023 | | - extent_buffer_get(leaf); |
|---|
| 5034 | + atomic_inc(&leaf->refs); |
|---|
| 5024 | 5035 | btrfs_free_tree_block(trans, root, leaf, 0, 1); |
|---|
| 5025 | 5036 | free_extent_buffer_stale(leaf); |
|---|
| 5026 | 5037 | } |
|---|
| .. | .. |
|---|
| 5040 | 5051 | int wret; |
|---|
| 5041 | 5052 | int i; |
|---|
| 5042 | 5053 | u32 nritems; |
|---|
| 5043 | | - struct btrfs_map_token token; |
|---|
| 5044 | | - |
|---|
| 5045 | | - btrfs_init_map_token(&token); |
|---|
| 5046 | 5054 | |
|---|
| 5047 | 5055 | leaf = path->nodes[0]; |
|---|
| 5048 | 5056 | last_off = btrfs_item_offset_nr(leaf, slot + nr - 1); |
|---|
| .. | .. |
|---|
| 5053 | 5061 | nritems = btrfs_header_nritems(leaf); |
|---|
| 5054 | 5062 | |
|---|
| 5055 | 5063 | if (slot + nr != nritems) { |
|---|
| 5056 | | - int data_end = leaf_data_end(fs_info, leaf); |
|---|
| 5064 | + int data_end = leaf_data_end(leaf); |
|---|
| 5065 | + struct btrfs_map_token token; |
|---|
| 5057 | 5066 | |
|---|
| 5058 | 5067 | memmove_extent_buffer(leaf, BTRFS_LEAF_DATA_OFFSET + |
|---|
| 5059 | 5068 | data_end + dsize, |
|---|
| 5060 | 5069 | BTRFS_LEAF_DATA_OFFSET + data_end, |
|---|
| 5061 | 5070 | last_off - data_end); |
|---|
| 5062 | 5071 | |
|---|
| 5072 | + btrfs_init_map_token(&token, leaf); |
|---|
| 5063 | 5073 | for (i = slot + nr; i < nritems; i++) { |
|---|
| 5064 | 5074 | u32 ioff; |
|---|
| 5065 | 5075 | |
|---|
| 5066 | 5076 | item = btrfs_item_nr(i); |
|---|
| 5067 | | - ioff = btrfs_token_item_offset(leaf, item, &token); |
|---|
| 5068 | | - btrfs_set_token_item_offset(leaf, item, |
|---|
| 5069 | | - ioff + dsize, &token); |
|---|
| 5077 | + ioff = btrfs_token_item_offset(&token, item); |
|---|
| 5078 | + btrfs_set_token_item_offset(&token, item, ioff + dsize); |
|---|
| 5070 | 5079 | } |
|---|
| 5071 | 5080 | |
|---|
| 5072 | 5081 | memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot), |
|---|
| .. | .. |
|---|
| 5083 | 5092 | btrfs_set_header_level(leaf, 0); |
|---|
| 5084 | 5093 | } else { |
|---|
| 5085 | 5094 | btrfs_set_path_blocking(path); |
|---|
| 5086 | | - clean_tree_block(fs_info, leaf); |
|---|
| 5095 | + btrfs_clean_tree_block(leaf); |
|---|
| 5087 | 5096 | btrfs_del_leaf(trans, root, path, leaf); |
|---|
| 5088 | 5097 | } |
|---|
| 5089 | 5098 | } else { |
|---|
| .. | .. |
|---|
| 5102 | 5111 | * for possible call to del_ptr below |
|---|
| 5103 | 5112 | */ |
|---|
| 5104 | 5113 | slot = path->slots[1]; |
|---|
| 5105 | | - extent_buffer_get(leaf); |
|---|
| 5114 | + atomic_inc(&leaf->refs); |
|---|
| 5106 | 5115 | |
|---|
| 5107 | 5116 | btrfs_set_path_blocking(path); |
|---|
| 5108 | 5117 | wret = push_leaf_left(trans, root, path, 1, 1, |
|---|
| .. | .. |
|---|
| 5213 | 5222 | struct btrfs_path *path, |
|---|
| 5214 | 5223 | u64 min_trans) |
|---|
| 5215 | 5224 | { |
|---|
| 5216 | | - struct btrfs_fs_info *fs_info = root->fs_info; |
|---|
| 5217 | 5225 | struct extent_buffer *cur; |
|---|
| 5218 | 5226 | struct btrfs_key found_key; |
|---|
| 5219 | 5227 | int slot; |
|---|
| .. | .. |
|---|
| 5238 | 5246 | while (1) { |
|---|
| 5239 | 5247 | nritems = btrfs_header_nritems(cur); |
|---|
| 5240 | 5248 | level = btrfs_header_level(cur); |
|---|
| 5241 | | - sret = btrfs_bin_search(cur, min_key, level, &slot); |
|---|
| 5249 | + sret = btrfs_bin_search(cur, min_key, &slot); |
|---|
| 5250 | + if (sret < 0) { |
|---|
| 5251 | + ret = sret; |
|---|
| 5252 | + goto out; |
|---|
| 5253 | + } |
|---|
| 5242 | 5254 | |
|---|
| 5243 | 5255 | /* at the lowest level, we're done, setup the path and exit */ |
|---|
| 5244 | 5256 | if (level == path->lowest_level) { |
|---|
| .. | .. |
|---|
| 5253 | 5265 | slot--; |
|---|
| 5254 | 5266 | /* |
|---|
| 5255 | 5267 | * check this node pointer against the min_trans parameters. |
|---|
| 5256 | | - * If it is too old, old, skip to the next one. |
|---|
| 5268 | + * If it is too old, skip to the next one. |
|---|
| 5257 | 5269 | */ |
|---|
| 5258 | 5270 | while (slot < nritems) { |
|---|
| 5259 | 5271 | u64 gen; |
|---|
| .. | .. |
|---|
| 5290 | 5302 | goto out; |
|---|
| 5291 | 5303 | } |
|---|
| 5292 | 5304 | btrfs_set_path_blocking(path); |
|---|
| 5293 | | - cur = read_node_slot(fs_info, cur, slot); |
|---|
| 5305 | + cur = btrfs_read_node_slot(cur, slot); |
|---|
| 5294 | 5306 | if (IS_ERR(cur)) { |
|---|
| 5295 | 5307 | ret = PTR_ERR(cur); |
|---|
| 5296 | 5308 | goto out; |
|---|
| .. | .. |
|---|
| 5301 | 5313 | path->locks[level - 1] = BTRFS_READ_LOCK; |
|---|
| 5302 | 5314 | path->nodes[level - 1] = cur; |
|---|
| 5303 | 5315 | unlock_up(path, level, 1, 0, NULL); |
|---|
| 5304 | | - btrfs_clear_path_blocking(path, NULL, 0); |
|---|
| 5305 | 5316 | } |
|---|
| 5306 | 5317 | out: |
|---|
| 5307 | 5318 | path->keep_locks = keep_locks; |
|---|
| .. | .. |
|---|
| 5310 | 5321 | btrfs_set_path_blocking(path); |
|---|
| 5311 | 5322 | memcpy(min_key, &found_key, sizeof(found_key)); |
|---|
| 5312 | 5323 | } |
|---|
| 5313 | | - return ret; |
|---|
| 5314 | | -} |
|---|
| 5315 | | - |
|---|
| 5316 | | -static int tree_move_down(struct btrfs_fs_info *fs_info, |
|---|
| 5317 | | - struct btrfs_path *path, |
|---|
| 5318 | | - int *level) |
|---|
| 5319 | | -{ |
|---|
| 5320 | | - struct extent_buffer *eb; |
|---|
| 5321 | | - |
|---|
| 5322 | | - BUG_ON(*level == 0); |
|---|
| 5323 | | - eb = read_node_slot(fs_info, path->nodes[*level], path->slots[*level]); |
|---|
| 5324 | | - if (IS_ERR(eb)) |
|---|
| 5325 | | - return PTR_ERR(eb); |
|---|
| 5326 | | - |
|---|
| 5327 | | - path->nodes[*level - 1] = eb; |
|---|
| 5328 | | - path->slots[*level - 1] = 0; |
|---|
| 5329 | | - (*level)--; |
|---|
| 5330 | | - return 0; |
|---|
| 5331 | | -} |
|---|
| 5332 | | - |
|---|
| 5333 | | -static int tree_move_next_or_upnext(struct btrfs_path *path, |
|---|
| 5334 | | - int *level, int root_level) |
|---|
| 5335 | | -{ |
|---|
| 5336 | | - int ret = 0; |
|---|
| 5337 | | - int nritems; |
|---|
| 5338 | | - nritems = btrfs_header_nritems(path->nodes[*level]); |
|---|
| 5339 | | - |
|---|
| 5340 | | - path->slots[*level]++; |
|---|
| 5341 | | - |
|---|
| 5342 | | - while (path->slots[*level] >= nritems) { |
|---|
| 5343 | | - if (*level == root_level) |
|---|
| 5344 | | - return -1; |
|---|
| 5345 | | - |
|---|
| 5346 | | - /* move upnext */ |
|---|
| 5347 | | - path->slots[*level] = 0; |
|---|
| 5348 | | - free_extent_buffer(path->nodes[*level]); |
|---|
| 5349 | | - path->nodes[*level] = NULL; |
|---|
| 5350 | | - (*level)++; |
|---|
| 5351 | | - path->slots[*level]++; |
|---|
| 5352 | | - |
|---|
| 5353 | | - nritems = btrfs_header_nritems(path->nodes[*level]); |
|---|
| 5354 | | - ret = 1; |
|---|
| 5355 | | - } |
|---|
| 5356 | | - return ret; |
|---|
| 5357 | | -} |
|---|
| 5358 | | - |
|---|
| 5359 | | -/* |
|---|
| 5360 | | - * Returns 1 if it had to move up and next. 0 is returned if it moved only next |
|---|
| 5361 | | - * or down. |
|---|
| 5362 | | - */ |
|---|
| 5363 | | -static int tree_advance(struct btrfs_fs_info *fs_info, |
|---|
| 5364 | | - struct btrfs_path *path, |
|---|
| 5365 | | - int *level, int root_level, |
|---|
| 5366 | | - int allow_down, |
|---|
| 5367 | | - struct btrfs_key *key) |
|---|
| 5368 | | -{ |
|---|
| 5369 | | - int ret; |
|---|
| 5370 | | - |
|---|
| 5371 | | - if (*level == 0 || !allow_down) { |
|---|
| 5372 | | - ret = tree_move_next_or_upnext(path, level, root_level); |
|---|
| 5373 | | - } else { |
|---|
| 5374 | | - ret = tree_move_down(fs_info, path, level); |
|---|
| 5375 | | - } |
|---|
| 5376 | | - if (ret >= 0) { |
|---|
| 5377 | | - if (*level == 0) |
|---|
| 5378 | | - btrfs_item_key_to_cpu(path->nodes[*level], key, |
|---|
| 5379 | | - path->slots[*level]); |
|---|
| 5380 | | - else |
|---|
| 5381 | | - btrfs_node_key_to_cpu(path->nodes[*level], key, |
|---|
| 5382 | | - path->slots[*level]); |
|---|
| 5383 | | - } |
|---|
| 5384 | | - return ret; |
|---|
| 5385 | | -} |
|---|
| 5386 | | - |
|---|
| 5387 | | -static int tree_compare_item(struct btrfs_path *left_path, |
|---|
| 5388 | | - struct btrfs_path *right_path, |
|---|
| 5389 | | - char *tmp_buf) |
|---|
| 5390 | | -{ |
|---|
| 5391 | | - int cmp; |
|---|
| 5392 | | - int len1, len2; |
|---|
| 5393 | | - unsigned long off1, off2; |
|---|
| 5394 | | - |
|---|
| 5395 | | - len1 = btrfs_item_size_nr(left_path->nodes[0], left_path->slots[0]); |
|---|
| 5396 | | - len2 = btrfs_item_size_nr(right_path->nodes[0], right_path->slots[0]); |
|---|
| 5397 | | - if (len1 != len2) |
|---|
| 5398 | | - return 1; |
|---|
| 5399 | | - |
|---|
| 5400 | | - off1 = btrfs_item_ptr_offset(left_path->nodes[0], left_path->slots[0]); |
|---|
| 5401 | | - off2 = btrfs_item_ptr_offset(right_path->nodes[0], |
|---|
| 5402 | | - right_path->slots[0]); |
|---|
| 5403 | | - |
|---|
| 5404 | | - read_extent_buffer(left_path->nodes[0], tmp_buf, off1, len1); |
|---|
| 5405 | | - |
|---|
| 5406 | | - cmp = memcmp_extent_buffer(right_path->nodes[0], tmp_buf, off2, len1); |
|---|
| 5407 | | - if (cmp) |
|---|
| 5408 | | - return 1; |
|---|
| 5409 | | - return 0; |
|---|
| 5410 | | -} |
|---|
| 5411 | | - |
|---|
| 5412 | | -#define ADVANCE 1 |
|---|
| 5413 | | -#define ADVANCE_ONLY_NEXT -1 |
|---|
| 5414 | | - |
|---|
| 5415 | | -/* |
|---|
| 5416 | | - * This function compares two trees and calls the provided callback for |
|---|
| 5417 | | - * every changed/new/deleted item it finds. |
|---|
| 5418 | | - * If shared tree blocks are encountered, whole subtrees are skipped, making |
|---|
| 5419 | | - * the compare pretty fast on snapshotted subvolumes. |
|---|
| 5420 | | - * |
|---|
| 5421 | | - * This currently works on commit roots only. As commit roots are read only, |
|---|
| 5422 | | - * we don't do any locking. The commit roots are protected with transactions. |
|---|
| 5423 | | - * Transactions are ended and rejoined when a commit is tried in between. |
|---|
| 5424 | | - * |
|---|
| 5425 | | - * This function checks for modifications done to the trees while comparing. |
|---|
| 5426 | | - * If it detects a change, it aborts immediately. |
|---|
| 5427 | | - */ |
|---|
| 5428 | | -int btrfs_compare_trees(struct btrfs_root *left_root, |
|---|
| 5429 | | - struct btrfs_root *right_root, |
|---|
| 5430 | | - btrfs_changed_cb_t changed_cb, void *ctx) |
|---|
| 5431 | | -{ |
|---|
| 5432 | | - struct btrfs_fs_info *fs_info = left_root->fs_info; |
|---|
| 5433 | | - int ret; |
|---|
| 5434 | | - int cmp; |
|---|
| 5435 | | - struct btrfs_path *left_path = NULL; |
|---|
| 5436 | | - struct btrfs_path *right_path = NULL; |
|---|
| 5437 | | - struct btrfs_key left_key; |
|---|
| 5438 | | - struct btrfs_key right_key; |
|---|
| 5439 | | - char *tmp_buf = NULL; |
|---|
| 5440 | | - int left_root_level; |
|---|
| 5441 | | - int right_root_level; |
|---|
| 5442 | | - int left_level; |
|---|
| 5443 | | - int right_level; |
|---|
| 5444 | | - int left_end_reached; |
|---|
| 5445 | | - int right_end_reached; |
|---|
| 5446 | | - int advance_left; |
|---|
| 5447 | | - int advance_right; |
|---|
| 5448 | | - u64 left_blockptr; |
|---|
| 5449 | | - u64 right_blockptr; |
|---|
| 5450 | | - u64 left_gen; |
|---|
| 5451 | | - u64 right_gen; |
|---|
| 5452 | | - |
|---|
| 5453 | | - left_path = btrfs_alloc_path(); |
|---|
| 5454 | | - if (!left_path) { |
|---|
| 5455 | | - ret = -ENOMEM; |
|---|
| 5456 | | - goto out; |
|---|
| 5457 | | - } |
|---|
| 5458 | | - right_path = btrfs_alloc_path(); |
|---|
| 5459 | | - if (!right_path) { |
|---|
| 5460 | | - ret = -ENOMEM; |
|---|
| 5461 | | - goto out; |
|---|
| 5462 | | - } |
|---|
| 5463 | | - |
|---|
| 5464 | | - tmp_buf = kvmalloc(fs_info->nodesize, GFP_KERNEL); |
|---|
| 5465 | | - if (!tmp_buf) { |
|---|
| 5466 | | - ret = -ENOMEM; |
|---|
| 5467 | | - goto out; |
|---|
| 5468 | | - } |
|---|
| 5469 | | - |
|---|
| 5470 | | - left_path->search_commit_root = 1; |
|---|
| 5471 | | - left_path->skip_locking = 1; |
|---|
| 5472 | | - right_path->search_commit_root = 1; |
|---|
| 5473 | | - right_path->skip_locking = 1; |
|---|
| 5474 | | - |
|---|
| 5475 | | - /* |
|---|
| 5476 | | - * Strategy: Go to the first items of both trees. Then do |
|---|
| 5477 | | - * |
|---|
| 5478 | | - * If both trees are at level 0 |
|---|
| 5479 | | - * Compare keys of current items |
|---|
| 5480 | | - * If left < right treat left item as new, advance left tree |
|---|
| 5481 | | - * and repeat |
|---|
| 5482 | | - * If left > right treat right item as deleted, advance right tree |
|---|
| 5483 | | - * and repeat |
|---|
| 5484 | | - * If left == right do deep compare of items, treat as changed if |
|---|
| 5485 | | - * needed, advance both trees and repeat |
|---|
| 5486 | | - * If both trees are at the same level but not at level 0 |
|---|
| 5487 | | - * Compare keys of current nodes/leafs |
|---|
| 5488 | | - * If left < right advance left tree and repeat |
|---|
| 5489 | | - * If left > right advance right tree and repeat |
|---|
| 5490 | | - * If left == right compare blockptrs of the next nodes/leafs |
|---|
| 5491 | | - * If they match advance both trees but stay at the same level |
|---|
| 5492 | | - * and repeat |
|---|
| 5493 | | - * If they don't match advance both trees while allowing to go |
|---|
| 5494 | | - * deeper and repeat |
|---|
| 5495 | | - * If tree levels are different |
|---|
| 5496 | | - * Advance the tree that needs it and repeat |
|---|
| 5497 | | - * |
|---|
| 5498 | | - * Advancing a tree means: |
|---|
| 5499 | | - * If we are at level 0, try to go to the next slot. If that's not |
|---|
| 5500 | | - * possible, go one level up and repeat. Stop when we found a level |
|---|
| 5501 | | - * where we could go to the next slot. We may at this point be on a |
|---|
| 5502 | | - * node or a leaf. |
|---|
| 5503 | | - * |
|---|
| 5504 | | - * If we are not at level 0 and not on shared tree blocks, go one |
|---|
| 5505 | | - * level deeper. |
|---|
| 5506 | | - * |
|---|
| 5507 | | - * If we are not at level 0 and on shared tree blocks, go one slot to |
|---|
| 5508 | | - * the right if possible or go up and right. |
|---|
| 5509 | | - */ |
|---|
| 5510 | | - |
|---|
| 5511 | | - down_read(&fs_info->commit_root_sem); |
|---|
| 5512 | | - left_level = btrfs_header_level(left_root->commit_root); |
|---|
| 5513 | | - left_root_level = left_level; |
|---|
| 5514 | | - left_path->nodes[left_level] = |
|---|
| 5515 | | - btrfs_clone_extent_buffer(left_root->commit_root); |
|---|
| 5516 | | - if (!left_path->nodes[left_level]) { |
|---|
| 5517 | | - up_read(&fs_info->commit_root_sem); |
|---|
| 5518 | | - ret = -ENOMEM; |
|---|
| 5519 | | - goto out; |
|---|
| 5520 | | - } |
|---|
| 5521 | | - extent_buffer_get(left_path->nodes[left_level]); |
|---|
| 5522 | | - |
|---|
| 5523 | | - right_level = btrfs_header_level(right_root->commit_root); |
|---|
| 5524 | | - right_root_level = right_level; |
|---|
| 5525 | | - right_path->nodes[right_level] = |
|---|
| 5526 | | - btrfs_clone_extent_buffer(right_root->commit_root); |
|---|
| 5527 | | - if (!right_path->nodes[right_level]) { |
|---|
| 5528 | | - up_read(&fs_info->commit_root_sem); |
|---|
| 5529 | | - ret = -ENOMEM; |
|---|
| 5530 | | - goto out; |
|---|
| 5531 | | - } |
|---|
| 5532 | | - extent_buffer_get(right_path->nodes[right_level]); |
|---|
| 5533 | | - up_read(&fs_info->commit_root_sem); |
|---|
| 5534 | | - |
|---|
| 5535 | | - if (left_level == 0) |
|---|
| 5536 | | - btrfs_item_key_to_cpu(left_path->nodes[left_level], |
|---|
| 5537 | | - &left_key, left_path->slots[left_level]); |
|---|
| 5538 | | - else |
|---|
| 5539 | | - btrfs_node_key_to_cpu(left_path->nodes[left_level], |
|---|
| 5540 | | - &left_key, left_path->slots[left_level]); |
|---|
| 5541 | | - if (right_level == 0) |
|---|
| 5542 | | - btrfs_item_key_to_cpu(right_path->nodes[right_level], |
|---|
| 5543 | | - &right_key, right_path->slots[right_level]); |
|---|
| 5544 | | - else |
|---|
| 5545 | | - btrfs_node_key_to_cpu(right_path->nodes[right_level], |
|---|
| 5546 | | - &right_key, right_path->slots[right_level]); |
|---|
| 5547 | | - |
|---|
| 5548 | | - left_end_reached = right_end_reached = 0; |
|---|
| 5549 | | - advance_left = advance_right = 0; |
|---|
| 5550 | | - |
|---|
| 5551 | | - while (1) { |
|---|
| 5552 | | - cond_resched(); |
|---|
| 5553 | | - if (advance_left && !left_end_reached) { |
|---|
| 5554 | | - ret = tree_advance(fs_info, left_path, &left_level, |
|---|
| 5555 | | - left_root_level, |
|---|
| 5556 | | - advance_left != ADVANCE_ONLY_NEXT, |
|---|
| 5557 | | - &left_key); |
|---|
| 5558 | | - if (ret == -1) |
|---|
| 5559 | | - left_end_reached = ADVANCE; |
|---|
| 5560 | | - else if (ret < 0) |
|---|
| 5561 | | - goto out; |
|---|
| 5562 | | - advance_left = 0; |
|---|
| 5563 | | - } |
|---|
| 5564 | | - if (advance_right && !right_end_reached) { |
|---|
| 5565 | | - ret = tree_advance(fs_info, right_path, &right_level, |
|---|
| 5566 | | - right_root_level, |
|---|
| 5567 | | - advance_right != ADVANCE_ONLY_NEXT, |
|---|
| 5568 | | - &right_key); |
|---|
| 5569 | | - if (ret == -1) |
|---|
| 5570 | | - right_end_reached = ADVANCE; |
|---|
| 5571 | | - else if (ret < 0) |
|---|
| 5572 | | - goto out; |
|---|
| 5573 | | - advance_right = 0; |
|---|
| 5574 | | - } |
|---|
| 5575 | | - |
|---|
| 5576 | | - if (left_end_reached && right_end_reached) { |
|---|
| 5577 | | - ret = 0; |
|---|
| 5578 | | - goto out; |
|---|
| 5579 | | - } else if (left_end_reached) { |
|---|
| 5580 | | - if (right_level == 0) { |
|---|
| 5581 | | - ret = changed_cb(left_path, right_path, |
|---|
| 5582 | | - &right_key, |
|---|
| 5583 | | - BTRFS_COMPARE_TREE_DELETED, |
|---|
| 5584 | | - ctx); |
|---|
| 5585 | | - if (ret < 0) |
|---|
| 5586 | | - goto out; |
|---|
| 5587 | | - } |
|---|
| 5588 | | - advance_right = ADVANCE; |
|---|
| 5589 | | - continue; |
|---|
| 5590 | | - } else if (right_end_reached) { |
|---|
| 5591 | | - if (left_level == 0) { |
|---|
| 5592 | | - ret = changed_cb(left_path, right_path, |
|---|
| 5593 | | - &left_key, |
|---|
| 5594 | | - BTRFS_COMPARE_TREE_NEW, |
|---|
| 5595 | | - ctx); |
|---|
| 5596 | | - if (ret < 0) |
|---|
| 5597 | | - goto out; |
|---|
| 5598 | | - } |
|---|
| 5599 | | - advance_left = ADVANCE; |
|---|
| 5600 | | - continue; |
|---|
| 5601 | | - } |
|---|
| 5602 | | - |
|---|
| 5603 | | - if (left_level == 0 && right_level == 0) { |
|---|
| 5604 | | - cmp = btrfs_comp_cpu_keys(&left_key, &right_key); |
|---|
| 5605 | | - if (cmp < 0) { |
|---|
| 5606 | | - ret = changed_cb(left_path, right_path, |
|---|
| 5607 | | - &left_key, |
|---|
| 5608 | | - BTRFS_COMPARE_TREE_NEW, |
|---|
| 5609 | | - ctx); |
|---|
| 5610 | | - if (ret < 0) |
|---|
| 5611 | | - goto out; |
|---|
| 5612 | | - advance_left = ADVANCE; |
|---|
| 5613 | | - } else if (cmp > 0) { |
|---|
| 5614 | | - ret = changed_cb(left_path, right_path, |
|---|
| 5615 | | - &right_key, |
|---|
| 5616 | | - BTRFS_COMPARE_TREE_DELETED, |
|---|
| 5617 | | - ctx); |
|---|
| 5618 | | - if (ret < 0) |
|---|
| 5619 | | - goto out; |
|---|
| 5620 | | - advance_right = ADVANCE; |
|---|
| 5621 | | - } else { |
|---|
| 5622 | | - enum btrfs_compare_tree_result result; |
|---|
| 5623 | | - |
|---|
| 5624 | | - WARN_ON(!extent_buffer_uptodate(left_path->nodes[0])); |
|---|
| 5625 | | - ret = tree_compare_item(left_path, right_path, |
|---|
| 5626 | | - tmp_buf); |
|---|
| 5627 | | - if (ret) |
|---|
| 5628 | | - result = BTRFS_COMPARE_TREE_CHANGED; |
|---|
| 5629 | | - else |
|---|
| 5630 | | - result = BTRFS_COMPARE_TREE_SAME; |
|---|
| 5631 | | - ret = changed_cb(left_path, right_path, |
|---|
| 5632 | | - &left_key, result, ctx); |
|---|
| 5633 | | - if (ret < 0) |
|---|
| 5634 | | - goto out; |
|---|
| 5635 | | - advance_left = ADVANCE; |
|---|
| 5636 | | - advance_right = ADVANCE; |
|---|
| 5637 | | - } |
|---|
| 5638 | | - } else if (left_level == right_level) { |
|---|
| 5639 | | - cmp = btrfs_comp_cpu_keys(&left_key, &right_key); |
|---|
| 5640 | | - if (cmp < 0) { |
|---|
| 5641 | | - advance_left = ADVANCE; |
|---|
| 5642 | | - } else if (cmp > 0) { |
|---|
| 5643 | | - advance_right = ADVANCE; |
|---|
| 5644 | | - } else { |
|---|
| 5645 | | - left_blockptr = btrfs_node_blockptr( |
|---|
| 5646 | | - left_path->nodes[left_level], |
|---|
| 5647 | | - left_path->slots[left_level]); |
|---|
| 5648 | | - right_blockptr = btrfs_node_blockptr( |
|---|
| 5649 | | - right_path->nodes[right_level], |
|---|
| 5650 | | - right_path->slots[right_level]); |
|---|
| 5651 | | - left_gen = btrfs_node_ptr_generation( |
|---|
| 5652 | | - left_path->nodes[left_level], |
|---|
| 5653 | | - left_path->slots[left_level]); |
|---|
| 5654 | | - right_gen = btrfs_node_ptr_generation( |
|---|
| 5655 | | - right_path->nodes[right_level], |
|---|
| 5656 | | - right_path->slots[right_level]); |
|---|
| 5657 | | - if (left_blockptr == right_blockptr && |
|---|
| 5658 | | - left_gen == right_gen) { |
|---|
| 5659 | | - /* |
|---|
| 5660 | | - * As we're on a shared block, don't |
|---|
| 5661 | | - * allow to go deeper. |
|---|
| 5662 | | - */ |
|---|
| 5663 | | - advance_left = ADVANCE_ONLY_NEXT; |
|---|
| 5664 | | - advance_right = ADVANCE_ONLY_NEXT; |
|---|
| 5665 | | - } else { |
|---|
| 5666 | | - advance_left = ADVANCE; |
|---|
| 5667 | | - advance_right = ADVANCE; |
|---|
| 5668 | | - } |
|---|
| 5669 | | - } |
|---|
| 5670 | | - } else if (left_level < right_level) { |
|---|
| 5671 | | - advance_right = ADVANCE; |
|---|
| 5672 | | - } else { |
|---|
| 5673 | | - advance_left = ADVANCE; |
|---|
| 5674 | | - } |
|---|
| 5675 | | - } |
|---|
| 5676 | | - |
|---|
| 5677 | | -out: |
|---|
| 5678 | | - btrfs_free_path(left_path); |
|---|
| 5679 | | - btrfs_free_path(right_path); |
|---|
| 5680 | | - kvfree(tmp_buf); |
|---|
| 5681 | 5324 | return ret; |
|---|
| 5682 | 5325 | } |
|---|
| 5683 | 5326 | |
|---|
| .. | .. |
|---|
| 5698 | 5341 | int slot; |
|---|
| 5699 | 5342 | struct extent_buffer *c; |
|---|
| 5700 | 5343 | |
|---|
| 5701 | | - WARN_ON(!path->keep_locks); |
|---|
| 5344 | + WARN_ON(!path->keep_locks && !path->skip_locking); |
|---|
| 5702 | 5345 | while (level < BTRFS_MAX_LEVEL) { |
|---|
| 5703 | 5346 | if (!path->nodes[level]) |
|---|
| 5704 | 5347 | return 1; |
|---|
| .. | .. |
|---|
| 5714 | 5357 | !path->nodes[level + 1]) |
|---|
| 5715 | 5358 | return 1; |
|---|
| 5716 | 5359 | |
|---|
| 5717 | | - if (path->locks[level + 1]) { |
|---|
| 5360 | + if (path->locks[level + 1] || path->skip_locking) { |
|---|
| 5718 | 5361 | level++; |
|---|
| 5719 | 5362 | continue; |
|---|
| 5720 | 5363 | } |
|---|
| .. | .. |
|---|
| 5886 | 5529 | } |
|---|
| 5887 | 5530 | if (!ret) { |
|---|
| 5888 | 5531 | btrfs_set_path_blocking(path); |
|---|
| 5889 | | - btrfs_tree_read_lock(next); |
|---|
| 5890 | | - btrfs_clear_path_blocking(path, next, |
|---|
| 5891 | | - BTRFS_READ_LOCK); |
|---|
| 5532 | + __btrfs_tree_read_lock(next, |
|---|
| 5533 | + BTRFS_NESTING_RIGHT, |
|---|
| 5534 | + path->recurse); |
|---|
| 5892 | 5535 | } |
|---|
| 5893 | 5536 | next_rw_lock = BTRFS_READ_LOCK; |
|---|
| 5894 | 5537 | } |
|---|
| .. | .. |
|---|
| 5923 | 5566 | ret = btrfs_try_tree_read_lock(next); |
|---|
| 5924 | 5567 | if (!ret) { |
|---|
| 5925 | 5568 | btrfs_set_path_blocking(path); |
|---|
| 5926 | | - btrfs_tree_read_lock(next); |
|---|
| 5927 | | - btrfs_clear_path_blocking(path, next, |
|---|
| 5928 | | - BTRFS_READ_LOCK); |
|---|
| 5569 | + __btrfs_tree_read_lock(next, |
|---|
| 5570 | + BTRFS_NESTING_RIGHT, |
|---|
| 5571 | + path->recurse); |
|---|
| 5929 | 5572 | } |
|---|
| 5930 | 5573 | next_rw_lock = BTRFS_READ_LOCK; |
|---|
| 5931 | 5574 | } |
|---|