* [PATCH 1/4] btrfs-progs: Use @fs_info to replace @root for btrfs_check_leaf/node()
@ 2019-03-07 11:31 Qu Wenruo
2019-03-07 11:31 ` [PATCH 2/4] btrfs-progs: Use mirror_num start from 1 to avoid unnecessary retry Qu Wenruo
2019-03-07 11:31 ` [PATCH 3/4] btrfs-progs: Move btrfs_num_copies() call out of the loop in read_tree_block() Qu Wenruo
0 siblings, 2 replies; 3+ messages in thread
From: Qu Wenruo @ 2019-03-07 11:31 UTC (permalink / raw)
To: linux-btrfs
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
check/main.c | 12 ++++++------
check/mode-lowmem.c | 8 ++++----
ctree.c | 32 ++++++++++++++++----------------
ctree.h | 8 ++++----
4 files changed, 30 insertions(+), 30 deletions(-)
diff --git a/check/main.c b/check/main.c
index 7547209c5604..51724a92af5f 100644
--- a/check/main.c
+++ b/check/main.c
@@ -1808,9 +1808,9 @@ static int walk_down_tree(struct btrfs_root *root, struct btrfs_path *path,
}
if (btrfs_is_leaf(next))
- status = btrfs_check_leaf(root, NULL, next);
+ status = btrfs_check_leaf(fs_info, NULL, next);
else
- status = btrfs_check_node(root, NULL, next);
+ status = btrfs_check_node(fs_info, NULL, next);
if (status != BTRFS_TREE_BLOCK_CLEAN) {
free_extent_buffer(next);
err = -EIO;
@@ -3403,9 +3403,9 @@ static int check_fs_root(struct btrfs_root *root,
/* We may not have checked the root block, lets do that now */
if (btrfs_is_leaf(root->node))
- status = btrfs_check_leaf(root, NULL, root->node);
+ status = btrfs_check_leaf(root->fs_info, NULL, root->node);
else
- status = btrfs_check_node(root, NULL, root->node);
+ status = btrfs_check_node(root->fs_info, NULL, root->node);
if (status != BTRFS_TREE_BLOCK_CLEAN)
return -EIO;
@@ -4244,9 +4244,9 @@ static int check_block(struct btrfs_root *root,
rec->info_level = level;
if (btrfs_is_leaf(buf))
- status = btrfs_check_leaf(root, &rec->parent_key, buf);
+ status = btrfs_check_leaf(root->fs_info, &rec->parent_key, buf);
else
- status = btrfs_check_node(root, &rec->parent_key, buf);
+ status = btrfs_check_node(root->fs_info, &rec->parent_key, buf);
if (status != BTRFS_TREE_BLOCK_CLEAN) {
if (repair)
diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c
index fc6228a05a1b..c32cbe028ec6 100644
--- a/check/mode-lowmem.c
+++ b/check/mode-lowmem.c
@@ -4617,7 +4617,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(root, NULL, cur);
+ ret = btrfs_check_leaf(fs_info, NULL, cur);
if (ret != BTRFS_TREE_BLOCK_CLEAN) {
err |= -EIO;
break;
@@ -4634,7 +4634,7 @@ static int walk_down_tree(struct btrfs_root *root, struct btrfs_path *path,
break;
}
if (check || !check_all) {
- ret = btrfs_check_node(root, NULL, cur);
+ ret = btrfs_check_node(fs_info, NULL, cur);
if (ret != BTRFS_TREE_BLOCK_CLEAN) {
err |= -EIO;
break;
@@ -4682,9 +4682,9 @@ static int walk_down_tree(struct btrfs_root *root, struct btrfs_path *path,
break;
if (btrfs_is_leaf(next))
- status = btrfs_check_leaf(root, NULL, next);
+ status = btrfs_check_leaf(fs_info, NULL, next);
else
- status = btrfs_check_node(root, NULL, next);
+ status = btrfs_check_node(fs_info, NULL, next);
if (status != BTRFS_TREE_BLOCK_CLEAN) {
free_extent_buffer(next);
err |= -EIO;
diff --git a/ctree.c b/ctree.c
index 7cb3f8451542..f93a60e42b65 100644
--- a/ctree.c
+++ b/ctree.c
@@ -434,8 +434,8 @@ static inline unsigned int leaf_data_end(const struct btrfs_fs_info *fs_info,
}
enum btrfs_tree_block_status
-btrfs_check_node(struct btrfs_root *root, struct btrfs_disk_key *parent_key,
- struct extent_buffer *buf)
+btrfs_check_node(struct btrfs_fs_info *fs_info,
+ struct btrfs_disk_key *parent_key, struct extent_buffer *buf)
{
int i;
struct btrfs_key cpukey;
@@ -443,7 +443,7 @@ btrfs_check_node(struct btrfs_root *root, struct btrfs_disk_key *parent_key,
u32 nritems = btrfs_header_nritems(buf);
enum btrfs_tree_block_status ret = BTRFS_TREE_BLOCK_INVALID_NRITEMS;
- if (nritems == 0 || nritems > BTRFS_NODEPTRS_PER_BLOCK(root->fs_info))
+ if (nritems == 0 || nritems > BTRFS_NODEPTRS_PER_BLOCK(fs_info))
goto fail;
ret = BTRFS_TREE_BLOCK_INVALID_PARENT_KEY;
@@ -466,7 +466,7 @@ fail:
btrfs_disk_key_to_cpu(&cpukey, parent_key);
else
btrfs_node_key_to_cpu(buf, &cpukey, 0);
- btrfs_add_corrupt_extent_record(root->fs_info, &cpukey,
+ btrfs_add_corrupt_extent_record(fs_info, &cpukey,
buf->start, buf->len,
btrfs_header_level(buf));
}
@@ -474,8 +474,8 @@ fail:
}
enum btrfs_tree_block_status
-btrfs_check_leaf(struct btrfs_root *root, struct btrfs_disk_key *parent_key,
- struct extent_buffer *buf)
+btrfs_check_leaf(struct btrfs_fs_info *fs_info,
+ struct btrfs_disk_key *parent_key, struct extent_buffer *buf)
{
int i;
struct btrfs_key cpukey;
@@ -531,18 +531,18 @@ btrfs_check_leaf(struct btrfs_root *root, struct btrfs_disk_key *parent_key,
goto fail;
}
if (i == 0 && btrfs_item_end_nr(buf, i) !=
- BTRFS_LEAF_DATA_SIZE(root->fs_info)) {
+ BTRFS_LEAF_DATA_SIZE(fs_info)) {
ret = BTRFS_TREE_BLOCK_INVALID_OFFSETS;
fprintf(stderr, "bad item end %u wanted %u\n",
btrfs_item_end_nr(buf, i),
- (unsigned)BTRFS_LEAF_DATA_SIZE(root->fs_info));
+ (unsigned)BTRFS_LEAF_DATA_SIZE(fs_info));
goto fail;
}
}
for (i = 0; i < nritems; i++) {
if (btrfs_item_end_nr(buf, i) >
- BTRFS_LEAF_DATA_SIZE(root->fs_info)) {
+ BTRFS_LEAF_DATA_SIZE(fs_info)) {
btrfs_item_key(buf, &key, 0);
btrfs_print_key(&key);
fflush(stdout);
@@ -550,7 +550,7 @@ btrfs_check_leaf(struct btrfs_root *root, struct btrfs_disk_key *parent_key,
fprintf(stderr, "slot end outside of leaf %llu > %llu\n",
(unsigned long long)btrfs_item_end_nr(buf, i),
(unsigned long long)BTRFS_LEAF_DATA_SIZE(
- root->fs_info));
+ fs_info));
goto fail;
}
}
@@ -563,13 +563,13 @@ fail:
else
btrfs_item_key_to_cpu(buf, &cpukey, 0);
- btrfs_add_corrupt_extent_record(root->fs_info, &cpukey,
+ btrfs_add_corrupt_extent_record(fs_info, &cpukey,
buf->start, buf->len, 0);
}
return ret;
}
-static int noinline check_block(struct btrfs_root *root,
+static int noinline check_block(struct btrfs_fs_info *fs_info,
struct btrfs_path *path, int level)
{
struct btrfs_disk_key key;
@@ -585,9 +585,9 @@ static int noinline check_block(struct btrfs_root *root,
key_ptr = &key;
}
if (level == 0)
- ret = btrfs_check_leaf(root, key_ptr, path->nodes[0]);
+ ret = btrfs_check_leaf(fs_info, key_ptr, path->nodes[0]);
else
- ret = btrfs_check_node(root, key_ptr, path->nodes[level]);
+ ret = btrfs_check_node(fs_info, key_ptr, path->nodes[level]);
if (ret == BTRFS_TREE_BLOCK_CLEAN)
return 0;
return -EIO;
@@ -871,7 +871,7 @@ static int balance_level(struct btrfs_trans_handle *trans,
}
}
/* double check we haven't messed things up */
- check_block(root, path, level);
+ check_block(root->fs_info, path, level);
if (orig_ptr !=
btrfs_node_blockptr(path->nodes[level], path->slots[level]))
BUG();
@@ -1169,7 +1169,7 @@ again:
WARN_ON(1);
level = btrfs_header_level(b);
p->nodes[level] = b;
- ret = check_block(root, p, level);
+ ret = check_block(fs_info, p, level);
if (ret)
return -1;
ret = bin_search(b, key, level, &slot);
diff --git a/ctree.h b/ctree.h
index abc20e283fdc..6f2bb5fc2cda 100644
--- a/ctree.h
+++ b/ctree.h
@@ -2570,11 +2570,11 @@ int btrfs_comp_cpu_keys(const struct btrfs_key *k1, const struct btrfs_key *k2);
int btrfs_del_ptr(struct btrfs_root *root, struct btrfs_path *path,
int level, int slot);
enum btrfs_tree_block_status
-btrfs_check_node(struct btrfs_root *root, struct btrfs_disk_key *parent_key,
- struct extent_buffer *buf);
+btrfs_check_node(struct btrfs_fs_info *fs_info,
+ struct btrfs_disk_key *parent_key, struct extent_buffer *buf);
enum btrfs_tree_block_status
-btrfs_check_leaf(struct btrfs_root *root, struct btrfs_disk_key *parent_key,
- struct extent_buffer *buf);
+btrfs_check_leaf(struct btrfs_fs_info *fs_info,
+ struct btrfs_disk_key *parent_key, struct extent_buffer *buf);
void reada_for_search(struct btrfs_fs_info *fs_info, struct btrfs_path *path,
int level, int slot, u64 objectid);
struct extent_buffer *read_node_slot(struct btrfs_fs_info *fs_info,
--
2.21.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 2/4] btrfs-progs: Use mirror_num start from 1 to avoid unnecessary retry
2019-03-07 11:31 [PATCH 1/4] btrfs-progs: Use @fs_info to replace @root for btrfs_check_leaf/node() Qu Wenruo
@ 2019-03-07 11:31 ` Qu Wenruo
2019-03-07 11:31 ` [PATCH 3/4] btrfs-progs: Move btrfs_num_copies() call out of the loop in read_tree_block() Qu Wenruo
1 sibling, 0 replies; 3+ messages in thread
From: Qu Wenruo @ 2019-03-07 11:31 UTC (permalink / raw)
To: linux-btrfs
[BUG]
If the first copy of a tree block is corrupted but the other copy is
good, btrfs-progs will report the error twice:
checksum verify failed on 30556160 found 42A2DA71 wanted 00000000
checksum verify failed on 30556160 found 42A2DA71 wanted 00000000
While kernel only report it once, just as expected:
BTRFS warning (device dm-3): dm-3 checksum verify failed on 30556160 wanted 0 found 42A2DA71 level 0
[CAUSE]
We use mirror_num = 0 in read_tree_block() of btrfs-progs.
At first glance it's pretty OK, but mirror num 0 in btrfs means ANY
good copy. Real mirror num starts from 1.
In the context of read_tree_block(), since it's read_tree_block() to do
all the checks, mirror num 0 just means the first copy.
So if the first copy is corrupted, btrfs-progs will try mirror num 1
next, which is just the same as mirror num 0.
After reporting the same error on the same copy, btrfs-progs will
finally try mirror num 2, and get the good copy.
[FIX]
The fix is way simpler than all the above analyse, just starts from
mirror num 1.
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
disk-io.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/disk-io.c b/disk-io.c
index 797b9b79ea3c..369592eb7b5c 100644
--- a/disk-io.c
+++ b/disk-io.c
@@ -325,7 +325,7 @@ struct extent_buffer* read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr,
struct extent_buffer *eb;
u64 best_transid = 0;
u32 sectorsize = fs_info->sectorsize;
- int mirror_num = 0;
+ int mirror_num = 1;
int good_mirror = 0;
int num_copies;
int ignore = 0;
@@ -381,7 +381,7 @@ struct extent_buffer* read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr,
ignore = 1;
continue;
}
- if (btrfs_header_generation(eb) > best_transid && mirror_num) {
+ if (btrfs_header_generation(eb) > best_transid) {
best_transid = btrfs_header_generation(eb);
good_mirror = mirror_num;
}
--
2.21.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 3/4] btrfs-progs: Move btrfs_num_copies() call out of the loop in read_tree_block()
2019-03-07 11:31 [PATCH 1/4] btrfs-progs: Use @fs_info to replace @root for btrfs_check_leaf/node() Qu Wenruo
2019-03-07 11:31 ` [PATCH 2/4] btrfs-progs: Use mirror_num start from 1 to avoid unnecessary retry Qu Wenruo
@ 2019-03-07 11:31 ` Qu Wenruo
1 sibling, 0 replies; 3+ messages in thread
From: Qu Wenruo @ 2019-03-07 11:31 UTC (permalink / raw)
To: linux-btrfs
btrfs_num_copies really only needs to be called once, so move it out of
the verification loop in read_tree_block().
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
disk-io.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/disk-io.c b/disk-io.c
index 369592eb7b5c..1736d4a1f94b 100644
--- a/disk-io.c
+++ b/disk-io.c
@@ -349,6 +349,7 @@ struct extent_buffer* read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr,
if (btrfs_buffer_uptodate(eb, parent_transid))
return eb;
+ num_copies = btrfs_num_copies(fs_info, eb->start, eb->len);
while (1) {
ret = read_whole_eb(fs_info, eb, mirror_num);
if (ret == 0 && csum_tree_block(fs_info, eb, 1) == 0 &&
@@ -376,7 +377,6 @@ struct extent_buffer* read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr,
ret = -EIO;
break;
}
- num_copies = btrfs_num_copies(fs_info, eb->start, eb->len);
if (num_copies == 1) {
ignore = 1;
continue;
--
2.21.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2019-03-07 11:31 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-03-07 11:31 [PATCH 1/4] btrfs-progs: Use @fs_info to replace @root for btrfs_check_leaf/node() Qu Wenruo
2019-03-07 11:31 ` [PATCH 2/4] btrfs-progs: Use mirror_num start from 1 to avoid unnecessary retry Qu Wenruo
2019-03-07 11:31 ` [PATCH 3/4] btrfs-progs: Move btrfs_num_copies() call out of the loop in read_tree_block() Qu Wenruo
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.