kern_linker: Handle module-loading failures in preloaded .ko files
The runtime kernel loader, linker_load_file, unloads kernel files that failed to load all of their modules. For consistency, treat preloaded (loader.conf loaded) kernel files in the same way. Reviewed by: kib Sponsored by: Dell EMC Isilon Differential Revision: https://reviews.freebsd.org/D8200
This commit is contained in:
parent
dd9e82f0e4
commit
56a5b1926a
@ -1599,7 +1599,6 @@ linker_preload(void *arg)
|
||||
if (error)
|
||||
panic("cannot add dependency");
|
||||
}
|
||||
lf->userrefs++; /* so we can (try to) kldunload it */
|
||||
error = linker_file_lookup_set(lf, MDT_SETNAME, &start,
|
||||
&stop, NULL);
|
||||
if (!error) {
|
||||
@ -1637,6 +1636,8 @@ linker_preload(void *arg)
|
||||
goto fail;
|
||||
}
|
||||
linker_file_register_modules(lf);
|
||||
if (!TAILQ_EMPTY(&lf->modules))
|
||||
lf->flags |= LINKER_FILE_MODULES;
|
||||
if (linker_file_lookup_set(lf, "sysinit_set", &si_start,
|
||||
&si_stop, NULL) == 0)
|
||||
sysinit_add(si_start, si_stop);
|
||||
@ -1653,6 +1654,41 @@ linker_preload(void *arg)
|
||||
|
||||
SYSINIT(preload, SI_SUB_KLD, SI_ORDER_MIDDLE, linker_preload, 0);
|
||||
|
||||
/*
|
||||
* Handle preload files that failed to load any modules.
|
||||
*/
|
||||
static void
|
||||
linker_preload_finish(void *arg)
|
||||
{
|
||||
linker_file_t lf, nlf;
|
||||
|
||||
sx_xlock(&kld_sx);
|
||||
TAILQ_FOREACH_SAFE(lf, &linker_files, link, nlf) {
|
||||
/*
|
||||
* If all of the modules in this file failed to load, unload
|
||||
* the file and return an error of ENOEXEC. (Parity with
|
||||
* linker_load_file.)
|
||||
*/
|
||||
if ((lf->flags & LINKER_FILE_MODULES) != 0 &&
|
||||
TAILQ_EMPTY(&lf->modules)) {
|
||||
linker_file_unload(lf, LINKER_UNLOAD_FORCE);
|
||||
continue;
|
||||
}
|
||||
|
||||
lf->flags &= ~LINKER_FILE_MODULES;
|
||||
lf->userrefs++; /* so we can (try to) kldunload it */
|
||||
}
|
||||
sx_xunlock(&kld_sx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to run after all DECLARE_MODULE SYSINITs. Unfortunately they can be
|
||||
* scheduled at any subsystem and order, so run this as late as possible. init
|
||||
* becomes runnable in SI_SUB_KTHREAD_INIT, so go slightly before that.
|
||||
*/
|
||||
SYSINIT(preload_finish, SI_SUB_KTHREAD_INIT - 100, SI_ORDER_MIDDLE,
|
||||
linker_preload_finish, 0);
|
||||
|
||||
/*
|
||||
* Search for a not-loaded module by name.
|
||||
*
|
||||
|
@ -73,6 +73,7 @@ struct linker_file {
|
||||
int userrefs; /* kldload(2) count */
|
||||
int flags;
|
||||
#define LINKER_FILE_LINKED 0x1 /* file has been fully linked */
|
||||
#define LINKER_FILE_MODULES 0x2 /* file has >0 modules at preload */
|
||||
TAILQ_ENTRY(linker_file) link; /* list of all loaded files */
|
||||
char* filename; /* file which was loaded */
|
||||
char* pathname; /* file name with full path */
|
||||
|
Loading…
Reference in New Issue
Block a user