* [PATCH] fs: btrfs: limit the mapped length to the original length
@ 2023-02-13 0:37 Qu Wenruo
2023-02-13 21:01 ` Andreas Schwab
2023-02-24 14:43 ` Tom Rini
0 siblings, 2 replies; 3+ messages in thread
From: Qu Wenruo @ 2023-02-13 0:37 UTC (permalink / raw)
To: u-boot; +Cc: linux-btrfs, Andreas Schwab
[BUG]
There is a bug report that btrfs driver caused hang during file read:
This breaks btrfs on the HiFive Unmatched.
=> pci enum
PCIE-0: Link up (Gen1-x8, Bus0)
=> nvme scan
=> load nvme 0:2 0x8c000000 /boot/dtb/sifive/hifive-unmatched-a00.dtb
[hangs]
[CAUSE]
The reporter provided some debug output:
read_extent_data: cur=615817216, orig_len=16384, cur_len=16384
read_extent_data: btrfs_map_block: cur_len=479944704; ret=0
read_extent_data: ret=0
read_extent_data: cur=615833600, orig_len=4096, cur_len=4096
read_extent_data: btrfs_map_block: cur_len=479928320; ret=0
Note the second and the last line, the @cur_len is 450+MiB, which is
almost a chunk size.
And inside __btrfs_map_block(), we limits the returned value to stripe
length, but that's depending on the chunk type:
if (map->type & (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1 |
BTRFS_BLOCK_GROUP_RAID1C3 | BTRFS_BLOCK_GROUP_RAID1C4 |
BTRFS_BLOCK_GROUP_RAID5 | BTRFS_BLOCK_GROUP_RAID6 |
BTRFS_BLOCK_GROUP_RAID10 |
BTRFS_BLOCK_GROUP_DUP)) {
/* we limit the length of each bio to what fits in a stripe */
*length = min_t(u64, ce->size - offset,
map->stripe_len - stripe_offset);
} else {
*length = ce->size - offset;
}
This means, if the chunk is SINGLE profile, then we don't limit the
returned length at all, and even for other profiles, we can still return
a length much larger than the requested one.
[FIX]
Properly clamp the returned length, preventing it from returning a much
larger range than expected.
Reported-by: Andreas Schwab <schwab@linux-m68k.org>
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
fs/btrfs/volumes.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 4aaaeab663f5..7d4095d9ca88 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -956,6 +956,7 @@ int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
struct btrfs_mapping_tree *map_tree = &fs_info->mapping_tree;
struct cache_extent *ce;
struct map_lookup *map;
+ u64 orig_len = *length;
u64 offset;
u64 stripe_offset;
u64 *raid_map = NULL;
@@ -1047,6 +1048,7 @@ again:
} else {
*length = ce->size - offset;
}
+ *length = min_t(u64, *length, orig_len);
if (!multi_ret)
goto out;
--
2.39.1
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [PATCH] fs: btrfs: limit the mapped length to the original length
2023-02-13 0:37 [PATCH] fs: btrfs: limit the mapped length to the original length Qu Wenruo
@ 2023-02-13 21:01 ` Andreas Schwab
2023-02-24 14:43 ` Tom Rini
1 sibling, 0 replies; 3+ messages in thread
From: Andreas Schwab @ 2023-02-13 21:01 UTC (permalink / raw)
To: Qu Wenruo; +Cc: u-boot, linux-btrfs
On Feb 13 2023, Qu Wenruo wrote:
> diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
> index 4aaaeab663f5..7d4095d9ca88 100644
> --- a/fs/btrfs/volumes.c
> +++ b/fs/btrfs/volumes.c
> @@ -956,6 +956,7 @@ int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
> struct btrfs_mapping_tree *map_tree = &fs_info->mapping_tree;
> struct cache_extent *ce;
> struct map_lookup *map;
> + u64 orig_len = *length;
> u64 offset;
> u64 stripe_offset;
> u64 *raid_map = NULL;
> @@ -1047,6 +1048,7 @@ again:
> } else {
> *length = ce->size - offset;
> }
> + *length = min_t(u64, *length, orig_len);
>
> if (!multi_ret)
> goto out;
I can confirm that this fixes the issue.
--
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510 2552 DF73 E780 A9DA AEC1
"And now for something completely different."
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH] fs: btrfs: limit the mapped length to the original length
2023-02-13 0:37 [PATCH] fs: btrfs: limit the mapped length to the original length Qu Wenruo
2023-02-13 21:01 ` Andreas Schwab
@ 2023-02-24 14:43 ` Tom Rini
1 sibling, 0 replies; 3+ messages in thread
From: Tom Rini @ 2023-02-24 14:43 UTC (permalink / raw)
To: Qu Wenruo; +Cc: u-boot, linux-btrfs, Andreas Schwab
[-- Attachment #1: Type: text/plain, Size: 1892 bytes --]
On Mon, Feb 13, 2023 at 08:37:59AM +0800, Qu Wenruo wrote:
> [BUG]
> There is a bug report that btrfs driver caused hang during file read:
>
> This breaks btrfs on the HiFive Unmatched.
>
> => pci enum
> PCIE-0: Link up (Gen1-x8, Bus0)
> => nvme scan
> => load nvme 0:2 0x8c000000 /boot/dtb/sifive/hifive-unmatched-a00.dtb
> [hangs]
>
> [CAUSE]
> The reporter provided some debug output:
>
> read_extent_data: cur=615817216, orig_len=16384, cur_len=16384
> read_extent_data: btrfs_map_block: cur_len=479944704; ret=0
> read_extent_data: ret=0
> read_extent_data: cur=615833600, orig_len=4096, cur_len=4096
> read_extent_data: btrfs_map_block: cur_len=479928320; ret=0
>
> Note the second and the last line, the @cur_len is 450+MiB, which is
> almost a chunk size.
>
> And inside __btrfs_map_block(), we limits the returned value to stripe
> length, but that's depending on the chunk type:
>
> if (map->type & (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1 |
> BTRFS_BLOCK_GROUP_RAID1C3 | BTRFS_BLOCK_GROUP_RAID1C4 |
> BTRFS_BLOCK_GROUP_RAID5 | BTRFS_BLOCK_GROUP_RAID6 |
> BTRFS_BLOCK_GROUP_RAID10 |
> BTRFS_BLOCK_GROUP_DUP)) {
> /* we limit the length of each bio to what fits in a stripe */
> *length = min_t(u64, ce->size - offset,
> map->stripe_len - stripe_offset);
> } else {
> *length = ce->size - offset;
> }
>
> This means, if the chunk is SINGLE profile, then we don't limit the
> returned length at all, and even for other profiles, we can still return
> a length much larger than the requested one.
>
> [FIX]
> Properly clamp the returned length, preventing it from returning a much
> larger range than expected.
>
> Reported-by: Andreas Schwab <schwab@linux-m68k.org>
> Signed-off-by: Qu Wenruo <wqu@suse.com>
Applied to u-boot/master, thanks!
--
Tom
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2023-02-24 14:43 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-02-13 0:37 [PATCH] fs: btrfs: limit the mapped length to the original length Qu Wenruo
2023-02-13 21:01 ` Andreas Schwab
2023-02-24 14:43 ` Tom Rini
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox