Skip to content

Commit 03a717b

Browse files
fdmananakdave
authored andcommitted
btrfs: abort transaction on specific error places when walking log tree
We do several things while walking a log tree (for replaying and for freeing a log tree) like reading extent buffers and cleaning them up, but we don't immediately abort the transaction, or turn the fs into an error state, when one of these things fails. Instead we the transaction abort or turn the fs into error state in the caller of the entry point function that walks a log tree - walk_log_tree() - which means we don't get to know exactly where an error came from. Improve on this by doing a transaction abort / turn fs into error state after each such failure so that when it happens we have a better understanding where the failure comes from. This deliberately leaves the transaction abort / turn fs into error state in the callers of walk_log_tree() as to ensure we don't get into an inconsistent state in case we forget to do it deeper in call chain. It also deliberately does not do it after errors from the calls to the callback defined in struct walk_control::process_func(), as we will do it later on another patch. Reviewed-by: Boris Burkov <[email protected]> Reviewed-by: Qu Wenruo <[email protected]> Signed-off-by: Filipe Manana <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 7f550e2 commit 03a717b

File tree

1 file changed

+28
-5
lines changed

1 file changed

+28
-5
lines changed

fs/btrfs/tree-log.c

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2618,15 +2618,24 @@ static int unaccount_log_buffer(struct btrfs_fs_info *fs_info, u64 start)
26182618
static int clean_log_buffer(struct btrfs_trans_handle *trans,
26192619
struct extent_buffer *eb)
26202620
{
2621+
int ret;
2622+
26212623
btrfs_tree_lock(eb);
26222624
btrfs_clear_buffer_dirty(trans, eb);
26232625
wait_on_extent_buffer_writeback(eb);
26242626
btrfs_tree_unlock(eb);
26252627

2626-
if (trans)
2627-
return btrfs_pin_reserved_extent(trans, eb);
2628+
if (trans) {
2629+
ret = btrfs_pin_reserved_extent(trans, eb);
2630+
if (ret)
2631+
btrfs_abort_transaction(trans, ret);
2632+
return ret;
2633+
}
26282634

2629-
return unaccount_log_buffer(eb->fs_info, eb->start);
2635+
ret = unaccount_log_buffer(eb->fs_info, eb->start);
2636+
if (ret)
2637+
btrfs_handle_fs_error(eb->fs_info, ret, NULL);
2638+
return ret;
26302639
}
26312640

26322641
static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
@@ -2662,8 +2671,14 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
26622671
next = btrfs_find_create_tree_block(fs_info, bytenr,
26632672
btrfs_header_owner(cur),
26642673
*level - 1);
2665-
if (IS_ERR(next))
2666-
return PTR_ERR(next);
2674+
if (IS_ERR(next)) {
2675+
ret = PTR_ERR(next);
2676+
if (trans)
2677+
btrfs_abort_transaction(trans, ret);
2678+
else
2679+
btrfs_handle_fs_error(fs_info, ret, NULL);
2680+
return ret;
2681+
}
26672682

26682683
if (*level == 1) {
26692684
ret = wc->process_func(root, next, wc, ptr_gen,
@@ -2678,6 +2693,10 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
26782693
ret = btrfs_read_extent_buffer(next, &check);
26792694
if (ret) {
26802695
free_extent_buffer(next);
2696+
if (trans)
2697+
btrfs_abort_transaction(trans, ret);
2698+
else
2699+
btrfs_handle_fs_error(fs_info, ret, NULL);
26812700
return ret;
26822701
}
26832702

@@ -2693,6 +2712,10 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
26932712
ret = btrfs_read_extent_buffer(next, &check);
26942713
if (ret) {
26952714
free_extent_buffer(next);
2715+
if (trans)
2716+
btrfs_abort_transaction(trans, ret);
2717+
else
2718+
btrfs_handle_fs_error(fs_info, ret, NULL);
26962719
return ret;
26972720
}
26982721

0 commit comments

Comments
 (0)