From 3625c5dc5d694ffc3795b5f46c3b0e97686374e9 Mon Sep 17 00:00:00 2001 From: Shaun Ruffell Date: Tue, 3 Apr 2012 20:10:03 +0000 Subject: dahdi_dynamic: Do not call into dahdi_dynamic without holding reference. Instead of registering a function pointer, register a dahdi_dynamic_ops structure that contains the owner as well as the ioctl callback. This way dahdi.ko can bump up the reference count on dahdi_dynamic.ko before calling the ioctl callback. Also, use the registration mutex to guard against the module being unloaded between the time the structure pointer was checked, and the module reference is taken. Signed-off-by: Shaun Ruffell Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10623 git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.6@10628 a0bf4364-ded3-4de4-8d8a-66a801d63aff --- drivers/dahdi/dahdi-base.c | 47 +++++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 13 deletions(-) (limited to 'drivers/dahdi/dahdi-base.c') diff --git a/drivers/dahdi/dahdi-base.c b/drivers/dahdi/dahdi-base.c index bb01415..0b037ab 100644 --- a/drivers/dahdi/dahdi-base.c +++ b/drivers/dahdi/dahdi-base.c @@ -122,7 +122,6 @@ EXPORT_SYMBOL(dahdi_qevent_nolock); EXPORT_SYMBOL(dahdi_qevent_lock); EXPORT_SYMBOL(dahdi_hooksig); EXPORT_SYMBOL(dahdi_alarm_notify); -EXPORT_SYMBOL(dahdi_set_dynamic_ioctl); EXPORT_SYMBOL(dahdi_hdlc_abort); EXPORT_SYMBOL(dahdi_hdlc_finish); EXPORT_SYMBOL(dahdi_hdlc_getbuf); @@ -4422,12 +4421,14 @@ static int dahdi_common_ioctl(struct file *file, unsigned int cmd, return 0; } -static int (*dahdi_dynamic_ioctl)(unsigned int cmd, unsigned long data); - -void dahdi_set_dynamic_ioctl(int (*func)(unsigned int cmd, unsigned long data)) +static const struct dahdi_dynamic_ops *dahdi_dynamic_ops; +void dahdi_set_dynamic_ops(const struct dahdi_dynamic_ops *ops) { - dahdi_dynamic_ioctl = func; + mutex_lock(®istration_mutex); + dahdi_dynamic_ops = ops; + mutex_unlock(®istration_mutex); } +EXPORT_SYMBOL(dahdi_set_dynamic_ops); static int (*dahdi_hpec_ioctl)(unsigned int cmd, unsigned long data); @@ -5146,6 +5147,33 @@ static int dahdi_ioctl_maint(unsigned long data) return 0; } +static int dahdi_ioctl_dynamic(unsigned int cmd, unsigned long data) +{ + bool tried_load = false; + int res; + +retry_check: + mutex_lock(®istration_mutex); + if (!dahdi_dynamic_ops) { + mutex_unlock(®istration_mutex); + if (tried_load) + return -ENOSYS; + + request_module("dahdi_dynamic"); + tried_load = true; + goto retry_check; + } + if (!try_module_get(dahdi_dynamic_ops->owner)) { + mutex_unlock(®istration_mutex); + return -ENOSYS; + } + mutex_unlock(®istration_mutex); + + res = dahdi_dynamic_ops->ioctl(cmd, data); + module_put(dahdi_dynamic_ops->owner); + return res; +} + static int dahdi_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long data) { @@ -5180,14 +5208,7 @@ dahdi_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long data) return dahdi_ioctl_maint(data); case DAHDI_DYNAMIC_CREATE: case DAHDI_DYNAMIC_DESTROY: - if (dahdi_dynamic_ioctl) { - return dahdi_dynamic_ioctl(cmd, data); - } else { - request_module("dahdi_dynamic"); - if (dahdi_dynamic_ioctl) - return dahdi_dynamic_ioctl(cmd, data); - } - return -ENOSYS; + return dahdi_ioctl_dynamic(cmd, data); case DAHDI_EC_LICENSE_CHALLENGE: case DAHDI_EC_LICENSE_RESPONSE: if (dahdi_hpec_ioctl) { -- cgit v1.2.3