flex_array: add flex_array_shrink function
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. Signed-off-by: David Rientjes <rientjes@google.com> Cc: Dave Hansen <dave@linux.vnet.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
19da3dd157
commit
4af5a2f770
2 changed files with 41 additions and 0 deletions
|
@ -46,5 +46,6 @@ int flex_array_put(struct flex_array *fa, unsigned int element_nr, void *src,
|
|||
gfp_t flags);
|
||||
int flex_array_clear(struct flex_array *fa, unsigned int element_nr);
|
||||
void *flex_array_get(struct flex_array *fa, unsigned int element_nr);
|
||||
int flex_array_shrink(struct flex_array *fa);
|
||||
|
||||
#endif /* _FLEX_ARRAY_H */
|
||||
|
|
|
@ -291,3 +291,43 @@ void *flex_array_get(struct flex_array *fa, unsigned int element_nr)
|
|||
}
|
||||
return &part->elements[index_inside_part(fa, element_nr)];
|
||||
}
|
||||
|
||||
static int part_is_free(struct flex_array_part *part)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(struct flex_array_part); i++)
|
||||
if (part->elements[i] != FLEX_ARRAY_FREE)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* flex_array_shrink - free unused second-level pages
|
||||
*
|
||||
* Frees all second-level pages that consist solely of unused
|
||||
* elements. Returns the number of pages freed.
|
||||
*
|
||||
* Locking must be provided by the caller.
|
||||
*/
|
||||
int flex_array_shrink(struct flex_array *fa)
|
||||
{
|
||||
struct flex_array_part *part;
|
||||
int max_part = nr_base_part_ptrs();
|
||||
int part_nr;
|
||||
int ret = 0;
|
||||
|
||||
if (elements_fit_in_base(fa))
|
||||
return ret;
|
||||
for (part_nr = 0; part_nr < max_part; part_nr++) {
|
||||
part = fa->parts[part_nr];
|
||||
if (!part)
|
||||
continue;
|
||||
if (part_is_free(part)) {
|
||||
fa->parts[part_nr] = NULL;
|
||||
kfree(part);
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue