summaryrefslogtreecommitdiff
path: root/cmds-check.c
diff options
context:
space:
mode:
authorQu Wenruo <quwenruo@cn.fujitsu.com>2016-12-05 17:07:54 +0800
committerDavid Sterba <dsterba@suse.com>2016-12-14 15:21:26 +0100
commit54c8f9152fd98c8b5d5e2c9b32d642cc5855241f (patch)
treed68b741058422f77ca2c011c8c792cd0d8cdab6b /cmds-check.c
parent0d8601ab6c7a73f025eeccf8e8ce3aa1cd2f3aa9 (diff)
btrfs-progs: check: Fix lowmem mode stack overflow caused by fsck/023
Lowmem mode fsck will overflow its stack since it will do infinite backref check for tree reloc root. We should not check backref if it's pointing to itself for tree reloc root. Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com> Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'cmds-check.c')
-rw-r--r--cmds-check.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/cmds-check.c b/cmds-check.c
index 2f7b1a8c..fc19e141 100644
--- a/cmds-check.c
+++ b/cmds-check.c
@@ -9975,10 +9975,15 @@ static int check_tree_block_ref(struct btrfs_root *root,
u32 nodesize = root->nodesize;
u32 item_size;
u64 offset;
+ int tree_reloc_root = 0;
int found_ref = 0;
int err = 0;
int ret;
+ 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))
@@ -10066,9 +10071,16 @@ static int check_tree_block_ref(struct btrfs_root *root,
(offset == root->objectid || offset == owner)) {
found_ref = 1;
} else if (type == BTRFS_SHARED_BLOCK_REF_KEY) {
+ /*
+ * Backref of tree reloc root points to itself, no need
+ * to check backref any more.
+ */
+ if (tree_reloc_root)
+ found_ref = 1;
+ else
/* Check if the backref points to valid referencer */
- found_ref = !check_tree_block_ref(root, NULL, offset,
- level + 1, owner);
+ found_ref = !check_tree_block_ref(root, NULL,
+ offset, level + 1, owner);
}
if (found_ref)