Skip to content

Commit

Permalink
btrfs: fix several uncheck memory allocations
Browse files Browse the repository at this point in the history
To make btrfs more stable, add several missing necessary memory allocation
checks, and when no memory, return proper errno.

We've checked that some of those -ENOMEM errors will be returned to
userspace, and some will be catched by BUG_ON() in the upper callers,
and none will be ignored silently.

Signed-off-by: Liu Bo <[email protected]>
Signed-off-by: Chris Mason <[email protected]>
  • Loading branch information
liub authored and chrismason-xx committed Jan 28, 2011
1 parent 6b82ce8 commit 2a29edc
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 0 deletions.
2 changes: 2 additions & 0 deletions fs/btrfs/export.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,8 @@ static struct dentry *btrfs_get_parent(struct dentry *child)
int ret;

path = btrfs_alloc_path();
if (!path)
return ERR_PTR(-ENOMEM);

if (dir->i_ino == BTRFS_FIRST_FREE_OBJECTID) {
key.objectid = root->root_key.objectid;
Expand Down
2 changes: 2 additions & 0 deletions fs/btrfs/file-item.c
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,8 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans,
root = root->fs_info->csum_root;

path = btrfs_alloc_path();
if (!path)
return -ENOMEM;

while (1) {
key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
Expand Down
4 changes: 4 additions & 0 deletions fs/btrfs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,10 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
PAGE_CACHE_SIZE, PAGE_CACHE_SIZE /
(sizeof(struct page *)));
pages = kmalloc(nrptrs * sizeof(struct page *), GFP_KERNEL);
if (!pages) {
ret = -ENOMEM;
goto out;
}

/* generic_write_checks can change our pos */
start_pos = pos;
Expand Down
25 changes: 25 additions & 0 deletions fs/btrfs/tree-log.c
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,12 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans,
}
dst_copy = kmalloc(item_size, GFP_NOFS);
src_copy = kmalloc(item_size, GFP_NOFS);
if (!dst_copy || !src_copy) {
btrfs_release_path(root, path);
kfree(dst_copy);
kfree(src_copy);
return -ENOMEM;
}

read_extent_buffer(eb, src_copy, src_ptr, item_size);

Expand Down Expand Up @@ -665,6 +671,9 @@ static noinline int drop_one_dir_item(struct btrfs_trans_handle *trans,
btrfs_dir_item_key_to_cpu(leaf, di, &location);
name_len = btrfs_dir_name_len(leaf, di);
name = kmalloc(name_len, GFP_NOFS);
if (!name)
return -ENOMEM;

read_extent_buffer(leaf, name, (unsigned long)(di + 1), name_len);
btrfs_release_path(root, path);

Expand Down Expand Up @@ -744,6 +753,9 @@ static noinline int backref_in_log(struct btrfs_root *log,
int match = 0;

path = btrfs_alloc_path();
if (!path)
return -ENOMEM;

ret = btrfs_search_slot(NULL, log, key, path, 0, 0);
if (ret != 0)
goto out;
Expand Down Expand Up @@ -967,6 +979,8 @@ static noinline int fixup_inode_link_count(struct btrfs_trans_handle *trans,
key.offset = (u64)-1;

path = btrfs_alloc_path();
if (!path)
return -ENOMEM;

while (1) {
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
Expand Down Expand Up @@ -1178,6 +1192,9 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans,

name_len = btrfs_dir_name_len(eb, di);
name = kmalloc(name_len, GFP_NOFS);
if (!name)
return -ENOMEM;

log_type = btrfs_dir_type(eb, di);
read_extent_buffer(eb, name, (unsigned long)(di + 1),
name_len);
Expand Down Expand Up @@ -1692,6 +1709,8 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
root_owner = btrfs_header_owner(parent);

next = btrfs_find_create_tree_block(root, bytenr, blocksize);
if (!next)
return -ENOMEM;

if (*level == 1) {
wc->process_func(root, next, wc, ptr_gen);
Expand Down Expand Up @@ -2194,6 +2213,9 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans,

log = root->log_root;
path = btrfs_alloc_path();
if (!path)
return -ENOMEM;

di = btrfs_lookup_dir_item(trans, log, path, dir->i_ino,
name, name_len, -1);
if (IS_ERR(di)) {
Expand Down Expand Up @@ -2594,6 +2616,9 @@ static noinline int copy_items(struct btrfs_trans_handle *trans,

ins_data = kmalloc(nr * sizeof(struct btrfs_key) +
nr * sizeof(u32), GFP_NOFS);
if (!ins_data)
return -ENOMEM;

ins_sizes = (u32 *)ins_data;
ins_keys = (struct btrfs_key *)(ins_data + nr * sizeof(u32));

Expand Down

0 comments on commit 2a29edc

Please sign in to comment.