aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorliubo <liubo2009@cn.fujitsu.com>2011-01-26 01:22:08 -0500
committerChris Mason <chris.mason@oracle.com>2011-01-28 16:40:36 -0500
commit2a29edc6b60a5248ccab588e7ba7dad38cef0235 (patch)
tree45a7939e9e061cb2f06b09ae5f48aa79853e1250
parent6b82ce8d824bd46053e46a895876cde39d9026e4 (diff)
btrfs: fix several uncheck memory allocations
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 <liubo2009@cn.fujitsu.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r--fs/btrfs/export.c2
-rw-r--r--fs/btrfs/file-item.c2
-rw-r--r--fs/btrfs/file.c4
-rw-r--r--fs/btrfs/tree-log.c25
4 files changed, 33 insertions, 0 deletions
diff --git a/fs/btrfs/export.c b/fs/btrfs/export.c
index 6f044447359..3220ad1aafc 100644
--- a/fs/btrfs/export.c
+++ b/fs/btrfs/export.c
@@ -176,6 +176,8 @@ static struct dentry *btrfs_get_parent(struct dentry *child)
176 int ret; 176 int ret;
177 177
178 path = btrfs_alloc_path(); 178 path = btrfs_alloc_path();
179 if (!path)
180 return ERR_PTR(-ENOMEM);
179 181
180 if (dir->i_ino == BTRFS_FIRST_FREE_OBJECTID) { 182 if (dir->i_ino == BTRFS_FIRST_FREE_OBJECTID) {
181 key.objectid = root->root_key.objectid; 183 key.objectid = root->root_key.objectid;
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
index a562a250ae7..d0bc72657cd 100644
--- a/fs/btrfs/file-item.c
+++ b/fs/btrfs/file-item.c
@@ -536,6 +536,8 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans,
536 root = root->fs_info->csum_root; 536 root = root->fs_info->csum_root;
537 537
538 path = btrfs_alloc_path(); 538 path = btrfs_alloc_path();
539 if (!path)
540 return -ENOMEM;
539 541
540 while (1) { 542 while (1) {
541 key.objectid = BTRFS_EXTENT_CSUM_OBJECTID; 543 key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index f903433f5bd..65b2424a411 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -945,6 +945,10 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
945 PAGE_CACHE_SIZE, PAGE_CACHE_SIZE / 945 PAGE_CACHE_SIZE, PAGE_CACHE_SIZE /
946 (sizeof(struct page *))); 946 (sizeof(struct page *)));
947 pages = kmalloc(nrptrs * sizeof(struct page *), GFP_KERNEL); 947 pages = kmalloc(nrptrs * sizeof(struct page *), GFP_KERNEL);
948 if (!pages) {
949 ret = -ENOMEM;
950 goto out;
951 }
948 952
949 /* generic_write_checks can change our pos */ 953 /* generic_write_checks can change our pos */
950 start_pos = pos; 954 start_pos = pos;
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 054744ac571..c25a41d8611 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -338,6 +338,12 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans,
338 } 338 }
339 dst_copy = kmalloc(item_size, GFP_NOFS); 339 dst_copy = kmalloc(item_size, GFP_NOFS);
340 src_copy = kmalloc(item_size, GFP_NOFS); 340 src_copy = kmalloc(item_size, GFP_NOFS);
341 if (!dst_copy || !src_copy) {
342 btrfs_release_path(root, path);
343 kfree(dst_copy);
344 kfree(src_copy);
345 return -ENOMEM;
346 }
341 347
342 read_extent_buffer(eb, src_copy, src_ptr, item_size); 348 read_extent_buffer(eb, src_copy, src_ptr, item_size);
343 349
@@ -665,6 +671,9 @@ static noinline int drop_one_dir_item(struct btrfs_trans_handle *trans,
665 btrfs_dir_item_key_to_cpu(leaf, di, &location); 671 btrfs_dir_item_key_to_cpu(leaf, di, &location);
666 name_len = btrfs_dir_name_len(leaf, di); 672 name_len = btrfs_dir_name_len(leaf, di);
667 name = kmalloc(name_len, GFP_NOFS); 673 name = kmalloc(name_len, GFP_NOFS);
674 if (!name)
675 return -ENOMEM;
676
668 read_extent_buffer(leaf, name, (unsigned long)(di + 1), name_len); 677 read_extent_buffer(leaf, name, (unsigned long)(di + 1), name_len);
669 btrfs_release_path(root, path); 678 btrfs_release_path(root, path);
670 679
@@ -744,6 +753,9 @@ static noinline int backref_in_log(struct btrfs_root *log,
744 int match = 0; 753 int match = 0;
745 754
746 path = btrfs_alloc_path(); 755 path = btrfs_alloc_path();
756 if (!path)
757 return -ENOMEM;
758
747 ret = btrfs_search_slot(NULL, log, key, path, 0, 0); 759 ret = btrfs_search_slot(NULL, log, key, path, 0, 0);
748 if (ret != 0) 760 if (ret != 0)
749 goto out; 761 goto out;
@@ -967,6 +979,8 @@ static noinline int fixup_inode_link_count(struct btrfs_trans_handle *trans,
967 key.offset = (u64)-1; 979 key.offset = (u64)-1;
968 980
969 path = btrfs_alloc_path(); 981 path = btrfs_alloc_path();
982 if (!path)
983 return -ENOMEM;
970 984
971 while (1) { 985 while (1) {
972 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); 986 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
@@ -1178,6 +1192,9 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans,
1178 1192
1179 name_len = btrfs_dir_name_len(eb, di); 1193 name_len = btrfs_dir_name_len(eb, di);
1180 name = kmalloc(name_len, GFP_NOFS); 1194 name = kmalloc(name_len, GFP_NOFS);
1195 if (!name)
1196 return -ENOMEM;
1197
1181 log_type = btrfs_dir_type(eb, di); 1198 log_type = btrfs_dir_type(eb, di);
1182 read_extent_buffer(eb, name, (unsigned long)(di + 1), 1199 read_extent_buffer(eb, name, (unsigned long)(di + 1),
1183 name_len); 1200 name_len);
@@ -1692,6 +1709,8 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
1692 root_owner = btrfs_header_owner(parent); 1709 root_owner = btrfs_header_owner(parent);
1693 1710
1694 next = btrfs_find_create_tree_block(root, bytenr, blocksize); 1711 next = btrfs_find_create_tree_block(root, bytenr, blocksize);
1712 if (!next)
1713 return -ENOMEM;
1695 1714
1696 if (*level == 1) { 1715 if (*level == 1) {
1697 wc->process_func(root, next, wc, ptr_gen); 1716 wc->process_func(root, next, wc, ptr_gen);
@@ -2194,6 +2213,9 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans,
2194 2213
2195 log = root->log_root; 2214 log = root->log_root;
2196 path = btrfs_alloc_path(); 2215 path = btrfs_alloc_path();
2216 if (!path)
2217 return -ENOMEM;
2218
2197 di = btrfs_lookup_dir_item(trans, log, path, dir->i_ino, 2219 di = btrfs_lookup_dir_item(trans, log, path, dir->i_ino,
2198 name, name_len, -1); 2220 name, name_len, -1);
2199 if (IS_ERR(di)) { 2221 if (IS_ERR(di)) {
@@ -2594,6 +2616,9 @@ static noinline int copy_items(struct btrfs_trans_handle *trans,
2594 2616
2595 ins_data = kmalloc(nr * sizeof(struct btrfs_key) + 2617 ins_data = kmalloc(nr * sizeof(struct btrfs_key) +
2596 nr * sizeof(u32), GFP_NOFS); 2618 nr * sizeof(u32), GFP_NOFS);
2619 if (!ins_data)
2620 return -ENOMEM;
2621
2597 ins_sizes = (u32 *)ins_data; 2622 ins_sizes = (u32 *)ins_data;
2598 ins_keys = (struct btrfs_key *)(ins_data + nr * sizeof(u32)); 2623 ins_keys = (struct btrfs_key *)(ins_data + nr * sizeof(u32));
2599 2624