Skip to content

Commit

Permalink
btrfs: replace many BUG_ONs with proper error handling
Browse files Browse the repository at this point in the history
 btrfs currently handles most errors with BUG_ON. This patch is a work-in-
 progress but aims to handle most errors other than internal logic
 errors and ENOMEM more gracefully.

 This iteration prevents most crashes but can run into lockups with
 the page lock on occasion when the timing "works out."

Signed-off-by: Jeff Mahoney <[email protected]>
  • Loading branch information
jeffmahoney authored and kdave committed Mar 22, 2012
1 parent 49b25e0 commit 79787ea
Show file tree
Hide file tree
Showing 23 changed files with 980 additions and 385 deletions.
24 changes: 12 additions & 12 deletions fs/btrfs/compression.c
Original file line number Diff line number Diff line change
Expand Up @@ -391,16 +391,16 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start,
*/
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);

Expand All @@ -420,15 +420,15 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start,
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;
Expand Down Expand Up @@ -661,7 +661,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
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
Expand All @@ -674,14 +674,14 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
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);

Expand All @@ -697,15 +697,15 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *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;
Expand Down
19 changes: 10 additions & 9 deletions fs/btrfs/ctree.c
Original file line number Diff line number Diff line change
Expand Up @@ -356,14 +356,14 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
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 {
Expand All @@ -373,7 +373,7 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
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,
Expand All @@ -390,9 +390,9 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
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;
Expand Down Expand Up @@ -475,7 +475,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,

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;
}

Expand Down Expand Up @@ -2713,7 +2713,8 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
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;
}

Expand Down Expand Up @@ -4017,7 +4018,7 @@ int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key,
}
btrfs_set_path_blocking(path);
cur = read_node_slot(root, cur, slot);
BUG_ON(!cur);
BUG_ON(!cur); /* -ENOMEM */

btrfs_tree_read_lock(cur);

Expand Down
27 changes: 20 additions & 7 deletions fs/btrfs/delayed-inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ static struct btrfs_delayed_node *btrfs_get_delayed_node(struct inode *inode)
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)
{
Expand Down Expand Up @@ -1106,16 +1107,25 @@ static int btrfs_update_delayed_inode(struct btrfs_trans_handle *trans,
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;
Expand All @@ -1128,17 +1138,18 @@ int btrfs_run_delayed_items(struct btrfs_trans_handle *trans,

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;
}

Expand All @@ -1149,6 +1160,7 @@ int btrfs_run_delayed_items(struct btrfs_trans_handle *trans,

btrfs_free_path(path);
trans->block_rsv = block_rsv;

return ret;
}

Expand Down Expand Up @@ -1369,6 +1381,7 @@ void btrfs_balance_delayed_items(struct btrfs_root *root)
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,
Expand Down
1 change: 1 addition & 0 deletions fs/btrfs/dir-item.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans,
* '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,
Expand Down
Loading

0 comments on commit 79787ea

Please sign in to comment.