[svn-commits] sruffell: branch linux/2.6 r10628 - in /linux/branches/2.6: drivers/dahdi/ in...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Tue Apr 3 15:10:07 CDT 2012


Author: sruffell
Date: Tue Apr  3 15:10:03 2012
New Revision: 10628

URL: http://svnview.digium.com/svn/dahdi?view=rev&rev=10628
Log:
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 <sruffell at digium.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10623

Modified:
    linux/branches/2.6/drivers/dahdi/dahdi-base.c
    linux/branches/2.6/drivers/dahdi/dahdi_dynamic.c
    linux/branches/2.6/include/dahdi/kernel.h

Modified: linux/branches/2.6/drivers/dahdi/dahdi-base.c
URL: http://svnview.digium.com/svn/dahdi/linux/branches/2.6/drivers/dahdi/dahdi-base.c?view=diff&rev=10628&r1=10627&r2=10628
==============================================================================
--- linux/branches/2.6/drivers/dahdi/dahdi-base.c (original)
+++ linux/branches/2.6/drivers/dahdi/dahdi-base.c Tue Apr  3 15:10:03 2012
@@ -122,7 +122,6 @@
 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 @@
 	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))
-{
-	dahdi_dynamic_ioctl = func;
-}
+static const struct dahdi_dynamic_ops *dahdi_dynamic_ops;
+void dahdi_set_dynamic_ops(const struct dahdi_dynamic_ops *ops)
+{
+	mutex_lock(&registration_mutex);
+	dahdi_dynamic_ops = ops;
+	mutex_unlock(&registration_mutex);
+}
+EXPORT_SYMBOL(dahdi_set_dynamic_ops);
 
 static int (*dahdi_hpec_ioctl)(unsigned int cmd, unsigned long data);
 
@@ -5144,6 +5145,33 @@
 	put_span(s);
 
 	return 0;
+}
+
+static int dahdi_ioctl_dynamic(unsigned int cmd, unsigned long data)
+{
+	bool tried_load = false;
+	int res;
+
+retry_check:
+	mutex_lock(&registration_mutex);
+	if (!dahdi_dynamic_ops) {
+		mutex_unlock(&registration_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(&registration_mutex);
+		return -ENOSYS;
+	}
+	mutex_unlock(&registration_mutex);
+
+	res = dahdi_dynamic_ops->ioctl(cmd, data);
+	module_put(dahdi_dynamic_ops->owner);
+	return res;
 }
 
 static int
@@ -5180,14 +5208,7 @@
 		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) {

Modified: linux/branches/2.6/drivers/dahdi/dahdi_dynamic.c
URL: http://svnview.digium.com/svn/dahdi/linux/branches/2.6/drivers/dahdi/dahdi_dynamic.c?view=diff&rev=10628&r1=10627&r2=10628
==============================================================================
--- linux/branches/2.6/drivers/dahdi/dahdi_dynamic.c (original)
+++ linux/branches/2.6/drivers/dahdi/dahdi_dynamic.c Tue Apr  3 15:10:03 2012
@@ -823,10 +823,13 @@
 	mod_timer(&alarmcheck, jiffies + 1 * HZ);
 }
 
+static const struct dahdi_dynamic_ops dahdi_dynamic_ops = {
+	.owner = THIS_MODULE,
+	.ioctl = dahdi_dynamic_ioctl,
+};
+
 static int dahdi_dynamic_init(void)
 {
-	dahdi_set_dynamic_ioctl(dahdi_dynamic_ioctl);
-
 	/* Start process to check for RED ALARM */
 	init_timer(&alarmcheck);
 	alarmcheck.expires = 0;
@@ -837,19 +840,22 @@
 #ifdef ENABLE_TASKLETS
 	tasklet_init(&dahdi_dynamic_tlet, dahdi_dynamic_tasklet, 0);
 #endif
+	dahdi_set_dynamic_ops(&dahdi_dynamic_ops);
+
 	printk(KERN_INFO "DAHDI Dynamic Span support LOADED\n");
 	return 0;
 }
 
 static void dahdi_dynamic_cleanup(void)
 {
+	dahdi_set_dynamic_ops(NULL);
+
 #ifdef ENABLE_TASKLETS
 	if (taskletpending) {
 		tasklet_disable(&dahdi_dynamic_tlet);
 		tasklet_kill(&dahdi_dynamic_tlet);
 	}
 #endif
-	dahdi_set_dynamic_ioctl(NULL);
 	del_timer(&alarmcheck);
 	printk(KERN_INFO "DAHDI Dynamic Span support unloaded\n");
 }

Modified: linux/branches/2.6/include/dahdi/kernel.h
URL: http://svnview.digium.com/svn/dahdi/linux/branches/2.6/include/dahdi/kernel.h?view=diff&rev=10628&r1=10627&r2=10628
==============================================================================
--- linux/branches/2.6/include/dahdi/kernel.h (original)
+++ linux/branches/2.6/include/dahdi/kernel.h Tue Apr  3 15:10:03 2012
@@ -1280,8 +1280,13 @@
 extern u_char __dahdi_lin2a[16384];
 #endif
 
+struct dahdi_dynamic_ops {
+	struct module *owner;
+	int (*ioctl)(unsigned int cmd, unsigned long data);
+};
+
 /*! \brief Used by dynamic DAHDI -- don't use directly */
-void dahdi_set_dynamic_ioctl(int (*func)(unsigned int cmd, unsigned long data));
+void dahdi_set_dynamic_ops(const struct dahdi_dynamic_ops *ops);
 
 /*! \brief Used by DAHDI HPEC module -- don't use directly */
 void dahdi_set_hpec_ioctl(int (*func)(unsigned int cmd, unsigned long data));




More information about the svn-commits mailing list