(Note: Patch also attached because the inline version is certain to get
line wrapped.)

Debugging and maintenance support code occasionally needs to know not
only of module insertions, but also modulke removals. This adds a notifier
chain for this purpose.

Signed-off-by: Jan Beulich <jbeulich@novell.com>

diff -Npru 2.6.13/include/linux/module.h 2.6.13-rmmod-notify/include/linux/module.h
--- 2.6.13/include/linux/module.h	2005-08-29 01:41:01.000000000 +0200
+++ 2.6.13-rmmod-notify/include/linux/module.h	2005-09-09 10:28:29.490342264 +0200
@@ -210,6 +210,7 @@ enum module_state
 	MODULE_STATE_LIVE,
 	MODULE_STATE_COMING,
 	MODULE_STATE_GOING,
+	MODULE_STATE_GONE
 };
 
 /* Similar stuff for section attributes. */
diff -Npru 2.6.13/kernel/module.c 2.6.13-rmmod-notify/kernel/module.c
--- 2.6.13/kernel/module.c	2005-08-29 01:41:01.000000000 +0200
+++ 2.6.13-rmmod-notify/kernel/module.c	2005-09-09 10:29:10.935041712 +0200
@@ -1165,6 +1165,10 @@ static int __unlink_module(void *_mod)
 /* Free a module, remove from lists, etc (must hold module mutex). */
 static void free_module(struct module *mod)
 {
+	down(&notify_mutex);
+	notifier_call_chain(&module_notify_list, MODULE_STATE_GONE, mod);
+	up(&notify_mutex);
+
 	/* Delete from various lists */
 	stop_machine_run(__unlink_module, mod, NR_CPUS);
 	remove_sect_attrs(mod);
@@ -1910,9 +1914,13 @@ sys_init_module(void __user *umod,
                    buggy refcounters. */
 		mod->state = MODULE_STATE_GOING;
 		synchronize_sched();
-		if (mod->unsafe)
+		if (mod->unsafe) {
 			printk(KERN_ERR "%s: module is now stuck!\n",
 			       mod->name);
+			down(&notify_mutex);
+			notifier_call_chain(&module_notify_list, MODULE_STATE_GONE, mod);
+			up(&notify_mutex);
+		}
 		else {
 			module_put(mod);
 			down(&module_mutex);
