| From 0fe8b2ff024aec861bac0aa495b13c94e728883c Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 8 Mar 2022 04:47:22 -0500 |
| Subject: mm: vmalloc: introduce array allocation functions |
| |
| From: Paolo Bonzini <pbonzini@redhat.com> |
| |
| [ Upstream commit a8749a35c39903120ec421ef2525acc8e0daa55c ] |
| |
| 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: Sasha Levin <sashal@kernel.org> |
| --- |
| include/linux/vmalloc.h | 5 +++++ |
| mm/util.c | 50 +++++++++++++++++++++++++++++++++++++++++ |
| 2 files changed, 55 insertions(+) |
| |
| diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h |
| index 4fe9e885bbfa..5535be1012a2 100644 |
| --- a/include/linux/vmalloc.h |
| +++ b/include/linux/vmalloc.h |
| @@ -159,6 +159,11 @@ void *__vmalloc_node(unsigned long size, unsigned long align, gfp_t gfp_mask, |
| int node, const void *caller); |
| void *vmalloc_no_huge(unsigned long size); |
| |
| +extern void *__vmalloc_array(size_t n, size_t size, gfp_t flags) __alloc_size(1, 2); |
| +extern void *vmalloc_array(size_t n, size_t size) __alloc_size(1, 2); |
| +extern void *__vcalloc(size_t n, size_t size, gfp_t flags) __alloc_size(1, 2); |
| +extern void *vcalloc(size_t n, size_t size) __alloc_size(1, 2); |
| + |
| extern void vfree(const void *addr); |
| extern void vfree_atomic(const void *addr); |
| |
| diff --git a/mm/util.c b/mm/util.c |
| index 3073de05c2bd..ea04979f131e 100644 |
| --- a/mm/util.c |
| +++ b/mm/util.c |
| @@ -698,6 +698,56 @@ static inline void *__page_rmapping(struct page *page) |
| 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) |
| { |
| -- |
| 2.35.1 |
| |