diff options
author | Liu Bo <bo.li.liu@oracle.com> | 2017-09-20 17:50:18 -0600 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2017-09-26 14:53:23 +0200 |
commit | cf1167d5c1abf3bc42b2a1562bfa7937c05337e2 (patch) | |
tree | a8e2a5e0fc58793ef9ce24ecd19834a3756c1e17 /fs/btrfs/compression.c | |
parent | bd7d63c2ceaf737eeb21630a2b62fc5fe34dba29 (diff) | |
download | linux-stable-cf1167d5c1abf3bc42b2a1562bfa7937c05337e2.tar.gz linux-stable-cf1167d5c1abf3bc42b2a1562bfa7937c05337e2.tar.bz2 linux-stable-cf1167d5c1abf3bc42b2a1562bfa7937c05337e2.zip |
Btrfs: fix kernel oops while reading compressed data
The kernel oops happens at
kernel BUG at fs/btrfs/extent_io.c:2104!
...
RIP: clean_io_failure+0x263/0x2a0 [btrfs]
It's showing that read-repair code is using an improper mirror index.
This is due to the fact that compression read's endio hasn't recorded
the failed mirror index in %cb->orig_bio.
With this, btrfs's read-repair can work properly on reading compressed
data.
Signed-off-by: Liu Bo <bo.li.liu@oracle.com>
Reported-by: Paul Jones <paul@pauljones.id.au>
Tested-by: Paul Jones <paul@pauljones.id.au>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs/compression.c')
-rw-r--r-- | fs/btrfs/compression.c | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index 883ecc58fd0d..c6aa53c4c102 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c @@ -107,6 +107,7 @@ static void end_compressed_bio_read(struct bio *bio) struct inode *inode; struct page *page; unsigned long index; + unsigned int mirror = btrfs_io_bio(bio)->mirror_num; int ret; if (bio->bi_status) @@ -118,6 +119,14 @@ static void end_compressed_bio_read(struct bio *bio) if (!refcount_dec_and_test(&cb->pending_bios)) goto out; + /* + * Record the correct mirror_num in cb->orig_bio so that + * read-repair can work properly. + */ + ASSERT(btrfs_io_bio(cb->orig_bio)); + btrfs_io_bio(cb->orig_bio)->mirror_num = mirror; + cb->mirror_num = mirror; + inode = cb->inode; ret = check_compressed_csum(BTRFS_I(inode), cb, (u64)bio->bi_iter.bi_sector << 9); |