@@ -1920,10 +1920,7 @@ static int walk_down_tree(struct btrfs_root *root, struct btrfs_path *path,
goto out;
}
- if (btrfs_is_leaf(next))
- status = btrfs_check_leaf(NULL, next);
- else
- status = btrfs_check_node(NULL, next);
+ status = btrfs_check_block_for_repair(next, NULL);
if (status != BTRFS_TREE_BLOCK_CLEAN) {
free_extent_buffer(next);
err = -EIO;
@@ -3701,10 +3698,7 @@ static int check_fs_root(struct btrfs_root *root,
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(NULL, root->node);
- else
- status = btrfs_check_node(NULL, root->node);
+ status = btrfs_check_block_for_repair(root->node, NULL);
if (status != BTRFS_TREE_BLOCK_CLEAN)
return -EIO;
@@ -4607,11 +4601,7 @@ static int check_block(struct btrfs_root *root,
}
rec->info_level = level;
- if (btrfs_is_leaf(buf))
- status = btrfs_check_leaf(&rec->parent_key, buf);
- else
- status = btrfs_check_node(&rec->parent_key, buf);
-
+ status = btrfs_check_block_for_repair(buf, &rec->parent_key);
if (status != BTRFS_TREE_BLOCK_CLEAN) {
if (opt_check_repair)
status = try_to_fix_bad_block(root, buf, status);
@@ -2695,7 +2695,7 @@ static int check_inode_item(struct btrfs_root *root, struct btrfs_path *path)
* we need to bail otherwise we could end up stuck.
*/
if (path->slots[0] == 0 &&
- btrfs_check_leaf(NULL, path->nodes[0]))
+ btrfs_check_block_for_repair(path->nodes[0], NULL))
ret = -EIO;
if (ret < 0) {
@@ -5001,7 +5001,7 @@ static int walk_down_tree(struct btrfs_root *root, struct btrfs_path *path,
if (*level == 0) {
/* skip duplicate check */
if (check || !check_all) {
- ret = btrfs_check_leaf(NULL, cur);
+ ret = btrfs_check_block_for_repair(cur, NULL);
if (ret != BTRFS_TREE_BLOCK_CLEAN) {
err |= -EIO;
break;
@@ -5018,7 +5018,7 @@ static int walk_down_tree(struct btrfs_root *root, struct btrfs_path *path,
break;
}
if (check || !check_all) {
- ret = btrfs_check_node(NULL, cur);
+ ret = btrfs_check_block_for_repair(cur, NULL);
if (ret != BTRFS_TREE_BLOCK_CLEAN) {
err |= -EIO;
break;
@@ -5065,10 +5065,7 @@ static int walk_down_tree(struct btrfs_root *root, struct btrfs_path *path,
if (ret < 0)
break;
- if (btrfs_is_leaf(next))
- status = btrfs_check_leaf(NULL, next);
- else
- status = btrfs_check_node(NULL, next);
+ status = btrfs_check_block_for_repair(next, NULL);
if (status != BTRFS_TREE_BLOCK_CLEAN) {
free_extent_buffer(next);
err |= -EIO;
@@ -299,3 +299,32 @@ out:
extent_io_tree_cleanup(&used);
return ret;
}
+
+enum btrfs_tree_block_status btrfs_check_block_for_repair(struct extent_buffer *eb,
+ struct btrfs_key *first_key)
+{
+ struct btrfs_fs_info *fs_info = eb->fs_info;
+ enum btrfs_tree_block_status status;
+
+ if (btrfs_is_leaf(eb))
+ status = btrfs_check_leaf(first_key, eb);
+ else
+ status = btrfs_check_node(first_key, eb);
+
+ if (status == BTRFS_TREE_BLOCK_CLEAN)
+ return status;
+
+ if (btrfs_header_owner(eb) == BTRFS_EXTENT_TREE_OBJECTID) {
+ struct btrfs_key key;
+
+ if (first_key)
+ memcpy(&key, first_key, sizeof(struct btrfs_key));
+ else
+ btrfs_node_key_to_cpu(eb, &key, 0);
+ btrfs_add_corrupt_extent_record(fs_info, &key,
+ eb->start, eb->len,
+ btrfs_header_level(eb));
+ }
+ return status;
+
+}
@@ -43,5 +43,6 @@ int btrfs_mark_used_tree_blocks(struct btrfs_fs_info *fs_info,
struct extent_io_tree *tree);
int btrfs_mark_used_blocks(struct btrfs_fs_info *fs_info,
struct extent_io_tree *tree);
-
+enum btrfs_tree_block_status btrfs_check_block_for_repair(struct extent_buffer *eb,
+ struct btrfs_key *first_key);
#endif
@@ -668,17 +668,8 @@ btrfs_check_node(struct btrfs_key *parent_key, struct extent_buffer *node)
goto fail;
}
}
- return BTRFS_TREE_BLOCK_CLEAN;
+ ret = BTRFS_TREE_BLOCK_CLEAN;
fail:
- if (btrfs_header_owner(node) == BTRFS_EXTENT_TREE_OBJECTID) {
- if (parent_key)
- memcpy(&key, parent_key, sizeof(struct btrfs_key));
- else
- btrfs_node_key_to_cpu(node, &key, 0);
- btrfs_add_corrupt_extent_record(fs_info, &key,
- node->start, node->len,
- btrfs_header_level(node));
- }
return ret;
}
@@ -782,17 +773,8 @@ btrfs_check_leaf(struct btrfs_key *parent_key, struct extent_buffer *leaf)
prev_key.offset = key.offset;
}
- return BTRFS_TREE_BLOCK_CLEAN;
+ ret = BTRFS_TREE_BLOCK_CLEAN;
fail:
- if (btrfs_header_owner(leaf) == BTRFS_EXTENT_TREE_OBJECTID) {
- if (parent_key)
- memcpy(&key, parent_key, sizeof(struct btrfs_key));
- else
- btrfs_item_key_to_cpu(leaf, &key, 0);
-
- btrfs_add_corrupt_extent_record(fs_info, &key,
- leaf->start, leaf->len, 0);
- }
return ret;
}
btrfs check wants to be able to record corrupted extents if it finds any bad blocks. This has been done directly inside of the btrfs_check_leaf/btrfs_check_node helpers, but these are going to be sync'ed from the kernel in the future. Add another helper and move the corrupt block handling into this helper and keep it inside of the check code. Signed-off-by: Josef Bacik <josef@toxicpanda.com> --- check/main.c | 16 +++------------- check/mode-lowmem.c | 11 ++++------- check/repair.c | 29 +++++++++++++++++++++++++++++ check/repair.h | 3 ++- kernel-shared/ctree.c | 22 ++-------------------- 5 files changed, 40 insertions(+), 41 deletions(-)