summaryrefslogtreecommitdiffstats
path: root/fs/btrfs/backref.c
diff options
context:
space:
mode:
authorJosef Bacik2013-04-23 20:17:42 +0200
committerJosef Bacik2013-05-06 21:55:07 +0200
commit416bc6580bb01ddf67befaaeb94f087b392e7f47 (patch)
tree28a781ba1559a3021cb2aea8bbeebcfb20653115 /fs/btrfs/backref.c
parentBtrfs: only exclude supers in the range of our block group (diff)
downloadkernel-qcow2-linux-416bc6580bb01ddf67befaaeb94f087b392e7f47.tar.gz
kernel-qcow2-linux-416bc6580bb01ddf67befaaeb94f087b392e7f47.tar.xz
kernel-qcow2-linux-416bc6580bb01ddf67befaaeb94f087b392e7f47.zip
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/backref.c')
-rw-r--r--fs/btrfs/backref.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index 23e927b191c9..04b5b3093893 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -423,7 +423,10 @@ static int __add_missing_keys(struct btrfs_fs_info *fs_info,
BUG_ON(!ref->wanted_disk_byte);
eb = read_tree_block(fs_info->tree_root, ref->wanted_disk_byte,
fs_info->tree_root->leafsize, 0);
- BUG_ON(!eb);
+ if (!eb || !extent_buffer_uptodate(eb)) {
+ free_extent_buffer(eb);
+ return -EIO;
+ }
btrfs_tree_read_lock(eb);
if (btrfs_header_level(eb) == 0)
btrfs_item_key_to_cpu(eb, &ref->key_for_search, 0);
@@ -913,7 +916,10 @@ again:
info_level);
eb = read_tree_block(fs_info->extent_root,
ref->parent, bsz, 0);
- BUG_ON(!eb);
+ if (!eb || !extent_buffer_uptodate(eb)) {
+ free_extent_buffer(eb);
+ return -EIO;
+ }
ret = find_extent_in_eb(eb, bytenr,
*extent_item_pos, &eie);
ref->inode_list = eie;