Commit 5ab116c9349ef52d6fbd2e2917a53f13194b048e

Authored by Miao Xie
Committed by Linus Torvalds
1 parent 5574169613

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>

Showing 3 changed files with 14 additions and 10 deletions Side-by-side Diff

... ... @@ -858,7 +858,7 @@
858 858 /*
859 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 863 * init can run on any cpu.
864 864 */
... ... @@ -920,9 +920,6 @@
920 920 * call to guarantee_online_mems(), as we know no one is changing
921 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 923 * While the mm_struct we are migrating is typically from some
927 924 * other task, the task_struct mems_allowed that we are hacking
928 925 * is for our current task, which must allocate new pages for that
929 926  
930 927  
... ... @@ -1391,11 +1388,10 @@
1391 1388  
1392 1389 if (cs == &top_cpuset) {
1393 1390 cpumask_copy(cpus_attach, cpu_possible_mask);
1394   - to = node_possible_map;
1395 1391 } else {
1396 1392 guarantee_online_cpus(cs, cpus_attach);
1397   - guarantee_online_mems(cs, &to);
1398 1393 }
  1394 + guarantee_online_mems(cs, &to);
1399 1395  
1400 1396 /* do per-task migration stuff possibly for each in the threadgroup */
1401 1397 cpuset_attach_task(tsk, &to, cs);
1402 1398  
1403 1399  
... ... @@ -2090,15 +2086,23 @@
2090 2086 static int cpuset_track_online_nodes(struct notifier_block *self,
2091 2087 unsigned long action, void *arg)
2092 2088 {
  2089 + nodemask_t oldmems;
  2090 +
2093 2091 cgroup_lock();
2094 2092 switch (action) {
2095 2093 case MEM_ONLINE:
2096   - case MEM_OFFLINE:
  2094 + oldmems = top_cpuset.mems_allowed;
2097 2095 mutex_lock(&callback_mutex);
2098 2096 top_cpuset.mems_allowed = node_states[N_HIGH_MEMORY];
2099 2097 mutex_unlock(&callback_mutex);
2100   - if (action == MEM_OFFLINE)
2101   - scan_for_empty_cpusets(&top_cpuset);
  2098 + update_tasks_nodemask(&top_cpuset, &oldmems, NULL);
  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 2106 break;
2103 2107 default:
2104 2108 break;
... ... @@ -219,7 +219,7 @@
219 219 set_task_comm(tsk, "kthreadd");
220 220 ignore_signals(tsk);
221 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 224 current->flags |= PF_NOFREEZE | PF_FREEZER_NOSIG;
225 225