Skip to content

Commit

Permalink
Btrfs: fix memory leaks on walking backrefs failure
Browse files Browse the repository at this point in the history
When walking backrefs, we may iterate every inode's extent
and add/merge them into ulist, and the caller will free memory
from ulist.

However, if we fail to allocate inode's extents element
memory or ulist_add() fail to allocate memory, we won't
add allocated memory into ulist, and the caller won't
free some allocated memory thus memory leaks happen.

Signed-off-by: Wang Shilong <wangsl.fnst@cn.fujitsu.com>
Signed-off-by: Josef Bacik <jbacik@fb.com>
Signed-off-by: Chris Mason <clm@fb.com>
  • Loading branch information
Wang Shilong authored and Chris Mason committed Jan 29, 2014
1 parent bf54f41 commit f05c474
Showing 1 changed file with 18 additions and 7 deletions.
25 changes: 18 additions & 7 deletions fs/btrfs/backref.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,16 @@ static int check_extent_in_eb(struct btrfs_key *key, struct extent_buffer *eb,
return 0;
}

static void free_inode_elem_list(struct extent_inode_elem *eie)
{
struct extent_inode_elem *eie_next;

for (; eie; eie = eie_next) {
eie_next = eie->next;
kfree(eie);
}
}

static int find_extent_in_eb(struct extent_buffer *eb, u64 wanted_disk_byte,
u64 extent_item_pos,
struct extent_inode_elem **eie)
Expand Down Expand Up @@ -275,13 +285,16 @@ static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path,
old = old->next;
old->next = eie;
}
eie = NULL;
}
next:
ret = btrfs_next_old_item(root, path, time_seq);
}

if (ret > 0)
ret = 0;
else if (ret < 0)
free_inode_elem_list(eie);
return ret;
}

Expand Down Expand Up @@ -845,6 +858,7 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
struct list_head prefs_delayed;
struct list_head prefs;
struct __prelim_ref *ref;
struct extent_inode_elem *eie = NULL;

INIT_LIST_HEAD(&prefs);
INIT_LIST_HEAD(&prefs_delayed);
Expand Down Expand Up @@ -958,7 +972,6 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
goto out;
}
if (ref->count && ref->parent) {
struct extent_inode_elem *eie = NULL;
if (extent_item_pos && !ref->inode_list) {
u32 bsz;
struct extent_buffer *eb;
Expand Down Expand Up @@ -993,6 +1006,7 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
eie = eie->next;
eie->next = ref->inode_list;
}
eie = NULL;
}
list_del(&ref->list);
kmem_cache_free(btrfs_prelim_ref_cache, ref);
Expand All @@ -1011,26 +1025,23 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
list_del(&ref->list);
kmem_cache_free(btrfs_prelim_ref_cache, ref);
}

if (ret < 0)
free_inode_elem_list(eie);
return ret;
}

static void free_leaf_list(struct ulist *blocks)
{
struct ulist_node *node = NULL;
struct extent_inode_elem *eie;
struct extent_inode_elem *eie_next;
struct ulist_iterator uiter;

ULIST_ITER_INIT(&uiter);
while ((node = ulist_next(blocks, &uiter))) {
if (!node->aux)
continue;
eie = (struct extent_inode_elem *)(uintptr_t)node->aux;
for (; eie; eie = eie_next) {
eie_next = eie->next;
kfree(eie);
}
free_inode_elem_list(eie);
node->aux = 0;
}

Expand Down

0 comments on commit f05c474

Please sign in to comment.