summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQu Wenruo <wqu@suse.com>2017-11-22 17:03:21 +0800
committerDavid Sterba <dsterba@suse.com>2018-01-03 17:09:19 +0100
commit77d47b4a3d304e52fd222c4bd21f9306e83037ac (patch)
treea85c35d06ddceb4f73e0615f784c5b02b4176b2d
parente6055097d12220c455468f01023e80c457b4e344 (diff)
btrfs-progs: lowmem check: Fix function call stack overflow caused by wrong tree reloc tree detection
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>
-rw-r--r--cmds-check.c10
1 files changed, 5 insertions, 5 deletions
diff --git a/cmds-check.c b/cmds-check.c
index 452e715b..7eb08b6c 100644
--- a/cmds-check.c
+++ b/cmds-check.c
@@ -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 {
/*