afs: use find_get_pages_range_tag()
[sfrench/cifs-2.6.git] / 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 */