From: Trond Myklebust RPC: Sync rpc_set_timeo() up to the 2.4.x version. In particular, this will ensure that the timeout shift is clamped to a maximum value of 8. RPC: Fix by Olaf Kirch to the rpc scheduler to ensure sync tasks respect the "intr" mount flag. --- include/linux/sunrpc/timer.h | 11 ++++++++++- net/sunrpc/sched.c | 23 ++++++++++++++--------- 2 files changed, 24 insertions(+), 10 deletions(-) diff -puN include/linux/sunrpc/timer.h~nfs-misc-rpc-fixes include/linux/sunrpc/timer.h --- 25/include/linux/sunrpc/timer.h~nfs-misc-rpc-fixes 2004-02-28 18:21:19.000000000 -0800 +++ 25-akpm/include/linux/sunrpc/timer.h 2004-02-28 18:21:19.000000000 -0800 @@ -25,9 +25,18 @@ extern unsigned long rpc_calc_rto(struct static inline void rpc_set_timeo(struct rpc_rtt *rt, int timer, int ntimeo) { + int *t; if (!timer) return; - rt->ntimeouts[timer-1] = ntimeo; + t = &rt->ntimeouts[timer-1]; + if (ntimeo < *t) { + if (*t > 0) + (*t)--; + } else { + if (ntimeo > 8) + ntimeo = 8; + *t = ntimeo; + } } static inline int rpc_ntimeo(struct rpc_rtt *rt, int timer) diff -puN net/sunrpc/sched.c~nfs-misc-rpc-fixes net/sunrpc/sched.c --- 25/net/sunrpc/sched.c~nfs-misc-rpc-fixes 2004-02-28 18:21:19.000000000 -0800 +++ 25-akpm/net/sunrpc/sched.c 2004-02-28 18:21:19.000000000 -0800 @@ -530,6 +530,9 @@ __rpc_execute(struct rpc_task *task) if (!task->tk_action) break; task->tk_action(task); + /* micro-optimization to avoid spinlock */ + if (RPC_IS_RUNNING(task)) + continue; } /* @@ -545,29 +548,31 @@ __rpc_execute(struct rpc_task *task) } spin_unlock_bh(&rpc_queue_lock); - while (RPC_IS_SLEEPING(task)) { - /* sync task: sleep here */ - dprintk("RPC: %4d sync task going to sleep\n", - task->tk_pid); - if (current->pid == rpciod_pid) - printk(KERN_ERR "RPC: rpciod waiting on sync task!\n"); + if (!RPC_IS_SLEEPING(task)) + continue; + /* sync task: sleep here */ + dprintk("RPC: %4d sync task going to sleep\n", task->tk_pid); + if (current->pid == rpciod_pid) + printk(KERN_ERR "RPC: rpciod waiting on sync task!\n"); + if (!task->tk_client->cl_intr) { __wait_event(task->tk_wait, !RPC_IS_SLEEPING(task)); - dprintk("RPC: %4d sync task resuming\n", task->tk_pid); - + } else { + __wait_event_interruptible(task->tk_wait, !RPC_IS_SLEEPING(task), status); /* * When a sync task receives a signal, it exits with * -ERESTARTSYS. In order to catch any callbacks that * clean up after sleeping on some queue, we don't * break the loop here, but go around once more. */ - if (task->tk_client->cl_intr && signalled()) { + if (status == -ERESTARTSYS) { dprintk("RPC: %4d got signal\n", task->tk_pid); task->tk_flags |= RPC_TASK_KILLED; rpc_exit(task, -ERESTARTSYS); rpc_wake_up_task(task); } } + dprintk("RPC: %4d sync task resuming\n", task->tk_pid); } if (task->tk_exit) { _