Commit d28446fe authored by NeilBrown's avatar NeilBrown Committed by Linus Torvalds
Browse files

[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: default avatarNeil Brown <neilb@cse.unsw.edu.au>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 187a2784
Loading
Loading
Loading
Loading
+8 −12
Original line number Diff line number Diff line
@@ -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);
}