btrfs-progs: check blocks in btrfs_next_sibling_block

By enabling the lowmem checks properly I uncovered the case where test
fsck/007 will infinite loop at the detection stage.  This is because
when checking the inode item we will just btrfs_next_item(), and because
we ignore check tree block failures at read time we don't get an -EIO
from btrfs_next_leaf.

This occurs because we allow fsck to raw-read blocks even if they fail
basic sanity checks, because we want the opportunity to repair the
blocks.  However this means corrupt blocks are sitting in cache marked
as uptodate.  btrfs_search_slot() handles this by doing a check_block()
on every block we add to the path, so that anything that is doing a
search gets a proper -EIO.

btrfs_next_sibling_block() needs a similar check.  With this fix we now
return -EIO on btrfs_next_leaf() properly and we no longer infinite loop
on fsck/007 with lowmem.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Josef Bacik 2021-08-23 15:23:06 -04:00 committed by David Sterba
parent 71404c50e8
commit 8c3c13bb45
1 changed files with 7 additions and 0 deletions

View File

@ -3125,6 +3125,13 @@ int btrfs_next_sibling_tree_block(struct btrfs_fs_info *fs_info,
free_extent_buffer(c);
path->nodes[level] = next;
path->slots[level] = 0;
/*
* Fsck will happily load corrupt blocks in order to fix them,
* so we need an extra check just to make sure this block isn't
* marked uptodate but invalid.
*/
if (check_block(fs_info, path, level))
return -EIO;
if (level == path->lowest_level)
break;
if (path->reada)