Date: Thu, 25 May 2006 22:27:55 GMT From: John Baldwin <jhb@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 97831 for review Message-ID: <200605252227.k4PMRtfK078612@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=97831 Change 97831 by jhb@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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200605252227.k4PMRtfK078612>