If check block fails during the extent tree checks we could evict the extent buffer from cache, so the next time we go to read it for the fs_tree checks we could miss the fact that its bogus and blow up in strange and interesting ways. Fix this by running the leaf/node checks on all blocks in the fs root so we know we're looking at valid blocks. Thanks,
Signed-off-by: Josef Bacik <jba...@fb.com> --- cmds-check.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/cmds-check.c b/cmds-check.c index 5b8417c..db779ae 100644 --- a/cmds-check.c +++ b/cmds-check.c @@ -1376,6 +1376,8 @@ static int walk_down_tree(struct btrfs_root *root, struct btrfs_path *path, next = btrfs_find_tree_block(root, bytenr, blocksize); if (!next || !btrfs_buffer_uptodate(next, ptr_gen)) { + enum btrfs_tree_block_status status; + free_extent_buffer(next); reada_walk_down(root, cur, path->slots[*level]); next = read_tree_block(root, bytenr, blocksize, @@ -1384,6 +1386,16 @@ static int walk_down_tree(struct btrfs_root *root, struct btrfs_path *path, err = -EIO; goto out; } + + if (btrfs_is_leaf(next)) + status = btrfs_check_leaf(root, NULL, next); + else + status = btrfs_check_node(root, NULL, next); + if (status != BTRFS_TREE_BLOCK_CLEAN) { + free_extent_buffer(next); + err = -EIO; + goto out; + } } *level = *level - 1; @@ -2078,6 +2090,7 @@ static int check_fs_root(struct btrfs_root *root, struct shared_node root_node; struct root_record *rec; struct btrfs_root_item *root_item = &root->root_item; + enum btrfs_tree_block_status status; if (root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID) { rec = get_root_rec(root_cache, root->root_key.objectid); @@ -2096,6 +2109,14 @@ static int check_fs_root(struct btrfs_root *root, wc->active_node = level; wc->root_level = level; + /* We may not have checked the root block, lets do that now */ + if (btrfs_is_leaf(root->node)) + status = btrfs_check_leaf(root, NULL, root->node); + else + status = btrfs_check_node(root, NULL, root->node); + if (status != BTRFS_TREE_BLOCK_CLEAN) + return -EIO; + if (btrfs_root_refs(root_item) > 0 || btrfs_disk_key_objectid(&root_item->drop_progress) == 0) { path.nodes[level] = root->node; -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html