lkml.org 
[lkml]   [2002]   [Nov]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH] Forced module unload
Date
This allows you to use "rmmod -f" to remove "unremovable" modules
(ie. marked unsafe, still holding refcount or don't have
a module_cleanup decl).

Cheers,
Rusty.

Name: Forced Module Unload
Author: Rusty Russell
Status: Experimental
Depends: Module/module.patch.gz

D: Allows the (very dangerous!) "rmmod -f" for kernel developers and
D: desperate people.

diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .9002-linux-2.5.45/include/linux/kernel.h .9002-linux-2.5.45.updated/include/linux/kernel.h
--- .9002-linux-2.5.45/include/linux/kernel.h 2002-10-19 17:48:10.000000000 +1000
+++ .9002-linux-2.5.45.updated/include/linux/kernel.h 2002-11-01 11:52:04.000000000 +1100
@@ -102,6 +102,7 @@ extern const char *print_tainted(void);
#define TAINT_PROPRIETORY_MODULE (1<<0)
#define TAINT_FORCED_MODULE (1<<1)
#define TAINT_UNSAFE_SMP (1<<2)
+#define TAINT_FORCED_RMMOD (1<<3)

extern void dump_stack(void);

diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .9002-linux-2.5.45/init/Kconfig .9002-linux-2.5.45.updated/init/Kconfig
--- .9002-linux-2.5.45/init/Kconfig 2002-11-01 11:51:08.000000000 +1100
+++ .9002-linux-2.5.45.updated/init/Kconfig 2002-11-01 11:55:00.000000000 +1100
@@ -125,6 +125,16 @@ config MODULE_UNLOAD
anyway), which makes your kernel slightly smaller and
simpler. If unsure, say Y.

+config MODULE_FORCE_UNLOAD
+ bool "Forced module unloading"
+ depends on MODULES && EXPERIMENTAL
+ help
+ This option allows you to force a module to unload, even if the
+ kernel believes it is unsafe: the kernel will remove the module
+ without waiting for anyone to stop using it (using the -f option to
+ rmmod). This is mainly for kernel developers and desparate users.
+ If unsure, say N.
+
config KMOD
bool "Kernel module loader"
depends on MODULES
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .9002-linux-2.5.45/kernel/module.c .9002-linux-2.5.45.updated/kernel/module.c
--- .9002-linux-2.5.45/kernel/module.c 2002-11-01 11:51:08.000000000 +1100
+++ .9002-linux-2.5.45.updated/kernel/module.c 2002-11-01 11:52:04.000000000 +1100
@@ -335,12 +335,24 @@ static unsigned int module_refcount(stru
/* This exists whether we can unload or not */
static void free_module(struct module *mod);

+#ifdef CONFIG_MODULE_FORCE_UNLOAD
+static inline int try_force(unsigned int flags)
+{
+ return (flags & O_TRUNC);
+}
+#else
+static inline int try_force(unsigned int flags)
+{
+ return 0;
+}
+#endif /* CONFIG_MODULE_FORCE_UNLOAD */
+
asmlinkage long
sys_delete_module(const char *name_user, unsigned int flags)
{
struct module *mod;
char name[MODULE_NAME_LEN];
- int ret;
+ int ret, forced = 0;

if (!capable(CAP_SYS_MODULE))
return -EPERM;
@@ -358,24 +370,29 @@ sys_delete_module(const char *name_user,
goto out;
}

+ if (!list_empty(&mod->modules_which_use_me)) {
+ /* Other modules depend on us: get rid of them first. */
+ ret = -EWOULDBLOCK;
+ goto out;
+ }
+
/* Already dying? */
if (!mod->live) {
+ /* FIXME: if (force), slam module count and wake up
+ waiter --RR */
DEBUGP("%s already dying\n", mod->name);
ret = -EBUSY;
goto out;
}

if (!mod->exit || mod->unsafe) {
- /* This module can't be removed */
- ret = -EBUSY;
- goto out;
- }
- if (!list_empty(&mod->modules_which_use_me)) {
- /* Other modules depend on us: get rid of them first. */
- ret = -EWOULDBLOCK;
- goto out;
+ forced = try_force(flags);
+ if (!forced) {
+ /* This module can't be removed */
+ ret = -EBUSY;
+ goto out;
+ }
}
-
/* Stop the machine so refcounts can't move: irqs disabled. */
DEBUGP("Stopping refcounts...\n");
ret = stop_refcounts();
@@ -383,9 +400,11 @@ sys_delete_module(const char *name_user,
goto out;

/* If it's not unused, quit unless we are told to block. */
- if ((flags & O_NONBLOCK) && module_refcount(mod) != 0)
- ret = -EWOULDBLOCK;
- else {
+ if ((flags & O_NONBLOCK) && module_refcount(mod) != 0) {
+ forced = try_force(flags);
+ if (!forced)
+ ret = -EWOULDBLOCK;
+ } else {
mod->waiter = current;
mod->live = 0;
}
@@ -394,6 +413,9 @@ sys_delete_module(const char *name_user,
if (ret != 0)
goto out;

+ if (forced)
+ goto destroy;
+
/* Since we might sleep for some time, drop the semaphore first */
up(&module_mutex);
for (;;) {
@@ -408,10 +430,11 @@ sys_delete_module(const char *name_user,
DEBUGP("Regrabbing mutex...\n");
down(&module_mutex);

+ destroy:
/* Final destruction now noone is using it. */
- mod->exit();
+ if (mod->exit)
+ mod->exit();
free_module(mod);
- ret = 0;

out:
up(&module_mutex);
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:31    [W:0.018 / U:0.044 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site