Skip to content

Commit 725026e

Browse files
fdmananakdave
authored andcommitted
btrfs: abort transaction at balance_level() when left child is missing
At balance_level() we are calling btrfs_handle_fs_error() when the middle child only has 1 item and the left child is missing, however we can simply use btrfs_abort_transaction(), which achieves the same purposes: to turn the fs to error state, abort the current transaction and turn the fs to RO mode. Besides that, btrfs_abort_transaction() also prints a stack trace which makes it more useful. Also, as this is a highly unexpected case and it's about a b+tree inconsistency, change the error code from -EROFS to -EUCLEAN, tag the if branch as 'unlikely' and log an explicit error message. Reviewed-by: Qu Wenruo <wqu@suse.com> Signed-off-by: Filipe Manana <fdmanana@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent 87b8e9d commit 725026e

1 file changed

Lines changed: 7 additions & 3 deletions

File tree

fs/btrfs/ctree.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,9 +1164,13 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
11641164
* otherwise we would have pulled some pointers from the
11651165
* right
11661166
*/
1167-
if (!left) {
1168-
ret = -EROFS;
1169-
btrfs_handle_fs_error(fs_info, ret, NULL);
1167+
if (unlikely(!left)) {
1168+
btrfs_crit(fs_info,
1169+
"missing left child when middle child only has 1 item, parent bytenr %llu level %d mid bytenr %llu root %llu",
1170+
parent->start, btrfs_header_level(parent),
1171+
mid->start, btrfs_root_id(root));
1172+
ret = -EUCLEAN;
1173+
btrfs_abort_transaction(trans, ret);
11701174
goto out;
11711175
}
11721176
wret = balance_node_right(trans, mid, left);

0 commit comments

Comments
 (0)