aboutsummaryrefslogtreecommitdiffstats
path: root/mm/slab.c
diff options
context:
space:
mode:
authorDavid Rientjes <rientjes@google.com>2016-12-12 19:41:44 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-12-12 21:55:07 -0500
commitbf00bd3458041c4643a13d80fb349d29cb66eb63 (patch)
tree743f4b6e25be9e4f5fbfb4d4c3472cd83b299cad /mm/slab.c
parentf728b0a5d72ae99c446f933912914a61254c03b6 (diff)
mm, slab: maintain total slab count instead of active count
Rather than tracking the number of active slabs for each node, track the total number of slabs. This is a minor improvement that avoids active slab tracking when a slab goes from free to partial or partial to free. For slab debugging, this also removes an explicit free count since it can easily be inferred by the difference in number of total objects and number of active objects. Link: http://lkml.kernel.org/r/alpine.DEB.2.10.1612042020110.115755@chino.kir.corp.google.com Signed-off-by: David Rientjes <rientjes@google.com> Suggested-by: Joonsoo Kim <iamjoonsoo.kim@lge.com> Cc: Greg Thelen <gthelen@google.com> Cc: Aruna Ramakrishna <aruna.ramakrishna@oracle.com> Cc: Christoph Lameter <cl@linux.com> Cc: Pekka Enberg <penberg@kernel.org> 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.c70
1 files changed, 29 insertions, 41 deletions
diff --git a/mm/slab.c b/mm/slab.c
index e06da6ceaf73..87b29e76cafd 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -227,7 +227,7 @@ static void kmem_cache_node_init(struct kmem_cache_node *parent)
227 INIT_LIST_HEAD(&parent->slabs_full); 227 INIT_LIST_HEAD(&parent->slabs_full);
228 INIT_LIST_HEAD(&parent->slabs_partial); 228 INIT_LIST_HEAD(&parent->slabs_partial);
229 INIT_LIST_HEAD(&parent->slabs_free); 229 INIT_LIST_HEAD(&parent->slabs_free);
230 parent->active_slabs = 0; 230 parent->total_slabs = 0;
231 parent->free_slabs = 0; 231 parent->free_slabs = 0;
232 parent->shared = NULL; 232 parent->shared = NULL;
233 parent->alien = NULL; 233 parent->alien = NULL;
@@ -1381,20 +1381,18 @@ slab_out_of_memory(struct kmem_cache *cachep, gfp_t gfpflags, int nodeid)
1381 cachep->name, cachep->size, cachep->gfporder); 1381 cachep->name, cachep->size, cachep->gfporder);
1382 1382
1383 for_each_kmem_cache_node(cachep, node, n) { 1383 for_each_kmem_cache_node(cachep, node, n) {
1384 unsigned long active_objs = 0, free_objs = 0; 1384 unsigned long total_slabs, free_slabs, free_objs;
1385 unsigned long active_slabs, num_slabs;
1386 1385
1387 spin_lock_irqsave(&n->list_lock, flags); 1386 spin_lock_irqsave(&n->list_lock, flags);
1388 active_slabs = n->active_slabs; 1387 total_slabs = n->total_slabs;
1389 num_slabs = active_slabs + n->free_slabs; 1388 free_slabs = n->free_slabs;
1390 1389 free_objs = n->free_objects;
1391 active_objs += (num_slabs * cachep->num) - n->free_objects;
1392 free_objs += n->free_objects;
1393 spin_unlock_irqrestore(&n->list_lock, flags); 1390 spin_unlock_irqrestore(&n->list_lock, flags);
1394 1391
1395 pr_warn(" node %d: slabs: %ld/%ld, objs: %ld/%ld, free: %ld\n", 1392 pr_warn(" node %d: slabs: %ld/%ld, objs: %ld/%ld\n",
1396 node, active_slabs, num_slabs, active_objs, 1393 node, total_slabs - free_slabs, total_slabs,
1397 num_slabs * cachep->num, free_objs); 1394 (total_slabs * cachep->num) - free_objs,
1395 total_slabs * cachep->num);
1398 } 1396 }
1399#endif 1397#endif
1400} 1398}
@@ -2307,6 +2305,7 @@ static int drain_freelist(struct kmem_cache *cache,
2307 page = list_entry(p, struct page, lru); 2305 page = list_entry(p, struct page, lru);
2308 list_del(&page->lru); 2306 list_del(&page->lru);
2309 n->free_slabs--; 2307 n->free_slabs--;
2308 n->total_slabs--;
2310 /* 2309 /*
2311 * Safe to drop the lock. The slab is no longer linked 2310 * Safe to drop the lock. The slab is no longer linked
2312 * to the cache. 2311 * to the cache.
@@ -2741,13 +2740,12 @@ static void cache_grow_end(struct kmem_cache *cachep, struct page *page)
2741 n = get_node(cachep, page_to_nid(page)); 2740 n = get_node(cachep, page_to_nid(page));
2742 2741
2743 spin_lock(&n->list_lock); 2742 spin_lock(&n->list_lock);
2743 n->total_slabs++;
2744 if (!page->active) { 2744 if (!page->active) {
2745 list_add_tail(&page->lru, &(n->slabs_free)); 2745 list_add_tail(&page->lru, &(n->slabs_free));
2746 n->free_slabs++; 2746 n->free_slabs++;
2747 } else { 2747 } else
2748 fixup_slab_list(cachep, n, page, &list); 2748 fixup_slab_list(cachep, n, page, &list);
2749 n->active_slabs++;
2750 }
2751 2749
2752 STATS_INC_GROWN(cachep); 2750 STATS_INC_GROWN(cachep);
2753 n->free_objects += cachep->num - page->active; 2751 n->free_objects += cachep->num - page->active;
@@ -2874,7 +2872,7 @@ static inline void fixup_slab_list(struct kmem_cache *cachep,
2874 2872
2875/* Try to find non-pfmemalloc slab if needed */ 2873/* Try to find non-pfmemalloc slab if needed */
2876static noinline struct page *get_valid_first_slab(struct kmem_cache_node *n, 2874static noinline struct page *get_valid_first_slab(struct kmem_cache_node *n,
2877 struct page *page, bool *page_is_free, bool pfmemalloc) 2875 struct page *page, bool pfmemalloc)
2878{ 2876{
2879 if (!page) 2877 if (!page)
2880 return NULL; 2878 return NULL;
@@ -2893,10 +2891,9 @@ static noinline struct page *get_valid_first_slab(struct kmem_cache_node *n,
2893 2891
2894 /* Move pfmemalloc slab to the end of list to speed up next search */ 2892 /* Move pfmemalloc slab to the end of list to speed up next search */
2895 list_del(&page->lru); 2893 list_del(&page->lru);
2896 if (*page_is_free) { 2894 if (!page->active) {
2897 WARN_ON(page->active);
2898 list_add_tail(&page->lru, &n->slabs_free); 2895 list_add_tail(&page->lru, &n->slabs_free);
2899 *page_is_free = false; 2896 n->free_slabs++;
2900 } else 2897 } else
2901 list_add_tail(&page->lru, &n->slabs_partial); 2898 list_add_tail(&page->lru, &n->slabs_partial);
2902 2899
@@ -2908,7 +2905,7 @@ static noinline struct page *get_valid_first_slab(struct kmem_cache_node *n,
2908 n->free_touched = 1; 2905 n->free_touched = 1;
2909 list_for_each_entry(page, &n->slabs_free, lru) { 2906 list_for_each_entry(page, &n->slabs_free, lru) {
2910 if (!PageSlabPfmemalloc(page)) { 2907 if (!PageSlabPfmemalloc(page)) {
2911 *page_is_free = true; 2908 n->free_slabs--;
2912 return page; 2909 return page;
2913 } 2910 }
2914 } 2911 }
@@ -2919,26 +2916,19 @@ static noinline struct page *get_valid_first_slab(struct kmem_cache_node *n,
2919static struct page *get_first_slab(struct kmem_cache_node *n, bool pfmemalloc) 2916static struct page *get_first_slab(struct kmem_cache_node *n, bool pfmemalloc)
2920{ 2917{
2921 struct page *page; 2918 struct page *page;
2922 bool page_is_free = false;
2923 2919
2924 assert_spin_locked(&n->list_lock); 2920 assert_spin_locked(&n->list_lock);
2925 page = list_first_entry_or_null(&n->slabs_partial, 2921 page = list_first_entry_or_null(&n->slabs_partial, struct page, lru);
2926 struct page, lru);
2927 if (!page) { 2922 if (!page) {
2928 n->free_touched = 1; 2923 n->free_touched = 1;
2929 page = list_first_entry_or_null(&n->slabs_free, 2924 page = list_first_entry_or_null(&n->slabs_free, struct page,
2930 struct page, lru); 2925 lru);
2931 if (page) 2926 if (page)
2932 page_is_free = true; 2927 n->free_slabs--;
2933 } 2928 }
2934 2929
2935 if (sk_memalloc_socks()) 2930 if (sk_memalloc_socks())
2936 page = get_valid_first_slab(n, page, &page_is_free, pfmemalloc); 2931 page = get_valid_first_slab(n, page, pfmemalloc);
2937
2938 if (page && page_is_free) {
2939 n->active_slabs++;
2940 n->free_slabs--;
2941 }
2942 2932
2943 return page; 2933 return page;
2944} 2934}
@@ -3441,7 +3431,6 @@ static void free_block(struct kmem_cache *cachep, void **objpp,
3441 if (page->active == 0) { 3431 if (page->active == 0) {
3442 list_add(&page->lru, &n->slabs_free); 3432 list_add(&page->lru, &n->slabs_free);
3443 n->free_slabs++; 3433 n->free_slabs++;
3444 n->active_slabs--;
3445 } else { 3434 } else {
3446 /* Unconditionally move a slab to the end of the 3435 /* Unconditionally move a slab to the end of the
3447 * partial list on free - maximum time for the 3436 * partial list on free - maximum time for the
@@ -3457,6 +3446,7 @@ static void free_block(struct kmem_cache *cachep, void **objpp,
3457 page = list_last_entry(&n->slabs_free, struct page, lru); 3446 page = list_last_entry(&n->slabs_free, struct page, lru);
3458 list_move(&page->lru, list); 3447 list_move(&page->lru, list);
3459 n->free_slabs--; 3448 n->free_slabs--;
3449 n->total_slabs--;
3460 } 3450 }
3461} 3451}
3462 3452
@@ -4109,8 +4099,8 @@ out:
4109void get_slabinfo(struct kmem_cache *cachep, struct slabinfo *sinfo) 4099void get_slabinfo(struct kmem_cache *cachep, struct slabinfo *sinfo)
4110{ 4100{
4111 unsigned long active_objs, num_objs, active_slabs; 4101 unsigned long active_objs, num_objs, active_slabs;
4112 unsigned long num_slabs = 0, free_objs = 0, shared_avail = 0; 4102 unsigned long total_slabs = 0, free_objs = 0, shared_avail = 0;
4113 unsigned long num_slabs_free = 0; 4103 unsigned long free_slabs = 0;
4114 int node; 4104 int node;
4115 struct kmem_cache_node *n; 4105 struct kmem_cache_node *n;
4116 4106
@@ -4118,9 +4108,8 @@ void get_slabinfo(struct kmem_cache *cachep, struct slabinfo *sinfo)
4118 check_irq_on(); 4108 check_irq_on();
4119 spin_lock_irq(&n->list_lock); 4109 spin_lock_irq(&n->list_lock);
4120 4110
4121 num_slabs += n->active_slabs + n->free_slabs; 4111 total_slabs += n->total_slabs;
4122 num_slabs_free += n->free_slabs; 4112 free_slabs += n->free_slabs;
4123
4124 free_objs += n->free_objects; 4113 free_objs += n->free_objects;
4125 4114
4126 if (n->shared) 4115 if (n->shared)
@@ -4128,15 +4117,14 @@ void get_slabinfo(struct kmem_cache *cachep, struct slabinfo *sinfo)
4128 4117
4129 spin_unlock_irq(&n->list_lock); 4118 spin_unlock_irq(&n->list_lock);
4130 } 4119 }
4131 num_objs = num_slabs * cachep->num; 4120 num_objs = total_slabs * cachep->num;
4132 active_slabs = num_slabs - num_slabs_free; 4121 active_slabs = total_slabs - free_slabs;
4133
4134 active_objs = num_objs - free_objs; 4122 active_objs = num_objs - free_objs;
4135 4123
4136 sinfo->active_objs = active_objs; 4124 sinfo->active_objs = active_objs;
4137 sinfo->num_objs = num_objs; 4125 sinfo->num_objs = num_objs;
4138 sinfo->active_slabs = active_slabs; 4126 sinfo->active_slabs = active_slabs;
4139 sinfo->num_slabs = num_slabs; 4127 sinfo->num_slabs = total_slabs;
4140 sinfo->shared_avail = shared_avail; 4128 sinfo->shared_avail = shared_avail;
4141 sinfo->limit = cachep->limit; 4129 sinfo->limit = cachep->limit;
4142 sinfo->batchcount = cachep->batchcount; 4130 sinfo->batchcount = cachep->batchcount;