Commit bce61dd49d6ba7799be2de17c772e4c701558f14

Authored by Ben Collins
Committed by Linus Torvalds
1 parent ee500f2749

[PATCH] Fix hardcoded cpu=0 in workqueue for per_cpu_ptr() calls

Tracked this down on an Ultra Enterprise 3000.  It's a 6-way machine.  Odd
thing about this machine (and it's good for finding bugs like this) is that
the CPU id's are not 0 based.  For instance, on my machine the CPU's are
6/7/10/11/14/15.

This caused some NULL pointer dereference in kernel/workqueue.c because for
single_threaded workqueue's, it hardcoded the cpu to 0.

I changed the 0's to any_online_cpu(cpu_online_mask), which cpumask.h
claims is "First cpu in mask".  So this fits the same usage.

Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 1 changed file with 6 additions and 6 deletions Side-by-side Diff

... ... @@ -102,7 +102,7 @@
102 102  
103 103 if (!test_and_set_bit(0, &work->pending)) {
104 104 if (unlikely(is_single_threaded(wq)))
105   - cpu = 0;
  105 + cpu = any_online_cpu(cpu_online_map);
106 106 BUG_ON(!list_empty(&work->entry));
107 107 __queue_work(per_cpu_ptr(wq->cpu_wq, cpu), work);
108 108 ret = 1;
... ... @@ -118,7 +118,7 @@
118 118 int cpu = smp_processor_id();
119 119  
120 120 if (unlikely(is_single_threaded(wq)))
121   - cpu = 0;
  121 + cpu = any_online_cpu(cpu_online_map);
122 122  
123 123 __queue_work(per_cpu_ptr(wq->cpu_wq, cpu), work);
124 124 }
... ... @@ -266,8 +266,8 @@
266 266 might_sleep();
267 267  
268 268 if (is_single_threaded(wq)) {
269   - /* Always use cpu 0's area. */
270   - flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, 0));
  269 + /* Always use first cpu's area. */
  270 + flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, any_online_cpu(cpu_online_map)));
271 271 } else {
272 272 int cpu;
273 273  
... ... @@ -320,7 +320,7 @@
320 320 lock_cpu_hotplug();
321 321 if (singlethread) {
322 322 INIT_LIST_HEAD(&wq->list);
323   - p = create_workqueue_thread(wq, 0);
  323 + p = create_workqueue_thread(wq, any_online_cpu(cpu_online_map));
324 324 if (!p)
325 325 destroy = 1;
326 326 else
... ... @@ -374,7 +374,7 @@
374 374 /* We don't need the distraction of CPUs appearing and vanishing. */
375 375 lock_cpu_hotplug();
376 376 if (is_single_threaded(wq))
377   - cleanup_workqueue_thread(wq, 0);
  377 + cleanup_workqueue_thread(wq, any_online_cpu(cpu_online_map));
378 378 else {
379 379 for_each_online_cpu(cpu)
380 380 cleanup_workqueue_thread(wq, cpu);