diff options
author | Shaun Ruffell <sruffell@digium.com> | 2011-01-06 21:34:10 +0000 |
---|---|---|
committer | Shaun Ruffell <sruffell@digium.com> | 2011-01-06 21:34:10 +0000 |
commit | ebd396872801f4998d413872716d743dee9cd9fe (patch) | |
tree | 7a8580dc8df0013536dd37da2e27c7aef9d1b292 | |
parent | a8c1e348c5544d1ca1e3d8019b94774cf0a9b29b (diff) |
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
-rw-r--r-- | drivers/dahdi/dahdi-base.c | 14 |
1 files changed, 8 insertions, 6 deletions
diff --git a/drivers/dahdi/dahdi-base.c b/drivers/dahdi/dahdi-base.c index 8c32f7c..0564fd8 100644 --- a/drivers/dahdi/dahdi-base.c +++ b/drivers/dahdi/dahdi-base.c @@ -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; |