Add a new function to the flex_array API: int flex_array_shrink(struct flex_array *fa) This function will free all unused second-level pages. Since elements are now poisoned if they are not allocated with __GFP_ZERO, it's possible to identify parts that consist solely of unused elements. flex_array_shrink() returns the number of pages freed.
Showing the changes to lib/flex_array.c (1 of 2 files). Show all
Unified · Split
| @@ -291,3 +291,43 @@ void *flex_array_get(struct flex_array *fa, unsigned int element_nr) · 290 unmodified lines | ||
| 291 | 291 | } |
| 292 | 292 | return &part->elements[index_inside_part(fa, element_nr)]; |
| 293 | 293 | } |
| 294 | + | |
| 295 | +static int part_is_free(struct flex_array_part *part) | |
| 296 | +{ | |
| 297 | + int i; | |
| 298 | + | |
| 299 | + for (i = 0; i < sizeof(struct flex_array_part); i++) | |
| 300 | + if (part->elements[i] != FLEX_ARRAY_FREE) | |
| 301 | + return 0; | |
| 302 | + return 1; | |
| 303 | +} | |
| 304 | + | |
| 305 | +/** | |
| 306 | + * flex_array_shrink - free unused second-level pages | |
| 307 | + * | |
| 308 | + * Frees all second-level pages that consist solely of unused | |
| 309 | + * elements. Returns the number of pages freed. | |
| 310 | + * | |
| 311 | + * Locking must be provided by the caller. | |
| 312 | + */ | |
| 313 | +int flex_array_shrink(struct flex_array *fa) | |
| 314 | +{ | |
| 315 | + struct flex_array_part *part; | |
| 316 | + int max_part = nr_base_part_ptrs(); | |
| 317 | + int part_nr; | |
| 318 | + int ret = 0; | |
| 319 | + | |
| 320 | + if (elements_fit_in_base(fa)) | |
| 321 | + return ret; | |
| 322 | + for (part_nr = 0; part_nr < max_part; part_nr++) { | |
| 323 | + part = fa->parts[part_nr]; | |
| 324 | + if (!part) | |
| 325 | + continue; | |
| 326 | + if (part_is_free(part)) { | |
| 327 | + fa->parts[part_nr] = NULL; | |
| 328 | + kfree(part); | |
| 329 | + ret++; | |
| 330 | + } | |
| 331 | + } | |
| 332 | + return ret; | |
| 333 | +} | |