From nobody@FreeBSD.org  Mon Oct 22 02:06:52 2001
Return-Path: <nobody@FreeBSD.org>
Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21])
	by hub.freebsd.org (Postfix) with ESMTP id 238BB37B401
	for <freebsd-gnats-submit@FreeBSD.org>; Mon, 22 Oct 2001 02:06:52 -0700 (PDT)
Received: (from nobody@localhost)
	by freefall.freebsd.org (8.11.4/8.11.4) id f9M96qF22169;
	Mon, 22 Oct 2001 02:06:52 -0700 (PDT)
	(envelope-from nobody)
Message-Id: <200110220906.f9M96qF22169@freefall.freebsd.org>
Date: Mon, 22 Oct 2001 02:06:52 -0700 (PDT)
From: Daniel Pouzzner <douzzer@mega.nu>
To: freebsd-gnats-submit@FreeBSD.org
Subject: kernel resource deadlock on /dev/dsp
X-Send-Pr-Version: www-1.0

>Number:         31429
>Category:       kern
>Synopsis:       kernel resource deadlock on /dev/dsp
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Oct 22 02:10:00 PDT 2001
>Closed-Date:    Mon Nov 5 01:21:21 PST 2001
>Last-Modified:  Mon Nov 05 01:22:04 PST 2001
>Originator:     Daniel Pouzzner
>Release:        4.3-REL
>Organization:
www.mega.nu
>Environment:
-* uname -a
FreeBSD mega 4.3-RELEASE FreeBSD 4.3-RELEASE #9: Mon Oct 22 04:52:54 EDT 2001     douzzer@mega:/usr/src.4.3/sys/compile/MEGA  i386

>Description:
dsp_open() in sys/dev/sound/pcm/dsp.c fails to release or remember the
read channel (rdch) if the subsequent wrch allocation craps out.  This
causes all subsequent attempts to allocate the rdch to fail, because it
is already allocated (but the pointer was discarded).

>How-To-Repeat:
start sound playing with xmms or any other program that opens the dsp
read-write.  try to record sound (from the same dsp of course) - EBUSY
results.  stop sound playing.  try record again.  should work, but
instead, more EBUSYs result.

>Fix:
I'm sure you can do a cleaner job, but I just wanted to get this fixed
prontissimo:

int
dsp_open(snddev_info *d, int chan, int oflags, int devtype)
{
	pcm_channel *rdch, *wrch;
	u_int32_t fmt;

	int gotrdchthiscall = 0;

	if (chan >= d->chancount) return ENODEV;
	if ((d->flags & SD_F_SIMPLEX) && (d->ref[chan] > 0))
	  return EBUSY;
	if (d->atype[chan] != 0 && d->atype[chan] != devtype)
	  return EBUSY;

	rdch = d->arec[chan];
	wrch = d->aplay[chan];
	if (oflags & FREAD) {
		if (rdch == NULL) {
			rdch = allocchn(d, PCMDIR_REC);
			if (!rdch)
			  return EBUSY;
			gotrdchthiscall = 1;
		} else 
		  return EBUSY;
	}
	if (oflags & FWRITE) {
		if (wrch == NULL) {
			wrch = allocchn(d, PCMDIR_PLAY);
			if (!wrch) {
				if (rdch && (oflags & FREAD))
					rdch->flags &= ~CHN_F_BUSY;
				  goto busyret;
			}
		} else
		  goto busyret;
		goto nobusyret;
	busyret:
		/* must liberate the rdch if it we opened it this call */
		if (gotrdchthiscall) {
		  chn_abort(rdch);
		  rdch->flags &= ~(CHN_F_BUSY | CHN_F_RUNNING | CHN_F_MAPPED | CHN_F_DEAD);
		  chn_reset(rdch, 0);
		}
		return EBUSY;
	nobusyret:
	}
[...]

>Release-Note:
>Audit-Trail:

From: Daniel Pouzzner <douzzer@mega.nu>
To: freebsd-gnats-submit@FreeBSD.org
Cc:  
Subject: Re: kern/31429: kernel resource deadlock on /dev/dsp
Date: Mon, 22 Oct 2001 05:47:26 -0400 (EDT)

 My original submission of half an hour ago was rather flawed, in two
 respects:
 
 (1) apparently, it doesn't matter if the dsp was opened WRONLY or RDWR
     - a subsequent RDONLY open results in EBUSY either way.
 
 (2) my fix was profoundly bogus, in particular causing a kernel hang
     on reboot (probably due to some other resource deadlock introduced
     by the code).
 
 Here is a much cleaner fix that seems to actually work all-around.
 The changes are that d->arec[chan] is updated immediately after the
 allocation, before the pointer can get lost, and the last EBUSY return
 in the FWRITE section includes the same un-busying code as the one
 before it.  I'm not sufficiently familiar with the subsystem to know
 if it's important to update d->arec[chan] scrupulously (as I have it
 doing now), but it doesn't hurt anything apparently.
 
 
 
 int
 dsp_open(snddev_info *d, int chan, int oflags, int devtype)
 {
 	pcm_channel *rdch, *wrch;
 	u_int32_t fmt;
 
 	if (chan >= d->chancount) return ENODEV;
 	if ((d->flags & SD_F_SIMPLEX) && (d->ref[chan] > 0))
 	  return EBUSY;
 	if (d->atype[chan] != 0 && d->atype[chan] != devtype)
 	  return EBUSY;
 
 	rdch = d->arec[chan];
 	wrch = d->aplay[chan];
 	if (oflags & FREAD) {
 		if (rdch == NULL) {
 			rdch = allocchn(d, PCMDIR_REC);
 			if (!rdch)
 			  return EBUSY;
 			d->arec[chan] = rdch;
 		} else 
 		  return EBUSY;
 	}
 	if (oflags & FWRITE) {
 		if (wrch == NULL) {
 			wrch = allocchn(d, PCMDIR_PLAY);
 			if (!wrch) {
 				if (rdch && (oflags & FREAD))
 					rdch->flags &= ~CHN_F_BUSY;
 				return EBUSY;
 			}
 		} else {
 		  if (rdch && (oflags & FREAD))
 		    rdch->flags &= ~CHN_F_BUSY;
 		  return EBUSY;
 		}
 	}
 	d->atype[chan] = devtype;
 	d->aplay[chan] = wrch;
 	d->ref[chan]++;
 	switch (devtype) {
 [...]

From: Daniel Pouzzner <douzzer@mega.nu>
To: freebsd-gnats-submit@FreeBSD.org
Cc:  
Subject: Re: kern/31429: kernel resource deadlock on /dev/dsp
Date: Sun, 4 Nov 2001 21:20:02 -0500 (EST)

 I checked the -current tree and discovered that this defect has
 already been repaired.  Therefore, the state on this bug can go to
 Closed.
State-Changed-From-To: open->closed 
State-Changed-By: dwmalone 
State-Changed-When: Mon Nov 5 01:21:21 PST 2001 
State-Changed-Why:  
Closed at submitters request (already fixed in -current). 

http://www.FreeBSD.org/cgi/query-pr.cgi?pr=31429 
>Unformatted:
