Btrfs: tolerate errors if we have retried successfully
With raid1 profile, dio read isn't tolerating IO errors if read length is less than the stripe length (64K). Our bio didn't get split in btrfs_submit_direct_hook() if (dip->flags & BTRFS_DIO_ORIG_BIO_SUBMITTED) is true and that happens when the read length is less than 64k. In this case, if the underlying device returns error somehow, bio->bi_error has recorded that error. If we could recover the correct data from another copy in profile raid1/10/5/6, with btrfs_subio_endio_read() returning 0, bio would have the correct data in its vector, but bio->bi_error is not updated accordingly so that the following dio_end_io(dio_bio, bio->bi_error) makes directIO think this read has failed. This fixes the problem by setting bio's error to 0 if a good copy has been found. Signed-off-by: Liu Bo <bo.li.liu@oracle.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
c821e7f3da
commit
e3d37faba2
|
@ -8261,8 +8261,11 @@ static void btrfs_endio_direct_read(struct bio *bio)
|
|||
struct btrfs_io_bio *io_bio = btrfs_io_bio(bio);
|
||||
int err = bio->bi_error;
|
||||
|
||||
if (dip->flags & BTRFS_DIO_ORIG_BIO_SUBMITTED)
|
||||
if (dip->flags & BTRFS_DIO_ORIG_BIO_SUBMITTED) {
|
||||
err = btrfs_subio_endio_read(inode, io_bio, err);
|
||||
if (!err)
|
||||
bio->bi_error = 0;
|
||||
}
|
||||
|
||||
unlock_extent(&BTRFS_I(inode)->io_tree, dip->logical_offset,
|
||||
dip->logical_offset + dip->bytes - 1);
|
||||
|
|
Loading…
Reference in New Issue