aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ctree.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/ctree.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/ctree.c')
-rw-r--r--fs/btrfs/ctree.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 566d99b51bef..2bc34408872d 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -1281,7 +1281,8 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
1281 free_extent_buffer(eb_root); 1281 free_extent_buffer(eb_root);
1282 blocksize = btrfs_level_size(root, old_root->level); 1282 blocksize = btrfs_level_size(root, old_root->level);
1283 old = read_tree_block(root, logical, blocksize, 0); 1283 old = read_tree_block(root, logical, blocksize, 0);
1284 if (!old) { 1284 if (!old || !extent_buffer_uptodate(old)) {
1285 free_extent_buffer(old);
1285 pr_warn("btrfs: failed to read tree block %llu from get_old_root\n", 1286 pr_warn("btrfs: failed to read tree block %llu from get_old_root\n",
1286 logical); 1287 logical);
1287 WARN_ON(1); 1288 WARN_ON(1);
@@ -1526,8 +1527,10 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
1526 if (!cur) { 1527 if (!cur) {
1527 cur = read_tree_block(root, blocknr, 1528 cur = read_tree_block(root, blocknr,
1528 blocksize, gen); 1529 blocksize, gen);
1529 if (!cur) 1530 if (!cur || !extent_buffer_uptodate(cur)) {
1531 free_extent_buffer(cur);
1530 return -EIO; 1532 return -EIO;
1533 }
1531 } else if (!uptodate) { 1534 } else if (!uptodate) {
1532 err = btrfs_read_buffer(cur, gen); 1535 err = btrfs_read_buffer(cur, gen);
1533 if (err) { 1536 if (err) {
@@ -1692,6 +1695,8 @@ static noinline struct extent_buffer *read_node_slot(struct btrfs_root *root,
1692 struct extent_buffer *parent, int slot) 1695 struct extent_buffer *parent, int slot)
1693{ 1696{
1694 int level = btrfs_header_level(parent); 1697 int level = btrfs_header_level(parent);
1698 struct extent_buffer *eb;
1699
1695 if (slot < 0) 1700 if (slot < 0)
1696 return NULL; 1701 return NULL;
1697 if (slot >= btrfs_header_nritems(parent)) 1702 if (slot >= btrfs_header_nritems(parent))
@@ -1699,9 +1704,15 @@ static noinline struct extent_buffer *read_node_slot(struct btrfs_root *root,
1699 1704
1700 BUG_ON(level == 0); 1705 BUG_ON(level == 0);
1701 1706
1702 return read_tree_block(root, btrfs_node_blockptr(parent, slot), 1707 eb = read_tree_block(root, btrfs_node_blockptr(parent, slot),
1703 btrfs_level_size(root, level - 1), 1708 btrfs_level_size(root, level - 1),
1704 btrfs_node_ptr_generation(parent, slot)); 1709 btrfs_node_ptr_generation(parent, slot));
1710 if (eb && !extent_buffer_uptodate(eb)) {
1711 free_extent_buffer(eb);
1712 eb = NULL;
1713 }
1714
1715 return eb;
1705} 1716}
1706 1717
1707/* 1718/*