1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-17 10:26:15 +00:00

Drop the global kernel linker lock while executing the sysinit's for a

freshly-loaded kernel module.  To avoid various unload races, hide linker
files whose sysinit's are being run from userland so that they can't be
kldunloaded until after all the sysinit's have finished.

Tested by:	gallatin
This commit is contained in:
John Baldwin 2007-02-23 19:46:59 +00:00
parent 0024ec11a6
commit 498eccc919
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=166921

View File

@ -403,8 +403,10 @@ linker_load_file(const char *filename, linker_file_t *result)
linker_file_unload(lf, LINKER_UNLOAD_FORCE);
return (error);
}
KLD_UNLOCK();
linker_file_register_sysctls(lf);
linker_file_sysinit(lf);
KLD_LOCK();
lf->flags |= LINKER_FILE_LINKED;
*result = lf;
return (0);
@ -502,7 +504,7 @@ linker_find_file_by_id(int fileid)
KLD_LOCK_ASSERT();
TAILQ_FOREACH(lf, &linker_files, link)
if (lf->id == fileid)
if (lf->id == fileid && lf->flags & LINKER_FILE_LINKED)
break;
return (lf);
}
@ -1033,21 +1035,25 @@ kldnext(struct thread *td, struct kldnext_args *uap)
#endif
KLD_LOCK();
if (uap->fileid == 0) {
if (TAILQ_FIRST(&linker_files))
td->td_retval[0] = TAILQ_FIRST(&linker_files)->id;
else
td->td_retval[0] = 0;
goto out;
if (uap->fileid == 0)
lf = TAILQ_FIRST(&linker_files);
else {
lf = linker_find_file_by_id(uap->fileid);
if (lf == NULL) {
error = ENOENT;
goto out;
}
lf = TAILQ_NEXT(lf, link);
}
lf = linker_find_file_by_id(uap->fileid);
if (lf) {
if (TAILQ_NEXT(lf, link))
td->td_retval[0] = TAILQ_NEXT(lf, link)->id;
else
td->td_retval[0] = 0;
} else
error = ENOENT;
/* Skip partially loaded files. */
while (lf != NULL && !(lf->flags & LINKER_FILE_LINKED))
lf = TAILQ_NEXT(lf, link);
if (lf)
td->td_retval[0] = lf->id;
else
td->td_retval[0] = 0;
out:
KLD_UNLOCK();
return (error);