summaryrefslogtreecommitdiff
path: root/check/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'check/main.c')
-rw-r--r--check/main.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/check/main.c b/check/main.c
index 152eecec..b5ca6515 100644
--- a/check/main.c
+++ b/check/main.c
@@ -3398,6 +3398,7 @@ static int check_fs_roots(struct btrfs_fs_info *fs_info,
struct extent_buffer *leaf, *tree_node;
struct btrfs_root *tmp_root;
struct btrfs_root *tree_root = fs_info->tree_root;
+ u64 skip_root = 0;
int ret;
int err = 0;
@@ -3413,7 +3414,10 @@ static int check_fs_roots(struct btrfs_fs_info *fs_info,
again:
key.offset = 0;
- key.objectid = 0;
+ if (skip_root)
+ key.objectid = skip_root + 1;
+ else
+ key.objectid = 0;
key.type = BTRFS_ROOT_ITEM_KEY;
ret = btrfs_search_slot(NULL, tree_root, &key, &path, 0, 0);
if (ret < 0) {
@@ -3422,6 +3426,7 @@ again:
}
tree_node = tree_root->node;
while (1) {
+
if (tree_node != tree_root->node) {
free_root_recs_tree(root_cache);
btrfs_release_path(&path);
@@ -3458,8 +3463,18 @@ again:
btrfs_release_path(&path);
goto again;
}
- if (ret)
+ if (ret) {
err = 1;
+
+ /*
+ * We failed to repair this root but modified
+ * tree root, after again: label we will still
+ * hit this root and fail to repair, so we must
+ * skip it to avoid infinite loop.
+ */
+ if (repair)
+ skip_root = key.objectid;
+ }
if (key.objectid == BTRFS_TREE_RELOC_OBJECTID)
btrfs_free_fs_root(tmp_root);
} else if (key.type == BTRFS_ROOT_REF_KEY ||