diff -urN linux.nfs10/fs/nfs/inode.c linux.nfs11/fs/nfs/inode.c
--- linux.nfs10/fs/nfs/inode.c	Tue May 28 14:29:37 2002
+++ linux.nfs11/fs/nfs/inode.c	Tue May 28 15:08:56 2002
@@ -486,7 +486,8 @@
 		goto failure_kill_reqlist;
 	}
 
-	/* We're airborne */
+	/* We're airborne. Set socket buffersize */
+	xprt_setbufsize(xprt, server->wsize + 1024, server->rsize + 1024);
 
 	/* Check whether to start the lockd process */
 	if (!(server->flags & NFS_MOUNT_NONLM))
diff -urN linux.nfs10/fs/nfs/write.c linux.nfs11/fs/nfs/write.c
--- linux.nfs10/fs/nfs/write.c	Tue May 28 14:29:37 2002
+++ linux.nfs11/fs/nfs/write.c	Tue May 28 15:08:56 2002
@@ -762,6 +762,8 @@
 	if (dirty >= NFS_STRATEGY_PAGES * wpages)
 		nfs_flush_file(inode, NULL, 0, 0, 0);
 #endif
+	if (current->need_resched)
+		schedule();
 }
 
 int
diff -urN linux.nfs10/include/linux/sunrpc/xprt.h linux.nfs11/include/linux/sunrpc/xprt.h
--- linux.nfs10/include/linux/sunrpc/xprt.h	Tue May 28 15:04:15 2002
+++ linux.nfs11/include/linux/sunrpc/xprt.h	Tue May 28 15:08:56 2002
@@ -139,6 +139,9 @@
 	unsigned long		cong;		/* current congestion */
 	unsigned long		cwnd;		/* congestion window */
 
+	int			sndsize,	/* length send buffer */
+				rcvsize;	/* length receive buffer */
+
 	struct rpc_wait_queue	sending;	/* requests waiting to send */
 	struct rpc_wait_queue	pending;	/* requests in flight */
 	struct rpc_wait_queue	backlog;	/* waiting for slot */
@@ -179,6 +182,7 @@
 
 struct rpc_xprt *	xprt_create_proto(int proto, struct sockaddr_in *addr,
 					struct rpc_timeout *toparms);
+void			xprt_setbufsize(struct rpc_xprt *, int, int);
 int			xprt_destroy(struct rpc_xprt *);
 void			xprt_shutdown(struct rpc_xprt *);
 void			xprt_default_timeout(struct rpc_timeout *, int);
diff -urN linux.nfs10/net/sunrpc/clnt.c linux.nfs11/net/sunrpc/clnt.c
--- linux.nfs10/net/sunrpc/clnt.c	Tue May 28 15:04:15 2002
+++ linux.nfs11/net/sunrpc/clnt.c	Tue May 28 15:08:56 2002
@@ -371,7 +371,6 @@
 	task->tk_status  = 0;
 	task->tk_action  = call_reserveresult;
 	task->tk_timeout = clnt->cl_timeout.to_resrvval;
-	clnt->cl_stats->rpccnt++;
 	xprt_reserve(task);
 }
 
@@ -395,21 +394,20 @@
 		 task->tk_status, task->tk_rqstp);
 
 	if (task->tk_status >= 0) {
+		task->tk_client->cl_stats->rpccnt++;
 		task->tk_action = call_allocate;
 		return;
 	}
 
 	task->tk_status = 0;
 	switch (status) {
+	case -ETIMEDOUT:
+		dprintk("RPC: task timed out\n");
 	case -EAGAIN:
 	case -ENOBUFS:
 		task->tk_timeout = task->tk_client->cl_timeout.to_resrvval;
 		task->tk_action = call_reserve;
 		break;
-	case -ETIMEDOUT:
-		dprintk("RPC: task timed out\n");
-		task->tk_action = call_timeout;
-		break;
 	default:
 		if (!task->tk_rqstp) {
 			printk(KERN_INFO "RPC: task has no request, exit EIO\n");
@@ -444,8 +442,7 @@
 	printk(KERN_INFO "RPC: buffer allocation failed for task %p\n", task); 
 
 	if (RPC_IS_ASYNC(task) || !(task->tk_client->cl_intr && signalled())) {
-		xprt_release(task);
-		task->tk_action = call_reserve;
+		task->tk_action = call_allocate;
 		rpc_delay(task, HZ>>4);
 		return;
 	}
@@ -620,6 +617,7 @@
 		}
 	case -ENOMEM:
 	case -EAGAIN:
+	case -ENOBUFS:
 		task->tk_action = call_transmit;
 		clnt->cl_stats->rpcretrans++;
 		break;
diff -urN linux.nfs10/net/sunrpc/sched.c linux.nfs11/net/sunrpc/sched.c
--- linux.nfs10/net/sunrpc/sched.c	Tue May 28 14:29:36 2002
+++ linux.nfs11/net/sunrpc/sched.c	Tue May 28 15:10:57 2002
@@ -105,7 +105,11 @@
 static inline void
 __rpc_disable_timer(struct rpc_task *task)
 {
+	struct timer_list *timer = &task->tk_timer;
+
 	dprintk("RPC: %4d disabling timer\n", task->tk_pid);
+	if (timer_pending(timer))
+		del_timer(timer);
 	task->tk_timeout_fn = NULL;
 	task->tk_timeout = 0;
 }
@@ -1065,7 +1069,7 @@
 		}
 		__rpc_schedule();
 
-		if (++rounds >= 64) {	/* safeguard */
+		if (++rounds >= 64 || current->need_resched) {	/* safeguard */
 			schedule();
 			rounds = 0;
 		}
@@ -1204,11 +1208,11 @@
 		spin_unlock(&rpc_sched_lock);
 		return;
 	}
-	printk("-pid- proc flgs status -client- -prog- --rqstp- -timeout "
+	printk("-pid- proc flgs runs status -client- -prog- --rqstp- -timeout "
 		"-rpcwait -action- --exit--\n");
 	alltask_for_each(t, le, &all_tasks)
-		printk("%05d %04d %04x %06d %8p %6d %8p %08ld %8s %8p %8p\n",
-			t->tk_pid, t->tk_msg.rpc_proc, t->tk_flags, t->tk_status,
+		printk("%05d %04d %04x %04lx %06d %8p %6d %8p %08ld %8s %8p %8p\n",
+			t->tk_pid, t->tk_msg.rpc_proc, t->tk_flags, t->tk_runstate, t->tk_status,
 			t->tk_client, t->tk_client->cl_prog,
 			t->tk_rqstp, t->tk_timeout,
 			t->tk_rpcwait ? rpc_qname(t->tk_rpcwait) : " <NULL> ",
diff -urN linux.nfs10/net/sunrpc/sunrpc_syms.c linux.nfs11/net/sunrpc/sunrpc_syms.c
--- linux.nfs10/net/sunrpc/sunrpc_syms.c	Tue May 28 14:29:36 2002
+++ linux.nfs11/net/sunrpc/sunrpc_syms.c	Tue May 28 15:08:56 2002
@@ -55,6 +55,7 @@
 EXPORT_SYMBOL(xprt_create_proto);
 EXPORT_SYMBOL(xprt_destroy);
 EXPORT_SYMBOL(xprt_set_timeout);
+EXPORT_SYMBOL(xprt_setbufsize);
 
 /* Client credential cache */
 EXPORT_SYMBOL(rpcauth_register);
diff -urN linux.nfs10/net/sunrpc/xprt.c linux.nfs11/net/sunrpc/xprt.c
--- linux.nfs10/net/sunrpc/xprt.c	Tue May 28 15:05:30 2002
+++ linux.nfs11/net/sunrpc/xprt.c	Tue May 28 15:08:56 2002
@@ -88,6 +88,7 @@
 static void	xprt_reconn_status(struct rpc_task *task);
 static struct socket *xprt_create_socket(int, struct rpc_timeout *);
 static int	xprt_bind_socket(struct rpc_xprt *, struct socket *);
+static void	xprt_sock_setbufsize(struct rpc_xprt *);
 
 #ifdef RPC_DEBUG_DATA
 /*
@@ -458,6 +459,7 @@
 		if (!(sock = xprt_create_socket(xprt->prot, &xprt->timeout)))
 			goto defer;
 		xprt_bind_socket(xprt, sock);
+		xprt_sock_setbufsize(xprt);
 		inet = sock->sk;
 	}
 
@@ -1442,6 +1444,37 @@
 }
 
 /*
+ * Set socket buffer length
+ */
+static void
+xprt_sock_setbufsize(struct rpc_xprt *xprt)
+{
+	struct sock *sk = xprt->inet;
+
+	if (xprt->rcvsize) {
+		sk->userlocks |= SOCK_RCVBUF_LOCK;
+		sk->rcvbuf = xprt->rcvsize << 1;
+	}
+	if (xprt->sndsize) {
+		sk->userlocks |= SOCK_SNDBUF_LOCK;
+		sk->sndbuf = xprt->sndsize << 1;
+		sk->write_space(sk);
+	}
+}
+
+void
+xprt_setbufsize(struct rpc_xprt *xprt, int sndsize, int rcvsize)
+{
+	xprt->sndsize = sndsize * RPC_MAXCONG;
+	if (xprt->sndsize && xprt->sndsize < SOCK_MIN_SNDBUF)
+		xprt->sndsize = SOCK_MIN_SNDBUF;
+	xprt->rcvsize = rcvsize * RPC_MAXCONG;
+	if (xprt->rcvsize && xprt->rcvsize < SOCK_MIN_RCVBUF)
+		xprt->rcvsize = SOCK_MIN_RCVBUF;
+	xprt_sock_setbufsize(xprt);
+}
+
+/*
  * Create a client socket given the protocol and peer address.
  */
 static struct socket *
