diff options
author | Eric Paris <eparis@redhat.com> | 2011-04-28 15:55:52 -0400 |
---|---|---|
committer | Eric Paris <eparis@redhat.com> | 2011-04-28 15:56:07 -0400 |
commit | a8d05c81fb238bbb18878ccfae7599ca79448dd3 (patch) | |
tree | b66baaf076be8f830cc07fb02ad22e2b3a9dd3e2 /lib/flex_array.c | |
parent | 150cdf6ec0ede8d9f102f1817212447727dcf08c (diff) |
flex_array: allow 0 length elements
flex_arrays are supposed to be a replacement for:
kmalloc(num_elements * sizeof(element))
If kmalloc is given 0 num_elements or a 0 size element it will happily return
ZERO_SIZE_PTR. Which looks like a valid allocation, but which will explode if
something actually try to use it. The current flex_array code will return an
equivalent result if num_elements is 0, but will fail to work if
sizeof(element) is 0. This patch allows allocation to work even for 0 size
elements. It will cause flex_arrays to explode though if they are used.
Imitating the kmalloc behavior.
Based-on-patch-by: Steffen Klassert <steffen.klassert@secunet.com>
Signed-off-by: Eric Paris <eparis@redhat.com>
Acked-by: Dave Hansen <dave@linux.vnet.ibm.com>
Diffstat (limited to 'lib/flex_array.c')
-rw-r--r-- | lib/flex_array.c | 26 |
1 files changed, 20 insertions, 6 deletions
diff --git a/lib/flex_array.c b/lib/flex_array.c index 854b57bd7d9d..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; |
@@ -264,6 +273,8 @@ int flex_array_prealloc(struct flex_array *fa, unsigned int start, | |||
264 | 273 | ||
265 | if (end >= fa->total_nr_elements) | 274 | if (end >= fa->total_nr_elements) |
266 | return -ENOSPC; | 275 | return -ENOSPC; |
276 | if (!fa->element_size) | ||
277 | return 0; | ||
267 | if (elements_fit_in_base(fa)) | 278 | if (elements_fit_in_base(fa)) |
268 | return 0; | 279 | return 0; |
269 | start_part = fa_element_to_part_nr(fa, start); | 280 | start_part = fa_element_to_part_nr(fa, start); |
@@ -291,14 +302,17 @@ EXPORT_SYMBOL(flex_array_prealloc); | |||
291 | */ | 302 | */ |
292 | 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) |
293 | { | 304 | { |
294 | int part_nr = fa_element_to_part_nr(fa, element_nr); | 305 | int part_nr; |
295 | struct flex_array_part *part; | 306 | struct flex_array_part *part; |
296 | 307 | ||
308 | if (!fa->element_size) | ||
309 | return NULL; | ||
297 | if (element_nr >= fa->total_nr_elements) | 310 | if (element_nr >= fa->total_nr_elements) |
298 | return NULL; | 311 | return NULL; |
299 | if (elements_fit_in_base(fa)) | 312 | if (elements_fit_in_base(fa)) |
300 | part = (struct flex_array_part *)&fa->parts[0]; | 313 | part = (struct flex_array_part *)&fa->parts[0]; |
301 | else { | 314 | else { |
315 | part_nr = fa_element_to_part_nr(fa, element_nr); | ||
302 | part = fa->parts[part_nr]; | 316 | part = fa->parts[part_nr]; |
303 | if (!part) | 317 | if (!part) |
304 | return NULL; | 318 | return NULL; |
@@ -353,7 +367,7 @@ int flex_array_shrink(struct flex_array *fa) | |||
353 | int part_nr; | 367 | int part_nr; |
354 | int ret = 0; | 368 | int ret = 0; |
355 | 369 | ||
356 | if (!fa->total_nr_elements) | 370 | if (!fa->total_nr_elements || !fa->element_size) |
357 | return 0; | 371 | return 0; |
358 | if (elements_fit_in_base(fa)) | 372 | if (elements_fit_in_base(fa)) |
359 | return ret; | 373 | return ret; |