*/
                        atomic_inc(&cb->pending_bios);
                        ret = btrfs_bio_wq_end_io(root->fs_info, bio, 0);
-                       BUG_ON(ret);
+                       BUG_ON(ret); /* -ENOMEM */
 
                        if (!skip_sum) {
                                ret = btrfs_csum_one_bio(root, inode, bio,
                                                         start, 1);
-                               BUG_ON(ret);
+                               BUG_ON(ret); /* -ENOMEM */
                        }
 
                        ret = btrfs_map_bio(root, WRITE, bio, 0, 1);
-                       BUG_ON(ret);
+                       BUG_ON(ret); /* -ENOMEM */
 
                        bio_put(bio);
 
        bio_get(bio);
 
        ret = btrfs_bio_wq_end_io(root->fs_info, bio, 0);
-       BUG_ON(ret);
+       BUG_ON(ret); /* -ENOMEM */
 
        if (!skip_sum) {
                ret = btrfs_csum_one_bio(root, inode, bio, start, 1);
-               BUG_ON(ret);
+               BUG_ON(ret); /* -ENOMEM */
        }
 
        ret = btrfs_map_bio(root, WRITE, bio, 0, 1);
-       BUG_ON(ret);
+       BUG_ON(ret); /* -ENOMEM */
 
        bio_put(bio);
        return 0;
                        bio_get(comp_bio);
 
                        ret = btrfs_bio_wq_end_io(root->fs_info, comp_bio, 0);
-                       BUG_ON(ret);
+                       BUG_ON(ret); /* -ENOMEM */
 
                        /*
                         * inc the count before we submit the bio so
                        if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) {
                                ret = btrfs_lookup_bio_sums(root, inode,
                                                        comp_bio, sums);
-                               BUG_ON(ret);
+                               BUG_ON(ret); /* -ENOMEM */
                        }
                        sums += (comp_bio->bi_size + root->sectorsize - 1) /
                                root->sectorsize;
 
                        ret = btrfs_map_bio(root, READ, comp_bio,
                                            mirror_num, 0);
-                       BUG_ON(ret);
+                       BUG_ON(ret); /* -ENOMEM */
 
                        bio_put(comp_bio);
 
        bio_get(comp_bio);
 
        ret = btrfs_bio_wq_end_io(root->fs_info, comp_bio, 0);
-       BUG_ON(ret);
+       BUG_ON(ret); /* -ENOMEM */
 
        if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) {
                ret = btrfs_lookup_bio_sums(root, inode, comp_bio, sums);
-               BUG_ON(ret);
+               BUG_ON(ret); /* -ENOMEM */
        }
 
        ret = btrfs_map_bio(root, READ, comp_bio, mirror_num, 0);
-       BUG_ON(ret);
+       BUG_ON(ret); /* -ENOMEM */
 
        bio_put(comp_bio);
        return 0;
 
                     root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) &&
                    !(flags & BTRFS_BLOCK_FLAG_FULL_BACKREF)) {
                        ret = btrfs_inc_ref(trans, root, buf, 1, 1);
-                       BUG_ON(ret);
+                       BUG_ON(ret); /* -ENOMEM */
 
                        if (root->root_key.objectid ==
                            BTRFS_TREE_RELOC_OBJECTID) {
                                ret = btrfs_dec_ref(trans, root, buf, 0, 1);
-                               BUG_ON(ret);
+                               BUG_ON(ret); /* -ENOMEM */
                                ret = btrfs_inc_ref(trans, root, cow, 1, 1);
-                               BUG_ON(ret);
+                               BUG_ON(ret); /* -ENOMEM */
                        }
                        new_flags |= BTRFS_BLOCK_FLAG_FULL_BACKREF;
                } else {
                                ret = btrfs_inc_ref(trans, root, cow, 1, 1);
                        else
                                ret = btrfs_inc_ref(trans, root, cow, 0, 1);
-                       BUG_ON(ret);
+                       BUG_ON(ret); /* -ENOMEM */
                }
                if (new_flags != 0) {
                        ret = btrfs_set_disk_extent_flags(trans, root,
                                ret = btrfs_inc_ref(trans, root, cow, 1, 1);
                        else
                                ret = btrfs_inc_ref(trans, root, cow, 0, 1);
-                       BUG_ON(ret);
+                       BUG_ON(ret); /* -ENOMEM */
                        ret = btrfs_dec_ref(trans, root, buf, 1, 1);
-                       BUG_ON(ret);
+                       BUG_ON(ret); /* -ENOMEM */
                }
                clean_tree_block(trans, root, buf);
                *last_ref = 1;
 
        ret = update_ref_for_cow(trans, root, buf, cow, &last_ref);
        if (ret) {
-               btrfs_std_error(root->fs_info, ret);
+               btrfs_abort_transaction(trans, root, ret);
                return ret;
        }
 
                              path->nodes[1], slot - 1, &left);
        if (ret) {
                /* we hit -ENOSPC, but it isn't fatal here */
-               ret = 1;
+               if (ret == -ENOSPC)
+                       ret = 1;
                goto out;
        }
 
                }
                btrfs_set_path_blocking(path);
                cur = read_node_slot(root, cur, slot);
-               BUG_ON(!cur);
+               BUG_ON(!cur); /* -ENOMEM */
 
                btrfs_tree_read_lock(cur);
 
 
        return NULL;
 }
 
+/* Will return either the node or PTR_ERR(-ENOMEM) */
 static struct btrfs_delayed_node *btrfs_get_or_create_delayed_node(
                                                        struct inode *inode)
 {
        return 0;
 }
 
-/* Called when committing the transaction. */
+/*
+ * Called when committing the transaction.
+ * Returns 0 on success.
+ * Returns < 0 on error and returns with an aborted transaction with any
+ * outstanding delayed items cleaned up.
+ */
 int btrfs_run_delayed_items(struct btrfs_trans_handle *trans,
                            struct btrfs_root *root)
 {
+       struct btrfs_root *curr_root = root;
        struct btrfs_delayed_root *delayed_root;
        struct btrfs_delayed_node *curr_node, *prev_node;
        struct btrfs_path *path;
        struct btrfs_block_rsv *block_rsv;
        int ret = 0;
 
+       if (trans->aborted)
+               return -EIO;
+
        path = btrfs_alloc_path();
        if (!path)
                return -ENOMEM;
 
        curr_node = btrfs_first_delayed_node(delayed_root);
        while (curr_node) {
-               root = curr_node->root;
-               ret = btrfs_insert_delayed_items(trans, path, root,
+               curr_root = curr_node->root;
+               ret = btrfs_insert_delayed_items(trans, path, curr_root,
                                                 curr_node);
                if (!ret)
-                       ret = btrfs_delete_delayed_items(trans, path, root,
-                                                        curr_node);
+                       ret = btrfs_delete_delayed_items(trans, path,
+                                               curr_root, curr_node);
                if (!ret)
-                       ret = btrfs_update_delayed_inode(trans, root, path,
-                                                        curr_node);
+                       ret = btrfs_update_delayed_inode(trans, curr_root,
+                                               path, curr_node);
                if (ret) {
                        btrfs_release_delayed_node(curr_node);
+                       btrfs_abort_transaction(trans, root, ret);
                        break;
                }
 
 
        btrfs_free_path(path);
        trans->block_rsv = block_rsv;
+
        return ret;
 }
 
        btrfs_wq_run_delayed_node(delayed_root, root, 0);
 }
 
+/* Will return 0 or -ENOMEM */
 int btrfs_insert_delayed_dir_index(struct btrfs_trans_handle *trans,
                                   struct btrfs_root *root, const char *name,
                                   int name_len, struct inode *dir,
 
  * 'location' is the key to stuff into the directory item, 'type' is the
  * type of the inode we're pointing to, and 'index' is the sequence number
  * to use for the second index (if one is created).
+ * Will return 0 or -ENOMEM
  */
 int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
                          *root, const char *name, int name_len,
 
         */
        u64 bio_offset;
        struct btrfs_work work;
+       int error;
 };
 
 /*
        u64 found_start;
        unsigned long len;
        struct extent_buffer *eb;
-       int ret;
+       int ret = -EIO;
 
        tree = &BTRFS_I(page->mapping->host)->io_tree;
 
        eb = alloc_extent_buffer(tree, start, len, page);
        if (eb == NULL) {
                WARN_ON(1);
+               ret = -ENOMEM;
                goto out;
        }
        ret = btree_read_extent_buffer_pages(root, eb, start + PAGE_CACHE_SIZE,
                                             btrfs_header_generation(eb));
-       BUG_ON(ret);
+       if (ret) {
+               btrfs_printk(root->fs_info, KERN_WARNING
+                            "Failed to checksum dirty buffer @ %llu[%lu]\n",
+                             start, len);
+               goto err;
+       }
        WARN_ON(!btrfs_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN));
 
+       ret = -EIO;
        found_start = btrfs_header_bytenr(eb);
        if (found_start != start) {
                WARN_ON(1);
                goto err;
        }
        csum_tree_block(root, eb, 0);
+       ret = 0;
 err:
        free_extent_buffer(eb);
 out:
-       return 0;
+       return ret;
 }
 
 static int check_tree_block_fsid(struct btrfs_root *root,
 static void run_one_async_start(struct btrfs_work *work)
 {
        struct async_submit_bio *async;
+       int ret;
 
        async = container_of(work, struct  async_submit_bio, work);
-       async->submit_bio_start(async->inode, async->rw, async->bio,
-                              async->mirror_num, async->bio_flags,
-                              async->bio_offset);
+       ret = async->submit_bio_start(async->inode, async->rw, async->bio,
+                                     async->mirror_num, async->bio_flags,
+                                     async->bio_offset);
+       if (ret)
+               async->error = ret;
 }
 
 static void run_one_async_done(struct btrfs_work *work)
            waitqueue_active(&fs_info->async_submit_wait))
                wake_up(&fs_info->async_submit_wait);
 
+       /* If an error occured we just want to clean up the bio and move on */
+       if (async->error) {
+               bio_endio(async->bio, async->error);
+               return;
+       }
+
        async->submit_bio_done(async->inode, async->rw, async->bio,
                               async->mirror_num, async->bio_flags,
                               async->bio_offset);
        async->bio_flags = bio_flags;
        async->bio_offset = bio_offset;
 
+       async->error = 0;
+
        atomic_inc(&fs_info->nr_async_submits);
 
        if (rw & REQ_SYNC)
        struct bio_vec *bvec = bio->bi_io_vec;
        int bio_index = 0;
        struct btrfs_root *root;
+       int ret = 0;
 
        WARN_ON(bio->bi_vcnt <= 0);
        while (bio_index < bio->bi_vcnt) {
                root = BTRFS_I(bvec->bv_page->mapping->host)->root;
-               csum_dirty_buffer(root, bvec->bv_page);
+               ret = csum_dirty_buffer(root, bvec->bv_page);
+               if (ret)
+                       break;
                bio_index++;
                bvec++;
        }
-       return 0;
+       return ret;
 }
 
 static int __btree_submit_bio_start(struct inode *inode, int rw,
         * when we're called for a write, we're already in the async
         * submission context.  Just jump into btrfs_map_bio
         */
-       btree_csum_one_bio(bio);
-       return 0;
+       return btree_csum_one_bio(bio);
 }
 
 static int __btree_submit_bio_done(struct inode *inode, int rw, struct bio *bio,
        root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item),
                                     blocksize, generation);
        root->commit_root = btrfs_root_node(root);
-       BUG_ON(!root->node);
+       BUG_ON(!root->node); /* -ENOMEM */
 out:
        if (location->objectid != BTRFS_TREE_LOG_OBJECTID) {
                root->ref_cows = 1;
        u64 transid;
        unsigned long now;
        unsigned long delay;
-       int ret;
 
        do {
                delay = HZ * 30;
                transid = cur->transid;
                spin_unlock(&root->fs_info->trans_lock);
 
+               /* If the file system is aborted, this will always fail. */
                trans = btrfs_join_transaction(root);
-               BUG_ON(IS_ERR(trans));
+               if (IS_ERR(trans))
+                       goto sleep;
                if (transid == trans->transid) {
-                       ret = btrfs_commit_transaction(trans, root);
-                       BUG_ON(ret);
+                       btrfs_commit_transaction(trans, root);
                } else {
                        btrfs_end_transaction(trans, root);
                }
        chunk_root->node = read_tree_block(chunk_root,
                                           btrfs_super_chunk_root(disk_super),
                                           blocksize, generation);
-       BUG_ON(!chunk_root->node);
+       BUG_ON(!chunk_root->node); /* -ENOMEM */
        if (!test_bit(EXTENT_BUFFER_UPTODATE, &chunk_root->node->bflags)) {
                printk(KERN_WARNING "btrfs: failed to read chunk root on %s\n",
                       sb->s_id);
                log_tree_root->node = read_tree_block(tree_root, bytenr,
                                                      blocksize,
                                                      generation + 1);
+               /* returns with log_tree_root freed on success */
                ret = btrfs_recover_log_trees(log_tree_root);
-               BUG_ON(ret);
+               if (ret) {
+                       btrfs_error(tree_root->fs_info, ret,
+                                   "Failed to recover log tree");
+                       free_extent_buffer(log_tree_root->node);
+                       kfree(log_tree_root);
+                       goto fail_trans_kthread;
+               }
 
                if (sb->s_flags & MS_RDONLY) {
-                       ret =  btrfs_commit_super(tree_root);
-                       BUG_ON(ret);
+                       ret = btrfs_commit_super(tree_root);
+                       if (ret)
+                               goto fail_trans_kthread;
                }
        }
 
        ret = btrfs_find_orphan_roots(tree_root);
-       BUG_ON(ret);
+       if (ret)
+               goto fail_trans_kthread;
 
        if (!(sb->s_flags & MS_RDONLY)) {
                ret = btrfs_cleanup_fs_roots(fs_info);
-               BUG_ON(ret);
+               if (ret) {
+                       }
 
                ret = btrfs_recover_relocation(tree_root);
                if (ret < 0) {
        if (total_errors > max_errors) {
                printk(KERN_ERR "btrfs: %d errors while writing supers\n",
                       total_errors);
+
+               /* This shouldn't happen. FUA is masked off if unsupported */
                BUG();
        }
 
        }
        mutex_unlock(&root->fs_info->fs_devices->device_list_mutex);
        if (total_errors > max_errors) {
-               printk(KERN_ERR "btrfs: %d errors while writing supers\n",
-                      total_errors);
-               BUG();
+               btrfs_error(root->fs_info, -EIO,
+                           "%d errors while writing supers", total_errors);
+               return -EIO;
        }
        return 0;
 }
        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_join_transaction(root);
        if (IS_ERR(trans))
                return PTR_ERR(trans);
-       btrfs_commit_transaction(trans, root);
+       ret = btrfs_commit_transaction(trans, root);
+       if (ret)
+               return ret;
        ret = btrfs_write_and_wait_transaction(NULL, root);
-       BUG_ON(ret);
+       if (ret) {
+               btrfs_error(root->fs_info, ret,
+                           "Failed to sync btree inode to disk.");
+               return ret;
+       }
 
        ret = write_ctree_super(NULL, root, 0);
        return ret;
        spin_unlock(&root->fs_info->ordered_extent_lock);
 }
 
-static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,
-                                     struct btrfs_root *root)
+int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,
+                              struct btrfs_root *root)
 {
        struct rb_node *node;
        struct btrfs_delayed_ref_root *delayed_refs;
 
        delayed_refs = &trans->delayed_refs;
 
+again:
        spin_lock(&delayed_refs->lock);
        if (delayed_refs->num_entries == 0) {
                spin_unlock(&delayed_refs->lock);
                        struct btrfs_delayed_ref_head *head;
 
                        head = btrfs_delayed_node_to_head(ref);
+                       spin_unlock(&delayed_refs->lock);
                        mutex_lock(&head->mutex);
                        kfree(head->extent_op);
                        delayed_refs->num_heads--;
                                delayed_refs->num_heads_ready--;
                        list_del_init(&head->cluster);
                        mutex_unlock(&head->mutex);
+                       btrfs_put_delayed_ref(ref);
+                       goto again;
                }
-
                spin_unlock(&delayed_refs->lock);
                btrfs_put_delayed_ref(ref);
 
        return 0;
 }
 
+static int btree_writepage_io_failed_hook(struct bio *bio, struct page *page,
+                                         u64 start, u64 end,
+                                         struct extent_state *state)
+{
+       struct super_block *sb = page->mapping->host->i_sb;
+       struct btrfs_fs_info *fs_info = btrfs_sb(sb);
+       btrfs_error(fs_info, -EIO,
+                   "Error occured while writing out btree at %llu", start);
+       return -EIO;
+}
+
 static struct extent_io_ops btree_extent_io_ops = {
        .write_cache_pages_lock_hook = btree_lock_page_hook,
        .readpage_end_io_hook = btree_readpage_end_io_hook,
        .submit_bio_hook = btree_submit_bio_hook,
        /* note we're sharing with inode.c for the merge bio hook */
        .merge_bio_hook = btrfs_merge_bio_hook,
+       .writepage_io_failed_hook = btree_writepage_io_failed_hook,
 };
 
        if (ret < 0)
                goto fail;
 
-       BUG_ON(ret == 0);
+       BUG_ON(ret == 0); /* Key with offset of -1 found */
        if (path->slots[0] == 0) {
                ret = -ENOENT;
                goto fail;
 
                cache->bytes_super += stripe_len;
                ret = add_excluded_extent(root, cache->key.objectid,
                                          stripe_len);
-               BUG_ON(ret);
+               BUG_ON(ret); /* -ENOMEM */
        }
 
        for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
                ret = btrfs_rmap_block(&root->fs_info->mapping_tree,
                                       cache->key.objectid, bytenr,
                                       0, &logical, &nr, &stripe_len);
-               BUG_ON(ret);
+               BUG_ON(ret); /* -ENOMEM */
 
                while (nr--) {
                        cache->bytes_super += stripe_len;
                        ret = add_excluded_extent(root, logical[nr],
                                                  stripe_len);
-                       BUG_ON(ret);
+                       BUG_ON(ret); /* -ENOMEM */
                }
 
                kfree(logical);
                        total_added += size;
                        ret = btrfs_add_free_space(block_group, start,
                                                   size);
-                       BUG_ON(ret);
+                       BUG_ON(ret); /* -ENOMEM or logic error */
                        start = extent_end + 1;
                } else {
                        break;
                size = end - start;
                total_added += size;
                ret = btrfs_add_free_space(block_group, start, size);
-               BUG_ON(ret);
+               BUG_ON(ret); /* -ENOMEM or logic error */
        }
 
        return total_added;
        int ret = 0;
 
        caching_ctl = kzalloc(sizeof(*caching_ctl), GFP_NOFS);
-       BUG_ON(!caching_ctl);
+       if (!caching_ctl)
+               return -ENOMEM;
 
        INIT_LIST_HEAD(&caching_ctl->list);
        mutex_init(&caching_ctl->mutex);
                                ret = btrfs_next_leaf(root, path);
                                if (ret < 0)
                                        return ret;
-                               BUG_ON(ret > 0);
+                               BUG_ON(ret > 0); /* Corruption */
                                leaf = path->nodes[0];
                        }
                        btrfs_item_key_to_cpu(leaf, &found_key,
                                new_size + extra_size, 1);
        if (ret < 0)
                return ret;
-       BUG_ON(ret);
+       BUG_ON(ret); /* Corruption */
 
        btrfs_extend_item(trans, root, path, new_size);
 
                err = ret;
                goto out;
        }
-       BUG_ON(ret);
+       if (ret && !insert) {
+               err = -ENOENT;
+               goto out;
+       }
+       BUG_ON(ret); /* Corruption */
 
        leaf = path->nodes[0];
        item_size = btrfs_item_size_nr(leaf, path->slots[0]);
        /* Tell the block device(s) that the sectors can be discarded */
        ret = btrfs_map_block(&root->fs_info->mapping_tree, REQ_DISCARD,
                              bytenr, &num_bytes, &bbio, 0);
+       /* Error condition is -ENOMEM */
        if (!ret) {
                struct btrfs_bio_stripe *stripe = bbio->stripes;
                int i;
                        if (!ret)
                                discarded_bytes += stripe->length;
                        else if (ret != -EOPNOTSUPP)
-                               break;
+                               break; /* Logic errors or -ENOMEM, or -EIO but I don't know how that could happen JDM */
 
                        /*
                         * Just in case we get back EOPNOTSUPP for some reason,
        return ret;
 }
 
+/* Can return -ENOMEM */
 int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
                         struct btrfs_root *root,
                         u64 bytenr, u64 num_bytes, u64 parent,
        ret = insert_extent_backref(trans, root->fs_info->extent_root,
                                    path, bytenr, parent, root_objectid,
                                    owner, offset, refs_to_add);
-       BUG_ON(ret);
+       if (ret)
+               btrfs_abort_transaction(trans, root, ret);
 out:
        btrfs_free_path(path);
        return err;
        int ret;
        int err = 0;
 
+       if (trans->aborted)
+               return 0;
+
        path = btrfs_alloc_path();
        if (!path)
                return -ENOMEM;
                               struct btrfs_delayed_extent_op *extent_op,
                               int insert_reserved)
 {
-       int ret;
+       int ret = 0;
+
+       if (trans->aborted)
+               return 0;
+
        if (btrfs_delayed_ref_is_head(node)) {
                struct btrfs_delayed_ref_head *head;
                /*
                                ret = btrfs_del_csums(trans, root,
                                                      node->bytenr,
                                                      node->num_bytes);
-                               BUG_ON(ret);
                        }
                }
                mutex_unlock(&head->mutex);
-               return 0;
+               return ret;
        }
 
        if (node->type == BTRFS_TREE_BLOCK_REF_KEY ||
        return NULL;
 }
 
+/*
+ * Returns 0 on success or if called with an already aborted transaction.
+ * Returns -ENOMEM or -EIO on failure and will abort the transaction.
+ */
 static noinline int run_clustered_refs(struct btrfs_trans_handle *trans,
                                       struct btrfs_root *root,
                                       struct list_head *cluster)
 
                                ret = run_delayed_extent_op(trans, root,
                                                            ref, extent_op);
-                               BUG_ON(ret);
                                kfree(extent_op);
 
+                               if (ret) {
+                                       printk(KERN_DEBUG "btrfs: run_delayed_extent_op returned %d\n", ret);
+                                       return ret;
+                               }
+
                                goto next;
                        }
 
 
                ret = run_one_delayed_ref(trans, root, ref, extent_op,
                                          must_insert_reserved);
-               BUG_ON(ret);
 
                btrfs_put_delayed_ref(ref);
                kfree(extent_op);
                count++;
+
+               if (ret) {
+                       printk(KERN_DEBUG "btrfs: run_one_delayed_ref returned %d\n", ret);
+                       return ret;
+               }
+
 next:
                do_chunk_alloc(trans, root->fs_info->extent_root,
                               2 * 1024 * 1024,
  * 0, which means to process everything in the tree at the start
  * of the run (but not newly added entries), or it can be some target
  * number you'd like to process.
+ *
+ * Returns 0 on success or if called with an aborted transaction
+ * Returns <0 on error and aborts the transaction
  */
 int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
                           struct btrfs_root *root, unsigned long count)
        unsigned long num_refs = 0;
        int consider_waiting;
 
+       /* We'll clean this up in btrfs_cleanup_transaction */
+       if (trans->aborted)
+               return 0;
+
        if (root == root->fs_info->extent_root)
                root = root->fs_info->tree_root;
 
                }
 
                ret = run_clustered_refs(trans, root, &cluster);
-               BUG_ON(ret < 0);
+               if (ret < 0) {
+                       spin_unlock(&delayed_refs->lock);
+                       btrfs_abort_transaction(trans, root, ret);
+                       return ret;
+               }
 
                count -= min_t(unsigned long, ret, count);
 
        ret = btrfs_search_slot(NULL, extent_root, &key, path, 0, 0);
        if (ret < 0)
                goto out;
-       BUG_ON(ret == 0);
+       BUG_ON(ret == 0); /* Corruption */
 
        ret = -ENOENT;
        if (path->slots[0] == 0)
        }
        return 0;
 fail:
-       BUG();
        return ret;
 }
 
        ret = btrfs_search_slot(trans, extent_root, &cache->key, path, 0, 1);
        if (ret < 0)
                goto fail;
-       BUG_ON(ret);
+       BUG_ON(ret); /* Corruption */
 
        leaf = path->nodes[0];
        bi = btrfs_item_ptr_offset(leaf, path->slots[0]);
        btrfs_mark_buffer_dirty(leaf);
        btrfs_release_path(path);
 fail:
-       if (ret)
+       if (ret) {
+               btrfs_abort_transaction(trans, root, ret);
                return ret;
+       }
        return 0;
 
 }
                if (last == 0) {
                        err = btrfs_run_delayed_refs(trans, root,
                                                     (unsigned long)-1);
-                       BUG_ON(err);
+                       if (err) /* File system offline */
+                               goto out;
                }
 
                cache = btrfs_lookup_first_block_group(root->fs_info, last);
                last = cache->key.objectid + cache->key.offset;
 
                err = write_one_cache_group(trans, root, path, cache);
-               BUG_ON(err);
+               if (err) /* File system offline */
+                       goto out;
+
                btrfs_put_block_group(cache);
        }
 
                if (last == 0) {
                        err = btrfs_run_delayed_refs(trans, root,
                                                     (unsigned long)-1);
-                       BUG_ON(err);
+                       if (err) /* File system offline */
+                               goto out;
                }
 
                cache = btrfs_lookup_first_block_group(root->fs_info, last);
                        continue;
                }
 
-               btrfs_write_out_cache(root, trans, cache, path);
+               err = btrfs_write_out_cache(root, trans, cache, path);
 
                /*
                 * If we didn't have an error then the cache state is still
                 * NEED_WRITE, so we can set it to WRITTEN.
                 */
-               if (cache->disk_cache_state == BTRFS_DC_NEED_WRITE)
+               if (!err && cache->disk_cache_state == BTRFS_DC_NEED_WRITE)
                        cache->disk_cache_state = BTRFS_DC_WRITTEN;
                last = cache->key.objectid + cache->key.offset;
                btrfs_put_block_group(cache);
        }
+out:
 
        btrfs_free_path(path);
-       return 0;
+       return err;
 }
 
 int btrfs_extent_readonly(struct btrfs_root *root, u64 bytenr)
        if (!space_info) {
                ret = update_space_info(extent_root->fs_info, flags,
                                        0, 0, &space_info);
-               BUG_ON(ret);
+               BUG_ON(ret); /* -ENOMEM */
        }
-       BUG_ON(!space_info);
+       BUG_ON(!space_info); /* Logic error */
 
 again:
        spin_lock(&space_info->lock);
                ret = wait_event_interruptible(space_info->wait,
                                               !space_info->flush);
                /* Must have been interrupted, return */
-               if (ret)
+               if (ret) {
+                       printk(KERN_DEBUG "btrfs: %s returning -EINTR\n", __func__);
                        return -EINTR;
+               }
 
                spin_lock(&space_info->lock);
        }
        return ret;
 }
 
-static struct btrfs_block_rsv *get_block_rsv(struct btrfs_trans_handle *trans,
-                                            struct btrfs_root *root)
+static struct btrfs_block_rsv *get_block_rsv(
+                                       const struct btrfs_trans_handle *trans,
+                                       const struct btrfs_root *root)
 {
        struct btrfs_block_rsv *block_rsv = NULL;
 
        trans->bytes_reserved = 0;
 }
 
+/* Can only return 0 or -ENOSPC */
 int btrfs_orphan_reserve_metadata(struct btrfs_trans_handle *trans,
                                  struct inode *inode)
 {
        while (total) {
                cache = btrfs_lookup_block_group(info, bytenr);
                if (!cache)
-                       return -1;
+                       return -ENOENT;
                if (cache->flags & (BTRFS_BLOCK_GROUP_DUP |
                                    BTRFS_BLOCK_GROUP_RAID1 |
                                    BTRFS_BLOCK_GROUP_RAID10))
        struct btrfs_block_group_cache *cache;
 
        cache = btrfs_lookup_block_group(root->fs_info, bytenr);
-       BUG_ON(!cache);
+       BUG_ON(!cache); /* Logic error */
 
        pin_down_extent(root, cache, bytenr, num_bytes, reserved);
 
        struct btrfs_block_group_cache *cache;
 
        cache = btrfs_lookup_block_group(root->fs_info, bytenr);
-       BUG_ON(!cache);
+       BUG_ON(!cache); /* Logic error */
 
        /*
         * pull in the free space cache (if any) so that our pin
 {
        struct btrfs_space_info *space_info = cache->space_info;
        int ret = 0;
+
        spin_lock(&space_info->lock);
        spin_lock(&cache->lock);
        if (reserve != RESERVE_FREE) {
                        if (cache)
                                btrfs_put_block_group(cache);
                        cache = btrfs_lookup_block_group(fs_info, start);
-                       BUG_ON(!cache);
+                       BUG_ON(!cache); /* Logic error */
                }
 
                len = cache->key.objectid + cache->key.offset - start;
        u64 end;
        int ret;
 
+       if (trans->aborted)
+               return 0;
+
        if (fs_info->pinned_extents == &fs_info->freed_extents[0])
                unpin = &fs_info->freed_extents[1];
        else
                        ret = remove_extent_backref(trans, extent_root, path,
                                                    NULL, refs_to_drop,
                                                    is_data);
-                       BUG_ON(ret);
+                       if (ret)
+                               goto abort;
                        btrfs_release_path(path);
                        path->leave_spinning = 1;
 
                                        btrfs_print_leaf(extent_root,
                                                         path->nodes[0]);
                        }
-                       BUG_ON(ret);
+                       if (ret < 0)
+                               goto abort;
                        extent_slot = path->slots[0];
                }
-       } else {
+       } else if (ret == -ENOENT) {
                btrfs_print_leaf(extent_root, path->nodes[0]);
                WARN_ON(1);
                printk(KERN_ERR "btrfs unable to find ref byte nr %llu "
                       (unsigned long long)root_objectid,
                       (unsigned long long)owner_objectid,
                       (unsigned long long)owner_offset);
+       } else {
+               goto abort;
        }
 
        leaf = path->nodes[0];
                BUG_ON(found_extent || extent_slot != path->slots[0]);
                ret = convert_extent_item_v0(trans, extent_root, path,
                                             owner_objectid, 0);
-               BUG_ON(ret < 0);
+               if (ret < 0)
+                       goto abort;
 
                btrfs_release_path(path);
                path->leave_spinning = 1;
                               (unsigned long long)bytenr);
                        btrfs_print_leaf(extent_root, path->nodes[0]);
                }
-               BUG_ON(ret);
+               if (ret < 0)
+                       goto abort;
                extent_slot = path->slots[0];
                leaf = path->nodes[0];
                item_size = btrfs_item_size_nr(leaf, extent_slot);
                        ret = remove_extent_backref(trans, extent_root, path,
                                                    iref, refs_to_drop,
                                                    is_data);
-                       BUG_ON(ret);
+                       if (ret)
+                               goto abort;
                }
        } else {
                if (found_extent) {
 
                ret = btrfs_del_items(trans, extent_root, path, path->slots[0],
                                      num_to_del);
-               BUG_ON(ret);
+               if (ret)
+                       goto abort;
                btrfs_release_path(path);
 
                if (is_data) {
                        ret = btrfs_del_csums(trans, root, bytenr, num_bytes);
-                       BUG_ON(ret);
+                       if (ret)
+                               goto abort;
                } else {
                        invalidate_mapping_pages(info->btree_inode->i_mapping,
                             bytenr >> PAGE_CACHE_SHIFT,
                }
 
                ret = update_block_group(trans, root, bytenr, num_bytes, 0);
-               BUG_ON(ret);
+               if (ret)
+                       goto abort;
        }
+out:
        btrfs_free_path(path);
        return ret;
+
+abort:
+       btrfs_abort_transaction(trans, extent_root, ret);
+       goto out;
 }
 
 /*
                                        parent, root->root_key.objectid,
                                        btrfs_header_level(buf),
                                        BTRFS_DROP_DELAYED_REF, NULL, for_cow);
-               BUG_ON(ret);
+               BUG_ON(ret); /* -ENOMEM */
        }
 
        if (!last_ref)
        btrfs_put_block_group(cache);
 }
 
+/* Can return -ENOMEM */
 int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root,
                      u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid,
                      u64 owner, u64 offset, int for_cow)
                                        num_bytes,
                                        parent, root_objectid, (int)owner,
                                        BTRFS_DROP_DELAYED_REF, NULL, for_cow);
-               BUG_ON(ret);
        } else {
                ret = btrfs_add_delayed_data_ref(fs_info, trans, bytenr,
                                                num_bytes,
                                                parent, root_objectid, owner,
                                                offset, BTRFS_DROP_DELAYED_REF,
                                                NULL, for_cow);
-               BUG_ON(ret);
        }
        return ret;
 }
                        found_uncached_bg = true;
                        ret = cache_block_group(block_group, trans,
                                                orig_root, 1);
+                       BUG_ON(ret < 0); /* -ENOMEM */
                        if (block_group->cached == BTRFS_CACHE_FINISHED)
                                goto alloc;
 
                        if (loop > LOOP_FIND_IDEAL) {
                                ret = cache_block_group(block_group, trans,
                                                        orig_root, 0);
-                               BUG_ON(ret);
+                               BUG_ON(ret); /* -ENOMEM */
                        }
 
                        /*
                                ret = do_chunk_alloc(trans, root, num_bytes +
                                                     2 * 1024 * 1024, data,
                                                     CHUNK_ALLOC_LIMITED);
+                               if (ret < 0) {
+                                       btrfs_abort_transaction(trans,
+                                                               root, ret);
+                                       goto out;
+                               }
                                allowed_chunk_alloc = 0;
                                if (ret == 1)
                                        done_chunk_alloc = 1;
        } else if (ins->objectid) {
                ret = 0;
        }
+out:
 
        return ret;
 }
         * the only place that sets empty_size is btrfs_realloc_node, which
         * is not called recursively on allocations
         */
-       if (empty_size || root->ref_cows)
+       if (empty_size || root->ref_cows) {
                ret = do_chunk_alloc(trans, root->fs_info->extent_root,
                                     num_bytes + 2 * 1024 * 1024, data,
                                     CHUNK_ALLOC_NO_FORCE);
+               if (ret < 0 && ret != -ENOSPC) {
+                       btrfs_abort_transaction(trans, root, ret);
+                       return ret;
+               }
+       }
 
        WARN_ON(num_bytes < root->sectorsize);
        ret = find_free_extent(trans, root, num_bytes, empty_size,
                        num_bytes = num_bytes >> 1;
                        num_bytes = num_bytes & ~(root->sectorsize - 1);
                        num_bytes = max(num_bytes, min_alloc_size);
-                       do_chunk_alloc(trans, root->fs_info->extent_root,
+                       ret = do_chunk_alloc(trans, root->fs_info->extent_root,
                                       num_bytes, data, CHUNK_ALLOC_FORCE);
+                       if (ret < 0 && ret != -ENOSPC) {
+                               btrfs_abort_transaction(trans, root, ret);
+                               return ret;
+                       }
                        if (num_bytes == min_alloc_size)
                                final_tried = true;
                        goto again;
        path->leave_spinning = 1;
        ret = btrfs_insert_empty_item(trans, fs_info->extent_root, path,
                                      ins, size);
-       BUG_ON(ret);
+       if (ret) {
+               btrfs_free_path(path);
+               return ret;
+       }
 
        leaf = path->nodes[0];
        extent_item = btrfs_item_ptr(leaf, path->slots[0],
        btrfs_free_path(path);
 
        ret = update_block_group(trans, root, ins->objectid, ins->offset, 1);
-       if (ret) {
+       if (ret) { /* -ENOENT, logic error */
                printk(KERN_ERR "btrfs update block group failed for %llu "
                       "%llu\n", (unsigned long long)ins->objectid,
                       (unsigned long long)ins->offset);
        path->leave_spinning = 1;
        ret = btrfs_insert_empty_item(trans, fs_info->extent_root, path,
                                      ins, size);
-       BUG_ON(ret);
+       if (ret) {
+               btrfs_free_path(path);
+               return ret;
+       }
 
        leaf = path->nodes[0];
        extent_item = btrfs_item_ptr(leaf, path->slots[0],
        btrfs_free_path(path);
 
        ret = update_block_group(trans, root, ins->objectid, ins->offset, 1);
-       if (ret) {
+       if (ret) { /* -ENOENT, logic error */
                printk(KERN_ERR "btrfs update block group failed for %llu "
                       "%llu\n", (unsigned long long)ins->objectid,
                       (unsigned long long)ins->offset);
        if (!caching_ctl) {
                BUG_ON(!block_group_cache_done(block_group));
                ret = btrfs_remove_free_space(block_group, start, num_bytes);
-               BUG_ON(ret);
+               BUG_ON(ret); /* -ENOMEM */
        } else {
                mutex_lock(&caching_ctl->mutex);
 
                if (start >= caching_ctl->progress) {
                        ret = add_excluded_extent(root, start, num_bytes);
-                       BUG_ON(ret);
+                       BUG_ON(ret); /* -ENOMEM */
                } else if (start + num_bytes <= caching_ctl->progress) {
                        ret = btrfs_remove_free_space(block_group,
                                                      start, num_bytes);
-                       BUG_ON(ret);
+                       BUG_ON(ret); /* -ENOMEM */
                } else {
                        num_bytes = caching_ctl->progress - start;
                        ret = btrfs_remove_free_space(block_group,
                                                      start, num_bytes);
-                       BUG_ON(ret);
+                       BUG_ON(ret); /* -ENOMEM */
 
                        start = caching_ctl->progress;
                        num_bytes = ins->objectid + ins->offset -
                                    caching_ctl->progress;
                        ret = add_excluded_extent(root, start, num_bytes);
-                       BUG_ON(ret);
+                       BUG_ON(ret); /* -ENOMEM */
                }
 
                mutex_unlock(&caching_ctl->mutex);
 
        ret = btrfs_update_reserved_bytes(block_group, ins->offset,
                                          RESERVE_ALLOC_NO_ACCOUNT);
-       BUG_ON(ret);
+       BUG_ON(ret); /* logic error */
        btrfs_put_block_group(block_group);
        ret = alloc_reserved_file_extent(trans, root, 0, root_objectid,
                                         0, owner, offset, ins, 1);
 
        buf = btrfs_init_new_buffer(trans, root, ins.objectid,
                                    blocksize, level);
-       BUG_ON(IS_ERR(buf));
+       BUG_ON(IS_ERR(buf)); /* -ENOMEM */
 
        if (root_objectid == BTRFS_TREE_RELOC_OBJECTID) {
                if (parent == 0)
        if (root_objectid != BTRFS_TREE_LOG_OBJECTID) {
                struct btrfs_delayed_extent_op *extent_op;
                extent_op = kmalloc(sizeof(*extent_op), GFP_NOFS);
-               BUG_ON(!extent_op);
+               BUG_ON(!extent_op); /* -ENOMEM */
                if (key)
                        memcpy(&extent_op->key, key, sizeof(extent_op->key));
                else
                                        ins.offset, parent, root_objectid,
                                        level, BTRFS_ADD_DELAYED_EXTENT,
                                        extent_op, for_cow);
-               BUG_ON(ret);
+               BUG_ON(ret); /* -ENOMEM */
        }
        return buf;
 }
                /* We don't lock the tree block, it's OK to be racy here */
                ret = btrfs_lookup_extent_info(trans, root, bytenr, blocksize,
                                               &refs, &flags);
-               BUG_ON(ret);
+               /* We don't care about errors in readahead. */
+               if (ret < 0)
+                       continue;
                BUG_ON(refs == 0);
 
                if (wc->stage == DROP_REFERENCE) {
                                               eb->start, eb->len,
                                               &wc->refs[level],
                                               &wc->flags[level]);
-               BUG_ON(ret);
+               BUG_ON(ret == -ENOMEM);
+               if (ret)
+                       return ret;
                BUG_ON(wc->refs[level] == 0);
        }
 
        if (!(wc->flags[level] & flag)) {
                BUG_ON(!path->locks[level]);
                ret = btrfs_inc_ref(trans, root, eb, 1, wc->for_reloc);
-               BUG_ON(ret);
+               BUG_ON(ret); /* -ENOMEM */
                ret = btrfs_dec_ref(trans, root, eb, 0, wc->for_reloc);
-               BUG_ON(ret);
+               BUG_ON(ret); /* -ENOMEM */
                ret = btrfs_set_disk_extent_flags(trans, root, eb->start,
                                                  eb->len, flag, 0);
-               BUG_ON(ret);
+               BUG_ON(ret); /* -ENOMEM */
                wc->flags[level] |= flag;
        }
 
        ret = btrfs_lookup_extent_info(trans, root, bytenr, blocksize,
                                       &wc->refs[level - 1],
                                       &wc->flags[level - 1]);
-       BUG_ON(ret);
+       if (ret < 0) {
+               btrfs_tree_unlock(next);
+               return ret;
+       }
+
        BUG_ON(wc->refs[level - 1] == 0);
        *lookup_info = 0;
 
 
                ret = btrfs_free_extent(trans, root, bytenr, blocksize, parent,
                                root->root_key.objectid, level - 1, 0, 0);
-               BUG_ON(ret);
+               BUG_ON(ret); /* -ENOMEM */
        }
        btrfs_tree_unlock(next);
        free_extent_buffer(next);
                                                       eb->start, eb->len,
                                                       &wc->refs[level],
                                                       &wc->flags[level]);
-                       BUG_ON(ret);
+                       if (ret < 0) {
+                               btrfs_tree_unlock_rw(eb, path->locks[level]);
+                               return ret;
+                       }
                        BUG_ON(wc->refs[level] == 0);
                        if (wc->refs[level] == 1) {
                                btrfs_tree_unlock_rw(eb, path->locks[level]);
                        else
                                ret = btrfs_dec_ref(trans, root, eb, 0,
                                                    wc->for_reloc);
-                       BUG_ON(ret);
+                       BUG_ON(ret); /* -ENOMEM */
                }
                /* make block locked assertion in clean_tree_block happy */
                if (!path->locks[level] &&
        }
 
        trans = btrfs_start_transaction(tree_root, 0);
-       BUG_ON(IS_ERR(trans));
+       if (IS_ERR(trans)) {
+               err = PTR_ERR(trans);
+               goto out_free;
+       }
 
        if (block_rsv)
                trans->block_rsv = block_rsv;
                path->lowest_level = 0;
                if (ret < 0) {
                        err = ret;
-                       goto out_free;
+                       goto out_end_trans;
                }
                WARN_ON(ret > 0);
 
                                                path->nodes[level]->len,
                                                &wc->refs[level],
                                                &wc->flags[level]);
-                       BUG_ON(ret);
+                       if (ret < 0) {
+                               err = ret;
+                               goto out_end_trans;
+                       }
                        BUG_ON(wc->refs[level] == 0);
 
                        if (level == root_item->drop_level)
                        ret = btrfs_update_root(trans, tree_root,
                                                &root->root_key,
                                                root_item);
-                       BUG_ON(ret);
+                       if (ret) {
+                               btrfs_abort_transaction(trans, tree_root, ret);
+                               err = ret;
+                               goto out_end_trans;
+                       }
 
                        btrfs_end_transaction_throttle(trans, tree_root);
                        trans = btrfs_start_transaction(tree_root, 0);
-                       BUG_ON(IS_ERR(trans));
+                       if (IS_ERR(trans)) {
+                               err = PTR_ERR(trans);
+                               goto out_free;
+                       }
                        if (block_rsv)
                                trans->block_rsv = block_rsv;
                }
        }
        btrfs_release_path(path);
-       BUG_ON(err);
+       if (err)
+               goto out_end_trans;
 
        ret = btrfs_del_root(trans, tree_root, &root->root_key);
-       BUG_ON(ret);
+       if (ret) {
+               btrfs_abort_transaction(trans, tree_root, ret);
+               goto out_end_trans;
+       }
 
        if (root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID) {
                ret = btrfs_find_last_root(tree_root, root->root_key.objectid,
                                           NULL, NULL);
-               BUG_ON(ret < 0);
-               if (ret > 0) {
+               if (ret < 0) {
+                       btrfs_abort_transaction(trans, tree_root, ret);
+                       err = ret;
+                       goto out_end_trans;
+               } else if (ret > 0) {
                        /* if we fail to delete the orphan item this time
                         * around, it'll get picked up the next time.
                         *
                free_extent_buffer(root->commit_root);
                kfree(root);
        }
-out_free:
+out_end_trans:
        btrfs_end_transaction_throttle(trans, tree_root);
+out_free:
        kfree(wc);
        btrfs_free_path(path);
 out:
        BUG_ON(cache->ro);
 
        trans = btrfs_join_transaction(root);
-       BUG_ON(IS_ERR(trans));
+       if (IS_ERR(trans))
+               return PTR_ERR(trans);
 
        alloc_flags = update_block_group_flags(root, cache->flags);
-       if (alloc_flags != cache->flags)
-               do_chunk_alloc(trans, root, 2 * 1024 * 1024, alloc_flags,
-                              CHUNK_ALLOC_FORCE);
+       if (alloc_flags != cache->flags) {
+               ret = do_chunk_alloc(trans, root, 2 * 1024 * 1024, alloc_flags,
+                                    CHUNK_ALLOC_FORCE);
+               if (ret < 0)
+                       goto out;
+       }
 
        ret = set_block_group_ro(cache, 0);
        if (!ret)
                ret = update_space_info(info, cache->flags, found_key.offset,
                                        btrfs_block_group_used(&cache->item),
                                        &space_info);
-               BUG_ON(ret);
+               BUG_ON(ret); /* -ENOMEM */
                cache->space_info = space_info;
                spin_lock(&cache->space_info->lock);
                cache->space_info->bytes_readonly += cache->bytes_super;
                __link_block_group(space_info, cache);
 
                ret = btrfs_add_block_group_cache(root->fs_info, cache);
-               BUG_ON(ret);
+               BUG_ON(ret); /* Logic error */
 
                set_avail_alloc_bits(root->fs_info, cache->flags);
                if (btrfs_chunk_readonly(root, cache->key.objectid))
 
        ret = update_space_info(root->fs_info, cache->flags, size, bytes_used,
                                &cache->space_info);
-       BUG_ON(ret);
+       BUG_ON(ret); /* -ENOMEM */
        update_global_block_rsv(root->fs_info);
 
        spin_lock(&cache->space_info->lock);
        __link_block_group(cache->space_info, cache);
 
        ret = btrfs_add_block_group_cache(root->fs_info, cache);
-       BUG_ON(ret);
+       BUG_ON(ret); /* Logic error */
 
        ret = btrfs_insert_item(trans, extent_root, &cache->key, &cache->item,
                                sizeof(cache->item));
-       BUG_ON(ret);
+       if (ret) {
+               btrfs_abort_transaction(trans, extent_root, ret);
+               return ret;
+       }
 
        set_avail_alloc_bits(extent_root->fs_info, type);
 
        inode = lookup_free_space_inode(tree_root, block_group, path);
        if (!IS_ERR(inode)) {
                ret = btrfs_orphan_add(trans, inode);
-               BUG_ON(ret);
+               if (ret) {
+                       btrfs_add_delayed_iput(inode);
+                       goto out;
+               }
                clear_nlink(inode);
                /* One for the block groups ref */
                spin_lock(&block_group->lock);
 
 
        while (index <= end_index) {
                page = find_get_page(tree->mapping, index);
-               BUG_ON(!page);
+               BUG_ON(!page); /* Pages should be in the extent_io_tree */
                set_page_writeback(page);
                page_cache_release(page);
                index++;
                        goto out_failed;
                }
        }
-       BUG_ON(ret);
+       BUG_ON(ret); /* Only valid values are 0 and -EAGAIN */
 
        /* step three, lock the state bits for the whole range */
        lock_extent_bits(tree, delalloc_start, delalloc_end, 0, &cached_state);
                /* Writeback already completed */
                if (ret == 0)
                        return 1;
-               BUG_ON(ret < 0);
        }
 
        if (!uptodate) {
                                if (ret == 0)
                                        goto error_handled;
                        }
-                       BUG_ON(ret < 0);
                }
 
                if (uptodate) {
        return bio;
 }
 
+/*
+ * Since writes are async, they will only return -ENOMEM.
+ * Reads can return the full range of I/O error conditions.
+ */
 static int __must_check submit_one_bio(int rw, struct bio *bio,
                                       int mirror_num, unsigned long bio_flags)
 {
                    bio_add_page(bio, page, page_size, offset) < page_size) {
                        ret = submit_one_bio(rw, bio, mirror_num,
                                             prev_bio_flags);
-                       BUG_ON(ret < 0);
+                       if (ret < 0)
+                               return ret;
                        bio = NULL;
                } else {
                        return 0;
 
        if (bio_ret)
                *bio_ret = bio;
-       else {
+       else
                ret = submit_one_bio(rw, bio, mirror_num, bio_flags);
-               BUG_ON(ret < 0);
-       }
 
        return ret;
 }
  * basic readpage implementation.  Locked extent state structs are inserted
  * into the tree that are removed when the IO is done (by the end_io
  * handlers)
+ * XXX JDM: This needs looking at to ensure proper page locking
  */
 static int __extent_read_full_page(struct extent_io_tree *tree,
                                   struct page *page,
                                         end_bio_extent_readpage, mirror_num,
                                         *bio_flags,
                                         this_bio_flag);
+                       BUG_ON(ret == -ENOMEM);
                        nr++;
                        *bio_flags = this_bio_flag;
                }
 
        ret = __extent_read_full_page(tree, page, get_extent, &bio, mirror_num,
                                      &bio_flags);
-       if (bio) {
+       if (bio)
                ret = submit_one_bio(READ, bio, mirror_num, bio_flags);
-               BUG_ON(ret < 0);
-       }
        return ret;
 }
 
                                                       delalloc_end,
                                                       &page_started,
                                                       &nr_written);
-                       BUG_ON(ret);
+                       /* File system has been set read-only */
+                       if (ret) {
+                               SetPageError(page);
+                               goto done;
+                       }
                        /*
                         * delalloc_end is already one less than the total
                         * length, so we don't subtract one from
                        rw = WRITE_SYNC;
 
                ret = submit_one_bio(rw, epd->bio, 0, 0);
-               BUG_ON(ret < 0);
+               BUG_ON(ret < 0); /* -ENOMEM */
                epd->bio = NULL;
        }
 }
                page_cache_release(page);
        }
        BUG_ON(!list_empty(pages));
-       if (bio) {
-               int ret = submit_one_bio(READ, bio, 0, bio_flags);
-               BUG_ON(ret < 0);
-       }
+       if (bio)
+               return submit_one_bio(READ, bio, 0, bio_flags);
        return 0;
 }
 
 
        if (bio) {
                err = submit_one_bio(READ, bio, mirror_num, bio_flags);
-               BUG_ON(err < 0);
+               if (err)
+                       return err;
        }
 
        if (ret || wait != WAIT_COMPLETE)
 
                                      sizeof(*item));
        if (ret < 0)
                goto out;
-       BUG_ON(ret);
+       BUG_ON(ret); /* Can't happen */
        leaf = path->nodes[0];
        item = btrfs_item_ptr(leaf, path->slots[0],
                              struct btrfs_file_extent_item);
                offset = page_offset(bvec->bv_page) + bvec->bv_offset;
 
        ordered = btrfs_lookup_ordered_extent(inode, offset);
-       BUG_ON(!ordered);
+       BUG_ON(!ordered); /* Logic error */
        sums->bytenr = ordered->start;
 
        while (bio_index < bio->bi_vcnt) {
 
                        sums = kzalloc(btrfs_ordered_sum_size(root, bytes_left),
                                       GFP_NOFS);
-                       BUG_ON(!sums);
+                       BUG_ON(!sums); /* -ENOMEM */
                        sector_sum = sums->sums;
                        sums->len = bytes_left;
                        ordered = btrfs_lookup_ordered_extent(inode, offset);
-                       BUG_ON(!ordered);
+                       BUG_ON(!ordered); /* Logic error */
                        sums->bytenr = ordered->start;
                }
 
                         * item changed size or key
                         */
                        ret = btrfs_split_item(trans, root, path, &key, offset);
-                       BUG_ON(ret && ret != -EAGAIN);
+                       if (ret && ret != -EAGAIN) {
+                               btrfs_abort_transaction(trans, root, ret);
+                               goto out;
+                       }
 
                        key.offset = end_byte - 1;
                } else {
 
                        split = alloc_extent_map();
                if (!split2)
                        split2 = alloc_extent_map();
-               BUG_ON(!split || !split2);
+               BUG_ON(!split || !split2); /* -ENOMEM */
 
                write_lock(&em_tree->lock);
                em = lookup_extent_mapping(em_tree, start, len);
                        split->flags = flags;
                        split->compress_type = em->compress_type;
                        ret = add_extent_mapping(em_tree, split);
-                       BUG_ON(ret);
+                       BUG_ON(ret); /* Logic error */
                        free_extent_map(split);
                        split = split2;
                        split2 = NULL;
                        }
 
                        ret = add_extent_mapping(em_tree, split);
-                       BUG_ON(ret);
+                       BUG_ON(ret); /* Logic error */
                        free_extent_map(split);
                        split = NULL;
                }
                                                root->root_key.objectid,
                                                new_key.objectid,
                                                start - extent_offset, 0);
-                               BUG_ON(ret);
+                               BUG_ON(ret); /* -ENOMEM */
                                *hint_byte = disk_bytenr;
                        }
                        key.offset = start;
                                                root->root_key.objectid,
                                                key.objectid, key.offset -
                                                extent_offset, 0);
-                               BUG_ON(ret);
+                               BUG_ON(ret); /* -ENOMEM */
                                inode_sub_bytes(inode,
                                                extent_end - key.offset);
                                *hint_byte = disk_bytenr;
 
                        ret = btrfs_del_items(trans, root, path, del_slot,
                                              del_nr);
-                       BUG_ON(ret);
+                       if (ret) {
+                               btrfs_abort_transaction(trans, root, ret);
+                               goto out;
+                       }
 
                        del_nr = 0;
                        del_slot = 0;
                BUG_ON(1);
        }
 
-       if (del_nr > 0) {
+       if (!ret && del_nr > 0) {
                ret = btrfs_del_items(trans, root, path, del_slot, del_nr);
-               BUG_ON(ret);
+               if (ret)
+                       btrfs_abort_transaction(trans, root, ret);
        }
 
+out:
        btrfs_free_path(path);
        return ret;
 }
                        btrfs_release_path(path);
                        goto again;
                }
-               BUG_ON(ret < 0);
+               if (ret < 0) {
+                       btrfs_abort_transaction(trans, root, ret);
+                       goto out;
+               }
 
                leaf = path->nodes[0];
                fi = btrfs_item_ptr(leaf, path->slots[0] - 1,
                ret = btrfs_inc_extent_ref(trans, root, bytenr, num_bytes, 0,
                                           root->root_key.objectid,
                                           ino, orig_offset, 0);
-               BUG_ON(ret);
+               BUG_ON(ret); /* -ENOMEM */
 
                if (split == start) {
                        key.offset = start;
                ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
                                        0, root->root_key.objectid,
                                        ino, orig_offset, 0);
-               BUG_ON(ret);
+               BUG_ON(ret); /* -ENOMEM */
        }
        other_start = 0;
        other_end = start;
                ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
                                        0, root->root_key.objectid,
                                        ino, orig_offset, 0);
-               BUG_ON(ret);
+               BUG_ON(ret); /* -ENOMEM */
        }
        if (del_nr == 0) {
                fi = btrfs_item_ptr(leaf, path->slots[0],
                btrfs_mark_buffer_dirty(leaf);
 
                ret = btrfs_del_items(trans, root, path, del_slot, del_nr);
-               BUG_ON(ret);
+               if (ret < 0) {
+                       btrfs_abort_transaction(trans, root, ret);
+                       goto out;
+               }
        }
 out:
        btrfs_free_path(path);
 
                em = btrfs_get_extent(inode, NULL, 0, cur_offset,
                                      alloc_end - cur_offset, 0);
-               BUG_ON(IS_ERR_OR_NULL(em));
+               if (IS_ERR_OR_NULL(em)) {
+                       if (!em)
+                               ret = -ENOMEM;
+                       else
+                               ret = PTR_ERR(em);
+                       break;
+               }
                last_byte = min(extent_map_end(em), alloc_end);
                actual_end = min_t(u64, extent_map_end(em), offset + len);
                last_byte = (last_byte + mask) & ~mask;
 
 
        if (ret) {
                trans->block_rsv = rsv;
-               WARN_ON(1);
+               btrfs_abort_transaction(trans, root, ret);
                return ret;
        }
 
        ret = btrfs_update_inode(trans, root, inode);
+       if (ret)
+               btrfs_abort_transaction(trans, root, ret);
        trans->block_rsv = rsv;
 
        return ret;
                 */
                ret = btrfs_add_free_space(block_group, old_start,
                                           offset - old_start);
-               WARN_ON(ret);
+               WARN_ON(ret); /* -ENOMEM */
                goto out;
        }
 
        ret = remove_from_bitmap(ctl, info, &offset, &bytes);
        if (ret == -EAGAIN)
                goto again;
-       BUG_ON(ret);
+       BUG_ON(ret); /* logic error */
 out_lock:
        spin_unlock(&ctl->tree_lock);
 out:
        rb_erase(&entry->offset_index, &ctl->free_space_offset);
        ret = tree_insert_offset(&cluster->root, entry->offset,
                                 &entry->offset_index, 1);
-       BUG_ON(ret);
+       BUG_ON(ret); /* -EEXIST; Logic error */
 
        trace_btrfs_setup_cluster(block_group, cluster,
                                  total_found * block_group->sectorsize, 1);
                ret = tree_insert_offset(&cluster->root, entry->offset,
                                         &entry->offset_index, 0);
                total_size += entry->bytes;
-               BUG_ON(ret);
+               BUG_ON(ret); /* -EEXIST; Logic error */
        } while (node && entry != last);
 
        cluster->max_size = max_extent;
                int ret;
 
                ret = search_bitmap(ctl, entry, &offset, &count);
+               /* Logic error; Should be empty if it can't find anything */
                BUG_ON(ret);
 
                ino = offset;
 
        return ret;
 }
 
+/* Will return 0, -ENOMEM, -EMLINK, or -EEXIST or anything from the CoW path */
 int btrfs_insert_inode_ref(struct btrfs_trans_handle *trans,
                           struct btrfs_root *root,
                           const char *name, int name_len,
 
 
        tsk = kthread_run(caching_kthread, root, "btrfs-ino-cache-%llu\n",
                          root->root_key.objectid);
-       BUG_ON(IS_ERR(tsk));
+       BUG_ON(IS_ERR(tsk)); /* -ENOMEM */
 }
 
 int btrfs_find_free_ino(struct btrfs_root *root, u64 *objectid)
                        break;
 
                info = rb_entry(n, struct btrfs_free_space, offset_index);
-               BUG_ON(info->bitmap);
+               BUG_ON(info->bitmap); /* Logic error */
 
                if (info->offset > root->cache_progress)
                        goto free;
                                      trans->bytes_reserved, 1);
 again:
        inode = lookup_free_ino_inode(root, path);
-       if (IS_ERR(inode) && PTR_ERR(inode) != -ENOENT) {
+       if (IS_ERR(inode) && (PTR_ERR(inode) != -ENOENT || retry)) {
                ret = PTR_ERR(inode);
                goto out_release;
        }
 
        if (IS_ERR(inode)) {
-               BUG_ON(retry);
+               BUG_ON(retry); /* Logic error */
                retry = true;
 
                ret = create_free_ino_inode(root, trans, path);
 
        BTRFS_I(inode)->generation = 0;
        ret = btrfs_update_inode(trans, root, inode);
-       WARN_ON(ret);
+       if (ret) {
+               btrfs_abort_transaction(trans, root, ret);
+               goto out_put;
+       }
 
        if (i_size_read(inode) > 0) {
                ret = btrfs_truncate_free_space_cache(root, trans, path, inode);
-               if (ret)
+               if (ret) {
+                       btrfs_abort_transaction(trans, root, ret);
                        goto out_put;
+               }
        }
 
        spin_lock(&root->cache_lock);
        ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0);
        if (ret < 0)
                goto error;
-       BUG_ON(ret == 0);
+       BUG_ON(ret == 0); /* Corruption */
        if (path->slots[0] > 0) {
                slot = path->slots[0] - 1;
                l = path->nodes[0];
 
        inode_add_bytes(inode, size);
        ret = btrfs_insert_empty_item(trans, root, path, &key,
                                      datasize);
-       BUG_ON(ret);
        if (ret) {
                err = ret;
                goto fail;
         * could end up racing with unlink.
         */
        BTRFS_I(inode)->disk_i_size = inode->i_size;
-       btrfs_update_inode(trans, root, inode);
+       ret = btrfs_update_inode(trans, root, inode);
 
-       return 0;
+       return ret;
 fail:
        btrfs_free_path(path);
        return err;
 
        ret = btrfs_drop_extents(trans, inode, start, aligned_end,
                                 &hint_byte, 1);
-       BUG_ON(ret);
+       if (ret)
+               return ret;
 
        if (isize > actual_end)
                inline_len = min_t(u64, isize, actual_end);
        ret = insert_inline_extent(trans, root, inode, start,
                                   inline_len, compressed_size,
                                   compress_type, compressed_pages);
-       BUG_ON(ret);
+       if (ret) {
+               btrfs_abort_transaction(trans, root, ret);
+               return ret;
+       }
        btrfs_delalloc_release_metadata(inode, end + 1 - start);
        btrfs_drop_extent_cache(inode, start, aligned_end - 1, 0);
        return 0;
        struct async_extent *async_extent;
 
        async_extent = kmalloc(sizeof(*async_extent), GFP_NOFS);
-       BUG_ON(!async_extent);
+       BUG_ON(!async_extent); /* -ENOMEM */
        async_extent->start = start;
        async_extent->ram_size = ram_size;
        async_extent->compressed_size = compressed_size;
 cont:
        if (start == 0) {
                trans = btrfs_join_transaction(root);
-               BUG_ON(IS_ERR(trans));
+               if (IS_ERR(trans)) {
+                       ret = PTR_ERR(trans);
+                       trans = NULL;
+                       goto cleanup_and_out;
+               }
                trans->block_rsv = &root->fs_info->delalloc_block_rsv;
 
                /* lets try to make an inline extent */
                                                    total_compressed,
                                                    compress_type, pages);
                }
-               if (ret == 0) {
+               if (ret <= 0) {
                        /*
-                        * inline extent creation worked, we don't need
-                        * to create any more async work items.  Unlock
-                        * and free up our temp pages.
+                        * inline extent creation worked or returned error,
+                        * we don't need to create any more async work items.
+                        * Unlock and free up our temp pages.
                         */
                        extent_clear_unlock_delalloc(inode,
                             &BTRFS_I(inode)->io_tree,
        }
 
 out:
-       return 0;
+       return ret;
 
 free_pages_out:
        for (i = 0; i < nr_pages_ret; i++) {
        kfree(pages);
 
        goto out;
+
+cleanup_and_out:
+       extent_clear_unlock_delalloc(inode, &BTRFS_I(inode)->io_tree,
+                                    start, end, NULL,
+                                    EXTENT_CLEAR_UNLOCK_PAGE |
+                                    EXTENT_CLEAR_DIRTY |
+                                    EXTENT_CLEAR_DELALLOC |
+                                    EXTENT_SET_WRITEBACK |
+                                    EXTENT_END_WRITEBACK);
+       if (!trans || IS_ERR(trans))
+               btrfs_error(root->fs_info, ret, "Failed to join transaction");
+       else
+               btrfs_abort_transaction(trans, root, ret);
+       goto free_pages_out;
 }
 
 /*
                                             async_extent->ram_size - 1,
                                             &page_started, &nr_written, 0);
 
+                       /* JDM XXX */
+
                        /*
                         * if page_started, cow_file_range inserted an
                         * inline extent and took care of all the unlocking
                            async_extent->start + async_extent->ram_size - 1);
 
                trans = btrfs_join_transaction(root);
-               BUG_ON(IS_ERR(trans));
-               trans->block_rsv = &root->fs_info->delalloc_block_rsv;
-               ret = btrfs_reserve_extent(trans, root,
+               if (IS_ERR(trans)) {
+                       ret = PTR_ERR(trans);
+               } else {
+                       trans->block_rsv = &root->fs_info->delalloc_block_rsv;
+                       ret = btrfs_reserve_extent(trans, root,
                                           async_extent->compressed_size,
                                           async_extent->compressed_size,
                                           0, alloc_hint,
                                           (u64)-1, &ins, 1);
-               btrfs_end_transaction(trans, root);
+                       if (ret)
+                               btrfs_abort_transaction(trans, root, ret);
+                       btrfs_end_transaction(trans, root);
+               }
 
                if (ret) {
                        int i;
                        unlock_extent(io_tree, async_extent->start,
                                      async_extent->start +
                                      async_extent->ram_size - 1);
-                       goto retry;
+                       if (ret == -ENOSPC)
+                               goto retry;
+                       goto out_free; /* JDM: Requeue? */
                }
 
                /*
                                        async_extent->ram_size - 1, 0);
 
                em = alloc_extent_map();
-               BUG_ON(!em);
+               BUG_ON(!em); /* -ENOMEM */
                em->start = async_extent->start;
                em->len = async_extent->ram_size;
                em->orig_start = em->start;
                                                ins.offset,
                                                BTRFS_ORDERED_COMPRESSED,
                                                async_extent->compress_type);
-               BUG_ON(ret);
+               BUG_ON(ret); /* -ENOMEM */
 
                /*
                 * clear dirty, set writeback and unlock the pages.
                                    ins.offset, async_extent->pages,
                                    async_extent->nr_pages);
 
-               BUG_ON(ret);
+               BUG_ON(ret); /* -ENOMEM */
                alloc_hint = ins.objectid + ins.offset;
                kfree(async_extent);
                cond_resched();
        }
-
-       return 0;
+       ret = 0;
+out:
+       return ret;
+out_free:
+       kfree(async_extent);
+       goto out;
 }
 
 static u64 get_extent_allocation_hint(struct inode *inode, u64 start,
 
        BUG_ON(btrfs_is_free_space_inode(root, inode));
        trans = btrfs_join_transaction(root);
-       BUG_ON(IS_ERR(trans));
+       if (IS_ERR(trans)) {
+               extent_clear_unlock_delalloc(inode,
+                            &BTRFS_I(inode)->io_tree,
+                            start, end, NULL,
+                            EXTENT_CLEAR_UNLOCK_PAGE |
+                            EXTENT_CLEAR_UNLOCK |
+                            EXTENT_CLEAR_DELALLOC |
+                            EXTENT_CLEAR_DIRTY |
+                            EXTENT_SET_WRITEBACK |
+                            EXTENT_END_WRITEBACK);
+               return PTR_ERR(trans);
+       }
        trans->block_rsv = &root->fs_info->delalloc_block_rsv;
 
        num_bytes = (end - start + blocksize) & ~(blocksize - 1);
                        *nr_written = *nr_written +
                             (end - start + PAGE_CACHE_SIZE) / PAGE_CACHE_SIZE;
                        *page_started = 1;
-                       ret = 0;
                        goto out;
+               } else if (ret < 0) {
+                       btrfs_abort_transaction(trans, root, ret);
+                       goto out_unlock;
                }
        }
 
                ret = btrfs_reserve_extent(trans, root, cur_alloc_size,
                                           root->sectorsize, 0, alloc_hint,
                                           (u64)-1, &ins, 1);
-               BUG_ON(ret);
+               if (ret < 0) {
+                       btrfs_abort_transaction(trans, root, ret);
+                       goto out_unlock;
+               }
 
                em = alloc_extent_map();
-               BUG_ON(!em);
+               BUG_ON(!em); /* -ENOMEM */
                em->start = start;
                em->orig_start = em->start;
                ram_size = ins.offset;
                cur_alloc_size = ins.offset;
                ret = btrfs_add_ordered_extent(inode, start, ins.objectid,
                                               ram_size, cur_alloc_size, 0);
-               BUG_ON(ret);
+               BUG_ON(ret); /* -ENOMEM */
 
                if (root->root_key.objectid ==
                    BTRFS_DATA_RELOC_TREE_OBJECTID) {
                        ret = btrfs_reloc_clone_csums(inode, start,
                                                      cur_alloc_size);
-                       BUG_ON(ret);
+                       if (ret) {
+                               btrfs_abort_transaction(trans, root, ret);
+                               goto out_unlock;
+                       }
                }
 
                if (disk_num_bytes < cur_alloc_size)
                alloc_hint = ins.objectid + ins.offset;
                start += cur_alloc_size;
        }
-out:
        ret = 0;
+out:
        btrfs_end_transaction(trans, root);
 
        return ret;
+out_unlock:
+       extent_clear_unlock_delalloc(inode,
+                    &BTRFS_I(inode)->io_tree,
+                    start, end, NULL,
+                    EXTENT_CLEAR_UNLOCK_PAGE |
+                    EXTENT_CLEAR_UNLOCK |
+                    EXTENT_CLEAR_DELALLOC |
+                    EXTENT_CLEAR_DIRTY |
+                    EXTENT_SET_WRITEBACK |
+                    EXTENT_END_WRITEBACK);
+
+       goto out;
 }
 
 /*
                         1, 0, NULL, GFP_NOFS);
        while (start < end) {
                async_cow = kmalloc(sizeof(*async_cow), GFP_NOFS);
-               BUG_ON(!async_cow);
+               BUG_ON(!async_cow); /* -ENOMEM */
                async_cow->inode = inode;
                async_cow->root = root;
                async_cow->locked_page = locked_page;
        u64 disk_bytenr;
        u64 num_bytes;
        int extent_type;
-       int ret;
+       int ret, err;
        int type;
        int nocow;
        int check_prev = 1;
        else
                trans = btrfs_join_transaction(root);
 
-       BUG_ON(IS_ERR(trans));
+       if (IS_ERR(trans)) {
+               btrfs_free_path(path);
+               return PTR_ERR(trans);
+       }
+
        trans->block_rsv = &root->fs_info->delalloc_block_rsv;
 
        cow_start = (u64)-1;
        while (1) {
                ret = btrfs_lookup_file_extent(trans, root, path, ino,
                                               cur_offset, 0);
-               BUG_ON(ret < 0);
+               if (ret < 0) {
+                       btrfs_abort_transaction(trans, root, ret);
+                       goto error;
+               }
                if (ret > 0 && path->slots[0] > 0 && check_prev) {
                        leaf = path->nodes[0];
                        btrfs_item_key_to_cpu(leaf, &found_key,
                leaf = path->nodes[0];
                if (path->slots[0] >= btrfs_header_nritems(leaf)) {
                        ret = btrfs_next_leaf(root, path);
-                       if (ret < 0)
-                               BUG_ON(1);
+                       if (ret < 0) {
+                               btrfs_abort_transaction(trans, root, ret);
+                               goto error;
+                       }
                        if (ret > 0)
                                break;
                        leaf = path->nodes[0];
                        ret = cow_file_range(inode, locked_page, cow_start,
                                        found_key.offset - 1, page_started,
                                        nr_written, 1);
-                       BUG_ON(ret);
+                       if (ret) {
+                               btrfs_abort_transaction(trans, root, ret);
+                               goto error;
+                       }
                        cow_start = (u64)-1;
                }
 
                        struct extent_map_tree *em_tree;
                        em_tree = &BTRFS_I(inode)->extent_tree;
                        em = alloc_extent_map();
-                       BUG_ON(!em);
+                       BUG_ON(!em); /* -ENOMEM */
                        em->start = cur_offset;
                        em->orig_start = em->start;
                        em->len = num_bytes;
 
                ret = btrfs_add_ordered_extent(inode, cur_offset, disk_bytenr,
                                               num_bytes, num_bytes, type);
-               BUG_ON(ret);
+               BUG_ON(ret); /* -ENOMEM */
 
                if (root->root_key.objectid ==
                    BTRFS_DATA_RELOC_TREE_OBJECTID) {
                        ret = btrfs_reloc_clone_csums(inode, cur_offset,
                                                      num_bytes);
-                       BUG_ON(ret);
+                       if (ret) {
+                               btrfs_abort_transaction(trans, root, ret);
+                               goto error;
+                       }
                }
 
                extent_clear_unlock_delalloc(inode, &BTRFS_I(inode)->io_tree,
        if (cow_start != (u64)-1) {
                ret = cow_file_range(inode, locked_page, cow_start, end,
                                     page_started, nr_written, 1);
-               BUG_ON(ret);
+               if (ret) {
+                       btrfs_abort_transaction(trans, root, ret);
+                       goto error;
+               }
        }
 
+error:
        if (nolock) {
-               ret = btrfs_end_transaction_nolock(trans, root);
-               BUG_ON(ret);
+               err = btrfs_end_transaction_nolock(trans, root);
        } else {
-               ret = btrfs_end_transaction(trans, root);
-               BUG_ON(ret);
+               err = btrfs_end_transaction(trans, root);
        }
+       if (!ret)
+               ret = err;
+
        btrfs_free_path(path);
-       return 0;
+       return ret;
 }
 
 /*
        int ret = 0;
 
        ret = btrfs_csum_one_bio(root, inode, bio, 0, 0);
-       BUG_ON(ret);
+       BUG_ON(ret); /* -ENOMEM */
        return 0;
 }
 
         */
        ret = btrfs_drop_extents(trans, inode, file_pos, file_pos + num_bytes,
                                 &hint, 0);
-       BUG_ON(ret);
+       if (ret)
+               goto out;
 
        ins.objectid = btrfs_ino(inode);
        ins.offset = file_pos;
        ins.type = BTRFS_EXTENT_DATA_KEY;
        ret = btrfs_insert_empty_item(trans, root, path, &ins, sizeof(*fi));
-       BUG_ON(ret);
+       if (ret)
+               goto out;
        leaf = path->nodes[0];
        fi = btrfs_item_ptr(leaf, path->slots[0],
                            struct btrfs_file_extent_item);
        ret = btrfs_alloc_reserved_file_extent(trans, root,
                                        root->root_key.objectid,
                                        btrfs_ino(inode), file_pos, &ins);
-       BUG_ON(ret);
+out:
        btrfs_free_path(path);
 
-       return 0;
+       return ret;
 }
 
 /*
                                             end - start + 1);
        if (!ret)
                return 0;
-       BUG_ON(!ordered_extent);
+       BUG_ON(!ordered_extent); /* Logic error */
 
        nolock = btrfs_is_free_space_inode(root, inode);
 
        if (test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags)) {
-               BUG_ON(!list_empty(&ordered_extent->list));
+               BUG_ON(!list_empty(&ordered_extent->list)); /* Logic error */
                ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent);
                if (!ret) {
                        if (nolock)
                                trans = btrfs_join_transaction_nolock(root);
                        else
                                trans = btrfs_join_transaction(root);
-                       BUG_ON(IS_ERR(trans));
+                       if (IS_ERR(trans))
+                               return PTR_ERR(trans);
                        trans->block_rsv = &root->fs_info->delalloc_block_rsv;
                        ret = btrfs_update_inode_fallback(trans, root, inode);
-                       BUG_ON(ret);
+                       if (ret) /* -ENOMEM or corruption */
+                               btrfs_abort_transaction(trans, root, ret);
                }
                goto out;
        }
                trans = btrfs_join_transaction_nolock(root);
        else
                trans = btrfs_join_transaction(root);
-       BUG_ON(IS_ERR(trans));
+       if (IS_ERR(trans)) {
+               ret = PTR_ERR(trans);
+               trans = NULL;
+               goto out_unlock;
+       }
        trans->block_rsv = &root->fs_info->delalloc_block_rsv;
 
        if (test_bit(BTRFS_ORDERED_COMPRESSED, &ordered_extent->flags))
                                                ordered_extent->file_offset,
                                                ordered_extent->file_offset +
                                                ordered_extent->len);
-               BUG_ON(ret);
        } else {
                BUG_ON(root == root->fs_info->tree_root);
                ret = insert_reserved_file_extent(trans, inode,
                unpin_extent_cache(&BTRFS_I(inode)->extent_tree,
                                   ordered_extent->file_offset,
                                   ordered_extent->len);
-               BUG_ON(ret);
        }
        unlock_extent_cached(io_tree, ordered_extent->file_offset,
                             ordered_extent->file_offset +
                             ordered_extent->len - 1, &cached_state, GFP_NOFS);
+       if (ret < 0) {
+               btrfs_abort_transaction(trans, root, ret);
+               goto out;
+       }
 
        add_pending_csums(trans, inode, ordered_extent->file_offset,
                          &ordered_extent->list);
        ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent);
        if (!ret || !test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) {
                ret = btrfs_update_inode_fallback(trans, root, inode);
-               BUG_ON(ret);
+               if (ret) { /* -ENOMEM or corruption */
+                       btrfs_abort_transaction(trans, root, ret);
+                       goto out;
+               }
        }
        ret = 0;
 out:
        btrfs_put_ordered_extent(ordered_extent);
 
        return 0;
+out_unlock:
+       unlock_extent_cached(io_tree, ordered_extent->file_offset,
+                            ordered_extent->file_offset +
+                            ordered_extent->len - 1, &cached_state, GFP_NOFS);
+       goto out;
 }
 
 static int btrfs_writepage_end_io_hook(struct page *page, u64 start, u64 end,
        struct inode *inode;
 };
 
+/* JDM: If this is fs-wide, why can't we add a pointer to
+ * btrfs_inode instead and avoid the allocation? */
 void btrfs_add_delayed_iput(struct inode *inode)
 {
        struct btrfs_fs_info *fs_info = BTRFS_I(inode)->root->fs_info;
        /* grab metadata reservation from transaction handle */
        if (reserve) {
                ret = btrfs_orphan_reserve_metadata(trans, inode);
-               BUG_ON(ret);
+               BUG_ON(ret); /* -ENOSPC in reservation; Logic error? JDM */
        }
 
        /* insert an orphan item to track this unlinked/truncated file */
        if (insert >= 1) {
                ret = btrfs_insert_orphan_item(trans, root, btrfs_ino(inode));
-               BUG_ON(ret && ret != -EEXIST);
+               if (ret && ret != -EEXIST) {
+                       btrfs_abort_transaction(trans, root, ret);
+                       return ret;
+               }
+               ret = 0;
        }
 
        /* insert an orphan item to track subvolume contains orphan files */
        if (insert >= 2) {
                ret = btrfs_insert_orphan_item(trans, root->fs_info->tree_root,
                                               root->root_key.objectid);
-               BUG_ON(ret);
+               if (ret && ret != -EEXIST) {
+                       btrfs_abort_transaction(trans, root, ret);
+                       return ret;
+               }
        }
        return 0;
 }
 
        if (trans && delete_item) {
                ret = btrfs_del_orphan_item(trans, root, btrfs_ino(inode));
-               BUG_ON(ret);
+               BUG_ON(ret); /* -ENOMEM or corruption (JDM: Recheck) */
        }
 
        if (release_rsv)
                        }
                        ret = btrfs_del_orphan_item(trans, root,
                                                    found_key.objectid);
-                       BUG_ON(ret);
+                       BUG_ON(ret); /* -ENOMEM or corruption (JDM: Recheck) */
                        btrfs_end_transaction(trans, root);
                        continue;
                }
                printk(KERN_INFO "btrfs failed to delete reference to %.*s, "
                       "inode %llu parent %llu\n", name_len, name,
                       (unsigned long long)ino, (unsigned long long)dir_ino);
+               btrfs_abort_transaction(trans, root, ret);
                goto err;
        }
 
        ret = btrfs_delete_delayed_dir_index(trans, root, dir, index);
-       if (ret)
+       if (ret) {
+               btrfs_abort_transaction(trans, root, ret);
                goto err;
+       }
 
        ret = btrfs_del_inode_ref_in_log(trans, root, name, name_len,
                                         inode, dir_ino);
-       BUG_ON(ret != 0 && ret != -ENOENT);
+       if (ret != 0 && ret != -ENOENT) {
+               btrfs_abort_transaction(trans, root, ret);
+               goto err;
+       }
 
        ret = btrfs_del_dir_entries_in_log(trans, root, name, name_len,
                                           dir, index);
                        err = ret;
                        goto out;
                }
-               BUG_ON(ret == 0);
+               BUG_ON(ret == 0); /* Corruption */
                if (check_path_shared(root, path))
                        goto out;
                btrfs_release_path(path);
                err = PTR_ERR(ref);
                goto out;
        }
-       BUG_ON(!ref);
+       BUG_ON(!ref); /* Logic error */
        if (check_path_shared(root, path))
                goto out;
        index = btrfs_inode_ref_index(path->nodes[0], ref);
 
        di = btrfs_lookup_dir_item(trans, root, path, dir_ino,
                                   name, name_len, -1);
-       BUG_ON(IS_ERR_OR_NULL(di));
+       if (IS_ERR_OR_NULL(di)) {
+               if (!di)
+                       ret = -ENOENT;
+               else
+                       ret = PTR_ERR(di);
+               goto out;
+       }
 
        leaf = path->nodes[0];
        btrfs_dir_item_key_to_cpu(leaf, di, &key);
        WARN_ON(key.type != BTRFS_ROOT_ITEM_KEY || key.objectid != objectid);
        ret = btrfs_delete_one_dir_name(trans, root, path, di);
-       BUG_ON(ret);
+       if (ret) {
+               btrfs_abort_transaction(trans, root, ret);
+               goto out;
+       }
        btrfs_release_path(path);
 
        ret = btrfs_del_root_ref(trans, root->fs_info->tree_root,
                                 objectid, root->root_key.objectid,
                                 dir_ino, &index, name, name_len);
        if (ret < 0) {
-               BUG_ON(ret != -ENOENT);
+               if (ret != -ENOENT) {
+                       btrfs_abort_transaction(trans, root, ret);
+                       goto out;
+               }
                di = btrfs_search_dir_index_item(root, path, dir_ino,
                                                 name, name_len);
-               BUG_ON(IS_ERR_OR_NULL(di));
+               if (IS_ERR_OR_NULL(di)) {
+                       if (!di)
+                               ret = -ENOENT;
+                       else
+                               ret = PTR_ERR(di);
+                       btrfs_abort_transaction(trans, root, ret);
+                       goto out;
+               }
 
                leaf = path->nodes[0];
                btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
        btrfs_release_path(path);
 
        ret = btrfs_delete_delayed_dir_index(trans, root, dir, index);
-       BUG_ON(ret);
+       if (ret) {
+               btrfs_abort_transaction(trans, root, ret);
+               goto out;
+       }
 
        btrfs_i_size_write(dir, dir->i_size - name_len * 2);
        dir->i_mtime = dir->i_ctime = CURRENT_TIME;
        ret = btrfs_update_inode(trans, root, dir);
-       BUG_ON(ret);
-
+       if (ret)
+               btrfs_abort_transaction(trans, root, ret);
+out:
        btrfs_free_path(path);
-       return 0;
+       return ret;
 }
 
 static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
                                ret = btrfs_del_items(trans, root, path,
                                                pending_del_slot,
                                                pending_del_nr);
-                               BUG_ON(ret);
+                               if (ret) {
+                                       btrfs_abort_transaction(trans,
+                                                               root, ret);
+                                       goto error;
+                               }
                                pending_del_nr = 0;
                        }
                        btrfs_release_path(path);
        if (pending_del_nr) {
                ret = btrfs_del_items(trans, root, path, pending_del_slot,
                                      pending_del_nr);
-               BUG_ON(ret);
+               if (ret)
+                       btrfs_abort_transaction(trans, root, ret);
        }
+error:
        btrfs_free_path(path);
        return err;
 }
        while (1) {
                em = btrfs_get_extent(inode, NULL, 0, cur_offset,
                                block_end - cur_offset, 0);
-               BUG_ON(IS_ERR_OR_NULL(em));
+               if (IS_ERR(em)) {
+                       err = PTR_ERR(em);
+                       break;
+               }
                last_byte = min(extent_map_end(em), block_end);
                last_byte = (last_byte + mask) & ~mask;
                if (!test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) {
                                                 cur_offset + hole_size,
                                                 &hint_byte, 1);
                        if (err) {
-                               btrfs_update_inode(trans, root, inode);
+                               btrfs_abort_transaction(trans, root, err);
                                btrfs_end_transaction(trans, root);
                                break;
                        }
                                        0, hole_size, 0, hole_size,
                                        0, 0, 0);
                        if (err) {
-                               btrfs_update_inode(trans, root, inode);
+                               btrfs_abort_transaction(trans, root, err);
                                btrfs_end_transaction(trans, root);
                                break;
                        }
                                             parent_ino, index);
        }
 
-       if (ret == 0) {
-               ret = btrfs_insert_dir_item(trans, root, name, name_len,
-                                           parent_inode, &key,
-                                           btrfs_inode_type(inode), index);
-               if (ret)
-                       goto fail_dir_item;
+       /* Nothing to clean up yet */
+       if (ret)
+               return ret;
 
-               btrfs_i_size_write(parent_inode, parent_inode->i_size +
-                                  name_len * 2);
-               parent_inode->i_mtime = parent_inode->i_ctime = CURRENT_TIME;
-               ret = btrfs_update_inode(trans, root, parent_inode);
+       ret = btrfs_insert_dir_item(trans, root, name, name_len,
+                                   parent_inode, &key,
+                                   btrfs_inode_type(inode), index);
+       if (ret == -EEXIST)
+               goto fail_dir_item;
+       else if (ret) {
+               btrfs_abort_transaction(trans, root, ret);
+               return ret;
        }
+
+       btrfs_i_size_write(parent_inode, parent_inode->i_size +
+                          name_len * 2);
+       parent_inode->i_mtime = parent_inode->i_ctime = CURRENT_TIME;
+       ret = btrfs_update_inode(trans, root, parent_inode);
+       if (ret)
+               btrfs_abort_transaction(trans, root, ret);
        return ret;
 
 fail_dir_item:
        } else {
                struct dentry *parent = dentry->d_parent;
                err = btrfs_update_inode(trans, root, inode);
-               BUG_ON(err);
+               if (err)
+                       goto fail;
                d_instantiate(dentry, inode);
                btrfs_log_new_name(trans, inode, NULL, parent);
        }
                                ret = uncompress_inline(path, inode, page,
                                                        pg_offset,
                                                        extent_offset, item);
-                               BUG_ON(ret);
+                               BUG_ON(ret); /* -ENOMEM */
                        } else {
                                map = kmap(page);
                                read_extent_buffer(leaf, map + pg_offset, ptr,
                free_extent_map(em);
                return ERR_PTR(err);
        }
+       BUG_ON(!em); /* Error is always set */
        return em;
 }
 
        int ret;
        struct btrfs_root *root = BTRFS_I(inode)->root;
        ret = btrfs_csum_one_bio(root, inode, bio, offset, 1);
-       BUG_ON(ret);
+       BUG_ON(ret); /* -ENOMEM */
        return 0;
 }
 
                if (!ret)
                        ret = btrfs_update_inode(trans, root, old_inode);
        }
-       BUG_ON(ret);
+       if (ret) {
+               btrfs_abort_transaction(trans, root, ret);
+               goto out_fail;
+       }
 
        if (new_inode) {
                new_inode->i_ctime = CURRENT_TIME;
                                                 new_dentry->d_name.name,
                                                 new_dentry->d_name.len);
                }
-               BUG_ON(ret);
-               if (new_inode->i_nlink == 0) {
+               if (!ret && new_inode->i_nlink == 0) {
                        ret = btrfs_orphan_add(trans, new_dentry->d_inode);
                        BUG_ON(ret);
                }
+               if (ret) {
+                       btrfs_abort_transaction(trans, root, ret);
+                       goto out_fail;
+               }
        }
 
        fixup_inode_flags(new_dir, old_inode);
        ret = btrfs_add_link(trans, new_dir, old_inode,
                             new_dentry->d_name.name,
                             new_dentry->d_name.len, 0, index);
-       BUG_ON(ret);
+       if (ret) {
+               btrfs_abort_transaction(trans, root, ret);
+               goto out_fail;
+       }
 
        if (old_ino != BTRFS_FIRST_FREE_OBJECTID) {
                struct dentry *parent = new_dentry->d_parent;
                                                  ins.offset, ins.offset,
                                                  ins.offset, 0, 0, 0,
                                                  BTRFS_FILE_EXTENT_PREALLOC);
-               BUG_ON(ret);
+               if (ret) {
+                       btrfs_abort_transaction(trans, root, ret);
+                       if (own_trans)
+                               btrfs_end_transaction(trans, root);
+                       break;
+               }
                btrfs_drop_extent_cache(inode, cur_offset,
                                        cur_offset + ins.offset -1, 0);
 
                }
 
                ret = btrfs_update_inode(trans, root, inode);
-               BUG_ON(ret);
+
+               if (ret) {
+                       btrfs_abort_transaction(trans, root, ret);
+                       if (own_trans)
+                               btrfs_end_transaction(trans, root);
+                       break;
+               }
 
                if (own_trans)
                        btrfs_end_transaction(trans, root);
 
 
        key.offset = (u64)-1;
        new_root = btrfs_read_fs_root_no_name(root->fs_info, &key);
-       BUG_ON(IS_ERR(new_root));
+       if (IS_ERR(new_root)) {
+               btrfs_abort_transaction(trans, root, PTR_ERR(new_root));
+               ret = PTR_ERR(new_root);
+               goto fail;
+       }
 
        btrfs_record_root_in_trans(trans, new_root);
 
        ret = btrfs_create_subvol_root(trans, new_root, new_dirid);
        if (ret) {
                /* We potentially lose an unused inode item here */
+               btrfs_abort_transaction(trans, root, ret);
                goto fail;
        }
 
         * insert the directory item
         */
        ret = btrfs_set_inode_index(dir, &index);
-       BUG_ON(ret);
+       if (ret) {
+               btrfs_abort_transaction(trans, root, ret);
+               goto fail;
+       }
 
        ret = btrfs_insert_dir_item(trans, root,
                                    name, namelen, dir, &key,
                                    BTRFS_FT_DIR, index);
-       if (ret)
+       if (ret) {
+               btrfs_abort_transaction(trans, root, ret);
                goto fail;
+       }
 
        btrfs_i_size_write(dir, dir->i_size + namelen * 2);
        ret = btrfs_update_inode(trans, root, dir);
                                dest->root_key.objectid,
                                dentry->d_name.name,
                                dentry->d_name.len);
-       BUG_ON(ret);
+       if (ret) {
+               err = ret;
+               btrfs_abort_transaction(trans, root, ret);
+               goto out_end_trans;
+       }
 
        btrfs_record_root_in_trans(trans, dest);
 
                ret = btrfs_insert_orphan_item(trans,
                                        root->fs_info->tree_root,
                                        dest->root_key.objectid);
-               BUG_ON(ret);
+               if (ret) {
+                       btrfs_abort_transaction(trans, root, ret);
+                       err = ret;
+                       goto out_end_trans;
+               }
        }
-
+out_end_trans:
        ret = btrfs_end_transaction(trans, root);
-       BUG_ON(ret);
+       if (ret && !err)
+               err = ret;
        inode->i_flags |= S_DEAD;
 out_up_write:
        up_write(&root->fs_info->subvol_sem);
                                                         new_key.offset,
                                                         new_key.offset + datal,
                                                         &hint_byte, 1);
-                               BUG_ON(ret);
+                               if (ret) {
+                                       btrfs_abort_transaction(trans, root,
+                                                               ret);
+                                       btrfs_end_transaction(trans, root);
+                                       goto out;
+                               }
 
                                ret = btrfs_insert_empty_item(trans, root, path,
                                                              &new_key, size);
-                               BUG_ON(ret);
+                               if (ret) {
+                                       btrfs_abort_transaction(trans, root,
+                                                               ret);
+                                       btrfs_end_transaction(trans, root);
+                                       goto out;
+                               }
 
                                leaf = path->nodes[0];
                                slot = path->slots[0];
                                                        btrfs_ino(inode),
                                                        new_key.offset - datao,
                                                        0);
-                                       BUG_ON(ret);
+                                       if (ret) {
+                                               btrfs_abort_transaction(trans,
+                                                                       root,
+                                                                       ret);
+                                               btrfs_end_transaction(trans,
+                                                                     root);
+                                               goto out;
+
+                                       }
                                }
                        } else if (type == BTRFS_FILE_EXTENT_INLINE) {
                                u64 skip = 0;
                                                         new_key.offset,
                                                         new_key.offset + datal,
                                                         &hint_byte, 1);
-                               BUG_ON(ret);
+                               if (ret) {
+                                       btrfs_abort_transaction(trans, root,
+                                                               ret);
+                                       btrfs_end_transaction(trans, root);
+                                       goto out;
+                               }
 
                                ret = btrfs_insert_empty_item(trans, root, path,
                                                              &new_key, size);
-                               BUG_ON(ret);
+                               if (ret) {
+                                       btrfs_abort_transaction(trans, root,
+                                                               ret);
+                                       btrfs_end_transaction(trans, root);
+                                       goto out;
+                               }
 
                                if (skip) {
                                        u32 start =
                                btrfs_i_size_write(inode, endoff);
 
                        ret = btrfs_update_inode(trans, root, inode);
-                       BUG_ON(ret);
-                       btrfs_end_transaction(trans, root);
+                       if (ret) {
+                               btrfs_abort_transaction(trans, root, ret);
+                               btrfs_end_transaction(trans, root);
+                               goto out;
+                       }
+                       ret = btrfs_end_transaction(trans, root);
                }
 next:
                btrfs_release_path(path);
 
        ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
        if (ret < 0)
                goto out;
-       if (ret) {
+       if (ret) { /* JDM: Really? */
                ret = -ENOENT;
                goto out;
        }
 
 static noinline_for_stack int mark_garbage_root(struct btrfs_root *root)
 {
        struct btrfs_trans_handle *trans;
-       int ret;
+       int ret, err;
 
        trans = btrfs_start_transaction(root->fs_info->tree_root, 0);
-       BUG_ON(IS_ERR(trans));
+       if (IS_ERR(trans))
+               return PTR_ERR(trans);
 
        memset(&root->root_item.drop_progress, 0,
                sizeof(root->root_item.drop_progress));
        btrfs_set_root_refs(&root->root_item, 0);
        ret = btrfs_update_root(trans, root->fs_info->tree_root,
                                &root->root_key, &root->root_item);
-       BUG_ON(ret);
 
-       ret = btrfs_end_transaction(trans, root->fs_info->tree_root);
-       BUG_ON(ret);
-       return 0;
+       err = btrfs_end_transaction(trans, root->fs_info->tree_root);
+       if (err)
+               return err;
+       return ret;
 }
 
 /*
                                        err = ret;
                                        goto out;
                                }
-                               mark_garbage_root(reloc_root);
+                               ret = mark_garbage_root(reloc_root);
+                               if (ret < 0) {
+                                       err = ret;
+                                       goto out;
+                               }
                        }
                }
 
 
                fs_root = read_fs_root(root->fs_info,
                                       reloc_root->root_key.offset);
-               BUG_ON(IS_ERR(fs_root));
+               if (IS_ERR(fs_root)) {
+                       err = PTR_ERR(fs_root);
+                       goto out_free;
+               }
 
                err = __add_reloc_root(reloc_root);
-               BUG_ON(err < 0);
+               BUG_ON(err < 0); /* -ENOMEM or logic error */
                fs_root->reloc_root = reloc_root;
        }
 
-       btrfs_commit_transaction(trans, rc->extent_root);
+       err = btrfs_commit_transaction(trans, rc->extent_root);
+       if (err)
+               goto out_free;
 
        merge_reloc_roots(rc);
 
        if (IS_ERR(trans))
                err = PTR_ERR(trans);
        else
-               btrfs_commit_transaction(trans, rc->extent_root);
+               err = btrfs_commit_transaction(trans, rc->extent_root);
 out_free:
        kfree(rc);
 out:
        disk_bytenr = file_pos + BTRFS_I(inode)->index_cnt;
        ret = btrfs_lookup_csums_range(root->fs_info->csum_root, disk_bytenr,
                                       disk_bytenr + len - 1, &list, 0);
+       if (ret)
+               goto out;
 
        while (!list_empty(&list)) {
                sums = list_entry(list.next, struct btrfs_ordered_sum, list);
 
                btrfs_add_ordered_sum(inode, ordered, sums);
        }
+out:
        btrfs_put_ordered_extent(ordered);
        return ret;
 }
 
                return -ENOMEM;
 
        ret = btrfs_search_slot(trans, root, key, path, 0, 1);
-       if (ret < 0)
+       if (ret < 0) {
+               btrfs_abort_transaction(trans, root, ret);
                goto out;
+       }
 
        if (ret != 0) {
                btrfs_print_leaf(root, path->nodes[0]);
  *
  * For a back ref the root_id is the id of the subvol or snapshot and
  * ref_id is the id of the tree referencing it.
+ *
+ * Will return 0, -ENOMEM, or anything from the CoW path
  */
 int btrfs_add_root_ref(struct btrfs_trans_handle *trans,
                       struct btrfs_root *tree_root,
 again:
        ret = btrfs_insert_empty_item(trans, tree_root, path, &key,
                                      sizeof(*ref) + name_len);
-       BUG_ON(ret);
+       if (ret) {
+               btrfs_abort_transaction(trans, tree_root, ret);
+               btrfs_free_path(path);
+               return ret;
+       }
 
        leaf = path->nodes[0];
        ref = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_root_ref);
 
        struct btrfs_device *device = sdev->dev;
        struct btrfs_root *root = device->dev_root;
 
+       if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR)
+               return -EIO;
+
        gen = root->fs_info->last_trans_committed;
 
        for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
 
                               struct btrfs_root *root, const char *function,
                               unsigned int line, int errno)
 {
-       WARN_ON_ONCE(1);
+       WARN_ONCE(1, KERN_DEBUG "btrfs: Transaction aborted");
        trans->aborted = errno;
        /* Nothing used. The other threads that have joined this
         * transaction may be able to continue. */
 
                                dentry->d_name.name, dentry->d_name.len,
                                parent_inode, &key,
                                BTRFS_FT_DIR, index);
-       if (ret) {
+       if (ret == -EEXIST) {
                pending->error = -EEXIST;
                dput(parent);
                goto fail;
-       } else if (ret)
-               goto abort_trans;
+       } else if (ret) {
+               goto abort_trans_dput;
+       }
 
        btrfs_i_size_write(parent_inode, parent_inode->i_size +
                                         dentry->d_name.len * 2);
        ret = btrfs_update_inode(trans, parent_root, parent_inode);
        if (ret)
-               goto abort_trans;
+               goto abort_trans_dput;
 
        /*
         * pull in the delayed directory update
         * snapshot
         */
        ret = btrfs_run_delayed_items(trans, root);
-       if (ret) /* Transaction aborted */
+       if (ret) { /* Transaction aborted */
+               dput(parent);
                goto fail;
+       }
 
        record_root_in_trans(trans, root);
        btrfs_set_root_last_snapshot(&root->root_item, trans->transid);
 
        old = btrfs_lock_root_node(root);
        ret = btrfs_cow_block(trans, root, old, NULL, 0, &old);
-       if (ret)
-               goto abort_trans;
+       if (ret) {
+               btrfs_tree_unlock(old);
+               free_extent_buffer(old);
+               goto abort_trans_dput;
+       }
 
        btrfs_set_lock_blocking(old);
 
        ret = btrfs_copy_root(trans, root, old, &tmp, objectid);
-       if (ret)
-               goto abort_trans;
-
+       /* clean up in any case */
        btrfs_tree_unlock(old);
        free_extent_buffer(old);
+       if (ret)
+               goto abort_trans_dput;
 
        /* see comments in should_cow_block() */
        root->force_cow = 1;
        btrfs_tree_unlock(tmp);
        free_extent_buffer(tmp);
        if (ret)
-               goto abort_trans;
+               goto abort_trans_dput;
 
        /*
         * insert root back/forward references
                                 parent_root->root_key.objectid,
                                 btrfs_ino(parent_inode), index,
                                 dentry->d_name.name, dentry->d_name.len);
+       dput(parent);
        if (ret)
                goto fail;
-       dput(parent);
 
        key.offset = (u64)-1;
        pending->snap = btrfs_read_fs_root_no_name(root->fs_info, &key);
-       if (IS_ERR(pending->snap))
+       if (IS_ERR(pending->snap)) {
+               ret = PTR_ERR(pending->snap);
                goto abort_trans;
+       }
 
        ret = btrfs_reloc_post_snapshot(trans, pending);
        if (ret)
        btrfs_block_rsv_release(root, &pending->block_rsv, (u64)-1);
        return ret;
 
+abort_trans_dput:
+       dput(parent);
 abort_trans:
        btrfs_abort_transaction(trans, root, ret);
        goto fail;
 
                                        BTRFS_TREE_LOG_OBJECTID);
                                ret = btrfs_free_and_pin_reserved_extent(root,
                                                         bytenr, blocksize);
-                               BUG_ON(ret);
+                               BUG_ON(ret); /* -ENOMEM or logic errors */
                        }
                        free_extent_buffer(next);
                        continue;
                wret = walk_down_log_tree(trans, log, path, &level, wc);
                if (wret > 0)
                        break;
-               if (wret < 0)
+               if (wret < 0) {
                        ret = wret;
+                       goto out;
+               }
 
                wret = walk_up_log_tree(trans, log, path, &level, wc);
                if (wret > 0)
                        break;
-               if (wret < 0)
+               if (wret < 0) {
                        ret = wret;
+                       goto out;
+               }
        }
 
        /* was the root node processed? if not, catch it here */
        if (path->nodes[orig_level]) {
-               wc->process_func(log, path->nodes[orig_level], wc,
+               ret = wc->process_func(log, path->nodes[orig_level], wc,
                         btrfs_header_generation(path->nodes[orig_level]));
+               if (ret)
+                       goto out;
                if (wc->free) {
                        struct extent_buffer *next;
 
                                BTRFS_TREE_LOG_OBJECTID);
                        ret = btrfs_free_and_pin_reserved_extent(log, next->start,
                                                         next->len);
-                       BUG_ON(ret);
+                       BUG_ON(ret); /* -ENOMEM or logic errors */
                }
        }
 
+out:
        for (i = 0; i <= orig_level; i++) {
                if (path->nodes[i]) {
                        free_extent_buffer(path->nodes[i]);
         * wait for them until later.
         */
        ret = btrfs_write_marked_extents(log, &log->dirty_log_pages, mark);
-       BUG_ON(ret);
+       if (ret) {
+               btrfs_abort_transaction(trans, root, ret);
+               mutex_unlock(&root->log_mutex);
+               goto out;
+       }
 
        btrfs_set_root_node(&log->root_item, log->node);
 
        }
 
        if (ret) {
-               BUG_ON(ret != -ENOSPC);
+               if (ret != -ENOSPC) {
+                       btrfs_abort_transaction(trans, root, ret);
+                       mutex_unlock(&log_root_tree->log_mutex);
+                       goto out;
+               }
                root->fs_info->last_trans_log_full_commit = trans->transid;
                btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark);
                mutex_unlock(&log_root_tree->log_mutex);
        ret = btrfs_write_and_wait_marked_extents(log_root_tree,
                                &log_root_tree->dirty_log_pages,
                                EXTENT_DIRTY | EXTENT_NEW);
-       BUG_ON(ret);
+       if (ret) {
+               btrfs_abort_transaction(trans, root, ret);
+               mutex_unlock(&log_root_tree->log_mutex);
+               goto out_wake_log_root;
+       }
        btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark);
 
        btrfs_set_super_log_root(root->fs_info->super_for_commit,
        if (ret == -ENOSPC) {
                root->fs_info->last_trans_log_full_commit = trans->transid;
                ret = 0;
-       }
+       } else if (ret < 0)
+               btrfs_abort_transaction(trans, root, ret);
+
        btrfs_end_log_trans(root);
 
        return err;
        if (ret == -ENOSPC) {
                root->fs_info->last_trans_log_full_commit = trans->transid;
                ret = 0;
-       }
+       } else if (ret < 0 && ret != -ENOENT)
+               btrfs_abort_transaction(trans, root, ret);
        btrfs_end_log_trans(root);
 
        return ret;
        fs_info->log_root_recovering = 1;
 
        trans = btrfs_start_transaction(fs_info->tree_root, 0);
-       BUG_ON(IS_ERR(trans));
+       if (IS_ERR(trans)) {
+               ret = PTR_ERR(trans);
+               goto error;
+       }
 
        wc.trans = trans;
        wc.pin = 1;
 
        ret = walk_log_tree(trans, log_root_tree, &wc);
-       BUG_ON(ret);
+       if (ret) {
+               btrfs_error(fs_info, ret, "Failed to pin buffers while "
+                           "recovering log root tree.");
+               goto error;
+       }
 
 again:
        key.objectid = BTRFS_TREE_LOG_OBJECTID;
 
        while (1) {
                ret = btrfs_search_slot(NULL, log_root_tree, &key, path, 0, 0);
-               if (ret < 0)
-                       break;
+
+               if (ret < 0) {
+                       btrfs_error(fs_info, ret,
+                                   "Couldn't find tree log root.");
+                       goto error;
+               }
                if (ret > 0) {
                        if (path->slots[0] == 0)
                                break;
 
                log = btrfs_read_fs_root_no_radix(log_root_tree,
                                                  &found_key);
-               BUG_ON(IS_ERR(log));
+               if (IS_ERR(log)) {
+                       ret = PTR_ERR(log);
+                       btrfs_error(fs_info, ret,
+                                   "Couldn't read tree log root.");
+                       goto error;
+               }
 
                tmp_key.objectid = found_key.offset;
                tmp_key.type = BTRFS_ROOT_ITEM_KEY;
                tmp_key.offset = (u64)-1;
 
                wc.replay_dest = btrfs_read_fs_root_no_name(fs_info, &tmp_key);
-               BUG_ON(IS_ERR_OR_NULL(wc.replay_dest));
+               if (IS_ERR(wc.replay_dest)) {
+                       ret = PTR_ERR(wc.replay_dest);
+                       btrfs_error(fs_info, ret, "Couldn't read target root "
+                                   "for tree log recovery.");
+                       goto error;
+               }
 
                wc.replay_dest->log_root = log;
                btrfs_record_root_in_trans(trans, wc.replay_dest);
 
        kfree(log_root_tree);
        return 0;
+
+error:
+       btrfs_free_path(path);
+       return ret;
 }
 
 /*
 
                        fs_devices->num_can_discard--;
 
                new_device = kmalloc(sizeof(*new_device), GFP_NOFS);
-               BUG_ON(!new_device);
+               BUG_ON(!new_device); /* -ENOMEM */
                memcpy(new_device, device, sizeof(*new_device));
                new_device->name = kstrdup(device->name, GFP_NOFS);
-               BUG_ON(device->name && !new_device->name);
+               BUG_ON(device->name && !new_device->name); /* -ENOMEM */
                new_device->bdev = NULL;
                new_device->writeable = 0;
                new_device->in_fs_metadata = 0;
                leaf = path->nodes[0];
                extent = btrfs_item_ptr(leaf, path->slots[0],
                                        struct btrfs_dev_extent);
+       } else {
+               btrfs_error(root->fs_info, ret, "Slot search failed");
+               goto out;
        }
-       BUG_ON(ret);
 
        if (device->bytes_used > 0) {
                u64 len = btrfs_dev_extent_length(leaf, extent);
                spin_unlock(&root->fs_info->free_chunk_lock);
        }
        ret = btrfs_del_item(trans, root, path);
-
+       if (ret) {
+               btrfs_error(root->fs_info, ret,
+                           "Failed to remove dev extent item");
+       }
 out:
        btrfs_free_path(path);
        return ret;
        if (ret < 0)
                goto error;
 
-       BUG_ON(ret == 0);
+       BUG_ON(ret == 0); /* Corruption */
 
        ret = btrfs_previous_item(root, path, 0, BTRFS_CHUNK_ITEM_KEY);
        if (ret) {
        if (ret < 0)
                goto error;
 
-       BUG_ON(ret == 0);
+       BUG_ON(ret == 0); /* Corruption */
 
        ret = btrfs_previous_item(root, path, BTRFS_DEV_ITEMS_OBJECTID,
                                  BTRFS_DEV_ITEM_KEY);
                                   (unsigned long)btrfs_device_fsid(dev_item),
                                   BTRFS_UUID_SIZE);
                device = btrfs_find_device(root, devid, dev_uuid, fs_uuid);
-               BUG_ON(!device);
+               BUG_ON(!device); /* Logic error */
 
                if (device->fs_devices->seeding) {
                        btrfs_set_device_generation(leaf, dev_item,
        if (seeding_dev) {
                sb->s_flags &= ~MS_RDONLY;
                ret = btrfs_prepare_sprout(root);
-               BUG_ON(ret);
+               BUG_ON(ret); /* -ENOMEM */
        }
 
        device->fs_devices = root->fs_info->fs_devices;
 
        if (seeding_dev) {
                ret = init_first_rw_device(trans, root, device);
-               BUG_ON(ret);
+               if (ret)
+                       goto error_trans;
                ret = btrfs_finish_sprout(trans, root);
-               BUG_ON(ret);
+               if (ret)
+                       goto error_trans;
        } else {
                ret = btrfs_add_device(trans, root, device);
+               if (ret)
+                       goto error_trans;
        }
 
        /*
        btrfs_clear_space_info_full(root->fs_info);
 
        unlock_chunks(root);
-       btrfs_commit_transaction(trans, root);
+       ret = btrfs_commit_transaction(trans, root);
 
        if (seeding_dev) {
                mutex_unlock(&uuid_mutex);
                up_write(&sb->s_umount);
 
+               if (ret) /* transaction commit */
+                       return ret;
+
                ret = btrfs_relocate_sys_chunks(root);
-               BUG_ON(ret);
+               if (ret < 0)
+                       btrfs_error(root->fs_info, ret,
+                                   "Failed to relocate sys chunks after "
+                                   "device initialization. This can be fixed "
+                                   "using the \"btrfs balance\" command.");
        }
 
        return ret;
+
+error_trans:
+       unlock_chunks(root);
+       btrfs_abort_transaction(trans, root, ret);
+       btrfs_end_transaction(trans, root);
+       kfree(device->name);
+       kfree(device);
 error:
        blkdev_put(bdev, FMODE_EXCL);
        if (seeding_dev) {
        key.type = BTRFS_CHUNK_ITEM_KEY;
 
        ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
-       BUG_ON(ret);
+       if (ret < 0)
+               goto out;
+       else if (ret > 0) { /* Logic error or corruption */
+               btrfs_error(root->fs_info, -ENOENT,
+                           "Failed lookup while freeing chunk.");
+               ret = -ENOENT;
+               goto out;
+       }
 
        ret = btrfs_del_item(trans, root, path);
-
+       if (ret < 0)
+               btrfs_error(root->fs_info, ret,
+                           "Failed to delete chunk item.");
+out:
        btrfs_free_path(path);
        return ret;
 }
                ret = btrfs_search_slot(NULL, chunk_root, &key, path, 0, 0);
                if (ret < 0)
                        goto error;
-               BUG_ON(ret == 0);
+               BUG_ON(ret == 0); /* Corruption */
 
                ret = btrfs_previous_item(chunk_root, path, key.objectid,
                                          key.type);
        ret = btrfs_make_block_group(trans, extent_root, 0, type,
                                     BTRFS_FIRST_CHUNK_TREE_OBJECTID,
                                     start, num_bytes);
-       BUG_ON(ret);
+       if (ret)
+               goto error;
 
        for (i = 0; i < map->num_stripes; ++i) {
                struct btrfs_device *device;
                                info->chunk_root->root_key.objectid,
                                BTRFS_FIRST_CHUNK_TREE_OBJECTID,
                                start, dev_offset, stripe_size);
-               BUG_ON(ret);
+               if (ret) {
+                       btrfs_abort_transaction(trans, extent_root, ret);
+                       goto error;
+               }
        }
 
        kfree(devices_info);
 
        ret = __finish_chunk_alloc(trans, extent_root, map, chunk_offset,
                                   chunk_size, stripe_size);
-       BUG_ON(ret);
+       if (ret)
+               return ret;
        return 0;
 }
 
 
        ret = __btrfs_alloc_chunk(trans, extent_root, &map, &chunk_size,
                                  &stripe_size, chunk_offset, alloc_profile);
-       BUG_ON(ret);
+       if (ret)
+               return ret;
 
        sys_chunk_offset = chunk_offset + chunk_size;
 
        ret = __btrfs_alloc_chunk(trans, extent_root, &sys_map,
                                  &sys_chunk_size, &sys_stripe_size,
                                  sys_chunk_offset, alloc_profile);
-       BUG_ON(ret);
+       if (ret)
+               goto abort;
 
        ret = btrfs_add_device(trans, fs_info->chunk_root, device);
-       BUG_ON(ret);
+       if (ret)
+               goto abort;
 
        /*
         * Modifying chunk tree needs allocating new blocks from both
         */
        ret = __finish_chunk_alloc(trans, extent_root, map, chunk_offset,
                                   chunk_size, stripe_size);
-       BUG_ON(ret);
+       if (ret)
+               goto abort;
 
        ret = __finish_chunk_alloc(trans, extent_root, sys_map,
                                   sys_chunk_offset, sys_chunk_size,
                                   sys_stripe_size);
-       BUG_ON(ret);
+       if (ret)
+               goto abort;
+
        return 0;
+
+abort:
+       btrfs_abort_transaction(trans, root, ret);
+       return ret;
 }
 
 int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset)
                do_div(length, map->num_stripes);
 
        buf = kzalloc(sizeof(u64) * map->num_stripes, GFP_NOFS);
-       BUG_ON(!buf);
+       BUG_ON(!buf); /* -ENOMEM */
 
        for (i = 0; i < map->num_stripes; i++) {
                if (devid && map->stripes[i].dev->devid != devid)
 
        ret = btrfs_map_block(map_tree, rw, logical, &map_length, &bbio,
                              mirror_num);
-       BUG_ON(ret);
+       if (ret) /* -ENOMEM */
+               return ret;
 
        total_devs = bbio->num_stripes;
        if (map_length < length) {
        while (dev_nr < total_devs) {
                if (dev_nr < total_devs - 1) {
                        bio = bio_clone(first_bio, GFP_NOFS);
-                       BUG_ON(!bio);
+                       BUG_ON(!bio); /* -ENOMEM */
                } else {
                        bio = first_bio;
                }
        write_lock(&map_tree->map_tree.lock);
        ret = add_extent_mapping(&map_tree->map_tree, em);
        write_unlock(&map_tree->map_tree.lock);
-       BUG_ON(ret);
+       BUG_ON(ret); /* Tree corruption */
        free_extent_map(em);
 
        return 0;