@@ -30,6 +30,7 @@
#include "zoned.h"
#include "block-group.h"
#include "compression.h"
+#include "read-repair.h"
static struct kmem_cache *extent_state_cache;
static struct kmem_cache *extent_buffer_cache;
@@ -2749,13 +2750,15 @@ void end_sector_io(struct page *page, u64 offset, bool uptodate)
offset + sectorsize - 1, &cached);
}
-static void submit_data_read_repair(struct inode *inode, struct bio *failed_bio,
+static void submit_data_read_repair(struct inode *inode,
+ struct btrfs_read_repair_ctrl *ctrl, struct bio *failed_bio,
u32 bio_offset, const struct bio_vec *bvec, int failed_mirror,
unsigned int error_bitmap)
{
const unsigned int pgoff = bvec->bv_offset;
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
struct page *page = bvec->bv_page;
+ struct btrfs_bio *failed_bbio = btrfs_bio(failed_bio);
const u64 start = page_offset(bvec->bv_page) + bvec->bv_offset;
const u64 end = start + bvec->bv_len - 1;
const u32 sectorsize = fs_info->sectorsize;
@@ -2780,7 +2783,9 @@ static void submit_data_read_repair(struct inode *inode, struct bio *failed_bio,
for (i = 0; i < nr_bits; i++) {
const unsigned int offset = i * sectorsize;
bool uptodate = false;
- int ret;
+ u64 logical = (failed_bbio->iter.bi_sector << SECTOR_SHIFT) +
+ bio_offset + offset;
+ u8 *csum = NULL;
if (!(error_bitmap & (1U << i))) {
/*
@@ -2788,28 +2793,17 @@ static void submit_data_read_repair(struct inode *inode, struct bio *failed_bio,
* and unlock the range.
*/
uptodate = true;
- goto next;
- }
-
- ret = btrfs_repair_one_sector(inode, failed_bio,
- bio_offset + offset,
- page, pgoff + offset, start + offset,
- failed_mirror, btrfs_submit_data_bio);
- if (!ret) {
- /*
- * We have submitted the read repair, the page release
- * will be handled by the endio function of the
- * submitted repair bio.
- * Thus we don't need to do any thing here.
- */
+ end_sector_io(page, start + offset, uptodate);
continue;
}
- /*
- * Continue on failed repair, otherwise the remaining sectors
- * will not be properly unlocked.
- */
-next:
- end_sector_io(page, start + offset, uptodate);
+ if (failed_bbio->csum)
+ csum = btrfs_csum_ptr(fs_info, failed_bbio->csum,
+ bio_offset + offset);
+
+ /* The function will release the page if hit failure. */
+ btrfs_read_repair_add_sector(inode, ctrl, page, pgoff + offset,
+ logical, start + offset, csum,
+ failed_mirror, false);
}
}
@@ -3017,6 +3011,7 @@ static void end_bio_extent_readpage(struct bio *bio)
struct btrfs_bio *bbio = btrfs_bio(bio);
struct extent_io_tree *tree, *failure_tree;
struct processed_extent processed = { 0 };
+ struct btrfs_read_repair_ctrl ctrl = { 0 };
/*
* The offset to the beginning of a bio, since one bio can never be
* larger than UINT_MAX, u32 here is enough.
@@ -3126,8 +3121,8 @@ static void end_bio_extent_readpage(struct bio *bio)
* submit_data_read_repair() will handle all the good
* and bad sectors, we just continue to the next bvec.
*/
- submit_data_read_repair(inode, bio, bio_offset, bvec,
- mirror, error_bitmap);
+ submit_data_read_repair(inode, &ctrl, bio, bio_offset,
+ bvec, mirror, error_bitmap);
} else {
/* Update page status and unlock */
end_page_read(page, uptodate, start, len);
@@ -3142,6 +3137,7 @@ static void end_bio_extent_readpage(struct bio *bio)
}
/* Release the last extent */
endio_readpage_release_extent(&processed, NULL, 0, 0, false);
+ btrfs_read_repair_finish(&ctrl);
btrfs_bio_free_csum(bbio);
bio_put(bio);
}
We only need to prepare the logical bytenr and file offset of the corrupted sector, and pass it to btrfs_read_repair_add_sector(). And call btrfs_read_repair_finish() before we free the csum. Signed-off-by: Qu Wenruo <wqu@suse.com> --- fs/btrfs/extent_io.c | 44 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 24 deletions(-)