2006-09-24 17:00:29

by Jean-Marc Saffroy

[permalink] [raw]
Subject: oops in :snd_pcm_oss:resample_expand+0x19c/0x1f0

Hello folks,

I hit the following bug a few times on my desktop:

Unable to handle kernel paging request at ffffc200100e4466 RIP:
[<ffffffff882234cc>] :snd_pcm_oss:resample_expand+0x19c/0x1f0
PGD 37919067 PUD 37918067 PMD 37f5b067 PTE 0
Oops: 0002 [1] SMP
CPU 0
Modules linked in: nvidia nfsd exportfs lockd nfs_acl sunrpc button ac
battery ipv6 nls_iso8859_1 nls_cp437 vfat fat usb_storage tuner
snd_intel8x0 snd_ac97_codec snd_ac97_bus bttv snd_pcm_oss video_buf
firmware_class snd_mixer_oss ir_common snd_pcm compat_ioctl32 i2c_algo_bit
snd_timer i2c_nforce2 psmouse snd btcx_risc tveeprom videodev v4l1_compat
v4l2_common i2c_core ohci_hcd ehci_hcd forcedeth serio_raw soundcore
snd_page_alloc pcspkr evdev thermal processor fan generic amd74xx sata_nv
libata ide_cd sd_mod ide_generic raid0 ext3 jbd mbcache ide_disk ide_core
sr_mod scsi_mod cdrom dm_mirror dm_snapshot dm_mod raid1 md_mod
Pid: 4860, comm: firefox-bin Tainted: P 2.6.18 #3
RIP: 0010:[<ffffffff882234cc>] [<ffffffff882234cc>] :snd_pcm_oss:resample_expand+0x19c/0x1f0
RSP: 0000:ffff81002c243d88 EFLAGS: 00010207
RAX: 0000000000000000 RBX: 000000000000024d RCX: 000000000000007d
RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffffc20000028e0e
RBP: ffff81002c243de8 R08: 00000000000002eb R09: ffffc200100e4466
R10: 000000000000007d R11: 0000000000000000 R12: 0000000000000000
R13: ffff81003f2e9f58 R14: 0000000000000004 R15: ffff81003f2e9f7c
FS: 00002ad1bd680ae0(0000) GS:ffffffff80586000(0063) knlGS:00000000f73676c0
CS: 0010 DS: 002b ES: 002b CR0: 000000008005003b
CR2: ffffc200100e4466 CR3: 000000002bc6b000 CR4: 00000000000006e0
Process firefox-bin (pid: 4860, threadinfo ffff81002c242000, task ffff810037a1a080)
Stack: ffff810025646000 0000040000001806 ffff81002412e140 ffff81001fe532c0
ffff81003f2e9ec0 0000000000000004 0000000125135c00 0000000000001806
0000000000000400 ffff81003f2e9ec0 ffff81002412e140 ffff81001fe532c0
Call Trace:
[<ffffffff8822387b>] :snd_pcm_oss:rate_transfer+0x5b/0x80
[<ffffffff88221438>] :snd_pcm_oss:snd_pcm_plug_write_transfer+0xb8/0x100
[<ffffffff88221319>] :snd_pcm_oss:snd_pcm_plug_client_channels_buf+0x59/0xc0
[<ffffffff8821f4b5>] :snd_pcm_oss:snd_pcm_oss_write2+0x95/0x100
[<ffffffff882207e6>] :snd_pcm_oss:snd_pcm_oss_write+0x1b6/0x250
[<ffffffff80215a22>] vfs_write+0xe2/0x1a0
[<ffffffff80216320>] sys_write+0x50/0x90
[<ffffffff8026480e>] ia32_sysret+0x0/0xa

Code: 66 41 89 11 4d 01 f1 41 8d 40 01 41 03 5d 00 85 c0 0f 8f 6d
RIP [<ffffffff882234cc>] :snd_pcm_oss:resample_expand+0x19c/0x1f0
RSP <ffff81002c243d88>

Yes yes, I know the kernel is tainted "P" (courtesy of the infamous Nvidia
module), so flame me if you want, but some investigation leads me to think
it could be an issue in core kernel modules, so read on if you still want
the gory details. ;-)

The kernel is vanilla 2.6.18 on Debian etch, the box is a dual core Athlon
in x86-64 mode (in case you didn't notice the long pointers ;-). The
offending process is a chroot'ed IA32 Firefox. At first I suspected a
problem with 32-bit compatibility, but stack traces below and source code
suggest the problem could be different:

- CPU #0 crashes in resample_expand() at line 116:

116 *dst = val;

The target address is at ffffc200100e4466, which looks like a vmalloc'ed
buffer (according to Documentation/x86_64/mm.txt).

- CPU #1 is somewhere down vfree() called by snd_pcm_oss_change_params(),
at line 1010:

1010 vfree(runtime->oss.buffer);
1011 runtime->oss.buffer = vmalloc(runtime->oss.period_bytes);

Now it really looks like it *could* be a race between two threads using
the same device, maybe the same buffers somehow, but I'm getting lost in
the data structures, so help from knowledgeable people would be welcome.

I keep a crash dump from kdump, below are the stack traces from the crash
command; I can post more results if requested. The stack frames on CPU #0
between 1 and 7 seem to me to be bogus.

Oh and I wish I could use gdb on a kdump core. :-)

%%%%%%% crash> bt -loa

PID: 4860 TASK: ffff810037a1a080 CPU: 0 COMMAND: "firefox-bin"
#0 [ffff81002c243aa0] crash_kexec at ffffffff802a855b
/home/saffroy/kernel/linux-2.6.18/kernel/kexec.c: 1062
#1 [ffff81002c243b28] resample_expand at ffffffff882234cc
/home/saffroy/kernel/linux-2.6.18/sound/core/oss/rate.c: 116
#2 [ffff81002c243b70] __die at ffffffff80268c23
/home/saffroy/kernel/linux-2.6.18/arch/x86_64/kernel/traps.c: 561
#3 [ffff81002c243bc0] do_page_fault at ffffffff8026a887
/home/saffroy/kernel/linux-2.6.18/arch/x86_64/mm/fault.c: 579
#4 [ffff81002c243bd0] snd_pcm_do_reset at ffffffff881e612e
/home/saffroy/kernel/linux-2.6.18/sound/core/pcm_native.c: 1253
#5 [ffff81002c243c60] mutex_unlock at ffffffff80266b69
/home/saffroy/kernel/linux-2.6.18/kernel/mutex.c: 117
#6 [ffff81002c243c70] snd_pcm_common_ioctl1 at ffffffff881e9e9d
/home/saffroy/kernel/linux-2.6.18/include/sound/core.h: 158
#7 [ffff81002c243cd0] error_exit at ffffffff8026374d
/home/saffroy/kernel/linux-2.6.18/include/linux/bitops.h: 42
[exception RIP: resample_expand+412]
RIP: ffffffff882234cc RSP: ffff81002c243d88 RFLAGS: 00010207
RAX: 0000000000000000 RBX: 000000000000024d RCX: 000000000000007d
RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffffc20000028e0e
RBP: ffff81002c243de8 R8: 00000000000002eb R9: ffffc200100e4466
R10: 000000000000007d R11: 0000000000000000 R12: 0000000000000000
R13: ffff81003f2e9f58 R14: 0000000000000004 R15: ffff81003f2e9f7c
ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0000
#8 [ffff81002c243df0] rate_transfer at ffffffff8822387b
/home/saffroy/kernel/linux-2.6.18/sound/core/oss/rate.c: 281
#9 [ffff81002c243e30] snd_pcm_plug_write_transfer at ffffffff88221438
/home/saffroy/kernel/linux-2.6.18/sound/core/oss/pcm_plugin.c: 594
#10 [ffff81002c243e40] snd_pcm_plug_client_channels_buf at
ffffffff88221319
/home/saffroy/kernel/linux-2.6.18/sound/core/oss/pcm_plugin.c: 555
#11 [ffff81002c243e80] snd_pcm_oss_write2 at ffffffff8821f4b5
/home/saffroy/kernel/linux-2.6.18/sound/core/oss/pcm_oss.c: 1284
#12 [ffff81002c243ec0] snd_pcm_oss_write at ffffffff882207e6
/home/saffroy/kernel/linux-2.6.18/sound/core/oss/pcm_oss.c: 1342
#13 [ffff81002c243f00] vfs_write at ffffffff80215a22
/home/saffroy/kernel/linux-2.6.18/fs/read_write.c: 316
#14 [ffff81002c243f40] sys_write at ffffffff80216320
/home/saffroy/kernel/linux-2.6.18/fs/read_write.c: 369
RIP: 00000000f7e2f3a1 RSP: 00000000ffd1b284 RFLAGS: 00000293
RAX: 0000000000000004 RBX: ffffffff8026480e RCX: 000000000ac13178
RDX: 0000000000002000 RSI: 00000000ffd1b2a0 RDI: 0000000000000000
RBP: 00000000ffd1b2c8 R8: ffffffffffffff10 R9: 00000000f756eff4
R10: 0000000000000002 R11: 0000000000000002 R12: 0000000000000000
R13: 0000000000000000 R14: 0000000000000000 R15: 000000000000003e
ORIG_RAX: 0000000000000004 CS: 0023 SS: 002b

PID: 5220 TASK: ffff81001ee6b830 CPU: 1 COMMAND: "firefox-bin"
#0 [ffff81003ffbff20] crash_nmi_callback at ffffffff8027b317
include2/asm/atomic.h: 117
#1 [ffff81003ffbff30] do_nmi at ffffffff80269411
/home/saffroy/kernel/linux-2.6.18/arch/x86_64/kernel/nmi.c: 599
#2 [ffff81003ffbff50] nmi at ffffffff80268857
/home/saffroy/arch/x86_64/kernel/entry.S
[exception RIP: __smp_call_function+118]
RIP: ffffffff80277df6 RSP: ffff8100205fdb78 RFLAGS: 00000202
RAX: 0000000000000000 RBX: 0000000000000001 RCX: 0000000000000001
RDX: 00000000000c08fc RSI: 0000000000000000 RDI: 0000000000000000
RBP: ffff8100205fdbb8 R8: 0000000000000000 R9: 0000000000000000
R10: 0000000000018b59 R11: 0000000000000001 R12: 0000000000000001
R13: ffffffff80277cd0 R14: 0000000000000000 R15: ffff810037918008
ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0000
WARNING: possibly bogus exception frame
--- <exception stack> ---
#3 [ffff8100205fdb78] __smp_call_function at ffffffff80277df6
include2/asm/processor.h: 396
#4 [ffff8100205fdbc0] smp_call_function at ffffffff80277f42
include2/asm/spinlock.h: 62
#5 [ffff8100205fdbf0] on_each_cpu at ffffffff8028fa8f
/home/saffroy/kernel/linux-2.6.18/kernel/softirq.c: 630
#6 [ffff8100205fdc20] flush_tlb_all at ffffffff80277c0c
/home/saffroy/kernel/linux-2.6.18/arch/x86_64/kernel/smp.c: 285
#7 [ffff8100205fdc30] unmap_vm_area at ffffffff80255b87
/home/saffroy/kernel/linux-2.6.18/mm/vmalloc.c: 85
#8 [ffff8100205fdc38] init_level4_pgt at ffffffff80201c28
#9 [ffff8100205fdca0] __remove_vm_area at ffffffff802be3c8
/home/saffroy/kernel/linux-2.6.18/mm/vmalloc.c: 285
#10 [ffff8100205fdcc0] remove_vm_area at ffffffff802be780
include2/asm/spinlock.h: 130
#11 [ffff8100205fdce0] __vunmap at ffffffff802be7f5
/home/saffroy/kernel/linux-2.6.18/mm/vmalloc.c: 326
#12 [ffff8100205fdd10] vfree at ffffffff802be92f
/home/saffroy/kernel/linux-2.6.18/mm/vmalloc.c: 368
#13 [ffff8100205fdd20] snd_pcm_oss_change_params at ffffffff8821e99b
/home/saffroy/kernel/linux-2.6.18/sound/core/oss/pcm_oss.c: 1011
#14 [ffff8100205fde60] snd_pcm_oss_get_active_substream at
ffffffff8821f10e
/home/saffroy/kernel/linux-2.6.18/sound/core/oss/pcm_oss.c: 1039
#15 [ffff8100205fde90] snd_pcm_oss_get_rate at ffffffff8821f151
/home/saffroy/kernel/linux-2.6.18/sound/core/oss/pcm_oss.c: 1636
#16 [ffff8100205fdea0] snd_pcm_oss_set_channels at ffffffff8821f229
/home/saffroy/kernel/linux-2.6.18/sound/core/oss/pcm_oss.c: 1660
#17 [ffff8100205fdeb0] snd_pcm_oss_ioctl at ffffffff8821fd6c
/home/saffroy/kernel/linux-2.6.18/sound/core/oss/pcm_oss.c: 2409
#18 [ffff8100205fdf10] compat_sys_ioctl at ffffffff802e3a81
/home/saffroy/kernel/linux-2.6.18/fs/compat.c: 426
#19 [ffff8100205fdf30] compat_sys_fcntl64 at ffffffff802e2508
/home/saffroy/kernel/linux-2.6.18/fs/compat.c: 585
RIP: 00000000f7504904 RSP: 00000000b9a62088 RFLAGS: 00000246
RAX: 0000000000000036 RBX: ffffffff8026480e RCX: 00000000c0045002
RDX: 00000000b9a620f4 RSI: 0000000000000000 RDI: 0000000000000000
RBP: 00000000b9a620e8 R8: ffffffffffffffed R9: 0000000000000001
R10: 0000000000000001 R11: 00000000b9a622dc R12: 0000000000000000
R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
ORIG_RAX: 0000000000000036 CS: 0023 SS: 002b


Cheers,

--
[email protected]


2006-09-24 17:39:03

by Lee Revell

[permalink] [raw]
Subject: Re: oops in :snd_pcm_oss:resample_expand+0x19c/0x1f0

On Sun, 2006-09-24 at 19:01 +0200, Jean-Marc Saffroy wrote:
> Yes yes, I know the kernel is tainted "P" (courtesy of the infamous
> Nvidia module), so flame me if you want, but some investigation leads
> me to think it could be an issue in core kernel modules, so read on if
> you still want the gory details. ;-)
>

Please don't post tainted Oops reports to LKML. It's not a political
issue, it's a technical one - a tainted kernel CANNOT be debugged.

Reproduce with an untainted kernel and repost.

Lee

2006-09-24 19:04:12

by Jean-Marc Saffroy

[permalink] [raw]
Subject: Re: oops in :snd_pcm_oss:resample_expand+0x19c/0x1f0

On Sun, 24 Sep 2006, Jean-Marc Saffroy wrote:

> On Sun, 2006-09-24 at 19:01 +0200, Jean-Marc Saffroy wrote:
>> Yes yes, I know the kernel is tainted "P" (courtesy of the infamous
>> Nvidia module), so flame me if you want, but some investigation leads
>> me to think it could be an issue in core kernel modules, so read on if
>> you still want the gory details. ;-)
>
> Please don't post tainted Oops reports to LKML. It's not a political
> issue, it's a technical one - a tainted kernel CANNOT be debugged.

Thank you for flaming. ;-) I thought the lines above would lead some
people to read on and post an enlightening answer to the implicit question
that followed, so I'll restate it below.

> Reproduce with an untainted kernel and repost.

Ok, I'll try.

In the mean time, maybe someone can try to answer my original question,
that was: is there a race between snd_pcm_oss_change_params() reallocating
a buffer and resample_expand() using another (possibly the same)?

Now I hope that my mail client does not taint the question as well. ;-)


Cheers,

--
[email protected]

2006-09-24 20:54:31

by Andrew Morton

[permalink] [raw]
Subject: Re: oops in :snd_pcm_oss:resample_expand+0x19c/0x1f0

On Sun, 24 Sep 2006 19:01:27 +0200 (CEST)
Jean-Marc Saffroy <[email protected]> wrote:

> Hello folks,
>
> I hit the following bug a few times on my desktop:
>
> Unable to handle kernel paging request at ffffc200100e4466 RIP:
> [<ffffffff882234cc>] :snd_pcm_oss:resample_expand+0x19c/0x1f0
>
> ...
>
> I keep a crash dump from kdump,

Whoa. Impressed. Which distro are you using and how did you go about this
and how much fuss was it to set up?

> Oh and I wish I could use gdb on a kdump core. :-)

Would be nice, but this is much better than what we usually get, no?

> %%%%%%% crash> bt -loa
>
> PID: 4860 TASK: ffff810037a1a080 CPU: 0 COMMAND: "firefox-bin"
> #0 [ffff81002c243aa0] crash_kexec at ffffffff802a855b
> /home/saffroy/kernel/linux-2.6.18/kernel/kexec.c: 1062
> #1 [ffff81002c243b28] resample_expand at ffffffff882234cc
> /home/saffroy/kernel/linux-2.6.18/sound/core/oss/rate.c: 116
> #2 [ffff81002c243b70] __die at ffffffff80268c23
> /home/saffroy/kernel/linux-2.6.18/arch/x86_64/kernel/traps.c: 561
> #3 [ffff81002c243bc0] do_page_fault at ffffffff8026a887
> /home/saffroy/kernel/linux-2.6.18/arch/x86_64/mm/fault.c: 579
> #4 [ffff81002c243bd0] snd_pcm_do_reset at ffffffff881e612e
> /home/saffroy/kernel/linux-2.6.18/sound/core/pcm_native.c: 1253
> #5 [ffff81002c243c60] mutex_unlock at ffffffff80266b69
> /home/saffroy/kernel/linux-2.6.18/kernel/mutex.c: 117
> #6 [ffff81002c243c70] snd_pcm_common_ioctl1 at ffffffff881e9e9d
> /home/saffroy/kernel/linux-2.6.18/include/sound/core.h: 158
> #7 [ffff81002c243cd0] error_exit at ffffffff8026374d
> /home/saffroy/kernel/linux-2.6.18/include/linux/bitops.h: 42
> [exception RIP: resample_expand+412]
> RIP: ffffffff882234cc RSP: ffff81002c243d88 RFLAGS: 00010207
> RAX: 0000000000000000 RBX: 000000000000024d RCX: 000000000000007d
> RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffffc20000028e0e
> RBP: ffff81002c243de8 R8: 00000000000002eb R9: ffffc200100e4466
> R10: 000000000000007d R11: 0000000000000000 R12: 0000000000000000
> R13: ffff81003f2e9f58 R14: 0000000000000004 R15: ffff81003f2e9f7c
> ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0000
> #8 [ffff81002c243df0] rate_transfer at ffffffff8822387b
> /home/saffroy/kernel/linux-2.6.18/sound/core/oss/rate.c: 281
> #9 [ffff81002c243e30] snd_pcm_plug_write_transfer at ffffffff88221438
> /home/saffroy/kernel/linux-2.6.18/sound/core/oss/pcm_plugin.c: 594
> #10 [ffff81002c243e40] snd_pcm_plug_client_channels_buf at
> ffffffff88221319
> /home/saffroy/kernel/linux-2.6.18/sound/core/oss/pcm_plugin.c: 555
> #11 [ffff81002c243e80] snd_pcm_oss_write2 at ffffffff8821f4b5
> /home/saffroy/kernel/linux-2.6.18/sound/core/oss/pcm_oss.c: 1284
> #12 [ffff81002c243ec0] snd_pcm_oss_write at ffffffff882207e6
> /home/saffroy/kernel/linux-2.6.18/sound/core/oss/pcm_oss.c: 1342
> #13 [ffff81002c243f00] vfs_write at ffffffff80215a22
> /home/saffroy/kernel/linux-2.6.18/fs/read_write.c: 316
> #14 [ffff81002c243f40] sys_write at ffffffff80216320
> /home/saffroy/kernel/linux-2.6.18/fs/read_write.c: 369
> RIP: 00000000f7e2f3a1 RSP: 00000000ffd1b284 RFLAGS: 00000293
> RAX: 0000000000000004 RBX: ffffffff8026480e RCX: 000000000ac13178
> RDX: 0000000000002000 RSI: 00000000ffd1b2a0 RDI: 0000000000000000
> RBP: 00000000ffd1b2c8 R8: ffffffffffffff10 R9: 00000000f756eff4
> R10: 0000000000000002 R11: 0000000000000002 R12: 0000000000000000
> R13: 0000000000000000 R14: 0000000000000000 R15: 000000000000003e
> ORIG_RAX: 0000000000000004 CS: 0023 SS: 002b
>
> PID: 5220 TASK: ffff81001ee6b830 CPU: 1 COMMAND: "firefox-bin"
> #0 [ffff81003ffbff20] crash_nmi_callback at ffffffff8027b317
> include2/asm/atomic.h: 117
> #1 [ffff81003ffbff30] do_nmi at ffffffff80269411
> /home/saffroy/kernel/linux-2.6.18/arch/x86_64/kernel/nmi.c: 599
> #2 [ffff81003ffbff50] nmi at ffffffff80268857
> /home/saffroy/arch/x86_64/kernel/entry.S
> [exception RIP: __smp_call_function+118]
> RIP: ffffffff80277df6 RSP: ffff8100205fdb78 RFLAGS: 00000202
> RAX: 0000000000000000 RBX: 0000000000000001 RCX: 0000000000000001
> RDX: 00000000000c08fc RSI: 0000000000000000 RDI: 0000000000000000
> RBP: ffff8100205fdbb8 R8: 0000000000000000 R9: 0000000000000000
> R10: 0000000000018b59 R11: 0000000000000001 R12: 0000000000000001
> R13: ffffffff80277cd0 R14: 0000000000000000 R15: ffff810037918008
> ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0000
> WARNING: possibly bogus exception frame
> --- <exception stack> ---
> #3 [ffff8100205fdb78] __smp_call_function at ffffffff80277df6
> include2/asm/processor.h: 396
> #4 [ffff8100205fdbc0] smp_call_function at ffffffff80277f42
> include2/asm/spinlock.h: 62
> #5 [ffff8100205fdbf0] on_each_cpu at ffffffff8028fa8f
> /home/saffroy/kernel/linux-2.6.18/kernel/softirq.c: 630
> #6 [ffff8100205fdc20] flush_tlb_all at ffffffff80277c0c
> /home/saffroy/kernel/linux-2.6.18/arch/x86_64/kernel/smp.c: 285
> #7 [ffff8100205fdc30] unmap_vm_area at ffffffff80255b87
> /home/saffroy/kernel/linux-2.6.18/mm/vmalloc.c: 85
> #8 [ffff8100205fdc38] init_level4_pgt at ffffffff80201c28
> #9 [ffff8100205fdca0] __remove_vm_area at ffffffff802be3c8
> /home/saffroy/kernel/linux-2.6.18/mm/vmalloc.c: 285
> #10 [ffff8100205fdcc0] remove_vm_area at ffffffff802be780
> include2/asm/spinlock.h: 130
> #11 [ffff8100205fdce0] __vunmap at ffffffff802be7f5
> /home/saffroy/kernel/linux-2.6.18/mm/vmalloc.c: 326
> #12 [ffff8100205fdd10] vfree at ffffffff802be92f
> /home/saffroy/kernel/linux-2.6.18/mm/vmalloc.c: 368
> #13 [ffff8100205fdd20] snd_pcm_oss_change_params at ffffffff8821e99b
> /home/saffroy/kernel/linux-2.6.18/sound/core/oss/pcm_oss.c: 1011
> #14 [ffff8100205fde60] snd_pcm_oss_get_active_substream at
> ffffffff8821f10e
> /home/saffroy/kernel/linux-2.6.18/sound/core/oss/pcm_oss.c: 1039
> #15 [ffff8100205fde90] snd_pcm_oss_get_rate at ffffffff8821f151
> /home/saffroy/kernel/linux-2.6.18/sound/core/oss/pcm_oss.c: 1636
> #16 [ffff8100205fdea0] snd_pcm_oss_set_channels at ffffffff8821f229
> /home/saffroy/kernel/linux-2.6.18/sound/core/oss/pcm_oss.c: 1660
> #17 [ffff8100205fdeb0] snd_pcm_oss_ioctl at ffffffff8821fd6c
> /home/saffroy/kernel/linux-2.6.18/sound/core/oss/pcm_oss.c: 2409
> #18 [ffff8100205fdf10] compat_sys_ioctl at ffffffff802e3a81
> /home/saffroy/kernel/linux-2.6.18/fs/compat.c: 426
> #19 [ffff8100205fdf30] compat_sys_fcntl64 at ffffffff802e2508
> /home/saffroy/kernel/linux-2.6.18/fs/compat.c: 585
> RIP: 00000000f7504904 RSP: 00000000b9a62088 RFLAGS: 00000246
> RAX: 0000000000000036 RBX: ffffffff8026480e RCX: 00000000c0045002
> RDX: 00000000b9a620f4 RSI: 0000000000000000 RDI: 0000000000000000
> RBP: 00000000b9a620e8 R8: ffffffffffffffed R9: 0000000000000001
> R10: 0000000000000001 R11: 00000000b9a622dc R12: 0000000000000000
> R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
> ORIG_RAX: 0000000000000036 CS: 0023 SS: 002b
>

[from other mail]

> is there a race between snd_pcm_oss_change_params() reallocating
> a buffer and resample_expand() using another (possibly the same)?

It does rather look like that.

2006-09-24 22:03:13

by Jean-Marc Saffroy

[permalink] [raw]
Subject: Re: oops in :snd_pcm_oss:resample_expand+0x19c/0x1f0

On Sun, 24 Sep 2006, Andrew Morton wrote:

>> I keep a crash dump from kdump,
>
> Whoa. Impressed. Which distro are you using and how did you go about this
> and how much fuss was it to set up?

Well, it sure didn't work right out of the box... But it's not that hard,
really: the main problems are lack of proper end-user docs and packaging,
as usual. A serial console on another PC very much helped in
troubleshooting problems (eg. my kdump kernel's initrd was initially too
large), but it's not required (though it's always a nice thing to have
anyway).

The basic instructions for setting up kdump are here:
http://lse.sourceforge.net/kdump/kdump-test-reports/test-plan.txt

I followed them, and also had to:
- reduce the uncompressed size of my initramfs (was 50+ MB initially, now
ca. 22MB), by listing only the required modules (lsmod w/ some hand
picking), see /etc/initramfs-tools/initramfs.conf
- reserve more RAM for the kdump kernel (now I use "crashkernel=96M@16M")

The distro is the AMD64 Debian etch, with two vanilla 2.6.18 kernels: one
"regular" SMP kernel with CONFIG_KEXEC=y, which is what I use, and one UP
kernel with CONFIG_PROC_VMCORE=y and a different load address, which is
activated on a crash; other than that they are the same.

The crude script below is run at boot time and configures kdump properly
for me. All oopses invoke panic ("kernel.panic_on_oops = 1" in
/etc/sysctl.conf), and thus the kdump kernel is activated. This kernel
boots on the very same root fs, runs the script below again, this time to
save the dump and reboot to the regular kernel. I did not try to have the
kdump kernel reset the vga console, so it stays in graphic mode and shows
garbage until the final reboot.

Now from an oops to being back to work, I would say it takes about 2-3
minutes (the longer part is the cold reboot, then the 30" timeout on the
Windows loader ;-)). I would certainly not do kernel development on my
desktop (backups? what backups?), but oopses do occur from time to time
(oh the joys of SMP on a desktop), and it's great to have a dump the first
time I see one.

>> Oh and I wish I could use gdb on a kdump core. :-)
>
> Would be nice, but this is much better than what we usually get, no?

I'm used to having LKCD for debugging at work (on IA64), it has raised my
expectations. :-)

But using gdb would be so much nicer, and I'm sure we're close to being
able to use it, it's probably only a matter of messing a bit with the ELF
image provided by kdump (it's really a good old core dump): ie. remapping
vmalloc'ed memory pages, so modules can be accessed, and ideally adding
processor context for each task (currently there is one per CPU). Crash
does all this stuff internally and has other nice commands, but I don't
find it quite as comfortable as gdb (with a few good scripts gdb would
certainly be on par with crash).

Now I hope you're converted!


Cheers,

--
[email protected]

#! /bin/bash
#
### BEGIN INIT INFO
# Provides: kdump
# Required-Start:
# Required-Stop:
# Default-Start: S
# Default-Stop:
### END INIT INFO
#
# This script configures a kdump kernel, or saves a dump and reboot.
#

_echo() {
echo "kdump: $@"
logger -p daemon.notice "kdump: $@"
echo "$(date) $@" >> /var/log/kdump.log
}

if grep -q crashkernel /proc/cmdline ; then
_echo "Configuring kdump kernel..."
_opts="$(sed -e 's,crashkernel=[^ ]*,,' /proc/cmdline)"
if kexec -p -t elf-x86_64 --args-linux \
--append="${_opts} init 1 irqpoll maxcpus=1" \
--initrd=/boot/initrd.img-kdump \
/boot/vmlinux-kdump
then
_echo "Successfully configured kdump kernel."
else
_echo "Failed to configure kdump kernel!"
fi
fi

if grep -q irqpoll /proc/cmdline ; then
_dump=/var/dump/dump-$(date +%F_%T)
_echo "Saving kernel dump under ${_dump}..."
cp /proc/vmcore "${_dump}"
rc=$?
ls -l /proc/vmcore "${_dump}"
chgrp adm "${_dump}"
chmod g+r "${_dump}"
_echo "Done saving kernel dump (rc=$rc), rebooting..."
reboot
fi

2006-09-25 15:32:14

by Vivek Goyal

[permalink] [raw]
Subject: Re: oops in :snd_pcm_oss:resample_expand+0x19c/0x1f0

On Mon, Sep 25, 2006 at 12:03:59AM +0200, Jean-Marc Saffroy wrote:
> On Sun, 24 Sep 2006, Andrew Morton wrote:
>
> >>I keep a crash dump from kdump,
> >
> >Whoa. Impressed. Which distro are you using and how did you go about this
> >and how much fuss was it to set up?
>
> Well, it sure didn't work right out of the box... But it's not that hard,
> really: the main problems are lack of proper end-user docs and packaging,
> as usual.

Hi Jean,

Thanks for trying out kdump. Things are still in state of flux when it
comes to packaging and I am hoping that its a matter of few more months
and things will be in a much better shape.

A lot of kdump functionality is in user space when it comes to configuring
kdump, saving the core dump, filtering the image and then finally doing the
analysis. Complete user space automation is still being implemented by
distros and issues are being resolved.

One of the issues is how to bring all the distros on the same platform.
SuSE and RedHat are doing quite some amount of automation for using kdump.
For example, the small script you wrote for saving the dump, is already
part of Fedora and SuSE and will be available in RHEL. I have no idea
what's going on in debian when it comes to packaging.

> A serial console on another PC very much helped in
> troubleshooting problems (eg. my kdump kernel's initrd was initially too
> large), but it's not required (though it's always a nice thing to have
> anyway).
>
> The basic instructions for setting up kdump are here:
> http://lse.sourceforge.net/kdump/kdump-test-reports/test-plan.txt
>

More docs:

- Documentation/kdump/kdump.txt
- Distros (SuSE, RedHat) are now also packaging a README file in
/usr/share/doc.... They are also putting together some man page
info for kexec sytem call.

> I followed them, and also had to:
> - reduce the uncompressed size of my initramfs (was 50+ MB initially, now
> ca. 22MB), by listing only the required modules (lsmod w/ some hand
> picking), see /etc/initramfs-tools/initramfs.conf

Hmm.. This looks like another packaging issue. Now we are automating
the process, so that a custom initrd is generated for kdump kernel
and dump will be saved from the initrd itself. This custom initrd will be
only big enough contain the functionality to perform the job of bringing
the dump device up and saving the dump. User shall have to just say
"service kdump start" and initrd will be generated and kdump kernel will
be loaded into the memory.

Developers from NEC are also working on providing a capability to filter
the dump so that final core size is small and managable. In fact this
filtering also can be done from initrd itself.

> - reserve more RAM for the kdump kernel (now I use "crashkernel=96M@16M")

Looks like big initramfs and running the init scripts in second kernel might
be taking some toll. We have been able to take dumps successfully by reserving
64MB on x86_64 boxes. Now with dump capturing capability from initrd, it
should become even better as we don't have to run user space init scripts
reducing memory pressure.

>
> The distro is the AMD64 Debian etch, with two vanilla 2.6.18 kernels: one
> "regular" SMP kernel with CONFIG_KEXEC=y, which is what I use, and one UP
> kernel with CONFIG_PROC_VMCORE=y and a different load address, which is
> activated on a crash; other than that they are the same.

Now we are also looking at a completely relocatable kernel so that the need
to build a separate kernel for dumping purposes is gone. Few weeks back
Eric posted the patches on LKML for RFC and testing purposes. We have been
testing out those patches and fixing few bugs. In a couple of weeks we
should be able to re-post the patches for another round of review. So
things should become even better once relocatable kernel is in.

>
> The crude script below is run at boot time and configures kdump properly
> for me. All oopses invoke panic ("kernel.panic_on_oops = 1" in
> /etc/sysctl.conf), and thus the kdump kernel is activated. This kernel
> boots on the very same root fs, runs the script below again, this time to
> save the dump and reboot to the regular kernel. I did not try to have the
> kdump kernel reset the vga console, so it stays in graphic mode and shows
> garbage until the final reboot.

Now latest kexec-tools has one patch to re-initialize frame buffer over
kdump boot but I am not sure what can we do if we are in X at the time
of crash? One suggestion was that at-least just blink the keyboard lights
while dump is being saved.

So at this point of time, I am not sure how can we reset the display if
user was in graphic mode at the time of crash.
>
> Now from an oops to being back to work, I would say it takes about 2-3
> minutes (the longer part is the cold reboot, then the 30" timeout on the
> Windows loader ;-)). I would certainly not do kernel development on my
> desktop (backups? what backups?), but oopses do occur from time to time
> (oh the joys of SMP on a desktop), and it's great to have a dump the first
> time I see one.
>
> >>Oh and I wish I could use gdb on a kdump core. :-)
> >

Currently we can use gdb but only for linearly mapped region. You are right
its just a matter of re-generating the elf headers and remap the vmalloc
areas to enable module debugging in gdb. I can not do it after the crash
so probably the best place would be do it in user space. A program can
read /proc/vmcore and regenerate the headers for enabling module debugging
with gdb.

> >Would be nice, but this is much better than what we usually get, no?
>
> I'm used to having LKCD for debugging at work (on IA64), it has raised my
> expectations. :-)
>
> But using gdb would be so much nicer, and I'm sure we're close to being
> able to use it, it's probably only a matter of messing a bit with the ELF
> image provided by kdump (it's really a good old core dump): ie. remapping
> vmalloc'ed memory pages, so modules can be accessed, and ideally adding
> processor context for each task (currently there is one per CPU). Crash
> does all this stuff internally and has other nice commands, but I don't
> find it quite as comfortable as gdb (with a few good scripts gdb would
> certainly be on par with crash).
>

Hmm.. Crash vs gdb is an interesting issue. I have not used
gdb very extensively on core dumps, but with my limited experiece, I
found "crash" to be more friendly. Crash has got so many in-built commands
tailored for kernel debugging and gdb lacks all those. Yes, we can write
gdb scripts to implement those, but last time Alaxender Nyberg wrote
few gdb scripts to dump all the threads and it was so slow.

Look at Documentation/kdump/gdbmacros.txt

So what's issue with crash? Is it just a matter of being more familiar
with gdb or gdb has got advantages over "crash" when it comes to kernel
debugging?

Thanks
Vivek

2006-09-25 21:01:36

by Jean-Marc Saffroy

[permalink] [raw]
Subject: Re: oops in :snd_pcm_oss:resample_expand+0x19c/0x1f0

Hi Vivek,

Thanks for all the good news on the future of kdump, it's nice to know
that people are working on improving the user experience.

On Mon, 25 Sep 2006, Vivek Goyal wrote:

>>>> Oh and I wish I could use gdb on a kdump core. :-)
>
> Currently we can use gdb but only for linearly mapped region. You are
> right its just a matter of re-generating the elf headers and remap the
> vmalloc areas to enable module debugging in gdb. I can not do it after
> the crash so probably the best place would be do it in user space. A
> program can read /proc/vmcore and regenerate the headers for enabling
> module debugging with gdb.

I assume that "after the crash" means "in the kernel crash handler",
AFAICT the current dump from vmcore has all what's needed.

> Hmm.. Crash vs gdb is an interesting issue. I have not used gdb very
> extensively on core dumps, but with my limited experiece, I found
> "crash" to be more friendly.

One thing I like *very much* in gdb is its ability to display function
params and local variables in any stack frame, and I haven't found out how
to do it with crash.

> Crash has got so many in-built commands tailored for kernel debugging
> and gdb lacks all those. Yes, we can write gdb scripts to implement
> those, but last time Alaxender Nyberg wrote few gdb scripts to dump all
> the threads and it was so slow.

I agree that gdb is sometimes very slow, but maybe it's easier to optimize
gdb than to make crash smarter?

For this particular problem (listing threads), the real fix would be to
add the PT_NOTE entry that each thread deserves, then gdb would let you do
"info threads" instead, and dump nice backtraces of each.

> Look at Documentation/kdump/gdbmacros.txt

Hmmm, these need an update, they no longer work with 2.6.18. But I have an
idea of how slow they can be, having tried a few things myself.

> So what's issue with crash? Is it just a matter of being more familiar
> with gdb or gdb has got advantages over "crash" when it comes to kernel
> debugging?

Oh I am certainly biased towards gdb :-) but function params and local
vars are very useful when debugging.

Of course crash is still a very useful tool, and until we can really use
gdb on kdumps (which requires some work), it will remain the best option
we have. Heck, it even impressed Andrew Morton! ;-)


Cheers,

--
[email protected]

2006-09-25 23:38:59

by Vivek Goyal

[permalink] [raw]
Subject: Re: oops in :snd_pcm_oss:resample_expand+0x19c/0x1f0

On Mon, Sep 25, 2006 at 11:01:52PM +0200, Jean-Marc Saffroy wrote:
> Hi Vivek,
>
> Thanks for all the good news on the future of kdump, it's nice to know
> that people are working on improving the user experience.
>
> On Mon, 25 Sep 2006, Vivek Goyal wrote:
>
> >>>>Oh and I wish I could use gdb on a kdump core. :-)
> >
> >Currently we can use gdb but only for linearly mapped region. You are
> >right its just a matter of re-generating the elf headers and remap the
> >vmalloc areas to enable module debugging in gdb. I can not do it after
> >the crash so probably the best place would be do it in user space. A
> >program can read /proc/vmcore and regenerate the headers for enabling
> >module debugging with gdb.
>
> I assume that "after the crash" means "in the kernel crash handler",
> AFAICT the current dump from vmcore has all what's needed.
>

Yes. I mean kernel crash handler. Yes all the contents are present
in the vmcore file. It is just a matter of somebody reading vmcore
and walk through either the page tables or may be vmlist and export
these mappings through ELF headers so that gdb can read it.

> >Hmm.. Crash vs gdb is an interesting issue. I have not used gdb very
> >extensively on core dumps, but with my limited experiece, I found
> >"crash" to be more friendly.
>
> One thing I like *very much* in gdb is its ability to display function
> params and local variables in any stack frame, and I haven't found out how
> to do it with crash.
>

Agreed. AFAIK, crash does not display the function params and local
variables. gdb has got this advantage, though last time I looked
at local variables dispalyed by gdb, they seemed to be junk. Not very
sure why it was so?

> >Crash has got so many in-built commands tailored for kernel debugging
> >and gdb lacks all those. Yes, we can write gdb scripts to implement
> >those, but last time Alaxender Nyberg wrote few gdb scripts to dump all
> >the threads and it was so slow.
>
> I agree that gdb is sometimes very slow, but maybe it's easier to optimize
> gdb than to make crash smarter?
>

I beg to differ here. Not sure why it is easier to optimize gdb. If we
try to optimize gdb by writing scripts, then IMHO, writing C program
is easier and faster. If the idea is to optimize gdb by modifying gdb
code then its no different than crash. In fact, why to reinvent the
wheel if crash already does so many things for us. Yes, but probably we
need to modify crash to be able to obtain function parameters and local
variables.

> For this particular problem (listing threads), the real fix would be to
> add the PT_NOTE entry that each thread deserves, then gdb would let you do
> "info threads" instead, and dump nice backtraces of each.
>

Displaying even the currently non executing threads using "info threads"
and their backtraces is interesting. Crash can already do that. I am
apprehensive about traversing through the task list and dumping every
thread's register state after a crash. There is no gurantee that list
is in a sane state. And in general, we are trying to make crash handler
as small as possible to improve the reliability of dumping operation.

Register state of every non-executing thread is already present in the
vmcore and IMHO, we should write scripts to get info about other
threads then doing it in kernel.

Thanks
Vivek

2006-09-26 00:59:15

by Jean-Marc Saffroy

[permalink] [raw]
Subject: Re: oops in :snd_pcm_oss:resample_expand+0x19c/0x1f0

On Mon, 25 Sep 2006, Vivek Goyal wrote:

>> One thing I like *very much* in gdb is its ability to display function
>> params and local variables in any stack frame, and I haven't found out how
>> to do it with crash.
>
> Agreed. AFAIK, crash does not display the function params and local
> variables. gdb has got this advantage, though last time I looked
> at local variables dispalyed by gdb, they seemed to be junk. Not very
> sure why it was so?

Most probably this is due to compiler optimizations, eg. the register is
reused for another purpose. Recently I was pleased to discover that gdb
6.5 is smart enough to tell the user that a variable has been optimized
out (certainly with help from debug info produced by gcc).

>> I agree that gdb is sometimes very slow, but maybe it's easier to
>> optimize gdb than to make crash smarter?
>
> I beg to differ here. Not sure why it is easier to optimize gdb. If we
> try to optimize gdb by writing scripts, then IMHO, writing C program is
> easier and faster. If the idea is to optimize gdb by modifying gdb code
> then its no different than crash. In fact, why to reinvent the wheel if
> crash already does so many things for us. Yes, but probably we need to
> modify crash to be able to obtain function parameters and local
> variables.

Oh I only meant that *maybe* gdb deserved some optimizations that would be
suitable for general use, but this is pure speculation. I agree that a
custom modified gdb is in a way akin to crash.

>> For this particular problem (listing threads), the real fix would be to
>> add the PT_NOTE entry that each thread deserves, then gdb would let you
>> do "info threads" instead, and dump nice backtraces of each.
>
> Displaying even the currently non executing threads using "info threads"
> and their backtraces is interesting. Crash can already do that. I am
> apprehensive about traversing through the task list and dumping every
> thread's register state after a crash. There is no gurantee that list is
> in a sane state. And in general, we are trying to make crash handler as
> small as possible to improve the reliability of dumping operation.
>
> Register state of every non-executing thread is already present in the
> vmcore and IMHO, we should write scripts to get info about other
> threads then doing it in kernel.

This is exactly what I had in mind, for the very reasons you mentioned.
:-)


--
[email protected]

2006-09-27 14:38:08

by Takashi Iwai

[permalink] [raw]
Subject: Re: oops in :snd_pcm_oss:resample_expand+0x19c/0x1f0

At Sun, 24 Sep 2006 19:01:27 +0200 (CEST),
Jean-Marc Saffroy wrote:
>
> The kernel is vanilla 2.6.18 on Debian etch, the box is a dual core Athlon
> in x86-64 mode (in case you didn't notice the long pointers ;-). The
> offending process is a chroot'ed IA32 Firefox. At first I suspected a
> problem with 32-bit compatibility, but stack traces below and source code
> suggest the problem could be different:
>
> - CPU #0 crashes in resample_expand() at line 116:
>
> 116 *dst = val;
>
> The target address is at ffffc200100e4466, which looks like a vmalloc'ed
> buffer (according to Documentation/x86_64/mm.txt).
>
> - CPU #1 is somewhere down vfree() called by snd_pcm_oss_change_params(),
> at line 1010:
>
> 1010 vfree(runtime->oss.buffer);
> 1011 runtime->oss.buffer = vmalloc(runtime->oss.period_bytes);
>
> Now it really looks like it *could* be a race between two threads using
> the same device, maybe the same buffers somehow, but I'm getting lost in
> the data structures, so help from knowledgeable people would be welcome.

Thanks for the detailed analysis. It looks indeed like a race between
two threads that we didn't consider much for OSS emulation (although
ALSA parts are coded to be thread-safe).

Could you try the patch below? It simply adds mutex around the parts
handling buffers concurrently.


Takashi

diff -r 7cc57ec28195 core/oss/pcm_oss.c
--- a/core/oss/pcm_oss.c Tue Sep 26 15:32:35 2006 +0200
+++ b/core/oss/pcm_oss.c Wed Sep 27 16:29:36 2006 +0200
@@ -810,6 +810,8 @@ static int snd_pcm_oss_change_params(str
struct snd_mask sformat_mask;
struct snd_mask mask;

+ if (mutex_lock_interruptible(&runtime->oss.params_lock))
+ return -EINTR;
sw_params = kmalloc(sizeof(*sw_params), GFP_KERNEL);
params = kmalloc(sizeof(*params), GFP_KERNEL);
sparams = kmalloc(sizeof(*sparams), GFP_KERNEL);
@@ -1020,6 +1022,7 @@ failure:
kfree(sw_params);
kfree(params);
kfree(sparams);
+ mutex_unlock(&runtime->oss.params_lock);
return err;
}

@@ -1307,14 +1310,17 @@ static ssize_t snd_pcm_oss_write1(struct

if ((tmp = snd_pcm_oss_make_ready(substream)) < 0)
return tmp;
+ mutex_lock(&runtime->oss.params_lock);
while (bytes > 0) {
if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) {
tmp = bytes;
if (tmp + runtime->oss.buffer_used > runtime->oss.period_bytes)
tmp = runtime->oss.period_bytes - runtime->oss.buffer_used;
if (tmp > 0) {
- if (copy_from_user(runtime->oss.buffer + runtime->oss.buffer_used, buf, tmp))
- return xfer > 0 ? (snd_pcm_sframes_t)xfer : -EFAULT;
+ if (copy_from_user(runtime->oss.buffer + runtime->oss.buffer_used, buf, tmp)) {
+ tmp = -EFAULT;
+ goto err;
+ }
}
runtime->oss.buffer_used += tmp;
buf += tmp;
@@ -1325,22 +1331,24 @@ static ssize_t snd_pcm_oss_write1(struct
tmp = snd_pcm_oss_write2(substream, runtime->oss.buffer + runtime->oss.period_ptr,
runtime->oss.buffer_used - runtime->oss.period_ptr, 1);
if (tmp <= 0)
- return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
+ goto err;
runtime->oss.bytes += tmp;
runtime->oss.period_ptr += tmp;
runtime->oss.period_ptr %= runtime->oss.period_bytes;
if (runtime->oss.period_ptr == 0 ||
runtime->oss.period_ptr == runtime->oss.buffer_used)
runtime->oss.buffer_used = 0;
- else if ((substream->f_flags & O_NONBLOCK) != 0)
- return xfer > 0 ? xfer : -EAGAIN;
+ else if ((substream->f_flags & O_NONBLOCK) != 0) {
+ tmp = -EAGAIN;
+ goto err;
+ }
}
} else {
tmp = snd_pcm_oss_write2(substream,
(const char __force *)buf,
runtime->oss.period_bytes, 0);
if (tmp <= 0)
- return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
+ goto err;
runtime->oss.bytes += tmp;
buf += tmp;
bytes -= tmp;
@@ -1350,7 +1358,12 @@ static ssize_t snd_pcm_oss_write1(struct
break;
}
}
+ mutex_unlock(&runtime->oss.params_lock);
return xfer;
+
+ err:
+ mutex_unlock(&runtime->oss.params_lock);
+ return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
}

static ssize_t snd_pcm_oss_read2(struct snd_pcm_substream *substream, char *buf, size_t bytes, int in_kernel)
@@ -1397,12 +1410,13 @@ static ssize_t snd_pcm_oss_read1(struct

if ((tmp = snd_pcm_oss_make_ready(substream)) < 0)
return tmp;
+ mutex_lock(&runtime->oss.params_lock);
while (bytes > 0) {
if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) {
if (runtime->oss.buffer_used == 0) {
tmp = snd_pcm_oss_read2(substream, runtime->oss.buffer, runtime->oss.period_bytes, 1);
if (tmp <= 0)
- return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
+ goto err;
runtime->oss.bytes += tmp;
runtime->oss.period_ptr = tmp;
runtime->oss.buffer_used = tmp;
@@ -1410,8 +1424,10 @@ static ssize_t snd_pcm_oss_read1(struct
tmp = bytes;
if ((size_t) tmp > runtime->oss.buffer_used)
tmp = runtime->oss.buffer_used;
- if (copy_to_user(buf, runtime->oss.buffer + (runtime->oss.period_ptr - runtime->oss.buffer_used), tmp))
- return xfer > 0 ? (snd_pcm_sframes_t)xfer : -EFAULT;
+ if (copy_to_user(buf, runtime->oss.buffer + (runtime->oss.period_ptr - runtime->oss.buffer_used), tmp)) {
+ tmp = -EFAULT;
+ goto err;
+ }
buf += tmp;
bytes -= tmp;
xfer += tmp;
@@ -1420,14 +1436,19 @@ static ssize_t snd_pcm_oss_read1(struct
tmp = snd_pcm_oss_read2(substream, (char __force *)buf,
runtime->oss.period_bytes, 0);
if (tmp <= 0)
- return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
+ goto err;
runtime->oss.bytes += tmp;
buf += tmp;
bytes -= tmp;
xfer += tmp;
}
}
+ mutex_unlock(&runtime->oss.params_lock);
return xfer;
+
+ err:
+ mutex_unlock(&runtime->oss.params_lock);
+ return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
}

static int snd_pcm_oss_reset(struct snd_pcm_oss_file *pcm_oss_file)
@@ -1528,6 +1549,7 @@ static int snd_pcm_oss_sync(struct snd_p
return err;
format = snd_pcm_oss_format_from(runtime->oss.format);
width = snd_pcm_format_physical_width(format);
+ mutex_lock(&runtime->oss.params_lock);
if (runtime->oss.buffer_used > 0) {
#ifdef OSS_DEBUG
printk("sync: buffer_used\n");
@@ -1537,8 +1559,10 @@ static int snd_pcm_oss_sync(struct snd_p
runtime->oss.buffer + runtime->oss.buffer_used,
size);
err = snd_pcm_oss_sync1(substream, runtime->oss.period_bytes);
- if (err < 0)
+ if (err < 0) {
+ mutex_unlock(&runtime->oss.params_lock);
return err;
+ }
} else if (runtime->oss.period_ptr > 0) {
#ifdef OSS_DEBUG
printk("sync: period_ptr\n");
@@ -1548,8 +1572,10 @@ static int snd_pcm_oss_sync(struct snd_p
runtime->oss.buffer,
size * 8 / width);
err = snd_pcm_oss_sync1(substream, size);
- if (err < 0)
+ if (err < 0) {
+ mutex_unlock(&runtime->oss.params_lock);
return err;
+ }
}
/*
* The ALSA's period might be a bit large than OSS one.
@@ -1579,6 +1605,7 @@ static int snd_pcm_oss_sync(struct snd_p
snd_pcm_lib_writev(substream, buffers, size);
}
}
+ mutex_unlock(&runtime->oss.params_lock);
/*
* finish sync: drain the buffer
*/
@@ -2172,6 +2199,7 @@ static void snd_pcm_oss_init_substream(s
runtime->oss.params = 1;
runtime->oss.trigger = 1;
runtime->oss.rate = 8000;
+ mutex_init(&runtime->oss.params_lock);
switch (SNDRV_MINOR_OSS_DEVICE(minor)) {
case SNDRV_MINOR_OSS_PCM_8:
runtime->oss.format = AFMT_U8;
diff -r 7cc57ec28195 include/pcm_oss.h
--- a/include/pcm_oss.h Tue Sep 26 15:32:35 2006 +0200
+++ b/include/pcm_oss.h Wed Sep 27 16:28:28 2006 +0200
@@ -56,6 +56,7 @@ struct snd_pcm_oss_runtime {
size_t mmap_bytes;
char *buffer; /* vmallocated period */
size_t buffer_used; /* used length from period buffer */
+ struct mutex params_lock;
#ifdef CONFIG_SND_PCM_OSS_PLUGINS
struct snd_pcm_plugin *plugin_first;
struct snd_pcm_plugin *plugin_last;