Commit bce61dd49d6ba7799be2de17c772e4c701558f14
Committed by
Linus Torvalds
1 parent
ee500f2749
Exists in
master
and in
7 other branches
[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
kernel/workqueue.c
... | ... | @@ -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); |