aboutsummaryrefslogtreecommitdiffstats
path: root/mm/slab_common.c
diff options
context:
space:
mode:
authorVlastimil Babka <vbabka@suse.cz>2018-10-26 18:05:34 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-10-26 19:26:31 -0400
commitcc252eae85e09552f9c1e7ac0c3227f835efdf2d (patch)
tree85c095ef367e82b35cccb72af5efc795429485bb /mm/slab_common.c
parent3b9aadf7278d16d7bed4d5d808501065f70898d8 (diff)
mm, slab: combine kmalloc_caches and kmalloc_dma_caches
Patch series "kmalloc-reclaimable caches", v4. As discussed at LSF/MM [1] here's a patchset that introduces kmalloc-reclaimable caches (more details in the second patch) and uses them for dcache external names. That allows us to repurpose the NR_INDIRECTLY_RECLAIMABLE_BYTES counter later in the series. With patch 3/6, dcache external names are allocated from kmalloc-rcl-* caches, eliminating the need for manual accounting. More importantly, it also ensures the reclaimable kmalloc allocations are grouped in pages separate from the regular kmalloc allocations. The need for proper accounting of dcache external names has shown it's easy for misbehaving process to allocate lots of them, causing premature OOMs. Without the added grouping, it's likely that a similar workload can interleave the dcache external names allocations with regular kmalloc allocations (note: I haven't searched myself for an example of such regular kmalloc allocation, but I would be very surprised if there wasn't some). A pathological case would be e.g. one 64byte regular allocations with 63 external dcache names in a page (64x64=4096), which means the page is not freed even after reclaiming after all dcache names, and the process can thus "steal" the whole page with single 64byte allocation. If other kmalloc users similar to dcache external names become identified, they can also benefit from the new functionality simply by adding __GFP_RECLAIMABLE to the kmalloc calls. Side benefits of the patchset (that could be also merged separately) include removed branch for detecting __GFP_DMA kmalloc(), and shortening kmalloc cache names in /proc/slabinfo output. The latter is potentially an ABI break in case there are tools parsing the names and expecting the values to be in bytes. This is how /proc/slabinfo looks like after booting in virtme: ... kmalloc-rcl-4M 0 0 4194304 1 1024 : tunables 1 1 0 : slabdata 0 0 0 ... kmalloc-rcl-96 7 32 128 32 1 : tunables 120 60 8 : slabdata 1 1 0 kmalloc-rcl-64 25 128 64 64 1 : tunables 120 60 8 : slabdata 2 2 0 kmalloc-rcl-32 0 0 32 124 1 : tunables 120 60 8 : slabdata 0 0 0 kmalloc-4M 0 0 4194304 1 1024 : tunables 1 1 0 : slabdata 0 0 0 kmalloc-2M 0 0 2097152 1 512 : tunables 1 1 0 : slabdata 0 0 0 kmalloc-1M 0 0 1048576 1 256 : tunables 1 1 0 : slabdata 0 0 0 ... /proc/vmstat with renamed nr_indirectly_reclaimable_bytes counter: ... nr_slab_reclaimable 2817 nr_slab_unreclaimable 1781 ... nr_kernel_misc_reclaimable 0 ... /proc/meminfo with new KReclaimable counter: ... Shmem: 564 kB KReclaimable: 11260 kB Slab: 18368 kB SReclaimable: 11260 kB SUnreclaim: 7108 kB KernelStack: 1248 kB ... This patch (of 6): The kmalloc caches currently mainain separate (optional) array kmalloc_dma_caches for __GFP_DMA allocations. There are tests for __GFP_DMA in the allocation hotpaths. We can avoid the branches by combining kmalloc_caches and kmalloc_dma_caches into a single two-dimensional array where the outer dimension is cache "type". This will also allow to add kmalloc-reclaimable caches as a third type. Link: http://lkml.kernel.org/r/20180731090649.16028-2-vbabka@suse.cz Signed-off-by: Vlastimil Babka <vbabka@suse.cz> Acked-by: Mel Gorman <mgorman@techsingularity.net> Acked-by: Christoph Lameter <cl@linux.com> Acked-by: Roman Gushchin <guro@fb.com> Cc: Michal Hocko <mhocko@kernel.org> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: David Rientjes <rientjes@google.com> Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com> Cc: Matthew Wilcox <willy@infradead.org> Cc: Laura Abbott <labbott@redhat.com> Cc: Sumit Semwal <sumit.semwal@linaro.org> Cc: Vijayanand Jitta <vjitta@codeaurora.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/slab_common.c')
-rw-r--r--mm/slab_common.c31
1 files changed, 12 insertions, 19 deletions
diff --git a/mm/slab_common.c b/mm/slab_common.c
index 3a7ac4f15194..d880b2a3c81b 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -973,14 +973,10 @@ struct kmem_cache *__init create_kmalloc_cache(const char *name,
973 return s; 973 return s;
974} 974}
975 975
976struct kmem_cache *kmalloc_caches[KMALLOC_SHIFT_HIGH + 1] __ro_after_init; 976struct kmem_cache *
977kmalloc_caches[NR_KMALLOC_TYPES][KMALLOC_SHIFT_HIGH + 1] __ro_after_init;
977EXPORT_SYMBOL(kmalloc_caches); 978EXPORT_SYMBOL(kmalloc_caches);
978 979
979#ifdef CONFIG_ZONE_DMA
980struct kmem_cache *kmalloc_dma_caches[KMALLOC_SHIFT_HIGH + 1] __ro_after_init;
981EXPORT_SYMBOL(kmalloc_dma_caches);
982#endif
983
984/* 980/*
985 * Conversion table for small slabs sizes / 8 to the index in the 981 * Conversion table for small slabs sizes / 8 to the index in the
986 * kmalloc array. This is necessary for slabs < 192 since we have non power 982 * kmalloc array. This is necessary for slabs < 192 since we have non power
@@ -1040,12 +1036,7 @@ struct kmem_cache *kmalloc_slab(size_t size, gfp_t flags)
1040 index = fls(size - 1); 1036 index = fls(size - 1);
1041 } 1037 }
1042 1038
1043#ifdef CONFIG_ZONE_DMA 1039 return kmalloc_caches[kmalloc_type(flags)][index];
1044 if (unlikely((flags & GFP_DMA)))
1045 return kmalloc_dma_caches[index];
1046
1047#endif
1048 return kmalloc_caches[index];
1049} 1040}
1050 1041
1051/* 1042/*
@@ -1119,7 +1110,8 @@ void __init setup_kmalloc_cache_index_table(void)
1119 1110
1120static void __init new_kmalloc_cache(int idx, slab_flags_t flags) 1111static void __init new_kmalloc_cache(int idx, slab_flags_t flags)
1121{ 1112{
1122 kmalloc_caches[idx] = create_kmalloc_cache(kmalloc_info[idx].name, 1113 kmalloc_caches[KMALLOC_NORMAL][idx] = create_kmalloc_cache(
1114 kmalloc_info[idx].name,
1123 kmalloc_info[idx].size, flags, 0, 1115 kmalloc_info[idx].size, flags, 0,
1124 kmalloc_info[idx].size); 1116 kmalloc_info[idx].size);
1125} 1117}
@@ -1132,9 +1124,10 @@ static void __init new_kmalloc_cache(int idx, slab_flags_t flags)
1132void __init create_kmalloc_caches(slab_flags_t flags) 1124void __init create_kmalloc_caches(slab_flags_t flags)
1133{ 1125{
1134 int i; 1126 int i;
1127 int type = KMALLOC_NORMAL;
1135 1128
1136 for (i = KMALLOC_SHIFT_LOW; i <= KMALLOC_SHIFT_HIGH; i++) { 1129 for (i = KMALLOC_SHIFT_LOW; i <= KMALLOC_SHIFT_HIGH; i++) {
1137 if (!kmalloc_caches[i]) 1130 if (!kmalloc_caches[type][i])
1138 new_kmalloc_cache(i, flags); 1131 new_kmalloc_cache(i, flags);
1139 1132
1140 /* 1133 /*
@@ -1142,9 +1135,9 @@ void __init create_kmalloc_caches(slab_flags_t flags)
1142 * These have to be created immediately after the 1135 * These have to be created immediately after the
1143 * earlier power of two caches 1136 * earlier power of two caches
1144 */ 1137 */
1145 if (KMALLOC_MIN_SIZE <= 32 && !kmalloc_caches[1] && i == 6) 1138 if (KMALLOC_MIN_SIZE <= 32 && !kmalloc_caches[type][1] && i == 6)
1146 new_kmalloc_cache(1, flags); 1139 new_kmalloc_cache(1, flags);
1147 if (KMALLOC_MIN_SIZE <= 64 && !kmalloc_caches[2] && i == 7) 1140 if (KMALLOC_MIN_SIZE <= 64 && !kmalloc_caches[type][2] && i == 7)
1148 new_kmalloc_cache(2, flags); 1141 new_kmalloc_cache(2, flags);
1149 } 1142 }
1150 1143
@@ -1153,7 +1146,7 @@ void __init create_kmalloc_caches(slab_flags_t flags)
1153 1146
1154#ifdef CONFIG_ZONE_DMA 1147#ifdef CONFIG_ZONE_DMA
1155 for (i = 0; i <= KMALLOC_SHIFT_HIGH; i++) { 1148 for (i = 0; i <= KMALLOC_SHIFT_HIGH; i++) {
1156 struct kmem_cache *s = kmalloc_caches[i]; 1149 struct kmem_cache *s = kmalloc_caches[KMALLOC_NORMAL][i];
1157 1150
1158 if (s) { 1151 if (s) {
1159 unsigned int size = kmalloc_size(i); 1152 unsigned int size = kmalloc_size(i);
@@ -1161,8 +1154,8 @@ void __init create_kmalloc_caches(slab_flags_t flags)
1161 "dma-kmalloc-%u", size); 1154 "dma-kmalloc-%u", size);
1162 1155
1163 BUG_ON(!n); 1156 BUG_ON(!n);
1164 kmalloc_dma_caches[i] = create_kmalloc_cache(n, 1157 kmalloc_caches[KMALLOC_DMA][i] = create_kmalloc_cache(
1165 size, SLAB_CACHE_DMA | flags, 0, 0); 1158 n, size, SLAB_CACHE_DMA | flags, 0, 0);
1166 } 1159 }
1167 } 1160 }
1168#endif 1161#endif