aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/md/md.c20
1 files changed, 8 insertions, 12 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index aa72c88a024f..44a164965546 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -2840,16 +2840,6 @@ mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev,
return thread;
}
-static void md_interrupt_thread(mdk_thread_t *thread)
-{
- if (!thread->tsk) {
- MD_BUG();
- return;
- }
- dprintk("interrupting MD-thread pid %d\n", thread->tsk->pid);
- send_sig(SIGKILL, thread->tsk, 1);
-}
-
void md_unregister_thread(mdk_thread_t *thread)
{
struct completion event;
@@ -2857,9 +2847,15 @@ void md_unregister_thread(mdk_thread_t *thread)
init_completion(&event);
thread->event = &event;
+
+ /* As soon as ->run is set to NULL, the task could disappear,
+ * so we need to hold tasklist_lock until we have sent the signal
+ */
+ dprintk("interrupting MD-thread pid %d\n", thread->tsk->pid);
+ read_lock(&tasklist_lock);
thread->run = NULL;
- thread->name = NULL;
- md_interrupt_thread(thread);
+ send_sig(SIGKILL, thread->tsk, 1);
+ read_unlock(&tasklist_lock);
wait_for_completion(&event);
kfree(thread);
}