diff mbox

[09/10] btrfs: handle btrfs_{start,join}_transaction call path failures

Message ID 20091104190434.604999770@suse.com (mailing list archive)
State Deferred
Headers show

Commit Message

Jeff Mahoney Nov. 4, 2009, 7:03 p.m. UTC
None
diff mbox

Patch

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 */