summaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
authorLiu Bo <bo.li.liu@oracle.com>2017-09-15 17:06:51 -0400
committerDavid Sterba <dsterba@suse.com>2017-09-26 08:54:07 -0400
commit99c4e3b96c797f047be4e6b7c03cfca01959f146 (patch)
treea0807ca940b96170eb888a23b5bd3b159b30fa4b /fs/btrfs/inode.c
parent36b96fdc6b2dc6f4a0fedc563fa7508c91b90a10 (diff)
Btrfs: fix unexpected result when dio reading corrupted blocks
commit 4246a0b63bd8 ("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: 4246a0b63bd8 ("block: add a bi_error field to struct bio") Signed-off-by: Liu Bo <bo.li.liu@oracle.com> Reported-by: Goffredo Baroncelli <kreijack@inwind.it> Tested-by: Goffredo Baroncelli <kreijack@inwind.it> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c7
1 files changed, 2 insertions, 5 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index f78c5640c6dc..c242d0230db9 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -8366,11 +8366,8 @@ static void btrfs_endio_direct_read(struct bio *bio)
8366 struct btrfs_io_bio *io_bio = btrfs_io_bio(bio); 8366 struct btrfs_io_bio *io_bio = btrfs_io_bio(bio);
8367 blk_status_t err = bio->bi_status; 8367 blk_status_t err = bio->bi_status;
8368 8368
8369 if (dip->flags & BTRFS_DIO_ORIG_BIO_SUBMITTED) { 8369 if (dip->flags & BTRFS_DIO_ORIG_BIO_SUBMITTED)
8370 err = btrfs_subio_endio_read(inode, io_bio, err); 8370 err = btrfs_subio_endio_read(inode, io_bio, err);
8371 if (!err)
8372 bio->bi_status = 0;
8373 }
8374 8371
8375 unlock_extent(&BTRFS_I(inode)->io_tree, dip->logical_offset, 8372 unlock_extent(&BTRFS_I(inode)->io_tree, dip->logical_offset,
8376 dip->logical_offset + dip->bytes - 1); 8373 dip->logical_offset + dip->bytes - 1);
@@ -8378,7 +8375,7 @@ static void btrfs_endio_direct_read(struct bio *bio)
8378 8375
8379 kfree(dip); 8376 kfree(dip);
8380 8377
8381 dio_bio->bi_status = bio->bi_status; 8378 dio_bio->bi_status = err;
8382 dio_end_io(dio_bio); 8379 dio_end_io(dio_bio);
8383 8380
8384 if (io_bio->end_io) 8381 if (io_bio->end_io)