Skip to content

Commit

Permalink
btrfs: handle missing chunk mapping more gracefully
Browse files Browse the repository at this point in the history
[BUG]
During my scrub rework, I did a stupid thing like this:

        bio->bi_iter.bi_sector = stripe->logical;
        btrfs_submit_bio(fs_info, bio, stripe->mirror_num);

Above bi_sector assignment is using logical address directly, which
lacks ">> SECTOR_SHIFT".

This results a read on a range which has no chunk mapping.

This results the following crash:

  BTRFS critical (device dm-1): unable to find logical 11274289152 length 65536
  assertion failed: !IS_ERR(em), in fs/btrfs/volumes.c:6387

Sure this is all my fault, but this shows a possible problem in real
world, that some bit flip in file extents/tree block can point to
unmapped ranges, and trigger above ASSERT(), or if CONFIG_BTRFS_ASSERT
is not configured, cause invalid pointer access.

[PROBLEMS]
In the above call chain, we just don't handle the possible error from
btrfs_get_chunk_map() inside __btrfs_map_block().

[FIX]
The fix is straightforward, replace the ASSERT() with proper error
handling (callers handle errors already).

Reviewed-by: Anand Jain <anand.jain@oracle.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
  • Loading branch information
Qu Wenruo authored and David Sterba committed Mar 15, 2023
1 parent 675dfe1 commit 1c3ab6d
Showing 1 changed file with 2 additions and 1 deletion.
3 changes: 2 additions & 1 deletion fs/btrfs/volumes.c
Original file line number Diff line number Diff line change
Expand Up @@ -6363,7 +6363,8 @@ int __btrfs_map_block(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
ASSERT(op != BTRFS_MAP_DISCARD);

em = btrfs_get_chunk_map(fs_info, logical, *length);
ASSERT(!IS_ERR(em));
if (IS_ERR(em))
return PTR_ERR(em);

map = em->map_lookup;
data_stripes = nr_data_stripes(map);
Expand Down

0 comments on commit 1c3ab6d

Please sign in to comment.