Commit fc75cdfa5b43ac4d3232b490800cd35063adafd3

Authored by Heiko Carstens
Committed by Linus Torvalds
1 parent 04a3446c90

[PATCH] cpu hotplug: fix CPU_UP_CANCEL handling

If a cpu hotplug callback fails on CPU_UP_PREPARE, all callbacks will be
called with CPU_UP_CANCELED.  A few of these callbacks assume that on
CPU_UP_PREPARE a pointer to task has been stored in a percpu array.  This
assumption is not true if CPU_UP_PREPARE fails and the following calls to
kthread_bind() in CPU_UP_CANCELED will cause an addressing exception
because of passing a NULL pointer.

Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Ashok Raj <ashok.raj@intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 4 changed files with 8 additions and 0 deletions Side-by-side Diff

... ... @@ -4756,6 +4756,8 @@
4756 4756 break;
4757 4757 #ifdef CONFIG_HOTPLUG_CPU
4758 4758 case CPU_UP_CANCELED:
  4759 + if (!cpu_rq(cpu)->migration_thread)
  4760 + break;
4759 4761 /* Unbind it from offline cpu so it can run. Fall thru. */
4760 4762 kthread_bind(cpu_rq(cpu)->migration_thread,
4761 4763 any_online_cpu(cpu_online_map));
... ... @@ -470,6 +470,8 @@
470 470 break;
471 471 #ifdef CONFIG_HOTPLUG_CPU
472 472 case CPU_UP_CANCELED:
  473 + if (!per_cpu(ksoftirqd, hotcpu))
  474 + break;
473 475 /* Unbind so it can run. Fall thru. */
474 476 kthread_bind(per_cpu(ksoftirqd, hotcpu),
475 477 any_online_cpu(cpu_online_map));
... ... @@ -127,6 +127,8 @@
127 127 break;
128 128 #ifdef CONFIG_HOTPLUG_CPU
129 129 case CPU_UP_CANCELED:
  130 + if (!per_cpu(watchdog_task, hotcpu))
  131 + break;
130 132 /* Unbind so it can run. Fall thru. */
131 133 kthread_bind(per_cpu(watchdog_task, hotcpu),
132 134 any_online_cpu(cpu_online_map));
... ... @@ -590,6 +590,8 @@
590 590  
591 591 case CPU_UP_CANCELED:
592 592 list_for_each_entry(wq, &workqueues, list) {
  593 + if (!per_cpu_ptr(wq->cpu_wq, hotcpu)->thread)
  594 + continue;
593 595 /* Unbind so it can run. */
594 596 kthread_bind(per_cpu_ptr(wq->cpu_wq, hotcpu)->thread,
595 597 any_online_cpu(cpu_online_map));