summaryrefslogtreecommitdiff
path: root/fs/btrfs/compression.c
diff options
context:
space:
mode:
authorLiu Bo <bo.li.liu@oracle.com>2017-09-21 02:50:18 +0300
committerDavid Sterba <dsterba@suse.com>2017-09-26 15:53:23 +0300
commitcf1167d5c1abf3bc42b2a1562bfa7937c05337e2 (patch)
treea8e2a5e0fc58793ef9ce24ecd19834a3756c1e17 /fs/btrfs/compression.c
parentbd7d63c2ceaf737eeb21630a2b62fc5fe34dba29 (diff)
downloadlinux-cf1167d5c1abf3bc42b2a1562bfa7937c05337e2.tar.xz
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.c9
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);