aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorSrivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>2012-05-24 10:16:55 -0400
committerIngo Molnar <mingo@kernel.org>2012-07-24 07:53:22 -0400
commit7ddf96b02fe8dd441f452deef879040def5f7b34 (patch)
tree779a01bad0b51eb8ca8acb96b75f5a1b06f9a6d3 /kernel
parent80d1fa6463d934969b7aebf04107fc133463f0f6 (diff)
cpusets, hotplug: Restructure functions that are invoked during hotplug
Separate out the cpuset related handling for CPU/Memory online/offline. This also helps us exploit the most obvious and basic level of optimization that any notification mechanism (CPU/Mem online/offline) has to offer us: "We *know* why we have been invoked. So stop pretending that we are lost, and do only the necessary amount of processing!". And while at it, rename scan_for_empty_cpusets() to scan_cpusets_upon_hotplug(), which is more appropriate considering how it is restructured. Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/20120524141650.3692.48637.stgit@srivatsabhat.in.ibm.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/cpuset.c88
-rw-r--r--kernel/sched/core.c4
2 files changed, 63 insertions, 29 deletions
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index ba96349aa522..ba0a4d74d262 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -147,6 +147,12 @@ typedef enum {
147 CS_SPREAD_SLAB, 147 CS_SPREAD_SLAB,
148} cpuset_flagbits_t; 148} cpuset_flagbits_t;
149 149
150/* the type of hotplug event */
151enum hotplug_event {
152 CPUSET_CPU_OFFLINE,
153 CPUSET_MEM_OFFLINE,
154};
155
150/* convenient tests for these bits */ 156/* convenient tests for these bits */
151static inline int is_cpu_exclusive(const struct cpuset *cs) 157static inline int is_cpu_exclusive(const struct cpuset *cs)
152{ 158{
@@ -2016,8 +2022,10 @@ static struct cpuset *cpuset_next(struct list_head *queue)
2016 2022
2017 2023
2018/* 2024/*
2019 * Walk the specified cpuset subtree and look for empty cpusets. 2025 * Walk the specified cpuset subtree upon a hotplug operation (CPU/Memory
2020 * The tasks of such cpuset must be moved to a parent cpuset. 2026 * online/offline) and update the cpusets accordingly.
2027 * For regular CPU/Mem hotplug, look for empty cpusets; the tasks of such
2028 * cpuset must be moved to a parent cpuset.
2021 * 2029 *
2022 * Called with cgroup_mutex held. We take callback_mutex to modify 2030 * Called with cgroup_mutex held. We take callback_mutex to modify
2023 * cpus_allowed and mems_allowed. 2031 * cpus_allowed and mems_allowed.
@@ -2030,38 +2038,58 @@ static struct cpuset *cpuset_next(struct list_head *queue)
2030 * that has tasks along with an empty 'mems'. But if we did see such 2038 * that has tasks along with an empty 'mems'. But if we did see such
2031 * a cpuset, we'd handle it just like we do if its 'cpus' was empty. 2039 * a cpuset, we'd handle it just like we do if its 'cpus' was empty.
2032 */ 2040 */
2033static void scan_for_empty_cpusets(struct cpuset *root) 2041static void
2042scan_cpusets_upon_hotplug(struct cpuset *root, enum hotplug_event event)
2034{ 2043{
2035 LIST_HEAD(queue); 2044 LIST_HEAD(queue);
2036 struct cpuset *cp; /* scans cpusets being updated */ 2045 struct cpuset *cp; /* scans cpusets being updated */
2037 static nodemask_t oldmems; /* protected by cgroup_mutex */ 2046 static nodemask_t oldmems; /* protected by cgroup_mutex */
2038 2047
2039 list_add_tail((struct list_head *)&root->stack_list, &queue); 2048 list_add_tail((struct list_head *)&root->stack_list, &queue);
2040 2049
2041 while ((cp = cpuset_next(&queue)) != NULL) { 2050 switch (event) {
2051 case CPUSET_CPU_OFFLINE:
2052 while ((cp = cpuset_next(&queue)) != NULL) {
2053
2054 /* Continue past cpusets with all cpus online */
2055 if (cpumask_subset(cp->cpus_allowed, cpu_active_mask))
2056 continue;
2057
2058 /* Remove offline cpus from this cpuset. */
2059 mutex_lock(&callback_mutex);
2060 cpumask_and(cp->cpus_allowed, cp->cpus_allowed,
2061 cpu_active_mask);
2062 mutex_unlock(&callback_mutex);
2063
2064 /* Move tasks from the empty cpuset to a parent */
2065 if (cpumask_empty(cp->cpus_allowed))
2066 remove_tasks_in_empty_cpuset(cp);
2067 else
2068 update_tasks_cpumask(cp, NULL);
2069 }
2070 break;
2042 2071
2043 /* Continue past cpusets with all cpus, mems online */ 2072 case CPUSET_MEM_OFFLINE:
2044 if (cpumask_subset(cp->cpus_allowed, cpu_active_mask) && 2073 while ((cp = cpuset_next(&queue)) != NULL) {
2045 nodes_subset(cp->mems_allowed, node_states[N_HIGH_MEMORY]))
2046 continue;
2047 2074
2048 oldmems = cp->mems_allowed; 2075 /* Continue past cpusets with all mems online */
2076 if (nodes_subset(cp->mems_allowed,
2077 node_states[N_HIGH_MEMORY]))
2078 continue;
2049 2079
2050 /* Remove offline cpus and mems from this cpuset. */ 2080 oldmems = cp->mems_allowed;
2051 mutex_lock(&callback_mutex); 2081
2052 cpumask_and(cp->cpus_allowed, cp->cpus_allowed, 2082 /* Remove offline mems from this cpuset. */
2053 cpu_active_mask); 2083 mutex_lock(&callback_mutex);
2054 nodes_and(cp->mems_allowed, cp->mems_allowed, 2084 nodes_and(cp->mems_allowed, cp->mems_allowed,
2055 node_states[N_HIGH_MEMORY]); 2085 node_states[N_HIGH_MEMORY]);
2056 mutex_unlock(&callback_mutex); 2086 mutex_unlock(&callback_mutex);
2057 2087
2058 /* Move tasks from the empty cpuset to a parent */ 2088 /* Move tasks from the empty cpuset to a parent */
2059 if (cpumask_empty(cp->cpus_allowed) || 2089 if (nodes_empty(cp->mems_allowed))
2060 nodes_empty(cp->mems_allowed)) 2090 remove_tasks_in_empty_cpuset(cp);
2061 remove_tasks_in_empty_cpuset(cp); 2091 else
2062 else { 2092 update_tasks_nodemask(cp, &oldmems, NULL);
2063 update_tasks_cpumask(cp, NULL);
2064 update_tasks_nodemask(cp, &oldmems, NULL);
2065 } 2093 }
2066 } 2094 }
2067} 2095}
@@ -2080,8 +2108,11 @@ static void scan_for_empty_cpusets(struct cpuset *root)
2080 * 2108 *
2081 * Called within get_online_cpus(). Needs to call cgroup_lock() 2109 * Called within get_online_cpus(). Needs to call cgroup_lock()
2082 * before calling generate_sched_domains(). 2110 * before calling generate_sched_domains().
2111 *
2112 * @cpu_online: Indicates whether this is a CPU online event (true) or
2113 * a CPU offline event (false).
2083 */ 2114 */
2084void cpuset_update_active_cpus(void) 2115void cpuset_update_active_cpus(bool cpu_online)
2085{ 2116{
2086 struct sched_domain_attr *attr; 2117 struct sched_domain_attr *attr;
2087 cpumask_var_t *doms; 2118 cpumask_var_t *doms;
@@ -2091,7 +2122,10 @@ void cpuset_update_active_cpus(void)
2091 mutex_lock(&callback_mutex); 2122 mutex_lock(&callback_mutex);
2092 cpumask_copy(top_cpuset.cpus_allowed, cpu_active_mask); 2123 cpumask_copy(top_cpuset.cpus_allowed, cpu_active_mask);
2093 mutex_unlock(&callback_mutex); 2124 mutex_unlock(&callback_mutex);
2094 scan_for_empty_cpusets(&top_cpuset); 2125
2126 if (!cpu_online)
2127 scan_cpusets_upon_hotplug(&top_cpuset, CPUSET_CPU_OFFLINE);
2128
2095 ndoms = generate_sched_domains(&doms, &attr); 2129 ndoms = generate_sched_domains(&doms, &attr);
2096 cgroup_unlock(); 2130 cgroup_unlock();
2097 2131
@@ -2122,9 +2156,9 @@ static int cpuset_track_online_nodes(struct notifier_block *self,
2122 case MEM_OFFLINE: 2156 case MEM_OFFLINE:
2123 /* 2157 /*
2124 * needn't update top_cpuset.mems_allowed explicitly because 2158 * needn't update top_cpuset.mems_allowed explicitly because
2125 * scan_for_empty_cpusets() will update it. 2159 * scan_cpusets_upon_hotplug() will update it.
2126 */ 2160 */
2127 scan_for_empty_cpusets(&top_cpuset); 2161 scan_cpusets_upon_hotplug(&top_cpuset, CPUSET_MEM_OFFLINE);
2128 break; 2162 break;
2129 default: 2163 default:
2130 break; 2164 break;
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 4c1d80c6b318..4b4a63d34396 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -7134,7 +7134,7 @@ static int cpuset_cpu_active(struct notifier_block *nfb, unsigned long action,
7134 7134
7135 case CPU_ONLINE: 7135 case CPU_ONLINE:
7136 case CPU_DOWN_FAILED: 7136 case CPU_DOWN_FAILED:
7137 cpuset_update_active_cpus(); 7137 cpuset_update_active_cpus(true);
7138 break; 7138 break;
7139 default: 7139 default:
7140 return NOTIFY_DONE; 7140 return NOTIFY_DONE;
@@ -7147,7 +7147,7 @@ static int cpuset_cpu_inactive(struct notifier_block *nfb, unsigned long action,
7147{ 7147{
7148 switch (action) { 7148 switch (action) {
7149 case CPU_DOWN_PREPARE: 7149 case CPU_DOWN_PREPARE:
7150 cpuset_update_active_cpus(); 7150 cpuset_update_active_cpus(false);
7151 break; 7151 break;
7152 case CPU_DOWN_PREPARE_FROZEN: 7152 case CPU_DOWN_PREPARE_FROZEN:
7153 num_cpus_frozen++; 7153 num_cpus_frozen++;