PERFORCE change 97831 for review

John Baldwin jhb at FreeBSD.org
Thu May 25 15:35:05 PDT 2006


http://perforce.freebsd.org/chv.cgi?CH=97831

Change 97831 by jhb at jhb_mutex on 2006/05/25 22:27:03

	Provide linker_release_module() as a compliment to
	linker_reference_module() instead of code matching calls to
	linker_reference_module() with calls to linker_file_unload().
	Also, while I'm here, make the task to unload firmware modules
	less racy by claering the FP entry first and then going any
	unloading the module using a cached copy of the linker_file_t.

Affected files ...

.. //depot/projects/smpng/sys/dev/digi/digi.c#32 edit
.. //depot/projects/smpng/sys/kern/kern_linker.c#60 edit
.. //depot/projects/smpng/sys/kern/subr_firmware.c#3 edit
.. //depot/projects/smpng/sys/sys/linker.h#22 edit

Differences ...

==== //depot/projects/smpng/sys/dev/digi/digi.c#32 (text+ko) ====

@@ -795,7 +795,7 @@
 	free(sym, M_TEMP);
 	if (symptr == NULL) {
 		printf("digi_%s.ko: Symbol `%s' not found\n", sc->module, sym);
-		linker_file_unload(lf, LINKER_UNLOAD_FORCE);
+		linker_release_module(NULL, NULL, lf);
 		return (EINVAL);
 	}
 
@@ -803,7 +803,7 @@
 	if (digi_mod->dm_version != DIGI_MOD_VERSION) {
 		printf("digi_%s.ko: Invalid version %d (need %d)\n",
 		    sc->module, digi_mod->dm_version, DIGI_MOD_VERSION);
-		linker_file_unload(lf, LINKER_UNLOAD_FORCE);
+		linker_release_module(NULL, NULL, lf);
 		return (EINVAL);
 	}
 
@@ -825,7 +825,7 @@
 		bcopy(digi_mod->dm_link.data, sc->link.data, sc->link.size);
 	}
 
-	linker_file_unload(lf, LINKER_UNLOAD_FORCE);
+	linker_release_module(NULL, NULL, lf);
 
 	return (0);
 }

==== //depot/projects/smpng/sys/kern/kern_linker.c#60 (text+ko) ====

@@ -425,7 +425,7 @@
     linker_file_t *result)
 {
 	modlist_t mod;
-	int error, locked;
+	int error;
 
 	KLD_LOCK();
 	if ((mod = modlist_lookup2(modname, verinfo)) != NULL) {
@@ -441,6 +441,31 @@
 	return (error);
 }
 
+int
+linker_release_module(const char *modname, struct mod_depend *verinfo,
+    linker_file_t lf)
+{
+	modlist_t mod;
+	int error;
+
+	KLD_LOCK();
+	if (lf == NULL) {
+		KASSERT(modname != NULL,
+		    ("linker_release_module: no file or name"));
+		mod = modlist_lookup2(modname, verinfo);
+		if (mod == NULL) {
+			KLD_UNLOCK();
+			return (ESRCH);
+		}
+		lf = mod->container;
+	} else
+		KASSERT(modname == NULL && verinfo == NULL,
+		    ("linker_release_module: both file and name"));
+	error =	linker_file_unload_internal(lf, LINKER_UNLOAD_NORMAL);
+	KLD_UNLOCK();
+	return (error);
+}
+
 static linker_file_t
 linker_find_file_by_name(const char *filename)
 {

==== //depot/projects/smpng/sys/kern/subr_firmware.c#3 (text+ko) ====

@@ -206,20 +206,17 @@
 unloadentry(void *unused1, int unused2)
 {
 	struct firmware *fp;
+	linker_file_t lf;
 
 	mtx_lock(&firmware_mtx);
 	while ((fp = lookup(name_unload))) {
-		/*
-		 * XXX: ugly, we should be able to lookup unlocked here if
-		 * we properly lock around clearentry below to avoid double
-		 * unload.  Play it safe for now.
-		 */
+		lf = fp->file;
+		clearentry(fp, 0);
 		mtx_unlock(&firmware_mtx);
 
-		linker_file_unload(fp->file, LINKER_UNLOAD_NORMAL);
+		linker_release_module(NULL, NULL, lf);
 
 		mtx_lock(&firmware_mtx);
-		clearentry(fp, 0);
 	}
 	mtx_unlock(&firmware_mtx);
 }

==== //depot/projects/smpng/sys/sys/linker.h#22 (text+ko) ====

@@ -111,6 +111,14 @@
 			    linker_file_t* _result);
 
 /*
+ * Release a reference to a module, unloading it if there are no more
+ * references.  Note that one should either provide a module name and
+ * optional version info or a linker file, but not both.
+ */
+int linker_release_module(const char *_modname, struct mod_depend *_verinfo,
+			  linker_file_t _file);
+
+/*
  * Unload a file, freeing up memory.
  */
 int linker_file_unload(linker_file_t _file, int flags);


More information about the p4-projects mailing list