MFC kern_linker.c 1.133 and related changes:

- push Giant into linker_reference_module();
- introduce linker_release_module(), which also takes care of
  proper locking.

The latter also fixes a missing mtx_loc/unlock in subr_firmware.c .

Apparently, digi.c is the only external client of linker_reference_module()
which is a bit suspicious - perhaps dev/digi/ could make with a bit
of review from someone knowledgeable to check how the function is used,
and whether it could be replaced by something else.
This commit is contained in:
luigi 2007-02-15 19:49:27 +00:00
parent 1228e65f75
commit d87a62d43f
4 changed files with 43 additions and 7 deletions

View File

@ -795,7 +795,7 @@ digi_loadmoduledata(struct digi_softc *sc)
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 @@ digi_loadmoduledata(struct digi_softc *sc)
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 @@ digi_loadmoduledata(struct digi_softc *sc)
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);
}

View File

@ -397,14 +397,44 @@ linker_reference_module(const char *modname, struct mod_depend *verinfo,
linker_file_t *result)
{
modlist_t mod;
int error;
mtx_lock(&Giant);
if ((mod = modlist_lookup2(modname, verinfo)) != NULL) {
*result = mod->container;
(*result)->refs++;
mtx_unlock(&Giant);
return (0);
}
return (linker_load_module(NULL, modname, NULL, verinfo, result));
error = linker_load_module(NULL, modname, NULL, verinfo, result);
mtx_unlock(&Giant);
return (error);
}
int
linker_release_module(const char *modname, struct mod_depend *verinfo,
linker_file_t lf)
{
modlist_t mod;
int error;
mtx_lock(&Giant);
if (lf == NULL) {
KASSERT(modname != NULL,
("linker_release_module: no file or name"));
mod = modlist_lookup2(modname, verinfo);
if (mod == NULL) {
mtx_unlock(&Giant);
return (ESRCH);
}
lf = mod->container;
} else
KASSERT(modname == NULL && verinfo == NULL,
("linker_release_module: both file and name"));
error = linker_file_unload(lf, LINKER_UNLOAD_NORMAL);
mtx_unlock(&Giant);
return (error);
}
linker_file_t

View File

@ -197,9 +197,7 @@ firmware_get(const char *imagename)
"load firmware image %s\n", __func__, imagename);
return NULL;
}
mtx_lock(&Giant); /* XXX */
(void) linker_reference_module(imagename, NULL, &result);
mtx_unlock(&Giant); /* XXX */
requested_load = 1;
goto again; /* sort of an Algol-style for loop */
}
@ -218,7 +216,7 @@ unloadentry(void *unused1, int unused2)
*/
mtx_unlock(&firmware_mtx);
linker_file_unload(fp->file, LINKER_UNLOAD_NORMAL);
linker_release_module(NULL, NULL, fp->file);
mtx_lock(&firmware_mtx);
clearentry(fp, 0);

View File

@ -117,6 +117,14 @@ int linker_load_module(const char *_kldname, const char *_modname,
int linker_reference_module(const char* _modname, struct mod_depend *_verinfo,
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);
/*
* Find a currently loaded file given its filename.
*/