All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jeff Mahoney <jeffm@suse.com>
To: linux-btrfs@vger.kernel.org
Subject: [patch 07/10] btrfs: handle kmalloc call path failures
Date: Wed, 04 Nov 2009 14:03:53 -0500	[thread overview]
Message-ID: <20091104190434.038152541@suse.com> (raw)
In-Reply-To: 20091104190346.971762946@suse.com

This patch adds checks to ensure that kmalloc or kmem_cache_alloc has
succeeded before using the memory.

Signed-off-by: Jeff Mahoney <jeffm@suse.com>
---
 fs/btrfs/compression.c |    3 ++-
 fs/btrfs/disk-io.c     |    5 ++++-
 fs/btrfs/extent-tree.c |   28 +++++++++++++++++++---------
 fs/btrfs/file.c        |    5 ++++-
 fs/btrfs/inode.c       |   17 +++++++++++------
 fs/btrfs/relocation.c  |   12 ++++++++----
 fs/btrfs/transaction.c |   10 +++++++---
 fs/btrfs/tree-log.c    |   25 +++++++++++++++----------
 fs/btrfs/volumes.c     |    5 ++++-
 9 files changed, 74 insertions(+), 36 deletions(-)

--- a/fs/btrfs/compression.c
+++ b/fs/btrfs/compression.c
@@ -351,7 +351,8 @@ int btrfs_submit_compressed_write(struct
 
 	WARN_ON(start & ((u64)PAGE_CACHE_SIZE - 1));
 	cb = kmalloc(compressed_bio_size(root, compressed_len), GFP_NOFS);
-	BTRFS_UERROR(!cb);
+	if (!cb)
+		return -ENOMEM;
 	atomic_set(&cb->pending_bios, 0);
 	cb->errors = 0;
 	cb->inode = inode;
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1958,7 +1958,10 @@ struct btrfs_root *open_ctree(struct sup
 
 		log_tree_root = kzalloc(sizeof(struct btrfs_root),
 						      GFP_NOFS);
-		BTRFS_UERROR(!log_tree_root);
+		if (!log_tree_root) {
+			err = -EIO;
+			goto fail_trans_kthread;
+		}
 
 		__setup_root(nodesize, leafsize, sectorsize, stripesize,
 			     log_tree_root, fs_info, BTRFS_TREE_LOG_OBJECTID);
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -414,7 +414,8 @@ static int cache_block_group(struct btrf
 		return 0;
 
 	caching_ctl = kzalloc(sizeof(*caching_ctl), GFP_KERNEL);
-	BTRFS_UERROR(!caching_ctl);
+	if (!caching_ctl)
+		return -ENOMEM;
 
 	INIT_LIST_HEAD(&caching_ctl->list);
 	mutex_init(&caching_ctl->mutex);
@@ -4217,7 +4218,7 @@ have_block_group:
 			if (loop > LOOP_CACHING_NOWAIT ||
 			    atomic_read(&space_info->caching_threads) < 2) {
 				ret = cache_block_group(block_group);
-				BUG_ON(ret);
+				BTRFS_UERROR(ret);
 			}
 		}
 
@@ -4743,7 +4744,8 @@ int btrfs_alloc_logged_file_extent(struc
 	u64 num_bytes = ins->offset;
 
 	block_group = btrfs_lookup_block_group(root->fs_info, ins->objectid);
-	cache_block_group(block_group);
+	ret = cache_block_group(block_group);
+	BTRFS_UERROR(ret);
 	caching_ctl = get_caching_control(block_group);
 
 	if (!caching_ctl) {
@@ -5388,7 +5390,10 @@ int btrfs_drop_snapshot(struct btrfs_roo
 	BUG_ON(!path);
 
 	wc = kzalloc(sizeof(*wc), GFP_NOFS);
-	BTRFS_UERROR(!wc);
+	if (!wc) {
+		btrfs_free_path(path);
+		return -ENOMEM;
+	}
 
 	trans = btrfs_start_transaction(tree_root, 1);
 
@@ -5550,7 +5555,10 @@ int btrfs_drop_subtree(struct btrfs_tran
 	BUG_ON(!path);
 
 	wc = kzalloc(sizeof(*wc), GFP_NOFS);
-	BTRFS_UERROR(!wc);
+	if (!wc) {
+		btrfs_free_path(path);
+		return -ENOMEM;
+	}
 
 	btrfs_assert_tree_locked(parent);
 	parent_level = btrfs_header_level(parent);
@@ -6528,7 +6536,8 @@ static noinline int replace_extents_in_l
 	int ret;
 
 	new_extent = kmalloc(sizeof(*new_extent), GFP_NOFS);
-	BTRFS_UERROR(!new_extent)
+	if (!new_extent)
+		return -ENOMEM;
 
 	ref = btrfs_lookup_leaf_ref(root, leaf->start);
 	BUG_ON(!ref);
@@ -6732,7 +6741,8 @@ static noinline int init_reloc_tree(stru
 		return 0;
 
 	root_item = kmalloc(sizeof(*root_item), GFP_NOFS);
-	BTRFS_UERROR(!root_item);
+	if (!root_item)
+		return -ENOMEM;
 
 	ret = btrfs_copy_root(trans, root, root->commit_root,
 			      &eb, BTRFS_TREE_RELOC_OBJECTID);
@@ -6816,7 +6826,7 @@ static noinline int relocate_one_path(st
 
 	mutex_lock(&root->fs_info->tree_reloc_mutex);
 	ret = init_reloc_tree(trans, root);
-	BUG_ON(ret);
+	BTRFS_UERROR(ret);
 	reloc_root = root->reloc_root;
 
 	shared_level = ref_path->shared_level;
@@ -6849,7 +6859,7 @@ static noinline int relocate_one_path(st
 			eb = path->nodes[0];
 			ret = replace_extents_in_leaf(trans, reloc_root, eb,
 						      group, reloc_inode);
-			BUG_ON(ret);
+			BTRFS_UERROR(ret);
 		}
 		btrfs_release_path(reloc_root, path);
 	} else {
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -946,7 +946,10 @@ static ssize_t btrfs_file_write(struct f
 	file_update_time(file);
 
 	pages = kmalloc(nrptrs * sizeof(struct page *), GFP_KERNEL);
-	BTRFS_UERROR(!pages);
+	if (!pages) {
+		err = -ENOMEM;
+		goto out;
+	}
 
 	/* generic_write_checks can change our pos */
 	start_pos = pos;
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -273,7 +273,8 @@ static noinline int add_async_extent(str
 	struct async_extent *async_extent;
 
 	async_extent = kmalloc(sizeof(*async_extent), GFP_NOFS);
-	BTRFS_UERROR(!async_extent);
+	if (!async_extent)
+		return -ENOMEM;
 	async_extent->start = start;
 	async_extent->ram_size = ram_size;
 	async_extent->compressed_size = compressed_size;
@@ -483,8 +484,9 @@ again:
 		 * allocation on disk for these compressed pages,
 		 * and will submit them to the elevator.
 		 */
-		add_async_extent(async_cow, start, num_bytes,
-				 total_compressed, pages, nr_pages_ret);
+		ret = add_async_extent(async_cow, start, num_bytes,
+				       total_compressed, pages, nr_pages_ret);
+		BTRFS_UERROR(ret);
 
 		if (start + num_bytes < end && start + num_bytes < actual_end) {
 			start += num_bytes;
@@ -506,7 +508,9 @@ cleanup_and_bail_uncompressed:
 			__set_page_dirty_nobuffers(locked_page);
 			/* unlocked later on in the async handlers */
 		}
-		add_async_extent(async_cow, start, end - start + 1, 0, NULL, 0);
+		ret = add_async_extent(async_cow, start,
+				       end - start + 1, 0, NULL, 0);
+		BTRFS_UERROR(ret);
 		*num_added += 1;
 	}
 
@@ -4450,7 +4454,8 @@ static noinline int uncompress_inline(st
 	inline_size = btrfs_file_extent_inline_item_len(leaf,
 					btrfs_item_nr(leaf, path->slots[0]));
 	tmp = kmalloc(inline_size, GFP_NOFS);
-	BTRFS_UERROR(!tmp);
+	if (!tmp)
+		return -ENOMEM;
 	ptr = btrfs_file_extent_inline_start(item);
 
 	read_extent_buffer(leaf, tmp, ptr, inline_size);
@@ -4648,7 +4653,7 @@ again:
 				ret = uncompress_inline(path, inode, page,
 							pg_offset,
 							extent_offset, item);
-				BUG_ON(ret);
+				BTRFS_UERROR(ret);
 			} else {
 				map = kmap(page);
 				read_extent_buffer(leaf, map + pg_offset, ptr,
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -850,7 +850,8 @@ static int __add_reloc_root(struct btrfs
 	struct reloc_control *rc = root->fs_info->reloc_ctl;
 
 	node = kmalloc(sizeof(*node), GFP_NOFS);
-	BTRFS_UERROR(!node);
+	if (!node)
+		return -ENOMEM;
 
 	node->bytenr = root->node->start;
 	node->data = root;
@@ -925,7 +926,8 @@ int btrfs_init_reloc_root(struct btrfs_t
 		return 0;
 
 	root_item = kmalloc(sizeof(*root_item), GFP_NOFS);
-	BTRFS_UERROR(!root_item);
+	if (!root_item)
+		return -ENOMEM;
 
 	root_key.objectid = BTRFS_TREE_RELOC_OBJECTID;
 	root_key.type = BTRFS_ROOT_ITEM_KEY;
@@ -957,7 +959,8 @@ int btrfs_init_reloc_root(struct btrfs_t
 	BUG_ON(IS_ERR(reloc_root));
 	reloc_root->last_trans = trans->transid;
 
-	__add_reloc_root(reloc_root);
+	ret = __add_reloc_root(reloc_root);
+	BTRFS_UERROR(ret);
 	root->reloc_root = reloc_root;
 	return 0;
 }
@@ -3721,7 +3724,8 @@ int btrfs_recover_relocation(struct btrf
 				       reloc_root->root_key.offset);
 		BUG_ON(IS_ERR(fs_root));
 
-		__add_reloc_root(reloc_root);
+		err = __add_reloc_root(reloc_root);
+		BTRFS_UERROR(err);
 		fs_root->reloc_root = reloc_root;
 	}
 
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -56,7 +56,8 @@ static noinline int join_transaction(str
 	if (!cur_trans) {
 		cur_trans = kmem_cache_alloc(btrfs_transaction_cachep,
 					     GFP_NOFS);
-		BTRFS_UERROR(!cur_trans);
+		if (!cur_trans)
+			return -ENOMEM;
 		root->fs_info->generation++;
 		cur_trans->num_writers = 1;
 		cur_trans->num_joined = 0;
@@ -102,6 +103,7 @@ static noinline int join_transaction(str
 static noinline int record_root_in_trans(struct btrfs_trans_handle *trans,
 					 struct btrfs_root *root)
 {
+	int ret;
 	if (root->ref_cows && root->last_trans < trans->transid) {
 		WARN_ON(root == root->fs_info->extent_root);
 		WARN_ON(root->commit_root != root->node);
@@ -110,7 +112,8 @@ static noinline int record_root_in_trans
 			   (unsigned long)root->root_key.objectid,
 			   BTRFS_ROOT_TRANS_TAG);
 		root->last_trans = trans->transid;
-		btrfs_init_reloc_root(trans, root);
+		ret = btrfs_init_reloc_root(trans, root);
+		BTRFS_UERROR(ret);
 	}
 	return 0;
 }
@@ -170,7 +173,8 @@ static struct btrfs_trans_handle *start_
 		kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS);
 	int ret;
 
-	BTRFS_UERROR(!h);
+	if (!h)
+		return ERR_PTR(-ENOMEM);
 
 	mutex_lock(&root->fs_info->trans_mutex);
 	if (!root->fs_info->log_root_recovering &&
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -663,7 +663,8 @@ static noinline int drop_one_dir_item(st
 	btrfs_dir_item_key_to_cpu(leaf, di, &location);
 	name_len = btrfs_dir_name_len(leaf, di);
 	name = kmalloc(name_len, GFP_NOFS);
-	BTRFS_UERROR(!name);
+	if (!name)
+		return -ENOMEM;
 	read_extent_buffer(leaf, name, (unsigned long)(di + 1), name_len);
 	btrfs_release_path(root, path);
 
@@ -895,7 +896,7 @@ conflict_again:
 					 name, namelen, 0);
 	if (di && !IS_ERR(di)) {
 		ret = drop_one_dir_item(trans, root, path, dir, di);
-		BUG_ON(ret);
+		BTRFS_UERROR(ret);
 	}
 	btrfs_release_path(root, path);
 
@@ -905,7 +906,7 @@ conflict_again:
 				   name, namelen, 0);
 	if (di && !IS_ERR(di)) {
 		ret = drop_one_dir_item(trans, root, path, dir, di);
-		BUG_ON(ret);
+		BTRFS_UERROR(ret);
 	}
 	btrfs_release_path(root, path);
 
@@ -1167,7 +1168,10 @@ static noinline int replay_one_name(stru
 
 	name_len = btrfs_dir_name_len(eb, di);
 	name = kmalloc(name_len, GFP_NOFS);
-	BTRFS_UERROR(!name);
+	if (!name) {
+		iput(dir);
+		return -ENOMEM;
+	}
 	log_type = btrfs_dir_type(eb, di);
 	read_extent_buffer(eb, name, (unsigned long)(di + 1),
 		   name_len);
@@ -1217,7 +1221,7 @@ static noinline int replay_one_name(stru
 		goto out;
 
 	ret = drop_one_dir_item(trans, root, path, dir, dst_di);
-	BUG_ON(ret);
+	BTRFS_UERROR(ret);
 
 	if (key->type == BTRFS_DIR_INDEX_KEY)
 		goto insert;
@@ -1261,7 +1265,7 @@ static noinline int replay_one_dir_item(
 		di = (struct btrfs_dir_item *)ptr;
 		name_len = btrfs_dir_name_len(eb, di);
 		ret = replay_one_name(trans, root, path, eb, di, key);
-		BUG_ON(ret);
+		BTRFS_UERROR(ret);
 		ptr = (unsigned long)(di + 1);
 		ptr += name_len;
 	}
@@ -2575,7 +2579,8 @@ static noinline int copy_items(struct bt
 
 	ins_data = kmalloc(nr * sizeof(struct btrfs_key) +
 			   nr * sizeof(u32), GFP_NOFS);
-	BTRFS_UERROR(!ins_data);
+	if (!ins_data)
+		return -ENOMEM;
 	ins_sizes = (u32 *)ins_data;
 	ins_keys = (struct btrfs_key *)(ins_data + nr * sizeof(u32));
 
@@ -2766,7 +2771,7 @@ again:
 
 		ret = copy_items(trans, log, dst_path, src, ins_start_slot,
 				 ins_nr, inode_only);
-		BUG_ON(ret);
+		BTRFS_UERROR(ret);
 		ins_nr = 1;
 		ins_start_slot = path->slots[0];
 next_slot:
@@ -2782,7 +2787,7 @@ next_slot:
 			ret = copy_items(trans, log, dst_path, src,
 					 ins_start_slot,
 					 ins_nr, inode_only);
-			BUG_ON(ret);
+			BTRFS_UERROR(ret);
 			ins_nr = 0;
 		}
 		btrfs_release_path(root, path);
@@ -2800,7 +2805,7 @@ next_slot:
 		ret = copy_items(trans, log, dst_path, src,
 				 ins_start_slot,
 				 ins_nr, inode_only);
-		BUG_ON(ret);
+		BTRFS_UERROR(ret);
 		ins_nr = 0;
 	}
 	WARN_ON(ins_nr);
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -2819,7 +2819,10 @@ int btrfs_rmap_block(struct btrfs_mappin
 		do_div(length, map->num_stripes);
 
 	buf = kzalloc(sizeof(u64) * map->num_stripes, GFP_NOFS);
-	BTRFS_UERROR(!buf);
+	if (!buf) {
+		free_extent_map(em);
+		return -ENOMEM;
+	}
 
 	for (i = 0; i < map->num_stripes; i++) {
 		if (devid && map->stripes[i].dev->devid != devid)


  parent reply	other threads:[~2009-11-04 19:03 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-11-04 19:03 [patch 00/10] btrfs: Error handling/propagation queue Jeff Mahoney
2009-11-04 19:03 ` [patch 01/10] btrfs: fix btrfs_read_block_groups return value Jeff Mahoney
2009-11-04 19:03 ` [patch 02/10] btrfs: fix memleak in btrfs_init_new_device Jeff Mahoney
2009-11-04 19:03 ` [patch 03/10] btrfs: fix btrfs_read_fs_root* return values Jeff Mahoney
2009-11-04 19:03 ` [patch 04/10] btrfs: btrfs_sync_file should return -EIO not EIO Jeff Mahoney
2009-11-04 19:03 ` [patch 05/10] btrfs: Add BTRFS_UERROR for unhandled errors Jeff Mahoney
2009-11-04 19:03 ` [patch 06/10] btrfs: annotate kmalloc failures Jeff Mahoney
2009-11-04 19:03 ` Jeff Mahoney [this message]
2009-11-04 19:03 ` [patch 08/10] btrfs: annotate btrfs_{start,join}_transaction failures Jeff Mahoney
2009-11-04 19:03 ` [patch 09/10] btrfs: handle btrfs_{start,join}_transaction call path failures Jeff Mahoney
2009-11-04 19:03 ` [patch 10/10] btrfs: annotate btrfs_alloc_path failures Jeff Mahoney
2009-11-04 19:43 ` [patch 00/10] btrfs: Error handling/propagation queue Jeff Mahoney

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20091104190434.038152541@suse.com \
    --to=jeffm@suse.com \
    --cc=linux-btrfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.