Introduce function kmemdup_array(), that will copy `n` number of elements from a given array `src` to `dst`. On success, kmemdup_array() returns 0 and copy the elements from `src` to newly allocated array `dst`, it also stores number of elements copied from `src` array to `dst_count` parameter. On failure, this returns a negative integer value containing the error value. Signed-off-by: Kartik <kkartik@xxxxxxxxxx> --- include/linux/string.h | 2 ++ mm/util.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/include/linux/string.h b/include/linux/string.h index dbfc66400050..6245a7918b05 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -179,6 +179,8 @@ extern char *kstrndup(const char *s, size_t len, gfp_t gfp); extern void *kmemdup(const void *src, size_t len, gfp_t gfp) __realloc_size(2); extern void *kvmemdup(const void *src, size_t len, gfp_t gfp) __realloc_size(2); extern char *kmemdup_nul(const char *s, size_t len, gfp_t gfp); +extern int kmemdup_array(void **dst, size_t *dst_count, const void *src, size_t element_size, + size_t count, gfp_t gfp); extern char **argv_split(gfp_t gfp, const char *str, int *argcp); extern void argv_free(char **argv); diff --git a/mm/util.c b/mm/util.c index 6eddd891198e..a7c87a119be1 100644 --- a/mm/util.c +++ b/mm/util.c @@ -135,6 +135,40 @@ void *kmemdup(const void *src, size_t len, gfp_t gfp) } EXPORT_SYMBOL(kmemdup); +/** + * kmemdup_array - duplicate a given array. + * + * @dst: reference to the pointer to store address of duplicated array. + * @dst_count: number of elements in the duplicated array. + * @src: array to duplicate. + * @element_size: size of each element of array. + * @count: number of elements to duplicate from array. + * @gfp: GFP mask to use. + * + * Return: Returns 0 on success, on failure this returns a negative error value. + */ +int kmemdup_array(void **dst, size_t *dst_count, const void *src, size_t element_size, size_t count, + gfp_t gfp) +{ + size_t size; + + *dst_count = 0; + + if (!src || !element_size || !count) + return -EINVAL; + + size = size_mul(element_size, count); + + *dst = kmemdup(src, size, gfp); + if (*dst) + return -ENOMEM; + + *dst_count = size / element_size; + + return 0; +} +EXPORT_SYMBOL(kmemdup_array); + /** * kvmemdup - duplicate region of memory * -- 2.34.1