diff -Nur linux-2.6.0.orig/fs/lockd/host.c linux-2.6.0/fs/lockd/host.c
--- linux-2.6.0.orig/fs/lockd/host.c	2003-12-18 10:58:56.000000000 +0800
+++ linux-2.6.0/fs/lockd/host.c	2003-12-21 22:39:40.000000000 +0800
@@ -25,7 +25,6 @@
 #define NLM_HOST_REBIND		(60 * HZ)
 #define NLM_HOST_EXPIRE		((nrhosts > NLM_HOST_MAX)? 300 * HZ : 120 * HZ)
 #define NLM_HOST_COLLECT	((nrhosts > NLM_HOST_MAX)? 120 * HZ :  60 * HZ)
-#define NLM_HOST_ADDR(sv)	(&(sv)->s_nlmclnt->cl_xprt->addr)
 
 static struct nlm_host *	nlm_hosts[NLM_HOST_NRHASH];
 static unsigned long		next_gc;
@@ -166,7 +165,6 @@
 nlm_bind_host(struct nlm_host *host)
 {
 	struct rpc_clnt	*clnt;
-	struct rpc_xprt	*xprt;
 
 	dprintk("lockd: nlm_bind_host(%08x)\n",
 			(unsigned)ntohl(host->h_addr.sin_addr.s_addr));
@@ -179,29 +177,23 @@
 	 * Note: why keep rebinding if we're on a tcp connection?
 	 */
 	if ((clnt = host->h_rpcclnt) != NULL) {
-		xprt = clnt->cl_xprt;
-		if (!xprt->stream && time_after_eq(jiffies, host->h_nextrebind)) {
-			clnt->cl_port = 0;
+		if (clnt->cl_prot == IPPROTO_UDP
+				&& time_after_eq(jiffies, host->h_nextrebind)) {
+			rpc_do_rebind(clnt);
 			host->h_nextrebind = jiffies + NLM_HOST_REBIND;
 			dprintk("lockd: next rebind in %ld jiffies\n",
 					host->h_nextrebind - jiffies);
 		}
 	} else {
-		xprt = xprt_create_proto(host->h_proto, &host->h_addr, NULL);
-		if (xprt == NULL)
+		clnt = rpc_create_client(host->h_name, host->h_proto,
+				&host->h_addr, &nlm_program,
+				host->h_version, host->h_authflavor);
+		if (clnt == NULL)
 			goto forgetit;
 
-		xprt_set_timeout(&xprt->timeout, 5, nlmsvc_timeout);
-
-		clnt = rpc_create_client(xprt, host->h_name, &nlm_program,
-					host->h_version, host->h_authflavor);
-		if (clnt == NULL) {
-			xprt_destroy(xprt);
-			goto forgetit;
-		}
+		// xprt_set_timeout(&xprt->timeout, 5, nlmsvc_timeout);
 		clnt->cl_autobind = 1;	/* turn on pmap queries */
-		xprt->nocong = 1;	/* No congestion control for NLM */
-		xprt->resvport = 1;	/* NLM requires a reserved port */
+		clnt->cl_resvport = 1;	/* NLM requires a reserved port */
 
 		host->h_rpcclnt = clnt;
 	}
@@ -223,7 +215,7 @@
 {
 	dprintk("lockd: rebind host %s\n", host->h_name);
 	if (host->h_rpcclnt && time_after_eq(jiffies, host->h_nextrebind)) {
-		host->h_rpcclnt->cl_port = 0;
+		rpc_do_rebind(host->h_rpcclnt);
 		host->h_nextrebind = jiffies + NLM_HOST_REBIND;
 	}
 }
diff -Nur linux-2.6.0.orig/fs/lockd/mon.c linux-2.6.0/fs/lockd/mon.c
--- linux-2.6.0.orig/fs/lockd/mon.c	2003-12-18 10:59:06.000000000 +0800
+++ linux-2.6.0/fs/lockd/mon.c	2003-12-21 22:39:40.000000000 +0800
@@ -103,7 +103,6 @@
 static struct rpc_clnt *
 nsm_create(void)
 {
-	struct rpc_xprt		*xprt;
 	struct rpc_clnt		*clnt = NULL;
 	struct sockaddr_in	sin;
 
@@ -111,25 +110,17 @@
 	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
 	sin.sin_port = 0;
 
-	xprt = xprt_create_proto(IPPROTO_UDP, &sin, NULL);
-	if (!xprt)
-		goto out;
-
-	clnt = rpc_create_client(xprt, "localhost",
+	clnt = rpc_create_client("localhost", IPPROTO_UDP, &sin,
 				&nsm_program, SM_VERSION,
 				RPC_AUTH_NULL);
 	if (!clnt)
-		goto out_destroy;
+		goto out;
 	clnt->cl_softrtry = 1;
 	clnt->cl_chatty   = 1;
 	clnt->cl_oneshot  = 1;
-	xprt->resvport = 1;	/* NSM requires a reserved port */
+	clnt->cl_resvport = 1;	/* NSM requires a reserved port */
 out:
 	return clnt;
-
-out_destroy:
-	xprt_destroy(xprt);
-	goto out;
 }
 
 /*
diff -Nur linux-2.6.0.orig/fs/nfs/inode.c linux-2.6.0/fs/nfs/inode.c
--- linux-2.6.0.orig/fs/nfs/inode.c	2003-12-18 10:59:18.000000000 +0800
+++ linux-2.6.0/fs/nfs/inode.c	2003-12-21 22:39:40.000000000 +0800
@@ -391,6 +391,7 @@
 	struct rpc_xprt		*xprt = NULL;
 	struct rpc_clnt		*clnt = NULL;
 	int			tcp   = (data->flags & NFS_MOUNT_TCP);
+	int			proto;
 
 	/* Initialize timeout values */
 	timeparms.to_initval = data->timeo * HZ / 10;
@@ -403,20 +404,17 @@
 	if (!timeparms.to_retries)
 		timeparms.to_retries = 5;
 
-	/* create transport and client */
-	xprt = xprt_create_proto(tcp ? IPPROTO_TCP : IPPROTO_UDP,
-				 &server->addr, &timeparms);
-	if (xprt == NULL) {
-		printk(KERN_WARNING "NFS: cannot create RPC transport.\n");
-		goto out_fail;
-	}
-	clnt = rpc_create_client(xprt, server->hostname, &nfs_program,
+	proto = tcp? IPPROTO_TCP : IPPROTO_UDP;
+	/* Now create transport and client */
+	clnt = rpc_create_client(server->hostname, proto,
+				&server->addr, &nfs_program,
 				 server->rpc_ops->version, data->pseudoflavor);
 	if (clnt == NULL) {
 		printk(KERN_WARNING "NFS: cannot create RPC client.\n");
 		goto out_fail;
 	}
 
+	rpc_set_timeout(clnt, &timeparms);
 	clnt->cl_intr     = (server->flags & NFS_MOUNT_INTR) ? 1 : 0;
 	clnt->cl_softrtry = (server->flags & NFS_MOUNT_SOFT) ? 1 : 0;
 	clnt->cl_droppriv = (server->flags & NFS_MOUNT_BROKEN_SUID) ? 1 : 0;
@@ -1340,7 +1338,6 @@
 static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, int silent)
 {
 	struct nfs_server *server;
-	struct rpc_xprt *xprt = NULL;
 	struct rpc_clnt *clnt = NULL;
 	struct rpc_timeout timeparms;
 	rpc_authflavor_t authflavour;
@@ -1389,13 +1386,6 @@
 		return -EINVAL;
 	}
 
-	/* Now create transport and client */
-	xprt = xprt_create_proto(proto, &server->addr, &timeparms);
-	if (xprt == NULL) {
-		printk(KERN_WARNING "NFS: cannot create RPC transport.\n");
-		goto out_fail;
-	}
-
 	authflavour = RPC_AUTH_UNIX;
 	if (data->auth_flavourlen != 0) {
 		if (data->auth_flavourlen > 1)
@@ -1405,14 +1395,17 @@
 			goto out_fail;
 		}
 	}
-	clnt = rpc_create_client(xprt, server->hostname, &nfs_program,
-				 server->rpc_ops->version, authflavour);
+
+	/* Now create transport and client */
+	clnt = rpc_create_client(server->hostname, proto,
+			&server->addr, &nfs_program,
+			server->rpc_ops->version, authflavour);
 	if (clnt == NULL) {
 		printk(KERN_WARNING "NFS: cannot create RPC client.\n");
-		xprt_destroy(xprt);
 		goto out_fail;
 	}
 
+	rpc_set_timeout(clnt, &timeparms);
 	clnt->cl_intr     = (server->flags & NFS4_MOUNT_INTR) ? 1 : 0;
 	clnt->cl_softrtry = (server->flags & NFS4_MOUNT_SOFT) ? 1 : 0;
 	clnt->cl_chatty   = 1;
diff -Nur linux-2.6.0.orig/include/linux/sunrpc/clnt.h linux-2.6.0/include/linux/sunrpc/clnt.h
--- linux-2.6.0.orig/include/linux/sunrpc/clnt.h	2003-12-18 10:58:57.000000000 +0800
+++ linux-2.6.0/include/linux/sunrpc/clnt.h	2003-12-21 22:39:40.000000000 +0800
@@ -41,6 +41,7 @@
 
 	char *			cl_server;	/* server machine name */
 	char *			cl_protname;	/* protocol name */
+	struct sockaddr_in	cl_addr;	/* server address */
 	struct rpc_auth *	cl_auth;	/* authenticator */
 	struct rpc_stat *	cl_stats;	/* statistics */
 
@@ -51,9 +52,11 @@
 				cl_binding  : 1,/* doing a getport() */
 				cl_droppriv : 1,/* enable NFS suid hack */
 				cl_oneshot  : 1,/* dispose after use */
+				cl_resvport : 1,/* use a reserved port */
 				cl_dead     : 1;/* abandoned */
 
 	struct rpc_rtt		cl_rtt;		/* RTO estimator data */
+	struct rpc_timeout	cl_timeout;	/* timeout parms */
 
 	struct rpc_portmap	cl_pmap;	/* port mapping */
 	struct rpc_wait_queue	cl_bindwait;	/* waiting on getport() */
@@ -62,8 +65,9 @@
 	char 			cl_nodename[UNX_MAXNODENAME];
 	char			cl_pathname[30];/* Path in rpc_pipe_fs */
 	struct dentry *		cl_dentry;	/* inode */
+
+	rwlock_t		cl_rwlock;
 };
-#define cl_timeout		cl_xprt->timeout
 #define cl_prog			cl_pmap.pm_prog
 #define cl_vers			cl_pmap.pm_vers
 #define cl_port			cl_pmap.pm_port
@@ -105,7 +109,8 @@
 
 #ifdef __KERNEL__
 
-struct rpc_clnt *rpc_create_client(struct rpc_xprt *xprt, char *servname,
+struct rpc_clnt *rpc_create_client(char *servname, int proto,
+				struct sockaddr_in *addr,
 				struct rpc_program *info,
 				u32 version, rpc_authflavor_t authflavor);
 int		rpc_shutdown_client(struct rpc_clnt *);
@@ -124,8 +129,25 @@
 void		rpc_clnt_sigmask(struct rpc_clnt *clnt, sigset_t *oldset);
 void		rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset);
 void		rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int);
+void		rpc_set_timeout(struct rpc_clnt *, struct rpc_timeout *);
+
+static inline int rpc_need_rebind(struct rpc_clnt *clnt)
+{
+	if (!clnt->cl_autobind)
+		return 0;
+	smp_rmb();
+	return clnt->cl_addr.sin_port == 0;
+}
+
+static inline void rpc_do_rebind(struct rpc_clnt *clnt)
+{
+	if (clnt->cl_autobind) {
+		clnt->cl_addr.sin_port = 0;
+		smp_wmb();
+	}
+}
 
-static __inline__
+static inline
 int rpc_call(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags)
 {
 	struct rpc_message msg = {
diff -Nur linux-2.6.0.orig/include/linux/sunrpc/sched.h linux-2.6.0/include/linux/sunrpc/sched.h
--- linux-2.6.0.orig/include/linux/sunrpc/sched.h	2003-12-18 10:59:05.000000000 +0800
+++ linux-2.6.0/include/linux/sunrpc/sched.h	2003-12-21 22:39:40.000000000 +0800
@@ -35,6 +35,7 @@
 #endif
 	struct list_head	tk_task;	/* global list of tasks */
 	struct rpc_clnt *	tk_client;	/* RPC client */
+	struct rpc_xprt *	tk_xprt;	/* RPC transport */
 	struct rpc_rqst *	tk_rqstp;	/* RPC request */
 	int			tk_status;	/* result of last operation */
 	struct rpc_wait_queue *	tk_rpcwait;	/* RPC wait queue we're on */
@@ -80,7 +81,6 @@
 #endif
 };
 #define tk_auth			tk_client->cl_auth
-#define tk_xprt			tk_client->cl_xprt
 
 /* support walking a list of tasks on a wait queue */
 #define	task_for_each(task, pos, head) \
@@ -119,6 +119,7 @@
 #define RPC_ASSASSINATED(t)	((t)->tk_flags & RPC_TASK_KILLED)
 #define RPC_IS_ACTIVATED(t)	((t)->tk_active)
 #define RPC_DO_CALLBACK(t)	((t)->tk_callback != NULL)
+#define RPC_IS_SOFT(t)		((t)->tk_client->cl_softrtry)
 
 #define RPC_TASK_SLEEPING	0
 #define RPC_TASK_RUNNING	1
diff -Nur linux-2.6.0.orig/include/linux/sunrpc/xprt.h linux-2.6.0/include/linux/sunrpc/xprt.h
--- linux-2.6.0.orig/include/linux/sunrpc/xprt.h	2003-12-18 10:59:15.000000000 +0800
+++ linux-2.6.0/include/linux/sunrpc/xprt.h	2003-12-21 22:39:40.000000000 +0800
@@ -128,10 +128,10 @@
 #define XPRT_COPY_DATA		(1 << 3)
 
 struct rpc_xprt {
+	struct list_head	list;		/* Global list */
 	struct socket *		sock;		/* BSD socket layer */
 	struct sock *		inet;		/* INET layer */
 
-	struct rpc_timeout	timeout;	/* timeout parms */
 	struct sockaddr_in	addr;		/* server address */
 	int			prot;		/* IP protocol */
 
@@ -153,6 +153,8 @@
 				resvport   : 1, /* use a reserved port */
 				stream     : 1;	/* TCP */
 
+	atomic_t		count;
+
 	/*
 	 * State of TCP reply receive stuff
 	 */
@@ -183,8 +185,8 @@
 #ifdef __KERNEL__
 
 struct rpc_xprt *	xprt_create_proto(int proto, struct sockaddr_in *addr,
-					struct rpc_timeout *toparms);
-int			xprt_destroy(struct rpc_xprt *);
+					int resvport);
+void			put_xprt(struct rpc_xprt *);
 void			xprt_shutdown(struct rpc_xprt *);
 void			xprt_default_timeout(struct rpc_timeout *, int);
 void			xprt_set_timeout(struct rpc_timeout *, unsigned int,
@@ -200,12 +202,23 @@
 int			xprt_clear_backlog(struct rpc_xprt *);
 void			xprt_sock_setbufsize(struct rpc_xprt *);
 
+static inline struct rpc_xprt *
+get_xprt(struct rpc_xprt *xprt)
+{
+	if (xprt)
+		atomic_inc(&xprt->count);
+	return xprt;
+}
+
+
 #define XPRT_CONNECT	0
+#define XPRT_DISCONNECT	1
 
 #define xprt_connected(xp)		(test_bit(XPRT_CONNECT, &(xp)->sockstate))
 #define xprt_set_connected(xp)		(set_bit(XPRT_CONNECT, &(xp)->sockstate))
 #define xprt_test_and_set_connected(xp)	(test_and_set_bit(XPRT_CONNECT, &(xp)->sockstate))
-#define xprt_clear_connected(xp)	(clear_bit(XPRT_CONNECT, &(xp)->sockstate))
+#define xprt_set_disconnected(xp)	(set_bit(XPRT_DISCONNECT, &(xp)->sockstate))
+#define xprt_disconnected(xp)		(test_bit(XPRT_DISCONNECT, &(xp)->sockstate))
 
 #endif /* __KERNEL__*/
 
diff -Nur linux-2.6.0.orig/net/sunrpc/auth_gss/auth_gss.c linux-2.6.0/net/sunrpc/auth_gss/auth_gss.c
--- linux-2.6.0.orig/net/sunrpc/auth_gss/auth_gss.c	2003-12-18 10:58:48.000000000 +0800
+++ linux-2.6.0/net/sunrpc/auth_gss/auth_gss.c	2003-12-21 22:39:40.000000000 +0800
@@ -640,8 +640,7 @@
 	struct gss_cl_ctx	*ctx = gss_cred_get_ctx(cred);
 	u32		*cred_len;
 	struct rpc_rqst *req = task->tk_rqstp;
-	struct rpc_clnt *clnt = task->tk_client;
-	struct rpc_xprt *xprt = clnt->cl_xprt;
+	struct rpc_xprt *xprt = task->tk_xprt;
 	u32             *verfbase = req->rq_svec[0].iov_base; 
 	u32             maj_stat = 0;
 	struct xdr_netobj bufin,bufout;
@@ -706,11 +705,10 @@
 	struct rpc_clnt *clnt = task->tk_client;
 	struct gss_auth *gss_auth = container_of(clnt->cl_auth,
 			struct gss_auth, rpc_auth);
-	struct rpc_xprt *xprt = task->tk_xprt;
 	struct rpc_cred *cred = task->tk_msg.rpc_cred;
 	int err = 0;
 
-	task->tk_timeout = xprt->timeout.to_current;
+	task->tk_timeout = clnt->cl_timeout.to_current;
 	spin_lock(&gss_auth->lock);
 	if (gss_cred_get_uptodate_ctx(cred))
 		goto out;
diff -Nur linux-2.6.0.orig/net/sunrpc/clnt.c linux-2.6.0/net/sunrpc/clnt.c
--- linux-2.6.0.orig/net/sunrpc/clnt.c	2003-12-18 10:58:45.000000000 +0800
+++ linux-2.6.0/net/sunrpc/clnt.c	2003-12-21 22:39:40.000000000 +0800
@@ -51,6 +51,7 @@
 static void	call_encode(struct rpc_task *task);
 static void	call_decode(struct rpc_task *task);
 static void	call_bind(struct rpc_task *task);
+static void	call_xprt(struct rpc_task *task);
 static void	call_transmit(struct rpc_task *task);
 static void	call_status(struct rpc_task *task);
 static void	call_refresh(struct rpc_task *task);
@@ -95,43 +96,42 @@
  * made to sleep too long.
  */
 struct rpc_clnt *
-rpc_create_client(struct rpc_xprt *xprt, char *servname,
+rpc_create_client(char *servname, int proto, struct sockaddr_in *addr,
 		  struct rpc_program *program, u32 vers,
 		  rpc_authflavor_t flavor)
 {
 	struct rpc_version	*version;
-	struct rpc_clnt		*clnt = NULL;
+	struct rpc_clnt		*clnt;
 
-	dprintk("RPC: creating %s client for %s (xprt %p)\n",
-		program->name, servname, xprt);
+	dprintk("RPC: creating %s client for %s\n", program->name, servname);
 
-	if (!xprt)
-		goto out;
 	if (vers >= program->nrvers || !(version = program->version[vers]))
-		goto out;
+		return NULL;
 
-	clnt = (struct rpc_clnt *) kmalloc(sizeof(*clnt), GFP_KERNEL);
+	clnt = (struct rpc_clnt *)kmalloc(sizeof(*clnt), GFP_KERNEL);
 	if (!clnt)
 		goto out_no_clnt;
 	memset(clnt, 0, sizeof(*clnt));
 	atomic_set(&clnt->cl_users, 0);
 
-	clnt->cl_xprt     = xprt;
 	clnt->cl_procinfo = version->procs;
 	clnt->cl_maxproc  = version->nrprocs;
 	clnt->cl_server   = servname;
 	clnt->cl_protname = program->name;
-	clnt->cl_port     = xprt->addr.sin_port;
-	clnt->cl_prog     = program->number;
-	clnt->cl_vers     = version->number;
-	clnt->cl_prot     = xprt->prot;
+	memcpy(&clnt->cl_addr, addr, sizeof(clnt->cl_addr));
+	clnt->cl_pmap.pm_port = addr->sin_port;
+	clnt->cl_pmap.pm_prog = program->number;
+	clnt->cl_pmap.pm_vers = version->number;
+	clnt->cl_pmap.pm_prot = proto;
 	clnt->cl_stats    = program->stats;
 	INIT_RPC_WAITQ(&clnt->cl_bindwait, "bindwait");
+	rwlock_init(&clnt->cl_rwlock);
 
-	if (!clnt->cl_port)
+	if (!clnt->cl_addr.sin_port)
 		clnt->cl_autobind = 1;
 
-	rpc_init_rtt(&clnt->cl_rtt, xprt->timeout.to_initval);
+	if (capable(CAP_NET_BIND_SERVICE))
+		clnt->cl_resvport = 1;
 
 	if (rpc_setup_pipedir(clnt, program->pipe_dir_name) < 0)
 		goto out_no_path;
@@ -161,6 +161,13 @@
 	goto out;
 }
 
+void
+rpc_set_timeout(struct rpc_clnt *clnt, struct rpc_timeout *timeout)
+{
+	memcpy(&clnt->cl_timeout, timeout, sizeof(clnt->cl_timeout));
+	rpc_init_rtt(&clnt->cl_rtt, clnt->cl_timeout.to_initval);
+}
+
 /*
  * Properly shut down an RPC client, terminating all outstanding
  * requests. Note that we must be certain that cl_oneshot and
@@ -209,10 +216,8 @@
 	}
 	if (clnt->cl_pathname[0])
 		rpc_rmdir(clnt->cl_pathname);
-	if (clnt->cl_xprt) {
-		xprt_destroy(clnt->cl_xprt);
-		clnt->cl_xprt = NULL;
-	}
+	if (clnt->cl_xprt)
+		put_xprt(clnt->cl_xprt);
 	kfree(clnt);
 	return 0;
 }
@@ -377,6 +382,7 @@
 void
 rpc_setbufsize(struct rpc_clnt *clnt, unsigned int sndsize, unsigned int rcvsize)
 {
+#if 0
 	struct rpc_xprt *xprt = clnt->cl_xprt;
 
 	xprt->sndsize = 0;
@@ -387,6 +393,7 @@
 		xprt->rcvsize = rcvsize + RPC_SLACK_SPACE;
 	if (xprt_connected(xprt))
 		xprt_sock_setbufsize(xprt);
+#endif
 }
 
 /*
@@ -420,11 +427,11 @@
 	/* Increment call count */
 	task->tk_msg.rpc_proc->p_count++;
 	clnt->cl_stats->rpccnt++;
-	task->tk_action = call_reserve;
+	task->tk_action = call_bind;
 }
 
 /*
- * 1.	Reserve an RPC call slot
+ * 2.	Reserve an RPC call slot
  */
 static void
 call_reserve(struct rpc_task *task)
@@ -436,13 +443,18 @@
 		return;
 	}
 
+	if (task->tk_rqstp) {
+		task->tk_action = call_allocate;
+		return;
+	}
+
 	task->tk_status  = 0;
 	task->tk_action  = call_reserveresult;
 	xprt_reserve(task);
 }
 
 /*
- * 1b.	Grok the result of xprt_reserve()
+ * 2b.	Grok the result of xprt_reserve()
  */
 static void
 call_reserveresult(struct rpc_task *task)
@@ -480,6 +492,9 @@
 	}
 
 	switch (status) {
+	case -ENOTCONN:
+		task->tk_action = call_bind;
+		return;
 	case -EAGAIN:	/* woken up; retry */
 		task->tk_action = call_reserve;
 		return;
@@ -494,7 +509,7 @@
 }
 
 /*
- * 2.	Allocate the buffer. For details, see sched.c:rpc_malloc.
+ * 3.	Allocate the buffer. For details, see sched.c:rpc_malloc.
  *	(Note: buffer memory is freed in rpc_task_release).
  */
 static void
@@ -504,7 +519,7 @@
 
 	dprintk("RPC: %4d call_allocate (status %d)\n", 
 				task->tk_pid, task->tk_status);
-	task->tk_action = call_bind;
+	task->tk_action = call_transmit;
 	if (task->tk_buffer)
 		return;
 
@@ -527,7 +542,7 @@
 }
 
 /*
- * 3.	Encode arguments of an RPC call
+ * 4.	Encode arguments of an RPC call
  */
 static void
 call_encode(struct rpc_task *task)
@@ -575,39 +590,91 @@
 }
 
 /*
- * 4.	Get the server port number if not yet set
+ * 1.	Get the server port number if not yet set
  */
 static void
 call_bind(struct rpc_task *task)
 {
 	struct rpc_clnt	*clnt = task->tk_client;
-	struct rpc_xprt *xprt = clnt->cl_xprt;
+	int status = task->tk_status;
 
-	dprintk("RPC: %4d call_bind xprt %p %s connected\n", task->tk_pid,
-			xprt, (xprt_connected(xprt) ? "is" : "is not"));
+	dprintk("RPC: %4d call_bind\n", task->tk_pid);
 
-	task->tk_action = (xprt_connected(xprt)) ? call_transmit : call_connect;
+	task->tk_status = 0;
+	if (rpc_need_rebind(clnt)) {
+		if (status >= 0 || !RPC_IS_SOFT(task)) {
+			task->tk_timeout = RPC_CONNECT_TIMEOUT;
+			rpc_getport(task, clnt);
+		} else
+			rpc_exit(task, -EIO);
+	} else
+		task->tk_action = call_xprt;
+}
 
-	if (!clnt->cl_port) {
-		task->tk_action = call_connect;
-		task->tk_timeout = RPC_CONNECT_TIMEOUT;
-		rpc_getport(task, clnt);
+/*
+ * 1a.  Bind the task to the current RPC transport
+ */
+static void call_xprt(struct rpc_task *task)
+{
+	struct rpc_clnt *clnt = task->tk_client;
+	struct rpc_xprt *new, *xprt;
+	struct sockaddr_in addr;
+
+	/* Check the common case: the client has a valid RPC transport */
+	read_lock(&clnt->cl_rwlock);
+	xprt = get_xprt(clnt->cl_xprt);
+	read_unlock(&clnt->cl_rwlock);
+	if (likely(xprt != NULL)) {
+		if (!xprt_disconnected(xprt))
+			goto out;
+		put_xprt(xprt);
+	}
+
+	/* Sigh... We need to create and install a new RPC transport */
+	memcpy(&addr, &clnt->cl_addr, sizeof(addr));
+	/* Hey, has someone asked us to bind to a new port too? */
+	if (addr.sin_port == 0) {
+		task->tk_action = call_bind;
+		return;
+	}
+	new = xprt_create_proto(clnt->cl_prot, &addr, clnt->cl_resvport);
+	if (new == NULL) {
+		rpc_exit(task, -EIO);
+		return;
+	}
+	write_lock(&clnt->cl_rwlock);
+	xprt = clnt->cl_xprt;
+	if (xprt == NULL || xprt_disconnected(xprt)) {
+		clnt->cl_xprt = new;
+		new = xprt;
+	}
+	xprt = get_xprt(clnt->cl_xprt);
+	write_unlock(&clnt->cl_rwlock);
+	if (new != NULL)
+		put_xprt(new);
+out:
+	if (task->tk_xprt) {
+		/* Release the old slot if the transports differ */
+		if (unlikely(xprt != task->tk_xprt))
+			xprt_release(task);
+		else
+			put_xprt(xprt);
 	}
+	task->tk_xprt = xprt;
+	task->tk_action = call_connect;
 }
 
 /*
- * 4a.	Connect to the RPC server (TCP case)
+ * 1b.	Connect to the RPC server (TCP case)
  */
 static void
 call_connect(struct rpc_task *task)
 {
-	struct rpc_clnt *clnt = task->tk_client;
-
 	dprintk("RPC: %4d call_connect status %d\n",
 				task->tk_pid, task->tk_status);
 
-	if (xprt_connected(clnt->cl_xprt)) {
-		task->tk_action = call_transmit;
+	if (xprt_connected(task->tk_xprt)) {
+		task->tk_action = call_reserve;
 		return;
 	}
 	task->tk_action = call_connect_status;
@@ -617,7 +684,7 @@
 }
 
 /*
- * 4b. Sort out connect result
+ * 1c. Sort out connect result
  */
 static void
 call_connect_status(struct rpc_task *task)
@@ -628,19 +695,23 @@
 	task->tk_status = 0;
 	if (status >= 0) {
 		clnt->cl_stats->netreconn++;
-		task->tk_action = call_transmit;
+		task->tk_action = call_reserve;
 		return;
 	}
 
 	/* Something failed: we may have to rebind */
-	if (clnt->cl_autobind)
-		clnt->cl_port = 0;
+	rpc_do_rebind(clnt);
 	switch (status) {
 	case -ENOTCONN:
 	case -ETIMEDOUT:
 	case -EAGAIN:
-		task->tk_action = (clnt->cl_port == 0) ? call_bind : call_connect;
-		break;
+		if (!RPC_IS_SOFT(task)) {
+			if (rpc_need_rebind(clnt))
+				task->tk_action = call_bind;
+			else
+				task->tk_action = call_xprt;
+			break;
+		}
 	default:
 		rpc_exit(task, -EIO);
 	}
@@ -704,9 +775,7 @@
 		break;
 	case -ECONNREFUSED:
 	case -ENOTCONN:
-		req->rq_bytes_sent = 0;
-		if (clnt->cl_autobind)
-			clnt->cl_port = 0;
+		rpc_do_rebind(clnt);
 		task->tk_action = call_bind;
 		break;
 	case -EAGAIN:
@@ -743,7 +812,7 @@
 	to->to_retries = clnt->cl_timeout.to_retries;
 
 	dprintk("RPC: %4d call_timeout (major)\n", task->tk_pid);
-	if (clnt->cl_softrtry) {
+	if (RPC_IS_SOFT(task)) {
 		if (clnt->cl_chatty)
 			printk(KERN_NOTICE "%s: server %s not responding, timed out\n",
 				clnt->cl_protname, clnt->cl_server);
@@ -756,8 +825,7 @@
 		printk(KERN_NOTICE "%s: server %s not responding, still trying\n",
 			clnt->cl_protname, clnt->cl_server);
 	}
-	if (clnt->cl_autobind)
-		clnt->cl_port = 0;
+	rpc_do_rebind(clnt);
 
 retry:
 	clnt->cl_stats->rpcretrans++;
@@ -786,7 +854,7 @@
 	}
 
 	if (task->tk_status < 12) {
-		if (!clnt->cl_softrtry) {
+		if (!RPC_IS_SOFT(task)) {
 			task->tk_action = call_bind;
 			clnt->cl_stats->rpcretrans++;
 			goto out_retry;
@@ -861,7 +929,7 @@
 				task->tk_pid, task->tk_status);
 
 	task->tk_status = 0;
-	task->tk_action = call_reserve;
+	task->tk_action = call_bind;
 	if (status >= 0 && rpcauth_uptodatecred(task))
 		return;
 	if (rpcauth_deadcred(task)) {
@@ -881,7 +949,7 @@
 call_header(struct rpc_task *task)
 {
 	struct rpc_clnt *clnt = task->tk_client;
-	struct rpc_xprt *xprt = clnt->cl_xprt;
+	struct rpc_xprt *xprt = task->tk_xprt;
 	struct rpc_rqst	*req = task->tk_rqstp;
 	u32		*p = req->rq_svec[0].iov_base;
 
diff -Nur linux-2.6.0.orig/net/sunrpc/pmap_clnt.c linux-2.6.0/net/sunrpc/pmap_clnt.c
--- linux-2.6.0.orig/net/sunrpc/pmap_clnt.c	2003-12-18 10:58:49.000000000 +0800
+++ linux-2.6.0/net/sunrpc/pmap_clnt.c	2003-12-21 22:39:40.000000000 +0800
@@ -32,7 +32,6 @@
 static struct rpc_clnt *	pmap_create(char *, struct sockaddr_in *, int);
 static void			pmap_getport_done(struct rpc_task *);
 extern struct rpc_program	pmap_program;
-static spinlock_t		pmap_lock = SPIN_LOCK_UNLOCKED;
 
 /*
  * Obtain the port for a given RPC service on a given host. This one can
@@ -42,11 +41,11 @@
 rpc_getport(struct rpc_task *task, struct rpc_clnt *clnt)
 {
 	struct rpc_portmap *map = &clnt->cl_pmap;
-	struct sockaddr_in *sap = &clnt->cl_xprt->addr;
+	struct sockaddr_in *sap = &clnt->cl_addr;
 	struct rpc_message msg = {
 		.rpc_proc	= &pmap_procedures[PMAP_GETPORT],
 		.rpc_argp	= map,
-		.rpc_resp	= &clnt->cl_port,
+		.rpc_resp	= &map->pm_port,
 		.rpc_cred	= NULL
 	};
 	struct rpc_clnt	*pmap_clnt;
@@ -56,18 +55,19 @@
 			task->tk_pid, clnt->cl_server,
 			map->pm_prog, map->pm_vers, map->pm_prot);
 
-	spin_lock(&pmap_lock);
+	write_lock(&clnt->cl_rwlock);
 	if (clnt->cl_binding) {
 		rpc_sleep_on(&clnt->cl_bindwait, task, NULL, 0);
-		spin_unlock(&pmap_lock);
+		write_unlock(&clnt->cl_rwlock);
 		return;
 	}
 	clnt->cl_binding = 1;
-	spin_unlock(&pmap_lock);
+	write_unlock(&clnt->cl_rwlock);
 
 	task->tk_status = -EACCES; /* why set this? returns -EIO below */
 	if (!(pmap_clnt = pmap_create(clnt->cl_server, sap, map->pm_prot)))
 		goto bailout;
+	pmap_clnt->cl_resvport = 0;
 	task->tk_status = 0;
 
 	/*
@@ -84,10 +84,10 @@
 	return;
 
 bailout:
-	spin_lock(&pmap_lock);
+	write_lock(&clnt->cl_rwlock);
 	clnt->cl_binding = 0;
+	write_unlock(&clnt->cl_rwlock);
 	rpc_wake_up(&clnt->cl_bindwait);
-	spin_unlock(&pmap_lock);
 	task->tk_status = -EIO;
 	task->tk_action = NULL;
 }
@@ -112,6 +112,7 @@
 	sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(sin->sin_addr.s_addr));
 	if (!(pmap_clnt = pmap_create(hostname, sin, prot)))
 		return -EACCES;
+	pmap_clnt->cl_resvport = 0;
 
 	/* Setup the call info struct */
 	status = rpc_call(pmap_clnt, PMAP_GETPORT, &map, &map.pm_port, 0);
@@ -129,25 +130,34 @@
 pmap_getport_done(struct rpc_task *task)
 {
 	struct rpc_clnt	*clnt = task->tk_client;
+	struct rpc_portmap *map = &clnt->cl_pmap;
+	struct rpc_xprt *xprt;
 
 	dprintk("RPC: %4d pmap_getport_done(status %d, port %d)\n",
-			task->tk_pid, task->tk_status, clnt->cl_port);
+			task->tk_pid, task->tk_status, map->pm_port);
+	write_lock(&clnt->cl_rwlock);
 	if (task->tk_status < 0) {
 		/* Make the calling task exit with an error */
 		task->tk_action = NULL;
-	} else if (clnt->cl_port == 0) {
+	} else if (map->pm_port == 0) {
 		/* Program not registered */
 		task->tk_status = -EACCES;
 		task->tk_action = NULL;
 	} else {
 		/* byte-swap port number first */
-		clnt->cl_port = htons(clnt->cl_port);
-		clnt->cl_xprt->addr.sin_port = clnt->cl_port;
+		clnt->cl_addr.sin_port = htons(map->pm_port);
+		wmb();
 	}
-	spin_lock(&pmap_lock);
+	xprt = clnt->cl_xprt;
+	if (xprt && xprt->addr.sin_port != clnt->cl_addr.sin_port)
+		clnt->cl_xprt = NULL;
+	else
+		xprt = NULL;
 	clnt->cl_binding = 0;
+	write_unlock(&clnt->cl_rwlock);
 	rpc_wake_up(&clnt->cl_bindwait);
-	spin_unlock(&pmap_lock);
+	if (xprt)
+		put_xprt(xprt);
 }
 
 /*
@@ -194,21 +204,13 @@
 static struct rpc_clnt *
 pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto)
 {
-	struct rpc_xprt	*xprt;
 	struct rpc_clnt	*clnt;
 
-	/* printk("pmap: create xprt\n"); */
-	if (!(xprt = xprt_create_proto(proto, srvaddr, NULL)))
-		return NULL;
-	xprt->addr.sin_port = htons(RPC_PMAP_PORT);
-
-	/* printk("pmap: create clnt\n"); */
-	clnt = rpc_create_client(xprt, hostname,
+	clnt = rpc_create_client(hostname, proto, srvaddr,
 				&pmap_program, RPC_PMAP_VERSION,
 				RPC_AUTH_NULL);
-	if (!clnt) {
-		xprt_destroy(xprt);
-	} else {
+	if (clnt) {
+		clnt->cl_addr.sin_port = htons(RPC_PMAP_PORT);
 		clnt->cl_softrtry = 1;
 		clnt->cl_chatty   = 1;
 		clnt->cl_oneshot  = 1;
diff -Nur linux-2.6.0.orig/net/sunrpc/rpc_pipe.c linux-2.6.0/net/sunrpc/rpc_pipe.c
--- linux-2.6.0.orig/net/sunrpc/rpc_pipe.c	2003-12-18 10:58:39.000000000 +0800
+++ linux-2.6.0/net/sunrpc/rpc_pipe.c	2003-12-21 22:39:40.000000000 +0800
@@ -257,9 +257,9 @@
 	seq_printf(m, "service: %s (%d) version %d\n", clnt->cl_protname,
 			clnt->cl_prog, clnt->cl_vers);
 	seq_printf(m, "address: %u.%u.%u.%u\n",
-			NIPQUAD(clnt->cl_xprt->addr.sin_addr.s_addr));
+			NIPQUAD(clnt->cl_addr.sin_addr));
 	seq_printf(m, "protocol: %s\n",
-			clnt->cl_xprt->prot == IPPROTO_UDP ? "udp" : "tcp");
+			clnt->cl_prot == IPPROTO_UDP ? "udp" : "tcp");
 	return 0;
 }
 
diff -Nur linux-2.6.0.orig/net/sunrpc/sunrpc_syms.c linux-2.6.0/net/sunrpc/sunrpc_syms.c
--- linux-2.6.0.orig/net/sunrpc/sunrpc_syms.c	2003-12-18 10:59:29.000000000 +0800
+++ linux-2.6.0/net/sunrpc/sunrpc_syms.c	2003-12-21 22:39:40.000000000 +0800
@@ -52,6 +52,9 @@
 EXPORT_SYMBOL(rpc_delay);
 EXPORT_SYMBOL(rpc_restart_call);
 EXPORT_SYMBOL(rpc_setbufsize);
+EXPORT_SYMBOL(rpc_set_timeout);
+
+/* RPC pipefs functions */
 EXPORT_SYMBOL(rpc_unlink);
 EXPORT_SYMBOL(rpc_wake_up);
 EXPORT_SYMBOL(rpc_queue_upcall);
@@ -59,8 +62,7 @@
 
 /* Client transport */
 EXPORT_SYMBOL(xprt_create_proto);
-EXPORT_SYMBOL(xprt_destroy);
-EXPORT_SYMBOL(xprt_set_timeout);
+EXPORT_SYMBOL(put_xprt);
 
 /* Client credential cache */
 EXPORT_SYMBOL(rpcauth_register);
diff -Nur linux-2.6.0.orig/net/sunrpc/xprt.c linux-2.6.0/net/sunrpc/xprt.c
--- linux-2.6.0.orig/net/sunrpc/xprt.c	2003-12-18 10:59:05.000000000 +0800
+++ linux-2.6.0/net/sunrpc/xprt.c	2003-12-21 22:41:02.000000000 +0800
@@ -84,11 +84,15 @@
 static void	xprt_disconnect(struct rpc_xprt *);
 static void	xprt_connect_status(struct rpc_task *task);
 static struct rpc_xprt * xprt_setup(int proto, struct sockaddr_in *ap,
-						struct rpc_timeout *to);
-static struct socket *xprt_create_socket(int, struct rpc_timeout *, int);
+						int resvport);
+static struct socket *xprt_create_socket(int, int);
 static void	xprt_bind_socket(struct rpc_xprt *, struct socket *);
 static int      __xprt_get_cong(struct rpc_xprt *, struct rpc_task *);
 
+/* Global list of xprt structs */
+static LIST_HEAD(all_xprts);
+static spinlock_t xprt_global_lock = SPIN_LOCK_UNLOCKED;
+
 #ifdef RPC_DEBUG_DATA
 /*
  * Print the buffer contents (first 128 bytes only--just enough for
@@ -139,6 +143,10 @@
 {
 	struct rpc_rqst *req = task->tk_rqstp;
 
+	if (xprt_disconnected(xprt)) {
+		task->tk_status = -ENOTCONN;
+		return 0;
+	}
 	if (!xprt->snd_task) {
 		if (xprt->nocong || __xprt_get_cong(xprt, task)) {
 			xprt->snd_task = task;
@@ -387,7 +395,6 @@
 	sk->sk_write_space  = xprt->old_write_space;
 	write_unlock_bh(&sk->sk_callback_lock);
 
-	xprt_disconnect(xprt);
 	sk->sk_no_check	 = 0;
 
 	sock_release(sock);
@@ -401,8 +408,10 @@
 {
 	dprintk("RPC:      disconnected transport %p\n", xprt);
 	spin_lock_bh(&xprt->sock_lock);
-	xprt_clear_connected(xprt);
+	xprt_set_disconnected(xprt);
 	rpc_wake_up_status(&xprt->pending, -ENOTCONN);
+	rpc_wake_up_status(&xprt->sending, -ENOTCONN);
+	rpc_wake_up_status(&xprt->resend, -ENOTCONN);
 	spin_unlock_bh(&xprt->sock_lock);
 }
 
@@ -434,23 +443,6 @@
 	if (xprt_connected(xprt))
 		goto out_write;
 
-	if (task->tk_rqstp)
-		task->tk_rqstp->rq_bytes_sent = 0;
-
-	/*
-	 * We're here because the xprt was marked disconnected.
-	 * Start by resetting any existing state.
-	 */
-	xprt_close(xprt);
-	if (!(sock = xprt_create_socket(xprt->prot, &xprt->timeout, xprt->resvport))) {
-		/* couldn't create socket or bind to reserved port;
-		 * this is likely a permanent error, so cause an abort */
-		task->tk_status = -EIO;
-		goto out_write;
-	}
-	xprt_bind_socket(xprt, sock);
-	xprt_sock_setbufsize(xprt);
-
 	if (!xprt->stream)
 		goto out_write;
 
@@ -477,8 +469,7 @@
 					task->tk_pid);
 			task->tk_timeout = RPC_CONNECT_TIMEOUT;
 			/* if the socket is already closing, delay briefly */
-			if ((1 << inet->sk_state) &
-			    ~(TCPF_SYN_SENT | TCPF_SYN_RECV))
+			if (xprt_disconnected(xprt))
 				task->tk_timeout = RPC_REESTABLISH_TIMEOUT;
 			rpc_sleep_on(&xprt->pending, task, xprt_connect_status,
 									NULL);
@@ -488,7 +479,7 @@
 	case -ECONNREFUSED:
 	case -ECONNRESET:
 	case -ENOTCONN:
-		if (!task->tk_client->cl_softrtry) {
+		if (!RPC_IS_SOFT(task)) {
 			rpc_delay(task, RPC_REESTABLISH_TIMEOUT);
 			task->tk_status = -ENOTCONN;
 			break;
@@ -496,7 +487,7 @@
 	default:
 		/* Report myriad other possible returns.  If this file
 		 * system is soft mounted, just error out, like Solaris.  */
-		if (task->tk_client->cl_softrtry) {
+		if (RPC_IS_SOFT(task)) {
 			printk(KERN_WARNING
 			"RPC: error %d connecting to server %s, exiting\n",
 					-status, task->tk_client->cl_server);
@@ -530,7 +521,7 @@
 	}
 
 	/* if soft mounted, just cause this RPC to fail */
-	if (task->tk_client->cl_softrtry)
+	if (RPC_IS_SOFT(task))
 		task->tk_status = -EIO;
 
 	switch (task->tk_status) {
@@ -998,12 +989,10 @@
 		}
 		spin_unlock_bh(&xprt->sock_lock);
 		break;
-	case TCP_SYN_SENT:
-	case TCP_SYN_RECV:
-		break;
-	default:
+	case TCP_CLOSING:
+	case TCP_CLOSE_WAIT:
+	case TCP_CLOSE:
 		xprt_disconnect(xprt);
-		break;
 	}
  out:
 	if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
@@ -1101,12 +1090,7 @@
 		goto out_unlock;
 	}
 	if (!__xprt_lock_write(xprt, task)) {
-		err = -EAGAIN;
-		goto out_unlock;
-	}
-
-	if (!xprt_connected(xprt)) {
-		err = -ENOTCONN;
+		err = task->tk_status;
 		goto out_unlock;
 	}
 out_unlock:
@@ -1187,6 +1171,9 @@
 	 *	 hence there is no danger of the waking up task being put on
 	 *	 schedq, and being picked up by a parallel run of rpciod().
 	 */
+	if (req->rq_received && !req->rq_bytes_sent)
+		goto out_release;
+
 	task->tk_status = status;
 
 	switch (status) {
@@ -1195,7 +1182,7 @@
 			/* Protect against races with xprt_write_space */
 			spin_lock_bh(&xprt->sock_lock);
 			/* Don't race with disconnect */
-			if (!xprt_connected(xprt))
+			if (xprt_disconnected(xprt))
 				task->tk_status = -ENOTCONN;
 			else if (test_bit(SOCK_NOSPACE, &xprt->sock->flags)) {
 				task->tk_timeout = req->rq_timeout.to_current;
@@ -1216,9 +1203,10 @@
 		if (xprt->stream)
 			xprt_disconnect(xprt);
 	}
+out_release:
 	xprt_release_write(xprt, task);
 	return;
- out_receive:
+out_receive:
 	dprintk("RPC: %4d xmit complete\n", task->tk_pid);
 	/* Set the task's receive timeout value */
 	spin_lock_bh(&xprt->sock_lock);
@@ -1233,7 +1221,7 @@
 	} else
 		task->tk_timeout = req->rq_timeout.to_current;
 	/* Don't race with disconnect */
-	if (!xprt_connected(xprt))
+	if (xprt_disconnected(xprt))
 		task->tk_status = -ENOTCONN;
 	else if (!req->rq_received)
 		rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer);
@@ -1308,7 +1296,7 @@
 {
 	struct rpc_rqst	*req = task->tk_rqstp;
 
-	req->rq_timeout = xprt->timeout;
+	memcpy(&req->rq_timeout, &task->tk_client->cl_timeout, sizeof(req->rq_timeout));
 	req->rq_task	= task;
 	req->rq_xprt    = xprt;
 	req->rq_xid     = xprt_alloc_xid();
@@ -1326,8 +1314,10 @@
 	struct rpc_xprt	*xprt = task->tk_xprt;
 	struct rpc_rqst	*req;
 
-	if (!(req = task->tk_rqstp))
+	if (!xprt)
 		return;
+	if (!(req = task->tk_rqstp))
+		goto out;
 	spin_lock_bh(&xprt->sock_lock);
 	__xprt_release_write(xprt, task);
 	__xprt_put_cong(xprt, req);
@@ -1345,6 +1335,9 @@
 
 	xprt_clear_backlog(xprt);
 	spin_unlock(&xprt->xprt_lock);
+out:
+	put_xprt(xprt);
+	task->tk_xprt = NULL;
 }
 
 /*
@@ -1373,14 +1366,35 @@
 	to->to_exponential = 0;
 }
 
+struct rpc_xprt *
+__xprt_find(int proto, struct sockaddr_in *ap, int resvport)
+{
+	struct rpc_xprt *xprt;
+
+	list_for_each_entry(xprt, &all_xprts, list) {
+		if (xprt_disconnected(xprt))
+			continue;
+		if (proto != xprt->prot)
+			continue;
+		if (memcmp(&xprt->addr, ap, sizeof(xprt->addr)))
+			continue;
+		if (resvport != xprt->resvport)
+			continue;
+		atomic_inc(&xprt->count);
+		return xprt;
+	}
+	return NULL;
+}
+
 /*
  * Initialize an RPC client
  */
 static struct rpc_xprt *
-xprt_setup(int proto, struct sockaddr_in *ap, struct rpc_timeout *to)
+xprt_setup(int proto, struct sockaddr_in *ap, int resvport)
 {
 	struct rpc_xprt	*xprt;
 	struct rpc_rqst	*req;
+	struct socket *sock;
 	int		i;
 
 	dprintk("RPC:      setting up %s transport...\n",
@@ -1390,7 +1404,7 @@
 		return NULL;
 	memset(xprt, 0, sizeof(*xprt)); /* Nnnngh! */
 
-	xprt->addr = *ap;
+	memcpy(&xprt->addr, ap, sizeof(xprt->addr));
 	xprt->prot = proto;
 	xprt->stream = (proto == IPPROTO_TCP)? 1 : 0;
 	if (xprt->stream) {
@@ -1402,14 +1416,10 @@
 	spin_lock_init(&xprt->xprt_lock);
 	init_waitqueue_head(&xprt->cong_wait);
 
-	INIT_LIST_HEAD(&xprt->recv);
+	atomic_set(&xprt->count, 1);
 
-	/* Set timeout parameters */
-	if (to) {
-		xprt->timeout = *to;
-		xprt->timeout.to_current = to->to_initval;
-	} else
-		xprt_default_timeout(&xprt->timeout, xprt->prot);
+	INIT_LIST_HEAD(&xprt->list);
+	INIT_LIST_HEAD(&xprt->recv);
 
 	INIT_RPC_WAITQ(&xprt->pending, "xprt_pending");
 	INIT_RPC_WAITQ(&xprt->sending, "xprt_sending");
@@ -1422,12 +1432,20 @@
 	req->rq_next = NULL;
 	xprt->free = xprt->slot;
 
-	/* Check whether we want to use a reserved port */
-	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
+	xprt->resvport = resvport;
+
+	/* Create the socket */
+	sock = xprt_create_socket(xprt->prot, resvport);
+	if (!sock)
+		goto out_nosock;
+	xprt_bind_socket(xprt, sock);
 
 	dprintk("RPC:      created transport %p\n", xprt);
 	
 	return xprt;
+out_nosock:
+	kfree(xprt);
+	return NULL;
 }
 
 /*
@@ -1483,7 +1501,6 @@
 		tp->nonagle = 1;	/* disable Nagle's algorithm */
 		sk->sk_data_ready = tcp_data_ready;
 		sk->sk_state_change = tcp_state_change;
-		xprt_clear_connected(xprt);
 	}
 	sk->sk_write_space = xprt_write_space;
 
@@ -1491,8 +1508,6 @@
 	xprt->sock = sock;
 	xprt->inet = sk;
 	write_unlock_bh(&sk->sk_callback_lock);
-
-	return;
 }
 
 /*
@@ -1521,7 +1536,7 @@
  * and connect stream sockets.
  */
 static struct socket *
-xprt_create_socket(int proto, struct rpc_timeout *to, int resvport)
+xprt_create_socket(int proto, int resvport)
 {
 	struct socket	*sock;
 	int		type, err;
@@ -1553,20 +1568,35 @@
  * Create an RPC client transport given the protocol and peer address.
  */
 struct rpc_xprt *
-xprt_create_proto(int proto, struct sockaddr_in *sap, struct rpc_timeout *to)
+xprt_create_proto(int proto, struct sockaddr_in *sap, int resvport)
 {
-	struct rpc_xprt	*xprt;
+	struct rpc_xprt	*xprt, *new_xprt = NULL;
 
-	xprt = xprt_setup(proto, sap, to);
-	if (!xprt)
-		goto out_bad;
+	spin_lock(&xprt_global_lock);
+	do {
+		xprt = __xprt_find(proto, sap, resvport);
+		if (xprt)
+			break;
 
+		if (!new_xprt) {
+			spin_unlock(&xprt_global_lock);
+			new_xprt = xprt_setup(proto, sap, resvport);
+			if (!new_xprt)
+				goto out_bad;
+			spin_lock(&xprt_global_lock);
+			continue;
+		}
+		list_add(&new_xprt->list, &all_xprts);
+		xprt = new_xprt;
+		new_xprt = NULL;
+	} while (xprt == NULL);
+	spin_unlock(&xprt_global_lock);
+	if (new_xprt)
+		put_xprt(new_xprt);
 	dprintk("RPC:      xprt_create_proto created xprt %p\n", xprt);
 	return xprt;
  out_bad:
 	dprintk("RPC:      xprt_create_proto failed\n");
-	if (xprt)
-		kfree(xprt);
 	return NULL;
 }
 
@@ -1597,15 +1627,18 @@
 }
 
 /*
- * Destroy an RPC transport, killing off all requests.
+ * Release an RPC transport.
  */
-int
-xprt_destroy(struct rpc_xprt *xprt)
+void
+put_xprt(struct rpc_xprt *xprt)
 {
+	if (!atomic_dec_and_lock(&xprt->count, &xprt_global_lock))
+		return;
+	if (!list_empty(&xprt->list))
+		list_del(&xprt->list);
+	spin_unlock(&xprt_global_lock);
 	dprintk("RPC:      destroying transport %p\n", xprt);
 	xprt_shutdown(xprt);
 	xprt_close(xprt);
 	kfree(xprt);
-
-	return 0;
 }