Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1535730 > unrolled thread
| Started by | Vegard Nossum <vegard.nossum@gmail.com> |
|---|---|
| First post | 2016-12-05 00:10 +0100 |
| Last post | 2016-12-05 19:30 +0100 |
| Articles | 16 — 6 participants |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: bio linked list corruption. Vegard Nossum <vegard.nossum@gmail.com> - 2016-12-05 00:10 +0100
Re: bio linked list corruption. Vegard Nossum <vegard.nossum@gmail.com> - 2016-12-05 18:20 +0100
Re: bio linked list corruption. Dave Jones <davej@codemonkey.org.uk> - 2016-12-05 18:30 +0100
Re: bio linked list corruption. Linus Torvalds <torvalds@linux-foundation.org> - 2016-12-05 19:00 +0100
Re: bio linked list corruption. Vegard Nossum <vegard.nossum@gmail.com> - 2016-12-05 20:20 +0100
Re: bio linked list corruption. Linus Torvalds <torvalds@linux-foundation.org> - 2016-12-05 21:20 +0100
Re: bio linked list corruption. Linus Torvalds <torvalds@linux-foundation.org> - 2016-12-05 21:40 +0100
Re: bio linked list corruption. Vegard Nossum <vegard.nossum@gmail.com> - 2016-12-05 22:40 +0100
Re: bio linked list corruption. Vegard Nossum <vegard.nossum@gmail.com> - 2016-12-06 09:50 +0100
Re: bio linked list corruption. Peter Zijlstra <peterz@infradead.org> - 2016-12-06 09:20 +0100
Re: bio linked list corruption. Ingo Molnar <mingo@kernel.org> - 2016-12-06 09:40 +0100
Re: bio linked list corruption. Linus Torvalds <torvalds@linux-foundation.org> - 2016-12-06 18:00 +0100
Re: bio linked list corruption. Vegard Nossum <vegard.nossum@gmail.com> - 2016-12-05 21:20 +0100
Re: bio linked list corruption. Andy Lutomirski <luto@kernel.org> - 2016-12-05 19:20 +0100
Re: bio linked list corruption. Vegard Nossum <vegard.nossum@gmail.com> - 2016-12-05 19:30 +0100
Re: bio linked list corruption. Linus Torvalds <torvalds@linux-foundation.org> - 2016-12-05 19:30 +0100
| From | Vegard Nossum <vegard.nossum@gmail.com> |
|---|---|
| Date | 2016-12-05 00:10 +0100 |
| Subject | Re: bio linked list corruption. |
| Message-ID | <sKO4V-504-11@gated-at.bofh.it> |
On 23 November 2016 at 20:58, Dave Jones <davej@codemonkey.org.uk> wrote: > On Wed, Nov 23, 2016 at 02:34:19PM -0500, Dave Jones wrote: > > > [ 317.689216] BUG: Bad page state in process kworker/u8:8 pfn:4d8fd4 > > trace from just before this happened. Does this shed any light ? > > > > https://codemonkey.org.uk/junk/trace.txt > > crap, I just noticed the timestamps in the trace come from quite a bit > later. I'll tweak the code to do the taint checking/ftrace stop after > every syscall, that should narrow the window some more. FWIW I hit this as well: BUG: unable to handle kernel paging request at ffffffff81ff08b7 IP: [<ffffffff8135f2ea>] __lock_acquire.isra.32+0xda/0x1a30 PGD 461e067 PUD 461f063 PMD 1e001e1 Oops: 0003 [#1] PREEMPT SMP KASAN Dumping ftrace buffer: (ftrace buffer empty) CPU: 0 PID: 21744 Comm: trinity-c56 Tainted: G B 4.9.0-rc7+ #217 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.9.3-0-ge2fc41e-prebuilt.qemu-project.org 04/01/2014 task: ffff8801ee924080 task.stack: ffff8801bab88000 RIP: 0010:[<ffffffff8135f2ea>] [<ffffffff8135f2ea>] __lock_acquire.isra.32+0xda/0x1a30 RSP: 0018:ffff8801bab8f730 EFLAGS: 00010082 RAX: ffffffff81ff071f RBX: 0000000000000000 RCX: 0000000000000000 RDX: 0000000000000003 RSI: 0000000000000000 RDI: ffffffff85ae7d00 RBP: ffff8801bab8f7b0 R08: 0000000000000001 R09: 0000000000000000 R10: ffff8801e727fc40 R11: fffffbfff0b54ced R12: ffffffff85ae7d00 R13: ffffffff84912920 R14: ffff8801ee924080 R15: 0000000000000000 FS: 00007f37ee653700(0000) GS:ffff8801f6a00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: ffffffff81ff08b7 CR3: 00000001daa70000 CR4: 00000000000006f0 DR0: 00007f37ee465000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000600 Stack: ffff8801ee9247d0 0000000000000000 0000000100000000 ffff8801ee924080 ffff8801f6a201c0 ffff8801f6a201c0 0000000000000000 0000000000000001 ffff880100000000 ffff880100000000 ffff8801e727fc40 ffff8801ee924080 Call Trace: [<ffffffff81361751>] lock_acquire+0x141/0x2b0 [<ffffffff813530c0>] ? finish_wait+0xb0/0x180 [<ffffffff83c95b29>] _raw_spin_lock_irqsave+0x49/0x60 [<ffffffff813530c0>] ? finish_wait+0xb0/0x180 [<ffffffff813530c0>] finish_wait+0xb0/0x180 [<ffffffff81576227>] shmem_fault+0x4c7/0x6b0 [<ffffffff83a9b7cd>] ? p9_client_rpc+0x13d/0xf40 [<ffffffff81575d60>] ? shmem_getpage_gfp+0x1c90/0x1c90 [<ffffffff81fbe777>] ? radix_tree_next_chunk+0x4f7/0x840 [<ffffffff81352150>] ? wake_atomic_t_function+0x210/0x210 [<ffffffff815ad316>] __do_fault+0x206/0x410 [<ffffffff815ad110>] ? do_page_mkwrite+0x320/0x320 [<ffffffff815b9bcf>] handle_mm_fault+0x1cef/0x2a60 [<ffffffff815b8012>] ? handle_mm_fault+0x132/0x2a60 [<ffffffff815b7ee0>] ? __pmd_alloc+0x370/0x370 [<ffffffff81692e7e>] ? inode_add_bytes+0x10e/0x160 [<ffffffff8162de11>] ? memset+0x31/0x40 [<ffffffff815cba10>] ? find_vma+0x30/0x150 [<ffffffff812373a2>] __do_page_fault+0x452/0x9f0 [<ffffffff81ff071f>] ? iov_iter_init+0xaf/0x1d0 [<ffffffff81237bf5>] trace_do_page_fault+0x1e5/0x3a0 [<ffffffff8122a007>] do_async_page_fault+0x27/0xa0 [<ffffffff83c97618>] async_page_fault+0x28/0x30 [<ffffffff82059341>] ? strnlen_user+0x91/0x1a0 [<ffffffff8205931e>] ? strnlen_user+0x6e/0x1a0 [<ffffffff8157e038>] strndup_user+0x28/0xb0 [<ffffffff81d83c17>] SyS_add_key+0xc7/0x370 [<ffffffff81d83b50>] ? key_get_type_from_user.constprop.6+0xd0/0xd0 [<ffffffff815143ea>] ? __context_tracking_exit.part.4+0x3a/0x1e0 [<ffffffff81d83b50>] ? key_get_type_from_user.constprop.6+0xd0/0xd0 [<ffffffff8100524f>] do_syscall_64+0x1af/0x4d0 [<ffffffff83c96534>] entry_SYSCALL64_slow_path+0x25/0x25 Code: 89 4d b8 44 89 45 c0 89 4d c8 4c 89 55 d0 e8 ee c3 ff ff 48 85 c0 4c 8b 55 d0 8b 4d c8 44 8b 45 c0 4c 8b 4d b8 0f 84 c6 01 00 00 <3e> ff 80 98 01 00 00 49 8d be 48 07 00 00 48 ba 00 00 00 00 00 RIP [<ffffffff8135f2ea>] __lock_acquire.isra.32+0xda/0x1a30 I didn't read all the emails in this thread, the crash site looks identical to one of the earlier traces although the caller may be different. I think you can rule out btrfs in any case, probably block layer as well, since it looks like this comes from shmem. Vegard
[toc] | [next] | [standalone]
| From | Vegard Nossum <vegard.nossum@gmail.com> |
|---|---|
| Date | 2016-12-05 18:20 +0100 |
| Message-ID | <sL55L-7o6-3@gated-at.bofh.it> |
| In reply to | #1535730 |
On 5 December 2016 at 12:10, Vegard Nossum <vegard.nossum@gmail.com> wrote: > On 5 December 2016 at 00:04, Vegard Nossum <vegard.nossum@gmail.com> wrote: >> FWIW I hit this as well: >> >> BUG: unable to handle kernel paging request at ffffffff81ff08b7 >> IP: [<ffffffff8135f2ea>] __lock_acquire.isra.32+0xda/0x1a30 >> CPU: 0 PID: 21744 Comm: trinity-c56 Tainted: G B 4.9.0-rc7+ #217 > [...] > >> I think you can rule out btrfs in any case, probably block layer as >> well, since it looks like this comes from shmem. > > I should rather say that the VM runs on a 9p root filesystem and it > doesn't use/mount any block devices or disk-based filesystems. > > I have all the trinity logs for the crash if that's useful. I tried a > couple of runs with just the (at the time) in-progress syscalls but it > didn't turn up anything interesting. Otherwise it seems like a lot of > data to go through by hand. I've hit this another 7 times in the past ~3 hours. Three times the address being dereferenced has pointed to iov_iter_init+0xaf (even across a kernel rebuild), three times it has pointed to put_prev_entity+0x55, once to 0x800000008, and twice to 0x292. The fact that it would hit even one of those more than once across runs is pretty suspicious to me, although the ones that point to iov_iter_init and put_prev_entity point to "random" instructions in the sense that they are neither entry points nor return addresses. shmem_fault() was always on the stack, but it came from different syscalls: add_key(), newuname(), pipe2(), newstat(), fstat(), clock_settime(), mount(), etc. I also got this warning which is related: ------------[ cut here ]------------ WARNING: CPU: 9 PID: 25045 at lib/list_debug.c:59 __list_del_entry+0x14f/0x1d0 list_del corruption. prev->next should be ffff88014bdc79e8, but was ffff88014bfbfc60 Kernel panic - not syncing: panic_on_warn set ... CPU: 9 PID: 25045 Comm: trinity-c22 Not tainted 4.9.0-rc7+ #219 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014 ffff88014bdc7700 ffffffff81fb0861 ffffffff83e74b60 ffff88014bdc77d8 ffffffff84006c00 ffffffff847103e0 ffff88014bdc77c8 ffffffff81515244 0000000041b58ab3 ffffffff844e21c2 ffffffff81515061 ffffffff00000054 Call Trace: [<ffffffff81fb0861>] dump_stack+0x83/0xb2 [<ffffffff81515244>] panic+0x1e3/0x3ad [<ffffffff81515061>] ? percpu_up_read_preempt_enable.constprop.45+0xcb/0xcb [<ffffffff82016f7f>] ? __list_del_entry+0x14f/0x1d0 [<ffffffff812708bf>] __warn+0x1bf/0x1e0 [<ffffffff8135f2d2>] ? __lock_acquire.isra.32+0xc2/0x1a30 [<ffffffff8127098c>] warn_slowpath_fmt+0xac/0xd0 [<ffffffff812708e0>] ? __warn+0x1e0/0x1e0 [<ffffffff813530c0>] ? finish_wait+0xb0/0x180 [<ffffffff82016f7f>] __list_del_entry+0x14f/0x1d0 [<ffffffff813530c0>] ? finish_wait+0xb0/0x180 [<ffffffff813530cb>] finish_wait+0xbb/0x180 [<ffffffff81576227>] shmem_fault+0x4c7/0x6b0 [<ffffffff81574743>] ? shmem_getpage_gfp+0x673/0x1c90 [<ffffffff81575d60>] ? shmem_getpage_gfp+0x1c90/0x1c90 [<ffffffff81352150>] ? wake_atomic_t_function+0x210/0x210 [<ffffffff815ad316>] __do_fault+0x206/0x410 [<ffffffff815ad110>] ? do_page_mkwrite+0x320/0x320 [<ffffffff815b80ac>] ? handle_mm_fault+0x1cc/0x2a60 [<ffffffff815b8fd7>] handle_mm_fault+0x10f7/0x2a60 [<ffffffff815b8012>] ? handle_mm_fault+0x132/0x2a60 [<ffffffff81310a7f>] ? thread_group_cputime+0x49f/0x6e0 [<ffffffff815b7ee0>] ? __pmd_alloc+0x370/0x370 [<ffffffff81310a9c>] ? thread_group_cputime+0x4bc/0x6e0 [<ffffffff81310d2d>] ? thread_group_cputime_adjusted+0x6d/0xe0 [<ffffffff81237170>] ? __do_page_fault+0x220/0x9f0 [<ffffffff815cba10>] ? find_vma+0x30/0x150 [<ffffffff812373a2>] __do_page_fault+0x452/0x9f0 [<ffffffff81237bf5>] trace_do_page_fault+0x1e5/0x3a0 [<ffffffff8122a007>] do_async_page_fault+0x27/0xa0 [<ffffffff83c97618>] async_page_fault+0x28/0x30 [<ffffffff81fdec7c>] ? copy_user_generic_string+0x2c/0x40 [<ffffffff812b0303>] ? SyS_times+0x93/0x110 [<ffffffff812b0270>] ? do_sys_times+0x2b0/0x2b0 [<ffffffff812b0270>] ? do_sys_times+0x2b0/0x2b0 [<ffffffff8100524f>] do_syscall_64+0x1af/0x4d0 [<ffffffff83c96534>] entry_SYSCALL64_slow_path+0x25/0x25 ------------[ cut here ]------------ The warning shows that it made it past the list_empty_careful() check in finish_wait() but then bugs out on the &wait->task_list dereference. Anything stick out? Vegard
[toc] | [prev] | [next] | [standalone]
| From | Dave Jones <davej@codemonkey.org.uk> |
|---|---|
| Date | 2016-12-05 18:30 +0100 |
| Message-ID | <sL5fr-7r6-15@gated-at.bofh.it> |
| In reply to | #1536246 |
On Mon, Dec 05, 2016 at 06:09:29PM +0100, Vegard Nossum wrote:
> On 5 December 2016 at 12:10, Vegard Nossum <vegard.nossum@gmail.com> wrote:
> > On 5 December 2016 at 00:04, Vegard Nossum <vegard.nossum@gmail.com> wrote:
> >> FWIW I hit this as well:
> >>
> >> BUG: unable to handle kernel paging request at ffffffff81ff08b7
> >> IP: [<ffffffff8135f2ea>] __lock_acquire.isra.32+0xda/0x1a30
> >> CPU: 0 PID: 21744 Comm: trinity-c56 Tainted: G B 4.9.0-rc7+ #217
> > [...]
> >
> >> I think you can rule out btrfs in any case, probably block layer as
> >> well, since it looks like this comes from shmem.
> >
> > I should rather say that the VM runs on a 9p root filesystem and it
> > doesn't use/mount any block devices or disk-based filesystems.
> >
> > I have all the trinity logs for the crash if that's useful. I tried a
> > couple of runs with just the (at the time) in-progress syscalls but it
> > didn't turn up anything interesting. Otherwise it seems like a lot of
> > data to go through by hand.
>
> I've hit this another 7 times in the past ~3 hours.
>
> Three times the address being dereferenced has pointed to
> iov_iter_init+0xaf (even across a kernel rebuild), three times it has
> pointed to put_prev_entity+0x55, once to 0x800000008, and twice to
> 0x292. The fact that it would hit even one of those more than once
> across runs is pretty suspicious to me, although the ones that point
> to iov_iter_init and put_prev_entity point to "random" instructions in
> the sense that they are neither entry points nor return addresses.
>
> shmem_fault() was always on the stack, but it came from different
> syscalls: add_key(), newuname(), pipe2(), newstat(), fstat(),
> clock_settime(), mount(), etc.
> ------------[ cut here ]------------
> The warning shows that it made it past the list_empty_careful() check
> in finish_wait() but then bugs out on the &wait->task_list
> dereference.
I just pushed out the ftrace changes I made to Trinity that might help
you gather more clues.
Right now it's hardcoded to dump a trace to /boot/trace.txt when it
detects the kernel has become tainted.
Before a trinity run, I run this as root..
#!/bin/sh
cd /sys/kernel/debug/tracing/
echo 10000 > buffer_size_kb
echo function >> current_tracer
for i in $(cat /home/davej/blacklist-symbols)
do
echo $i >> set_ftrace_notrace
done
echo 1 >> tracing_on
blacklist-symbols is the more noisy stuff that pollutes traces.
Right now I use these: https://paste.fedoraproject.org/499794/14809582/
You may need to add some more.
(I'll get around to making all this scripting go away, and have trinity
just set this stuff up itself eventually)
Oh, and if you're not running as root, you might need a diff like below
so that trinity can stop the trace when it detects tainting.
Dave
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 8696ce6bf2f6..2d6c97e871e0 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -7217,7 +7217,7 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer)
trace_create_file("trace_clock", 0644, d_tracer, tr,
&trace_clock_fops);
- trace_create_file("tracing_on", 0644, d_tracer,
+ trace_create_file("tracing_on", 0666, d_tracer,
tr, &rb_simple_fops);
create_trace_options_dir(tr);
[toc] | [prev] | [next] | [standalone]
| From | Linus Torvalds <torvalds@linux-foundation.org> |
|---|---|
| Date | 2016-12-05 19:00 +0100 |
| Message-ID | <sL5Iu-7AR-11@gated-at.bofh.it> |
| In reply to | #1536246 |
[Multipart message — attachments visible in raw view] — view raw
On Mon, Dec 5, 2016 at 9:09 AM, Vegard Nossum <vegard.nossum@gmail.com> wrote:
>
> The warning shows that it made it past the list_empty_careful() check
> in finish_wait() but then bugs out on the &wait->task_list
> dereference.
>
> Anything stick out?
I hate that shmem waitqueue garbage. It's really subtle.
I think the problem is that "wake_up_all()" in shmem_fallocate()
doesn't necessarily wake up everything. It wakes up TASK_NORMAL -
which does include TASK_UNINTERRUPTIBLE, but doesn't actually mean
"everything on the list".
I think that what happens is that the waiters somehow move from
TASK_UNINTERRUPTIBLE to TASK_RUNNING early, and this means that
wake_up_all() will ignore them, leave them on the list, and now that
list on stack is no longer empty at the end.
And the way *THAT* can happen is that the task is on some *other*
waitqueue as well, and that other waiqueue wakes it up. That's not
impossible, you can certainly have people on wait-queues that still
take faults.
Or somebody just uses a directed wake_up_process() or something.
Since you apparently can recreate this fairly easily, how about trying
this stupid patch?
NOTE! This is entirely untested. I may have screwed this up entirely.
You get the idea, though - just remove the wait queue head from the
list - the list entries stay around, but nothing points to the stack
entry (that we're going to free) any more.
And add the warning to see if this actually ever triggers (and because
I'd like to see the callchain when it does, to see if it's another
waitqueue somewhere or what..)
Linus
[toc] | [prev] | [next] | [standalone]
| From | Vegard Nossum <vegard.nossum@gmail.com> |
|---|---|
| Date | 2016-12-05 20:20 +0100 |
| Message-ID | <sL6XT-81-3@gated-at.bofh.it> |
| In reply to | #1536285 |
[Multipart message — attachments visible in raw view] — view raw
On 5 December 2016 at 18:55, Linus Torvalds <torvalds@linux-foundation.org> wrote: > On Mon, Dec 5, 2016 at 9:09 AM, Vegard Nossum <vegard.nossum@gmail.com> wrote: >> >> The warning shows that it made it past the list_empty_careful() check >> in finish_wait() but then bugs out on the &wait->task_list >> dereference. >> >> Anything stick out? > > I hate that shmem waitqueue garbage. It's really subtle. > > I think the problem is that "wake_up_all()" in shmem_fallocate() > doesn't necessarily wake up everything. It wakes up TASK_NORMAL - > which does include TASK_UNINTERRUPTIBLE, but doesn't actually mean > "everything on the list". > > I think that what happens is that the waiters somehow move from > TASK_UNINTERRUPTIBLE to TASK_RUNNING early, and this means that > wake_up_all() will ignore them, leave them on the list, and now that > list on stack is no longer empty at the end. > > And the way *THAT* can happen is that the task is on some *other* > waitqueue as well, and that other waiqueue wakes it up. That's not > impossible, you can certainly have people on wait-queues that still > take faults. > > Or somebody just uses a directed wake_up_process() or something. > > Since you apparently can recreate this fairly easily, how about trying > this stupid patch? > > NOTE! This is entirely untested. I may have screwed this up entirely. > You get the idea, though - just remove the wait queue head from the > list - the list entries stay around, but nothing points to the stack > entry (that we're going to free) any more. > > And add the warning to see if this actually ever triggers (and because > I'd like to see the callchain when it does, to see if it's another > waitqueue somewhere or what..) ------------[ cut here ]------------ WARNING: CPU: 22 PID: 14012 at mm/shmem.c:2668 shmem_fallocate+0x9a7/0xac0 Kernel panic - not syncing: panic_on_warn set ... CPU: 22 PID: 14012 Comm: trinity-c73 Not tainted 4.9.0-rc7+ #220 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014 ffff8801e32af970 ffffffff81fb08c1 ffffffff83e74b60 ffff8801e32afa48 ffffffff83ed7600 ffffffff847103e0 ffff8801e32afa38 ffffffff81515244 0000000041b58ab3 ffffffff844e21da ffffffff81515061 ffffffff8151591e Call Trace: [<ffffffff81fb08c1>] dump_stack+0x83/0xb2 [<ffffffff81515244>] panic+0x1e3/0x3ad [<ffffffff812708bf>] __warn+0x1bf/0x1e0 [<ffffffff81270aac>] warn_slowpath_null+0x2c/0x40 [<ffffffff8157aef7>] shmem_fallocate+0x9a7/0xac0 [<ffffffff8167c6c0>] vfs_fallocate+0x350/0x620 [<ffffffff815ee5c2>] SyS_madvise+0x432/0x1290 [<ffffffff8100524f>] do_syscall_64+0x1af/0x4d0 [<ffffffff83c965b4>] entry_SYSCALL64_slow_path+0x25/0x25 ------------[ cut here ]------------ Attached a full log. Vegard
[toc] | [prev] | [next] | [standalone]
| From | Linus Torvalds <torvalds@linux-foundation.org> |
|---|---|
| Date | 2016-12-05 21:20 +0100 |
| Message-ID | <sL7TY-KS-7@gated-at.bofh.it> |
| In reply to | #1536351 |
[Multipart message — attachments visible in raw view] — view raw
On Mon, Dec 5, 2016 at 11:11 AM, Vegard Nossum <vegard.nossum@gmail.com> wrote:
>
> ------------[ cut here ]------------
> WARNING: CPU: 22 PID: 14012 at mm/shmem.c:2668 shmem_fallocate+0x9a7/0xac0
Ok, good. So that's confirmed as the cause of this problem.
And the call chain that I wanted is obviously completely
uninteresting, because it's call cghain on the other side (the page
fault side) that would show the nested wake queue behavior. I was just
being stupid about it.
I wonder if we have any other places where we just blithely assume
that "wake_up_all()" will actually empty the whole wait queue. It's
_usually_ true, but as noted, nested waiting does happen.
Anyway, can you try this patch instead? It should actually cause the
wake_up_all() to always remove all entries, and thus the WARN_ON()
should no longer happen (and I removed the "list_del()" hackery).
Linus
[toc] | [prev] | [next] | [standalone]
| From | Linus Torvalds <torvalds@linux-foundation.org> |
|---|---|
| Date | 2016-12-05 21:40 +0100 |
| Message-ID | <sL8dj-QU-19@gated-at.bofh.it> |
| In reply to | #1536389 |
[Multipart message — attachments visible in raw view] — view raw
Adding the scheduler people to the participants list, and re-attaching
the patch, because while this patch is internal to the VM code, the
issue itself is not.
There might well be other cases where somebody goes "wake_up_all()"
will wake everybody up, so I can put the wait queue head on the stack,
and then after I've woken people up I can return".
Ingo/PeterZ: the reason that does *not* work is that "wake_up_all()"
does make sure that everybody is woken up, but the usual autoremove
wake function only removes the wakeup entry if the process was woken
up by that particular wakeup. If something else had woken it up, the
entry remains on the list, and the waker in this case returned with
the wait head still containing entries.
Which is deadly when the wait queue head is on the stack.
So I'm wondering if we should make that "synchronous_wake_function()"
available generally, and maybe introduce a DEFINE_WAIT_SYNC() helper
that uses it.
Of course, I'm really hoping that this shmem.c use is the _only_ such
case. But I doubt it.
Comments?
Note for Ingo and Peter: this patch has not been tested at all. But
Vegard did test an earlier patch of mine that just verified that yes,
the issue really was that wait queue entries remained on the wait
queue head just as we were about to return and free it.
Linus
On Mon, Dec 5, 2016 at 12:10 PM, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
>
> Anyway, can you try this patch instead? It should actually cause the
> wake_up_all() to always remove all entries, and thus the WARN_ON()
> should no longer happen (and I removed the "list_del()" hackery).
>
> Linus
[toc] | [prev] | [next] | [standalone]
| From | Vegard Nossum <vegard.nossum@gmail.com> |
|---|---|
| Date | 2016-12-05 22:40 +0100 |
| Message-ID | <sL99o-1pH-39@gated-at.bofh.it> |
| In reply to | #1536397 |
On 5 December 2016 at 21:35, Linus Torvalds <torvalds@linux-foundation.org> wrote: > Note for Ingo and Peter: this patch has not been tested at all. But > Vegard did test an earlier patch of mine that just verified that yes, > the issue really was that wait queue entries remained on the wait > queue head just as we were about to return and free it. The second patch has been running for 1h+ without any problems of any kind. I should typically have seen 2 crashes by now. I'll let it run overnight to be sure. Vegard
[toc] | [prev] | [next] | [standalone]
| From | Vegard Nossum <vegard.nossum@gmail.com> |
|---|---|
| Date | 2016-12-06 09:50 +0100 |
| Message-ID | <sLjBL-8aU-21@gated-at.bofh.it> |
| In reply to | #1536445 |
On 5 December 2016 at 22:33, Vegard Nossum <vegard.nossum@gmail.com> wrote: > On 5 December 2016 at 21:35, Linus Torvalds > <torvalds@linux-foundation.org> wrote: >> Note for Ingo and Peter: this patch has not been tested at all. But >> Vegard did test an earlier patch of mine that just verified that yes, >> the issue really was that wait queue entries remained on the wait >> queue head just as we were about to return and free it. > > The second patch has been running for 1h+ without any problems of any > kind. I should typically have seen 2 crashes by now. I'll let it run > overnight to be sure. Alright, so nearly 12 hours later I don't see either the new warning or the original crash at all, so feel free to add: Tested-by: Vegard Nossum <vegard.nossum@oracle.com>. That said, my 8 VMs had all panicked in some way due to OOMs (which is new since v4.8), although some got page allocation stalls for >20s and died because "khugepaged blocked for more than 120 seconds", others got "Out of memory and no killable processes". Vegard
[toc] | [prev] | [next] | [standalone]
| From | Peter Zijlstra <peterz@infradead.org> |
|---|---|
| Date | 2016-12-06 09:20 +0100 |
| Message-ID | <sLj8J-81i-9@gated-at.bofh.it> |
| In reply to | #1536397 |
On Mon, Dec 05, 2016 at 12:35:52PM -0800, Linus Torvalds wrote:
> Adding the scheduler people to the participants list, and re-attaching
> the patch, because while this patch is internal to the VM code, the
> issue itself is not.
>
> There might well be other cases where somebody goes "wake_up_all()"
> will wake everybody up, so I can put the wait queue head on the stack,
> and then after I've woken people up I can return".
>
> Ingo/PeterZ: the reason that does *not* work is that "wake_up_all()"
> does make sure that everybody is woken up, but the usual autoremove
> wake function only removes the wakeup entry if the process was woken
> up by that particular wakeup. If something else had woken it up, the
> entry remains on the list, and the waker in this case returned with
> the wait head still containing entries.
>
> Which is deadly when the wait queue head is on the stack.
Yes, very much so.
> So I'm wondering if we should make that "synchronous_wake_function()"
> available generally, and maybe introduce a DEFINE_WAIT_SYNC() helper
> that uses it.
We could also do some debug code that tracks the ONSTACK ness and warns
on autoremove. Something like the below, equally untested.
>
> Of course, I'm really hoping that this shmem.c use is the _only_ such
> case. But I doubt it.
$ git grep DECLARE_WAIT_QUEUE_HEAD_ONSTACK | wc -l
28
---
diff --git a/include/linux/wait.h b/include/linux/wait.h
index 2408e8d5c05c..199faaa89847 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -39,6 +39,9 @@ struct wait_bit_queue {
struct __wait_queue_head {
spinlock_t lock;
struct list_head task_list;
+#ifdef CONFIG_DEBUG_WAITQUEUE
+ int onstack;
+#endif
};
typedef struct __wait_queue_head wait_queue_head_t;
@@ -56,9 +59,18 @@ struct task_struct;
#define DECLARE_WAITQUEUE(name, tsk) \
wait_queue_t name = __WAITQUEUE_INITIALIZER(name, tsk)
-#define __WAIT_QUEUE_HEAD_INITIALIZER(name) { \
+#ifdef CONFIG_DEBUG_WAITQUEUE
+#define ___WAIT_QUEUE_ONSTACK(onstack) .onstack = (onstack),
+#else
+#define ___WAIT_QUEUE_ONSTACK(onstack)
+#endif
+
+#define ___WAIT_QUEUE_HEAD_INITIALIZER(name, onstack) { \
.lock = __SPIN_LOCK_UNLOCKED(name.lock), \
- .task_list = { &(name).task_list, &(name).task_list } }
+ .task_list = { &(name).task_list, &(name).task_list }, \
+ ___WAIT_QUEUE_ONSTACK(onstack) }
+
+#define __WAIT_QUEUE_HEAD_INITIALIZER(name) ___WAIT_QUEUE_HEAD_INITIALIZER(name, 0)
#define DECLARE_WAIT_QUEUE_HEAD(name) \
wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)
@@ -80,11 +92,12 @@ extern void __init_waitqueue_head(wait_queue_head_t *q, const char *name, struct
#ifdef CONFIG_LOCKDEP
# define __WAIT_QUEUE_HEAD_INIT_ONSTACK(name) \
- ({ init_waitqueue_head(&name); name; })
+ ({ init_waitqueue_head(&name); (name).onstack = 1; name; })
# define DECLARE_WAIT_QUEUE_HEAD_ONSTACK(name) \
wait_queue_head_t name = __WAIT_QUEUE_HEAD_INIT_ONSTACK(name)
#else
-# define DECLARE_WAIT_QUEUE_HEAD_ONSTACK(name) DECLARE_WAIT_QUEUE_HEAD(name)
+# define DECLARE_WAIT_QUEUE_HEAD_ONSTACK(name) \
+ wait_queue_head_t name = ___WAIT_QUEUE_HEAD_INITIALIZER(name, 1)
#endif
static inline void init_waitqueue_entry(wait_queue_t *q, struct task_struct *p)
diff --git a/kernel/sched/wait.c b/kernel/sched/wait.c
index 9453efe9b25a..746d00117d08 100644
--- a/kernel/sched/wait.c
+++ b/kernel/sched/wait.c
@@ -156,6 +156,13 @@ void __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr_exclusive)
}
EXPORT_SYMBOL_GPL(__wake_up_sync); /* For internal use only */
+static inline void prepare_debug(wait_queue_head_t *q, wait_queue_t *wait)
+{
+#ifdef CONFIG_DEBUG_WAITQUEUE
+ WARN_ON_ONCE(q->onstack && wait->func == autoremove_wake_function)
+#endif
+}
+
/*
* Note: we use "set_current_state()" _after_ the wait-queue add,
* because we need a memory barrier there on SMP, so that any
@@ -178,6 +185,7 @@ prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state)
if (list_empty(&wait->task_list))
__add_wait_queue(q, wait);
set_current_state(state);
+ prepare_debug(q, wait);
spin_unlock_irqrestore(&q->lock, flags);
}
EXPORT_SYMBOL(prepare_to_wait);
@@ -192,6 +200,7 @@ prepare_to_wait_exclusive(wait_queue_head_t *q, wait_queue_t *wait, int state)
if (list_empty(&wait->task_list))
__add_wait_queue_tail(q, wait);
set_current_state(state);
+ prepare_debug(q, wait);
spin_unlock_irqrestore(&q->lock, flags);
}
EXPORT_SYMBOL(prepare_to_wait_exclusive);
@@ -235,6 +244,7 @@ long prepare_to_wait_event(wait_queue_head_t *q, wait_queue_t *wait, int state)
}
set_current_state(state);
}
+ prepare_debug(q, wait);
spin_unlock_irqrestore(&q->lock, flags);
return ret;
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 9bb7d825ba14..af2ef22a5b2b 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1235,6 +1235,14 @@ config DEBUG_PI_LIST
If unsure, say N.
+config DEBUG_WAITQUEUE
+ bool "Debug waitqueue"
+ depends on DEBUG_KERNEL
+ help
+ Enable this to do sanity checking on waitqueue usage
+
+ If unsure, say N.
+
config DEBUG_SG
bool "Debug SG table operations"
depends on DEBUG_KERNEL
[toc] | [prev] | [next] | [standalone]
| From | Ingo Molnar <mingo@kernel.org> |
|---|---|
| Date | 2016-12-06 09:40 +0100 |
| Message-ID | <sLjs6-87p-25@gated-at.bofh.it> |
| In reply to | #1536743 |
* Peter Zijlstra <peterz@infradead.org> wrote:
> $ git grep DECLARE_WAIT_QUEUE_HEAD_ONSTACK | wc -l
> 28
This debug facility looks sensible. A couple of minor suggestions:
> --- a/include/linux/wait.h
> +++ b/include/linux/wait.h
> @@ -39,6 +39,9 @@ struct wait_bit_queue {
> struct __wait_queue_head {
> spinlock_t lock;
> struct list_head task_list;
> +#ifdef CONFIG_DEBUG_WAITQUEUE
> + int onstack;
> +#endif
The structure will pack better in the debug-enabled case if 'onstack' is next to
'lock', as spinlock_t is 4 bytes on many architectures.
> -#define __WAIT_QUEUE_HEAD_INITIALIZER(name) { \
> +#ifdef CONFIG_DEBUG_WAITQUEUE
> +#define ___WAIT_QUEUE_ONSTACK(onstack) .onstack = (onstack),
> +#else
> +#define ___WAIT_QUEUE_ONSTACK(onstack)
> +#endif
Please help readers by showing the internal structure of the definition:
#ifdef CONFIG_DEBUG_WAITQUEUE
# define ___WAIT_QUEUE_ONSTACK(onstack) .onstack = (onstack),
#else
# define ___WAIT_QUEUE_ONSTACK(onstack)
#endif
> +static inline void prepare_debug(wait_queue_head_t *q, wait_queue_t *wait)
> +{
> +#ifdef CONFIG_DEBUG_WAITQUEUE
> + WARN_ON_ONCE(q->onstack && wait->func == autoremove_wake_function)
> +#endif
> +}
I'd name this debug_waitqueue_check() or such - as the 'prepare' is a bit
misleadig (we don't prepare debugging, we do the debug check here).
> +config DEBUG_WAITQUEUE
> + bool "Debug waitqueue"
> + depends on DEBUG_KERNEL
I'd name it DEBUG_SCHED_WAITQUEUE=y and I'd also make it depend on
CONFIG_DEBUG_SCHED.
LGTM otherwise!
Thanks,
Ingo
[toc] | [prev] | [next] | [standalone]
| From | Linus Torvalds <torvalds@linux-foundation.org> |
|---|---|
| Date | 2016-12-06 18:00 +0100 |
| Message-ID | <sLrfX-4AN-29@gated-at.bofh.it> |
| In reply to | #1536743 |
On Tue, Dec 6, 2016 at 12:16 AM, Peter Zijlstra <peterz@infradead.org> wrote:
>>
>> Of course, I'm really hoping that this shmem.c use is the _only_ such
>> case. But I doubt it.
>
> $ git grep DECLARE_WAIT_QUEUE_HEAD_ONSTACK | wc -l
> 28
Hmm. Most of them seem to be ok, because they use "wait_event()",
which will always remove itself from the wait-queue. And they do it
from the place that allocates the wait-queue.
IOW, the mm/shmem.c case really was fairly special, because it just
did "prepare_to_wait()", and then did a finish_wait() - and not in the
thread that allocated it on the stack.
So it's really that "some _other_ thread allocated the waitqueue on
the stack, and now we're doing a wait on it" that is bad.
So the normal pattern seems to be:
- allocate wq on the stack
- pass it on to a waker
- wait for it
and that's ok, because as part of "wait for it" we will also be
cleaning things up.
The reason mm/shmem.c was buggy was that it did
- allocate wq on the stack
- pass it on to somebody else to wait for
- wake it up
and *that* is buggy, because it's the waiter, not the waker, that
normally cleans things up.
Is there some good way to find this kind of pattern automatically, I wonder....
Linus
[toc] | [prev] | [next] | [standalone]
| From | Vegard Nossum <vegard.nossum@gmail.com> |
|---|---|
| Date | 2016-12-05 21:20 +0100 |
| Message-ID | <sL7TY-KS-9@gated-at.bofh.it> |
| In reply to | #1536351 |
On 5 December 2016 at 20:11, Vegard Nossum <vegard.nossum@gmail.com> wrote: > On 5 December 2016 at 18:55, Linus Torvalds > <torvalds@linux-foundation.org> wrote: >> On Mon, Dec 5, 2016 at 9:09 AM, Vegard Nossum <vegard.nossum@gmail.com> wrote: >> Since you apparently can recreate this fairly easily, how about trying >> this stupid patch? >> >> NOTE! This is entirely untested. I may have screwed this up entirely. >> You get the idea, though - just remove the wait queue head from the >> list - the list entries stay around, but nothing points to the stack >> entry (that we're going to free) any more. >> >> And add the warning to see if this actually ever triggers (and because >> I'd like to see the callchain when it does, to see if it's another >> waitqueue somewhere or what..) > > ------------[ cut here ]------------ > WARNING: CPU: 22 PID: 14012 at mm/shmem.c:2668 shmem_fallocate+0x9a7/0xac0 > Kernel panic - not syncing: panic_on_warn set ... So I noticed that panic_on_warn just after sending the email and I've been waiting for it it to trigger again. The warning has triggered twice more without panic_on_warn set and I haven't seen any crash yet. Vegard
[toc] | [prev] | [next] | [standalone]
| From | Andy Lutomirski <luto@kernel.org> |
|---|---|
| Date | 2016-12-05 19:20 +0100 |
| Message-ID | <sL61P-80t-7@gated-at.bofh.it> |
| In reply to | #1535730 |
On Sun, Dec 4, 2016 at 3:04 PM, Vegard Nossum <vegard.nossum@gmail.com> wrote:
> On 23 November 2016 at 20:58, Dave Jones <davej@codemonkey.org.uk> wrote:
>> On Wed, Nov 23, 2016 at 02:34:19PM -0500, Dave Jones wrote:
>>
>> > [ 317.689216] BUG: Bad page state in process kworker/u8:8 pfn:4d8fd4
>> > trace from just before this happened. Does this shed any light ?
>> >
>> > https://codemonkey.org.uk/junk/trace.txt
>>
>> crap, I just noticed the timestamps in the trace come from quite a bit
>> later. I'll tweak the code to do the taint checking/ftrace stop after
>> every syscall, that should narrow the window some more.
>
> FWIW I hit this as well:
>
> BUG: unable to handle kernel paging request at ffffffff81ff08b7
We really ought to improve this message. If nothing else, it should
say whether it was a read, a write, or an instruction fetch.
> IP: [<ffffffff8135f2ea>] __lock_acquire.isra.32+0xda/0x1a30
> PGD 461e067 PUD 461f063
> PMD 1e001e1
Too lazy to manually decode this right now, but I don't think it matters.
> Oops: 0003 [#1] PREEMPT SMP KASAN
Note this is SMP, but that just means CONFIG_SMP=y. Vegard, how many
CPUs does your kernel think you have?
> RIP: 0010:[<ffffffff8135f2ea>] [<ffffffff8135f2ea>]
> __lock_acquire.isra.32+0xda/0x1a30
> RSP: 0018:ffff8801bab8f730 EFLAGS: 00010082
> RAX: ffffffff81ff071f RBX: 0000000000000000 RCX: 0000000000000000
RAX points to kernel text.
> Code: 89 4d b8 44 89 45 c0 89 4d c8 4c 89 55 d0 e8 ee c3 ff ff 48 85
> c0 4c 8b 55 d0 8b 4d c8 44 8b 45 c0 4c 8b 4d b8 0f 84 c6 01 00 00 <3e>
> ff 80 98 01 00 00 49 8d be 48 07 00 00 48 ba 00 00 00 00 00
2b: 3e ff 80 98 01 00 00 incl %ds:*0x198(%rax) <--
trapping instruction
That's very strange. I think this is:
atomic_inc((atomic_t *)&class->ops);
but my kernel contains:
3cb4: f0 ff 80 98 01 00 00 lock incl 0x198(%rax)
So your kernel has been smp-alternatived. That 3e comes from
alternatives_smp_unlock. If you're running on SMP with UP
alternatives, things will break.
What's your kernel command line? Can we have your entire kernel log from boot?
Adding Borislav, since he's the guru for this code.
[toc] | [prev] | [next] | [standalone]
| From | Vegard Nossum <vegard.nossum@gmail.com> |
|---|---|
| Date | 2016-12-05 19:30 +0100 |
| Message-ID | <sL6bv-84q-9@gated-at.bofh.it> |
| In reply to | #1536294 |
[Multipart message — attachments visible in raw view] — view raw
On 5 December 2016 at 19:11, Andy Lutomirski <luto@kernel.org> wrote: > On Sun, Dec 4, 2016 at 3:04 PM, Vegard Nossum <vegard.nossum@gmail.com> wrote: >> On 23 November 2016 at 20:58, Dave Jones <davej@codemonkey.org.uk> wrote: >>> On Wed, Nov 23, 2016 at 02:34:19PM -0500, Dave Jones wrote: >>> >>> > [ 317.689216] BUG: Bad page state in process kworker/u8:8 pfn:4d8fd4 >>> > trace from just before this happened. Does this shed any light ? >>> > >>> > https://codemonkey.org.uk/junk/trace.txt >>> >>> crap, I just noticed the timestamps in the trace come from quite a bit >>> later. I'll tweak the code to do the taint checking/ftrace stop after >>> every syscall, that should narrow the window some more. >> >> FWIW I hit this as well: >> >> BUG: unable to handle kernel paging request at ffffffff81ff08b7 > > We really ought to improve this message. If nothing else, it should > say whether it was a read, a write, or an instruction fetch. > >> IP: [<ffffffff8135f2ea>] __lock_acquire.isra.32+0xda/0x1a30 >> PGD 461e067 PUD 461f063 >> PMD 1e001e1 > > Too lazy to manually decode this right now, but I don't think it matters. > >> Oops: 0003 [#1] PREEMPT SMP KASAN > > Note this is SMP, but that just means CONFIG_SMP=y. Vegard, how many > CPUs does your kernel think you have? My first crash was running on a 1-CPU guest (not intentionally, but because of a badly configured qemu). I'm honestly surprised it triggered at all with 1 CPU, but I guess it shows that it's not a true concurrency issue at least! > >> RIP: 0010:[<ffffffff8135f2ea>] [<ffffffff8135f2ea>] >> __lock_acquire.isra.32+0xda/0x1a30 >> RSP: 0018:ffff8801bab8f730 EFLAGS: 00010082 >> RAX: ffffffff81ff071f RBX: 0000000000000000 RCX: 0000000000000000 > > RAX points to kernel text. Yes, it's somewhere in the middle of iov_iter_init() -- other crashes also had put_prev_entity(), a null pointer, and some garbage values I couldn't identify. > >> Code: 89 4d b8 44 89 45 c0 89 4d c8 4c 89 55 d0 e8 ee c3 ff ff 48 85 >> c0 4c 8b 55 d0 8b 4d c8 44 8b 45 c0 4c 8b 4d b8 0f 84 c6 01 00 00 <3e> >> ff 80 98 01 00 00 49 8d be 48 07 00 00 48 ba 00 00 00 00 00 > > 2b: 3e ff 80 98 01 00 00 incl %ds:*0x198(%rax) <-- > trapping instruction > > That's very strange. I think this is: > > atomic_inc((atomic_t *)&class->ops); > > but my kernel contains: > > 3cb4: f0 ff 80 98 01 00 00 lock incl 0x198(%rax) > > So your kernel has been smp-alternatived. That 3e comes from > alternatives_smp_unlock. If you're running on SMP with UP > alternatives, things will break. Yes, indeed. It was running on 1 CPU by mistake and still triggered the bug. The crashes started really pouring in once I got my qemu fixed. Just to reassure you, here's another crash which shows it's using the correct instruction on an actual multicore guest: BUG: unable to handle kernel paging request at 00000003030001de IP: [<ffffffff8135f2ea>] __lock_acquire.isra.32+0xda/0x1a30 PGD 183fd2067 PUD 0 Oops: 0002 [#1] PREEMPT SMP KASAN Dumping ftrace buffer: (ftrace buffer empty) CPU: 23 PID: 9584 Comm: trinity-c104 Not tainted 4.9.0-rc7+ #219 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014 task: ffff880189f68000 task.stack: ffff88017fe50000 RIP: 0010:[<ffffffff8135f2ea>] [<ffffffff8135f2ea>] __lock_acquire.isra.32+0xda/0x1a30 RSP: 0018:ffff88017fe575e0 EFLAGS: 00010002 RAX: 0000000303000046 RBX: 0000000000000000 RCX: 0000000000000000 [...] Code: 89 4d b8 44 89 45 c0 89 4d c8 4c 89 55 d0 e8 ee c3 ff ff 48 85 c0 4c 8b 55 d0 8b 4d c8 44 8b 45 c0 4c 8b 4d b8 0f 84 c6 01 00 00 <f0> ff 80 98 01 00 00 49 8d be 48 07 00 00 48 ba 00 00 00 00 00 RIP [<ffffffff8135f2ea>] __lock_acquire.isra.32+0xda/0x1a30 RSP <ffff88017fe575e0> CR2: 00000003030001de ---[ end trace 2846425104eb6141 ]--- Kernel panic - not syncing: Fatal exception ------------[ cut here ]------------ 2b:* f0 ff 80 98 01 00 00 lock incl 0x198(%rax) <-- trapping instruction > What's your kernel command line? Can we have your entire kernel log from boot? Just in case you still want this, I've attached the boot log for the "true SMP" guest above. Vegard
[toc] | [prev] | [next] | [standalone]
| From | Linus Torvalds <torvalds@linux-foundation.org> |
|---|---|
| Date | 2016-12-05 19:30 +0100 |
| Message-ID | <sL6bv-84q-17@gated-at.bofh.it> |
| In reply to | #1536294 |
On Mon, Dec 5, 2016 at 10:11 AM, Andy Lutomirski <luto@kernel.org> wrote:
>
> So your kernel has been smp-alternatived. That 3e comes from
> alternatives_smp_unlock. If you're running on SMP with UP
> alternatives, things will break.
I'm assuming he's just running in a VM with a single CPU.
The problem that I pointed out with assuming wake_up_all() actually
removes all wait queue entries does not depend on SMP. The race is
much more fundamental and long-lived.
Linus
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web