From: Manfred Spraul sunrpc uses sleep_on to wait until the rpciod thread has died. This could race if rpciod_down is called without lock_kernel. Right now all calls in the main tree are under lock_kernel, but rpciod is an exported function and sleep_on should die. Additionally, I've replaced spin_lock_irqsave() with spin_lock_irq(): rpciod_down sleeps, interrupts are guaranteed to be enabled. --- net/sunrpc/sched.c | 19 +++++++++++++------ 1 files changed, 13 insertions(+), 6 deletions(-) diff -puN net/sunrpc/sched.c~sunrpc-sleep_on-removal net/sunrpc/sched.c --- 25/net/sunrpc/sched.c~sunrpc-sleep_on-removal 2004-01-19 13:35:41.000000000 -0800 +++ 25-akpm/net/sunrpc/sched.c 2004-01-19 13:35:41.000000000 -0800 @@ -1060,7 +1060,7 @@ out: void rpciod_down(void) { - unsigned long flags; + DECLARE_WAITQUEUE(wait, current); down(&rpciod_sema); dprintk("rpciod_down pid %d sema %d\n", rpciod_pid, rpciod_users); @@ -1085,17 +1085,24 @@ rpciod_down(void) /* * Display a message if we're going to wait longer. */ - while (rpciod_pid) { - dprintk("rpciod_down: waiting for pid %d to exit\n", rpciod_pid); + add_wait_queue(&rpciod_killer, &wait); + for (;;) { + set_current_state(TASK_INTERRUPTIBLE); + if (rpciod_pid == 0) + break; + dprintk("rpciod_down: waiting for pid %d to exit\n", + rpciod_pid); if (signalled()) { dprintk("rpciod_down: caught signal\n"); break; } - interruptible_sleep_on(&rpciod_killer); + schedule(); } - spin_lock_irqsave(¤t->sighand->siglock, flags); + __set_current_state(TASK_RUNNING); + remove_wait_queue(&rpciod_killer, &wait); + spin_lock_irq(¤t->sighand->siglock); recalc_sigpending(); - spin_unlock_irqrestore(¤t->sighand->siglock, flags); + spin_unlock_irq(¤t->sighand->siglock); out: up(&rpciod_sema); } _