xref: /linux-6.15/fs/bcachefs/darray.c (revision f0d33020)
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