@@ -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;
@@ -2756,10 +2757,13 @@ static void submit_data_read_repair(struct inode *inode, struct bio *failed_bio,
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 bio_logical = failed_bbio->iter.bi_sector << SECTOR_SHIFT;
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;
const int nr_bits = (end + 1 - start) >> fs_info->sectorsize_bits;
+ int num_copies;
int i;
BUG_ON(bio_op(failed_bio) == REQ_OP_WRITE);
@@ -2776,10 +2780,13 @@ static void submit_data_read_repair(struct inode *inode, struct bio *failed_bio,
*/
ASSERT(page->mapping && !bio_flagged(failed_bio, BIO_CLONED));
+ num_copies = btrfs_num_copies(fs_info, bio_logical, fs_info->sectorsize);
+
/* Iterate through all the sectors in the range */
for (i = 0; i < nr_bits; i++) {
const unsigned int offset = i * sectorsize;
bool uptodate = false;
+ u8 *expected_csum = NULL;
int ret;
if (!(error_bitmap & (1U << i))) {
@@ -2791,22 +2798,19 @@ static void submit_data_read_repair(struct inode *inode, struct bio *failed_bio,
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.
- */
- continue;
- }
+ if (failed_bbio->csum)
+ expected_csum = btrfs_csum_ptr(fs_info,
+ failed_bbio->csum, bio_offset + offset);
+
+ ret = btrfs_read_repair_sector(inode, page, pgoff + offset,
+ bio_logical + bio_offset + offset,
+ start + offset, failed_bbio->mirror_num,
+ num_copies, expected_csum);
+ if (!ret)
+ uptodate = true;
/*
- * Continue on failed repair, otherwise the remaining sectors
- * will not be properly unlocked.
+ * If above repair failed, we have tried all mirrors, time to
+ * release the corrupted sector.
*/
next:
end_sector_io(page, start + offset, uptodate);
Just call the new btrfs_read_repair_sector() to replace the old btrfs_repair_one_sector(). And since the new helper only handles the page content, the caller still needs to handle the page status update and unlock. Signed-off-by: Qu Wenruo <wqu@suse.com> --- fs/btrfs/extent_io.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-)