/[linux-patches]/genpatches-2.6/trunk/2.6.14/1405_15.1_workqueue-cpu-offline.patch
Gentoo

Contents of /genpatches-2.6/trunk/2.6.14/1405_15.1_workqueue-cpu-offline.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 328 - (show annotations) (download) (as text)
Tue Mar 14 13:34:17 2006 UTC (14 years, 7 months ago) by johnm
File MIME type: text/x-diff
File size: 5061 byte(s)
2.6.14-11, rebase against local tree
1 Backported for 2.6.14 by Kerin Millar <kerframil@gmail.com> and Tim Yamin
2 <plasmaroo@gentoo.org>. This is a combination of the following commits:
3
4 234fd41c9c0ed59dd3e05e7f59ebaa29452af86d
5 bce61dd49d6ba7799be2de17c772e4c701558f14
6
7 ---
8
9 From: Ben Collins <bcollins@debian.org>
10 Date: Mon, 28 Nov 2005 21:43:56 +0000 (-0800)
11 Subject: [PATCH] Fix hardcoded cpu=0 in workqueue for per_cpu_ptr() calls
12 X-Git-Tag: v2.6.15-rc3
13 X-Git-Url: http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=bce61dd49d6ba7799be2de17c772e4c701558f14
14
15 [PATCH] Fix hardcoded cpu=0 in workqueue for per_cpu_ptr() calls
16
17 Tracked this down on an Ultra Enterprise 3000. It's a 6-way machine. Odd
18 thing about this machine (and it's good for finding bugs like this) is that
19 the CPU id's are not 0 based. For instance, on my machine the CPU's are
20 6/7/10/11/14/15.
21
22 This caused some NULL pointer dereference in kernel/workqueue.c because for
23 single_threaded workqueue's, it hardcoded the cpu to 0.
24
25 I changed the 0's to any_online_cpu(cpu_online_mask), which cpumask.h
26 claims is "First cpu in mask". So this fits the same usage.
27
28 Signed-off-by: Andrew Morton <akpm@osdl.org>
29 Signed-off-by: Linus Torvalds <torvalds@osdl.org>
30 ---
31
32 From stable-bounces@linux.kernel.org Sun Jan 8 01:09:03 2006
33 Message-Id: <200601080905.k0895NZ1015408@shell0.pdx.osdl.net>
34 To: torvalds@osdl.org
35 From: akpm@osdl.org
36 Date: Sun, 08 Jan 2006 01:05:12 -0800
37 Cc: ntl@pobox.com, stable@kernel.org
38 Subject: [PATCH] fix workqueue oops during cpu offline
39
40 From: Nathan Lynch <ntl@pobox.com>
41
42 Use first_cpu(cpu_possible_map) for the single-thread workqueue case. We
43 used to hardcode 0, but that broke on systems where !cpu_possible(0) when
44 workqueue_struct->cpu_workqueue_struct was changed from a static array to
45 alloc_percpu.
46
47 Commit id bce61dd49d6ba7799be2de17c772e4c701558f14 ("Fix hardcoded cpu=0 in
48 workqueue for per_cpu_ptr() calls") fixed that for Ben's funky sparc64
49 system, but it regressed my Power5. Offlining cpu 0 oopses upon the next
50 call to queue_work for a single-thread workqueue, because now we try to
51 manipulate per_cpu_ptr(wq->cpu_wq, 1), which is uninitialized.
52
53 So we need to establish an unchanging "slot" for single-thread workqueues
54 which will have a valid percpu allocation. Since alloc_percpu keys off of
55 cpu_possible_map, which must not change after initialization, make this
56 slot == first_cpu(cpu_possible_map).
57
58 Signed-off-by: Nathan Lynch <ntl@pobox.com>
59 Cc: <stable@kernel.org>
60 Signed-off-by: Andrew Morton <akpm@osdl.org>
61 Signed-off-by: Chris Wright <chrisw@sous-sol.org>
62 ---
63
64 --- linux-2.6.14.orig/kernel/workqueue.c 2006-01-30 16:39:01.000000000 -0500
65 +++ linux-2.6.14/kernel/workqueue.c 2006-01-30 16:39:57.000000000 -0500
66 @@ -27,7 +27,8 @@
67 #include <linux/kthread.h>
68
69 /*
70 - * The per-CPU workqueue (if single thread, we always use cpu 0's).
71 + * The per-CPU workqueue (if single thread, we always use the first
72 + * possible cpu).
73 *
74 * The sequence counters are for flush_scheduled_work(). It wants to wait
75 * until until all currently-scheduled works are completed, but it doesn't
76 @@ -67,6 +68,8 @@ struct workqueue_struct {
77 static DEFINE_SPINLOCK(workqueue_lock);
78 static LIST_HEAD(workqueues);
79
80 +static int singlethread_cpu;
81 +
82 /* If it's single threaded, it isn't in the list of workqueues. */
83 static inline int is_single_threaded(struct workqueue_struct *wq)
84 {
85 @@ -100,7 +103,7 @@ int fastcall queue_work(struct workqueue
86
87 if (!test_and_set_bit(0, &work->pending)) {
88 if (unlikely(is_single_threaded(wq)))
89 - cpu = 0;
90 + cpu = singlethread_cpu;
91 BUG_ON(!list_empty(&work->entry));
92 __queue_work(wq->cpu_wq + cpu, work);
93 ret = 1;
94 @@ -116,7 +119,7 @@ static void delayed_work_timer_fn(unsign
95 int cpu = smp_processor_id();
96
97 if (unlikely(is_single_threaded(wq)))
98 - cpu = 0;
99 + cpu = singlethread_cpu;
100
101 __queue_work(wq->cpu_wq + cpu, work);
102 }
103 @@ -264,8 +267,8 @@ void fastcall flush_workqueue(struct wor
104 might_sleep();
105
106 if (is_single_threaded(wq)) {
107 - /* Always use cpu 0's area. */
108 - flush_cpu_workqueue(wq->cpu_wq + 0);
109 + /* Always use first cpu's area. */
110 + flush_cpu_workqueue(wq->cpu_wq + singlethread_cpu);
111 } else {
112 int cpu;
113
114 @@ -317,7 +320,7 @@ struct workqueue_struct *__create_workqu
115 lock_cpu_hotplug();
116 if (singlethread) {
117 INIT_LIST_HEAD(&wq->list);
118 - p = create_workqueue_thread(wq, 0);
119 + p = create_workqueue_thread(wq, singlethread_cpu);
120 if (!p)
121 destroy = 1;
122 else
123 @@ -371,7 +374,7 @@ void destroy_workqueue(struct workqueue_
124 /* We don't need the distraction of CPUs appearing and vanishing. */
125 lock_cpu_hotplug();
126 if (is_single_threaded(wq))
127 - cleanup_workqueue_thread(wq, 0);
128 + cleanup_workqueue_thread(wq, singlethread_cpu);
129 else {
130 for_each_online_cpu(cpu)
131 cleanup_workqueue_thread(wq, cpu);
132 @@ -536,6 +539,7 @@ static int __devinit workqueue_cpu_callb
133
134 void init_workqueues(void)
135 {
136 + singlethread_cpu = first_cpu(cpu_possible_map);
137 hotcpu_notifier(workqueue_cpu_callback, 0);
138 keventd_wq = create_workqueue("events");
139 BUG_ON(!keventd_wq);

  ViewVC Help
Powered by ViewVC 1.1.20