diff options
author | Miao Xie <miaox@cn.fujitsu.com> | 2010-03-23 16:35:34 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-24 19:31:21 -0400 |
commit | 5ab116c9349ef52d6fbd2e2917a53f13194b048e (patch) | |
tree | 636a6cf02d5ca47c6da5d4935b07ddf08666a09c | |
parent | 5574169613b40b85d6f4c67208fa4846b897a0a1 (diff) |
cpuset: fix the problem that cpuset_mem_spread_node() returns an offline node
cpuset_mem_spread_node() returns an offline node, and causes an oops.
This patch fixes it by initializing task->mems_allowed to
node_states[N_HIGH_MEMORY], and updating task->mems_allowed when doing
memory hotplug.
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
Acked-by: David Rientjes <rientjes@google.com>
Reported-by: Nick Piggin <npiggin@suse.de>
Tested-by: Nick Piggin <npiggin@suse.de>
Cc: Paul Menage <menage@google.com>
Cc: Li Zefan <lizf@cn.fujitsu.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | init/main.c | 2 | ||||
-rw-r--r-- | kernel/cpuset.c | 20 | ||||
-rw-r--r-- | kernel/kthread.c | 2 |
3 files changed, 14 insertions, 10 deletions
diff --git a/init/main.c b/init/main.c index a1ab78ceb4b6..cbead27caefc 100644 --- a/init/main.c +++ b/init/main.c | |||
@@ -858,7 +858,7 @@ static int __init kernel_init(void * unused) | |||
858 | /* | 858 | /* |
859 | * init can allocate pages on any node | 859 | * init can allocate pages on any node |
860 | */ | 860 | */ |
861 | set_mems_allowed(node_possible_map); | 861 | set_mems_allowed(node_states[N_HIGH_MEMORY]); |
862 | /* | 862 | /* |
863 | * init can run on any cpu. | 863 | * init can run on any cpu. |
864 | */ | 864 | */ |
diff --git a/kernel/cpuset.c b/kernel/cpuset.c index ba401fab459f..5d38bd74483c 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c | |||
@@ -920,9 +920,6 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs, | |||
920 | * call to guarantee_online_mems(), as we know no one is changing | 920 | * call to guarantee_online_mems(), as we know no one is changing |
921 | * our task's cpuset. | 921 | * our task's cpuset. |
922 | * | 922 | * |
923 | * Hold callback_mutex around the two modifications of our tasks | ||
924 | * mems_allowed to synchronize with cpuset_mems_allowed(). | ||
925 | * | ||
926 | * While the mm_struct we are migrating is typically from some | 923 | * While the mm_struct we are migrating is typically from some |
927 | * other task, the task_struct mems_allowed that we are hacking | 924 | * other task, the task_struct mems_allowed that we are hacking |
928 | * is for our current task, which must allocate new pages for that | 925 | * is for our current task, which must allocate new pages for that |
@@ -1391,11 +1388,10 @@ static void cpuset_attach(struct cgroup_subsys *ss, struct cgroup *cont, | |||
1391 | 1388 | ||
1392 | if (cs == &top_cpuset) { | 1389 | if (cs == &top_cpuset) { |
1393 | cpumask_copy(cpus_attach, cpu_possible_mask); | 1390 | cpumask_copy(cpus_attach, cpu_possible_mask); |
1394 | to = node_possible_map; | ||
1395 | } else { | 1391 | } else { |
1396 | guarantee_online_cpus(cs, cpus_attach); | 1392 | guarantee_online_cpus(cs, cpus_attach); |
1397 | guarantee_online_mems(cs, &to); | ||
1398 | } | 1393 | } |
1394 | guarantee_online_mems(cs, &to); | ||
1399 | 1395 | ||
1400 | /* do per-task migration stuff possibly for each in the threadgroup */ | 1396 | /* do per-task migration stuff possibly for each in the threadgroup */ |
1401 | cpuset_attach_task(tsk, &to, cs); | 1397 | cpuset_attach_task(tsk, &to, cs); |
@@ -2090,15 +2086,23 @@ static int cpuset_track_online_cpus(struct notifier_block *unused_nb, | |||
2090 | static int cpuset_track_online_nodes(struct notifier_block *self, | 2086 | static int cpuset_track_online_nodes(struct notifier_block *self, |
2091 | unsigned long action, void *arg) | 2087 | unsigned long action, void *arg) |
2092 | { | 2088 | { |
2089 | nodemask_t oldmems; | ||
2090 | |||
2093 | cgroup_lock(); | 2091 | cgroup_lock(); |
2094 | switch (action) { | 2092 | switch (action) { |
2095 | case MEM_ONLINE: | 2093 | case MEM_ONLINE: |
2096 | case MEM_OFFLINE: | 2094 | oldmems = top_cpuset.mems_allowed; |
2097 | mutex_lock(&callback_mutex); | 2095 | mutex_lock(&callback_mutex); |
2098 | top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY]; | 2096 | top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY]; |
2099 | mutex_unlock(&callback_mutex); | 2097 | mutex_unlock(&callback_mutex); |
2100 | if (action == MEM_OFFLINE) | 2098 | update_tasks_nodemask(&top_cpuset, &oldmems, NULL); |
2101 | scan_for_empty_cpusets(&top_cpuset); | 2099 | break; |
2100 | case MEM_OFFLINE: | ||
2101 | /* | ||
2102 | * needn't update top_cpuset.mems_allowed explicitly because | ||
2103 | * scan_for_empty_cpusets() will update it. | ||
2104 | */ | ||
2105 | scan_for_empty_cpusets(&top_cpuset); | ||
2102 | break; | 2106 | break; |
2103 | default: | 2107 | default: |
2104 | break; | 2108 | break; |
diff --git a/kernel/kthread.c b/kernel/kthread.c index 82ed0ea15194..83911c780175 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c | |||
@@ -219,7 +219,7 @@ int kthreadd(void *unused) | |||
219 | set_task_comm(tsk, "kthreadd"); | 219 | set_task_comm(tsk, "kthreadd"); |
220 | ignore_signals(tsk); | 220 | ignore_signals(tsk); |
221 | set_cpus_allowed_ptr(tsk, cpu_all_mask); | 221 | set_cpus_allowed_ptr(tsk, cpu_all_mask); |
222 | set_mems_allowed(node_possible_map); | 222 | set_mems_allowed(node_states[N_HIGH_MEMORY]); |
223 | 223 | ||
224 | current->flags |= PF_NOFREEZE | PF_FREEZER_NOSIG; | 224 | current->flags |= PF_NOFREEZE | PF_FREEZER_NOSIG; |
225 | 225 | ||