History

[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.

Ben Collins committed 20 years ago

Commit bce61dd1 parent ee500f21 file · +6 −6Browse files

Showing the changes to kernel/workqueue.c (1 of 1 file). Show all

Unified · Split

kernel/workqueue.c+6−6
@@ -102,7 +102,7 @@ int fastcall queue_work(struct workqueue_struct *wq, struct work_struct *work) · 101 unmodified lines
102 102
103 if (!test_and_set_bit(0, &work->pending)) {103 if (!test_and_set_bit(0, &work->pending)) {
104 if (unlikely(is_single_threaded(wq)))104 if (unlikely(is_single_threaded(wq)))
105 cpu = 0;105 cpu = any_online_cpu(cpu_online_map);
106 BUG_ON(!list_empty(&work->entry));106 BUG_ON(!list_empty(&work->entry));
107 __queue_work(per_cpu_ptr(wq->cpu_wq, cpu), work);107 __queue_work(per_cpu_ptr(wq->cpu_wq, cpu), work);
108 ret = 1;108 ret = 1;
@@ -118,7 +118,7 @@ static void delayed_work_timer_fn(unsigned long __data) · 9 unmodified lines
118 int cpu = smp_processor_id();118 int cpu = smp_processor_id();
119 119
120 if (unlikely(is_single_threaded(wq)))120 if (unlikely(is_single_threaded(wq)))
121 cpu = 0;121 cpu = any_online_cpu(cpu_online_map);
122 122
123 __queue_work(per_cpu_ptr(wq->cpu_wq, cpu), work);123 __queue_work(per_cpu_ptr(wq->cpu_wq, cpu), work);
124}124}
@@ -266,8 +266,8 @@ void fastcall flush_workqueue(struct workqueue_struct *wq) · 141 unmodified lines
266 might_sleep();266 might_sleep();
267 267
268 if (is_single_threaded(wq)) {268 if (is_single_threaded(wq)) {
269 /* Always use cpu 0's area. */269 /* Always use first cpu's area. */
270 flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, 0));270 flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, any_online_cpu(cpu_online_map)));
271 } else {271 } else {
272 int cpu;272 int cpu;
273 273
@@ -320,7 +320,7 @@ struct workqueue_struct *__create_workqueue(const char *name, · 46 unmodified lines
320 lock_cpu_hotplug();320 lock_cpu_hotplug();
321 if (singlethread) {321 if (singlethread) {
322 INIT_LIST_HEAD(&wq->list);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 if (!p)324 if (!p)
325 destroy = 1;325 destroy = 1;
326 else326 else
@@ -374,7 +374,7 @@ void destroy_workqueue(struct workqueue_struct *wq) · 47 unmodified lines
374 /* We don't need the distraction of CPUs appearing and vanishing. */374 /* We don't need the distraction of CPUs appearing and vanishing. */
375 lock_cpu_hotplug();375 lock_cpu_hotplug();
376 if (is_single_threaded(wq))376 if (is_single_threaded(wq))
377 cleanup_workqueue_thread(wq, 0);377 cleanup_workqueue_thread(wq, any_online_cpu(cpu_online_map));
378 else {378 else {
379 for_each_online_cpu(cpu)379 for_each_online_cpu(cpu)
380 cleanup_workqueue_thread(wq, cpu);380 cleanup_workqueue_thread(wq, cpu);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t