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

This patch changes start_transaction() to return an ERR_PTR instead of
NULL. Things like I/O errors and allocation failures can be handled
differently.

Many calls that were previously handled by BTRFS_UERROR are changed to
actually pass the error up the tree where appropriate.

In cases where the handling isn't small or obvious, the BTRFS_UERROR
call is kept for handling in small patches specific to that site.

Eventually it may be preferable to allow passing of gfp_t to
btrfs_start_transaction (or a one-off) so that handling can be done at
allocation time instead of failing all the way up the call path.

Signed-off-by: Jeff Mahoney <jeffm@suse.com>

---
 fs/btrfs/compression.c |   10 ++-
 fs/btrfs/disk-io.c     |   37 +++++++++-----
 fs/btrfs/extent-tree.c |   43 ++++++++++------
 fs/btrfs/extent_io.c   |   60 ++++++++++++++--------
 fs/btrfs/file.c        |   16 ++++--
 fs/btrfs/inode.c       |  128 ++++++++++++++++++++++++++++++-------------------
 fs/btrfs/ioctl.c       |   73 +++++++++++++++++++--------
 fs/btrfs/relocation.c  |   96 ++++++++++++++++++++++++++++--------
 fs/btrfs/super.c       |   12 +++-
 fs/btrfs/transaction.c |   34 +++++++++----
 fs/btrfs/tree-log.c    |   14 +++--
 fs/btrfs/volumes.c     |   44 ++++++++++------
 fs/btrfs/xattr.c       |    3 -
 13 files changed, 382 insertions(+), 188 deletions(-)

--- a/fs/btrfs/compression.c
+++ b/fs/btrfs/compression.c
@@ -280,6 +280,7 @@ static void end_compressed_bio_write(str
 	struct inode *inode;
 	struct page *page;
 	unsigned long index;
+	int ret;
 
 	if (err)
 		cb->errors = 1;
@@ -296,10 +297,11 @@ static void end_compressed_bio_write(str
 	inode = cb->inode;
 	tree = &BTRFS_I(inode)->io_tree;
 	cb->compressed_pages[0]->mapping = cb->inode->i_mapping;
-	tree->ops->writepage_end_io_hook(cb->compressed_pages[0],
-					 cb->start,
-					 cb->start + cb->len - 1,
-					 NULL, 1);
+	ret = tree->ops->writepage_end_io_hook(cb->compressed_pages[0],
+					       cb->start,
+					       cb->start + cb->len - 1,
+					       NULL, 1);
+	BTRFS_UERROR(ret);
 	cb->compressed_pages[0]->mapping = NULL;
 
 	end_compressed_writeback(inode, cb->start, cb->len);
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1468,6 +1468,7 @@ static void end_workqueue_fn(struct btrf
 static int cleaner_kthread(void *arg)
 {
 	struct btrfs_root *root = arg;
+	int ret;
 
 	do {
 		smp_mb();
@@ -1478,7 +1479,8 @@ static int cleaner_kthread(void *arg)
 
 		if (!(root->fs_info->sb->s_flags & MS_RDONLY) &&
 		    mutex_trylock(&root->fs_info->cleaner_mutex)) {
-			btrfs_clean_old_snapshots(root);
+			ret = btrfs_clean_old_snapshots(root);
+			BTRFS_UERROR(ret);
 			mutex_unlock(&root->fs_info->cleaner_mutex);
 		}
 
@@ -1529,9 +1531,11 @@ static int transaction_kthread(void *arg
 		}
 		mutex_unlock(&root->fs_info->trans_mutex);
 		trans = btrfs_start_transaction(root, 1);
-		BTRFS_UERROR(!trans);
-		ret = btrfs_commit_transaction(trans, root);
+		if (!IS_ERR(trans))
+			ret = btrfs_commit_transaction(trans, root);
 
+		if (IS_ERR(trans) || ret)
+			delay = HZ * 5;
 sleep:
 		wake_up_process(root->fs_info->cleaner_kthread);
 		mutex_unlock(&root->fs_info->transaction_kthread_mutex);
@@ -1971,11 +1975,15 @@ struct btrfs_root *open_ctree(struct sup
 						      blocksize,
 						      generation + 1);
 		ret = btrfs_recover_log_trees(log_tree_root);
-		BUG_ON(ret);
+		if (ret) {
+			/* log_tree_root is cleaned up by
+			 * btrfs_recover_log_trees */
+			goto fail_trans_thread;
+		}
 
 		if (sb->s_flags & MS_RDONLY) {
 			ret =  btrfs_commit_super(tree_root);
-			BUG_ON(ret);
+			BTRFS_UERROR(ret);
 		}
 	}
 
@@ -1984,7 +1992,7 @@ struct btrfs_root *open_ctree(struct sup
 
 	if (!(sb->s_flags & MS_RDONLY)) {
 		ret = btrfs_recover_relocation(tree_root);
-		BUG_ON(ret);
+		BTRFS_UERROR(ret);
 	}
 
 	location.objectid = BTRFS_FS_TREE_OBJECTID;
@@ -2393,16 +2401,23 @@ int btrfs_commit_super(struct btrfs_root
 	int ret;
 
 	mutex_lock(&root->fs_info->cleaner_mutex);
-	btrfs_clean_old_snapshots(root);
+	ret = btrfs_clean_old_snapshots(root);
 	mutex_unlock(&root->fs_info->cleaner_mutex);
+	if (ret)
+		return ret;
 	trans = btrfs_start_transaction(root, 1);
-	BTRFS_UERROR(!trans);
+	if (IS_ERR(trans))
+		return PTR_ERR(trans);
 	ret = btrfs_commit_transaction(trans, root);
-	BUG_ON(ret);
+	if (ret)
+		return ret;
 	/* run commit again to drop the original snapshot */
 	trans = btrfs_start_transaction(root, 1);
-	BTRFS_UERROR(!trans);
-	btrfs_commit_transaction(trans, root);
+	if (IS_ERR(trans))
+		return PTR_ERR(trans);
+	ret = btrfs_commit_transaction(trans, root);
+	if (ret)
+		return ret;
 	ret = btrfs_write_and_wait_transaction(NULL, root);
 	BUG_ON(ret);
 
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -3009,8 +3009,8 @@ static int maybe_allocate_chunk(struct b
 	}
 
 	trans = btrfs_start_transaction(root, 1);
-	if (!trans) {
-		ret = -ENOMEM;
+	if (IS_ERR(trans)) {
+		ret = PTR_ERR(trans);
 		goto out;
 	}
 
@@ -3044,6 +3044,7 @@ int btrfs_reserve_metadata_for_delalloc(
 	u64 alloc_target;
 	int flushed = 0;
 	int force_delalloc;
+	int ret = 0;
 
 	/* get the space info for where the metadata will live */
 	alloc_target = btrfs_get_alloc_profile(root, 0);
@@ -3249,8 +3250,8 @@ again:
 alloc:
 			alloc_target = btrfs_get_alloc_profile(root, 1);
 			trans = btrfs_start_transaction(root, 1);
-			if (!trans)
-				return -ENOMEM;
+			if (IS_ERR(trans))
+				return PTR_ERR(trans);
 
 			ret = do_chunk_alloc(trans, root->fs_info->extent_root,
 					     bytes + 2 * 1024 * 1024,
@@ -3271,7 +3272,7 @@ alloc:
 		if (!committed && !root->fs_info->open_ioctl_trans) {
 			committed = 1;
 			trans = btrfs_join_transaction(root, 1);
-			if (!trans)
+			if (IS_ERR(trans))
 				return PTR_ERR(trans);
 			ret = btrfs_commit_transaction(trans, root);
 			if (ret)
@@ -5396,7 +5397,10 @@ int btrfs_drop_snapshot(struct btrfs_roo
 	}
 
 	trans = btrfs_start_transaction(tree_root, 1);
-	BTRFS_UERROR(!trans);
+	if (IS_ERR(trans)) {
+		err = PTR_ERR(trans);
+		goto out_err;
+	}
 
 	if (btrfs_disk_key_objectid(&root_item->drop_progress) == 0) {
 		level = btrfs_header_level(root->node);
@@ -5493,7 +5497,7 @@ int btrfs_drop_snapshot(struct btrfs_roo
 
 			btrfs_end_transaction(trans, tree_root);
 			trans = btrfs_start_transaction(tree_root, 1);
-			BTRFS_UERROR(!trans);
+			BTRFS_UERROR(IS_ERR(trans));
 		} else {
 			unsigned long update;
 			update = trans->delayed_ref_updates;
@@ -5529,6 +5533,7 @@ int btrfs_drop_snapshot(struct btrfs_roo
 	}
 out:
 	btrfs_end_transaction(trans, tree_root);
+out_err:
 	kfree(wc);
 	btrfs_free_path(path);
 	return err;
@@ -6656,7 +6661,7 @@ int btrfs_drop_dead_reloc_roots(struct b
 		BUG_ON(reloc_root->commit_root != NULL);
 		while (1) {
 			trans = btrfs_join_transaction(root, 1);
-			BTRFS_UERROR(!trans);
+			BTRFS_UERROR(IS_ERR(trans));
 
 			mutex_lock(&root->fs_info->drop_mutex);
 			ret = btrfs_drop_snapshot(trans, reloc_root);
@@ -6669,6 +6674,7 @@ int btrfs_drop_dead_reloc_roots(struct b
 			BUG_ON(ret);
 			btrfs_btree_balance_dirty(root, nr);
 		}
+		BTRFS_UERROR(ret);
 
 		free_extent_buffer(reloc_root->node);
 
@@ -6714,9 +6720,11 @@ int btrfs_cleanup_reloc_trees(struct btr
 
 	if (found) {
 		trans = btrfs_start_transaction(root, 1);
-		BTRFS_UERROR(!trans);
+		if (IS_ERR(trans))
+			return PTR_ERR(trans);
 		ret = btrfs_commit_transaction(trans, root);
-		BUG_ON(ret);
+		if (ret)
+			return ret;
 	}
 
 	location.objectid = BTRFS_DATA_RELOC_TREE_OBJECTID;
@@ -6959,7 +6967,8 @@ static noinline int relocate_one_extent(
 
 
 	trans = btrfs_start_transaction(extent_root, 1);
-	BTRFS_UERROR(!trans);
+	if (IS_ERR(trans))
+		return PTR_ERR(trans);
 
 	if (extent_key->objectid == 0) {
 		ret = del_extent_zero(trans, extent_root, path, extent_key);
@@ -6989,7 +6998,7 @@ static noinline int relocate_one_extent(
 			continue;
 
 		found_root = read_ref_root(extent_root->fs_info, ref_path);
-		BUG_ON(IS_ERR(found_root));
+		BTRFS_UERROR(IS_ERR(found_root));
 		/*
 		 * for reference counted tree, only process reference paths
 		 * rooted at the latest committed root.
@@ -7142,7 +7151,8 @@ static int __alloc_chunk_for_shrink(stru
 		spin_unlock(&shrink_block_group->lock);
 
 		trans = btrfs_start_transaction(root, 1);
-		BTRFS_UERROR(!trans);
+		if (IS_ERR(trans))
+			return PTR_ERR(trans);
 		spin_lock(&shrink_block_group->lock);
 
 		new_alloc_flags = update_block_group_flags(root,
@@ -7169,9 +7179,10 @@ int btrfs_prepare_block_group_relocation
 					 struct btrfs_block_group_cache *group)
 
 {
-	__alloc_chunk_for_shrink(root, group, 1);
-	set_block_group_readonly(group);
-	return 0;
+	int ret = __alloc_chunk_for_shrink(root, group, 1);
+	if (!ret)
+		set_block_group_readonly(group);
+	return ret;
 }
 
 /*
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -1899,10 +1899,11 @@ static int submit_one_bio(int rw, struct
 
 	bio_get(bio);
 
-	if (tree->ops && tree->ops->submit_bio_hook)
-		tree->ops->submit_bio_hook(page->mapping->host, rw, bio,
-					   mirror_num, bio_flags);
-	else
+	if (tree->ops && tree->ops->submit_bio_hook) {
+		ret = tree->ops->submit_bio_hook(page->mapping->host, rw, bio,
+						 mirror_num, bio_flags);
+		BTRFS_UERROR(ret);
+	} else
 		submit_bio(rw, bio);
 	if (bio_flagged(bio, BIO_EOPNOTSUPP))
 		ret = -EOPNOTSUPP;
@@ -2189,7 +2190,7 @@ static int __extent_writepage(struct pag
 	struct extent_state *cached_state = NULL;
 	struct extent_map *em;
 	struct block_device *bdev;
-	int ret;
+	int ret = 0;
 	int nr = 0;
 	size_t pg_offset = 0;
 	size_t blocksize;
@@ -2250,9 +2251,12 @@ static int __extent_writepage(struct pag
 				delalloc_start = delalloc_end + 1;
 				continue;
 			}
-			tree->ops->fill_delalloc(inode, page, delalloc_start,
-						 delalloc_end, &page_started,
-						 &nr_written);
+			ret = tree->ops->fill_delalloc(inode, page,
+						       delalloc_start,
+						       delalloc_end,
+						       &page_started,
+						       &nr_written);
+			BTRFS_UERROR(ret);
 			/*
 			 * delalloc_end is already one less than the total
 			 * length, so we don't subtract one from
@@ -2306,9 +2310,11 @@ static int __extent_writepage(struct pag
 
 	end = page_end;
 	if (last_byte <= start) {
-		if (tree->ops && tree->ops->writepage_end_io_hook)
-			tree->ops->writepage_end_io_hook(page, start,
-							 page_end, NULL, 1);
+		if (tree->ops && tree->ops->writepage_end_io_hook) {
+			ret = tree->ops->writepage_end_io_hook(page, start,
+							page_end, NULL, 1);
+			BTRFS_UERROR(ret);
+		}
 		unlock_start = page_end + 1;
 		goto done;
 	}
@@ -2317,9 +2323,12 @@ static int __extent_writepage(struct pag
 
 	while (cur <= end) {
 		if (cur >= last_byte) {
-			if (tree->ops && tree->ops->writepage_end_io_hook)
-				tree->ops->writepage_end_io_hook(page, cur,
-							 page_end, NULL, 1);
+			if (tree->ops && tree->ops->writepage_end_io_hook) {
+				ret = tree->ops->writepage_end_io_hook(page,
+								cur, page_end,
+								NULL, 1);
+				BTRFS_UERROR(ret);
+			}
 			unlock_start = page_end + 1;
 			break;
 		}
@@ -2353,10 +2362,12 @@ static int __extent_writepage(struct pag
 			 * compressed extents
 			 */
 			if (!compressed && tree->ops &&
-			    tree->ops->writepage_end_io_hook)
-				tree->ops->writepage_end_io_hook(page, cur,
-							 cur + iosize - 1,
-							 NULL, 1);
+			    tree->ops->writepage_end_io_hook) {
+				ret = tree->ops->writepage_end_io_hook(page,
+							cur, cur + iosize - 1,
+							NULL, 1);
+				BTRFS_UERROR(ret);
+			}
 			else if (compressed) {
 				/* we don't want to end_page_writeback on
 				 * a compressed extent.  this happens
@@ -2421,7 +2432,7 @@ done_unlocked:
 
 	/* drop our reference on any cached states */
 	free_extent_state(cached_state);
-	return 0;
+	return ret;
 }
 
 /**
@@ -2621,10 +2632,13 @@ int extent_write_locked_range(struct ext
 		if (clear_page_dirty_for_io(page))
 			ret = __extent_writepage(page, &wbc_writepages, &epd);
 		else {
-			if (tree->ops && tree->ops->writepage_end_io_hook)
-				tree->ops->writepage_end_io_hook(page, start,
-						 start + PAGE_CACHE_SIZE - 1,
-						 NULL, 1);
+			if (tree->ops && tree->ops->writepage_end_io_hook) {
+				ret = tree->ops->writepage_end_io_hook(page,
+						start,
+						start + PAGE_CACHE_SIZE - 1,
+						NULL, 1);
+				BTRFS_UERROR(ret);
+			}
 			unlock_page(page);
 		}
 		page_cache_release(page);
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1083,7 +1083,10 @@ out_nolock:
 
 		if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) {
 			trans = btrfs_start_transaction(root, 1);
-			BTRFS_UERROR(!trans);
+			if (IS_ERR(trans)) {
+				err = PTR_ERR(trans);
+				goto out;
+			}
 			ret = btrfs_log_dentry_safe(trans, root,
 						    file->f_dentry);
 			if (ret == 0) {
@@ -1091,9 +1094,11 @@ out_nolock:
 				if (ret == 0)
 					btrfs_end_transaction(trans, root);
 				else
-					btrfs_commit_transaction(trans, root);
+					err = btrfs_commit_transaction(trans,
+								       root);
+
 			} else if (ret != BTRFS_NO_LOG_SYNC) {
-				btrfs_commit_transaction(trans, root);
+				err = btrfs_commit_transaction(trans, root);
 			} else {
 				btrfs_end_transaction(trans, root);
 			}
@@ -1104,6 +1109,7 @@ out_nolock:
 			     (start_pos + num_written - 1) >> PAGE_CACHE_SHIFT);
 		}
 	}
+out:
 	current->backing_dev_info = NULL;
 	return num_written ? num_written : err;
 }
@@ -1180,8 +1186,8 @@ int btrfs_sync_file(struct file *file, s
 		btrfs_ioctl_trans_end(file);
 
 	trans = btrfs_start_transaction(root, 1);
-	if (!trans) {
-		ret = -ENOMEM;
+	if (IS_ERR(trans)) {
+		ret = PTR_ERR(trans);
 		goto out;
 	}
 
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -403,7 +403,7 @@ again:
 	}
 	if (start == 0) {
 		trans = btrfs_join_transaction(root, 1);
-		BTRFS_UERROR(!trans);
+		BTRFS_UERROR(IS_ERR(trans));
 		btrfs_set_trans_block_group(trans, inode);
 
 		/* lets try to make an inline extent */
@@ -550,7 +550,8 @@ static noinline int submit_compressed_ex
 		return 0;
 
 	trans = btrfs_join_transaction(root, 1);
-	BTRFS_UERROR(!trans);
+	if (IS_ERR(trans))
+		return PTR_ERR(trans);
 
 	while (!list_empty(&async_cow->extents)) {
 		async_extent = list_entry(async_cow->extents.next,
@@ -569,11 +570,12 @@ static noinline int submit_compressed_ex
 				    async_extent->ram_size - 1, GFP_NOFS);
 
 			/* allocate blocks */
-			cow_file_range(inode, async_cow->locked_page,
-				       async_extent->start,
-				       async_extent->start +
-				       async_extent->ram_size - 1,
-				       &page_started, &nr_written, 0);
+			ret = cow_file_range(inode, async_cow->locked_page,
+					     async_extent->start,
+					     async_extent->start +
+					     async_extent->ram_size - 1,
+					     &page_started, &nr_written, 0);
+			BTRFS_UERROR(ret);
 
 			/*
 			 * if page_started, cow_file_range inserted an
@@ -581,13 +583,15 @@ static noinline int submit_compressed_ex
 			 * and IO for us.  Otherwise, we need to submit
 			 * all those pages down to the drive.
 			 */
-			if (!page_started)
-				extent_write_locked_range(io_tree,
+			if (!page_started) {
+				ret = extent_write_locked_range(io_tree,
 						  inode, async_extent->start,
 						  async_extent->start +
 						  async_extent->ram_size - 1,
 						  btrfs_get_extent,
 						  WB_SYNC_ALL);
+				BTRFS_UERROR(ret);
+			}
 			kfree(async_extent);
 			cond_resched();
 			continue;
@@ -665,7 +669,7 @@ static noinline int submit_compressed_ex
 
 		BUG_ON(ret);
 		trans = btrfs_join_transaction(root, 1);
-		BTRFS_UERROR(!trans);
+		BTRFS_UERROR(IS_ERR(trans));
 		alloc_hint = ins.objectid + ins.offset;
 		kfree(async_extent);
 		cond_resched();
@@ -710,7 +714,8 @@ static noinline int cow_file_range(struc
 	int ret = 0;
 
 	trans = btrfs_join_transaction(root, 1);
-	BTRFS_UERROR(!trans);
+	if (IS_ERR(trans))
+		return PTR_ERR(trans);
 	btrfs_set_trans_block_group(trans, inode);
 
 	actual_end = min_t(u64, isize, end + 1);
@@ -838,10 +843,12 @@ static noinline void async_cow_start(str
 	struct async_cow *async_cow;
 	int num_added = 0;
 	async_cow = container_of(work, struct async_cow, work);
+	int ret;
 
-	compress_file_range(async_cow->inode, async_cow->locked_page,
-			    async_cow->start, async_cow->end, async_cow,
-			    &num_added);
+	ret = compress_file_range(async_cow->inode, async_cow->locked_page,
+				  async_cow->start, async_cow->end, async_cow,
+				  &num_added);
+	BTRFS_UERROR(ret);
 	if (num_added == 0)
 		async_cow->inode = NULL;
 }
@@ -992,7 +999,8 @@ static noinline int run_delalloc_nocow(s
 	path = btrfs_alloc_path();
 	BUG_ON(!path);
 	trans = btrfs_join_transaction(root, 1);
-	BTRFS_UERROR(!trans);
+	if (IS_ERR(trans))
+		return PTR_ERR(trans);
 
 	cow_start = (u64)-1;
 	cur_offset = start;
@@ -1102,7 +1110,7 @@ out_check:
 			ret = cow_file_range(inode, locked_page, cow_start,
 					found_key.offset - 1, page_started,
 					nr_written, 1);
-			BUG_ON(ret);
+			BTRFS_UERROR(ret);
 			cow_start = (u64)-1;
 		}
 
@@ -1154,7 +1162,7 @@ out_check:
 	if (cow_start != (u64)-1) {
 		ret = cow_file_range(inode, locked_page, cow_start, end,
 				     page_started, nr_written, 1);
-		BUG_ON(ret);
+		BTRFS_UERROR(ret);
 	}
 
 	ret = btrfs_end_transaction(trans, root);
@@ -1711,7 +1719,8 @@ static int btrfs_finish_ordered_io(struc
 	}
 
 	trans = btrfs_join_transaction(root, 1);
-	BTRFS_UERROR(!trans);
+	if (IS_ERR(trans))
+		return PTR_ERR(trans);
 
 	if (!ordered_extent)
 		ordered_extent = btrfs_lookup_ordered_extent(inode, start);
@@ -2132,7 +2141,7 @@ void btrfs_orphan_cleanup(struct btrfs_r
 		 */
 		if (is_bad_inode(inode)) {
 			trans = btrfs_start_transaction(root, 1);
-			BTRFS_UERROR(!trans);
+			BTRFS_UERROR(IS_ERR(trans));
 			btrfs_orphan_del(trans, inode);
 			btrfs_end_transaction(trans, root);
 			iput(inode);
@@ -2486,7 +2495,8 @@ static int btrfs_unlink(struct inode *di
 	root = BTRFS_I(dir)->root;
 
 	trans = btrfs_start_transaction(root, 1);
-	BTRFS_UERROR(!trans);
+	if (IS_ERR(trans))
+		return PTR_ERR(trans);
 
 	btrfs_set_trans_block_group(trans, dir);
 
@@ -2582,7 +2592,9 @@ static int btrfs_rmdir(struct inode *dir
 		return -ENOTEMPTY;
 
 	trans = btrfs_start_transaction(root, 1);
-	BTRFS_UERROR(!trans);
+	if (IS_ERR(trans))
+		return PTR_ERR(trans);
+
 	btrfs_set_trans_block_group(trans, dir);
 
 	if (unlikely(inode->i_ino == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)) {
@@ -3158,14 +3170,17 @@ int btrfs_cont_expand(struct inode *inod
 	}
 
 	trans = btrfs_start_transaction(root, 1);
-	BTRFS_UERROR(!trans);
+	if (IS_ERR(trans)) {
+		err = PTR_ERR(trans);
+		goto out;
+	}
 	btrfs_set_trans_block_group(trans, inode);
 
 	cur_offset = hole_start;
 	while (1) {
 		em = btrfs_get_extent(inode, NULL, 0, cur_offset,
 				block_end - cur_offset, 0);
-		BUG_ON(IS_ERR(em) || !em);
+		BTRFS_UERROR(IS_ERR(em) || !em);
 		last_byte = min(extent_map_end(em), block_end);
 		last_byte = (last_byte + mask) & ~mask;
 		if (test_bit(EXTENT_FLAG_VACANCY, &em->flags)) {
@@ -3198,6 +3213,7 @@ int btrfs_cont_expand(struct inode *inod
 	}
 
 	btrfs_end_transaction(trans, root);
+out:
 	unlock_extent(io_tree, hole_start, block_end - 1, GFP_NOFS);
 	return err;
 }
@@ -3256,7 +3272,7 @@ void btrfs_delete_inode(struct inode *in
 
 	btrfs_i_size_write(inode, 0);
 	trans = btrfs_join_transaction(root, 1);
-	BTRFS_UERROR(!trans);
+	BTRFS_UERROR(IS_ERR(trans));
 
 	btrfs_set_trans_block_group(trans, inode);
 	ret = btrfs_truncate_inode_items(trans, root, inode, inode->i_size, 0);
@@ -3853,7 +3869,8 @@ int btrfs_write_inode(struct inode *inod
 
 	if (wait) {
 		trans = btrfs_join_transaction(root, 1);
-		BTRFS_UERROR(!trans);
+		if (IS_ERR(trans))
+			return PTR_ERR(trans);
 		btrfs_set_trans_block_group(trans, inode);
 		ret = btrfs_commit_transaction(trans, root);
 	}
@@ -3872,7 +3889,8 @@ void btrfs_dirty_inode(struct inode *ino
 	struct btrfs_trans_handle *trans;
 
 	trans = btrfs_join_transaction(root, 1);
-	BTRFS_UERROR(!trans);
+	if (IS_ERR(trans))
+		return;
 	btrfs_set_trans_block_group(trans, inode);
 	btrfs_update_inode(trans, root, inode);
 	btrfs_end_transaction(trans, root);
@@ -4166,9 +4184,10 @@ static int btrfs_mknod(struct inode *dir
 		return err;
 
 	trans = btrfs_start_transaction(root, 1);
-	err = -ENOMEM;
-	if (!trans)
-		goto fail;
+	if (IS_ERR(trans)) {
+		btrfs_unreserve_metadata_space(root, 5);
+		return PTR_ERR(trans);
+	}
 	btrfs_set_trans_block_group(trans, dir);
 
 	err = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid);
@@ -4237,9 +4256,10 @@ static int btrfs_create(struct inode *di
 		return err;
 
 	trans = btrfs_start_transaction(root, 1);
-	err = -ENOMEM;
-	if (!trans)
-		goto fail;
+	if (IS_ERR(trans)) {
+		btrfs_unreserve_metadata_space(root, 5);
+		return PTR_ERR(trans);
+	}
 	btrfs_set_trans_block_group(trans, dir);
 
 	err = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid);
@@ -4318,7 +4338,12 @@ static int btrfs_link(struct dentry *old
 		goto fail;
 
 	trans = btrfs_start_transaction(root, 1);
-	BTRFS_UERROR(!trans);
+	if (IS_ERR(trans)) {
+		btrfs_dec_nlink(inode);
+		BTRFS_I(dir)->index_cnt = index;
+		err = PTR_ERR(trans);
+		goto fail;
+	}
 
 	btrfs_set_trans_block_group(trans, dir);
 	atomic_inc(&inode->i_count);
@@ -4367,8 +4392,8 @@ static int btrfs_mkdir(struct inode *dir
 		return err;
 
 	trans = btrfs_start_transaction(root, 1);
-	if (!trans) {
-		err = -ENOMEM;
+	if (IS_ERR(trans)) {
+		err = PTR_ERR(trans);
 		goto out_unlock;
 	}
 	btrfs_set_trans_block_group(trans, dir);
@@ -4686,7 +4711,7 @@ again:
 				em = NULL;
 				btrfs_release_path(root, path);
 				trans = btrfs_join_transaction(root, 1);
-				BTRFS_UERROR(!trans);
+				BTRFS_UERROR(IS_ERR(trans));
 				goto again;
 			}
 			map = kmap(page);
@@ -4892,8 +4917,10 @@ static void btrfs_invalidatepage(struct
 		 * for the finish_ordered_io
 		 */
 		if (TestClearPagePrivate2(page)) {
-			btrfs_finish_ordered_io(page->mapping->host,
-						page_start, page_end);
+			int ret;
+			ret = btrfs_finish_ordered_io(page->mapping->host,
+						      page_start, page_end);
+			BTRFS_UERROR(ret);
 		}
 		btrfs_put_ordered_extent(ordered);
 		lock_extent(tree, page_start, page_end, GFP_NOFS);
@@ -5042,7 +5069,7 @@ static void btrfs_truncate(struct inode
 	struct btrfs_root *root = BTRFS_I(inode)->root;
 	int ret;
 	struct btrfs_trans_handle *trans;
-	unsigned long nr;
+	unsigned long nr = 0;
 	u64 mask = root->sectorsize - 1;
 
 	if (!S_ISREG(inode->i_mode))
@@ -5056,7 +5083,7 @@ static void btrfs_truncate(struct inode
 	btrfs_wait_ordered_range(inode, inode->i_size & (~mask), (u64)-1);
 
 	trans = btrfs_start_transaction(root, 1);
-	BTRFS_UERROR(!trans);
+	BTRFS_UERROR(IS_ERR(trans));
 
 	/*
 	 * setattr is responsible for setting the ordered_data_close flag,
@@ -5329,7 +5356,10 @@ static int btrfs_rename(struct inode *ol
 		down_read(&root->fs_info->subvol_sem);
 
 	trans = btrfs_start_transaction(root, 1);
-	BTRFS_UERROR(!trans);
+	if (IS_ERR(trans)) {
+		ret = PTR_ERR(trans);
+		goto out_fail_notrans;
+	}
 	btrfs_set_trans_block_group(trans, new_dir);
 
 	if (dest != root)
@@ -5425,6 +5455,8 @@ static int btrfs_rename(struct inode *ol
 out_fail:
 	btrfs_end_transaction_throttle(trans, root);
 
+out_fail_notrans:
+
 	if (old_inode->i_ino == BTRFS_FIRST_FREE_OBJECTID)
 		up_read(&root->fs_info->subvol_sem);
 
@@ -5510,9 +5542,10 @@ static int btrfs_symlink(struct inode *d
 		return err;
 
 	trans = btrfs_start_transaction(root, 1);
-	err = -ENOMEM;
-	if (!trans)
-		goto out_fail;
+	if (IS_ERR(trans)) {
+		btrfs_unreserve_metadata_space(root, 5);
+		return PTR_ERR(trans);
+	}
 	btrfs_set_trans_block_group(trans, dir);
 
 	err = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid);
@@ -5592,7 +5625,6 @@ static int btrfs_symlink(struct inode *d
 out_unlock:
 	nr = trans->blocks_used;
 	btrfs_end_transaction_throttle(trans, root);
-out_fail:
 	btrfs_unreserve_metadata_space(root, 5);
 	if (drop_inode) {
 		inode_dec_link_count(inode);
@@ -5698,8 +5730,8 @@ static long btrfs_fallocate(struct inode
 		struct btrfs_ordered_extent *ordered;
 
 		trans = btrfs_start_transaction(BTRFS_I(inode)->root, 1);
-		if (!trans) {
-			ret = -EIO;
+		if (IS_ERR(trans)) {
+			ret = PTR_ERR(trans);
 			goto out_free;
 		}
 
@@ -5735,7 +5767,7 @@ static long btrfs_fallocate(struct inode
 	while (1) {
 		em = btrfs_get_extent(inode, NULL, 0, cur_offset,
 				      alloc_end - cur_offset, 0);
-		BUG_ON(IS_ERR(em) || !em);
+		BTRFS_UERROR(IS_ERR(em) || !em);
 		last_byte = min(extent_map_end(em), alloc_end);
 		last_byte = (last_byte + mask) & ~mask;
 		if (em->block_start == EXTENT_MAP_HOLE) {
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -172,6 +172,12 @@ static int btrfs_ioctl_setflags(struct f
 	if (ret)
 		goto out_unlock;
 
+	trans = btrfs_join_transaction(root, 1);
+	if (IS_ERR(trans)) {
+		ret = PTR_ERR(trans);
+		goto out_drop_write;
+	}
+
 	if (flags & FS_SYNC_FL)
 		ip->flags |= BTRFS_INODE_SYNC;
 	else
@@ -197,10 +203,6 @@ static int btrfs_ioctl_setflags(struct f
 	else
 		ip->flags &= ~BTRFS_INODE_DIRSYNC;
 
-
-	trans = btrfs_join_transaction(root, 1);
-	BTRFS_UERROR(!trans);
-
 	ret = btrfs_update_inode(trans, root, inode);
 	BUG_ON(ret);
 
@@ -208,10 +210,11 @@ static int btrfs_ioctl_setflags(struct f
 	inode->i_ctime = CURRENT_TIME;
 	btrfs_end_transaction(trans, root);
 
+out_drop_write:
 	mnt_drop_write(file->f_path.mnt);
- out_unlock:
+out_unlock:
 	mutex_unlock(&inode->i_mutex);
-	return 0;
+	return ret;
 }
 
 static int btrfs_ioctl_getversion(struct file *file, int __user *arg)
@@ -232,6 +235,7 @@ static noinline int create_subvol(struct
 	struct extent_buffer *leaf;
 	struct btrfs_root *new_root;
 	struct inode *dir = dentry->d_parent->d_inode;
+	struct inode *inode;
 	int ret;
 	int err;
 	u64 objectid;
@@ -250,7 +254,10 @@ static noinline int create_subvol(struct
 		return ret;
 
 	trans = btrfs_start_transaction(root, 1);
-	BTRFS_UERROR(!trans);
+	if (IS_ERR(trans)) {
+		btrfs_unreserve_metadata_space(root, 6);
+		return PTR_ERR(trans);
+	}
 
 	ret = btrfs_find_free_objectid(trans, root->fs_info->tree_root,
 				       0, &objectid);
@@ -312,7 +319,7 @@ static noinline int create_subvol(struct
 
 	key.offset = (u64)-1;
 	new_root = btrfs_read_fs_root_no_name(root->fs_info, &key);
-	BUG_ON(IS_ERR(new_root));
+	BTRFS_UERROR(IS_ERR(new_root));
 
 	btrfs_record_root_in_trans(trans, new_root);
 
@@ -340,13 +347,14 @@ static noinline int create_subvol(struct
 
 	BUG_ON(ret);
 
-	d_instantiate(dentry, btrfs_lookup_dentry(dir, dentry));
+	inode = btrfs_lookup_dentry(dir, dentry);
+	BTRFS_UERROR(IS_ERR(inode));
+	d_instantiate(dentry, inode);
 fail:
 	nr = trans->blocks_used;
 	err = btrfs_commit_transaction(trans, root);
 	if (err && !ret)
 		ret = err;
-
 	btrfs_unreserve_metadata_space(root, 6);
 	btrfs_btree_balance_dirty(root, nr);
 	return ret;
@@ -358,7 +366,6 @@ static int create_snapshot(struct btrfs_
 	struct btrfs_pending_snapshot *pending_snapshot;
 	struct btrfs_trans_handle *trans;
 	int ret = 0;
-	int err;
 	unsigned long nr = 0;
 
 	if (!root->ref_cows)
@@ -391,11 +398,16 @@ static int create_snapshot(struct btrfs_
 	pending_snapshot->name[namelen] = '\0';
 	pending_snapshot->dentry = dentry;
 	trans = btrfs_start_transaction(root, 1);
-	BTRFS_UERROR(!trans);
+	if (IS_ERR(trans)) {
+		kfree(pending_snapshot->name);
+		kfree(pending_snapshot);
+		ret = PTR_ERR(trans);
+		goto fail_unlock;
+	}
 	pending_snapshot->root = root;
 	list_add(&pending_snapshot->list,
 		 &trans->transaction->pending_snapshots);
-	err = btrfs_commit_transaction(trans, root);
+	ret = btrfs_commit_transaction(trans, root);
 
 fail_unlock:
 	btrfs_btree_balance_dirty(root, nr);
@@ -638,10 +650,15 @@ static noinline int btrfs_ioctl_resize(s
 		device->name, (unsigned long long)new_size);
 
 	if (new_size > old_size) {
+		int err;
 		trans = btrfs_start_transaction(root, 1);
-		BTRFS_UERROR(!trans);
+		if (IS_ERR(trans)) {
+			ret = PTR_ERR(trans);
+			goto out_unlock;
+		}
 		ret = btrfs_grow_device(trans, device, new_size);
-		btrfs_commit_transaction(trans, root);
+		err = btrfs_commit_transaction(trans, root);
+		ret = ret ?: err;
 	} else {
 		ret = btrfs_shrink_device(device, new_size);
 	}
@@ -805,7 +822,10 @@ static noinline int btrfs_ioctl_snap_des
 		goto out_up_write;
 
 	trans = btrfs_start_transaction(root, 1);
-	BTRFS_UERROR(!trans);
+	if (IS_ERR(trans)) {
+		err = PTR_ERR(trans);
+		goto out_up_write;
+	}
 	ret = btrfs_unlink_subvol(trans, root, dir,
 				dest->root_key.objectid,
 				dentry->d_name.name,
@@ -825,7 +845,7 @@ static noinline int btrfs_ioctl_snap_des
 	BUG_ON(ret);
 
 	ret = btrfs_commit_transaction(trans, root);
-	BUG_ON(ret);
+	BTRFS_UERROR(ret);
 	inode->i_flags |= S_DEAD;
 out_up_write:
 	up_write(&root->fs_info->subvol_sem);
@@ -862,15 +882,16 @@ static int btrfs_ioctl_defrag(struct fil
 			ret = -EPERM;
 			goto out;
 		}
-		btrfs_defrag_root(root, 0);
-		btrfs_defrag_root(root->fs_info->extent_root, 0);
+		ret = btrfs_defrag_root(root, 0);
+		if (!ret)
+			ret = btrfs_defrag_root(root->fs_info->extent_root, 0);
 		break;
 	case S_IFREG:
 		if (!(file->f_mode & FMODE_WRITE)) {
 			ret = -EINVAL;
 			goto out;
 		}
-		btrfs_defrag_file(file);
+		ret = btrfs_defrag_file(file);
 		break;
 	}
 out:
@@ -1026,7 +1047,12 @@ static noinline long btrfs_ioctl_clone(s
 	}
 
 	trans = btrfs_start_transaction(root, 1);
-	BTRFS_UERROR(!trans);
+	if (IS_ERR(trans)) {
+		ret = PTR_ERR(trans);
+		btrfs_release_path(root, path);
+		unlock_extent(&BTRFS_I(src)->io_tree, off, off+len, GFP_NOFS);
+		goto out_unlock;
+	}
 
 	/* punch hole in destination first */
 	btrfs_drop_extents(trans, root, inode, off, off + len,
@@ -1255,10 +1281,11 @@ static long btrfs_ioctl_trans_start(stru
 	root->fs_info->open_ioctl_trans++;
 	mutex_unlock(&root->fs_info->trans_mutex);
 
-	ret = -ENOMEM;
 	trans = btrfs_start_ioctl_transaction(root, 0);
-	if (!trans)
+	if (IS_ERR(trans)) {
+		ret = PTR_ERR(trans);
 		goto out_drop;
+	}
 
 	file->private_data = trans;
 	return 0;
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -398,7 +398,8 @@ struct btrfs_root *find_tree_root(struct
 	BUG_ON(root_objectid == BTRFS_TREE_RELOC_OBJECTID);
 
 	root = read_fs_root(rc->extent_root->fs_info, root_objectid);
-	BUG_ON(IS_ERR(root));
+	if (IS_ERR(root))
+		return ERR_CAST(root);
 
 	if (root->ref_cows &&
 	    generation != btrfs_root_generation(&root->root_item))
@@ -592,6 +593,7 @@ again:
 				ref0 = btrfs_item_ptr(eb, path1->slots[0],
 						struct btrfs_extent_ref_v0);
 				root = find_tree_root(rc, eb, ref0);
+				BTRFS_UERROR(IS_ERR(root));
 				if (root)
 					cur->root = root;
 				else
@@ -1638,12 +1640,20 @@ static noinline_for_stack int merge_relo
 
 	if (level == 0 && rc->stage == UPDATE_DATA_PTRS) {
 		trans = btrfs_start_transaction(root, 1);
-		BTRFS_UERROR(!trans);
+		if (IS_ERR(trans)) {
+			extent_buffer_put(reloc_root->node);
+		}
+		BTRFS_UERROR(IS_ERR(trans));
 
 		leaf = path->nodes[0];
 		btrfs_item_key_to_cpu(leaf, &key, 0);
 		btrfs_release_path(reloc_root, path);
 
+		if (IS_ERR(trans)) {
+			err = PTR_ERR(trans);
+			goto out;
+		}
+
 		ret = btrfs_search_slot(trans, root, &key, path, 0, 1);
 		if (ret < 0) {
 			err = ret;
@@ -1665,7 +1675,7 @@ static noinline_for_stack int merge_relo
 		leaf = NULL;
 		replaced = 0;
 		trans = btrfs_start_transaction(root, 1);
-		BTRFS_UERROR(!trans);
+		BTRFS_UERROR(IS_ERR(trans));
 		max_level = level;
 
 		ret = walk_down_reloc_tree(reloc_root, path, &level);
@@ -1788,6 +1798,7 @@ static void merge_func(struct btrfs_work
 	struct btrfs_root *root;
 	struct btrfs_root *reloc_root;
 	struct async_merge *async;
+	int ret = 0;
 
 	async = container_of(work, struct async_merge, work);
 	reloc_root = async->root;
@@ -1795,18 +1806,20 @@ static void merge_func(struct btrfs_work
 	if (btrfs_root_refs(&reloc_root->root_item) > 0) {
 		root = read_fs_root(reloc_root->fs_info,
 				    reloc_root->root_key.offset);
-		BUG_ON(IS_ERR(root));
+		BTRFS_UERROR(IS_ERR(root));
 		BUG_ON(root->reloc_root != reloc_root);
 
-		merge_reloc_root(async->rc, root);
+		ret = merge_reloc_root(async->rc, root);
+		BTRFS_UERROR(ret);
 
 		trans = btrfs_start_transaction(root, 1);
-		BTRFS_UERROR(!trans);
+		BTRFS_UERROR(IS_ERR(trans));
 		btrfs_update_reloc_root(trans, root);
 		btrfs_end_transaction(trans, root);
 	}
 
-	btrfs_drop_snapshot(reloc_root, 0);
+	ret = btrfs_drop_snapshot(reloc_root, 0);
+	BTRFS_UERROR(ret);
 
 	if (atomic_dec_and_test(async->num_pending))
 		complete(async->done);
@@ -1868,7 +1881,8 @@ static int record_reloc_root_in_trans(st
 		return 0;
 
 	root = read_fs_root(reloc_root->fs_info, reloc_root->root_key.offset);
-	BUG_ON(IS_ERR(root));
+	if (IS_ERR(root))
+		return PTR_ERR(root);
 	BUG_ON(root->reloc_root != reloc_root);
 
 	return btrfs_record_root_in_trans(trans, root);
@@ -1888,6 +1902,7 @@ static struct btrfs_root *__select_one_r
 	struct btrfs_root *root;
 	int index;
 	int loop = 0;
+	int ret;
 again:
 	index = 0;
 	next = node;
@@ -1907,7 +1922,11 @@ again:
 		}
 
 		if (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) {
-			record_reloc_root_in_trans(trans, root);
+			ret = record_reloc_root_in_trans(trans, root);
+			if (ret) {
+				root = ERR_PTR(ret);
+				goto out;
+			}
 			break;
 		}
 
@@ -1946,6 +1965,7 @@ skip:
 	else
 		*nr = 0;
 
+out:
 	return root;
 }
 
@@ -2026,6 +2046,7 @@ static int do_relocation(struct btrfs_tr
 		root = select_reloc_root(trans, upper, edges, &nr);
 		if (!root)
 			continue;
+		BTRFS_UERROR(IS_ERR(root));
 
 		if (upper->eb && !upper->locked)
 			drop_node_buffer(upper);
@@ -2372,6 +2393,11 @@ static int relocate_tree_block(struct bt
 	int ret;
 
 	root = select_one_root(trans, node);
+	if (unlikely(IS_ERR(root))) {
+		ret = PTR_ERR(root);
+		goto out;
+	}
+
 	if (unlikely(!root)) {
 		rc->found_old_snapshot = 1;
 		update_processed_blocks(rc, node);
@@ -3109,6 +3135,7 @@ int add_data_references(struct reloc_con
 			dref = (struct btrfs_extent_data_ref *)(&iref->offset);
 			ret = find_data_references(rc, extent_key,
 						   eb, dref, blocks);
+			BTRFS_UERROR(ret);
 		} else {
 			BUG();
 		}
@@ -3294,12 +3321,18 @@ static noinline_for_stack int relocate_b
 	set_reloc_control(rc);
 
 	trans = btrfs_start_transaction(rc->extent_root, 1);
-	BTRFS_UERROR(!trans);
+	BTRFS_UERROR(IS_ERR(trans));
+	if (IS_ERR(trans)) {
+		rc->create_reloc_root = 0;
+		smp_mb();
+		unset_reloc_control(rc);
+		return PTR_ERR(trans);
+	}
 	btrfs_commit_transaction(trans, rc->extent_root);
 
 	while (1) {
 		trans = btrfs_start_transaction(rc->extent_root, 1);
-		BTRFS_UERROR(!trans);
+		BTRFS_UERROR(IS_ERR(trans));
 
 		ret = find_next_extent(trans, rc, path);
 		if (ret < 0)
@@ -3356,6 +3389,7 @@ static noinline_for_stack int relocate_b
 		} else if (rc->stage == UPDATE_DATA_PTRS &&
 			 (flags & BTRFS_EXTENT_FLAG_DATA)) {
 			ret = add_data_references(rc, &key, path, &blocks);
+			BTRFS_UERROR(ret);
 		} else {
 			btrfs_release_path(rc->extent_root, path);
 			ret = 0;
@@ -3410,7 +3444,7 @@ static noinline_for_stack int relocate_b
 
 	if (rc->extents_found > 0) {
 		trans = btrfs_start_transaction(rc->extent_root, 1);
-		BTRFS_UERROR(!trans);
+		BTRFS_UERROR(IS_ERR(trans));
 		btrfs_commit_transaction(trans, rc->extent_root);
 	}
 
@@ -3420,7 +3454,7 @@ static noinline_for_stack int relocate_b
 
 	/* get rid of pinned extents */
 	trans = btrfs_start_transaction(rc->extent_root, 1);
-	BTRFS_UERROR(!trans);
+	BTRFS_UERROR(IS_ERR(trans));
 	btrfs_commit_transaction(trans, rc->extent_root);
 
 	return err;
@@ -3476,7 +3510,8 @@ static struct inode *create_reloc_inode(
 		return ERR_CAST(root);
 
 	trans = btrfs_start_transaction(root, 1);
-	BTRFS_UERROR(!trans);
+	if (IS_ERR(trans))
+		return ERR_CAST(trans);
 
 	err = btrfs_find_free_objectid(trans, root, objectid, &objectid);
 	if (err)
@@ -3531,9 +3566,14 @@ int btrfs_relocate_block_group(struct bt
 			   fs_info->thread_pool_size, NULL);
 
 	rc->extent_root = extent_root;
-	btrfs_prepare_block_group_relocation(extent_root, rc->block_group);
+	ret = btrfs_prepare_block_group_relocation(extent_root,
+						   rc->block_group);
+	if (ret)
+		goto out;
 
 	rc->data_inode = create_reloc_inode(fs_info, rc->block_group);
+	/* We can't clean up from btrfs_prepare_block_group_relocation */
+	BTRFS_UERROR(IS_ERR(rc->data_inode));
 	if (IS_ERR(rc->data_inode)) {
 		err = PTR_ERR(rc->data_inode);
 		rc->data_inode = NULL;
@@ -3553,7 +3593,8 @@ int btrfs_relocate_block_group(struct bt
 
 		mutex_lock(&fs_info->cleaner_mutex);
 
-		btrfs_clean_old_snapshots(fs_info->tree_root);
+		ret = btrfs_clean_old_snapshots(fs_info->tree_root);
+		BTRFS_UERROR(ret);
 		ret = relocate_block_group(rc);
 
 		mutex_unlock(&fs_info->cleaner_mutex);
@@ -3610,7 +3651,8 @@ static noinline_for_stack int mark_garba
 	int ret;
 
 	trans = btrfs_start_transaction(root->fs_info->tree_root, 1);
-	BTRFS_UERROR(!trans);
+	if (IS_ERR(trans))
+		return PTR_ERR(trans);
 
 	memset(&root->root_item.drop_progress, 0,
 		sizeof(root->root_item.drop_progress));
@@ -3689,7 +3731,11 @@ int btrfs_recover_relocation(struct btrf
 					err = ret;
 					goto out;
 				}
-				mark_garbage_root(reloc_root);
+				ret = mark_garbage_root(reloc_root);
+				if (ret) {
+					err = ret;
+					goto out;
+				}
 			}
 		}
 
@@ -3738,16 +3784,22 @@ int btrfs_recover_relocation(struct btrf
 	}
 
 	trans = btrfs_start_transaction(rc->extent_root, 1);
-	BTRFS_UERROR(!trans);
-	btrfs_commit_transaction(trans, rc->extent_root);
+	if (IS_ERR(trans)) {
+		err = PTR_ERR(trans);
+		unset_reloc_control(rc);
+		goto out;
+	}
+	err = btrfs_commit_transaction(trans, rc->extent_root);
 
 	merge_reloc_roots(rc);
 
 	unset_reloc_control(rc);
 
 	trans = btrfs_start_transaction(rc->extent_root, 1);
-	BTRFS_UERROR(!trans);
-	btrfs_commit_transaction(trans, rc->extent_root);
+	if (IS_ERR(trans)) {
+		err = PTR_ERR(trans);
+		goto out;
+	err = btrfs_commit_transaction(trans, rc->extent_root);
 out:
 	if (rc) {
 		btrfs_stop_workers(&rc->workers);
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -417,8 +417,11 @@ int btrfs_sync_fs(struct super_block *sb
 	btrfs_wait_ordered_extents(root, 0);
 
 	trans = btrfs_start_transaction(root, 1);
-	BTRFS_UERROR(!trans);
-	ret = btrfs_commit_transaction(trans, root);
+	if (!IS_ERR(trans))
+		ret = btrfs_commit_transaction(trans, root);
+	else
+		ret = PTR_ERR(trans);
+
 	return ret;
 }
 
@@ -601,7 +604,8 @@ static int btrfs_remount(struct super_bl
 
 		/* recover relocation */
 		ret = btrfs_recover_relocation(root);
-		WARN_ON(ret);
+		if (ret)
+			return ret;
 
 		ret = btrfs_cleanup_fs_roots(root->fs_info);
 		WARN_ON(ret);
@@ -609,7 +613,7 @@ static int btrfs_remount(struct super_bl
 		sb->s_flags &= ~MS_RDONLY;
 	}
 
-	return 0;
+	return ret;
 }
 
 static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -181,7 +181,10 @@ static struct btrfs_trans_handle *start_
 	    ((wait == 1 && !root->fs_info->open_ioctl_trans) || wait == 2))
 		wait_current_trans(root);
 	ret = join_transaction(root);
-	BUG_ON(ret);
+	if (ret) {
+		h = ERR_PTR(ret);
+		goto out;
+	}
 
 	h->transid = root->fs_info->running_transaction->transid;
 	h->transaction = root->fs_info->running_transaction;
@@ -197,6 +200,7 @@ static struct btrfs_trans_handle *start_
 
 	root->fs_info->running_transaction->use_count++;
 	record_root_in_trans(h, root);
+out:
 	mutex_unlock(&root->fs_info->trans_mutex);
 	return h;
 }
@@ -629,8 +633,11 @@ int btrfs_defrag_root(struct btrfs_root
 	smp_mb();
 	if (root->defrag_running)
 		return 0;
+
 	trans = btrfs_start_transaction(root, 1);
-	BTRFS_UERROR(!trans);
+	if (IS_ERR(trans))
+		return PTR_ERR(trans);
+
 	while (1) {
 		root->defrag_running = 1;
 		ret = btrfs_defrag_leaves(trans, root, cacheonly);
@@ -640,14 +647,16 @@ int btrfs_defrag_root(struct btrfs_root
 		cond_resched();
 
 		trans = btrfs_start_transaction(root, 1);
-		BTRFS_UERROR(!trans);
+		if (IS_ERR(trans))
+			ret = PTR_ERR(trans);
 		if (root->fs_info->closing || ret != -EAGAIN)
 			break;
 	}
 	root->defrag_running = 0;
 	smp_mb();
-	btrfs_end_transaction(trans, root);
-	return 0;
+	if (!IS_ERR(trans))
+		btrfs_end_transaction(trans, root);
+	return ret;
 }
 
 #if 0
@@ -814,7 +823,8 @@ static noinline int finish_pending_snaps
 	parent_inode = pending->dentry->d_parent->d_inode;
 	parent_root = BTRFS_I(parent_inode)->root;
 	trans = btrfs_join_transaction(parent_root, 1);
-	BTRFS_UERROR(!trans);
+	if (IS_ERR(trans))
+		return PTR_ERR(trans);
 
 	/*
 	 * insert the directory item
@@ -842,6 +852,7 @@ static noinline int finish_pending_snaps
 	BUG_ON(ret);
 
 	inode = btrfs_lookup_dentry(parent_inode, pending->dentry);
+	BTRFS_UERROR(IS_ERR(inode));
 	d_instantiate(pending->dentry, inode);
 fail:
 	btrfs_end_transaction(trans, fs_info->fs_root);
@@ -876,7 +887,7 @@ static noinline int finish_pending_snaps
 		pending = list_entry(head->next,
 				     struct btrfs_pending_snapshot, list);
 		ret = finish_pending_snapshot(fs_info, pending);
-		BUG_ON(ret);
+		BTRFS_UERROR(ret);
 		list_del(&pending->list);
 		kfree(pending->name);
 		kfree(pending);
@@ -1099,7 +1110,8 @@ int btrfs_commit_transaction(struct btrf
 	btrfs_finish_extent_commit(trans, root);
 
 	/* do the directory inserts of any pending snapshot creations */
-	finish_pending_snapshots(trans, root->fs_info);
+	ret = finish_pending_snapshots(trans, root->fs_info);
+	BTRFS_UERROR(ret);
 
 	mutex_lock(&root->fs_info->trans_mutex);
 
@@ -1128,6 +1140,7 @@ int btrfs_clean_old_snapshots(struct btr
 {
 	LIST_HEAD(list);
 	struct btrfs_fs_info *fs_info = root->fs_info;
+	int ret = 0;
 
 	mutex_lock(&fs_info->trans_mutex);
 	list_splice_init(&fs_info->dead_roots, &list);
@@ -1139,9 +1152,10 @@ int btrfs_clean_old_snapshots(struct btr
 
 		if (btrfs_header_backref_rev(root->node) <
 		    BTRFS_MIXED_BACKREF_REV)
-			btrfs_drop_snapshot(root, 0);
+			ret = btrfs_drop_snapshot(root, 0);
 		else
-			btrfs_drop_snapshot(root, 1);
+			ret = btrfs_drop_snapshot(root, 1);
+		BTRFS_UERROR(ret);
 	}
 	return 0;
 }
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -3024,7 +3024,10 @@ int btrfs_recover_log_trees(struct btrfs
 	BUG_ON(!path);
 
 	trans = btrfs_start_transaction(fs_info->tree_root, 1);
-	BTRFS_UERROR(!trans);
+	if (IS_ERR(trans)) {
+		ret = PTR_ERR(trans);
+		goto fail;
+	}
 
 	wc.trans = trans;
 	wc.pin = 1;
@@ -3053,8 +3056,7 @@ again:
 
 		log = btrfs_read_fs_root_no_radix(log_root_tree,
 						  &found_key);
-		BUG_ON(IS_ERR(log));
-
+		BTRFS_UERROR(IS_ERR(log));
 
 		tmp_key.objectid = found_key.offset;
 		tmp_key.type = BTRFS_ROOT_ITEM_KEY;
@@ -3098,6 +3100,7 @@ again:
 		goto again;
 	}
 
+fail:
 	btrfs_free_path(path);
 
 	free_extent_buffer(log_root_tree->node);
@@ -3105,10 +3108,11 @@ again:
 	fs_info->log_root_recovering = 0;
 
 	/* step 4: commit the transaction, which also unpins the blocks */
-	btrfs_commit_transaction(trans, fs_info->tree_root);
+	if (!ret)
+		ret = btrfs_commit_transaction(trans, fs_info->tree_root);
 
 	kfree(log_root_tree);
-	return 0;
+	return ret;
 }
 
 /*
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -1078,7 +1078,7 @@ out:
 static int btrfs_rm_dev_item(struct btrfs_root *root,
 			     struct btrfs_device *device)
 {
-	int ret;
+	int ret, err;
 	struct btrfs_path *path;
 	struct btrfs_key key;
 	struct btrfs_trans_handle *trans;
@@ -1090,7 +1090,10 @@ static int btrfs_rm_dev_item(struct btrf
 		return -ENOMEM;
 
 	trans = btrfs_start_transaction(root, 1);
-	BTRFS_UERROR(!trans);
+	if (IS_ERR(trans)) {
+		btrfs_free_path(path);
+		return PTR_ERR(trans);
+	}
 	key.objectid = BTRFS_DEV_ITEMS_OBJECTID;
 	key.type = BTRFS_DEV_ITEM_KEY;
 	key.offset = device->devid;
@@ -1111,7 +1114,8 @@ static int btrfs_rm_dev_item(struct btrf
 out:
 	btrfs_free_path(path);
 	unlock_chunks(root);
-	btrfs_commit_transaction(trans, root);
+	err = btrfs_commit_transaction(trans, root);
+	ret = ret ?: err;
 	return ret;
 }
 
@@ -1429,7 +1433,7 @@ int btrfs_init_new_device(struct btrfs_r
 	struct super_block *sb = root->fs_info->sb;
 	u64 total_bytes;
 	int seeding_dev = 0;
-	int ret = 0;
+	int err, ret = 0;
 
 	if ((sb->s_flags & MS_RDONLY) && !root->fs_info->fs_devices->seeding)
 		return -EINVAL;
@@ -1481,7 +1485,12 @@ int btrfs_init_new_device(struct btrfs_r
 	}
 
 	trans = btrfs_start_transaction(root, 1);
-	BTRFS_UERROR(!trans);
+	if (IS_ERR(trans)) {
+		kfree(device->name);
+		kfree(device);
+		ret = PTR_ERR(trans);
+		goto error;
+	}
 	lock_chunks(root);
 
 	device->barriers = 1;
@@ -1550,14 +1559,15 @@ int btrfs_init_new_device(struct btrfs_r
 	btrfs_clear_space_info_full(root->fs_info);
 
 	unlock_chunks(root);
-	btrfs_commit_transaction(trans, root);
+	err = btrfs_commit_transaction(trans, root);
+	ret = ret ?: err;
 
 	if (seeding_dev) {
 		mutex_unlock(&uuid_mutex);
 		up_write(&sb->s_umount);
 
 		ret = btrfs_relocate_sys_chunks(root);
-		BUG_ON(ret);
+		BTRFS_UERROR(ret);
 	}
 out:
 	mutex_unlock(&root->fs_info->volume_mutex);
@@ -1746,10 +1756,11 @@ static int btrfs_relocate_chunk(struct b
 
 	/* step one, relocate all the extents inside this chunk */
 	ret = btrfs_relocate_block_group(extent_root, chunk_offset);
-	BUG_ON(ret);
+	if (ret)
+		return ret;
 
 	trans = btrfs_start_transaction(root, 1);
-	BTRFS_UERROR(!trans);
+	BTRFS_UERROR(IS_ERR(trans));
 
 	lock_chunks(root);
 
@@ -1855,8 +1866,8 @@ again:
 						   found_key.offset);
 			if (ret == -ENOSPC)
 				failed++;
-			else if (ret)
-				BUG();
+			else
+				BTRFS_UERROR(ret);
 		}
 
 		if (found_key.offset == 0)
@@ -1918,10 +1929,11 @@ int btrfs_balance(struct btrfs_root *dev
 		ret = btrfs_shrink_device(device, old_size - size_to_free);
 		if (ret == -ENOSPC)
 			break;
-		BUG_ON(ret);
+		else if (ret)
+			return ret;
 
 		trans = btrfs_start_transaction(dev_root, 1);
-		BTRFS_UERROR(!trans);
+		BTRFS_UERROR(IS_ERR(trans));
 
 		ret = btrfs_grow_device(trans, device, old_size);
 		BUG_ON(ret);
@@ -1971,7 +1983,7 @@ int btrfs_balance(struct btrfs_root *dev
 					   chunk_root->root_key.objectid,
 					   found_key.objectid,
 					   found_key.offset);
-		BUG_ON(ret && ret != -ENOSPC);
+		BTRFS_UERROR(ret && ret != -ENOSPC);
 		key.offset = found_key.offset - 1;
 	}
 	ret = 0;
@@ -2090,8 +2102,8 @@ again:
 
 	/* Shrinking succeeded, else we would be at "done". */
 	trans = btrfs_start_transaction(root, 1);
-	if (!trans) {
-		ret = -ENOMEM;
+	if (IS_ERR(trans)) {
+		ret = PTR_ERR(trans);
 		goto done;
 	}
 	lock_chunks(root);
--- a/fs/btrfs/xattr.c
+++ b/fs/btrfs/xattr.c
@@ -99,7 +99,8 @@ int __btrfs_setxattr(struct inode *inode
 		return -ENOMEM;
 
 	trans = btrfs_join_transaction(root, 1);
-	BTRFS_UERROR(!trans);
+	if (IS_ERR(trans))
+		return PTR_ERR(trans);
 	btrfs_set_trans_block_group(trans, inode);
 
 	/* first lets see if we already have this xattr */


  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 ` [patch 07/10] btrfs: handle kmalloc call path failures Jeff Mahoney
2009-11-04 19:03 ` [patch 08/10] btrfs: annotate btrfs_{start,join}_transaction failures Jeff Mahoney
2009-11-04 19:03 ` Jeff Mahoney [this message]
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.604999770@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.