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.

 It also checks every start_transaction call. Where the error can be
 handled simply, we clean up state and return an error.

 If the recovery is more involved, we BUG. This isn't a change in
 functionality since we'd Oops anyway. The more complex recovery should
 be done in separate patches, so this is really just to annotate where
 that needs to happen.

Signed-off-by: Jeff Mahoney <je...@suse.com>
---
 fs/btrfs/disk-io.c     |    4 +++
 fs/btrfs/extent-tree.c |   24 ++++++++++++++----
 fs/btrfs/extent_io.c   |   18 ++++++++-----
 fs/btrfs/file.c        |    9 ++++---
 fs/btrfs/inode.c       |   62 ++++++++++++++++++++++++++++++++++++++---------
 fs/btrfs/ioctl.c       |   34 +++++++++++++++++++++----
 fs/btrfs/super.c       |   11 +++++++-
 fs/btrfs/transaction.c |   23 ++++++++++++++++-
 fs/btrfs/tree-log.c    |    4 +++
 fs/btrfs/volumes.c     |   17 ++++++++++---
 10 files changed, 163 insertions(+), 43 deletions(-)

diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index adda739..c7d4136 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1492,6 +1492,8 @@ static int transaction_kthread(void *arg)
                }
                mutex_unlock(&root->fs_info->trans_mutex);
                trans = btrfs_start_transaction(root, 1);
+               if (IS_ERR(trans))
+                       goto sleep;
                ret = btrfs_commit_transaction(trans, root);
 sleep:
                wake_up_process(root->fs_info->cleaner_kthread);
@@ -2241,10 +2243,12 @@ int btrfs_commit_super(struct btrfs_root *root)
        btrfs_clean_old_snapshots(root);
        mutex_unlock(&root->fs_info->cleaner_mutex);
        trans = btrfs_start_transaction(root, 1);
+       BUG_ON(IS_ERR(trans));
        ret = btrfs_commit_transaction(trans, root);
        BUG_ON(ret);
        /* run commit again to drop the original snapshot */
        trans = btrfs_start_transaction(root, 1);
+       BUG_ON(IS_ERR(trans));
        btrfs_commit_transaction(trans, root);
        ret = btrfs_write_and_wait_transaction(NULL, root);
        BUG_ON(ret);
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 777af73..ad699c2 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -5276,7 +5276,7 @@ int btrfs_drop_dead_reloc_roots(struct btrfs_root *root)
                BUG_ON(reloc_root->commit_root != NULL);
                while (1) {
                        trans = btrfs_join_transaction(root, 1);
-                       BUG_ON(!trans);
+                       BUG_ON(IS_ERR(trans));
 
                        mutex_lock(&root->fs_info->drop_mutex);
                        ret = btrfs_drop_snapshot(trans, reloc_root);
@@ -5334,7 +5334,7 @@ int btrfs_cleanup_reloc_trees(struct btrfs_root *root)
 
        if (found) {
                trans = btrfs_start_transaction(root, 1);
-               BUG_ON(!trans);
+               BUG_ON(IS_ERR(trans));
                ret = btrfs_commit_transaction(trans, root);
                BUG_ON(ret);
        }
@@ -5581,7 +5581,8 @@ static noinline int relocate_one_extent(struct btrfs_root 
*extent_root,
 
 
        trans = btrfs_start_transaction(extent_root, 1);
-       BUG_ON(!trans);
+       if (IS_ERR(trans))
+               return PTR_ERR(trans);
 
        if (extent_key->objectid == 0) {
                ret = del_extent_zero(trans, extent_root, path, extent_key);
@@ -5761,6 +5762,8 @@ static int __alloc_chunk_for_shrink(struct btrfs_root 
*root,
                spin_unlock(&shrink_block_group->lock);
 
                trans = btrfs_start_transaction(root, 1);
+               if (IS_ERR(trans))
+                       return PTR_ERR(trans);
                spin_lock(&shrink_block_group->lock);
 
                new_alloc_flags = update_block_group_flags(root,
@@ -5831,7 +5834,8 @@ static noinline struct inode *create_reloc_inode(struct 
btrfs_fs_info *fs_info,
                return ERR_CAST(root);
 
        trans = btrfs_start_transaction(root, 1);
-       BUG_ON(!trans);
+       if (IS_ERR(trans))
+               return ERR_CAST(trans);
 
        err = btrfs_find_free_objectid(trans, root, objectid, &objectid);
        if (err)
@@ -5943,7 +5947,8 @@ int btrfs_relocate_block_group(struct btrfs_root *root, 
u64 group_start)
        reloc_inode = create_reloc_inode(info, block_group);
        BUG_ON(IS_ERR(reloc_inode));
 
-       __alloc_chunk_for_shrink(root, block_group, 1);
+       ret = __alloc_chunk_for_shrink(root, block_group, 1);
+       BUG_ON(ret);
        set_block_group_readonly(block_group);
 
        btrfs_start_delalloc_inodes(info->tree_root);
@@ -5958,6 +5963,10 @@ again:
        cur_byte = key.objectid;
 
        trans = btrfs_start_transaction(info->tree_root, 1);
+       if (IS_ERR(trans)) {
+               ret = PTR_ERR(trans);
+               goto out;
+       }
        btrfs_commit_transaction(trans, info->tree_root);
 
        mutex_lock(&root->fs_info->cleaner_mutex);
@@ -6008,7 +6017,8 @@ next:
                cur_byte = key.objectid + key.offset;
                btrfs_release_path(root, path);
 
-               __alloc_chunk_for_shrink(root, block_group, 0);
+               ret = __alloc_chunk_for_shrink(root, block_group, 0);
+               BUG_ON(ret);
                ret = relocate_one_extent(root, path, &key, block_group,
                                          reloc_inode, pass);
                BUG_ON(ret < 0);
@@ -6034,6 +6044,7 @@ next:
                if (total_found == skipped && pass > 2) {
                        iput(reloc_inode);
                        reloc_inode = create_reloc_inode(info, block_group);
+                       BUG_ON(IS_ERR(reloc_inode));
                        pass = 0;
                }
                goto again;
@@ -6044,6 +6055,7 @@ next:
 
        /* unpin extents in this range */
        trans = btrfs_start_transaction(info->tree_root, 1);
+       BUG_ON(IS_ERR(trans));
        btrfs_commit_transaction(trans, info->tree_root);
 
        spin_lock(&block_group->lock);
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index ebe6b29..b192a15 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -1848,10 +1848,11 @@ static int submit_one_bio(int rw, struct bio *bio, int 
mirror_num,
 
        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);
+               BUG_ON(ret);
+       } else
                submit_bio(rw, bio);
        if (bio_flagged(bio, BIO_EOPNOTSUPP))
                ret = -EOPNOTSUPP;
@@ -2174,9 +2175,12 @@ static int __extent_writepage(struct page *page, struct 
writeback_control *wbc,
                                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);
+                       BUG_ON(ret);
                        delalloc_start = delalloc_end + 1;
                }
 
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 3e8023e..c5419a4 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -129,8 +129,8 @@ static noinline int dirty_and_release_pages(struct 
btrfs_trans_handle *trans,
 
        lock_extent(io_tree, start_pos, end_of_last_block, GFP_NOFS);
        trans = btrfs_join_transaction(root, 1);
-       if (!trans) {
-               err = -ENOMEM;
+       if (IS_ERR(trans)) {
+               err = PTR_ERR(trans);
                goto out_unlock;
        }
        btrfs_set_trans_block_group(trans, inode);
@@ -1154,6 +1154,7 @@ out_nolock:
 
                if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) {
                        trans = btrfs_start_transaction(root, 1);
+                       BUG_ON(IS_ERR(trans));
                        ret = btrfs_log_dentry_safe(trans, root,
                                                    file->f_dentry);
                        if (ret == 0) {
@@ -1226,8 +1227,8 @@ int btrfs_sync_file(struct file *file, struct dentry 
*dentry, int datasync)
                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;
        }
 
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 3cee77a..18a65f6 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -429,7 +429,7 @@ again:
        }
        if (start == 0) {
                trans = btrfs_join_transaction(root, 1);
-               BUG_ON(!trans);
+               BUG_ON(IS_ERR(trans));
                btrfs_set_trans_block_group(trans, inode);
 
                /* lets try to make an inline extent */
@@ -588,11 +588,12 @@ static noinline int submit_compressed_extents(struct 
inode *inode,
                                    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);
+                       BUG_ON(ret);
 
                        /*
                         * if page_started, cow_file_range inserted an
@@ -725,7 +726,8 @@ static noinline int cow_file_range(struct inode *inode,
        int ret = 0;
 
        trans = btrfs_join_transaction(root, 1);
-       BUG_ON(!trans);
+       if (IS_ERR(trans))
+               return PTR_ERR(trans);
        btrfs_set_trans_block_group(trans, inode);
 
        actual_end = min_t(u64, isize, end + 1);
@@ -987,7 +989,8 @@ static int run_delalloc_nocow(struct inode *inode, struct 
page *locked_page,
        path = btrfs_alloc_path();
        BUG_ON(!path);
        trans = btrfs_join_transaction(root, 1);
-       BUG_ON(!trans);
+       if (IS_ERR(trans))
+               return PTR_ERR(trans);
 
        cow_start = (u64)-1;
        cur_offset = start;
@@ -1954,6 +1957,7 @@ void btrfs_orphan_cleanup(struct btrfs_root *root)
                 */
                if (is_bad_inode(inode)) {
                        trans = btrfs_start_transaction(root, 1);
+                       BUG_ON(IS_ERR(trans));
                        btrfs_orphan_del(trans, inode);
                        btrfs_end_transaction(trans, root);
                        iput(inode);
@@ -2250,6 +2254,10 @@ static int btrfs_unlink(struct inode *dir, struct dentry 
*dentry)
                goto fail;
 
        trans = btrfs_start_transaction(root, 1);
+       if (IS_ERR(trans)) {
+               ret = PTR_ERR(trans);
+               goto fail;
+       }
 
        btrfs_set_trans_block_group(trans, dir);
        ret = btrfs_unlink_inode(trans, root, dir, dentry->d_inode,
@@ -2289,6 +2297,10 @@ static int btrfs_rmdir(struct inode *dir, struct dentry 
*dentry)
                goto fail;
 
        trans = btrfs_start_transaction(root, 1);
+       if (IS_ERR(trans)) {
+               ret = PTR_ERR(trans);
+               goto fail;
+       }
        btrfs_set_trans_block_group(trans, dir);
 
        err = btrfs_orphan_add(trans, inode);
@@ -2837,6 +2849,10 @@ int btrfs_cont_expand(struct inode *inode, loff_t size)
        }
 
        trans = btrfs_start_transaction(root, 1);
+       if (IS_ERR(trans)) {
+               err = PTR_ERR(trans);
+               goto out;
+       }
        btrfs_set_trans_block_group(trans, inode);
 
        cur_offset = hole_start;
@@ -2869,6 +2885,7 @@ int btrfs_cont_expand(struct inode *inode, loff_t size)
        }
 
        btrfs_end_transaction(trans, root);
+out:
        unlock_extent(io_tree, hole_start, block_end - 1, GFP_NOFS);
        return err;
 }
@@ -3607,6 +3624,10 @@ static int btrfs_mknod(struct inode *dir, struct dentry 
*dentry,
                goto fail;
 
        trans = btrfs_start_transaction(root, 1);
+       if (IS_ERR(trans)) {
+               err = PTR_ERR(trans);
+               goto fail;
+       }
        btrfs_set_trans_block_group(trans, dir);
 
        err = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid);
@@ -3669,6 +3690,10 @@ static int btrfs_create(struct inode *dir, struct dentry 
*dentry,
        if (err)
                goto fail;
        trans = btrfs_start_transaction(root, 1);
+       if (IS_ERR(trans)) {
+               err = PTR_ERR(trans);
+               goto fail;
+       }
        btrfs_set_trans_block_group(trans, dir);
 
        err = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid);
@@ -3741,6 +3766,11 @@ static int btrfs_link(struct dentry *old_dentry, struct 
inode *dir,
                goto fail;
 
        trans = btrfs_start_transaction(root, 1);
+       if (IS_ERR(trans)) {
+               BTRFS_I(dir)->index_cnt = index;
+               err = PTR_ERR(trans);
+               goto fail;
+       }
 
        btrfs_set_trans_block_group(trans, dir);
        atomic_inc(&inode->i_count);
@@ -3784,13 +3814,13 @@ static int btrfs_mkdir(struct inode *dir, struct dentry 
*dentry, int mode)
                goto out_unlock;
 
        trans = btrfs_start_transaction(root, 1);
-       btrfs_set_trans_block_group(trans, dir);
-
        if (IS_ERR(trans)) {
                err = PTR_ERR(trans);
                goto out_unlock;
        }
 
+       btrfs_set_trans_block_group(trans, dir);
+
        err = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid);
        if (err) {
                err = -ENOSPC;
@@ -4400,7 +4430,7 @@ static void btrfs_truncate(struct inode *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))
@@ -4412,6 +4442,8 @@ static void btrfs_truncate(struct inode *inode)
        btrfs_wait_ordered_range(inode, inode->i_size & (~mask), (u64)-1);
 
        trans = btrfs_start_transaction(root, 1);
+       if (IS_ERR(trans))
+               return;
        btrfs_set_trans_block_group(trans, inode);
        btrfs_i_size_write(inode, inode->i_size);
 
@@ -4636,6 +4668,10 @@ static int btrfs_rename(struct inode *old_dir, struct 
dentry *old_dentry,
                goto out_unlock;
 
        trans = btrfs_start_transaction(root, 1);
+       if (IS_ERR(trans)) {
+               ret = PTR_ERR(trans);
+               goto out_unlock;
+       }
 
        btrfs_set_trans_block_group(trans, new_dir);
 
@@ -4754,6 +4790,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry 
*dentry,
                goto out_fail;
 
        trans = btrfs_start_transaction(root, 1);
+       BUG_ON(IS_ERR(trans));
        btrfs_set_trans_block_group(trans, dir);
 
        err = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid);
@@ -4855,7 +4892,8 @@ static int prealloc_file_range(struct inode *inode, u64 
start, u64 end,
        int ret = 0;
 
        trans = btrfs_join_transaction(root, 1);
-       BUG_ON(!trans);
+       if (IS_ERR(trans))
+               return PTR_ERR(trans);
        btrfs_set_trans_block_group(trans, inode);
 
        while (num_bytes > 0) {
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 988fdc8..4b62868 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -75,7 +75,10 @@ static noinline int create_subvol(struct btrfs_root *root,
                goto fail_commit;
 
        trans = btrfs_start_transaction(root, 1);
-       BUG_ON(!trans);
+       if (IS_ERR(trans)) {
+               ret = PTR_ERR(trans);
+               goto fail_commit;
+       }
 
        ret = btrfs_find_free_objectid(trans, root->fs_info->tree_root,
                                       0, &objectid);
@@ -174,7 +177,11 @@ static noinline int create_subvol(struct btrfs_root *root,
        BUG_ON(!new_root);
 
        trans = btrfs_start_transaction(new_root, 1);
-       BUG_ON(!trans);
+       if (IS_ERR(trans)) {
+               /* JDM: When is all the stuff we just made cleaned up? */
+               ret = PTR_ERR(trans);
+               goto fail_commit;
+       }
 
        ret = btrfs_create_subvol_root(trans, new_root, dentry, new_dirid,
                                       BTRFS_I(dir)->block_group);
@@ -222,7 +229,12 @@ static int create_snapshot(struct btrfs_root *root, struct 
dentry *dentry,
        pending_snapshot->name[namelen] = '\0';
        pending_snapshot->dentry = dentry;
        trans = btrfs_start_transaction(root, 1);
-       BUG_ON(!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);
@@ -537,6 +549,10 @@ static int btrfs_ioctl_resize(struct btrfs_root *root, 
void __user *arg)
 
        if (new_size > old_size) {
                trans = btrfs_start_transaction(root, 1);
+               if (IS_ERR(trans)) {
+                       ret = PTR_ERR(trans);
+                       goto out_unlock;
+               }
                ret = btrfs_grow_device(trans, device, new_size);
                btrfs_commit_transaction(trans, root);
        } else {
@@ -651,8 +667,9 @@ static int btrfs_ioctl_defrag(struct file *file)
                        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)) {
@@ -827,7 +844,12 @@ static long btrfs_ioctl_clone(struct file *file, unsigned 
long srcfd,
        }
 
        trans = btrfs_start_transaction(root, 1);
-       BUG_ON(!trans);
+       if (IS_ERR(trans)) {
+               btrfs_release_path(root, path);
+               unlock_extent(&BTRFS_I(src)->io_tree, off, off+len, GFP_NOFS);
+               ret = PTR_ERR(trans);
+               goto out_unlock;
+       }
 
        /* punch hole in destination first */
        btrfs_drop_extents(trans, root, inode, off, off+len, 0, &hint_byte);
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 19a4daf..19af4ca 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -380,7 +380,13 @@ int btrfs_sync_fs(struct super_block *sb, int wait)
        btrfs_wait_ordered_extents(root, 0);
 
        trans = btrfs_start_transaction(root, 1);
-       ret = btrfs_commit_transaction(trans, root);
+       if (!IS_ERR(trans))
+               ret = btrfs_commit_transaction(trans, root);
+       else
+               ret = PTR_ERR(trans);
+
+       /* Even if the transaction isn't committed, sync_supers
+        * will loop if we don't clear the dirty flag */
        sb->s_dirt = 0;
        return ret;
 }
@@ -530,7 +536,8 @@ static int btrfs_remount(struct super_block *sb, int 
*flags, char *data)
                        return -EINVAL;
 
                ret = btrfs_cleanup_reloc_trees(root);
-               WARN_ON(ret);
+               if (ret)
+                       return ret;
 
                ret = btrfs_cleanup_fs_roots(root->fs_info);
                WARN_ON(ret);
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 4112d53..fa07264 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -51,7 +51,8 @@ static noinline int join_transaction(struct btrfs_root *root)
        if (!cur_trans) {
                cur_trans = kmem_cache_alloc(btrfs_transaction_cachep,
                                             GFP_NOFS);
-               BUG_ON(!cur_trans);
+               if (!cur_trans)
+                       return -ENOMEM;
                root->fs_info->generation++;
                root->fs_info->last_alloc = 0;
                root->fs_info->last_data_alloc = 0;
@@ -167,12 +168,18 @@ static struct btrfs_trans_handle 
*start_transaction(struct btrfs_root *root,
                kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS);
        int ret;
 
+       if (!h)
+               return ERR_PTR(-ENOMEM);
+
        mutex_lock(&root->fs_info->trans_mutex);
        if (!root->fs_info->log_root_recovering &&
            ((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;
+       }
 
        btrfs_record_root_in_trans(root);
        h->transid = root->fs_info->running_transaction->transid;
@@ -183,6 +190,7 @@ static struct btrfs_trans_handle *start_transaction(struct 
btrfs_root *root,
        h->alloc_exclude_nr = 0;
        h->alloc_exclude_start = 0;
        root->fs_info->running_transaction->use_count++;
+out:
        mutex_unlock(&root->fs_info->trans_mutex);
        return h;
 }
@@ -616,6 +624,8 @@ int btrfs_defrag_root(struct btrfs_root *root, int 
cacheonly)
        if (root->defrag_running)
                return 0;
        trans = btrfs_start_transaction(root, 1);
+       if (IS_ERR(trans))
+               return PTR_ERR(trans);
        while (1) {
                root->defrag_running = 1;
                ret = btrfs_defrag_leaves(trans, root, cacheonly);
@@ -625,6 +635,11 @@ int btrfs_defrag_root(struct btrfs_root *root, int 
cacheonly)
                cond_resched();
 
                trans = btrfs_start_transaction(root, 1);
+               if (IS_ERR(trans)) {
+                       root->defrag_running = 0;
+                       smp_mb();
+                       return PTR_ERR(trans);
+               }
                if (root->fs_info->closing || ret != -EAGAIN)
                        break;
        }
@@ -662,6 +677,10 @@ static noinline int drop_dirty_roots(struct btrfs_root 
*tree_root,
 
                while (1) {
                        trans = btrfs_start_transaction(tree_root, 1);
+                       if (IS_ERR(trans)) {
+                               ret = PTR_ERR(trans);
+                               break;
+                       }
                        mutex_lock(&root->fs_info->drop_mutex);
                        ret = btrfs_drop_snapshot(trans, dirty->root);
                        if (ret != -EAGAIN)
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 9c462fb..b161e63 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -2793,6 +2793,10 @@ int btrfs_recover_log_trees(struct btrfs_root 
*log_root_tree)
        BUG_ON(!path);
 
        trans = btrfs_start_transaction(fs_info->tree_root, 1);
+       if (IS_ERR(trans)) {
+               btrfs_free_path(path);
+               return PTR_ERR(trans);
+       }
 
        wc.trans = trans;
        wc.pin = 1;
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 1316139..1b35ae0 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -951,6 +951,10 @@ static int btrfs_rm_dev_item(struct btrfs_root *root,
                return -ENOMEM;
 
        trans = btrfs_start_transaction(root, 1);
+       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;
@@ -1324,6 +1328,11 @@ int btrfs_init_new_device(struct btrfs_root *root, char 
*device_path)
        }
 
        trans = btrfs_start_transaction(root, 1);
+       if (IS_ERR(trans)) {
+               kfree(device);
+               ret = PTR_ERR(trans);
+               goto error;
+       }
        lock_chunks(root);
 
        device->barriers = 1;
@@ -1569,7 +1578,7 @@ static int btrfs_relocate_chunk(struct btrfs_root *root,
        BUG_ON(ret);
 
        trans = btrfs_start_transaction(root, 1);
-       BUG_ON(!trans);
+       BUG_ON(IS_ERR(trans));
 
        lock_chunks(root);
 
@@ -1725,7 +1734,7 @@ int btrfs_balance(struct btrfs_root *dev_root)
                BUG_ON(ret);
 
                trans = btrfs_start_transaction(dev_root, 1);
-               BUG_ON(!trans);
+               BUG_ON(IS_ERR(trans));
 
                ret = btrfs_grow_device(trans, device, old_size);
                BUG_ON(ret);
@@ -1816,8 +1825,8 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 
new_size)
                return -ENOMEM;
 
        trans = btrfs_start_transaction(root, 1);
-       if (!trans) {
-               ret = -ENOMEM;
+       if (IS_ERR(trans)) {
+               ret = PTR_ERR(trans);
                goto done;
        }
 
-- 
1.6.0.2

--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to