aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2016-08-23 08:53:19 -0400
committerThomas Gleixner <tglx@linutronix.de>2016-09-06 12:30:20 -0400
commit6731d4f12315aed5f7eefc52dac30428e382d7d0 (patch)
tree66abd6f0c2aa4191a11e076b7090f29e257cc7b3
parente6d4989a9ad1ccc343f29578a461612ed80fc6c5 (diff)
slab: Convert to hotplug state machine
Install the callbacks via the state machine. Signed-off-by: Richard Weinberger <richard@nod.at> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Pekka Enberg <penberg@kernel.org> Cc: linux-mm@kvack.org Cc: rt@linutronix.de Cc: David Rientjes <rientjes@google.com> Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Christoph Lameter <cl@linux.com> Link: http://lkml.kernel.org/r/20160823125319.abeapfjapf2kfezp@linutronix.de Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--include/linux/cpuhotplug.h1
-rw-r--r--include/linux/slab.h8
-rw-r--r--kernel/cpu.c6
-rw-r--r--mm/slab.c114
4 files changed, 66 insertions, 63 deletions
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
index 4c79f40fcebc..c2cf14953abc 100644
--- a/include/linux/cpuhotplug.h
+++ b/include/linux/cpuhotplug.h
@@ -22,6 +22,7 @@ enum cpuhp_state {
22 CPUHP_X2APIC_PREPARE, 22 CPUHP_X2APIC_PREPARE,
23 CPUHP_SMPCFD_PREPARE, 23 CPUHP_SMPCFD_PREPARE,
24 CPUHP_RELAY_PREPARE, 24 CPUHP_RELAY_PREPARE,
25 CPUHP_SLAB_PREPARE,
25 CPUHP_RCUTREE_PREP, 26 CPUHP_RCUTREE_PREP,
26 CPUHP_NOTIFY_PREPARE, 27 CPUHP_NOTIFY_PREPARE,
27 CPUHP_TIMERS_DEAD, 28 CPUHP_TIMERS_DEAD,
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 4293808d8cfb..084b12bad198 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -650,4 +650,12 @@ static inline void *kzalloc_node(size_t size, gfp_t flags, int node)
650unsigned int kmem_cache_size(struct kmem_cache *s); 650unsigned int kmem_cache_size(struct kmem_cache *s);
651void __init kmem_cache_init_late(void); 651void __init kmem_cache_init_late(void);
652 652
653#if defined(CONFIG_SMP) && defined(CONFIG_SLAB)
654int slab_prepare_cpu(unsigned int cpu);
655int slab_dead_cpu(unsigned int cpu);
656#else
657#define slab_prepare_cpu NULL
658#define slab_dead_cpu NULL
659#endif
660
653#endif /* _LINUX_SLAB_H */ 661#endif /* _LINUX_SLAB_H */
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 0c0d4b2ddd1c..7c783876cbcb 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -24,6 +24,7 @@
24#include <linux/irq.h> 24#include <linux/irq.h>
25#include <linux/smpboot.h> 25#include <linux/smpboot.h>
26#include <linux/relay.h> 26#include <linux/relay.h>
27#include <linux/slab.h>
27 28
28#include <trace/events/power.h> 29#include <trace/events/power.h>
29#define CREATE_TRACE_POINTS 30#define CREATE_TRACE_POINTS
@@ -1278,6 +1279,11 @@ static struct cpuhp_step cpuhp_bp_states[] = {
1278 .startup.single = relay_prepare_cpu, 1279 .startup.single = relay_prepare_cpu,
1279 .teardown.single = NULL, 1280 .teardown.single = NULL,
1280 }, 1281 },
1282 [CPUHP_SLAB_PREPARE] = {
1283 .name = "slab:prepare",
1284 .startup.single = slab_prepare_cpu,
1285 .teardown.single = slab_dead_cpu,
1286 },
1281 [CPUHP_RCUTREE_PREP] = { 1287 [CPUHP_RCUTREE_PREP] = {
1282 .name = "RCU/tree:prepare", 1288 .name = "RCU/tree:prepare",
1283 .startup.single = rcutree_prepare_cpu, 1289 .startup.single = rcutree_prepare_cpu,
diff --git a/mm/slab.c b/mm/slab.c
index b67271024135..090fb26b3a39 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -886,6 +886,7 @@ static int init_cache_node(struct kmem_cache *cachep, int node, gfp_t gfp)
886 return 0; 886 return 0;
887} 887}
888 888
889#if (defined(CONFIG_NUMA) && defined(CONFIG_MEMORY_HOTPLUG)) || defined(CONFIG_SMP)
889/* 890/*
890 * Allocates and initializes node for a node on each slab cache, used for 891 * Allocates and initializes node for a node on each slab cache, used for
891 * either memory or cpu hotplug. If memory is being hot-added, the kmem_cache_node 892 * either memory or cpu hotplug. If memory is being hot-added, the kmem_cache_node
@@ -908,6 +909,7 @@ static int init_cache_node_node(int node)
908 909
909 return 0; 910 return 0;
910} 911}
912#endif
911 913
912static int setup_kmem_cache_node(struct kmem_cache *cachep, 914static int setup_kmem_cache_node(struct kmem_cache *cachep,
913 int node, gfp_t gfp, bool force_change) 915 int node, gfp_t gfp, bool force_change)
@@ -975,6 +977,8 @@ fail:
975 return ret; 977 return ret;
976} 978}
977 979
980#ifdef CONFIG_SMP
981
978static void cpuup_canceled(long cpu) 982static void cpuup_canceled(long cpu)
979{ 983{
980 struct kmem_cache *cachep; 984 struct kmem_cache *cachep;
@@ -1075,65 +1079,54 @@ bad:
1075 return -ENOMEM; 1079 return -ENOMEM;
1076} 1080}
1077 1081
1078static int cpuup_callback(struct notifier_block *nfb, 1082int slab_prepare_cpu(unsigned int cpu)
1079 unsigned long action, void *hcpu)
1080{ 1083{
1081 long cpu = (long)hcpu; 1084 int err;
1082 int err = 0;
1083 1085
1084 switch (action) { 1086 mutex_lock(&slab_mutex);
1085 case CPU_UP_PREPARE: 1087 err = cpuup_prepare(cpu);
1086 case CPU_UP_PREPARE_FROZEN: 1088 mutex_unlock(&slab_mutex);
1087 mutex_lock(&slab_mutex); 1089 return err;
1088 err = cpuup_prepare(cpu); 1090}
1089 mutex_unlock(&slab_mutex); 1091
1090 break; 1092/*
1091 case CPU_ONLINE: 1093 * This is called for a failed online attempt and for a successful
1092 case CPU_ONLINE_FROZEN: 1094 * offline.
1093 start_cpu_timer(cpu); 1095 *
1094 break; 1096 * Even if all the cpus of a node are down, we don't free the
1095#ifdef CONFIG_HOTPLUG_CPU 1097 * kmem_list3 of any cache. This to avoid a race between cpu_down, and
1096 case CPU_DOWN_PREPARE: 1098 * a kmalloc allocation from another cpu for memory from the node of
1097 case CPU_DOWN_PREPARE_FROZEN: 1099 * the cpu going down. The list3 structure is usually allocated from
1098 /* 1100 * kmem_cache_create() and gets destroyed at kmem_cache_destroy().
1099 * Shutdown cache reaper. Note that the slab_mutex is 1101 */
1100 * held so that if cache_reap() is invoked it cannot do 1102int slab_dead_cpu(unsigned int cpu)
1101 * anything expensive but will only modify reap_work 1103{
1102 * and reschedule the timer. 1104 mutex_lock(&slab_mutex);
1103 */ 1105 cpuup_canceled(cpu);
1104 cancel_delayed_work_sync(&per_cpu(slab_reap_work, cpu)); 1106 mutex_unlock(&slab_mutex);
1105 /* Now the cache_reaper is guaranteed to be not running. */ 1107 return 0;
1106 per_cpu(slab_reap_work, cpu).work.func = NULL; 1108}
1107 break;
1108 case CPU_DOWN_FAILED:
1109 case CPU_DOWN_FAILED_FROZEN:
1110 start_cpu_timer(cpu);
1111 break;
1112 case CPU_DEAD:
1113 case CPU_DEAD_FROZEN:
1114 /*
1115 * Even if all the cpus of a node are down, we don't free the
1116 * kmem_cache_node of any cache. This to avoid a race between
1117 * cpu_down, and a kmalloc allocation from another cpu for
1118 * memory from the node of the cpu going down. The node
1119 * structure is usually allocated from kmem_cache_create() and
1120 * gets destroyed at kmem_cache_destroy().
1121 */
1122 /* fall through */
1123#endif 1109#endif
1124 case CPU_UP_CANCELED: 1110
1125 case CPU_UP_CANCELED_FROZEN: 1111static int slab_online_cpu(unsigned int cpu)
1126 mutex_lock(&slab_mutex); 1112{
1127 cpuup_canceled(cpu); 1113 start_cpu_timer(cpu);
1128 mutex_unlock(&slab_mutex); 1114 return 0;
1129 break;
1130 }
1131 return notifier_from_errno(err);
1132} 1115}
1133 1116
1134static struct notifier_block cpucache_notifier = { 1117static int slab_offline_cpu(unsigned int cpu)
1135 &cpuup_callback, NULL, 0 1118{
1136}; 1119 /*
1120 * Shutdown cache reaper. Note that the slab_mutex is held so
1121 * that if cache_reap() is invoked it cannot do anything
1122 * expensive but will only modify reap_work and reschedule the
1123 * timer.
1124 */
1125 cancel_delayed_work_sync(&per_cpu(slab_reap_work, cpu));
1126 /* Now the cache_reaper is guaranteed to be not running. */
1127 per_cpu(slab_reap_work, cpu).work.func = NULL;
1128 return 0;
1129}
1137 1130
1138#if defined(CONFIG_NUMA) && defined(CONFIG_MEMORY_HOTPLUG) 1131#if defined(CONFIG_NUMA) && defined(CONFIG_MEMORY_HOTPLUG)
1139/* 1132/*
@@ -1336,12 +1329,6 @@ void __init kmem_cache_init_late(void)
1336 /* Done! */ 1329 /* Done! */
1337 slab_state = FULL; 1330 slab_state = FULL;
1338 1331
1339 /*
1340 * Register a cpu startup notifier callback that initializes
1341 * cpu_cache_get for all new cpus
1342 */
1343 register_cpu_notifier(&cpucache_notifier);
1344
1345#ifdef CONFIG_NUMA 1332#ifdef CONFIG_NUMA
1346 /* 1333 /*
1347 * Register a memory hotplug callback that initializes and frees 1334 * Register a memory hotplug callback that initializes and frees
@@ -1358,13 +1345,14 @@ void __init kmem_cache_init_late(void)
1358 1345
1359static int __init cpucache_init(void) 1346static int __init cpucache_init(void)
1360{ 1347{
1361 int cpu; 1348 int ret;
1362 1349
1363 /* 1350 /*
1364 * Register the timers that return unneeded pages to the page allocator 1351 * Register the timers that return unneeded pages to the page allocator
1365 */ 1352 */
1366 for_each_online_cpu(cpu) 1353 ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "SLAB online",
1367 start_cpu_timer(cpu); 1354 slab_online_cpu, slab_offline_cpu);
1355 WARN_ON(ret < 0);
1368 1356
1369 /* Done! */ 1357 /* Done! */
1370 slab_state = FULL; 1358 slab_state = FULL;