diff options
Diffstat (limited to 'lib/flex_array.c')
-rw-r--r-- | lib/flex_array.c | 48 |
1 files changed, 37 insertions, 11 deletions
diff --git a/lib/flex_array.c b/lib/flex_array.c index c0ea40ba2082..cab7621f98aa 100644 --- a/lib/flex_array.c +++ b/lib/flex_array.c | |||
@@ -88,8 +88,11 @@ struct flex_array *flex_array_alloc(int element_size, unsigned int total, | |||
88 | gfp_t flags) | 88 | gfp_t flags) |
89 | { | 89 | { |
90 | struct flex_array *ret; | 90 | struct flex_array *ret; |
91 | int max_size = FLEX_ARRAY_NR_BASE_PTRS * | 91 | int max_size = 0; |
92 | FLEX_ARRAY_ELEMENTS_PER_PART(element_size); | 92 | |
93 | if (element_size) | ||
94 | max_size = FLEX_ARRAY_NR_BASE_PTRS * | ||
95 | FLEX_ARRAY_ELEMENTS_PER_PART(element_size); | ||
93 | 96 | ||
94 | /* max_size will end up 0 if element_size > PAGE_SIZE */ | 97 | /* max_size will end up 0 if element_size > PAGE_SIZE */ |
95 | if (total > max_size) | 98 | if (total > max_size) |
@@ -183,15 +186,18 @@ __fa_get_part(struct flex_array *fa, int part_nr, gfp_t flags) | |||
183 | int flex_array_put(struct flex_array *fa, unsigned int element_nr, void *src, | 186 | int flex_array_put(struct flex_array *fa, unsigned int element_nr, void *src, |
184 | gfp_t flags) | 187 | gfp_t flags) |
185 | { | 188 | { |
186 | int part_nr = fa_element_to_part_nr(fa, element_nr); | 189 | int part_nr; |
187 | struct flex_array_part *part; | 190 | struct flex_array_part *part; |
188 | void *dst; | 191 | void *dst; |
189 | 192 | ||
190 | if (element_nr >= fa->total_nr_elements) | 193 | if (element_nr >= fa->total_nr_elements) |
191 | return -ENOSPC; | 194 | return -ENOSPC; |
195 | if (!fa->element_size) | ||
196 | return 0; | ||
192 | if (elements_fit_in_base(fa)) | 197 | if (elements_fit_in_base(fa)) |
193 | part = (struct flex_array_part *)&fa->parts[0]; | 198 | part = (struct flex_array_part *)&fa->parts[0]; |
194 | else { | 199 | else { |
200 | part_nr = fa_element_to_part_nr(fa, element_nr); | ||
195 | part = __fa_get_part(fa, part_nr, flags); | 201 | part = __fa_get_part(fa, part_nr, flags); |
196 | if (!part) | 202 | if (!part) |
197 | return -ENOMEM; | 203 | return -ENOMEM; |
@@ -211,15 +217,18 @@ EXPORT_SYMBOL(flex_array_put); | |||
211 | */ | 217 | */ |
212 | int flex_array_clear(struct flex_array *fa, unsigned int element_nr) | 218 | int flex_array_clear(struct flex_array *fa, unsigned int element_nr) |
213 | { | 219 | { |
214 | int part_nr = fa_element_to_part_nr(fa, element_nr); | 220 | int part_nr; |
215 | struct flex_array_part *part; | 221 | struct flex_array_part *part; |
216 | void *dst; | 222 | void *dst; |
217 | 223 | ||
218 | if (element_nr >= fa->total_nr_elements) | 224 | if (element_nr >= fa->total_nr_elements) |
219 | return -ENOSPC; | 225 | return -ENOSPC; |
226 | if (!fa->element_size) | ||
227 | return 0; | ||
220 | if (elements_fit_in_base(fa)) | 228 | if (elements_fit_in_base(fa)) |
221 | part = (struct flex_array_part *)&fa->parts[0]; | 229 | part = (struct flex_array_part *)&fa->parts[0]; |
222 | else { | 230 | else { |
231 | part_nr = fa_element_to_part_nr(fa, element_nr); | ||
223 | part = fa->parts[part_nr]; | 232 | part = fa->parts[part_nr]; |
224 | if (!part) | 233 | if (!part) |
225 | return -EINVAL; | 234 | return -EINVAL; |
@@ -232,10 +241,10 @@ EXPORT_SYMBOL(flex_array_clear); | |||
232 | 241 | ||
233 | /** | 242 | /** |
234 | * flex_array_prealloc - guarantee that array space exists | 243 | * flex_array_prealloc - guarantee that array space exists |
235 | * @fa: the flex array for which to preallocate parts | 244 | * @fa: the flex array for which to preallocate parts |
236 | * @start: index of first array element for which space is allocated | 245 | * @start: index of first array element for which space is allocated |
237 | * @end: index of last (inclusive) element for which space is allocated | 246 | * @nr_elements: number of elements for which space is allocated |
238 | * @flags: page allocation flags | 247 | * @flags: page allocation flags |
239 | * | 248 | * |
240 | * This will guarantee that no future calls to flex_array_put() | 249 | * This will guarantee that no future calls to flex_array_put() |
241 | * will allocate memory. It can be used if you are expecting to | 250 | * will allocate memory. It can be used if you are expecting to |
@@ -245,15 +254,27 @@ EXPORT_SYMBOL(flex_array_clear); | |||
245 | * Locking must be provided by the caller. | 254 | * Locking must be provided by the caller. |
246 | */ | 255 | */ |
247 | int flex_array_prealloc(struct flex_array *fa, unsigned int start, | 256 | int flex_array_prealloc(struct flex_array *fa, unsigned int start, |
248 | unsigned int end, gfp_t flags) | 257 | unsigned int nr_elements, gfp_t flags) |
249 | { | 258 | { |
250 | int start_part; | 259 | int start_part; |
251 | int end_part; | 260 | int end_part; |
252 | int part_nr; | 261 | int part_nr; |
262 | unsigned int end; | ||
253 | struct flex_array_part *part; | 263 | struct flex_array_part *part; |
254 | 264 | ||
255 | if (start >= fa->total_nr_elements || end >= fa->total_nr_elements) | 265 | if (!start && !nr_elements) |
266 | return 0; | ||
267 | if (start >= fa->total_nr_elements) | ||
268 | return -ENOSPC; | ||
269 | if (!nr_elements) | ||
270 | return 0; | ||
271 | |||
272 | end = start + nr_elements - 1; | ||
273 | |||
274 | if (end >= fa->total_nr_elements) | ||
256 | return -ENOSPC; | 275 | return -ENOSPC; |
276 | if (!fa->element_size) | ||
277 | return 0; | ||
257 | if (elements_fit_in_base(fa)) | 278 | if (elements_fit_in_base(fa)) |
258 | return 0; | 279 | return 0; |
259 | start_part = fa_element_to_part_nr(fa, start); | 280 | start_part = fa_element_to_part_nr(fa, start); |
@@ -281,14 +302,17 @@ EXPORT_SYMBOL(flex_array_prealloc); | |||
281 | */ | 302 | */ |
282 | void *flex_array_get(struct flex_array *fa, unsigned int element_nr) | 303 | void *flex_array_get(struct flex_array *fa, unsigned int element_nr) |
283 | { | 304 | { |
284 | int part_nr = fa_element_to_part_nr(fa, element_nr); | 305 | int part_nr; |
285 | struct flex_array_part *part; | 306 | struct flex_array_part *part; |
286 | 307 | ||
308 | if (!fa->element_size) | ||
309 | return NULL; | ||
287 | if (element_nr >= fa->total_nr_elements) | 310 | if (element_nr >= fa->total_nr_elements) |
288 | return NULL; | 311 | return NULL; |
289 | if (elements_fit_in_base(fa)) | 312 | if (elements_fit_in_base(fa)) |
290 | part = (struct flex_array_part *)&fa->parts[0]; | 313 | part = (struct flex_array_part *)&fa->parts[0]; |
291 | else { | 314 | else { |
315 | part_nr = fa_element_to_part_nr(fa, element_nr); | ||
292 | part = fa->parts[part_nr]; | 316 | part = fa->parts[part_nr]; |
293 | if (!part) | 317 | if (!part) |
294 | return NULL; | 318 | return NULL; |
@@ -343,6 +367,8 @@ int flex_array_shrink(struct flex_array *fa) | |||
343 | int part_nr; | 367 | int part_nr; |
344 | int ret = 0; | 368 | int ret = 0; |
345 | 369 | ||
370 | if (!fa->total_nr_elements || !fa->element_size) | ||
371 | return 0; | ||
346 | if (elements_fit_in_base(fa)) | 372 | if (elements_fit_in_base(fa)) |
347 | return ret; | 373 | return ret; |
348 | for (part_nr = 0; part_nr < FLEX_ARRAY_NR_BASE_PTRS; part_nr++) { | 374 | for (part_nr = 0; part_nr < FLEX_ARRAY_NR_BASE_PTRS; part_nr++) { |