Skip to content

Commit 79787ea

Browse files
jeffmahoneykdave
authored andcommitted
btrfs: replace many BUG_ONs with proper error handling
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]>
1 parent 49b25e0 commit 79787ea

23 files changed

+980
-385
lines changed

fs/btrfs/compression.c

+12-12
Original file line numberDiff line numberDiff line change
@@ -391,16 +391,16 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start,
391391
*/
392392
atomic_inc(&cb->pending_bios);
393393
ret = btrfs_bio_wq_end_io(root->fs_info, bio, 0);
394-
BUG_ON(ret);
394+
BUG_ON(ret); /* -ENOMEM */
395395

396396
if (!skip_sum) {
397397
ret = btrfs_csum_one_bio(root, inode, bio,
398398
start, 1);
399-
BUG_ON(ret);
399+
BUG_ON(ret); /* -ENOMEM */
400400
}
401401

402402
ret = btrfs_map_bio(root, WRITE, bio, 0, 1);
403-
BUG_ON(ret);
403+
BUG_ON(ret); /* -ENOMEM */
404404

405405
bio_put(bio);
406406

@@ -420,15 +420,15 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start,
420420
bio_get(bio);
421421

422422
ret = btrfs_bio_wq_end_io(root->fs_info, bio, 0);
423-
BUG_ON(ret);
423+
BUG_ON(ret); /* -ENOMEM */
424424

425425
if (!skip_sum) {
426426
ret = btrfs_csum_one_bio(root, inode, bio, start, 1);
427-
BUG_ON(ret);
427+
BUG_ON(ret); /* -ENOMEM */
428428
}
429429

430430
ret = btrfs_map_bio(root, WRITE, bio, 0, 1);
431-
BUG_ON(ret);
431+
BUG_ON(ret); /* -ENOMEM */
432432

433433
bio_put(bio);
434434
return 0;
@@ -661,7 +661,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
661661
bio_get(comp_bio);
662662

663663
ret = btrfs_bio_wq_end_io(root->fs_info, comp_bio, 0);
664-
BUG_ON(ret);
664+
BUG_ON(ret); /* -ENOMEM */
665665

666666
/*
667667
* inc the count before we submit the bio so
@@ -674,14 +674,14 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
674674
if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) {
675675
ret = btrfs_lookup_bio_sums(root, inode,
676676
comp_bio, sums);
677-
BUG_ON(ret);
677+
BUG_ON(ret); /* -ENOMEM */
678678
}
679679
sums += (comp_bio->bi_size + root->sectorsize - 1) /
680680
root->sectorsize;
681681

682682
ret = btrfs_map_bio(root, READ, comp_bio,
683683
mirror_num, 0);
684-
BUG_ON(ret);
684+
BUG_ON(ret); /* -ENOMEM */
685685

686686
bio_put(comp_bio);
687687

@@ -697,15 +697,15 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
697697
bio_get(comp_bio);
698698

699699
ret = btrfs_bio_wq_end_io(root->fs_info, comp_bio, 0);
700-
BUG_ON(ret);
700+
BUG_ON(ret); /* -ENOMEM */
701701

702702
if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) {
703703
ret = btrfs_lookup_bio_sums(root, inode, comp_bio, sums);
704-
BUG_ON(ret);
704+
BUG_ON(ret); /* -ENOMEM */
705705
}
706706

707707
ret = btrfs_map_bio(root, READ, comp_bio, mirror_num, 0);
708-
BUG_ON(ret);
708+
BUG_ON(ret); /* -ENOMEM */
709709

710710
bio_put(comp_bio);
711711
return 0;

fs/btrfs/ctree.c

+10-9
Original file line numberDiff line numberDiff line change
@@ -356,14 +356,14 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
356356
root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) &&
357357
!(flags & BTRFS_BLOCK_FLAG_FULL_BACKREF)) {
358358
ret = btrfs_inc_ref(trans, root, buf, 1, 1);
359-
BUG_ON(ret);
359+
BUG_ON(ret); /* -ENOMEM */
360360

361361
if (root->root_key.objectid ==
362362
BTRFS_TREE_RELOC_OBJECTID) {
363363
ret = btrfs_dec_ref(trans, root, buf, 0, 1);
364-
BUG_ON(ret);
364+
BUG_ON(ret); /* -ENOMEM */
365365
ret = btrfs_inc_ref(trans, root, cow, 1, 1);
366-
BUG_ON(ret);
366+
BUG_ON(ret); /* -ENOMEM */
367367
}
368368
new_flags |= BTRFS_BLOCK_FLAG_FULL_BACKREF;
369369
} else {
@@ -373,7 +373,7 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
373373
ret = btrfs_inc_ref(trans, root, cow, 1, 1);
374374
else
375375
ret = btrfs_inc_ref(trans, root, cow, 0, 1);
376-
BUG_ON(ret);
376+
BUG_ON(ret); /* -ENOMEM */
377377
}
378378
if (new_flags != 0) {
379379
ret = btrfs_set_disk_extent_flags(trans, root,
@@ -390,9 +390,9 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
390390
ret = btrfs_inc_ref(trans, root, cow, 1, 1);
391391
else
392392
ret = btrfs_inc_ref(trans, root, cow, 0, 1);
393-
BUG_ON(ret);
393+
BUG_ON(ret); /* -ENOMEM */
394394
ret = btrfs_dec_ref(trans, root, buf, 1, 1);
395-
BUG_ON(ret);
395+
BUG_ON(ret); /* -ENOMEM */
396396
}
397397
clean_tree_block(trans, root, buf);
398398
*last_ref = 1;
@@ -475,7 +475,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
475475

476476
ret = update_ref_for_cow(trans, root, buf, cow, &last_ref);
477477
if (ret) {
478-
btrfs_std_error(root->fs_info, ret);
478+
btrfs_abort_transaction(trans, root, ret);
479479
return ret;
480480
}
481481

@@ -2713,7 +2713,8 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
27132713
path->nodes[1], slot - 1, &left);
27142714
if (ret) {
27152715
/* we hit -ENOSPC, but it isn't fatal here */
2716-
ret = 1;
2716+
if (ret == -ENOSPC)
2717+
ret = 1;
27172718
goto out;
27182719
}
27192720

@@ -4017,7 +4018,7 @@ int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key,
40174018
}
40184019
btrfs_set_path_blocking(path);
40194020
cur = read_node_slot(root, cur, slot);
4020-
BUG_ON(!cur);
4021+
BUG_ON(!cur); /* -ENOMEM */
40214022

40224023
btrfs_tree_read_lock(cur);
40234024

fs/btrfs/delayed-inode.c

+20-7
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ static struct btrfs_delayed_node *btrfs_get_delayed_node(struct inode *inode)
115115
return NULL;
116116
}
117117

118+
/* Will return either the node or PTR_ERR(-ENOMEM) */
118119
static struct btrfs_delayed_node *btrfs_get_or_create_delayed_node(
119120
struct inode *inode)
120121
{
@@ -1106,16 +1107,25 @@ static int btrfs_update_delayed_inode(struct btrfs_trans_handle *trans,
11061107
return 0;
11071108
}
11081109

1109-
/* Called when committing the transaction. */
1110+
/*
1111+
* Called when committing the transaction.
1112+
* Returns 0 on success.
1113+
* Returns < 0 on error and returns with an aborted transaction with any
1114+
* outstanding delayed items cleaned up.
1115+
*/
11101116
int btrfs_run_delayed_items(struct btrfs_trans_handle *trans,
11111117
struct btrfs_root *root)
11121118
{
1119+
struct btrfs_root *curr_root = root;
11131120
struct btrfs_delayed_root *delayed_root;
11141121
struct btrfs_delayed_node *curr_node, *prev_node;
11151122
struct btrfs_path *path;
11161123
struct btrfs_block_rsv *block_rsv;
11171124
int ret = 0;
11181125

1126+
if (trans->aborted)
1127+
return -EIO;
1128+
11191129
path = btrfs_alloc_path();
11201130
if (!path)
11211131
return -ENOMEM;
@@ -1128,17 +1138,18 @@ int btrfs_run_delayed_items(struct btrfs_trans_handle *trans,
11281138

11291139
curr_node = btrfs_first_delayed_node(delayed_root);
11301140
while (curr_node) {
1131-
root = curr_node->root;
1132-
ret = btrfs_insert_delayed_items(trans, path, root,
1141+
curr_root = curr_node->root;
1142+
ret = btrfs_insert_delayed_items(trans, path, curr_root,
11331143
curr_node);
11341144
if (!ret)
1135-
ret = btrfs_delete_delayed_items(trans, path, root,
1136-
curr_node);
1145+
ret = btrfs_delete_delayed_items(trans, path,
1146+
curr_root, curr_node);
11371147
if (!ret)
1138-
ret = btrfs_update_delayed_inode(trans, root, path,
1139-
curr_node);
1148+
ret = btrfs_update_delayed_inode(trans, curr_root,
1149+
path, curr_node);
11401150
if (ret) {
11411151
btrfs_release_delayed_node(curr_node);
1152+
btrfs_abort_transaction(trans, root, ret);
11421153
break;
11431154
}
11441155

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

11501161
btrfs_free_path(path);
11511162
trans->block_rsv = block_rsv;
1163+
11521164
return ret;
11531165
}
11541166

@@ -1369,6 +1381,7 @@ void btrfs_balance_delayed_items(struct btrfs_root *root)
13691381
btrfs_wq_run_delayed_node(delayed_root, root, 0);
13701382
}
13711383

1384+
/* Will return 0 or -ENOMEM */
13721385
int btrfs_insert_delayed_dir_index(struct btrfs_trans_handle *trans,
13731386
struct btrfs_root *root, const char *name,
13741387
int name_len, struct inode *dir,

fs/btrfs/dir-item.c

+1
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans,
115115
* 'location' is the key to stuff into the directory item, 'type' is the
116116
* type of the inode we're pointing to, and 'index' is the sequence number
117117
* to use for the second index (if one is created).
118+
* Will return 0 or -ENOMEM
118119
*/
119120
int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
120121
*root, const char *name, int name_len,

0 commit comments

Comments
 (0)