From: Ingo Molnar I have 3 more NFS related changes in the -RT tree: - convert sleep_on() to wait_event_timeout(). Probably safe with the BKL but could be racy once BKL use in NFS-client is gone. - the rpc_delete_timer() change & debugging conditions i picked up from the timer-races thread. No testing update, other than these changes didnt break anything, nor did the debugging messages trigger. - drop the BKL at module exit time - just for symmetry reasons which ones should i keep/drop? Cc: Trond Myklebust Signed-off-by: Andrew Morton --- fs/nfsd/nfssvc.c | 1 + net/sunrpc/clnt.c | 3 ++- net/sunrpc/sched.c | 8 ++++++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff -puN fs/nfsd/nfssvc.c~ingo-nfs-stuff fs/nfsd/nfssvc.c --- 25/fs/nfsd/nfssvc.c~ingo-nfs-stuff 2005-06-24 02:25:51.000000000 -0700 +++ 25-akpm/fs/nfsd/nfssvc.c 2005-06-24 02:25:51.000000000 -0700 @@ -286,6 +286,7 @@ out: /* Release the thread */ svc_exit_thread(rqstp); + unlock_kernel(); /* Release module */ module_put_and_exit(0); } diff -puN net/sunrpc/clnt.c~ingo-nfs-stuff net/sunrpc/clnt.c --- 25/net/sunrpc/clnt.c~ingo-nfs-stuff 2005-06-24 02:25:51.000000000 -0700 +++ 25-akpm/net/sunrpc/clnt.c 2005-06-24 02:25:51.000000000 -0700 @@ -267,7 +267,8 @@ rpc_shutdown_client(struct rpc_clnt *cln clnt->cl_oneshot = 0; clnt->cl_dead = 0; rpc_killall_tasks(clnt); - sleep_on_timeout(&destroy_wait, 1*HZ); + wait_event_timeout(destroy_wait, + atomic_read(&clnt->cl_users) > 0, 1*HZ); } if (atomic_read(&clnt->cl_users) < 0) { diff -puN net/sunrpc/sched.c~ingo-nfs-stuff net/sunrpc/sched.c --- 25/net/sunrpc/sched.c~ingo-nfs-stuff 2005-06-24 02:25:51.000000000 -0700 +++ 25-akpm/net/sunrpc/sched.c 2005-06-24 02:27:50.000000000 -0700 @@ -135,8 +135,6 @@ __rpc_add_timer(struct rpc_task *task, r static void rpc_delete_timer(struct rpc_task *task) { - if (RPC_IS_QUEUED(task)) - return; if (test_and_clear_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate)) { del_singleshot_timer_sync(&task->tk_timer); dprintk("RPC: %4d deleting timer\n", task->tk_pid); @@ -337,6 +335,8 @@ static void __rpc_sleep_on(struct rpc_wa void rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task, rpc_action action, rpc_action timer) { + BUG_ON(test_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate) != 0 || + timer_pending(&task->tk_timer)); /* * Protect the queue operations. */ @@ -625,6 +625,8 @@ static int __rpc_execute(struct rpc_task unlock_kernel(); } + BUG_ON(test_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate) != 0 || + timer_pending(&task->tk_timer)); /* * Perform the next FSM step. * tk_action may be NULL when the task has been killed @@ -937,6 +939,8 @@ fail: void rpc_run_child(struct rpc_task *task, struct rpc_task *child, rpc_action func) { + BUG_ON(test_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate) != 0 || + timer_pending(&task->tk_timer)); spin_lock_bh(&childq.lock); /* N.B. Is it possible for the child to have already finished? */ __rpc_sleep_on(&childq, task, func, NULL); _