| From stable-bounces@linux.kernel.org Wed Dec 6 20:45:28 2006 |
| Message-Id: <200612070439.kB74ddJq030058@shell0.pdx.osdl.net> |
| To: torvalds@osdl.org |
| From: akpm@osdl.org |
| Date: Wed, 06 Dec 2006 20:39:39 -0800 |
| Cc: akpm@osdl.org, zach@vmware.com, mingo@elte.hu, stable@kernel.org, caglar@pardus.org.tr |
| Subject: softirq: remove BUG_ONs which can incorrectly trigger |
| |
| From: Zachary Amsden <zach@vmware.com> |
| |
| It is possible to have tasklets get scheduled before softirqd has had a chance |
| to spawn on all CPUs. This is totally harmless; after success during action |
| CPU_UP_PREPARE, action CPU_ONLINE will be called, which immediately wakes |
| softirqd on the appropriate CPU to process the already pending tasklets. So |
| there is no danger of having a missed wakeup for any tasklets that were |
| already pending. |
| |
| In particular, i386 is affected by this during startup, and is visible when |
| using a very large initrd; during the time it takes for the initrd to be |
| decompressed, a timer IRQ can come in and schedule RCU callbacks. It is also |
| possible that resending of a hardware IRQ via a softirq triggers the same bug. |
| |
| Because of different timing conditions, this shows up in all emulators and |
| virtual machines tested, including Xen, VMware, Virtual PC, and Qemu. It is |
| also possible to trigger on native hardware with a large enough initrd, |
| although I don't have a reliable case demonstrating that. |
| |
| Signed-off-by: Zachary Amsden <zach@vmware.com> |
| Cc: <caglar@pardus.org.tr> |
| Cc: Ingo Molnar <mingo@elte.hu> |
| Cc: <stable@kernel.org> |
| Signed-off-by: Andrew Morton <akpm@osdl.org> |
| Signed-off-by: Chris Wright <chrisw@sous-sol.org> |
| --- |
| |
| kernel/softirq.c | 2 -- |
| 1 file changed, 2 deletions(-) |
| |
| --- linux-2.6.19.orig/kernel/softirq.c |
| +++ linux-2.6.19/kernel/softirq.c |
| @@ -574,8 +574,6 @@ static int __cpuinit cpu_callback(struct |
| |
| switch (action) { |
| case CPU_UP_PREPARE: |
| - BUG_ON(per_cpu(tasklet_vec, hotcpu).list); |
| - BUG_ON(per_cpu(tasklet_hi_vec, hotcpu).list); |
| p = kthread_create(ksoftirqd, hcpu, "ksoftirqd/%d", hotcpu); |
| if (IS_ERR(p)) { |
| printk("ksoftirqd for %i failed\n", hotcpu); |