Commit b968fed1 authored by Zhao Lei's avatar Zhao Lei Committed by Chris Mason

Btrfs: Combine per-page recover in dev-replace and scrub

The code are similar, combine them to make code clean and easy to maintenance.
Some lost condition are also completed with benefit of this combination.
Signed-off-by: default avatarZhao Lei <zhaolei@cn.fujitsu.com>
Signed-off-by: default avatarMiao Xie <miaox@cn.fujitsu.com>
Signed-off-by: default avatarChris Mason <clm@fb.com>
parent 8d6738c1
...@@ -1107,54 +1107,10 @@ static int scrub_handle_errored_block(struct scrub_block *sblock_to_check) ...@@ -1107,54 +1107,10 @@ static int scrub_handle_errored_block(struct scrub_block *sblock_to_check)
} }
} }
/* if (sblock_bad->no_io_error_seen && !sctx->is_dev_replace)
* for dev_replace, pick good pages and write to the target device. goto did_not_correct_error;
*/
if (sctx->is_dev_replace) {
success = 1;
for (page_num = 0; page_num < sblock_bad->page_count;
page_num++) {
struct scrub_block *sblock_other = NULL;
for (mirror_index = 0;
mirror_index < BTRFS_MAX_MIRRORS &&
sblocks_for_recheck[mirror_index].page_count > 0;
mirror_index++) {
if (!sblocks_for_recheck[mirror_index].
pagev[page_num]->io_error) {
sblock_other = sblocks_for_recheck +
mirror_index;
break;
}
}
if (!sblock_other) {
/*
* did not find a mirror to fetch the page
* from. scrub_write_page_to_dev_replace()
* handles this case (page->io_error), by
* filling the block with zeros before
* submitting the write request
*/
sblock_other = sblock_bad;
success = 0;
}
if (scrub_write_page_to_dev_replace(sblock_other,
page_num) != 0) {
btrfs_dev_replace_stats_inc(
&sctx->dev_root->
fs_info->dev_replace.
num_write_errors);
success = 0;
}
}
goto out;
}
/* /*
* for regular scrub, repair those pages that are errored.
* In case of I/O errors in the area that is supposed to be * In case of I/O errors in the area that is supposed to be
* repaired, continue by picking good copies of those pages. * repaired, continue by picking good copies of those pages.
* Select the good pages from mirrors to rewrite bad pages from * Select the good pages from mirrors to rewrite bad pages from
...@@ -1178,44 +1134,64 @@ static int scrub_handle_errored_block(struct scrub_block *sblock_to_check) ...@@ -1178,44 +1134,64 @@ static int scrub_handle_errored_block(struct scrub_block *sblock_to_check)
* mirror, even if other 512 byte sectors in the same PAGE_SIZE * mirror, even if other 512 byte sectors in the same PAGE_SIZE
* area are unreadable. * area are unreadable.
*/ */
/* can only fix I/O errors from here on */
if (sblock_bad->no_io_error_seen)
goto did_not_correct_error;
success = 1; success = 1;
for (page_num = 0; page_num < sblock_bad->page_count; page_num++) { for (page_num = 0; page_num < sblock_bad->page_count;
page_num++) {
struct scrub_page *page_bad = sblock_bad->pagev[page_num]; struct scrub_page *page_bad = sblock_bad->pagev[page_num];
struct scrub_block *sblock_other = NULL;
if (!page_bad->io_error) /* skip no-io-error page in scrub */
if (!page_bad->io_error && !sctx->is_dev_replace)
continue; continue;
for (mirror_index = 0; /* try to find no-io-error page in mirrors */
mirror_index < BTRFS_MAX_MIRRORS && if (page_bad->io_error) {
sblocks_for_recheck[mirror_index].page_count > 0; for (mirror_index = 0;
mirror_index++) { mirror_index < BTRFS_MAX_MIRRORS &&
struct scrub_block *sblock_other = sblocks_for_recheck + sblocks_for_recheck[mirror_index].page_count > 0;
mirror_index; mirror_index++) {
struct scrub_page *page_other = sblock_other->pagev[ if (!sblocks_for_recheck[mirror_index].
page_num]; pagev[page_num]->io_error) {
sblock_other = sblocks_for_recheck +
if (!page_other->io_error) { mirror_index;
ret = scrub_repair_page_from_good_copy( break;
sblock_bad, sblock_other, page_num, 0);
if (0 == ret) {
page_bad->io_error = 0;
break; /* succeeded for this page */
} }
} }
if (!sblock_other)
success = 0;
} }
if (page_bad->io_error) { if (sctx->is_dev_replace) {
/* did not find a mirror to copy the page from */ /*
success = 0; * did not find a mirror to fetch the page
* from. scrub_write_page_to_dev_replace()
* handles this case (page->io_error), by
* filling the block with zeros before
* submitting the write request
*/
if (!sblock_other)
sblock_other = sblock_bad;
if (scrub_write_page_to_dev_replace(sblock_other,
page_num) != 0) {
btrfs_dev_replace_stats_inc(
&sctx->dev_root->
fs_info->dev_replace.
num_write_errors);
success = 0;
}
} else if (sblock_other) {
ret = scrub_repair_page_from_good_copy(sblock_bad,
sblock_other,
page_num, 0);
if (0 == ret)
page_bad->io_error = 0;
else
success = 0;
} }
} }
if (success) { if (success && !sctx->is_dev_replace) {
if (is_metadata || have_csum) { if (is_metadata || have_csum) {
/* /*
* need to verify the checksum now that all * need to verify the checksum now that all
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment