173ab9e03SKent Overstreet // SPDX-License-Identifier: GPL-2.0
273ab9e03SKent Overstreet
373ab9e03SKent Overstreet #include <linux/log2.h>
473ab9e03SKent Overstreet #include <linux/slab.h>
5*f0d33020SKent Overstreet #include <linux/vmalloc.h>
673ab9e03SKent Overstreet #include "darray.h"
773ab9e03SKent Overstreet
__bch2_darray_resize_noprof(darray_char * d,size_t element_size,size_t new_size,gfp_t gfp)8a803fa55SKent Overstreet int __bch2_darray_resize_noprof(darray_char *d, size_t element_size, size_t new_size, gfp_t gfp)
973ab9e03SKent Overstreet {
1073ab9e03SKent Overstreet if (new_size > d->size) {
1173ab9e03SKent Overstreet new_size = roundup_pow_of_two(new_size);
1273ab9e03SKent Overstreet
13*f0d33020SKent Overstreet /*
14*f0d33020SKent Overstreet * This is a workaround: kvmalloc() doesn't support > INT_MAX
15*f0d33020SKent Overstreet * allocations, but vmalloc() does.
16*f0d33020SKent Overstreet * The limit needs to be lifted from kvmalloc, and when it does
17*f0d33020SKent Overstreet * we'll go back to just using that.
18*f0d33020SKent Overstreet */
19*f0d33020SKent Overstreet size_t bytes;
20*f0d33020SKent Overstreet if (unlikely(check_mul_overflow(new_size, element_size, &bytes)))
21*f0d33020SKent Overstreet return -ENOMEM;
22*f0d33020SKent Overstreet
23*f0d33020SKent Overstreet void *data = likely(bytes < INT_MAX)
24*f0d33020SKent Overstreet ? kvmalloc_noprof(bytes, gfp)
25*f0d33020SKent Overstreet : vmalloc_noprof(bytes);
2673ab9e03SKent Overstreet if (!data)
2773ab9e03SKent Overstreet return -ENOMEM;
2873ab9e03SKent Overstreet
292e118ba3STavian Barnes if (d->size)
30a58a6a58SKent Overstreet memcpy(data, d->data, d->size * element_size);
31099dc5c2SKent Overstreet if (d->data != d->preallocated)
32a58a6a58SKent Overstreet kvfree(d->data);
3373ab9e03SKent Overstreet d->data = data;
3473ab9e03SKent Overstreet d->size = new_size;
3573ab9e03SKent Overstreet }
3673ab9e03SKent Overstreet
3773ab9e03SKent Overstreet return 0;
3873ab9e03SKent Overstreet }
39