dahdi: Do not call dahdi_check_conf under lock.

dahdi_check_conf() acqurires the locks as needed when scanning the
channels and should not be called under any spinlocks.

Fixes a regression that Tzafrir reported in #asterisk-dev that he could
trigger via "asterisk -rx 'channel originate Local/600@demo
Application Meetme 3000,d'"

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@9621 a0bf4364-ded3-4de4-8d8a-66a801d63aff
This commit is contained in:
Shaun Ruffell
2011-01-06 21:34:10 +00:00
parent 5f952783bf
commit d5520c533a

View File

@@ -1493,8 +1493,6 @@ static void close_channel(struct dahdi_chan *chan)
chan->dacs_chan = NULL;
chan->confmute = 0;
/* release conference resource, if any to release */
if (oldconf) dahdi_check_conf(oldconf);
chan->gotgs = 0;
reset_conf(chan);
chan->dacs_chan = NULL;
@@ -1523,6 +1521,10 @@ static void close_channel(struct dahdi_chan *chan)
spin_unlock_irqrestore(&chan->lock, flags);
/* release conference resource, if any to release */
if (oldconf)
dahdi_check_conf(oldconf);
if (rxgain)
kfree(rxgain);
if (readchunkpreec)
@@ -5141,7 +5143,7 @@ static int dahdi_ioctl_setconf(struct file *file, unsigned long data)
struct dahdi_chan *conf_chan = NULL;
unsigned long flags;
unsigned int confmode;
int j;
int oldconf;
if (copy_from_user(&conf, (void __user *)data, sizeof(conf)))
return -EFAULT;
@@ -5173,6 +5175,7 @@ static int dahdi_ioctl_setconf(struct file *file, unsigned long data)
/* likewise if 0 mode must have no conf */
if ((!conf.confmode) && conf.confno)
return -EINVAL;
dahdi_check_conf(conf.confno);
conf.chan = chan->channo; /* return with real channel # */
spin_lock_irqsave(&chan_lock, flags);
spin_lock(&chan->lock);
@@ -5190,13 +5193,11 @@ static int dahdi_ioctl_setconf(struct file *file, unsigned long data)
memset(chan->conflast1, 0, DAHDI_MAX_CHUNKSIZE);
memset(chan->conflast2, 0, DAHDI_MAX_CHUNKSIZE);
}
j = chan->confna; /* save old conference number */
oldconf = chan->confna; /* save old conference number */
chan->confna = conf.confno; /* set conference number */
chan->conf_chan = conf_chan;
chan->confmode = conf.confmode; /* set conference mode */
chan->_confn = 0; /* Clear confn */
dahdi_check_conf(j);
dahdi_check_conf(conf.confno);
if (chan->span && chan->span->ops->dacs) {
if ((confmode == DAHDI_CONF_DIGITALMON) &&
(chan->txgain == defgain) &&
@@ -5234,6 +5235,7 @@ static int dahdi_ioctl_setconf(struct file *file, unsigned long data)
spin_unlock(&chan->lock);
spin_unlock_irqrestore(&chan_lock, flags);
dahdi_check_conf(oldconf);
if (copy_to_user((void __user *)data, &conf, sizeof(conf)))
return -EFAULT;
return 0;