From: Trond Myklebust <trond.myklebust@fys.uio.no>

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) {

_