struct extent_buffer *eb;
        struct btrfs_root_item *root_item;
        struct btrfs_key root_key;
-       int ret;
+       int ret = 0;
+       bool must_abort = false;
 
        root_item = kmalloc(sizeof(*root_item), GFP_NOFS);
-       BUG_ON(!root_item);
+       if (!root_item)
+               return ERR_PTR(-ENOMEM);
 
        root_key.objectid = BTRFS_TREE_RELOC_OBJECTID;
        root_key.type = BTRFS_ROOT_ITEM_KEY;
                /* called by btrfs_init_reloc_root */
                ret = btrfs_copy_root(trans, root, root->commit_root, &eb,
                                      BTRFS_TREE_RELOC_OBJECTID);
-               BUG_ON(ret);
+               if (ret)
+                       goto fail;
+
                /*
                 * Set the last_snapshot field to the generation of the commit
                 * root - like this ctree.c:btrfs_block_can_be_shared() behaves
                 */
                ret = btrfs_copy_root(trans, root, root->node, &eb,
                                      BTRFS_TREE_RELOC_OBJECTID);
-               BUG_ON(ret);
+               if (ret)
+                       goto fail;
        }
 
+       /*
+        * We have changed references at this point, we must abort the
+        * transaction if anything fails.
+        */
+       must_abort = true;
+
        memcpy(root_item, &root->root_item, sizeof(*root_item));
        btrfs_set_root_bytenr(root_item, eb->start);
        btrfs_set_root_level(root_item, btrfs_header_level(eb));
 
        ret = btrfs_insert_root(trans, fs_info->tree_root,
                                &root_key, root_item);
-       BUG_ON(ret);
+       if (ret)
+               goto fail;
+
        kfree(root_item);
 
        reloc_root = btrfs_read_tree_root(fs_info->tree_root, &root_key);
-       BUG_ON(IS_ERR(reloc_root));
+       if (IS_ERR(reloc_root)) {
+               ret = PTR_ERR(reloc_root);
+               goto abort;
+       }
        set_bit(BTRFS_ROOT_SHAREABLE, &reloc_root->state);
        reloc_root->last_trans = trans->transid;
        return reloc_root;
+fail:
+       kfree(root_item);
+abort:
+       if (must_abort)
+               btrfs_abort_transaction(trans, ret);
+       return ERR_PTR(ret);
 }
 
 /*