OK. I've flung together a prototype.
It doesn't immediately crash.... --- linux-official/kernel/module.c Fri Jun 9 23:00:28 2000
+++ linux-akpm/kernel/module.c Sun Jun 25 01:15:57 2000
@@ -365,17 +365,14 @@
return res;
}
-asmlinkage long
-sys_delete_module(const char *name_user)
+static long
+do_sys_delete_module(const char *name_user)
{
struct module *mod, *next;
char *name;
long error;
int something_changed;
- if (!capable(CAP_SYS_MODULE))
- return -EPERM;
-
lock_kernel();
if (name_user) {
if ((error = get_mod_name(name_user, &name)) < 0)
@@ -442,6 +439,75 @@
unlock_kernel();
return error;
}
+
+#ifdef CONFIG_SMP
+static volatile int ice_block;
+static spinlock_t freeze_lock = SPIN_LOCK_UNLOCKED;
+
+static int
+antarctica(void *dummy)
+{
+ printk("start antarctica on %d\n", smp_processor_id());
+ while (ice_block)
+ ;
+ printk("stop antarctica on %d\n", smp_processor_id());
+ return 0;
+}
+
+static int
+freeze_other_cpus(void)
+{
+ int cpu, retval;
+
+ if (!spin_trylock(&freeze_lock))
+ return -EAGAIN;
+
+ printk("start freeze_other_cpus()\n");
+ ice_block = 1;
+ for (cpu = 0; cpu < smp_num_cpus - 1; cpu++) {
+ retval = kernel_thread(antarctica, (void *)0, 0);
+ if (retval < 0)
+ goto out_melt;
+ }
+ printk("continue freeze_other_cpus()\n");
+ return 0;
+out_melt:
+ ice_block = 0;
+ spin_unlock(&freeze_lock);
+ return retval;
+}
+
+static void
+melt_other_cpus(void)
+{
+ printk("melt_other_cpus() starts\n");
+ ice_block = 0;
+ spin_unlock(&freeze_lock);
+ printk("melt_other_cpus() stops\n");
+}
+
+#else /* CONFIG_SMP */
+
+#define freeze_other_cpus() 0
+#define melt_other_cpus() do { } while (0)
+#endif
+
+asmlinkage long
+sys_delete_module(const char *name_user)
+{
+ long ret;
+
+ if (!capable(CAP_SYS_MODULE))
+ return -EPERM;
+
+ if ((ret = freeze_other_cpus()))
+ return ret;
+
+ ret = do_sys_delete_module(name_user);
+ melt_other_cpus();
+ return ret;
+}
+
/* Query various bits about modules. */
|