/[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 - (hide annotations) (download) (as text)
Tue Mar 14 13:34:17 2006 UTC (14 years, 8 months ago) by johnm
File MIME type: text/x-diff
File size: 5061 byte(s)
2.6.14-11, rebase against local tree
1 johnm 328 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