Commit 8c594ea8 authored by Chris Mason's avatar Chris Mason

Btrfs: use the right node in reada_for_balance

reada_for_balance was using the wrong index into the path node array,
so it wasn't reading the right blocks.  We never directly used the
results of the read done by this function because the btree search is
started over at the end.

This fixes reada_for_balance to reada in the correct node and to
avoid searching past the last slot in the node.  It also makes sure to
hold the parent lock while we are finding the nodes to read.
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 11c8349b
...@@ -1325,12 +1325,12 @@ static noinline int reada_for_balance(struct btrfs_root *root, ...@@ -1325,12 +1325,12 @@ static noinline int reada_for_balance(struct btrfs_root *root,
int ret = 0; int ret = 0;
int blocksize; int blocksize;
parent = path->nodes[level - 1]; parent = path->nodes[level + 1];
if (!parent) if (!parent)
return 0; return 0;
nritems = btrfs_header_nritems(parent); nritems = btrfs_header_nritems(parent);
slot = path->slots[level]; slot = path->slots[level + 1];
blocksize = btrfs_level_size(root, level); blocksize = btrfs_level_size(root, level);
if (slot > 0) { if (slot > 0) {
...@@ -1341,7 +1341,7 @@ static noinline int reada_for_balance(struct btrfs_root *root, ...@@ -1341,7 +1341,7 @@ static noinline int reada_for_balance(struct btrfs_root *root,
block1 = 0; block1 = 0;
free_extent_buffer(eb); free_extent_buffer(eb);
} }
if (slot < nritems) { if (slot + 1 < nritems) {
block2 = btrfs_node_blockptr(parent, slot + 1); block2 = btrfs_node_blockptr(parent, slot + 1);
gen = btrfs_node_ptr_generation(parent, slot + 1); gen = btrfs_node_ptr_generation(parent, slot + 1);
eb = btrfs_find_tree_block(root, block2, blocksize); eb = btrfs_find_tree_block(root, block2, blocksize);
...@@ -1351,7 +1351,11 @@ static noinline int reada_for_balance(struct btrfs_root *root, ...@@ -1351,7 +1351,11 @@ static noinline int reada_for_balance(struct btrfs_root *root,
} }
if (block1 || block2) { if (block1 || block2) {
ret = -EAGAIN; ret = -EAGAIN;
/* release the whole path */
btrfs_release_path(root, path); btrfs_release_path(root, path);
/* read the blocks */
if (block1) if (block1)
readahead_tree_block(root, block1, blocksize, 0); readahead_tree_block(root, block1, blocksize, 0);
if (block2) if (block2)
...@@ -1361,7 +1365,7 @@ static noinline int reada_for_balance(struct btrfs_root *root, ...@@ -1361,7 +1365,7 @@ static noinline int reada_for_balance(struct btrfs_root *root,
eb = read_tree_block(root, block1, blocksize, 0); eb = read_tree_block(root, block1, blocksize, 0);
free_extent_buffer(eb); free_extent_buffer(eb);
} }
if (block1) { if (block2) {
eb = read_tree_block(root, block2, blocksize, 0); eb = read_tree_block(root, block2, blocksize, 0);
free_extent_buffer(eb); free_extent_buffer(eb);
} }
...@@ -1481,12 +1485,15 @@ read_block_for_search(struct btrfs_trans_handle *trans, ...@@ -1481,12 +1485,15 @@ read_block_for_search(struct btrfs_trans_handle *trans,
* of the btree by dropping locks before * of the btree by dropping locks before
* we read. * we read.
*/ */
btrfs_release_path(NULL, p); btrfs_unlock_up_safe(p, level + 1);
btrfs_set_path_blocking(p);
if (tmp) if (tmp)
free_extent_buffer(tmp); free_extent_buffer(tmp);
if (p->reada) if (p->reada)
reada_for_search(root, p, level, slot, key->objectid); reada_for_search(root, p, level, slot, key->objectid);
btrfs_release_path(NULL, p);
tmp = read_tree_block(root, blocknr, blocksize, gen); tmp = read_tree_block(root, blocknr, blocksize, gen);
if (tmp) if (tmp)
free_extent_buffer(tmp); free_extent_buffer(tmp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment