Skip to content

Commit b64764e

Browse files
fdmananagregkh
authored andcommitted
btrfs: abort transaction on specific error places when walking log tree
[ Upstream commit 6ebd726b104fa99d47c0d45979e6a6109844ac18 ] 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]> Signed-off-by: Sasha Levin <[email protected]>
1 parent c198b19 commit b64764e

1 file changed

Lines changed: 28 additions & 5 deletions

File tree

fs/btrfs/tree-log.c

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2630,15 +2630,24 @@ static int unaccount_log_buffer(struct btrfs_fs_info *fs_info, u64 start)
26302630
static int clean_log_buffer(struct btrfs_trans_handle *trans,
26312631
struct extent_buffer *eb)
26322632
{
2633+
int ret;
2634+
26332635
btrfs_tree_lock(eb);
26342636
btrfs_clear_buffer_dirty(trans, eb);
26352637
wait_on_extent_buffer_writeback(eb);
26362638
btrfs_tree_unlock(eb);
26372639

2638-
if (trans)
2639-
return btrfs_pin_reserved_extent(trans, eb);
2640+
if (trans) {
2641+
ret = btrfs_pin_reserved_extent(trans, eb);
2642+
if (ret)
2643+
btrfs_abort_transaction(trans, ret);
2644+
return ret;
2645+
}
26402646

2641-
return unaccount_log_buffer(eb->fs_info, eb->start);
2647+
ret = unaccount_log_buffer(eb->fs_info, eb->start);
2648+
if (ret)
2649+
btrfs_handle_fs_error(eb->fs_info, ret, NULL);
2650+
return ret;
26422651
}
26432652

26442653
static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
@@ -2674,8 +2683,14 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
26742683
next = btrfs_find_create_tree_block(fs_info, bytenr,
26752684
btrfs_header_owner(cur),
26762685
*level - 1);
2677-
if (IS_ERR(next))
2678-
return PTR_ERR(next);
2686+
if (IS_ERR(next)) {
2687+
ret = PTR_ERR(next);
2688+
if (trans)
2689+
btrfs_abort_transaction(trans, ret);
2690+
else
2691+
btrfs_handle_fs_error(fs_info, ret, NULL);
2692+
return ret;
2693+
}
26792694

26802695
if (*level == 1) {
26812696
ret = wc->process_func(root, next, wc, ptr_gen,
@@ -2690,6 +2705,10 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
26902705
ret = btrfs_read_extent_buffer(next, &check);
26912706
if (ret) {
26922707
free_extent_buffer(next);
2708+
if (trans)
2709+
btrfs_abort_transaction(trans, ret);
2710+
else
2711+
btrfs_handle_fs_error(fs_info, ret, NULL);
26932712
return ret;
26942713
}
26952714

@@ -2705,6 +2724,10 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
27052724
ret = btrfs_read_extent_buffer(next, &check);
27062725
if (ret) {
27072726
free_extent_buffer(next);
2727+
if (trans)
2728+
btrfs_abort_transaction(trans, ret);
2729+
else
2730+
btrfs_handle_fs_error(fs_info, ret, NULL);
27082731
return ret;
27092732
}
27102733

0 commit comments

Comments
 (0)