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++) { |
