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.
Unified · Split
| @@ -88,8 +88,11 @@ struct flex_array *flex_array_alloc(int element_size, unsigned int total, · 87 unmodified lines | ||
| 88 | 88 | gfp_t flags) |
| 89 | 89 | { |
| 90 | 90 | struct flex_array *ret; |
| 91 | − int max_size = FLEX_ARRAY_NR_BASE_PTRS * | |
| 92 | − FLEX_ARRAY_ELEMENTS_PER_PART(element_size); | |
| 91 | + int max_size = 0; | |
| 92 | + | |
| 93 | + if (element_size) | |
| 94 | + max_size = FLEX_ARRAY_NR_BASE_PTRS * | |
| 95 | + FLEX_ARRAY_ELEMENTS_PER_PART(element_size); | |
| 93 | 96 | |
| 94 | 97 | /* max_size will end up 0 if element_size > PAGE_SIZE */ |
| 95 | 98 | if (total > max_size) |
| @@ -183,15 +186,18 @@ __fa_get_part(struct flex_array *fa, int part_nr, gfp_t flags) · 87 unmodified lines | ||
| 183 | 186 | int flex_array_put(struct flex_array *fa, unsigned int element_nr, void *src, |
| 184 | 187 | gfp_t flags) |
| 185 | 188 | { |
| 186 | − int part_nr = fa_element_to_part_nr(fa, element_nr); | |
| 189 | + int part_nr; | |
| 187 | 190 | struct flex_array_part *part; |
| 188 | 191 | void *dst; |
| 189 | 192 | |
| 190 | 193 | if (element_nr >= fa->total_nr_elements) |
| 191 | 194 | return -ENOSPC; |
| 195 | + if (!fa->element_size) | |
| 196 | + return 0; | |
| 192 | 197 | if (elements_fit_in_base(fa)) |
| 193 | 198 | part = (struct flex_array_part *)&fa->parts[0]; |
| 194 | 199 | else { |
| 200 | + part_nr = fa_element_to_part_nr(fa, element_nr); | |
| 195 | 201 | part = __fa_get_part(fa, part_nr, flags); |
| 196 | 202 | if (!part) |
| 197 | 203 | return -ENOMEM; |
| @@ -211,15 +217,18 @@ EXPORT_SYMBOL(flex_array_put); · 13 unmodified lines | ||
| 211 | 217 | */ |
| 212 | 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 | 221 | struct flex_array_part *part; |
| 216 | 222 | void *dst; |
| 217 | 223 | |
| 218 | 224 | if (element_nr >= fa->total_nr_elements) |
| 219 | 225 | return -ENOSPC; |
| 226 | + if (!fa->element_size) | |
| 227 | + return 0; | |
| 220 | 228 | if (elements_fit_in_base(fa)) |
| 221 | 229 | part = (struct flex_array_part *)&fa->parts[0]; |
| 222 | 230 | else { |
| 231 | + part_nr = fa_element_to_part_nr(fa, element_nr); | |
| 223 | 232 | part = fa->parts[part_nr]; |
| 224 | 233 | if (!part) |
| 225 | 234 | return -EINVAL; |
| @@ -264,6 +273,8 @@ int flex_array_prealloc(struct flex_array *fa, unsigned int start, · 38 unmodified lines | ||
| 264 | 273 | |
| 265 | 274 | if (end >= fa->total_nr_elements) |
| 266 | 275 | return -ENOSPC; |
| 276 | + if (!fa->element_size) | |
| 277 | + return 0; | |
| 267 | 278 | if (elements_fit_in_base(fa)) |
| 268 | 279 | return 0; |
| 269 | 280 | start_part = fa_element_to_part_nr(fa, start); |
| @@ -291,14 +302,17 @@ EXPORT_SYMBOL(flex_array_prealloc); · 21 unmodified lines | ||
| 291 | 302 | */ |
| 292 | 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 | 306 | struct flex_array_part *part; |
| 296 | 307 | |
| 308 | + if (!fa->element_size) | |
| 309 | + return NULL; | |
| 297 | 310 | if (element_nr >= fa->total_nr_elements) |
| 298 | 311 | return NULL; |
| 299 | 312 | if (elements_fit_in_base(fa)) |
| 300 | 313 | part = (struct flex_array_part *)&fa->parts[0]; |
| 301 | 314 | else { |
| 315 | + part_nr = fa_element_to_part_nr(fa, element_nr); | |
| 302 | 316 | part = fa->parts[part_nr]; |
| 303 | 317 | if (!part) |
| 304 | 318 | return NULL; |
| @@ -353,7 +367,7 @@ int flex_array_shrink(struct flex_array *fa) · 48 unmodified lines | ||
| 353 | 367 | int part_nr; |
| 354 | 368 | int ret = 0; |
| 355 | 369 | |
| 356 | − if (!fa->total_nr_elements) | |
| 370 | + if (!fa->total_nr_elements || !fa->element_size) | |
| 357 | 371 | return 0; |
| 358 | 372 | if (elements_fit_in_base(fa)) |
| 359 | 373 | return ret; |