| @@ -467,6 +467,15 @@ static inline int tree_mod_dont_log(struct btrfs_fs_info *fs_info, · 466 unmodified lines |
| 467 | return 0; | 467 | return 0; |
| 468 | } | 468 | } |
| 469 | | 469 | |
| | 470 | /* |
| | 471 | * This allocates memory and gets a tree modification sequence number when |
| | 472 | * needed. |
| | 473 | * |
| | 474 | * Returns 0 when no sequence number is needed, < 0 on error. |
| | 475 | * Returns 1 when a sequence number was added. In this case, |
| | 476 | * fs_info->tree_mod_seq_lock was acquired and must be released by the caller |
| | 477 | * after inserting into the rb tree. |
| | 478 | */ |
| 470 | static inline int tree_mod_alloc(struct btrfs_fs_info *fs_info, gfp_t flags, | 479 | static inline int tree_mod_alloc(struct btrfs_fs_info *fs_info, gfp_t flags, |
| 471 | struct tree_mod_elem **tm_ret) | 480 | struct tree_mod_elem **tm_ret) |
| 472 | { | 481 | { |
| @@ -491,11 +500,11 @@ static inline int tree_mod_alloc(struct btrfs_fs_info *fs_info, gfp_t flags, · 18 unmodified lines |
| 491 | */ | 500 | */ |
| 492 | kfree(tm); | 501 | kfree(tm); |
| 493 | seq = 0; | 502 | seq = 0; |
| | 503 | spin_unlock(&fs_info->tree_mod_seq_lock); |
| 494 | } else { | 504 | } else { |
| 495 | __get_tree_mod_seq(fs_info, &tm->elem); | 505 | __get_tree_mod_seq(fs_info, &tm->elem); |
| 496 | seq = tm->elem.seq; | 506 | seq = tm->elem.seq; |
| 497 | } | 507 | } |
| 498 | spin_unlock(&fs_info->tree_mod_seq_lock); | | |
| 499 | | 508 | |
| 500 | return seq; | 509 | return seq; |
| 501 | } | 510 | } |
| @@ -521,7 +530,9 @@ tree_mod_log_insert_key_mask(struct btrfs_fs_info *fs_info, · 19 unmodified lines |
| 521 | tm->slot = slot; | 530 | tm->slot = slot; |
| 522 | tm->generation = btrfs_node_ptr_generation(eb, slot); | 531 | tm->generation = btrfs_node_ptr_generation(eb, slot); |
| 523 | | 532 | |
| 524 | return __tree_mod_log_insert(fs_info, tm); | 533 | ret = __tree_mod_log_insert(fs_info, tm); |
| | 534 | spin_unlock(&fs_info->tree_mod_seq_lock); |
| | 535 | return ret; |
| 525 | } | 536 | } |
| 526 | | 537 | |
| 527 | static noinline int | 538 | static noinline int |
| @@ -559,7 +570,9 @@ tree_mod_log_insert_move(struct btrfs_fs_info *fs_info, · 31 unmodified lines |
| 559 | tm->move.nr_items = nr_items; | 570 | tm->move.nr_items = nr_items; |
| 560 | tm->op = MOD_LOG_MOVE_KEYS; | 571 | tm->op = MOD_LOG_MOVE_KEYS; |
| 561 | | 572 | |
| 562 | return __tree_mod_log_insert(fs_info, tm); | 573 | ret = __tree_mod_log_insert(fs_info, tm); |
| | 574 | spin_unlock(&fs_info->tree_mod_seq_lock); |
| | 575 | return ret; |
| 563 | } | 576 | } |
| 564 | | 577 | |
| 565 | static noinline int | 578 | static noinline int |
| @@ -580,7 +593,9 @@ tree_mod_log_insert_root(struct btrfs_fs_info *fs_info, · 14 unmodified lines |
| 580 | tm->generation = btrfs_header_generation(old_root); | 593 | tm->generation = btrfs_header_generation(old_root); |
| 581 | tm->op = MOD_LOG_ROOT_REPLACE; | 594 | tm->op = MOD_LOG_ROOT_REPLACE; |
| 582 | | 595 | |
| 583 | return __tree_mod_log_insert(fs_info, tm); | 596 | ret = __tree_mod_log_insert(fs_info, tm); |
| | 597 | spin_unlock(&fs_info->tree_mod_seq_lock); |
| | 598 | return ret; |
| 584 | } | 599 | } |
| 585 | | 600 | |
| 586 | static struct tree_mod_elem * | 601 | static struct tree_mod_elem * |
| @@ -1023,6 +1038,10 @@ __tree_mod_log_oldest_root(struct btrfs_fs_info *fs_info, · 436 unmodified lines |
| 1023 | looped = 1; | 1038 | looped = 1; |
| 1024 | } | 1039 | } |
| 1025 | | 1040 | |
| | 1041 | /* if there's no old root to return, return what we found instead */ |
| | 1042 | if (!found) |
| | 1043 | found = tm; |
| | 1044 | |
| 1026 | return found; | 1045 | return found; |
| 1027 | } | 1046 | } |
| 1028 | | 1047 | |
| @@ -1143,22 +1162,36 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb, · 114 unmodified lines |
| 1143 | return eb_rewin; | 1162 | return eb_rewin; |
| 1144 | } | 1163 | } |
| 1145 | | 1164 | |
| | 1165 | /* |
| | 1166 | * get_old_root() rewinds the state of @root's root node to the given @time_seq |
| | 1167 | * value. If there are no changes, the current root->root_node is returned. If |
| | 1168 | * anything changed in between, there's a fresh buffer allocated on which the |
| | 1169 | * rewind operations are done. In any case, the returned buffer is read locked. |
| | 1170 | * Returns NULL on error (with no locks held). |
| | 1171 | */ |
| 1146 | static inline struct extent_buffer * | 1172 | static inline struct extent_buffer * |
| 1147 | get_old_root(struct btrfs_root *root, u64 time_seq) | 1173 | get_old_root(struct btrfs_root *root, u64 time_seq) |
| 1148 | { | 1174 | { |
| 1149 | struct tree_mod_elem *tm; | 1175 | struct tree_mod_elem *tm; |
| 1150 | struct extent_buffer *eb; | 1176 | struct extent_buffer *eb; |
| 1151 | struct tree_mod_root *old_root; | 1177 | struct tree_mod_root *old_root = NULL; |
| 1152 | u64 old_generation; | 1178 | u64 old_generation; |
| | 1179 | u64 logical; |
| 1153 | | 1180 | |
| | 1181 | eb = btrfs_read_lock_root_node(root); |
| 1154 | tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq); | 1182 | tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq); |
| 1155 | if (!tm) | 1183 | if (!tm) |
| 1156 | return root->node; | 1184 | return root->node; |
| 1157 | | 1185 | |
| 1158 | old_root = &tm->old_root; | 1186 | if (tm->op == MOD_LOG_ROOT_REPLACE) { |
| 1159 | old_generation = tm->generation; | 1187 | old_root = &tm->old_root; |
| | 1188 | old_generation = tm->generation; |
| | 1189 | logical = old_root->logical; |
| | 1190 | } else { |
| | 1191 | logical = root->node->start; |
| | 1192 | } |
| 1160 | | 1193 | |
| 1161 | tm = tree_mod_log_search(root->fs_info, old_root->logical, time_seq); | 1194 | tm = tree_mod_log_search(root->fs_info, logical, time_seq); |
| 1162 | /* | 1195 | /* |
| 1163 | * there was an item in the log when __tree_mod_log_oldest_root | 1196 | * there was an item in the log when __tree_mod_log_oldest_root |
| 1164 | * returned. this one must not go away, because the time_seq passed to | 1197 | * returned. this one must not go away, because the time_seq passed to |
| @@ -1166,22 +1199,25 @@ get_old_root(struct btrfs_root *root, u64 time_seq) · 1 unmodified line |
| 1166 | */ | 1199 | */ |
| 1167 | BUG_ON(!tm); | 1200 | BUG_ON(!tm); |
| 1168 | | 1201 | |
| 1169 | if (old_root->logical == root->node->start) { | 1202 | if (old_root) |
| 1170 | /* there are logged operations for the current root */ | | |
| 1171 | eb = btrfs_clone_extent_buffer(root->node); | | |
| 1172 | } else { | | |
| 1173 | /* there's a root replace operation for the current root */ | | |
| 1174 | eb = alloc_dummy_extent_buffer(tm->index << PAGE_CACHE_SHIFT, | 1203 | eb = alloc_dummy_extent_buffer(tm->index << PAGE_CACHE_SHIFT, |
| 1175 | root->nodesize); | 1204 | root->nodesize); |
| | 1205 | else |
| | 1206 | eb = btrfs_clone_extent_buffer(root->node); |
| | 1207 | btrfs_tree_read_unlock(root->node); |
| | 1208 | free_extent_buffer(root->node); |
| | 1209 | if (!eb) |
| | 1210 | return NULL; |
| | 1211 | btrfs_tree_read_lock(eb); |
| | 1212 | if (old_root) { |
| 1176 | btrfs_set_header_bytenr(eb, eb->start); | 1213 | btrfs_set_header_bytenr(eb, eb->start); |
| 1177 | btrfs_set_header_backref_rev(eb, BTRFS_MIXED_BACKREF_REV); | 1214 | btrfs_set_header_backref_rev(eb, BTRFS_MIXED_BACKREF_REV); |
| 1178 | btrfs_set_header_owner(eb, root->root_key.objectid); | 1215 | btrfs_set_header_owner(eb, root->root_key.objectid); |
| | 1216 | btrfs_set_header_level(eb, old_root->level); |
| | 1217 | btrfs_set_header_generation(eb, old_generation); |
| 1179 | } | 1218 | } |
| 1180 | if (!eb) | | |
| 1181 | return NULL; | | |
| 1182 | btrfs_set_header_level(eb, old_root->level); | | |
| 1183 | btrfs_set_header_generation(eb, old_generation); | | |
| 1184 | __tree_mod_log_rewind(eb, time_seq, tm); | 1219 | __tree_mod_log_rewind(eb, time_seq, tm); |
| | 1220 | extent_buffer_get(eb); |
| 1185 | | 1221 | |
| 1186 | return eb; | 1222 | return eb; |
| 1187 | } | 1223 | } |
| @@ -1650,8 +1686,6 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, · 462 unmodified lines |
| 1650 | BTRFS_NODEPTRS_PER_BLOCK(root) / 4) | 1686 | BTRFS_NODEPTRS_PER_BLOCK(root) / 4) |
| 1651 | return 0; | 1687 | return 0; |
| 1652 | | 1688 | |
| 1653 | btrfs_header_nritems(mid); | | |
| 1654 | | | |
| 1655 | left = read_node_slot(root, parent, pslot - 1); | 1689 | left = read_node_slot(root, parent, pslot - 1); |
| 1656 | if (left) { | 1690 | if (left) { |
| 1657 | btrfs_tree_lock(left); | 1691 | btrfs_tree_lock(left); |
| @@ -1681,7 +1715,6 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, · 23 unmodified lines |
| 1681 | wret = push_node_left(trans, root, left, mid, 1); | 1715 | wret = push_node_left(trans, root, left, mid, 1); |
| 1682 | if (wret < 0) | 1716 | if (wret < 0) |
| 1683 | ret = wret; | 1717 | ret = wret; |
| 1684 | btrfs_header_nritems(mid); | | |
| 1685 | } | 1718 | } |
| 1686 | | 1719 | |
| 1687 | /* | 1720 | /* |
| @@ -2615,9 +2648,7 @@ int btrfs_search_old_slot(struct btrfs_root *root, struct btrfs_key *key, · 927 unmodified lines |
| 2615 | | 2648 | |
| 2616 | again: | 2649 | again: |
| 2617 | b = get_old_root(root, time_seq); | 2650 | b = get_old_root(root, time_seq); |
| 2618 | extent_buffer_get(b); | | |
| 2619 | level = btrfs_header_level(b); | 2651 | level = btrfs_header_level(b); |
| 2620 | btrfs_tree_read_lock(b); | | |
| 2621 | p->locks[level] = BTRFS_READ_LOCK; | 2652 | p->locks[level] = BTRFS_READ_LOCK; |
| 2622 | | 2653 | |
| 2623 | while (b) { | 2654 | while (b) { |
| @@ -5000,6 +5031,12 @@ next: · 2376 unmodified lines |
| 5000 | * returns < 0 on io errors. | 5031 | * returns < 0 on io errors. |
| 5001 | */ | 5032 | */ |
| 5002 | int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path) | 5033 | int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path) |
| | 5034 | { |
| | 5035 | return btrfs_next_old_leaf(root, path, 0); |
| | 5036 | } |
| | 5037 | |
| | 5038 | int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path, |
| | 5039 | u64 time_seq) |
| 5003 | { | 5040 | { |
| 5004 | int slot; | 5041 | int slot; |
| 5005 | int level; | 5042 | int level; |
| @@ -5025,7 +5062,10 @@ again: · 19 unmodified lines |
| 5025 | path->keep_locks = 1; | 5062 | path->keep_locks = 1; |
| 5026 | path->leave_spinning = 1; | 5063 | path->leave_spinning = 1; |
| 5027 | | 5064 | |
| 5028 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 5065 | if (time_seq) |
| | 5066 | ret = btrfs_search_old_slot(root, &key, path, time_seq); |
| | 5067 | else |
| | 5068 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
| 5029 | path->keep_locks = 0; | 5069 | path->keep_locks = 0; |
| 5030 | | 5070 | |
| 5031 | if (ret < 0) | 5071 | if (ret < 0) |