aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Rientjes <rientjes@google.com>2009-09-21 20:04:31 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-22 10:17:47 -0400
commit4af5a2f770cc8575840ccb1514ec76ecb592985c (patch)
tree7af18234d7d171a946925e65e987fd51648be3aa
parent19da3dd157f8db6fe727ff268dab4791d55a6371 (diff)
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>
-rw-r--r--include/linux/flex_array.h1
-rw-r--r--lib/flex_array.c40
2 files changed, 41 insertions, 0 deletions
diff --git a/include/linux/flex_array.h b/include/linux/flex_array.h
index 3887b21f883f..f12401e485fe 100644
--- a/include/linux/flex_array.h
+++ b/include/linux/flex_array.h
@@ -46,5 +46,6 @@ int flex_array_put(struct flex_array *fa, unsigned int element_nr, void *src,
46 gfp_t flags); 46 gfp_t flags);
47int flex_array_clear(struct flex_array *fa, unsigned int element_nr); 47int flex_array_clear(struct flex_array *fa, unsigned int element_nr);
48void *flex_array_get(struct flex_array *fa, unsigned int element_nr); 48void *flex_array_get(struct flex_array *fa, unsigned int element_nr);
49int flex_array_shrink(struct flex_array *fa);
49 50
50#endif /* _FLEX_ARRAY_H */ 51#endif /* _FLEX_ARRAY_H */
diff --git a/lib/flex_array.c b/lib/flex_array.c
index e22d0e9776aa..1b03bb553410 100644
--- a/lib/flex_array.c
+++ b/lib/flex_array.c
@@ -291,3 +291,43 @@ void *flex_array_get(struct flex_array *fa, unsigned int element_nr)
291 } 291 }
292 return &part->elements[index_inside_part(fa, element_nr)]; 292 return &part->elements[index_inside_part(fa, element_nr)];
293} 293}
294
295static 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 */
313int 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}