btrfs-progs: lowmem check: Fix function call stack overflow caused by wrong tree...
authorQu Wenruo <wqu@suse.com>
Wed, 22 Nov 2017 09:03:21 +0000 (17:03 +0800)
committerDavid Sterba <dsterba@suse.com>
Wed, 3 Jan 2018 16:09:19 +0000 (17:09 +0100)
For reloc tree root, its backref points to itself.  So for such case,
we should finish the lookup.

Previous end condition is to ensure it's reloc tree *and* needs its root
bytenr to match the bytenr passed in.

However the @root passed can be another tree, e.g. other tree reloc root
which shares the node/leaf.  This makes any check based on @root passed
in invalid.

The patch removes the unreliable root objectid detection, and only uses
root->bytenr check.
For the possibility of invalid self-pointing backref, extent tree
checker should have already handled it, so we don't need to bother in
fs tree checker.

Fixes: 54c8f9152fd9 ("btrfs-progs: check: Fix lowmem mode stack overflow caused by fsck/023")
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
cmds-check.c

index 452e715..7eb08b6 100644 (file)
@@ -11700,16 +11700,12 @@ static int check_tree_block_ref(struct btrfs_root *root,
        u32 nodesize = root->fs_info->nodesize;
        u32 item_size;
        u64 offset;
-       int tree_reloc_root = 0;
        int found_ref = 0;
        int err = 0;
        int ret;
        int strict = 1;
        int parent = 0;
 
-       if (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID &&
-           btrfs_header_bytenr(root->node) == bytenr)
-               tree_reloc_root = 1;
        btrfs_init_path(&path);
        key.objectid = bytenr;
        if (btrfs_fs_incompat(root->fs_info, SKINNY_METADATA))
@@ -11817,8 +11813,12 @@ static int check_tree_block_ref(struct btrfs_root *root,
                        /*
                         * Backref of tree reloc root points to itself, no need
                         * to check backref any more.
+                        *
+                        * This may be an error of loop backref, but extent tree
+                        * checker should have already handled it.
+                        * Here we only need to avoid infinite iteration.
                         */
-                       if (tree_reloc_root) {
+                       if (offset == bytenr) {
                                found_ref = 1;
                        } else {
                                /*