Commit 99c4e3b9 authored by Liu Bo's avatar Liu Bo Committed by David Sterba

Btrfs: fix unexpected result when dio reading corrupted blocks

commit 4246a0b6 ("block: add a bi_error field to struct bio")
changed the logic of how dio read endio reports errors.

For single stripe dio read, %bio->bi_status reflects the error before
verifying checksum, and now we're updating it when data block matches
with its checksum, while in the mismatching case, %bio->bi_status is
not updated to relfect that.

When some blocks in a file have been corrupted on disk, reading such a
file ends up with

1) checksum errors are reported in kernel log
2) read(2) returns successfully with some content being 0x01.

In order to fix it, we need to report its checksum mismatch error to
the upper layer (dio layer in this case) as well.

Fixes: 4246a0b6 ("block: add a bi_error field to struct bio")
Signed-off-by: default avatarLiu Bo <bo.li.liu@oracle.com>
Reported-by: default avatarGoffredo Baroncelli <kreijack@inwind.it>
Tested-by: default avatarGoffredo Baroncelli <kreijack@inwind.it>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 36b96fdc
...@@ -8366,11 +8366,8 @@ static void btrfs_endio_direct_read(struct bio *bio) ...@@ -8366,11 +8366,8 @@ static void btrfs_endio_direct_read(struct bio *bio)
struct btrfs_io_bio *io_bio = btrfs_io_bio(bio); struct btrfs_io_bio *io_bio = btrfs_io_bio(bio);
blk_status_t err = bio->bi_status; blk_status_t err = bio->bi_status;
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); err = btrfs_subio_endio_read(inode, io_bio, err);
if (!err)
bio->bi_status = 0;
}
unlock_extent(&BTRFS_I(inode)->io_tree, dip->logical_offset, unlock_extent(&BTRFS_I(inode)->io_tree, dip->logical_offset,
dip->logical_offset + dip->bytes - 1); dip->logical_offset + dip->bytes - 1);
...@@ -8378,7 +8375,7 @@ static void btrfs_endio_direct_read(struct bio *bio) ...@@ -8378,7 +8375,7 @@ static void btrfs_endio_direct_read(struct bio *bio)
kfree(dip); kfree(dip);
dio_bio->bi_status = bio->bi_status; dio_bio->bi_status = err;
dio_end_io(dio_bio); dio_end_io(dio_bio);
if (io_bio->end_io) if (io_bio->end_io)
......
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