Skip to content

Commit 4b0c7a1

Browse files
committed
Merge tag 'for-6.4-rc7-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fix from David Sterba: "One more regression fix for an assertion failure that uncovered a nasty problem with stripe calculations. This is caused by a u32 overflow when there are enough devices. The fstests require 6 so this hasn't been caught, I was able to hit it with 8. The fix is minimal and only adds u64 casts, we'll clean that up later. I did various additional tests to be sure" * tag 'for-6.4-rc7-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: fix u32 overflows when left shifting stripe_nr
2 parents 99ec1ed + a7299a1 commit 4b0c7a1

File tree

1 file changed

+7
-5
lines changed

1 file changed

+7
-5
lines changed

fs/btrfs/volumes.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5975,12 +5975,12 @@ struct btrfs_discard_stripe *btrfs_map_discard(struct btrfs_fs_info *fs_info,
59755975
stripe_nr = offset >> BTRFS_STRIPE_LEN_SHIFT;
59765976

59775977
/* stripe_offset is the offset of this block in its stripe */
5978-
stripe_offset = offset - (stripe_nr << BTRFS_STRIPE_LEN_SHIFT);
5978+
stripe_offset = offset - ((u64)stripe_nr << BTRFS_STRIPE_LEN_SHIFT);
59795979

59805980
stripe_nr_end = round_up(offset + length, BTRFS_STRIPE_LEN) >>
59815981
BTRFS_STRIPE_LEN_SHIFT;
59825982
stripe_cnt = stripe_nr_end - stripe_nr;
5983-
stripe_end_offset = (stripe_nr_end << BTRFS_STRIPE_LEN_SHIFT) -
5983+
stripe_end_offset = ((u64)stripe_nr_end << BTRFS_STRIPE_LEN_SHIFT) -
59845984
(offset + length);
59855985
/*
59865986
* after this, stripe_nr is the number of stripes on this
@@ -6023,7 +6023,7 @@ struct btrfs_discard_stripe *btrfs_map_discard(struct btrfs_fs_info *fs_info,
60236023
for (i = 0; i < *num_stripes; i++) {
60246024
stripes[i].physical =
60256025
map->stripes[stripe_index].physical +
6026-
stripe_offset + (stripe_nr << BTRFS_STRIPE_LEN_SHIFT);
6026+
stripe_offset + ((u64)stripe_nr << BTRFS_STRIPE_LEN_SHIFT);
60276027
stripes[i].dev = map->stripes[stripe_index].dev;
60286028

60296029
if (map->type & (BTRFS_BLOCK_GROUP_RAID0 |
@@ -6196,9 +6196,11 @@ static u64 btrfs_max_io_len(struct map_lookup *map, enum btrfs_map_op op,
61966196
* not ensured to be power of 2.
61976197
*/
61986198
*full_stripe_start =
6199-
rounddown(*stripe_nr, nr_data_stripes(map)) <<
6199+
(u64)rounddown(*stripe_nr, nr_data_stripes(map)) <<
62006200
BTRFS_STRIPE_LEN_SHIFT;
62016201

6202+
ASSERT(*full_stripe_start + full_stripe_len > offset);
6203+
ASSERT(*full_stripe_start <= offset);
62026204
/*
62036205
* For writes to RAID56, allow to write a full stripe set, but
62046206
* no straddling of stripe sets.
@@ -6221,7 +6223,7 @@ static void set_io_stripe(struct btrfs_io_stripe *dst, const struct map_lookup *
62216223
{
62226224
dst->dev = map->stripes[stripe_index].dev;
62236225
dst->physical = map->stripes[stripe_index].physical +
6224-
stripe_offset + (stripe_nr << BTRFS_STRIPE_LEN_SHIFT);
6226+
stripe_offset + ((u64)stripe_nr << BTRFS_STRIPE_LEN_SHIFT);
62256227
}
62266228

62276229
int __btrfs_map_block(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,

0 commit comments

Comments
 (0)