summaryrefslogtreecommitdiff
path: root/cmds-check.c
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fb.com>2014-10-03 10:50:15 -0400
committerDavid Sterba <dsterba@suse.cz>2014-10-14 11:06:31 +0200
commitf738a758af3b04c302dca2a1c50b9a021a40148c (patch)
tree337d95744ec4122f6ffc9eae17c1f8a950c1eb0b /cmds-check.c
parent187b85436b8d2209bb0df1d67a97be711663615e (diff)
btrfs-progs: check blocks when checking fs roots
Usually if we find a bad block during the extent tree stuff we will error out, but if the bad block is in an fs tree and doens't have extents in it then fsck may still pass even though the block was complete garbage. So add the check block logic to the fs root checking so we actually error out of fsck if there is a bad block. Thanks, Signed-off-by: Josef Bacik <jbacik@fb.com> Signed-off-by: David Sterba <dsterba@suse.cz>
Diffstat (limited to 'cmds-check.c')
-rw-r--r--cmds-check.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/cmds-check.c b/cmds-check.c
index 75b984f2..db7f7452 100644
--- a/cmds-check.c
+++ b/cmds-check.c
@@ -1396,6 +1396,7 @@ static int check_child_node(struct btrfs_root *root,
static int walk_down_tree(struct btrfs_root *root, struct btrfs_path *path,
struct walk_control *wc, int *level)
{
+ enum btrfs_tree_block_status status;
u64 bytenr;
u64 ptr_gen;
struct extent_buffer *next;
@@ -1473,6 +1474,17 @@ static int walk_down_tree(struct btrfs_root *root, struct btrfs_path *path,
err = ret;
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;
free_extent_buffer(path->nodes[*level]);
path->nodes[*level] = next;
@@ -2257,6 +2269,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);
@@ -2275,6 +2288,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;