linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Module rewrite 15/20: Forced Unload Support
@ 2002-09-25  3:18 Rusty Russell
  0 siblings, 0 replies; only message in thread
From: Rusty Russell @ 2002-09-25  3:18 UTC (permalink / raw)
  To: torvalds; +Cc: linux-kernel

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

D: Allows the (very dangerous!) "rmmod -f" for kernel developers and
D: desperate people.  It is currently under CONFIG_DEBUG_KERNEL, but it
D: could be moved out.

diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .10910-linux-2.5.38/arch/i386/Config.help .10910-linux-2.5.38.updated/arch/i386/Config.help
--- .10910-linux-2.5.38/arch/i386/Config.help	2002-09-18 16:04:37.000000000 +1000
+++ .10910-linux-2.5.38.updated/arch/i386/Config.help	2002-09-25 02:00:14.000000000 +1000
@@ -976,3 +976,10 @@ CONFIG_SOFTWARE_SUSPEND
   absence of features.
 
   For more information take a look at Documentation/swsusp.txt.
+
+CONFIG_MODULE_FORCE_UNLOAD
+  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.  In unsure, say N.
+
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .10910-linux-2.5.38/arch/i386/config.in .10910-linux-2.5.38.updated/arch/i386/config.in
--- .10910-linux-2.5.38/arch/i386/config.in	2002-09-21 13:55:07.000000000 +1000
+++ .10910-linux-2.5.38.updated/arch/i386/config.in	2002-09-25 02:00:14.000000000 +1000
@@ -436,6 +436,7 @@ if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; th
    if [ "$CONFIG_HIGHMEM" = "y" ]; then
       bool '  Highmem debugging' CONFIG_DEBUG_HIGHMEM
    fi
+   dep_bool '  Forced module removal' CONFIG_MODULE_FORCE_UNLOAD $CONFIG_MODULE_UNLOAD
 fi
 
 if [ "$CONFIG_X86_LOCAL_APIC" = "y" ]; then
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .10910-linux-2.5.38/include/linux/kernel.h .10910-linux-2.5.38.updated/include/linux/kernel.h
--- .10910-linux-2.5.38/include/linux/kernel.h	2002-09-25 01:59:44.000000000 +1000
+++ .10910-linux-2.5.38.updated/include/linux/kernel.h	2002-09-25 02:00:14.000000000 +1000
@@ -95,6 +95,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 .10910-linux-2.5.38/init/Config.help .10910-linux-2.5.38.updated/init/Config.help
--- .10910-linux-2.5.38/init/Config.help	2002-09-25 01:59:50.000000000 +1000
+++ .10910-linux-2.5.38.updated/init/Config.help	2002-09-25 02:00:14.000000000 +1000
@@ -93,7 +93,7 @@ CONFIG_MODULES
 
 CONFIG_MODULE_UNLOAD
   Without this option you will not be able to unload any modules (note
-  that some modules may not be unloadable anyway).  This makes your
+  that some modules may not be unloadable anyway), which makes your
   kernel slightly smaller and simpler.  If unsure, say Y.
 
 CONFIG_OBSOLETE_MODPARM
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .10910-linux-2.5.38/kernel/module.c .10910-linux-2.5.38.updated/kernel/module.c
--- .10910-linux-2.5.38/kernel/module.c	2002-09-25 01:59:51.000000000 +1000
+++ .10910-linux-2.5.38.updated/kernel/module.c	2002-09-25 02:01:30.000000000 +1000
@@ -191,12 +191,24 @@ static void module_unload_free(struct mo
 /* 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;
@@ -214,9 +226,12 @@ sys_delete_module(const char *name_user,
 		goto out;
 	}
 	if (!mod->exit || mod->unsafe_to_unload) {
-		/* This module can't be removed */
-		ret = -EBUSY;
-		goto out;
+		forced = try_force(flags);
+		if (!forced) {
+			/* 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. */
@@ -242,29 +257,42 @@ sys_delete_module(const char *name_user,
 
 	/* If they don't want to wait, and refcount non-zero, bring it
            back to life and report that we lost. */
-	if (((flags & O_NONBLOCK) && bigref_approx_val(&mod->use) != 0)
-	    || mod->unsafe_to_unload) {
-		mod->live = 1;
-		try_module_get(mod); /* Can't fail */
-		spin_lock_irq(&modlist_lock);
-		list_add(&mod->symbols.list, &kernel_symbols.list);
-		list_add(&mod->gpl_symbols.list, &kernel_symbols.list);
-		spin_unlock_irq(&modlist_lock);
-		ret = -EWOULDBLOCK;
-		goto out;
-	}
+	if ((flags & O_NONBLOCK) && bigref_approx_val(&mod->use) != 0)
+		if (!(forced = try_force(flags)))
+			goto reanimate;
 
-	/* Since it's not live, this should monotonically decrease. */
-	bigref_wait_for_zero(&mod->use);
+	/* It may have just become unsafe */
+	if (mod->unsafe_to_unload)
+		if (!(forced = try_force(flags)))
+			goto reanimate;
+
+	/* Since it's not live, count should monotonically decrease. */
+	if (!forced)
+		bigref_wait_for_zero(&mod->use);
+	else {
+		printk(KERN_WARNING "Forced removal of %s.\n", mod->name);
+		tainted |= TAINT_FORCED_RMMOD;
+	}
 
 	/* Final destruction now noone is using it. */
-	mod->exit();
+	if (mod->exit)
+		mod->exit();
 	free_module(mod);
 	ret = 0;
 
  out:
 	up(&module_mutex);
 	return ret;
+
+ reanimate:
+	mod->live = 1;
+	try_module_get(mod); /* Can't fail */
+	spin_lock_irq(&modlist_lock);
+	list_add(&mod->symbols.list, &kernel_symbols.list);
+	list_add(&mod->gpl_symbols.list, &kernel_symbols.list);
+	spin_unlock_irq(&modlist_lock);
+	ret = -EWOULDBLOCK;
+	goto out;
 }
 
 static void print_unload_info(struct seq_file *m, struct module *mod)

--
  Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2002-09-25  3:35 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-09-25  3:18 [PATCH] Module rewrite 15/20: Forced Unload Support Rusty Russell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).