/[linux-patches]/genpatches-2.6/tags/2.6.15-2/1910_workqueue-cpu-offline.patch
Gentoo

Contents of /genpatches-2.6/tags/2.6.15-2/1910_workqueue-cpu-offline.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 259 - (show annotations) (download)
Wed Jan 11 21:46:01 2006 UTC (9 years, 5 months ago) by dsd
File size: 4108 byte(s)
2.6.15-2 release
1 From stable-bounces@linux.kernel.org Sun Jan 8 01:09:03 2006
2 Message-Id: <200601080905.k0895NZ1015408@shell0.pdx.osdl.net>
3 To: torvalds@osdl.org
4 From: akpm@osdl.org
5 Date: Sun, 08 Jan 2006 01:05:12 -0800
6 Cc: ntl@pobox.com, stable@kernel.org
7 Subject: [PATCH] fix workqueue oops during cpu offline
8
9 From: Nathan Lynch <ntl@pobox.com>
10
11 Use first_cpu(cpu_possible_map) for the single-thread workqueue case. We
12 used to hardcode 0, but that broke on systems where !cpu_possible(0) when
13 workqueue_struct->cpu_workqueue_struct was changed from a static array to
14 alloc_percpu.
15
16 Commit id bce61dd49d6ba7799be2de17c772e4c701558f14 ("Fix hardcoded cpu=0 in
17 workqueue for per_cpu_ptr() calls") fixed that for Ben's funky sparc64
18 system, but it regressed my Power5. Offlining cpu 0 oopses upon the next
19 call to queue_work for a single-thread workqueue, because now we try to
20 manipulate per_cpu_ptr(wq->cpu_wq, 1), which is uninitialized.
21
22 So we need to establish an unchanging "slot" for single-thread workqueues
23 which will have a valid percpu allocation. Since alloc_percpu keys off of
24 cpu_possible_map, which must not change after initialization, make this
25 slot == first_cpu(cpu_possible_map).
26
27 Signed-off-by: Nathan Lynch <ntl@pobox.com>
28 Cc: <stable@kernel.org>
29 Signed-off-by: Andrew Morton <akpm@osdl.org>
30 Signed-off-by: Chris Wright <chrisw@sous-sol.org>
31 ---
32
33 kernel/workqueue.c | 16 ++++++++++------
34 1 files changed, 10 insertions(+), 6 deletions(-)
35
36 Index: linux-2.6.15.y/kernel/workqueue.c
37 ===================================================================
38 --- linux-2.6.15.y.orig/kernel/workqueue.c
39 +++ linux-2.6.15.y/kernel/workqueue.c
40 @@ -29,7 +29,8 @@
41 #include <linux/kthread.h>
42
43 /*
44 - * The per-CPU workqueue (if single thread, we always use cpu 0's).
45 + * The per-CPU workqueue (if single thread, we always use the first
46 + * possible cpu).
47 *
48 * The sequence counters are for flush_scheduled_work(). It wants to wait
49 * until until all currently-scheduled works are completed, but it doesn't
50 @@ -69,6 +70,8 @@ struct workqueue_struct {
51 static DEFINE_SPINLOCK(workqueue_lock);
52 static LIST_HEAD(workqueues);
53
54 +static int singlethread_cpu;
55 +
56 /* If it's single threaded, it isn't in the list of workqueues. */
57 static inline int is_single_threaded(struct workqueue_struct *wq)
58 {
59 @@ -102,7 +105,7 @@ int fastcall queue_work(struct workqueue
60
61 if (!test_and_set_bit(0, &work->pending)) {
62 if (unlikely(is_single_threaded(wq)))
63 - cpu = any_online_cpu(cpu_online_map);
64 + cpu = singlethread_cpu;
65 BUG_ON(!list_empty(&work->entry));
66 __queue_work(per_cpu_ptr(wq->cpu_wq, cpu), work);
67 ret = 1;
68 @@ -118,7 +121,7 @@ static void delayed_work_timer_fn(unsign
69 int cpu = smp_processor_id();
70
71 if (unlikely(is_single_threaded(wq)))
72 - cpu = any_online_cpu(cpu_online_map);
73 + cpu = singlethread_cpu;
74
75 __queue_work(per_cpu_ptr(wq->cpu_wq, cpu), work);
76 }
77 @@ -267,7 +270,7 @@ void fastcall flush_workqueue(struct wor
78
79 if (is_single_threaded(wq)) {
80 /* Always use first cpu's area. */
81 - flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, any_online_cpu(cpu_online_map)));
82 + flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, singlethread_cpu));
83 } else {
84 int cpu;
85
86 @@ -320,7 +323,7 @@ struct workqueue_struct *__create_workqu
87 lock_cpu_hotplug();
88 if (singlethread) {
89 INIT_LIST_HEAD(&wq->list);
90 - p = create_workqueue_thread(wq, any_online_cpu(cpu_online_map));
91 + p = create_workqueue_thread(wq, singlethread_cpu);
92 if (!p)
93 destroy = 1;
94 else
95 @@ -374,7 +377,7 @@ void destroy_workqueue(struct workqueue_
96 /* We don't need the distraction of CPUs appearing and vanishing. */
97 lock_cpu_hotplug();
98 if (is_single_threaded(wq))
99 - cleanup_workqueue_thread(wq, any_online_cpu(cpu_online_map));
100 + cleanup_workqueue_thread(wq, singlethread_cpu);
101 else {
102 for_each_online_cpu(cpu)
103 cleanup_workqueue_thread(wq, cpu);
104 @@ -543,6 +546,7 @@ static int __devinit workqueue_cpu_callb
105
106 void init_workqueues(void)
107 {
108 + singlethread_cpu = first_cpu(cpu_possible_map);
109 hotcpu_notifier(workqueue_cpu_callback, 0);
110 keventd_wq = create_workqueue("events");
111 BUG_ON(!keventd_wq);

  ViewVC Help
Powered by ViewVC 1.1.20