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.c69
1 files changed, 48 insertions, 21 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 362879da4f0d..0abed1a0caa7 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -1866,7 +1866,6 @@ static void root_sub_used(struct btrfs_root *root, u32 size)
1866 1866
1867/* given a node and slot number, this reads the blocks it points to. The 1867/* given a node and slot number, this reads the blocks it points to. The
1868 * extent buffer is returned with a reference taken (but unlocked). 1868 * extent buffer is returned with a reference taken (but unlocked).
1869 * NULL is returned on error.
1870 */ 1869 */
1871static noinline struct extent_buffer *read_node_slot(struct btrfs_root *root, 1870static noinline struct extent_buffer *read_node_slot(struct btrfs_root *root,
1872 struct extent_buffer *parent, int slot) 1871 struct extent_buffer *parent, int slot)
@@ -1874,19 +1873,16 @@ static noinline struct extent_buffer *read_node_slot(struct btrfs_root *root,
1874 int level = btrfs_header_level(parent); 1873 int level = btrfs_header_level(parent);
1875 struct extent_buffer *eb; 1874 struct extent_buffer *eb;
1876 1875
1877 if (slot < 0) 1876 if (slot < 0 || slot >= btrfs_header_nritems(parent))
1878 return NULL; 1877 return ERR_PTR(-ENOENT);
1879 if (slot >= btrfs_header_nritems(parent))
1880 return NULL;
1881 1878
1882 BUG_ON(level == 0); 1879 BUG_ON(level == 0);
1883 1880
1884 eb = read_tree_block(root, btrfs_node_blockptr(parent, slot), 1881 eb = read_tree_block(root, btrfs_node_blockptr(parent, slot),
1885 btrfs_node_ptr_generation(parent, slot)); 1882 btrfs_node_ptr_generation(parent, slot));
1886 if (IS_ERR(eb) || !extent_buffer_uptodate(eb)) { 1883 if (!IS_ERR(eb) && !extent_buffer_uptodate(eb)) {
1887 if (!IS_ERR(eb)) 1884 free_extent_buffer(eb);
1888 free_extent_buffer(eb); 1885 eb = ERR_PTR(-EIO);
1889 eb = NULL;
1890 } 1886 }
1891 1887
1892 return eb; 1888 return eb;
@@ -1939,8 +1935,8 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
1939 1935
1940 /* promote the child to a root */ 1936 /* promote the child to a root */
1941 child = read_node_slot(root, mid, 0); 1937 child = read_node_slot(root, mid, 0);
1942 if (!child) { 1938 if (IS_ERR(child)) {
1943 ret = -EROFS; 1939 ret = PTR_ERR(child);
1944 btrfs_handle_fs_error(root->fs_info, ret, NULL); 1940 btrfs_handle_fs_error(root->fs_info, ret, NULL);
1945 goto enospc; 1941 goto enospc;
1946 } 1942 }
@@ -1978,6 +1974,9 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
1978 return 0; 1974 return 0;
1979 1975
1980 left = read_node_slot(root, parent, pslot - 1); 1976 left = read_node_slot(root, parent, pslot - 1);
1977 if (IS_ERR(left))
1978 left = NULL;
1979
1981 if (left) { 1980 if (left) {
1982 btrfs_tree_lock(left); 1981 btrfs_tree_lock(left);
1983 btrfs_set_lock_blocking(left); 1982 btrfs_set_lock_blocking(left);
@@ -1988,7 +1987,11 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
1988 goto enospc; 1987 goto enospc;
1989 } 1988 }
1990 } 1989 }
1990
1991 right = read_node_slot(root, parent, pslot + 1); 1991 right = read_node_slot(root, parent, pslot + 1);
1992 if (IS_ERR(right))
1993 right = NULL;
1994
1992 if (right) { 1995 if (right) {
1993 btrfs_tree_lock(right); 1996 btrfs_tree_lock(right);
1994 btrfs_set_lock_blocking(right); 1997 btrfs_set_lock_blocking(right);
@@ -2143,6 +2146,8 @@ static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans,
2143 return 1; 2146 return 1;
2144 2147
2145 left = read_node_slot(root, parent, pslot - 1); 2148 left = read_node_slot(root, parent, pslot - 1);
2149 if (IS_ERR(left))
2150 left = NULL;
2146 2151
2147 /* first, try to make some room in the middle buffer */ 2152 /* first, try to make some room in the middle buffer */
2148 if (left) { 2153 if (left) {
@@ -2193,6 +2198,8 @@ static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans,
2193 free_extent_buffer(left); 2198 free_extent_buffer(left);
2194 } 2199 }
2195 right = read_node_slot(root, parent, pslot + 1); 2200 right = read_node_slot(root, parent, pslot + 1);
2201 if (IS_ERR(right))
2202 right = NULL;
2196 2203
2197 /* 2204 /*
2198 * then try to empty the right most buffer into the middle 2205 * then try to empty the right most buffer into the middle
@@ -3781,7 +3788,11 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
3781 btrfs_assert_tree_locked(path->nodes[1]); 3788 btrfs_assert_tree_locked(path->nodes[1]);
3782 3789
3783 right = read_node_slot(root, upper, slot + 1); 3790 right = read_node_slot(root, upper, slot + 1);
3784 if (right == NULL) 3791 /*
3792 * slot + 1 is not valid or we fail to read the right node,
3793 * no big deal, just return.
3794 */
3795 if (IS_ERR(right))
3785 return 1; 3796 return 1;
3786 3797
3787 btrfs_tree_lock(right); 3798 btrfs_tree_lock(right);
@@ -4011,7 +4022,11 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
4011 btrfs_assert_tree_locked(path->nodes[1]); 4022 btrfs_assert_tree_locked(path->nodes[1]);
4012 4023
4013 left = read_node_slot(root, path->nodes[1], slot - 1); 4024 left = read_node_slot(root, path->nodes[1], slot - 1);
4014 if (left == NULL) 4025 /*
4026 * slot - 1 is not valid or we fail to read the left node,
4027 * no big deal, just return.
4028 */
4029 if (IS_ERR(left))
4015 return 1; 4030 return 1;
4016 4031
4017 btrfs_tree_lock(left); 4032 btrfs_tree_lock(left);
@@ -5218,7 +5233,10 @@ find_next_key:
5218 } 5233 }
5219 btrfs_set_path_blocking(path); 5234 btrfs_set_path_blocking(path);
5220 cur = read_node_slot(root, cur, slot); 5235 cur = read_node_slot(root, cur, slot);
5221 BUG_ON(!cur); /* -ENOMEM */ 5236 if (IS_ERR(cur)) {
5237 ret = PTR_ERR(cur);
5238 goto out;
5239 }
5222 5240
5223 btrfs_tree_read_lock(cur); 5241 btrfs_tree_read_lock(cur);
5224 5242
@@ -5237,15 +5255,21 @@ out:
5237 return ret; 5255 return ret;
5238} 5256}
5239 5257
5240static void tree_move_down(struct btrfs_root *root, 5258static int tree_move_down(struct btrfs_root *root,
5241 struct btrfs_path *path, 5259 struct btrfs_path *path,
5242 int *level, int root_level) 5260 int *level, int root_level)
5243{ 5261{
5262 struct extent_buffer *eb;
5263
5244 BUG_ON(*level == 0); 5264 BUG_ON(*level == 0);
5245 path->nodes[*level - 1] = read_node_slot(root, path->nodes[*level], 5265 eb = read_node_slot(root, path->nodes[*level], path->slots[*level]);
5246 path->slots[*level]); 5266 if (IS_ERR(eb))
5267 return PTR_ERR(eb);
5268
5269 path->nodes[*level - 1] = eb;
5247 path->slots[*level - 1] = 0; 5270 path->slots[*level - 1] = 0;
5248 (*level)--; 5271 (*level)--;
5272 return 0;
5249} 5273}
5250 5274
5251static int tree_move_next_or_upnext(struct btrfs_root *root, 5275static int tree_move_next_or_upnext(struct btrfs_root *root,
@@ -5290,8 +5314,7 @@ static int tree_advance(struct btrfs_root *root,
5290 if (*level == 0 || !allow_down) { 5314 if (*level == 0 || !allow_down) {
5291 ret = tree_move_next_or_upnext(root, path, level, root_level); 5315 ret = tree_move_next_or_upnext(root, path, level, root_level);
5292 } else { 5316 } else {
5293 tree_move_down(root, path, level, root_level); 5317 ret = tree_move_down(root, path, level, root_level);
5294 ret = 0;
5295 } 5318 }
5296 if (ret >= 0) { 5319 if (ret >= 0) {
5297 if (*level == 0) 5320 if (*level == 0)
@@ -5465,8 +5488,10 @@ int btrfs_compare_trees(struct btrfs_root *left_root,
5465 left_root_level, 5488 left_root_level,
5466 advance_left != ADVANCE_ONLY_NEXT, 5489 advance_left != ADVANCE_ONLY_NEXT,
5467 &left_key); 5490 &left_key);
5468 if (ret < 0) 5491 if (ret == -1)
5469 left_end_reached = ADVANCE; 5492 left_end_reached = ADVANCE;
5493 else if (ret < 0)
5494 goto out;
5470 advance_left = 0; 5495 advance_left = 0;
5471 } 5496 }
5472 if (advance_right && !right_end_reached) { 5497 if (advance_right && !right_end_reached) {
@@ -5474,8 +5499,10 @@ int btrfs_compare_trees(struct btrfs_root *left_root,
5474 right_root_level, 5499 right_root_level,
5475 advance_right != ADVANCE_ONLY_NEXT, 5500 advance_right != ADVANCE_ONLY_NEXT,
5476 &right_key); 5501 &right_key);
5477 if (ret < 0) 5502 if (ret == -1)
5478 right_end_reached = ADVANCE; 5503 right_end_reached = ADVANCE;
5504 else if (ret < 0)
5505 goto out;
5479 advance_right = 0; 5506 advance_right = 0;
5480 } 5507 }
5481 5508