aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ctree.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r--fs/btrfs/ctree.c60
1 files changed, 35 insertions, 25 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 15cbc2bf4ff0..8206b3900587 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -1024,11 +1024,18 @@ __tree_mod_log_oldest_root(struct btrfs_fs_info *fs_info,
1024 if (!looped && !tm) 1024 if (!looped && !tm)
1025 return 0; 1025 return 0;
1026 /* 1026 /*
1027 * we must have key remove operations in the log before the 1027 * if there are no tree operation for the oldest root, we simply
1028 * replace operation. 1028 * return it. this should only happen if that (old) root is at
1029 * level 0.
1029 */ 1030 */
1030 BUG_ON(!tm); 1031 if (!tm)
1032 break;
1031 1033
1034 /*
1035 * if there's an operation that's not a root replacement, we
1036 * found the oldest version of our root. normally, we'll find a
1037 * MOD_LOG_KEY_REMOVE_WHILE_FREEING operation here.
1038 */
1032 if (tm->op != MOD_LOG_ROOT_REPLACE) 1039 if (tm->op != MOD_LOG_ROOT_REPLACE)
1033 break; 1040 break;
1034 1041
@@ -1087,11 +1094,7 @@ __tree_mod_log_rewind(struct extent_buffer *eb, u64 time_seq,
1087 tm->generation); 1094 tm->generation);
1088 break; 1095 break;
1089 case MOD_LOG_KEY_ADD: 1096 case MOD_LOG_KEY_ADD:
1090 if (tm->slot != n - 1) { 1097 /* if a move operation is needed it's in the log */
1091 o_dst = btrfs_node_key_ptr_offset(tm->slot);
1092 o_src = btrfs_node_key_ptr_offset(tm->slot + 1);
1093 memmove_extent_buffer(eb, o_dst, o_src, p_size);
1094 }
1095 n--; 1098 n--;
1096 break; 1099 break;
1097 case MOD_LOG_MOVE_KEYS: 1100 case MOD_LOG_MOVE_KEYS:
@@ -1192,16 +1195,8 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
1192 } 1195 }
1193 1196
1194 tm = tree_mod_log_search(root->fs_info, logical, time_seq); 1197 tm = tree_mod_log_search(root->fs_info, logical, time_seq);
1195 /*
1196 * there was an item in the log when __tree_mod_log_oldest_root
1197 * returned. this one must not go away, because the time_seq passed to
1198 * us must be blocking its removal.
1199 */
1200 BUG_ON(!tm);
1201
1202 if (old_root) 1198 if (old_root)
1203 eb = alloc_dummy_extent_buffer(tm->index << PAGE_CACHE_SHIFT, 1199 eb = alloc_dummy_extent_buffer(logical, root->nodesize);
1204 root->nodesize);
1205 else 1200 else
1206 eb = btrfs_clone_extent_buffer(root->node); 1201 eb = btrfs_clone_extent_buffer(root->node);
1207 btrfs_tree_read_unlock(root->node); 1202 btrfs_tree_read_unlock(root->node);
@@ -1216,7 +1211,10 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
1216 btrfs_set_header_level(eb, old_root->level); 1211 btrfs_set_header_level(eb, old_root->level);
1217 btrfs_set_header_generation(eb, old_generation); 1212 btrfs_set_header_generation(eb, old_generation);
1218 } 1213 }
1219 __tree_mod_log_rewind(eb, time_seq, tm); 1214 if (tm)
1215 __tree_mod_log_rewind(eb, time_seq, tm);
1216 else
1217 WARN_ON(btrfs_header_level(eb) != 0);
1220 extent_buffer_get(eb); 1218 extent_buffer_get(eb);
1221 1219
1222 return eb; 1220 return eb;
@@ -2995,7 +2993,7 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans,
2995static void insert_ptr(struct btrfs_trans_handle *trans, 2993static void insert_ptr(struct btrfs_trans_handle *trans,
2996 struct btrfs_root *root, struct btrfs_path *path, 2994 struct btrfs_root *root, struct btrfs_path *path,
2997 struct btrfs_disk_key *key, u64 bytenr, 2995 struct btrfs_disk_key *key, u64 bytenr,
2998 int slot, int level, int tree_mod_log) 2996 int slot, int level)
2999{ 2997{
3000 struct extent_buffer *lower; 2998 struct extent_buffer *lower;
3001 int nritems; 2999 int nritems;
@@ -3008,7 +3006,7 @@ static void insert_ptr(struct btrfs_trans_handle *trans,
3008 BUG_ON(slot > nritems); 3006 BUG_ON(slot > nritems);
3009 BUG_ON(nritems == BTRFS_NODEPTRS_PER_BLOCK(root)); 3007 BUG_ON(nritems == BTRFS_NODEPTRS_PER_BLOCK(root));
3010 if (slot != nritems) { 3008 if (slot != nritems) {
3011 if (tree_mod_log && level) 3009 if (level)
3012 tree_mod_log_eb_move(root->fs_info, lower, slot + 1, 3010 tree_mod_log_eb_move(root->fs_info, lower, slot + 1,
3013 slot, nritems - slot); 3011 slot, nritems - slot);
3014 memmove_extent_buffer(lower, 3012 memmove_extent_buffer(lower,
@@ -3016,7 +3014,7 @@ static void insert_ptr(struct btrfs_trans_handle *trans,
3016 btrfs_node_key_ptr_offset(slot), 3014 btrfs_node_key_ptr_offset(slot),
3017 (nritems - slot) * sizeof(struct btrfs_key_ptr)); 3015 (nritems - slot) * sizeof(struct btrfs_key_ptr));
3018 } 3016 }
3019 if (tree_mod_log && level) { 3017 if (level) {
3020 ret = tree_mod_log_insert_key(root->fs_info, lower, slot, 3018 ret = tree_mod_log_insert_key(root->fs_info, lower, slot,
3021 MOD_LOG_KEY_ADD); 3019 MOD_LOG_KEY_ADD);
3022 BUG_ON(ret < 0); 3020 BUG_ON(ret < 0);
@@ -3104,7 +3102,7 @@ static noinline int split_node(struct btrfs_trans_handle *trans,
3104 btrfs_mark_buffer_dirty(split); 3102 btrfs_mark_buffer_dirty(split);
3105 3103
3106 insert_ptr(trans, root, path, &disk_key, split->start, 3104 insert_ptr(trans, root, path, &disk_key, split->start,
3107 path->slots[level + 1] + 1, level + 1, 1); 3105 path->slots[level + 1] + 1, level + 1);
3108 3106
3109 if (path->slots[level] >= mid) { 3107 if (path->slots[level] >= mid) {
3110 path->slots[level] -= mid; 3108 path->slots[level] -= mid;
@@ -3641,7 +3639,7 @@ static noinline void copy_for_split(struct btrfs_trans_handle *trans,
3641 btrfs_set_header_nritems(l, mid); 3639 btrfs_set_header_nritems(l, mid);
3642 btrfs_item_key(right, &disk_key, 0); 3640 btrfs_item_key(right, &disk_key, 0);
3643 insert_ptr(trans, root, path, &disk_key, right->start, 3641 insert_ptr(trans, root, path, &disk_key, right->start,
3644 path->slots[1] + 1, 1, 0); 3642 path->slots[1] + 1, 1);
3645 3643
3646 btrfs_mark_buffer_dirty(right); 3644 btrfs_mark_buffer_dirty(right);
3647 btrfs_mark_buffer_dirty(l); 3645 btrfs_mark_buffer_dirty(l);
@@ -3848,7 +3846,7 @@ again:
3848 if (mid <= slot) { 3846 if (mid <= slot) {
3849 btrfs_set_header_nritems(right, 0); 3847 btrfs_set_header_nritems(right, 0);
3850 insert_ptr(trans, root, path, &disk_key, right->start, 3848 insert_ptr(trans, root, path, &disk_key, right->start,
3851 path->slots[1] + 1, 1, 0); 3849 path->slots[1] + 1, 1);
3852 btrfs_tree_unlock(path->nodes[0]); 3850 btrfs_tree_unlock(path->nodes[0]);
3853 free_extent_buffer(path->nodes[0]); 3851 free_extent_buffer(path->nodes[0]);
3854 path->nodes[0] = right; 3852 path->nodes[0] = right;
@@ -3857,7 +3855,7 @@ again:
3857 } else { 3855 } else {
3858 btrfs_set_header_nritems(right, 0); 3856 btrfs_set_header_nritems(right, 0);
3859 insert_ptr(trans, root, path, &disk_key, right->start, 3857 insert_ptr(trans, root, path, &disk_key, right->start,
3860 path->slots[1], 1, 0); 3858 path->slots[1], 1);
3861 btrfs_tree_unlock(path->nodes[0]); 3859 btrfs_tree_unlock(path->nodes[0]);
3862 free_extent_buffer(path->nodes[0]); 3860 free_extent_buffer(path->nodes[0]);
3863 path->nodes[0] = right; 3861 path->nodes[0] = right;
@@ -5121,6 +5119,18 @@ again:
5121 5119
5122 if (!path->skip_locking) { 5120 if (!path->skip_locking) {
5123 ret = btrfs_try_tree_read_lock(next); 5121 ret = btrfs_try_tree_read_lock(next);
5122 if (!ret && time_seq) {
5123 /*
5124 * If we don't get the lock, we may be racing
5125 * with push_leaf_left, holding that lock while
5126 * itself waiting for the leaf we've currently
5127 * locked. To solve this situation, we give up
5128 * on our lock and cycle.
5129 */
5130 btrfs_release_path(path);
5131 cond_resched();
5132 goto again;
5133 }
5124 if (!ret) { 5134 if (!ret) {
5125 btrfs_set_path_blocking(path); 5135 btrfs_set_path_blocking(path);
5126 btrfs_tree_read_lock(next); 5136 btrfs_tree_read_lock(next);