Skip to content

Commit 0bbf8b9

Browse files
committed
btrfs-progs: check: add more transaction error handling
Update error handling where a transaction start may not be paired with a commit (that actually checks errors). Add aborts where missing. Signed-off-by: David Sterba <dsterba@suse.com>
1 parent 3b89906 commit 0bbf8b9

File tree

3 files changed

+256
-78
lines changed

3 files changed

+256
-78
lines changed

check/main.c

+130-32
Original file line numberDiff line numberDiff line change
@@ -2187,7 +2187,11 @@ static int add_missing_dir_index(struct btrfs_root *root,
21872187
key.type = BTRFS_DIR_INDEX_KEY;
21882188
key.offset = backref->index;
21892189
ret = btrfs_insert_empty_item(trans, root, &path, &key, data_size);
2190-
BUG_ON(ret);
2190+
if (ret < 0) {
2191+
errno = -ret;
2192+
error_msg(ERROR_MSG_START_TRANS, "%m");
2193+
return ret;
2194+
}
21912195

21922196
leaf = path.nodes[0];
21932197
dir_item = btrfs_item_ptr(leaf, path.slots[0], struct btrfs_dir_item);
@@ -2204,7 +2208,12 @@ static int add_missing_dir_index(struct btrfs_root *root,
22042208
write_extent_buffer(leaf, backref->name, name_ptr, backref->namelen);
22052209
btrfs_mark_buffer_dirty(leaf);
22062210
btrfs_release_path(&path);
2207-
btrfs_commit_transaction(trans, root);
2211+
ret = btrfs_commit_transaction(trans, root);
2212+
if (ret < 0) {
2213+
errno = -ret;
2214+
error_msg(ERROR_MSG_START_TRANS, "%m");
2215+
return ret;
2216+
}
22082217

22092218
backref->found_dir_index = 1;
22102219
dir_rec = get_inode_rec(inode_cache, backref->dir, 0);
@@ -2258,7 +2267,11 @@ static int delete_dir_index(struct btrfs_root *root,
22582267
ret = btrfs_delete_one_dir_name(trans, root, &path, di);
22592268
BUG_ON(ret);
22602269
btrfs_release_path(&path);
2261-
btrfs_commit_transaction(trans, root);
2270+
ret = btrfs_commit_transaction(trans, root);
2271+
if (ret < 0) {
2272+
errno = -ret;
2273+
error_msg(ERROR_MSG_START_TRANS, "%m");
2274+
}
22622275
return ret;
22632276
}
22642277

@@ -2295,8 +2308,18 @@ static int create_inode_item(struct btrfs_root *root,
22952308

22962309
ret = insert_inode_item(trans, root, rec->ino, size, rec->nbytes,
22972310
nlink, mode);
2298-
btrfs_commit_transaction(trans, root);
2299-
return 0;
2311+
if (ret < 0) {
2312+
btrfs_abort_transaction(trans, ret);
2313+
btrfs_commit_transaction(trans, root);
2314+
return ret;
2315+
}
2316+
2317+
ret = btrfs_commit_transaction(trans, root);
2318+
if (ret < 0) {
2319+
errno = -ret;
2320+
error_msg(ERROR_MSG_START_TRANS, "%m");
2321+
}
2322+
return ret;
23002323
}
23012324

23022325
static int repair_inode_backrefs(struct btrfs_root *root,
@@ -2390,8 +2413,17 @@ static int repair_inode_backrefs(struct btrfs_root *root,
23902413
backref->dir, &location,
23912414
imode_to_type(rec->imode),
23922415
backref->index);
2393-
BUG_ON(ret);
2394-
btrfs_commit_transaction(trans, root);
2416+
if (ret < 0) {
2417+
btrfs_abort_transaction(trans, ret);
2418+
btrfs_commit_transaction(trans, root);
2419+
break;
2420+
}
2421+
ret = btrfs_commit_transaction(trans, root);
2422+
if (ret < 0) {
2423+
errno = -ret;
2424+
error_msg(ERROR_MSG_COMMIT_TRANS, "%m");
2425+
break;
2426+
}
23952427
repaired++;
23962428
}
23972429

@@ -3074,8 +3106,12 @@ static int try_repair_inode(struct btrfs_root *root, struct inode_record *rec)
30743106
ret = repair_unaligned_extent_recs(trans, root, &path, rec);
30753107
if (!ret && rec->errors & I_ERR_INVALID_GEN)
30763108
ret = repair_inode_gen_original(trans, root, &path, rec);
3077-
btrfs_commit_transaction(trans, root);
30783109
btrfs_release_path(&path);
3110+
ret = btrfs_commit_transaction(trans, root);
3111+
if (ret < 0) {
3112+
errno = -ret;
3113+
error_msg(ERROR_MSG_COMMIT_TRANS, "%m");
3114+
}
30793115
return ret;
30803116
}
30813117

@@ -3184,7 +3220,12 @@ static int check_inode_recs(struct btrfs_root *root,
31843220
return ret;
31853221
}
31863222

3187-
btrfs_commit_transaction(trans, root);
3223+
ret = btrfs_commit_transaction(trans, root);
3224+
if (ret < 0) {
3225+
errno = -ret;
3226+
error_msg(ERROR_MSG_COMMIT_TRANS, "%m");
3227+
return ret;
3228+
}
31883229
return -EAGAIN;
31893230
}
31903231

@@ -3662,8 +3703,12 @@ static int repair_btree(struct btrfs_root *root,
36623703
cache = next_cache_extent(cache);
36633704
}
36643705
out:
3665-
btrfs_commit_transaction(trans, root);
36663706
btrfs_release_path(&path);
3707+
ret = btrfs_commit_transaction(trans, root);
3708+
if (ret < 0) {
3709+
errno = -ret;
3710+
error_msg(ERROR_MSG_COMMIT_TRANS, "%m");
3711+
}
36673712
return ret;
36683713
}
36693714

@@ -4605,6 +4650,7 @@ static int try_to_fix_bad_block(struct btrfs_root *root,
46054650
ret = btrfs_search_slot(trans, search_root, &key, &path, 0, 1);
46064651
if (ret) {
46074652
ret = -EIO;
4653+
btrfs_abort_transaction(trans, ret);
46084654
btrfs_commit_transaction(trans, search_root);
46094655
break;
46104656
}
@@ -4613,11 +4659,17 @@ static int try_to_fix_bad_block(struct btrfs_root *root,
46134659
else if (status == BTRFS_TREE_BLOCK_INVALID_OFFSETS)
46144660
ret = fix_item_offset(search_root, &path);
46154661
if (ret) {
4662+
btrfs_abort_transaction(trans, ret);
46164663
btrfs_commit_transaction(trans, search_root);
46174664
break;
46184665
}
46194666
btrfs_release_path(&path);
4620-
btrfs_commit_transaction(trans, search_root);
4667+
ret = btrfs_commit_transaction(trans, search_root);
4668+
if (ret < 0) {
4669+
errno = -ret;
4670+
error_msg(ERROR_MSG_COMMIT_TRANS, "%m");
4671+
break;
4672+
}
46214673
}
46224674
ulist_free(roots);
46234675
btrfs_release_path(&path);
@@ -7843,6 +7895,7 @@ static int fixup_extent_flags(struct extent_record *rec)
78437895
ret = btrfs_search_slot(trans, root, &key, &path, 0, 1);
78447896
if (ret < 0) {
78457897
btrfs_release_path(&path);
7898+
btrfs_abort_transaction(trans, ret);
78467899
btrfs_commit_transaction(trans, root);
78477900
return ret;
78487901
} else if (ret) {
@@ -7852,7 +7905,12 @@ static int fixup_extent_flags(struct extent_record *rec)
78527905
}
78537906
fprintf(stderr, "Didn't find extent for %llu\n", rec->start);
78547907
btrfs_release_path(&path);
7855-
btrfs_commit_transaction(trans, root);
7908+
ret = btrfs_commit_transaction(trans, root);
7909+
if (ret < 0) {
7910+
errno = -ret;
7911+
error_msg(ERROR_MSG_COMMIT_TRANS, "%m");
7912+
return ret;
7913+
}
78567914
return -ENOENT;
78577915
}
78587916

@@ -7870,8 +7928,12 @@ static int fixup_extent_flags(struct extent_record *rec)
78707928
btrfs_mark_buffer_dirty(path.nodes[0]);
78717929
btrfs_release_path(&path);
78727930
ret = btrfs_commit_transaction(trans, root);
7873-
if (!ret)
7931+
if (ret < 0) {
7932+
errno = -ret;
7933+
error_msg(ERROR_MSG_COMMIT_TRANS, "%m");
7934+
} else {
78747935
fprintf(stderr, "Repaired extent flags for %llu\n", rec->start);
7936+
}
78757937

78767938
return ret;
78777939
}
@@ -7950,7 +8012,7 @@ static int prune_corrupt_blocks(void)
79508012
struct btrfs_trans_handle *trans = NULL;
79518013
struct cache_extent *cache;
79528014
struct btrfs_corrupt_block *corrupt;
7953-
int ret;
8015+
int ret = 0;
79548016

79558017
while (1) {
79568018
cache = search_cache_extent(gfs_info->corrupt_blocks, 0);
@@ -7969,9 +8031,14 @@ static int prune_corrupt_blocks(void)
79698031
prune_one_block(trans, corrupt);
79708032
remove_cache_extent(gfs_info->corrupt_blocks, cache);
79718033
}
7972-
if (trans)
7973-
return btrfs_commit_transaction(trans, gfs_info->tree_root);
7974-
return 0;
8034+
if (trans) {
8035+
ret = btrfs_commit_transaction(trans, gfs_info->tree_root);
8036+
if (ret < 0) {
8037+
errno = -ret;
8038+
error_msg(ERROR_MSG_COMMIT_TRANS, "%m");
8039+
}
8040+
}
8041+
return ret;
79758042
}
79768043

79778044
static int record_unaligned_extent_rec(struct extent_record *rec)
@@ -8096,13 +8163,19 @@ static int repair_extent_item_generation(struct extent_record *rec)
80968163
/* Not possible */
80978164
if (ret == 0)
80988165
ret = -EUCLEAN;
8099-
if (ret < 0)
8166+
if (ret < 0) {
8167+
btrfs_abort_transaction(trans, ret);
8168+
btrfs_commit_transaction(trans, extent_root);
81008169
goto out;
8170+
}
81018171
ret = btrfs_previous_extent_item(extent_root, &path, rec->start);
81028172
if (ret > 0)
81038173
ret = -ENOENT;
8104-
if (ret < 0)
8174+
if (ret < 0) {
8175+
btrfs_abort_transaction(trans, ret);
8176+
btrfs_commit_transaction(trans, extent_root);
81058177
goto out;
8178+
}
81068179

81078180
if (!new_gen)
81088181
new_gen = trans->transid;
@@ -8120,10 +8193,6 @@ static int repair_extent_item_generation(struct extent_record *rec)
81208193
rec->generation = new_gen;
81218194
out:
81228195
btrfs_release_path(&path);
8123-
if (ret < 0) {
8124-
btrfs_abort_transaction(trans, ret);
8125-
btrfs_commit_transaction(trans, extent_root);
8126-
}
81278196
return ret;
81288197
}
81298198

@@ -8343,8 +8412,11 @@ static int check_extent_refs(struct btrfs_root *root,
83438412
goto repair_abort;
83448413
}
83458414
ret = btrfs_commit_transaction(trans, root);
8346-
if (ret)
8415+
if (ret < 0) {
8416+
errno = -ret;
8417+
error_msg(ERROR_MSG_COMMIT_TRANS, "%m");
83478418
goto repair_abort;
8419+
}
83488420
}
83498421
return ret;
83508422
}
@@ -8826,8 +8898,18 @@ static int check_block_groups(struct block_group_tree *bg_cache)
88268898
}
88278899

88288900
ret = btrfs_fix_block_accounting(trans);
8829-
btrfs_commit_transaction(trans, gfs_info->tree_root);
8830-
return ret ? ret : -EAGAIN;
8901+
if (ret < 0) {
8902+
btrfs_abort_transaction(trans, ret);
8903+
btrfs_commit_transaction(trans, gfs_info->tree_root);
8904+
return ret;
8905+
}
8906+
ret = btrfs_commit_transaction(trans, gfs_info->tree_root);
8907+
if (ret < 0) {
8908+
errno = -ret;
8909+
error_msg(ERROR_MSG_COMMIT_TRANS, "%m");
8910+
return ret;
8911+
}
8912+
return -EAGAIN;
88318913
}
88328914

88338915
/**
@@ -9646,14 +9728,24 @@ static int delete_bad_item(struct btrfs_root *root, struct bad_item *bad)
96469728
}
96479729

96489730
ret = btrfs_search_slot(trans, root, &bad->key, &path, -1, 1);
9649-
if (ret) {
9650-
if (ret > 0)
9651-
ret = 0;
9731+
if (ret < 0) {
9732+
btrfs_abort_transaction(trans, ret);
9733+
btrfs_commit_transaction(trans, root);
96529734
goto out;
96539735
}
9736+
if (ret > 0) {
9737+
ret = 0;
9738+
goto out_commit;
9739+
}
96549740
ret = btrfs_del_item(trans, root, &path);
9655-
out:
9741+
if (ret < 0) {
9742+
btrfs_abort_transaction(trans, ret);
9743+
btrfs_commit_transaction(trans, root);
9744+
goto out;
9745+
}
9746+
out_commit:
96569747
btrfs_commit_transaction(trans, root);
9748+
out:
96579749
btrfs_release_path(&path);
96589750
return ret;
96599751
}
@@ -9998,8 +10090,14 @@ static int repair_root_items(void)
999810090
out:
999910091
free_roots_info_cache();
1000010092
btrfs_release_path(&path);
10001-
if (trans)
10002-
btrfs_commit_transaction(trans, gfs_info->tree_root);
10093+
if (trans) {
10094+
ret = btrfs_commit_transaction(trans, gfs_info->tree_root);
10095+
if (ret < 0) {
10096+
errno = -ret;
10097+
error_msg(ERROR_MSG_COMMIT_TRANS, "%m");
10098+
return ret;
10099+
}
10100+
}
1000310101
if (ret < 0)
1000410102
return ret;
1000510103

check/mode-common.c

+21-14
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,7 @@ int reset_imode(struct btrfs_trans_handle *trans, struct btrfs_root *root,
727727
iitem = btrfs_item_ptr(leaf, slot, struct btrfs_inode_item);
728728
btrfs_set_inode_mode(leaf, iitem, mode);
729729
btrfs_mark_buffer_dirty(leaf);
730-
return ret;
730+
return 0;
731731
}
732732

733733
static int find_file_type_dir_index(struct btrfs_root *root, u64 ino, u64 dirid,
@@ -1006,16 +1006,20 @@ int repair_imode_common(struct btrfs_root *root, struct btrfs_path *path)
10061006
btrfs_release_path(path);
10071007

10081008
ret = reset_imode(trans, root, path, key.objectid, imode);
1009-
if (ret < 0)
1010-
goto abort;
1009+
if (ret < 0) {
1010+
btrfs_abort_transaction(trans, ret);
1011+
btrfs_commit_transaction(trans, root);
1012+
return ret;
1013+
}
10111014
ret = btrfs_commit_transaction(trans, root);
1012-
if (!ret)
1013-
printf("reset mode for inode %llu root %llu\n",
1014-
key.objectid, root->root_key.objectid);
1015+
if (ret < 0) {
1016+
errno = -ret;
1017+
error_msg(ERROR_MSG_COMMIT_TRANS, "%m");
1018+
return ret;
1019+
}
1020+
printf("reset mode for inode %llu root %llu\n",
1021+
key.objectid, root->root_key.objectid);
10151022
return ret;
1016-
abort:
1017-
btrfs_abort_transaction(trans, ret);
1018-
return ret;
10191023
}
10201024

10211025
/*
@@ -1084,7 +1088,11 @@ int recow_extent_buffer(struct btrfs_root *root, struct extent_buffer *eb)
10841088
btrfs_item_key_to_cpu(eb, &key, 0);
10851089

10861090
ret = btrfs_search_slot(trans, root, &key, &path, 0, 1);
1087-
btrfs_commit_transaction(trans, root);
1091+
ret = btrfs_commit_transaction(trans, root);
1092+
if (ret < 0) {
1093+
errno = -ret;
1094+
error_msg(ERROR_MSG_COMMIT_TRANS, "%m");
1095+
}
10881096
btrfs_release_path(&path);
10891097
return ret;
10901098
}
@@ -1183,7 +1191,9 @@ int repair_dev_item_bytes_used(struct btrfs_fs_info *fs_info,
11831191
if (ret < 0) {
11841192
errno = -ret;
11851193
error("failed to update device item for devid %llu: %m", devid);
1186-
goto error;
1194+
btrfs_abort_transaction(trans, ret);
1195+
btrfs_commit_transaction(trans, fs_info->chunk_root);
1196+
return ret;
11871197
}
11881198

11891199
/*
@@ -1199,9 +1209,6 @@ int repair_dev_item_bytes_used(struct btrfs_fs_info *fs_info,
11991209
device->bytes_used);
12001210
}
12011211
return ret;
1202-
error:
1203-
btrfs_abort_transaction(trans, ret);
1204-
return ret;
12051212
}
12061213

12071214
static int populate_csum(struct btrfs_trans_handle *trans,

0 commit comments

Comments
 (0)