summaryrefslogtreecommitdiffstats
path: root/mm/slab.c
diff options
context:
space:
mode:
authorJoonsoo Kim <iamjoonsoo.kim@lge.com>2016-05-19 20:10:17 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-05-19 22:12:14 -0400
commit6052b7880a95554993898f7cac075c2669f1dd7c (patch)
treefdb9ca36dff1135808c5ae05c0b2763a688bb084 /mm/slab.c
parentc3d332b6b2c11ddda9cce3e2f3135b68929d4b82 (diff)
mm/slab: don't keep free slabs if free_objects exceeds free_limit
Currently, determination to free a slab is done whenever each freed object is put into the slab. This has a following problem. Assume free_limit = 10 and nr_free = 9. Free happens as following sequence and nr_free changes as following. free(become a free slab) free(not become a free slab) nr_free: 9 -> 10 (at first free) -> 11 (at second free) If we try to check if we can free current slab or not on each object free, we can't free any slab in this situation because current slab isn't a free slab when nr_free exceed free_limit (at second free) even if there is a free slab. However, if we check it lastly, we can free 1 free slab. This problem would cause to keep too much memory in the slab subsystem. This patch try to fix it by checking number of free object after all free work is done. If there is free slab at that time, we can free slab as much as possible so we keep free slab as minimal. Signed-off-by: Joonsoo Kim <iamjoonsoo.kim@lge.com> Cc: Jesper Dangaard Brouer <brouer@redhat.com> Cc: Christoph Lameter <cl@linux.com> Cc: Pekka Enberg <penberg@kernel.org> Cc: David Rientjes <rientjes@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/slab.c')
-rw-r--r--mm/slab.c23
1 files changed, 14 insertions, 9 deletions
diff --git a/mm/slab.c b/mm/slab.c
index f1db679c2b5d..3f16475b7189 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -3296,6 +3296,9 @@ static void free_block(struct kmem_cache *cachep, void **objpp,
3296{ 3296{
3297 int i; 3297 int i;
3298 struct kmem_cache_node *n = get_node(cachep, node); 3298 struct kmem_cache_node *n = get_node(cachep, node);
3299 struct page *page;
3300
3301 n->free_objects += nr_objects;
3299 3302
3300 for (i = 0; i < nr_objects; i++) { 3303 for (i = 0; i < nr_objects; i++) {
3301 void *objp; 3304 void *objp;
@@ -3308,17 +3311,11 @@ static void free_block(struct kmem_cache *cachep, void **objpp,
3308 check_spinlock_acquired_node(cachep, node); 3311 check_spinlock_acquired_node(cachep, node);
3309 slab_put_obj(cachep, page, objp); 3312 slab_put_obj(cachep, page, objp);
3310 STATS_DEC_ACTIVE(cachep); 3313 STATS_DEC_ACTIVE(cachep);
3311 n->free_objects++;
3312 3314
3313 /* fixup slab chains */ 3315 /* fixup slab chains */
3314 if (page->active == 0) { 3316 if (page->active == 0)
3315 if (n->free_objects > n->free_limit) { 3317 list_add(&page->lru, &n->slabs_free);
3316 n->free_objects -= cachep->num; 3318 else {
3317 list_add_tail(&page->lru, list);
3318 } else {
3319 list_add(&page->lru, &n->slabs_free);
3320 }
3321 } else {
3322 /* Unconditionally move a slab to the end of the 3319 /* Unconditionally move a slab to the end of the
3323 * partial list on free - maximum time for the 3320 * partial list on free - maximum time for the
3324 * other objects to be freed, too. 3321 * other objects to be freed, too.
@@ -3326,6 +3323,14 @@ static void free_block(struct kmem_cache *cachep, void **objpp,
3326 list_add_tail(&page->lru, &n->slabs_partial); 3323 list_add_tail(&page->lru, &n->slabs_partial);
3327 } 3324 }
3328 } 3325 }
3326
3327 while (n->free_objects > n->free_limit && !list_empty(&n->slabs_free)) {
3328 n->free_objects -= cachep->num;
3329
3330 page = list_last_entry(&n->slabs_free, struct page, lru);
3331 list_del(&page->lru);
3332 list_add(&page->lru, list);
3333 }
3329} 3334}
3330 3335
3331static void cache_flusharray(struct kmem_cache *cachep, struct array_cache *ac) 3336static void cache_flusharray(struct kmem_cache *cachep, struct array_cache *ac)