diff options
| -rw-r--r-- | include/linux/cpuset.h | 4 | ||||
| -rw-r--r-- | kernel/cpuset.c | 88 | ||||
| -rw-r--r-- | kernel/sched/core.c | 4 |
3 files changed, 65 insertions, 31 deletions
diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h index 668f66baac7b..838320fc3d1d 100644 --- a/include/linux/cpuset.h +++ b/include/linux/cpuset.h | |||
| @@ -20,7 +20,7 @@ extern int number_of_cpusets; /* How many cpusets are defined in system? */ | |||
| 20 | 20 | ||
| 21 | extern int cpuset_init(void); | 21 | extern int cpuset_init(void); |
| 22 | extern void cpuset_init_smp(void); | 22 | extern void cpuset_init_smp(void); |
| 23 | extern void cpuset_update_active_cpus(void); | 23 | extern void cpuset_update_active_cpus(bool cpu_online); |
| 24 | extern void cpuset_cpus_allowed(struct task_struct *p, struct cpumask *mask); | 24 | extern void cpuset_cpus_allowed(struct task_struct *p, struct cpumask *mask); |
| 25 | extern void cpuset_cpus_allowed_fallback(struct task_struct *p); | 25 | extern void cpuset_cpus_allowed_fallback(struct task_struct *p); |
| 26 | extern nodemask_t cpuset_mems_allowed(struct task_struct *p); | 26 | extern nodemask_t cpuset_mems_allowed(struct task_struct *p); |
| @@ -124,7 +124,7 @@ static inline void set_mems_allowed(nodemask_t nodemask) | |||
| 124 | static inline int cpuset_init(void) { return 0; } | 124 | static inline int cpuset_init(void) { return 0; } |
| 125 | static inline void cpuset_init_smp(void) {} | 125 | static inline void cpuset_init_smp(void) {} |
| 126 | 126 | ||
| 127 | static inline void cpuset_update_active_cpus(void) | 127 | static inline void cpuset_update_active_cpus(bool cpu_online) |
| 128 | { | 128 | { |
| 129 | partition_sched_domains(1, NULL, NULL); | 129 | partition_sched_domains(1, NULL, NULL); |
| 130 | } | 130 | } |
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 */ | ||
| 151 | enum hotplug_event { | ||
| 152 | CPUSET_CPU_OFFLINE, | ||
| 153 | CPUSET_MEM_OFFLINE, | ||
| 154 | }; | ||
| 155 | |||
| 150 | /* convenient tests for these bits */ | 156 | /* convenient tests for these bits */ |
| 151 | static inline int is_cpu_exclusive(const struct cpuset *cs) | 157 | static 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 | */ |
| 2033 | static void scan_for_empty_cpusets(struct cpuset *root) | 2041 | static void |
| 2042 | scan_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 | */ |
| 2084 | void cpuset_update_active_cpus(void) | 2115 | void 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++; |
