|
@@ -151,10 +151,10 @@ static int scrub_setup_recheck_block(struct scrub_ctx *sctx,
|
|
struct btrfs_mapping_tree *map_tree,
|
|
struct btrfs_mapping_tree *map_tree,
|
|
u64 length, u64 logical,
|
|
u64 length, u64 logical,
|
|
struct scrub_block *sblock);
|
|
struct scrub_block *sblock);
|
|
-static int scrub_recheck_block(struct btrfs_fs_info *fs_info,
|
|
|
|
- struct scrub_block *sblock, int is_metadata,
|
|
|
|
- int have_csum, u8 *csum, u64 generation,
|
|
|
|
- u16 csum_size);
|
|
|
|
|
|
+static void scrub_recheck_block(struct btrfs_fs_info *fs_info,
|
|
|
|
+ struct scrub_block *sblock, int is_metadata,
|
|
|
|
+ int have_csum, u8 *csum, u64 generation,
|
|
|
|
+ u16 csum_size);
|
|
static void scrub_recheck_block_checksum(struct btrfs_fs_info *fs_info,
|
|
static void scrub_recheck_block_checksum(struct btrfs_fs_info *fs_info,
|
|
struct scrub_block *sblock,
|
|
struct scrub_block *sblock,
|
|
int is_metadata, int have_csum,
|
|
int is_metadata, int have_csum,
|
|
@@ -718,16 +718,8 @@ static int scrub_handle_errored_block(struct scrub_block *sblock_to_check)
|
|
sblock_bad = sblocks_for_recheck + failed_mirror_index;
|
|
sblock_bad = sblocks_for_recheck + failed_mirror_index;
|
|
|
|
|
|
/* build and submit the bios for the failed mirror, check checksums */
|
|
/* build and submit the bios for the failed mirror, check checksums */
|
|
- ret = scrub_recheck_block(fs_info, sblock_bad, is_metadata, have_csum,
|
|
|
|
- csum, generation, sctx->csum_size);
|
|
|
|
- if (ret) {
|
|
|
|
- spin_lock(&sctx->stat_lock);
|
|
|
|
- sctx->stat.read_errors++;
|
|
|
|
- sctx->stat.uncorrectable_errors++;
|
|
|
|
- spin_unlock(&sctx->stat_lock);
|
|
|
|
- btrfs_dev_stat_inc_and_print(dev, BTRFS_DEV_STAT_READ_ERRS);
|
|
|
|
- goto out;
|
|
|
|
- }
|
|
|
|
|
|
+ scrub_recheck_block(fs_info, sblock_bad, is_metadata, have_csum,
|
|
|
|
+ csum, generation, sctx->csum_size);
|
|
|
|
|
|
if (!sblock_bad->header_error && !sblock_bad->checksum_error &&
|
|
if (!sblock_bad->header_error && !sblock_bad->checksum_error &&
|
|
sblock_bad->no_io_error_seen) {
|
|
sblock_bad->no_io_error_seen) {
|
|
@@ -843,10 +835,11 @@ static int scrub_handle_errored_block(struct scrub_block *sblock_to_check)
|
|
sblock_other = sblocks_for_recheck + mirror_index;
|
|
sblock_other = sblocks_for_recheck + mirror_index;
|
|
|
|
|
|
/* build and submit the bios, check checksums */
|
|
/* build and submit the bios, check checksums */
|
|
- ret = scrub_recheck_block(fs_info, sblock_other, is_metadata,
|
|
|
|
- have_csum, csum, generation,
|
|
|
|
- sctx->csum_size);
|
|
|
|
- if (!ret && !sblock_other->header_error &&
|
|
|
|
|
|
+ scrub_recheck_block(fs_info, sblock_other, is_metadata,
|
|
|
|
+ have_csum, csum, generation,
|
|
|
|
+ sctx->csum_size);
|
|
|
|
+
|
|
|
|
+ if (!sblock_other->header_error &&
|
|
!sblock_other->checksum_error &&
|
|
!sblock_other->checksum_error &&
|
|
sblock_other->no_io_error_seen) {
|
|
sblock_other->no_io_error_seen) {
|
|
int force_write = is_metadata || have_csum;
|
|
int force_write = is_metadata || have_csum;
|
|
@@ -931,10 +924,10 @@ static int scrub_handle_errored_block(struct scrub_block *sblock_to_check)
|
|
* is verified, but most likely the data comes out
|
|
* is verified, but most likely the data comes out
|
|
* of the page cache.
|
|
* of the page cache.
|
|
*/
|
|
*/
|
|
- ret = scrub_recheck_block(fs_info, sblock_bad,
|
|
|
|
- is_metadata, have_csum, csum,
|
|
|
|
- generation, sctx->csum_size);
|
|
|
|
- if (!ret && !sblock_bad->header_error &&
|
|
|
|
|
|
+ scrub_recheck_block(fs_info, sblock_bad,
|
|
|
|
+ is_metadata, have_csum, csum,
|
|
|
|
+ generation, sctx->csum_size);
|
|
|
|
+ if (!sblock_bad->header_error &&
|
|
!sblock_bad->checksum_error &&
|
|
!sblock_bad->checksum_error &&
|
|
sblock_bad->no_io_error_seen)
|
|
sblock_bad->no_io_error_seen)
|
|
goto corrected_error;
|
|
goto corrected_error;
|
|
@@ -1061,10 +1054,10 @@ leave_nomem:
|
|
* to take those pages that are not errored from all the mirrors so that
|
|
* to take those pages that are not errored from all the mirrors so that
|
|
* the pages that are errored in the just handled mirror can be repaired.
|
|
* the pages that are errored in the just handled mirror can be repaired.
|
|
*/
|
|
*/
|
|
-static int scrub_recheck_block(struct btrfs_fs_info *fs_info,
|
|
|
|
- struct scrub_block *sblock, int is_metadata,
|
|
|
|
- int have_csum, u8 *csum, u64 generation,
|
|
|
|
- u16 csum_size)
|
|
|
|
|
|
+static void scrub_recheck_block(struct btrfs_fs_info *fs_info,
|
|
|
|
+ struct scrub_block *sblock, int is_metadata,
|
|
|
|
+ int have_csum, u8 *csum, u64 generation,
|
|
|
|
+ u16 csum_size)
|
|
{
|
|
{
|
|
int page_num;
|
|
int page_num;
|
|
|
|
|
|
@@ -1074,7 +1067,6 @@ static int scrub_recheck_block(struct btrfs_fs_info *fs_info,
|
|
|
|
|
|
for (page_num = 0; page_num < sblock->page_count; page_num++) {
|
|
for (page_num = 0; page_num < sblock->page_count; page_num++) {
|
|
struct bio *bio;
|
|
struct bio *bio;
|
|
- int ret;
|
|
|
|
struct scrub_page *page = sblock->pagev[page_num];
|
|
struct scrub_page *page = sblock->pagev[page_num];
|
|
DECLARE_COMPLETION_ONSTACK(complete);
|
|
DECLARE_COMPLETION_ONSTACK(complete);
|
|
|
|
|
|
@@ -1086,18 +1078,17 @@ static int scrub_recheck_block(struct btrfs_fs_info *fs_info,
|
|
|
|
|
|
WARN_ON(!page->page);
|
|
WARN_ON(!page->page);
|
|
bio = bio_alloc(GFP_NOFS, 1);
|
|
bio = bio_alloc(GFP_NOFS, 1);
|
|
- if (!bio)
|
|
|
|
- return -EIO;
|
|
|
|
|
|
+ if (!bio) {
|
|
|
|
+ page->io_error = 1;
|
|
|
|
+ sblock->no_io_error_seen = 0;
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
bio->bi_bdev = page->dev->bdev;
|
|
bio->bi_bdev = page->dev->bdev;
|
|
bio->bi_sector = page->physical >> 9;
|
|
bio->bi_sector = page->physical >> 9;
|
|
bio->bi_end_io = scrub_complete_bio_end_io;
|
|
bio->bi_end_io = scrub_complete_bio_end_io;
|
|
bio->bi_private = &complete;
|
|
bio->bi_private = &complete;
|
|
|
|
|
|
- ret = bio_add_page(bio, page->page, PAGE_SIZE, 0);
|
|
|
|
- if (PAGE_SIZE != ret) {
|
|
|
|
- bio_put(bio);
|
|
|
|
- return -EIO;
|
|
|
|
- }
|
|
|
|
|
|
+ bio_add_page(bio, page->page, PAGE_SIZE, 0);
|
|
btrfsic_submit_bio(READ, bio);
|
|
btrfsic_submit_bio(READ, bio);
|
|
|
|
|
|
/* this will also unplug the queue */
|
|
/* this will also unplug the queue */
|
|
@@ -1114,7 +1105,7 @@ static int scrub_recheck_block(struct btrfs_fs_info *fs_info,
|
|
have_csum, csum, generation,
|
|
have_csum, csum, generation,
|
|
csum_size);
|
|
csum_size);
|
|
|
|
|
|
- return 0;
|
|
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
|
|
|
|
static void scrub_recheck_block_checksum(struct btrfs_fs_info *fs_info,
|
|
static void scrub_recheck_block_checksum(struct btrfs_fs_info *fs_info,
|