summaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorPoul-Henning Kamp <phk@FreeBSD.org>2004-07-13 19:36:59 +0000
committerPoul-Henning Kamp <phk@FreeBSD.org>2004-07-13 19:36:59 +0000
commit65a311fcb2f44fce7eb05160d3198cefed5c27f9 (patch)
treed2eb15e6477b3d5e7e1f7c49c1e2eed3b85ec318 /sys/kern
parent1a946b9fef9f4b4cd10611232e8844d4c2d33e69 (diff)
Notes
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/init_sysent.c3
-rw-r--r--sys/kern/kern_linker.c49
-rw-r--r--sys/kern/kern_module.c8
-rw-r--r--sys/kern/link_elf.c4
-rw-r--r--sys/kern/link_elf_obj.c2
-rw-r--r--sys/kern/syscalls.c3
-rw-r--r--sys/kern/vfs_mount.c2
7 files changed, 53 insertions, 18 deletions
diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c
index 9d0ecade6a44..1185cf817f81 100644
--- a/sys/kern/init_sysent.c
+++ b/sys/kern/init_sysent.c
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: src/sys/kern/syscalls.master,v 1.174 2004/07/02 00:35:52 marcel Exp
+ * created from FreeBSD: src/sys/kern/syscalls.master,v 1.176 2004/07/13 19:35:10 phk Exp
*/
#include "opt_compat.h"
@@ -472,4 +472,5 @@ struct sysent sysent[] = {
{ SYF_MPSAFE | AS(ksem_timedwait_args), (sy_call_t *)lkmressys }, /* 441 = ksem_timedwait */
{ SYF_MPSAFE | AS(thr_suspend_args), (sy_call_t *)thr_suspend }, /* 442 = thr_suspend */
{ SYF_MPSAFE | AS(thr_wake_args), (sy_call_t *)thr_wake }, /* 443 = thr_wake */
+ { SYF_MPSAFE | AS(kldunloadf_args), (sy_call_t *)kldunloadf }, /* 444 = kldunloadf */
};
diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c
index 4ad549eec183..d2a2329a4880 100644
--- a/sys/kern/kern_linker.c
+++ b/sys/kern/kern_linker.c
@@ -466,7 +466,7 @@ out:
}
int
-linker_file_unload(linker_file_t file)
+linker_file_unload(linker_file_t file, int flags)
{
module_t mod, next;
modlist_t ml, nextml;
@@ -500,7 +500,7 @@ linker_file_unload(linker_file_t file)
/*
* Give the module a chance to veto the unload.
*/
- if ((error = module_unload(mod)) != 0) {
+ if ((error = module_unload(mod, flags)) != 0) {
KLD_DPF(FILE, ("linker_file_unload: module %p"
" vetoes unload\n", mod));
goto out;
@@ -536,7 +536,7 @@ linker_file_unload(linker_file_t file)
if (file->deps) {
for (i = 0; i < file->ndeps; i++)
- linker_file_unload(file->deps[i]);
+ linker_file_unload(file->deps[i], flags);
free(file->deps, M_LINKER);
file->deps = NULL;
}
@@ -789,8 +789,8 @@ out:
/*
* MPSAFE
*/
-int
-kldunload(struct thread *td, struct kldunload_args *uap)
+static int
+kern_kldunload(struct thread *td, int fileid, int flags)
{
linker_file_t lf;
int error = 0;
@@ -803,17 +803,20 @@ kldunload(struct thread *td, struct kldunload_args *uap)
if ((error = suser(td)) != 0)
goto out;
- lf = linker_find_file_by_id(uap->fileid);
+ lf = linker_find_file_by_id(fileid);
if (lf) {
KLD_DPF(FILE, ("kldunload: lf->userrefs=%d\n", lf->userrefs));
if (lf->userrefs == 0) {
+ /*
+ * XXX: maybe LINKER_UNLOAD_FORCE should override ?
+ */
printf("kldunload: attempt to unload file that was"
" loaded by the kernel\n");
error = EBUSY;
goto out;
}
lf->userrefs--;
- error = linker_file_unload(lf);
+ error = linker_file_unload(lf, flags);
if (error)
lf->userrefs++;
} else
@@ -827,6 +830,29 @@ out:
* MPSAFE
*/
int
+kldunload(struct thread *td, struct kldunload_args *uap)
+{
+
+ return (kern_kldunload(td, uap->fileid, LINKER_UNLOAD_NORMAL));
+}
+
+/*
+ * MPSAFE
+ */
+int
+kldunloadf(struct thread *td, struct kldunloadf_args *uap)
+{
+
+ if (uap->flags != LINKER_UNLOAD_NORMAL &&
+ uap->flags != LINKER_UNLOAD_FORCE)
+ return (EINVAL);
+ return (kern_kldunload(td, uap->fileid, uap->flags));
+}
+
+/*
+ * MPSAFE
+ */
+int
kldfind(struct thread *td, struct kldfind_args *uap)
{
char *pathname;
@@ -1250,7 +1276,8 @@ restart:
nver) != NULL) {
printf("module %s already"
" present!\n", modname);
- linker_file_unload(lf);
+ linker_file_unload(lf,
+ LINKER_UNLOAD_FORCE);
TAILQ_REMOVE(&loaded_files,
lf, loaded);
/* we changed tailq next ptr */
@@ -1276,7 +1303,7 @@ restart:
*/
TAILQ_FOREACH(lf, &loaded_files, loaded) {
printf("KLD file %s is missing dependencies\n", lf->filename);
- linker_file_unload(lf);
+ linker_file_unload(lf, LINKER_UNLOAD_FORCE);
TAILQ_REMOVE(&loaded_files, lf, loaded);
}
@@ -1317,7 +1344,7 @@ restart:
if (error) {
printf("KLD file %s - could not finalize loading\n",
lf->filename);
- linker_file_unload(lf);
+ linker_file_unload(lf, LINKER_UNLOAD_FORCE);
continue;
}
linker_file_register_modules(lf);
@@ -1676,7 +1703,7 @@ linker_load_module(const char *kldname, const char *modname,
break;
if (modname && verinfo &&
modlist_lookup2(modname, verinfo) == NULL) {
- linker_file_unload(lfdep);
+ linker_file_unload(lfdep, LINKER_UNLOAD_FORCE);
error = ENOENT;
break;
}
diff --git a/sys/kern/kern_module.c b/sys/kern/kern_module.c
index 3832922f5961..158612e822c1 100644
--- a/sys/kern/kern_module.c
+++ b/sys/kern/kern_module.c
@@ -215,9 +215,15 @@ module_lookupbyid(int modid)
}
int
-module_unload(module_t mod)
+module_unload(module_t mod, int flags)
{
+ int error;
+ error = MOD_EVENT(mod, MOD_QUIESCE);
+ if (error == EOPNOTSUPP)
+ error = 0;
+ if (flags == LINKER_UNLOAD_NORMAL && error != 0)
+ return (error);
return (MOD_EVENT(mod, MOD_UNLOAD));
}
diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c
index 0f00d904a978..5679cbf2f3fa 100644
--- a/sys/kern/link_elf.c
+++ b/sys/kern/link_elf.c
@@ -492,7 +492,7 @@ link_elf_link_preload(linker_class_t cls,
error = parse_dynamic(ef);
if (error) {
- linker_file_unload(lf);
+ linker_file_unload(lf, LINKER_UNLOAD_FORCE);
return error;
}
link_elf_reloc_local(lf);
@@ -846,7 +846,7 @@ nosyms:
out:
if (error && lf)
- linker_file_unload(lf);
+ linker_file_unload(lf, LINKER_UNLOAD_FORCE);
if (shdr)
free(shdr, M_LINKER);
if (firstpage)
diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c
index 9049880fe8fb..e5fa30e98045 100644
--- a/sys/kern/link_elf_obj.c
+++ b/sys/kern/link_elf_obj.c
@@ -588,7 +588,7 @@ link_elf_load_file(linker_class_t cls, const char *filename,
out:
if (error && lf)
- linker_file_unload(lf);
+ linker_file_unload(lf, LINKER_UNLOAD_FORCE);
if (hdr)
free(hdr, M_LINKER);
VOP_UNLOCK(nd.ni_vp, 0, td);
diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c
index 202c7d136c77..9a2f79556b91 100644
--- a/sys/kern/syscalls.c
+++ b/sys/kern/syscalls.c
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: src/sys/kern/syscalls.master,v 1.174 2004/07/02 00:35:52 marcel Exp
+ * created from FreeBSD: src/sys/kern/syscalls.master,v 1.176 2004/07/13 19:35:10 phk Exp
*/
const char *syscallnames[] = {
@@ -451,4 +451,5 @@ const char *syscallnames[] = {
"ksem_timedwait", /* 441 = ksem_timedwait */
"thr_suspend", /* 442 = thr_suspend */
"thr_wake", /* 443 = thr_wake */
+ "kldunloadf", /* 444 = kldunloadf */
};
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
index d697499a80a7..cf7b7c127257 100644
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -799,7 +799,7 @@ vfs_domount(
break;
if (vfsp == NULL) {
lf->userrefs--;
- linker_file_unload(lf);
+ linker_file_unload(lf, LINKER_UNLOAD_FORCE);
vput(vp);
return (ENODEV);
}