summaryrefslogtreecommitdiffstats
path: root/kernel/module.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-03-17 22:05:47 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-03-17 22:05:47 +0000
commit27cfca1ec98e91261b1a5355d10a8996464b63af (patch)
tree8e895a53e372fa682b4c0a585b9377d67ed70d0e /kernel/module.c
parent6a76fb7214c477ccf6582bd79c5b4ccc4f9c41b1 (diff)
Look Ma' what I found on my harddisk ...
o New faster syscalls for 2.1.x, too o Upgrade to 2.1.89. Don't try to run this. It's flaky as hell. But feel free to debug ...
Diffstat (limited to 'kernel/module.c')
-rw-r--r--kernel/module.c49
1 files changed, 32 insertions, 17 deletions
diff --git a/kernel/module.c b/kernel/module.c
index 83479fa03..efee5902e 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -54,7 +54,7 @@ struct module *module_list = &kernel_module;
static long get_mod_name(const char *user_name, char **buf);
static void put_mod_name(char *buf);
static struct module *find_module(const char *name);
-static void free_module(struct module *);
+static void free_module(struct module *, int tag_freed);
/*
@@ -305,17 +305,17 @@ sys_init_module(const char *name_user, struct module *mod_user)
for (i = 0, dep = mod->deps; i < mod->ndeps; ++i, ++dep) {
struct module *o, *d = dep->dep;
- /* Make sure the indicated dependancies are really modules. */
+ /* Make sure the indicated dependencies are really modules. */
if (d == mod) {
printk(KERN_ERR "init_module: self-referential "
- "dependancy in mod->deps.\n");
+ "dependency in mod->deps.\n");
goto err3;
}
for (o = module_list; o != &kernel_module; o = o->next)
if (o == d) goto found_dep;
- printk(KERN_ERR "init_module: found dependancy that is "
+ printk(KERN_ERR "init_module: found dependency that is "
"(no longer?) a module.\n");
goto err3;
@@ -363,6 +363,7 @@ sys_delete_module(const char *name_user)
struct module *mod, *next;
char *name;
long error = -EPERM;
+ int something_changed;
lock_kernel();
if (!suser())
@@ -386,25 +387,35 @@ sys_delete_module(const char *name_user)
if (mod->refs != NULL || __MOD_IN_USE(mod))
goto out;
- free_module(mod);
+ free_module(mod, 0);
error = 0;
goto out;
}
/* Do automatic reaping */
+restart:
+ something_changed = 0;
for (mod = module_list; mod != &kernel_module; mod = next) {
next = mod->next;
- if (mod->refs == NULL &&
- ((mod->flags
- & (MOD_AUTOCLEAN|MOD_RUNNING|MOD_DELETED|MOD_USED_ONCE))
- == (MOD_AUTOCLEAN|MOD_RUNNING|MOD_USED_ONCE)) &&
- !__MOD_IN_USE(mod)) {
- if (mod->flags & MOD_VISITED)
+ if (mod->refs == NULL
+ && (mod->flags & MOD_AUTOCLEAN)
+ && (mod->flags & MOD_RUNNING)
+ && !(mod->flags & MOD_DELETED)
+ && (mod->flags & MOD_USED_ONCE)
+ && !__MOD_IN_USE(mod)) {
+ if ((mod->flags & MOD_VISITED)
+ && !(mod->flags & MOD_JUST_FREED)) {
mod->flags &= ~MOD_VISITED;
- else
- free_module(mod);
+ } else {
+ free_module(mod, 1);
+ something_changed = 1;
+ }
}
}
+ if (something_changed)
+ goto restart;
+ for (mod = module_list; mod != &kernel_module; mod = mod->next)
+ mod->flags &= ~MOD_JUST_FREED;
error = 0;
out:
unlock_kernel();
@@ -764,7 +775,7 @@ find_module(const char *name)
*/
static void
-free_module(struct module *mod)
+free_module(struct module *mod, int tag_freed)
{
struct module_ref *dep;
unsigned i;
@@ -772,18 +783,22 @@ free_module(struct module *mod)
/* Let the module clean up. */
mod->flags |= MOD_DELETED;
- if (mod->flags & MOD_RUNNING) {
- mod->cleanup();
+ if (mod->flags & MOD_RUNNING)
+ {
+ if(mod->cleanup)
+ mod->cleanup();
mod->flags &= ~MOD_RUNNING;
}
- /* Remove the module from the dependancy lists. */
+ /* Remove the module from the dependency lists. */
for (i = 0, dep = mod->deps; i < mod->ndeps; ++i, ++dep) {
struct module_ref **pp;
for (pp = &dep->dep->refs; *pp != dep; pp = &(*pp)->next_ref)
continue;
*pp = dep->next_ref;
+ if (tag_freed && dep->dep->refs == NULL)
+ dep->dep->flags |= MOD_JUST_FREED;
}
/* And from the main module list. */