aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/relocation.c
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2013-04-23 14:17:42 -0400
committerJosef Bacik <jbacik@fusionio.com>2013-05-06 15:55:07 -0400
commit416bc6580bb01ddf67befaaeb94f087b392e7f47 (patch)
tree28a781ba1559a3021cb2aea8bbeebcfb20653115 /fs/btrfs/relocation.c
parent51bf5f0bc4d132a3646ce36061e83fdc8b77f302 (diff)
Btrfs: fix all callers of read_tree_block
We kept leaking extent buffers when mounting a broken file system and it turns out it's because not everybody uses read_tree_block properly. You need to check and make sure the extent_buffer is uptodate before you use it. This patch fixes everybody who calls read_tree_block directly to make sure they check that it is uptodate and free it and return an error if it is not. With this we no longer leak EB's when things go horribly wrong. Thanks, Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs/btrfs/relocation.c')
-rw-r--r--fs/btrfs/relocation.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 208154986c4c..63cdd9246c70 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -1771,7 +1771,11 @@ again:
1771 1771
1772 eb = read_tree_block(dest, old_bytenr, blocksize, 1772 eb = read_tree_block(dest, old_bytenr, blocksize,
1773 old_ptr_gen); 1773 old_ptr_gen);
1774 BUG_ON(!eb); 1774 if (!eb || !extent_buffer_uptodate(eb)) {
1775 ret = (!eb) ? -ENOMEM : -EIO;
1776 free_extent_buffer(eb);
1777 return ret;
1778 }
1775 btrfs_tree_lock(eb); 1779 btrfs_tree_lock(eb);
1776 if (cow) { 1780 if (cow) {
1777 ret = btrfs_cow_block(trans, dest, eb, parent, 1781 ret = btrfs_cow_block(trans, dest, eb, parent,
@@ -1924,6 +1928,10 @@ int walk_down_reloc_tree(struct btrfs_root *root, struct btrfs_path *path,
1924 bytenr = btrfs_node_blockptr(eb, path->slots[i]); 1928 bytenr = btrfs_node_blockptr(eb, path->slots[i]);
1925 blocksize = btrfs_level_size(root, i - 1); 1929 blocksize = btrfs_level_size(root, i - 1);
1926 eb = read_tree_block(root, bytenr, blocksize, ptr_gen); 1930 eb = read_tree_block(root, bytenr, blocksize, ptr_gen);
1931 if (!eb || !extent_buffer_uptodate(eb)) {
1932 free_extent_buffer(eb);
1933 return -EIO;
1934 }
1927 BUG_ON(btrfs_header_level(eb) != i - 1); 1935 BUG_ON(btrfs_header_level(eb) != i - 1);
1928 path->nodes[i - 1] = eb; 1936 path->nodes[i - 1] = eb;
1929 path->slots[i - 1] = 0; 1937 path->slots[i - 1] = 0;
@@ -2601,7 +2609,8 @@ static int do_relocation(struct btrfs_trans_handle *trans,
2601 blocksize = btrfs_level_size(root, node->level); 2609 blocksize = btrfs_level_size(root, node->level);
2602 generation = btrfs_node_ptr_generation(upper->eb, slot); 2610 generation = btrfs_node_ptr_generation(upper->eb, slot);
2603 eb = read_tree_block(root, bytenr, blocksize, generation); 2611 eb = read_tree_block(root, bytenr, blocksize, generation);
2604 if (!eb) { 2612 if (!eb || !extent_buffer_uptodate(eb)) {
2613 free_extent_buffer(eb);
2605 err = -EIO; 2614 err = -EIO;
2606 goto next; 2615 goto next;
2607 } 2616 }
@@ -2762,7 +2771,10 @@ static int get_tree_block_key(struct reloc_control *rc,
2762 BUG_ON(block->key_ready); 2771 BUG_ON(block->key_ready);
2763 eb = read_tree_block(rc->extent_root, block->bytenr, 2772 eb = read_tree_block(rc->extent_root, block->bytenr,
2764 block->key.objectid, block->key.offset); 2773 block->key.objectid, block->key.offset);
2765 BUG_ON(!eb); 2774 if (!eb || !extent_buffer_uptodate(eb)) {
2775 free_extent_buffer(eb);
2776 return -EIO;
2777 }
2766 WARN_ON(btrfs_header_level(eb) != block->level); 2778 WARN_ON(btrfs_header_level(eb) != block->level);
2767 if (block->level == 0) 2779 if (block->level == 0)
2768 btrfs_item_key_to_cpu(eb, &block->key, 0); 2780 btrfs_item_key_to_cpu(eb, &block->key, 0);