From: Rusty Russell <rusty@rustcorp.com.au>

We can't just return from kthread when something goes wrong: use goto. 
Also, we wake then immediately kthread_stop() the thread: it's possible
that it may not have run the function at all yet.  Use a completion.



---

 kernel/module.c |   12 ++++++++++--
 1 files changed, 10 insertions(+), 2 deletions(-)

diff -puN kernel/module.c~module-removal-use-kthread-fixes kernel/module.c
--- 25/kernel/module.c~module-removal-use-kthread-fixes	2004-02-03 21:06:15.000000000 -0800
+++ 25-akpm/kernel/module.c	2004-02-03 21:06:15.000000000 -0800
@@ -568,6 +568,7 @@ struct stopref
 	struct module *mod;
 	int flags;
 	int *forced;
+	struct completion started;
 };
 
 static int spawn_stopref(void *data)
@@ -577,6 +578,8 @@ static int spawn_stopref(void *data)
 	unsigned int i, cpu = smp_processor_id();
 	int ret = 0;
 
+	complete(&sref->started);
+
 	/* One high-prio thread per cpu.  We'll do one (any one). */
 	set_cpus_allowed(current, cpumask_of_cpu(cpu));
 	sys_sched_setscheduler(current->pid, SCHED_FIFO, &param);
@@ -601,7 +604,7 @@ static int spawn_stopref(void *data)
 	/* If some failed, kill them all. */
 	if (ret < 0) {
 		stopref_set_state(STOPREF_EXIT, 1);
-		return ret;
+		goto out;
 	}
 
 	/* Don't schedule us away at this point, please. */
@@ -619,6 +622,7 @@ static int spawn_stopref(void *data)
 	stopref_set_state(STOPREF_EXIT, 0);
 	preempt_enable();
 
+out:
 	/* Wait for kthread_stop */
 	while (!signal_pending(current)) {
 		__set_current_state(TASK_INTERRUPTIBLE);
@@ -633,13 +637,17 @@ static int try_stop_module(struct module
 	struct stopref sref = { mod, flags, forced };
 	int ret;
 
+	init_completion(&sref.started);
+
 	/* No CPUs can come up or down during this. */
 	lock_cpu_hotplug();
 	p = kthread_run(spawn_stopref, &sref, "krmmod");
 	if (IS_ERR(p))
 		ret = PTR_ERR(p);
-	else
+	else {
+		wait_for_completion(&sref.started);
 		ret = kthread_stop(p);
+	}
 	unlock_cpu_hotplug();
 	return ret;
 }

_