diff options
author | NeilBrown <neilb@cse.unsw.edu.au> | 2005-04-16 18:26:41 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:26:41 -0400 |
commit | d28446fe2d87ea344c14741c39962dcc7aee5c78 (patch) | |
tree | b41bec77e5e5123f8f5349eb01ced9ee8fd9a924 /drivers | |
parent | 187a27845a9dc1c3da3995e24625ccf2e7a346aa (diff) |
[PATCH] md: close a small race in md thread deregistration
There is a tiny race when de-registering an MD thread, in that the thread
could disappear before it is set a SIGKILL, causing send_sig to have
problems.
This is most easily closed by holding tasklist_lock between enabling the
thread to exit (setting ->run to NULL) and telling it to exit.
(akpm: ick. Needs to use kthread API and stop using signals)
Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/md/md.c | 20 |
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, | |||
2840 | return thread; | 2840 | return thread; |
2841 | } | 2841 | } |
2842 | 2842 | ||
2843 | static void md_interrupt_thread(mdk_thread_t *thread) | ||
2844 | { | ||
2845 | if (!thread->tsk) { | ||
2846 | MD_BUG(); | ||
2847 | return; | ||
2848 | } | ||
2849 | dprintk("interrupting MD-thread pid %d\n", thread->tsk->pid); | ||
2850 | send_sig(SIGKILL, thread->tsk, 1); | ||
2851 | } | ||
2852 | |||
2853 | void md_unregister_thread(mdk_thread_t *thread) | 2843 | void md_unregister_thread(mdk_thread_t *thread) |
2854 | { | 2844 | { |
2855 | struct completion event; | 2845 | struct completion event; |
@@ -2857,9 +2847,15 @@ void md_unregister_thread(mdk_thread_t *thread) | |||
2857 | init_completion(&event); | 2847 | init_completion(&event); |
2858 | 2848 | ||
2859 | thread->event = &event; | 2849 | thread->event = &event; |
2850 | |||
2851 | /* As soon as ->run is set to NULL, the task could disappear, | ||
2852 | * so we need to hold tasklist_lock until we have sent the signal | ||
2853 | */ | ||
2854 | dprintk("interrupting MD-thread pid %d\n", thread->tsk->pid); | ||
2855 | read_lock(&tasklist_lock); | ||
2860 | thread->run = NULL; | 2856 | thread->run = NULL; |
2861 | thread->name = NULL; | 2857 | send_sig(SIGKILL, thread->tsk, 1); |
2862 | md_interrupt_thread(thread); | 2858 | read_unlock(&tasklist_lock); |
2863 | wait_for_completion(&event); | 2859 | wait_for_completion(&event); |
2864 | kfree(thread); | 2860 | kfree(thread); |
2865 | } | 2861 | } |