| From a8749a35c39903120ec421ef2525acc8e0daa55c Mon Sep 17 00:00:00 2001 |
| From: Paolo Bonzini <pbonzini@redhat.com> |
| Date: Tue, 8 Mar 2022 04:47:22 -0500 |
| Subject: mm: vmalloc: introduce array allocation functions |
| |
| From: Paolo Bonzini <pbonzini@redhat.com> |
| |
| commit a8749a35c39903120ec421ef2525acc8e0daa55c upstream. |
| |
| Linux has dozens of occurrences of vmalloc(array_size()) and |
| vzalloc(array_size()). Allow to simplify the code by providing |
| vmalloc_array and vcalloc, as well as the underscored variants that let |
| the caller specify the GFP flags. |
| |
| Acked-by: Michal Hocko <mhocko@suse.com> |
| Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> |
| Signed-off-by: Alexander Ofitserov <oficerovas@altlinux.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| include/linux/vmalloc.h | 5 ++++ |
| mm/util.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ |
| 2 files changed, 55 insertions(+) |
| |
| --- a/include/linux/vmalloc.h |
| +++ b/include/linux/vmalloc.h |
| @@ -112,6 +112,11 @@ extern void *__vmalloc_node_range(unsign |
| void *__vmalloc_node(unsigned long size, unsigned long align, gfp_t gfp_mask, |
| int node, const void *caller); |
| |
| +extern void *__vmalloc_array(size_t n, size_t size, gfp_t flags); |
| +extern void *vmalloc_array(size_t n, size_t size); |
| +extern void *__vcalloc(size_t n, size_t size, gfp_t flags); |
| +extern void *vcalloc(size_t n, size_t size); |
| + |
| extern void vfree(const void *addr); |
| extern void vfree_atomic(const void *addr); |
| |
| --- a/mm/util.c |
| +++ b/mm/util.c |
| @@ -686,6 +686,56 @@ static inline void *__page_rmapping(stru |
| return (void *)mapping; |
| } |
| |
| +/** |
| + * __vmalloc_array - allocate memory for a virtually contiguous array. |
| + * @n: number of elements. |
| + * @size: element size. |
| + * @flags: the type of memory to allocate (see kmalloc). |
| + */ |
| +void *__vmalloc_array(size_t n, size_t size, gfp_t flags) |
| +{ |
| + size_t bytes; |
| + |
| + if (unlikely(check_mul_overflow(n, size, &bytes))) |
| + return NULL; |
| + return __vmalloc(bytes, flags); |
| +} |
| +EXPORT_SYMBOL(__vmalloc_array); |
| + |
| +/** |
| + * vmalloc_array - allocate memory for a virtually contiguous array. |
| + * @n: number of elements. |
| + * @size: element size. |
| + */ |
| +void *vmalloc_array(size_t n, size_t size) |
| +{ |
| + return __vmalloc_array(n, size, GFP_KERNEL); |
| +} |
| +EXPORT_SYMBOL(vmalloc_array); |
| + |
| +/** |
| + * __vcalloc - allocate and zero memory for a virtually contiguous array. |
| + * @n: number of elements. |
| + * @size: element size. |
| + * @flags: the type of memory to allocate (see kmalloc). |
| + */ |
| +void *__vcalloc(size_t n, size_t size, gfp_t flags) |
| +{ |
| + return __vmalloc_array(n, size, flags | __GFP_ZERO); |
| +} |
| +EXPORT_SYMBOL(__vcalloc); |
| + |
| +/** |
| + * vcalloc - allocate and zero memory for a virtually contiguous array. |
| + * @n: number of elements. |
| + * @size: element size. |
| + */ |
| +void *vcalloc(size_t n, size_t size) |
| +{ |
| + return __vmalloc_array(n, size, GFP_KERNEL | __GFP_ZERO); |
| +} |
| +EXPORT_SYMBOL(vcalloc); |
| + |
| /* Neutral page->mapping pointer to address_space or anon_vma or other */ |
| void *page_rmapping(struct page *page) |
| { |