misc/114291: [PATCH]dynamic module references

david chosrova david.chosrova at libertysurf.fr
Wed Jul 4 15:20:04 UTC 2007


>Number:         114291
>Category:       misc
>Synopsis:       [PATCH]dynamic module references
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Jul 04 15:20:03 GMT 2007
>Closed-Date:
>Last-Modified:
>Originator:     david chosrova
>Release:        6-2
>Organization:
>Environment:
>Description:
Hi,

 I'm new to Freebsd and interested in system programming. So I'have picked up a task from the project ideas list to start with.
 (part of) the subject is : "This task is to define and implement a general mechanism for tracking these references and use them in handling module unload requests."

So, to do that, I'have added an "int dynrefs" in struct module (kern_module.c), and functions to increase or decrease this count (module_add/remove_dynrefs(const char * modname) and module_updatedynrefs(const char * modname, int action) ) in kern_module.c.

 To avoid unload of a module which has a dynrefs count != 0  , I have modified module_unload(), so that unload is process only if dynrefs=0 or flag=LINKER_UNLOAD_FORCE.

 module_unload(module_t mod, int flags)
 {
 	int error;
-	error = MOD_EVENT(mod, MOD_QUIESCE);
+	MOD_SLOCK;
+	(mod->dynrefs == 0) ? (error = MOD_EVENT(mod, MOD_QUIESCE)) : (error = EPERM);
+	MOD_SUNLOCK;



 I have compiled and tested. with a 6-2 RELEASE. For the test I'have used two dummy module, one adding a dynrefs on the other.

 Any comment are welcome

 David chosrova 





>How-To-Repeat:

>Fix:


Patch attached with submission follows:

--- kern_module.c.orig	Wed Jul  4 10:33:06 2007
+++ kern_module.c	Wed Jul  4 10:21:28 2007
@@ -52,6 +52,7 @@
 	TAILQ_ENTRY(module)	flink;	/* all modules in a file */
 	struct linker_file	*file;	/* file which contains this module */
 	int			refs;	/* reference count */
+	int			dynrefs;        /* dynamic reference count */
 	int 			id;	/* unique id number */
 	char 			*name;	/* module name */
 	modeventhand_t 		handler;	/* event handler */
@@ -65,6 +66,7 @@
 struct sx modules_sx;
 static int nextid = 1;
 static void module_shutdown(void *, int);
+static int module_updatedynrefs(const char* , int );
 
 static int
 modevent_nop(module_t mod, int what, void *arg)
@@ -152,6 +154,7 @@
 	}
 	newmod->refs = 1;
 	newmod->id = nextid++;
+	newmod->dynrefs = 0;
 	newmod->name = (char *)(newmod + 1);
 	strcpy(newmod->name, data->name);
 	newmod->handler = data->evhand ? data->evhand : modevent_nop;
@@ -231,7 +234,9 @@
 module_unload(module_t mod, int flags)
 {
 	int error;
-	error = MOD_EVENT(mod, MOD_QUIESCE);
+	MOD_SLOCK;
+	(mod->dynrefs == 0) ? (error = MOD_EVENT(mod, MOD_QUIESCE)) : (error = EPERM);
+	MOD_SUNLOCK;
 	if (error == EOPNOTSUPP || error == EINVAL)
 		error = 0;
 	if (flags == LINKER_UNLOAD_NORMAL && error != 0)
@@ -261,6 +266,37 @@
 
 	MOD_XLOCK_ASSERT;
 	mod->data = *datap;
+}
+
+static int
+module_updatedynrefs(const char* modname, int action)
+{
+	module_t mod;
+	
+	MOD_XLOCK;
+	mod = module_lookupbyname(modname);
+
+	if(mod == 0) {
+		MOD_XUNLOCK;
+		return(-1);
+	}
+
+	(action == 1) ? mod->dynrefs++ : mod->dynrefs--;
+	MOD_XUNLOCK;
+	return (0);
+}
+
+int
+module_add_dynrefs(const char *modname)
+{
+
+	return (module_updatedynrefs(modname,1));
+}
+
+int
+module_remove_dynrefs(const char * modname)
+{
+	return (module_updatedynrefs(modname,0));
 }
 
 /*	


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list