Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Drop flex_arrays

All existing users have been converted to generic radix trees

Link: http://lkml.kernel.org/r/20181217131929.11727-8-kent.overstreet@gmail.com
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Acked-by: Dave Hansen <dave.hansen@intel.com>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Eric Paris <eparis@parisplace.org>
Cc: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Neil Horman <nhorman@tuxdriver.com>
Cc: Paul Moore <paul@paul-moore.com>
Cc: Pravin B Shelar <pshelar@ovn.org>
Cc: Shaohua Li <shli@kernel.org>
Cc: Stephen Smalley <sds@tycho.nsa.gov>
Cc: Vlad Yasevich <vyasevich@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Kent Overstreet and committed by
Linus Torvalds
586187d7 2075e50c

+1 -807
-130
Documentation/core-api/flexible-arrays.rst
··· 1 - 2 - =================================== 3 - Using flexible arrays in the kernel 4 - =================================== 5 - 6 - Large contiguous memory allocations can be unreliable in the Linux kernel. 7 - Kernel programmers will sometimes respond to this problem by allocating 8 - pages with :c:func:`vmalloc()`. This solution not ideal, though. On 32-bit 9 - systems, memory from vmalloc() must be mapped into a relatively small address 10 - space; it's easy to run out. On SMP systems, the page table changes required 11 - by vmalloc() allocations can require expensive cross-processor interrupts on 12 - all CPUs. And, on all systems, use of space in the vmalloc() range increases 13 - pressure on the translation lookaside buffer (TLB), reducing the performance 14 - of the system. 15 - 16 - In many cases, the need for memory from vmalloc() can be eliminated by piecing 17 - together an array from smaller parts; the flexible array library exists to make 18 - this task easier. 19 - 20 - A flexible array holds an arbitrary (within limits) number of fixed-sized 21 - objects, accessed via an integer index. Sparse arrays are handled 22 - reasonably well. Only single-page allocations are made, so memory 23 - allocation failures should be relatively rare. The down sides are that the 24 - arrays cannot be indexed directly, individual object size cannot exceed the 25 - system page size, and putting data into a flexible array requires a copy 26 - operation. It's also worth noting that flexible arrays do no internal 27 - locking at all; if concurrent access to an array is possible, then the 28 - caller must arrange for appropriate mutual exclusion. 29 - 30 - The creation of a flexible array is done with :c:func:`flex_array_alloc()`:: 31 - 32 - #include <linux/flex_array.h> 33 - 34 - struct flex_array *flex_array_alloc(int element_size, 35 - unsigned int total, 36 - gfp_t flags); 37 - 38 - The individual object size is provided by ``element_size``, while total is the 39 - maximum number of objects which can be stored in the array. The flags 40 - argument is passed directly to the internal memory allocation calls. With 41 - the current code, using flags to ask for high memory is likely to lead to 42 - notably unpleasant side effects. 43 - 44 - It is also possible to define flexible arrays at compile time with:: 45 - 46 - DEFINE_FLEX_ARRAY(name, element_size, total); 47 - 48 - This macro will result in a definition of an array with the given name; the 49 - element size and total will be checked for validity at compile time. 50 - 51 - Storing data into a flexible array is accomplished with a call to 52 - :c:func:`flex_array_put()`:: 53 - 54 - int flex_array_put(struct flex_array *array, unsigned int element_nr, 55 - void *src, gfp_t flags); 56 - 57 - This call will copy the data from src into the array, in the position 58 - indicated by ``element_nr`` (which must be less than the maximum specified when 59 - the array was created). If any memory allocations must be performed, flags 60 - will be used. The return value is zero on success, a negative error code 61 - otherwise. 62 - 63 - There might possibly be a need to store data into a flexible array while 64 - running in some sort of atomic context; in this situation, sleeping in the 65 - memory allocator would be a bad thing. That can be avoided by using 66 - ``GFP_ATOMIC`` for the flags value, but, often, there is a better way. The 67 - trick is to ensure that any needed memory allocations are done before 68 - entering atomic context, using :c:func:`flex_array_prealloc()`:: 69 - 70 - int flex_array_prealloc(struct flex_array *array, unsigned int start, 71 - unsigned int nr_elements, gfp_t flags); 72 - 73 - This function will ensure that memory for the elements indexed in the range 74 - defined by ``start`` and ``nr_elements`` has been allocated. Thereafter, a 75 - ``flex_array_put()`` call on an element in that range is guaranteed not to 76 - block. 77 - 78 - Getting data back out of the array is done with :c:func:`flex_array_get()`:: 79 - 80 - void *flex_array_get(struct flex_array *fa, unsigned int element_nr); 81 - 82 - The return value is a pointer to the data element, or NULL if that 83 - particular element has never been allocated. 84 - 85 - Note that it is possible to get back a valid pointer for an element which 86 - has never been stored in the array. Memory for array elements is allocated 87 - one page at a time; a single allocation could provide memory for several 88 - adjacent elements. Flexible array elements are normally initialized to the 89 - value ``FLEX_ARRAY_FREE`` (defined as 0x6c in <linux/poison.h>), so errors 90 - involving that number probably result from use of unstored array entries. 91 - Note that, if array elements are allocated with ``__GFP_ZERO``, they will be 92 - initialized to zero and this poisoning will not happen. 93 - 94 - Individual elements in the array can be cleared with 95 - :c:func:`flex_array_clear()`:: 96 - 97 - int flex_array_clear(struct flex_array *array, unsigned int element_nr); 98 - 99 - This function will set the given element to ``FLEX_ARRAY_FREE`` and return 100 - zero. If storage for the indicated element is not allocated for the array, 101 - ``flex_array_clear()`` will return ``-EINVAL`` instead. Note that clearing an 102 - element does not release the storage associated with it; to reduce the 103 - allocated size of an array, call :c:func:`flex_array_shrink()`:: 104 - 105 - int flex_array_shrink(struct flex_array *array); 106 - 107 - The return value will be the number of pages of memory actually freed. 108 - This function works by scanning the array for pages containing nothing but 109 - ``FLEX_ARRAY_FREE`` bytes, so (1) it can be expensive, and (2) it will not work 110 - if the array's pages are allocated with ``__GFP_ZERO``. 111 - 112 - It is possible to remove all elements of an array with a call to 113 - :c:func:`flex_array_free_parts()`:: 114 - 115 - void flex_array_free_parts(struct flex_array *array); 116 - 117 - This call frees all elements, but leaves the array itself in place. 118 - Freeing the entire array is done with :c:func:`flex_array_free()`:: 119 - 120 - void flex_array_free(struct flex_array *array); 121 - 122 - As of this writing, there are no users of flexible arrays in the mainline 123 - kernel. The functions described here are also not exported to modules; 124 - that will probably be fixed when somebody comes up with a need for it. 125 - 126 - 127 - Flexible array functions 128 - ------------------------ 129 - 130 - .. kernel-doc:: include/linux/flex_array.h
-123
Documentation/flexible-arrays.txt
··· 1 - =================================== 2 - Using flexible arrays in the kernel 3 - =================================== 4 - 5 - :Updated: Last updated for 2.6.32 6 - :Author: Jonathan Corbet <corbet@lwn.net> 7 - 8 - Large contiguous memory allocations can be unreliable in the Linux kernel. 9 - Kernel programmers will sometimes respond to this problem by allocating 10 - pages with vmalloc(). This solution not ideal, though. On 32-bit systems, 11 - memory from vmalloc() must be mapped into a relatively small address space; 12 - it's easy to run out. On SMP systems, the page table changes required by 13 - vmalloc() allocations can require expensive cross-processor interrupts on 14 - all CPUs. And, on all systems, use of space in the vmalloc() range 15 - increases pressure on the translation lookaside buffer (TLB), reducing the 16 - performance of the system. 17 - 18 - In many cases, the need for memory from vmalloc() can be eliminated by 19 - piecing together an array from smaller parts; the flexible array library 20 - exists to make this task easier. 21 - 22 - A flexible array holds an arbitrary (within limits) number of fixed-sized 23 - objects, accessed via an integer index. Sparse arrays are handled 24 - reasonably well. Only single-page allocations are made, so memory 25 - allocation failures should be relatively rare. The down sides are that the 26 - arrays cannot be indexed directly, individual object size cannot exceed the 27 - system page size, and putting data into a flexible array requires a copy 28 - operation. It's also worth noting that flexible arrays do no internal 29 - locking at all; if concurrent access to an array is possible, then the 30 - caller must arrange for appropriate mutual exclusion. 31 - 32 - The creation of a flexible array is done with:: 33 - 34 - #include <linux/flex_array.h> 35 - 36 - struct flex_array *flex_array_alloc(int element_size, 37 - unsigned int total, 38 - gfp_t flags); 39 - 40 - The individual object size is provided by element_size, while total is the 41 - maximum number of objects which can be stored in the array. The flags 42 - argument is passed directly to the internal memory allocation calls. With 43 - the current code, using flags to ask for high memory is likely to lead to 44 - notably unpleasant side effects. 45 - 46 - It is also possible to define flexible arrays at compile time with:: 47 - 48 - DEFINE_FLEX_ARRAY(name, element_size, total); 49 - 50 - This macro will result in a definition of an array with the given name; the 51 - element size and total will be checked for validity at compile time. 52 - 53 - Storing data into a flexible array is accomplished with a call to:: 54 - 55 - int flex_array_put(struct flex_array *array, unsigned int element_nr, 56 - void *src, gfp_t flags); 57 - 58 - This call will copy the data from src into the array, in the position 59 - indicated by element_nr (which must be less than the maximum specified when 60 - the array was created). If any memory allocations must be performed, flags 61 - will be used. The return value is zero on success, a negative error code 62 - otherwise. 63 - 64 - There might possibly be a need to store data into a flexible array while 65 - running in some sort of atomic context; in this situation, sleeping in the 66 - memory allocator would be a bad thing. That can be avoided by using 67 - GFP_ATOMIC for the flags value, but, often, there is a better way. The 68 - trick is to ensure that any needed memory allocations are done before 69 - entering atomic context, using:: 70 - 71 - int flex_array_prealloc(struct flex_array *array, unsigned int start, 72 - unsigned int nr_elements, gfp_t flags); 73 - 74 - This function will ensure that memory for the elements indexed in the range 75 - defined by start and nr_elements has been allocated. Thereafter, a 76 - flex_array_put() call on an element in that range is guaranteed not to 77 - block. 78 - 79 - Getting data back out of the array is done with:: 80 - 81 - void *flex_array_get(struct flex_array *fa, unsigned int element_nr); 82 - 83 - The return value is a pointer to the data element, or NULL if that 84 - particular element has never been allocated. 85 - 86 - Note that it is possible to get back a valid pointer for an element which 87 - has never been stored in the array. Memory for array elements is allocated 88 - one page at a time; a single allocation could provide memory for several 89 - adjacent elements. Flexible array elements are normally initialized to the 90 - value FLEX_ARRAY_FREE (defined as 0x6c in <linux/poison.h>), so errors 91 - involving that number probably result from use of unstored array entries. 92 - Note that, if array elements are allocated with __GFP_ZERO, they will be 93 - initialized to zero and this poisoning will not happen. 94 - 95 - Individual elements in the array can be cleared with:: 96 - 97 - int flex_array_clear(struct flex_array *array, unsigned int element_nr); 98 - 99 - This function will set the given element to FLEX_ARRAY_FREE and return 100 - zero. If storage for the indicated element is not allocated for the array, 101 - flex_array_clear() will return -EINVAL instead. Note that clearing an 102 - element does not release the storage associated with it; to reduce the 103 - allocated size of an array, call:: 104 - 105 - int flex_array_shrink(struct flex_array *array); 106 - 107 - The return value will be the number of pages of memory actually freed. 108 - This function works by scanning the array for pages containing nothing but 109 - FLEX_ARRAY_FREE bytes, so (1) it can be expensive, and (2) it will not work 110 - if the array's pages are allocated with __GFP_ZERO. 111 - 112 - It is possible to remove all elements of an array with a call to:: 113 - 114 - void flex_array_free_parts(struct flex_array *array); 115 - 116 - This call frees all elements, but leaves the array itself in place. 117 - Freeing the entire array is done with:: 118 - 119 - void flex_array_free(struct flex_array *array); 120 - 121 - As of this writing, there are no users of flexible arrays in the mainline 122 - kernel. The functions described here are also not exported to modules; 123 - that will probably be fixed when somebody comes up with a need for it.
-149
include/linux/flex_array.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - #ifndef _FLEX_ARRAY_H 3 - #define _FLEX_ARRAY_H 4 - 5 - #include <linux/types.h> 6 - #include <linux/reciprocal_div.h> 7 - #include <asm/page.h> 8 - 9 - #define FLEX_ARRAY_PART_SIZE PAGE_SIZE 10 - #define FLEX_ARRAY_BASE_SIZE PAGE_SIZE 11 - 12 - struct flex_array_part; 13 - 14 - /* 15 - * This is meant to replace cases where an array-like 16 - * structure has gotten too big to fit into kmalloc() 17 - * and the developer is getting tempted to use 18 - * vmalloc(). 19 - */ 20 - 21 - struct flex_array { 22 - union { 23 - struct { 24 - int element_size; 25 - int total_nr_elements; 26 - int elems_per_part; 27 - struct reciprocal_value reciprocal_elems; 28 - struct flex_array_part *parts[]; 29 - }; 30 - /* 31 - * This little trick makes sure that 32 - * sizeof(flex_array) == PAGE_SIZE 33 - */ 34 - char padding[FLEX_ARRAY_BASE_SIZE]; 35 - }; 36 - }; 37 - 38 - /* Number of bytes left in base struct flex_array, excluding metadata */ 39 - #define FLEX_ARRAY_BASE_BYTES_LEFT \ 40 - (FLEX_ARRAY_BASE_SIZE - offsetof(struct flex_array, parts)) 41 - 42 - /* Number of pointers in base to struct flex_array_part pages */ 43 - #define FLEX_ARRAY_NR_BASE_PTRS \ 44 - (FLEX_ARRAY_BASE_BYTES_LEFT / sizeof(struct flex_array_part *)) 45 - 46 - /* Number of elements of size that fit in struct flex_array_part */ 47 - #define FLEX_ARRAY_ELEMENTS_PER_PART(size) \ 48 - (FLEX_ARRAY_PART_SIZE / size) 49 - 50 - /* 51 - * Defines a statically allocated flex array and ensures its parameters are 52 - * valid. 53 - */ 54 - #define DEFINE_FLEX_ARRAY(__arrayname, __element_size, __total) \ 55 - struct flex_array __arrayname = { { { \ 56 - .element_size = (__element_size), \ 57 - .total_nr_elements = (__total), \ 58 - } } }; \ 59 - static inline void __arrayname##_invalid_parameter(void) \ 60 - { \ 61 - BUILD_BUG_ON((__total) > FLEX_ARRAY_NR_BASE_PTRS * \ 62 - FLEX_ARRAY_ELEMENTS_PER_PART(__element_size)); \ 63 - } 64 - 65 - /** 66 - * flex_array_alloc() - Creates a flexible array. 67 - * @element_size: individual object size. 68 - * @total: maximum number of objects which can be stored. 69 - * @flags: GFP flags 70 - * 71 - * Return: Returns an object of structure flex_array. 72 - */ 73 - struct flex_array *flex_array_alloc(int element_size, unsigned int total, 74 - gfp_t flags); 75 - 76 - /** 77 - * flex_array_prealloc() - Ensures that memory for the elements indexed in the 78 - * range defined by start and nr_elements has been allocated. 79 - * @fa: array to allocate memory to. 80 - * @start: start address 81 - * @nr_elements: number of elements to be allocated. 82 - * @flags: GFP flags 83 - * 84 - */ 85 - int flex_array_prealloc(struct flex_array *fa, unsigned int start, 86 - unsigned int nr_elements, gfp_t flags); 87 - 88 - /** 89 - * flex_array_free() - Removes all elements of a flexible array. 90 - * @fa: array to be freed. 91 - */ 92 - void flex_array_free(struct flex_array *fa); 93 - 94 - /** 95 - * flex_array_free_parts() - Removes all elements of a flexible array, but 96 - * leaves the array itself in place. 97 - * @fa: array to be emptied. 98 - */ 99 - void flex_array_free_parts(struct flex_array *fa); 100 - 101 - /** 102 - * flex_array_put() - Stores data into a flexible array. 103 - * @fa: array where element is to be stored. 104 - * @element_nr: position to copy, must be less than the maximum specified when 105 - * the array was created. 106 - * @src: data source to be copied into the array. 107 - * @flags: GFP flags 108 - * 109 - * Return: Returns zero on success, a negative error code otherwise. 110 - */ 111 - int flex_array_put(struct flex_array *fa, unsigned int element_nr, void *src, 112 - gfp_t flags); 113 - 114 - /** 115 - * flex_array_clear() - Clears an individual element in the array, sets the 116 - * given element to FLEX_ARRAY_FREE. 117 - * @element_nr: element position to clear. 118 - * @fa: array to which element to be cleared belongs. 119 - * 120 - * Return: Returns zero on success, -EINVAL otherwise. 121 - */ 122 - int flex_array_clear(struct flex_array *fa, unsigned int element_nr); 123 - 124 - /** 125 - * flex_array_get() - Retrieves data into a flexible array. 126 - * 127 - * @element_nr: Element position to retrieve data from. 128 - * @fa: array from which data is to be retrieved. 129 - * 130 - * Return: Returns a pointer to the data element, or NULL if that 131 - * particular element has never been allocated. 132 - */ 133 - void *flex_array_get(struct flex_array *fa, unsigned int element_nr); 134 - 135 - /** 136 - * flex_array_shrink() - Reduces the allocated size of an array. 137 - * @fa: array to shrink. 138 - * 139 - * Return: Returns number of pages of memory actually freed. 140 - * 141 - */ 142 - int flex_array_shrink(struct flex_array *fa); 143 - 144 - #define flex_array_put_ptr(fa, nr, src, gfp) \ 145 - flex_array_put(fa, nr, (void *)&(src), gfp) 146 - 147 - void *flex_array_get_ptr(struct flex_array *fa, unsigned int element_nr); 148 - 149 - #endif /* _FLEX_ARRAY_H */
-3
include/linux/poison.h
··· 83 83 #define MUTEX_DEBUG_FREE 0x22 84 84 #define MUTEX_POISON_WW_CTX ((void *) 0x500 + POISON_POINTER_DELTA) 85 85 86 - /********** lib/flex_array.c **********/ 87 - #define FLEX_ARRAY_FREE 0x6c /* for use-after-free poisoning */ 88 - 89 86 /********** security/ **********/ 90 87 #define KEY_DESTROY 0xbd 91 88
+1 -1
lib/Makefile
··· 35 35 36 36 obj-y += bcd.o div64.o sort.o parser.o debug_locks.o random32.o \ 37 37 bust_spinlocks.o kasprintf.o bitmap.o scatterlist.o \ 38 - gcd.o lcm.o list_sort.o uuid.o flex_array.o iov_iter.o clz_ctz.o \ 38 + gcd.o lcm.o list_sort.o uuid.o iov_iter.o clz_ctz.o \ 39 39 bsearch.o find_bit.o llist.o memweight.o kfifo.o \ 40 40 percpu-refcount.o rhashtable.o reciprocal_div.o \ 41 41 once.o refcount.o usercopy.o errseq.o bucket_locks.o \
-398
lib/flex_array.c
··· 1 - /* 2 - * Flexible array managed in PAGE_SIZE parts 3 - * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License as published by 6 - * the Free Software Foundation; either version 2 of the License, or 7 - * (at your option) any later version. 8 - * 9 - * This program is distributed in the hope that it will be useful, 10 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 - * GNU General Public License for more details. 13 - * 14 - * You should have received a copy of the GNU General Public License 15 - * along with this program; if not, write to the Free Software 16 - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 - * 18 - * Copyright IBM Corporation, 2009 19 - * 20 - * Author: Dave Hansen <dave@linux.vnet.ibm.com> 21 - */ 22 - 23 - #include <linux/flex_array.h> 24 - #include <linux/slab.h> 25 - #include <linux/stddef.h> 26 - #include <linux/export.h> 27 - #include <linux/reciprocal_div.h> 28 - 29 - struct flex_array_part { 30 - char elements[FLEX_ARRAY_PART_SIZE]; 31 - }; 32 - 33 - /* 34 - * If a user requests an allocation which is small 35 - * enough, we may simply use the space in the 36 - * flex_array->parts[] array to store the user 37 - * data. 38 - */ 39 - static inline int elements_fit_in_base(struct flex_array *fa) 40 - { 41 - int data_size = fa->element_size * fa->total_nr_elements; 42 - if (data_size <= FLEX_ARRAY_BASE_BYTES_LEFT) 43 - return 1; 44 - return 0; 45 - } 46 - 47 - /** 48 - * flex_array_alloc - allocate a new flexible array 49 - * @element_size: the size of individual elements in the array 50 - * @total: total number of elements that this should hold 51 - * @flags: page allocation flags to use for base array 52 - * 53 - * Note: all locking must be provided by the caller. 54 - * 55 - * @total is used to size internal structures. If the user ever 56 - * accesses any array indexes >=@total, it will produce errors. 57 - * 58 - * The maximum number of elements is defined as: the number of 59 - * elements that can be stored in a page times the number of 60 - * page pointers that we can fit in the base structure or (using 61 - * integer math): 62 - * 63 - * (PAGE_SIZE/element_size) * (PAGE_SIZE-8)/sizeof(void *) 64 - * 65 - * Here's a table showing example capacities. Note that the maximum 66 - * index that the get/put() functions is just nr_objects-1. This 67 - * basically means that you get 4MB of storage on 32-bit and 2MB on 68 - * 64-bit. 69 - * 70 - * 71 - * Element size | Objects | Objects | 72 - * PAGE_SIZE=4k | 32-bit | 64-bit | 73 - * ---------------------------------| 74 - * 1 bytes | 4177920 | 2088960 | 75 - * 2 bytes | 2088960 | 1044480 | 76 - * 3 bytes | 1392300 | 696150 | 77 - * 4 bytes | 1044480 | 522240 | 78 - * 32 bytes | 130560 | 65408 | 79 - * 33 bytes | 126480 | 63240 | 80 - * 2048 bytes | 2040 | 1020 | 81 - * 2049 bytes | 1020 | 510 | 82 - * void * | 1044480 | 261120 | 83 - * 84 - * Since 64-bit pointers are twice the size, we lose half the 85 - * capacity in the base structure. Also note that no effort is made 86 - * to efficiently pack objects across page boundaries. 87 - */ 88 - struct flex_array *flex_array_alloc(int element_size, unsigned int total, 89 - gfp_t flags) 90 - { 91 - struct flex_array *ret; 92 - int elems_per_part = 0; 93 - int max_size = 0; 94 - struct reciprocal_value reciprocal_elems = { 0 }; 95 - 96 - if (element_size) { 97 - elems_per_part = FLEX_ARRAY_ELEMENTS_PER_PART(element_size); 98 - reciprocal_elems = reciprocal_value(elems_per_part); 99 - max_size = FLEX_ARRAY_NR_BASE_PTRS * elems_per_part; 100 - } 101 - 102 - /* max_size will end up 0 if element_size > PAGE_SIZE */ 103 - if (total > max_size) 104 - return NULL; 105 - ret = kzalloc(sizeof(struct flex_array), flags); 106 - if (!ret) 107 - return NULL; 108 - ret->element_size = element_size; 109 - ret->total_nr_elements = total; 110 - ret->elems_per_part = elems_per_part; 111 - ret->reciprocal_elems = reciprocal_elems; 112 - if (elements_fit_in_base(ret) && !(flags & __GFP_ZERO)) 113 - memset(&ret->parts[0], FLEX_ARRAY_FREE, 114 - FLEX_ARRAY_BASE_BYTES_LEFT); 115 - return ret; 116 - } 117 - EXPORT_SYMBOL(flex_array_alloc); 118 - 119 - static int fa_element_to_part_nr(struct flex_array *fa, 120 - unsigned int element_nr) 121 - { 122 - /* 123 - * if element_size == 0 we don't get here, so we never touch 124 - * the zeroed fa->reciprocal_elems, which would yield invalid 125 - * results 126 - */ 127 - return reciprocal_divide(element_nr, fa->reciprocal_elems); 128 - } 129 - 130 - /** 131 - * flex_array_free_parts - just free the second-level pages 132 - * @fa: the flex array from which to free parts 133 - * 134 - * This is to be used in cases where the base 'struct flex_array' 135 - * has been statically allocated and should not be free. 136 - */ 137 - void flex_array_free_parts(struct flex_array *fa) 138 - { 139 - int part_nr; 140 - 141 - if (elements_fit_in_base(fa)) 142 - return; 143 - for (part_nr = 0; part_nr < FLEX_ARRAY_NR_BASE_PTRS; part_nr++) 144 - kfree(fa->parts[part_nr]); 145 - } 146 - EXPORT_SYMBOL(flex_array_free_parts); 147 - 148 - void flex_array_free(struct flex_array *fa) 149 - { 150 - flex_array_free_parts(fa); 151 - kfree(fa); 152 - } 153 - EXPORT_SYMBOL(flex_array_free); 154 - 155 - static unsigned int index_inside_part(struct flex_array *fa, 156 - unsigned int element_nr, 157 - unsigned int part_nr) 158 - { 159 - unsigned int part_offset; 160 - 161 - part_offset = element_nr - part_nr * fa->elems_per_part; 162 - return part_offset * fa->element_size; 163 - } 164 - 165 - static struct flex_array_part * 166 - __fa_get_part(struct flex_array *fa, int part_nr, gfp_t flags) 167 - { 168 - struct flex_array_part *part = fa->parts[part_nr]; 169 - if (!part) { 170 - part = kmalloc(sizeof(struct flex_array_part), flags); 171 - if (!part) 172 - return NULL; 173 - if (!(flags & __GFP_ZERO)) 174 - memset(part, FLEX_ARRAY_FREE, 175 - sizeof(struct flex_array_part)); 176 - fa->parts[part_nr] = part; 177 - } 178 - return part; 179 - } 180 - 181 - /** 182 - * flex_array_put - copy data into the array at @element_nr 183 - * @fa: the flex array to copy data into 184 - * @element_nr: index of the position in which to insert 185 - * the new element. 186 - * @src: address of data to copy into the array 187 - * @flags: page allocation flags to use for array expansion 188 - * 189 - * 190 - * Note that this *copies* the contents of @src into 191 - * the array. If you are trying to store an array of 192 - * pointers, make sure to pass in &ptr instead of ptr. 193 - * You may instead wish to use the flex_array_put_ptr() 194 - * helper function. 195 - * 196 - * Locking must be provided by the caller. 197 - */ 198 - int flex_array_put(struct flex_array *fa, unsigned int element_nr, void *src, 199 - gfp_t flags) 200 - { 201 - int part_nr = 0; 202 - struct flex_array_part *part; 203 - void *dst; 204 - 205 - if (element_nr >= fa->total_nr_elements) 206 - return -ENOSPC; 207 - if (!fa->element_size) 208 - return 0; 209 - if (elements_fit_in_base(fa)) 210 - part = (struct flex_array_part *)&fa->parts[0]; 211 - else { 212 - part_nr = fa_element_to_part_nr(fa, element_nr); 213 - part = __fa_get_part(fa, part_nr, flags); 214 - if (!part) 215 - return -ENOMEM; 216 - } 217 - dst = &part->elements[index_inside_part(fa, element_nr, part_nr)]; 218 - memcpy(dst, src, fa->element_size); 219 - return 0; 220 - } 221 - EXPORT_SYMBOL(flex_array_put); 222 - 223 - /** 224 - * flex_array_clear - clear element in array at @element_nr 225 - * @fa: the flex array of the element. 226 - * @element_nr: index of the position to clear. 227 - * 228 - * Locking must be provided by the caller. 229 - */ 230 - int flex_array_clear(struct flex_array *fa, unsigned int element_nr) 231 - { 232 - int part_nr = 0; 233 - struct flex_array_part *part; 234 - void *dst; 235 - 236 - if (element_nr >= fa->total_nr_elements) 237 - return -ENOSPC; 238 - if (!fa->element_size) 239 - return 0; 240 - if (elements_fit_in_base(fa)) 241 - part = (struct flex_array_part *)&fa->parts[0]; 242 - else { 243 - part_nr = fa_element_to_part_nr(fa, element_nr); 244 - part = fa->parts[part_nr]; 245 - if (!part) 246 - return -EINVAL; 247 - } 248 - dst = &part->elements[index_inside_part(fa, element_nr, part_nr)]; 249 - memset(dst, FLEX_ARRAY_FREE, fa->element_size); 250 - return 0; 251 - } 252 - EXPORT_SYMBOL(flex_array_clear); 253 - 254 - /** 255 - * flex_array_prealloc - guarantee that array space exists 256 - * @fa: the flex array for which to preallocate parts 257 - * @start: index of first array element for which space is allocated 258 - * @nr_elements: number of elements for which space is allocated 259 - * @flags: page allocation flags 260 - * 261 - * This will guarantee that no future calls to flex_array_put() 262 - * will allocate memory. It can be used if you are expecting to 263 - * be holding a lock or in some atomic context while writing 264 - * data into the array. 265 - * 266 - * Locking must be provided by the caller. 267 - */ 268 - int flex_array_prealloc(struct flex_array *fa, unsigned int start, 269 - unsigned int nr_elements, gfp_t flags) 270 - { 271 - int start_part; 272 - int end_part; 273 - int part_nr; 274 - unsigned int end; 275 - struct flex_array_part *part; 276 - 277 - if (!start && !nr_elements) 278 - return 0; 279 - if (start >= fa->total_nr_elements) 280 - return -ENOSPC; 281 - if (!nr_elements) 282 - return 0; 283 - 284 - end = start + nr_elements - 1; 285 - 286 - if (end >= fa->total_nr_elements) 287 - return -ENOSPC; 288 - if (!fa->element_size) 289 - return 0; 290 - if (elements_fit_in_base(fa)) 291 - return 0; 292 - start_part = fa_element_to_part_nr(fa, start); 293 - end_part = fa_element_to_part_nr(fa, end); 294 - for (part_nr = start_part; part_nr <= end_part; part_nr++) { 295 - part = __fa_get_part(fa, part_nr, flags); 296 - if (!part) 297 - return -ENOMEM; 298 - } 299 - return 0; 300 - } 301 - EXPORT_SYMBOL(flex_array_prealloc); 302 - 303 - /** 304 - * flex_array_get - pull data back out of the array 305 - * @fa: the flex array from which to extract data 306 - * @element_nr: index of the element to fetch from the array 307 - * 308 - * Returns a pointer to the data at index @element_nr. Note 309 - * that this is a copy of the data that was passed in. If you 310 - * are using this to store pointers, you'll get back &ptr. You 311 - * may instead wish to use the flex_array_get_ptr helper. 312 - * 313 - * Locking must be provided by the caller. 314 - */ 315 - void *flex_array_get(struct flex_array *fa, unsigned int element_nr) 316 - { 317 - int part_nr = 0; 318 - struct flex_array_part *part; 319 - 320 - if (!fa->element_size) 321 - return NULL; 322 - if (element_nr >= fa->total_nr_elements) 323 - return NULL; 324 - if (elements_fit_in_base(fa)) 325 - part = (struct flex_array_part *)&fa->parts[0]; 326 - else { 327 - part_nr = fa_element_to_part_nr(fa, element_nr); 328 - part = fa->parts[part_nr]; 329 - if (!part) 330 - return NULL; 331 - } 332 - return &part->elements[index_inside_part(fa, element_nr, part_nr)]; 333 - } 334 - EXPORT_SYMBOL(flex_array_get); 335 - 336 - /** 337 - * flex_array_get_ptr - pull a ptr back out of the array 338 - * @fa: the flex array from which to extract data 339 - * @element_nr: index of the element to fetch from the array 340 - * 341 - * Returns the pointer placed in the flex array at element_nr using 342 - * flex_array_put_ptr(). This function should not be called if the 343 - * element in question was not set using the _put_ptr() helper. 344 - */ 345 - void *flex_array_get_ptr(struct flex_array *fa, unsigned int element_nr) 346 - { 347 - void **tmp; 348 - 349 - tmp = flex_array_get(fa, element_nr); 350 - if (!tmp) 351 - return NULL; 352 - 353 - return *tmp; 354 - } 355 - EXPORT_SYMBOL(flex_array_get_ptr); 356 - 357 - static int part_is_free(struct flex_array_part *part) 358 - { 359 - int i; 360 - 361 - for (i = 0; i < sizeof(struct flex_array_part); i++) 362 - if (part->elements[i] != FLEX_ARRAY_FREE) 363 - return 0; 364 - return 1; 365 - } 366 - 367 - /** 368 - * flex_array_shrink - free unused second-level pages 369 - * @fa: the flex array to shrink 370 - * 371 - * Frees all second-level pages that consist solely of unused 372 - * elements. Returns the number of pages freed. 373 - * 374 - * Locking must be provided by the caller. 375 - */ 376 - int flex_array_shrink(struct flex_array *fa) 377 - { 378 - struct flex_array_part *part; 379 - int part_nr; 380 - int ret = 0; 381 - 382 - if (!fa->total_nr_elements || !fa->element_size) 383 - return 0; 384 - if (elements_fit_in_base(fa)) 385 - return ret; 386 - for (part_nr = 0; part_nr < FLEX_ARRAY_NR_BASE_PTRS; part_nr++) { 387 - part = fa->parts[part_nr]; 388 - if (!part) 389 - continue; 390 - if (part_is_free(part)) { 391 - fa->parts[part_nr] = NULL; 392 - kfree(part); 393 - ret++; 394 - } 395 - } 396 - return ret; 397 - } 398 - EXPORT_SYMBOL(flex_array_shrink);
-3
tools/include/linux/poison.h
··· 87 87 #define MUTEX_DEBUG_INIT 0x11 88 88 #define MUTEX_DEBUG_FREE 0x22 89 89 90 - /********** lib/flex_array.c **********/ 91 - #define FLEX_ARRAY_FREE 0x6c /* for use-after-free poisoning */ 92 - 93 90 /********** security/ **********/ 94 91 #define KEY_DESTROY 0xbd 95 92