From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Qu Wenruo <wqu@suse.com>, Anand Jain <anand.jain@oracle.com>,
David Sterba <dsterba@suse.com>, Sasha Levin <sashal@kernel.org>,
linux-btrfs@vger.kernel.org
Subject: [PATCH AUTOSEL 5.13 172/219] btrfs: grab correct extent map for subpage compressed extent read
Date: Thu, 9 Sep 2021 07:45:48 -0400 [thread overview]
Message-ID: <20210909114635.143983-172-sashal@kernel.org> (raw)
In-Reply-To: <20210909114635.143983-1-sashal@kernel.org>
From: Qu Wenruo <wqu@suse.com>
[ Upstream commit 557023ea9f06baf2659b232b08b8e8711f7001a6 ]
[BUG]
When subpage compressed read write support is enabled, btrfs/038 always
fails with EIO.
A simplified script can easily trigger the problem:
mkfs.btrfs -f -s 4k $dev
mount $dev $mnt -o compress=lzo
xfs_io -f -c "truncate 118811" $mnt/foo
xfs_io -c "pwrite -S 0x0d -b 39987 92267 39987" $mnt/foo > /dev/null
sync
btrfs subvolume snapshot -r $mnt $mnt/mysnap1
xfs_io -c "pwrite -S 0x3e -b 80000 200000 80000" $mnt/foo > /dev/null
sync
xfs_io -c "pwrite -S 0xdc -b 10000 250000 10000" $mnt/foo > /dev/null
xfs_io -c "pwrite -S 0xff -b 10000 300000 10000" $mnt/foo > /dev/null
sync
btrfs subvolume snapshot -r $mnt $mnt/mysnap2
cat $mnt/mysnap2/foo
# Above cat will fail due to EIO
[CAUSE]
The problem is in btrfs_submit_compressed_read().
When it tries to grab the extent map of the read range, it uses the
following call:
em = lookup_extent_mapping(em_tree,
page_offset(bio_first_page_all(bio)),
fs_info->sectorsize);
The problem is in the page_offset(bio_first_page_all(bio)) part.
The offending inode has the following file extent layout
item 10 key (257 EXTENT_DATA 131072) itemoff 15639 itemsize 53
generation 8 type 1 (regular)
extent data disk byte 13680640 nr 4096
extent data offset 0 nr 4096 ram 4096
extent compression 0 (none)
item 11 key (257 EXTENT_DATA 135168) itemoff 15586 itemsize 53
generation 8 type 1 (regular)
extent data disk byte 0 nr 0
item 12 key (257 EXTENT_DATA 196608) itemoff 15533 itemsize 53
generation 8 type 1 (regular)
extent data disk byte 13676544 nr 4096
extent data offset 0 nr 53248 ram 86016
extent compression 2 (lzo)
And the bio passed in has the following parameters:
page_offset(bio_first_page_all(bio)) = 131072
bio_first_bvec_all(bio)->bv_offset = 65536
If we use page_offset(bio_first_page_all(bio) without adding bv_offset,
we will get an extent map for file offset 131072, not 196608.
This means we read uncompressed data from disk, and later decompression
will definitely fail.
[FIX]
Take bv_offset into consideration when trying to grab an extent map.
And add an ASSERT() to ensure we're really getting a compressed extent.
Thankfully this won't affect anything but subpage, thus we only need to
ensure this patch get merged before we enabled basic subpage support.
Reviewed-by: Anand Jain <anand.jain@oracle.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/btrfs/compression.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
index f69b8d332574..f25ea4764ea1 100644
--- a/fs/btrfs/compression.c
+++ b/fs/btrfs/compression.c
@@ -683,6 +683,7 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
struct page *page;
struct bio *comp_bio;
u64 cur_disk_byte = bio->bi_iter.bi_sector << 9;
+ u64 file_offset;
u64 em_len;
u64 em_start;
struct extent_map *em;
@@ -692,15 +693,17 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
em_tree = &BTRFS_I(inode)->extent_tree;
+ file_offset = bio_first_bvec_all(bio)->bv_offset +
+ page_offset(bio_first_page_all(bio));
+
/* we need the actual starting offset of this extent in the file */
read_lock(&em_tree->lock);
- em = lookup_extent_mapping(em_tree,
- page_offset(bio_first_page_all(bio)),
- fs_info->sectorsize);
+ em = lookup_extent_mapping(em_tree, file_offset, fs_info->sectorsize);
read_unlock(&em_tree->lock);
if (!em)
return BLK_STS_IOERR;
+ ASSERT(em->compress_type != BTRFS_COMPRESS_NONE);
compressed_len = em->block_len;
cb = kmalloc(compressed_bio_size(fs_info, compressed_len), GFP_NOFS);
if (!cb)
--
2.30.2
next prev parent reply other threads:[~2021-09-09 12:22 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20210909114635.143983-1-sashal@kernel.org>
2021-09-09 11:45 ` [PATCH AUTOSEL 5.13 169/219] btrfs: remove racy and unnecessary inode transaction update when using no-holes Sasha Levin
2021-09-09 11:45 ` [PATCH AUTOSEL 5.13 170/219] btrfs: reset this_bio_flag to avoid inheriting old flags Sasha Levin
2021-09-09 13:00 ` David Sterba
2021-09-09 11:45 ` [PATCH AUTOSEL 5.13 171/219] btrfs: subpage: check if there are compressed extents inside one page Sasha Levin
2021-09-09 11:58 ` David Sterba
2021-09-09 11:45 ` Sasha Levin [this message]
2021-09-09 11:58 ` [PATCH AUTOSEL 5.13 172/219] btrfs: grab correct extent map for subpage compressed extent read David Sterba
2021-09-09 11:45 ` [PATCH AUTOSEL 5.13 173/219] btrfs: subpage: fix race between prepare_pages() and btrfs_releasepage() Sasha Levin
2021-09-09 11:58 ` David Sterba
2021-09-09 11:45 ` [PATCH AUTOSEL 5.13 174/219] btrfs: subpage: fix false alert when relocating partial preallocated data extents Sasha Levin
2021-09-09 11:58 ` David Sterba
2021-09-09 11:45 ` [PATCH AUTOSEL 5.13 175/219] btrfs: tree-log: check btrfs_lookup_data_extent return value Sasha Levin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210909114635.143983-172-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=anand.jain@oracle.com \
--cc=dsterba@suse.com \
--cc=linux-btrfs@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=stable@vger.kernel.org \
--cc=wqu@suse.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox