Commit db42549d authored by Kent Overstreet's avatar Kent Overstreet

bcachefs: Add a better limit for maximum number of buckets

The bucket_gens array is a single array allocation (one byte per
bucket), and kernel allocations are still limited to INT_MAX.

Check this limit to avoid failing the bucket_gens array allocation.

Reported-by: syzbot+b29f436493184ea42e2b@syzkaller.appspotmail.com
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 18b4abce
...@@ -591,6 +591,12 @@ struct bch_member { ...@@ -591,6 +591,12 @@ struct bch_member {
__le64 btree_allocated_bitmap; __le64 btree_allocated_bitmap;
}; };
/*
* This limit comes from the bucket_gens array - it's a single allocation, and
* kernel allocation are limited to INT_MAX
*/
#define BCH_MEMBER_NBUCKETS_MAX (INT_MAX - 64)
#define BCH_MEMBER_V1_BYTES 56 #define BCH_MEMBER_V1_BYTES 56
LE64_BITMASK(BCH_MEMBER_STATE, struct bch_member, flags, 0, 4) LE64_BITMASK(BCH_MEMBER_STATE, struct bch_member, flags, 0, 4)
......
...@@ -175,6 +175,7 @@ ...@@ -175,6 +175,7 @@
x(EINVAL, block_size_too_small) \ x(EINVAL, block_size_too_small) \
x(EINVAL, bucket_size_too_small) \ x(EINVAL, bucket_size_too_small) \
x(EINVAL, device_size_too_small) \ x(EINVAL, device_size_too_small) \
x(EINVAL, device_size_too_big) \
x(EINVAL, device_not_a_member_of_filesystem) \ x(EINVAL, device_not_a_member_of_filesystem) \
x(EINVAL, device_has_been_removed) \ x(EINVAL, device_has_been_removed) \
x(EINVAL, device_splitbrain) \ x(EINVAL, device_splitbrain) \
......
...@@ -124,9 +124,9 @@ static int validate_member(struct printbuf *err, ...@@ -124,9 +124,9 @@ static int validate_member(struct printbuf *err,
struct bch_sb *sb, struct bch_sb *sb,
int i) int i)
{ {
if (le64_to_cpu(m.nbuckets) > LONG_MAX) { if (le64_to_cpu(m.nbuckets) > BCH_MEMBER_NBUCKETS_MAX) {
prt_printf(err, "device %u: too many buckets (got %llu, max %lu)", prt_printf(err, "device %u: too many buckets (got %llu, max %u)",
i, le64_to_cpu(m.nbuckets), LONG_MAX); i, le64_to_cpu(m.nbuckets), BCH_MEMBER_NBUCKETS_MAX);
return -BCH_ERR_invalid_sb_members; return -BCH_ERR_invalid_sb_members;
} }
......
...@@ -1959,6 +1959,13 @@ int bch2_dev_resize(struct bch_fs *c, struct bch_dev *ca, u64 nbuckets) ...@@ -1959,6 +1959,13 @@ int bch2_dev_resize(struct bch_fs *c, struct bch_dev *ca, u64 nbuckets)
goto err; goto err;
} }
if (nbuckets > BCH_MEMBER_NBUCKETS_MAX) {
bch_err(ca, "New device size too big (%llu greater than max %u)",
nbuckets, BCH_MEMBER_NBUCKETS_MAX);
ret = -BCH_ERR_device_size_too_big;
goto err;
}
if (bch2_dev_is_online(ca) && if (bch2_dev_is_online(ca) &&
get_capacity(ca->disk_sb.bdev->bd_disk) < get_capacity(ca->disk_sb.bdev->bd_disk) <
ca->mi.bucket_size * nbuckets) { ca->mi.bucket_size * nbuckets) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment