diff -Nru linux-2.6.11/fs/lockd/svc4proc.c linux-2.6.11-09/fs/lockd/svc4proc.c
--- linux-2.6.11/fs/lockd/svc4proc.c	2005-03-14 14:51:31.000000000 +0100
+++ linux-2.6.11-09/fs/lockd/svc4proc.c	2005-04-04 15:43:37.000000000 +0200
@@ -416,19 +416,18 @@
 nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
 					      void	        *resp)
 {
-	struct sockaddr_in	saddr = rqstp->rq_addr;
+	struct sockaddr_in	saddr;
 	int			vers = argp->vers;
 	int			prot = argp->proto >> 1;
-
 	struct nlm_host		*host;
+	char			addrbuf[MAX_ADDR_BUF];
 
 	dprintk("lockd: SM_NOTIFY     called\n");
-	if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK)
-	 || ntohs(saddr.sin_port) >= 1024) {
+	memcpy(&saddr, &rqstp->rq_addr, sizeof(saddr));
+	if (!is_valid_addr((struct sockaddr *)&saddr)) {
+		svc_print_addr((struct sockaddr *)&saddr, addrbuf, sizeof(addrbuf));
 		printk(KERN_WARNING
-			"lockd: rejected NSM callback from %08x:%d\n",
-			ntohl(rqstp->rq_addr.sin_addr.s_addr),
-			ntohs(rqstp->rq_addr.sin_port));
+			"lockd: rejected NSM callback from %s\n", addrbuf);
 		return rpc_system_err;
 	}
 
diff -Nru linux-2.6.11/fs/lockd/svc.c linux-2.6.11-09/fs/lockd/svc.c
--- linux-2.6.11/fs/lockd/svc.c	2005-03-14 14:51:31.000000000 +0100
+++ linux-2.6.11-09/fs/lockd/svc.c	2005-04-04 15:43:37.000000000 +0200
@@ -97,7 +97,8 @@
 {
 	struct svc_serv	*serv = rqstp->rq_server;
 	int		err = 0;
-	unsigned long grace_period_expire;
+	unsigned long	grace_period_expire;
+	char		addrbuf[MAX_ADDR_BUF];
 
 	/* Lock module and set up kernel thread */
 	/* lockd_up is waiting for us to startup, so will
@@ -169,8 +170,9 @@
 			break;
 		}
 
-		dprintk("lockd: request from %08x\n",
-			(unsigned)ntohl(rqstp->rq_addr.sin_addr.s_addr));
+		svc_print_addr((struct sockaddr *)&rqstp->rq_addr,
+			       addrbuf, sizeof(addrbuf));
+		dprintk("lockd: request from %s\n", addrbuf);
 
 		svc_process(serv, rqstp);
 
diff -Nru linux-2.6.11/fs/lockd/svclock.c linux-2.6.11-09/fs/lockd/svclock.c
--- linux-2.6.11/fs/lockd/svclock.c	2005-03-14 14:51:31.000000000 +0100
+++ linux-2.6.11-09/fs/lockd/svclock.c	2005-04-04 15:43:37.000000000 +0200
@@ -585,7 +585,7 @@
 	char buf[255];
 
 	rpc_peeraddr(task->tk_client, &addr, sizeof(addr));
-	rpc_print_peeraddr(task->tk_client, buf, sizeof(buf), 0x1);
+	rpc_print_peeraddr(task->tk_client, buf, sizeof(buf), ADDR_FMT);
 
 	dprintk("lockd: GRANT_MSG RPC callback\n");
 	dprintk("callback: looking for cookie %s, host (%s)\n",
@@ -629,10 +629,12 @@
 {
 	struct nlm_block	*block;
 	struct nlm_file		*file;
+	char			addrbuf[MAX_ADDR_BUF];
 
-	dprintk("grant_reply: looking for cookie %x, host (%08x), s=%d \n", 
-		*(unsigned int *)(cookie->data), 
-		ntohl(rqstp->rq_addr.sin_addr.s_addr), status);
+	svc_print_addr((struct sockaddr *)&rqstp->rq_addr,
+		       addrbuf, sizeof(addrbuf));
+	dprintk("grant_reply: looking for cookie %x, host (%s), s=%d \n", 
+		*(unsigned int *)(cookie->data), addrbuf, status);
 	if (!(block = nlmsvc_find_block(cookie, &rqstp->rq_addr)))
 		return;
 	file = block->b_file;
diff -Nru linux-2.6.11/fs/lockd/svcproc.c linux-2.6.11-09/fs/lockd/svcproc.c
--- linux-2.6.11/fs/lockd/svcproc.c	2005-03-14 14:51:31.000000000 +0100
+++ linux-2.6.11-09/fs/lockd/svcproc.c	2005-04-04 15:43:37.000000000 +0200
@@ -444,18 +444,18 @@
 nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
 					      void	        *resp)
 {
-	struct sockaddr_in	saddr = rqstp->rq_addr;
+	struct sockaddr_in	saddr;
 	int			vers = argp->vers;
 	int			prot = argp->proto >> 1;
 	struct nlm_host		*host;
+	char			addrbuf[MAX_ADDR_BUF];
 
 	dprintk("lockd: SM_NOTIFY     called\n");
-	if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK)
-	 || ntohs(saddr.sin_port) >= 1024) {
+	memcpy(&saddr, &rqstp->rq_addr, sizeof(saddr));
+	if (!is_valid_addr((struct sockaddr *)&saddr)) {
+		svc_print_addr((struct sockaddr *)&saddr, addrbuf, sizeof(addrbuf));
 		printk(KERN_WARNING
-			"lockd: rejected NSM callback from %08x:%d\n",
-			ntohl(rqstp->rq_addr.sin_addr.s_addr),
-			ntohs(rqstp->rq_addr.sin_port));
+			"lockd: rejected NSM callback from %s\n", addrbuf);
 		return rpc_system_err;
 	}
 
diff -Nru linux-2.6.11/fs/nfs/callback.c linux-2.6.11-09/fs/nfs/callback.c
--- linux-2.6.11/fs/nfs/callback.c	2005-03-14 14:50:30.000000000 +0100
+++ linux-2.6.11-09/fs/nfs/callback.c	2005-04-19 09:39:17.000000000 +0200
@@ -64,8 +64,6 @@
 					__FUNCTION__, -err);
 			break;
 		}
-		dprintk("%s: request from %u.%u.%u.%u\n", __FUNCTION__,
-				NIPQUAD(rqstp->rq_addr.sin_addr.s_addr));
 		svc_process(serv, rqstp);
 	}
 
@@ -94,8 +92,7 @@
 	ret = -ENOMEM;
 	if (!serv)
 		goto out_err;
-	/* FIXME: We don't want to register this socket with the portmapper */
-	ret = svc_makesock(serv, IPPROTO_TCP, 0);
+	ret = svc_makesock2(serv, IPPROTO_TCP, 0, 0);
 	if (ret < 0)
 		goto out_destroy;
 	if (!list_empty(&serv->sv_permsocks)) {
@@ -142,14 +139,17 @@
 
 static int nfs_callback_authenticate(struct svc_rqst *rqstp)
 {
-	struct in_addr *addr = &rqstp->rq_addr.sin_addr;
+	struct sockaddr *addr = (struct sockaddr *)&rqstp->rq_addr;
 	struct nfs4_client *clp;
+	char addr_buf[RPC_BUF_ADDR_MAX_SIZE];
 
 	/* Don't talk to strangers */
 	clp = nfs4_find_client(addr);
 	if (clp == NULL)
 		return SVC_DROP;
-	dprintk("%s: %u.%u.%u.%u NFSv4 callback!\n", __FUNCTION__, NIPQUAD(addr));
+	rpc_print_peeraddr(clp->cl_rpcclient, addr_buf, sizeof(addr_buf),
+			   ADDR_FMT);
+	dprintk("%s: %s NFSv4 callback!\n", __FUNCTION__, addr_buf);
 	nfs4_put_client(clp);
 	switch (rqstp->rq_authop->flavour) {
 		case RPC_AUTH_NULL:
diff -Nru linux-2.6.11/fs/nfs/callback.h linux-2.6.11-09/fs/nfs/callback.h
--- linux-2.6.11/fs/nfs/callback.h	2005-03-02 08:38:20.000000000 +0100
+++ linux-2.6.11-09/fs/nfs/callback.h	2005-04-08 09:04:11.000000000 +0200
@@ -38,7 +38,7 @@
 };
 
 struct cb_getattrargs {
-	struct sockaddr_in *addr;
+	struct sockaddr *addr;
 	struct nfs_fh fh;
 	uint32_t bitmap[2];
 };
@@ -53,7 +53,7 @@
 };
 
 struct cb_recallargs {
-	struct sockaddr_in *addr;
+	struct sockaddr *addr;
 	struct nfs_fh fh;
 	nfs4_stateid stateid;
 	uint32_t truncate;
diff -Nru linux-2.6.11/fs/nfs/callback_proc.c linux-2.6.11-09/fs/nfs/callback_proc.c
--- linux-2.6.11/fs/nfs/callback_proc.c	2005-03-14 14:50:30.000000000 +0100
+++ linux-2.6.11-09/fs/nfs/callback_proc.c	2005-04-04 16:39:32.000000000 +0200
@@ -20,12 +20,16 @@
 	struct nfs_delegation *delegation;
 	struct nfs_inode *nfsi;
 	struct inode *inode;
+	char addr_buf[255];
 	
 	res->bitmap[0] = res->bitmap[1] = 0;
 	res->status = htonl(NFS4ERR_BADHANDLE);
-	clp = nfs4_find_client(&args->addr->sin_addr);
+	clp = nfs4_find_client(args->addr);
 	if (clp == NULL)
 		goto out;
+	rpc_print_peeraddr(clp->cl_rpcclient, addr_buf, sizeof(addr_buf),
+			   ADDR_FMT);
+	dprintk("%s: request from %s\n", __FUNCTION__, addr_buf);
 	inode = nfs_delegation_find_inode(clp, &args->fh);
 	if (inode == NULL)
 		goto out_putclient;
@@ -57,12 +61,16 @@
 {
 	struct nfs4_client *clp;
 	struct inode *inode;
+	char addr_buf[RPC_BUF_ADDR_MAX_SIZE];
 	unsigned res;
 	
 	res = htonl(NFS4ERR_BADHANDLE);
-	clp = nfs4_find_client(&args->addr->sin_addr);
+	clp = nfs4_find_client(args->addr);
 	if (clp == NULL)
 		goto out;
+	rpc_print_peeraddr(clp->cl_rpcclient, addr_buf, sizeof(addr_buf),
+			   ADDR_FMT);
+	dprintk("%s: request from %s\n", __FUNCTION__, addr_buf);
 	inode = nfs_delegation_find_inode(clp, &args->fh);
 	if (inode == NULL)
 		goto out_putclient;
diff -Nru linux-2.6.11/fs/nfs/callback_xdr.c linux-2.6.11-09/fs/nfs/callback_xdr.c
--- linux-2.6.11/fs/nfs/callback_xdr.c	2005-03-14 14:50:30.000000000 +0100
+++ linux-2.6.11-09/fs/nfs/callback_xdr.c	2005-04-08 09:04:11.000000000 +0200
@@ -177,7 +177,7 @@
 	status = decode_fh(xdr, &args->fh);
 	if (unlikely(status != 0))
 		goto out;
-	args->addr = &rqstp->rq_addr;
+	args->addr = (struct sockaddr *)&rqstp->rq_addr;
 	status = decode_bitmap(xdr, args->bitmap);
 out:
 	dprintk("%s: exit with status = %d\n", __FUNCTION__, status);
@@ -189,7 +189,7 @@
 	uint32_t *p;
 	unsigned status;
 
-	args->addr = &rqstp->rq_addr;
+	args->addr = (struct sockaddr *)&rqstp->rq_addr;
 	status = decode_stateid(xdr, &args->stateid);
 	if (unlikely(status != 0))
 		goto out;
diff -Nru linux-2.6.11/fs/nfs/delegation.c linux-2.6.11-09/fs/nfs/delegation.c
--- linux-2.6.11/fs/nfs/delegation.c	2005-03-14 14:50:30.000000000 +0100
+++ linux-2.6.11-09/fs/nfs/delegation.c	2005-04-04 13:37:13.000000000 +0200
@@ -83,6 +83,7 @@
 	struct nfs4_client *clp = NFS_SERVER(inode)->nfs4_state;
 	struct nfs_inode *nfsi = NFS_I(inode);
 	struct nfs_delegation *delegation;
+	char addr_buf[RPC_BUF_ADDR_MAX_SIZE];
 	int status = 0;
 
 	delegation = nfs_alloc_delegation();
@@ -105,8 +106,10 @@
 		if (memcmp(&delegation->stateid, &nfsi->delegation->stateid,
 					sizeof(delegation->stateid)) != 0 ||
 				delegation->type != nfsi->delegation->type) {
-			printk("%s: server %u.%u.%u.%u, handed out a duplicate delegation!\n",
-					__FUNCTION__, NIPQUAD(clp->cl_addr));
+			rpc_print_peeraddr(clp->cl_rpcclient, addr_buf,
+					   sizeof(addr_buf), ADDR_FMT);
+			printk("%s: server %s, handed out a duplicate delegation!\n",
+					__FUNCTION__, addr_buf);
 			status = -EIO;
 		}
 	}
diff -Nru linux-2.6.11/fs/nfs/inode.c linux-2.6.11-09/fs/nfs/inode.c
--- linux-2.6.11/fs/nfs/inode.c	2005-03-14 14:51:31.000000000 +0100
+++ linux-2.6.11-09/fs/nfs/inode.c	2005-04-08 15:24:34.000000000 +0200
@@ -421,8 +421,8 @@
 	};
 	struct rpc_create_args args = {
 		.protocol	= (tcp ? IPPROTO_TCP : IPPROTO_UDP),
-		.address	= (struct sockaddr *)&server->addr,
-		.addrsize	= sizeof(server->addr),
+		.address	= server->addr,
+		.addrsize	= server->addrlen,
 		.timeout	= &timeparms,
 		.servername	= server->hostname,
 		.program	= &nfs_program,
@@ -1733,9 +1733,7 @@
 	struct nfs_server *server = data;
 	struct nfs_server *old = NFS_SB(sb);
 
-	if (old->addr.sin_addr.s_addr != server->addr.sin_addr.s_addr)
-		return 0;
-	if (old->addr.sin_port != server->addr.sin_port)
+	if (memcmp((void *)&old->addr, (void *)server->addr, server->addrlen))
 		return 0;
 	return !nfs_compare_fh(&old->fh, &server->fh);
 }
@@ -1775,6 +1773,11 @@
 		}
 		if (data->version < 5)
 			data->flags &= ~NFS_MOUNT_SECFLAVOUR;
+		if (data->version < 7) {
+			data->addrlen = sizeof(struct sockaddr_in);
+			memcpy(&data->addr, &data->old_addr,
+				sizeof(struct sockaddr_in));
+		}
 	}
 
 	root = &server->fh;
@@ -1790,16 +1793,18 @@
 	memcpy(root->data, data->root.data, root->size);
 
 	/* We now require that the mount process passes the remote address */
-	memcpy(&server->addr, &data->addr, sizeof(server->addr));
-	if (server->addr.sin_addr.s_addr == INADDR_ANY) {
-		printk("NFS: mount program didn't pass remote address!\n");
+	server->addrlen = data->addrlen;
+	server->addr = kmalloc(server->addrlen, GFP_KERNEL);
+	if (!server->addr) {
 		kfree(server);
-		return ERR_PTR(-EINVAL);
+		return ERR_PTR(-ENOMEM);
 	}
+	memcpy(server->addr, &data->addr, server->addrlen);
 
 	s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
 
 	if (IS_ERR(s) || s->s_root) {
+		kfree(server->addr);
 		kfree(server);
 		return s;
 	}
@@ -1809,6 +1814,7 @@
 	/* Fire up rpciod if not yet running */
 	if (rpciod_up() != 0) {
 		printk(KERN_WARNING "NFS: couldn't start rpciod!\n");
+		kfree(server->addr);
 		kfree(server);
 		return ERR_PTR(-EIO);
 	}
@@ -1999,7 +2005,7 @@
 	server->retrans_timeo = timeparms.to_initval;
 	server->retrans_count = timeparms.to_retries;
 
-	clp = nfs4_get_client(&server->addr.sin_addr);
+	clp = nfs4_get_client(server->addr, server->addrlen);
 	if (!clp) {
 		printk(KERN_WARNING "NFS: failed to create NFS4 client.\n");
 		return -EIO;
@@ -2020,8 +2026,8 @@
 	if (clp->cl_rpcclient == NULL) {
 		struct rpc_create_args args = {
 			.protocol	= proto,
-			.address	= (struct sockaddr *)&server->addr,
-			.addrsize	= sizeof(server->addr),
+			.address	= server->addr,
+			.addrsize	= server->addrlen,
 			.timeout	= &timeparms,
 			.servername	= server->hostname,
 			.program	= &nfs_program,
@@ -2170,18 +2176,18 @@
 		goto out_err;
 
 	/* We now require that the mount process passes the remote address */
-	if (data->host_addrlen != sizeof(server->addr)) {
+	if (data->host_addrlen > sizeof(struct sockaddr_storage)) {
 		s = ERR_PTR(-EINVAL);
 		goto out_free;
 	}
-	if (copy_from_user(&server->addr, data->host_addr, sizeof(server->addr))) {
-		s = ERR_PTR(-EFAULT);
+	server->addrlen = data->host_addrlen;
+	server->addr = kmalloc(server->addrlen, GFP_KERNEL);
+	if (!server->addr) {
+		s = ERR_PTR(-ENOMEM);
 		goto out_free;
 	}
-	if (server->addr.sin_family != AF_INET ||
-	    server->addr.sin_addr.s_addr == INADDR_ANY) {
-		printk("NFS: mount program didn't pass remote IP address!\n");
-		s = ERR_PTR(-EINVAL);
+	if (copy_from_user(server->addr, data->host_addr, server->addrlen)) {
+		s = ERR_PTR(-EFAULT);
 		goto out_free;
 	}
 
@@ -2210,6 +2216,8 @@
 out_err:
 	s = (struct super_block *)p;
 out_free:
+	if (server->addr)
+		kfree(server->addr);
 	if (server->mnt_path)
 		kfree(server->mnt_path);
 	if (server->hostname)
@@ -2235,6 +2243,8 @@
 
 	if (server->hostname != NULL)
 		kfree(server->hostname);
+	if (server->addr != NULL)
+		kfree(server->addr);
 	kfree(server);
 	nfs_release_automount_timer();
 }
@@ -2350,10 +2360,15 @@
 	if (server->hostname == NULL)
 		goto free_server;
 	memcpy(server->hostname, parent->hostname, len);
+	len = parent->addrlen;
+	server->addr = kmalloc(len, GFP_KERNEL);
+	if (server->addr == NULL)
+		goto free_hostname;
+	memcpy(server->addr, parent->addr, len);
 	server->fsid = data->fattr->fsid;
 	nfs_copy_fh(&server->fh, data->fh);
 	if (rpciod_up() != 0)
-		goto free_hostname;
+		goto free_addr;
 
 	switch (parent->rpc_ops->version) {
 		case 2:
@@ -2400,6 +2415,8 @@
 	return (struct super_block *)err;
 kill_rpciod:
 	rpciod_down();
+free_addr:
+	kfree(server->addr);
 free_hostname:
 	kfree(server->hostname);
 free_server:
diff -Nru linux-2.6.11/fs/nfs/nfs4_fs.h linux-2.6.11-09/fs/nfs/nfs4_fs.h
--- linux-2.6.11/fs/nfs/nfs4_fs.h	2005-03-14 14:50:30.000000000 +0100
+++ linux-2.6.11-09/fs/nfs/nfs4_fs.h	2005-04-08 09:04:11.000000000 +0200
@@ -45,7 +45,8 @@
  */
 struct nfs4_client {
 	struct list_head	cl_servers;	/* Global list of servers */
-	struct in_addr		cl_addr;	/* Server identifier */
+	struct sockaddr	*	cl_addr;	/* Server identifier */
+	int			cl_addrlen;
 	u64			cl_clientid;	/* constant */
 	nfs4_verifier		cl_confirm;
 	unsigned long		cl_state;
@@ -87,7 +88,7 @@
 	/* Our own IP address, as a null-terminated string.
 	 * This is used to generate the clientid, and the callback address.
 	 */
-	char			cl_ipaddr[16];
+	char			cl_ipaddr[80];
 	unsigned char		cl_id_uniquifier;
 };
 
@@ -209,10 +210,10 @@
 /* nfs4state.c */
 extern void init_nfsv4_state(struct nfs_server *);
 extern void destroy_nfsv4_state(struct nfs_server *);
-extern struct nfs4_client *nfs4_get_client(struct in_addr *);
+extern struct nfs4_client *nfs4_get_client(struct sockaddr *, int);
 extern void nfs4_put_client(struct nfs4_client *clp);
 extern int nfs4_init_client(struct nfs4_client *clp);
-extern struct nfs4_client *nfs4_find_client(struct in_addr *);
+extern struct nfs4_client *nfs4_find_client(struct sockaddr *);
 extern u32 nfs4_alloc_lockowner_id(struct nfs4_client *);
 
 extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *);
diff -Nru linux-2.6.11/fs/nfs/nfs4proc.c linux-2.6.11-09/fs/nfs/nfs4proc.c
--- linux-2.6.11/fs/nfs/nfs4proc.c	2005-03-14 14:51:31.000000000 +0100
+++ linux-2.6.11-09/fs/nfs/nfs4proc.c	2005-04-04 13:37:13.000000000 +0200
@@ -2493,6 +2493,7 @@
 		.rpc_cred = clp->cl_cred,
 	};
 	u32 *p;
+	char addr_buf[RPC_BUF_ADDR_MAX_SIZE];
 	int loop = 0;
 	int status;
 
@@ -2501,9 +2502,11 @@
 	*p = htonl((u32)clp->cl_boot_time.tv_nsec);
 
 	for(;;) {
+		rpc_print_peeraddr(clp->cl_rpcclient, addr_buf,
+				   sizeof(addr_buf), ADDR_FMT|RAW_FMT);
 		setclientid.sc_name_len = scnprintf(setclientid.sc_name,
-				sizeof(setclientid.sc_name), "%s/%u.%u.%u.%u %s %u",
-				clp->cl_ipaddr, NIPQUAD(clp->cl_addr.s_addr),
+				sizeof(setclientid.sc_name), "%s/%s %s %u",
+				clp->cl_ipaddr, addr_buf,
 				clp->cl_cred->cr_ops->cr_name,
 				clp->cl_id_uniquifier);
 		setclientid.sc_netid_len = scnprintf(setclientid.sc_netid,
diff -Nru linux-2.6.11/fs/nfs/nfs4state.c linux-2.6.11-09/fs/nfs/nfs4state.c
--- linux-2.6.11/fs/nfs/nfs4state.c	2005-03-14 14:50:30.000000000 +0100
+++ linux-2.6.11-09/fs/nfs/nfs4state.c	2005-04-04 13:37:13.000000000 +0200
@@ -94,7 +94,7 @@
  * bother putting them in a slab cache...
  */
 static struct nfs4_client *
-nfs4_alloc_client(struct in_addr *addr)
+nfs4_alloc_client(struct sockaddr *addr, int addrlen)
 {
 	struct nfs4_client *clp;
 
@@ -105,7 +105,13 @@
 		return NULL;
 	}
 	memset(clp, 0, sizeof(*clp));
-	memcpy(&clp->cl_addr, addr, sizeof(clp->cl_addr));
+	clp->cl_addrlen = addrlen;
+	if ((clp->cl_addr = kmalloc(clp->cl_addrlen, GFP_KERNEL)) == NULL) {
+		kfree(clp);
+		nfs_callback_down();
+		return NULL;
+	}
+	memcpy(clp->cl_addr, addr, clp->cl_addrlen);
 	init_rwsem(&clp->cl_sem);
 	INIT_LIST_HEAD(&clp->cl_delegations);
 	INIT_LIST_HEAD(&clp->cl_state_owners);
@@ -140,11 +146,13 @@
 	nfs_idmap_delete(clp);
 	if (clp->cl_rpcclient)
 		rpc_shutdown_client(clp->cl_rpcclient);
+	if (clp->cl_addr)
+		kfree(clp->cl_addr);
 	kfree(clp);
 	nfs_callback_down();
 }
 
-static struct nfs4_client *__nfs4_find_client(struct in_addr *addr)
+static struct nfs4_client *__nfs4_find_client(struct sockaddr *addr)
 {
 	struct nfs4_client *clp;
 	list_for_each_entry(clp, &nfs4_clientid_list, cl_servers) {
@@ -156,7 +164,7 @@
 	return NULL;
 }
 
-struct nfs4_client *nfs4_find_client(struct in_addr *addr)
+struct nfs4_client *nfs4_find_client(struct sockaddr *addr)
 {
 	struct nfs4_client *clp;
 	spin_lock(&state_spinlock);
@@ -166,7 +174,7 @@
 }
 
 struct nfs4_client *
-nfs4_get_client(struct in_addr *addr)
+nfs4_get_client(struct sockaddr *addr, int addrlen)
 {
 	struct nfs4_client *clp, *new = NULL;
 
@@ -182,7 +190,7 @@
 			break;
 		}
 		spin_unlock(&state_spinlock);
-		new = nfs4_alloc_client(addr);
+		new = nfs4_alloc_client(addr, addrlen);
 		spin_lock(&state_spinlock);
 		if (new == NULL)
 			break;
@@ -858,9 +866,12 @@
 	struct nfs4_client *clp = args->clp;
 	struct nfs4_state_owner *sp;
 	struct nfs4_state_recovery_ops *ops;
+	char addr_buf[RPC_BUF_ADDR_MAX_SIZE];
 	int status = 0;
 
-	daemonize("%u.%u.%u.%u-reclaim", NIPQUAD(clp->cl_addr));
+	rpc_print_peeraddr(clp->cl_rpcclient, addr_buf, sizeof(addr_buf),
+			   ADDR_FMT);
+	daemonize("%s-reclaim", addr_buf);
 	allow_signal(SIGKILL);
 
 	atomic_inc(&clp->cl_count);
@@ -916,8 +927,8 @@
 	nfs4_put_client(clp);
 	return 0;
 out_error:
-	printk(KERN_WARNING "Error: state recovery failed on NFSv4 server %u.%u.%u.%u with error %d\n",
-				NIPQUAD(clp->cl_addr.s_addr), -status);
+	printk(KERN_WARNING "Error: state recovery failed on NFSv4 server %s with error %d\n",
+			addr_buf, -status);
 	goto out;
 }
 
diff -Nru linux-2.6.11/fs/nfs/nfs4xdr.c linux-2.6.11-09/fs/nfs/nfs4xdr.c
--- linux-2.6.11/fs/nfs/nfs4xdr.c	2005-03-14 14:51:31.000000000 +0100
+++ linux-2.6.11-09/fs/nfs/nfs4xdr.c	2005-04-08 09:04:11.000000000 +0200
@@ -101,10 +101,11 @@
 #define decode_renew_maxsz	(op_decode_hdr_maxsz)
 #define encode_setclientid_maxsz \
 				(op_encode_hdr_maxsz + \
-				4 /*server->ip_addr*/ + \
-				1 /*Netid*/ + \
-				6 /*uaddr*/ + \
-				6 + (NFS4_VERIFIER_SIZE >> 2))
+				192 /*sc_name*/ + \
+				4 /*Netid*/ + \
+				22 /*uaddr*/ + \
+				2 /*cb_program + cb_ident*/ + \
+				(NFS4_VERIFIER_SIZE >> 2))
 #define decode_setclientid_maxsz \
 				(op_decode_hdr_maxsz + \
 				2 + \
diff -Nru linux-2.6.11/fs/nfsd/nfs4state.c linux-2.6.11-09/fs/nfsd/nfs4state.c
--- linux-2.6.11/fs/nfsd/nfs4state.c	2005-03-14 14:50:31.000000000 +0100
+++ linux-2.6.11-09/fs/nfsd/nfs4state.c	2005-04-04 15:43:37.000000000 +0200
@@ -639,7 +639,7 @@
 int
 nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
 {
-	u32 			ip_addr = rqstp->rq_addr.sin_addr.s_addr;
+	u32 			ip_addr = ((struct sockaddr_in *)&rqstp->rq_addr)->sin_addr.s_addr;
 	struct xdr_netobj 	clname = { 
 		.len = setclid->se_namelen,
 		.data = setclid->se_name,
@@ -820,7 +820,7 @@
 int
 nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confirm *setclientid_confirm)
 {
-	u32 ip_addr = rqstp->rq_addr.sin_addr.s_addr;
+	u32 ip_addr = ((struct sockaddr_in *)&rqstp->rq_addr)->sin_addr.s_addr;
 	struct nfs4_client *clp, *conf = NULL, *unconf = NULL;
 	nfs4_verifier confirm = setclientid_confirm->sc_confirm; 
 	clientid_t * clid = &setclientid_confirm->sc_clientid;
diff -Nru linux-2.6.11/fs/nfsd/nfscache.c linux-2.6.11-09/fs/nfsd/nfscache.c
--- linux-2.6.11/fs/nfsd/nfscache.c	2005-03-02 08:38:33.000000000 +0100
+++ linux-2.6.11-09/fs/nfsd/nfscache.c	2005-04-04 15:43:37.000000000 +0200
@@ -233,7 +233,7 @@
 	rp->c_state = RC_INPROG;
 	rp->c_xid = xid;
 	rp->c_proc = proc;
-	rp->c_addr = rqstp->rq_addr;
+	memcpy(&rp->c_addr, &rqstp->rq_addr, sizeof(struct sockaddr_in));
 	rp->c_prot = proto;
 	rp->c_vers = vers;
 	rp->c_timestamp = jiffies;
diff -Nru linux-2.6.11/fs/nfsd/nfsfh.c linux-2.6.11-09/fs/nfsd/nfsfh.c
--- linux-2.6.11/fs/nfsd/nfsfh.c	2005-03-02 08:38:00.000000000 +0100
+++ linux-2.6.11-09/fs/nfsd/nfsfh.c	2005-04-04 15:43:37.000000000 +0200
@@ -117,6 +117,7 @@
 	struct svc_export *exp = NULL;
 	struct dentry	*dentry;
 	u32		error = 0;
+	char		addrbuf[MAX_ADDR_BUF];
 
 	dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp));
 
@@ -180,10 +181,11 @@
 		/* Check if the request originated from a secure port. */
 		error = nfserr_perm;
 		if (!rqstp->rq_secure && EX_SECURE(exp)) {
+			svc_print_addr((struct sockaddr *)&rqstp->rq_addr,
+				       addrbuf, sizeof(addrbuf));
 			printk(KERN_WARNING
-			       "nfsd: request from insecure port (%u.%u.%u.%u:%d)!\n",
-			       NIPQUAD(rqstp->rq_addr.sin_addr.s_addr),
-			       ntohs(rqstp->rq_addr.sin_port));
+			       "nfsd: request from insecure port (%s)!\n",
+			       addrbuf);
 			goto out;
 		}
 
diff -Nru linux-2.6.11/fs/nfsd/nfsproc.c linux-2.6.11-09/fs/nfsd/nfsproc.c
--- linux-2.6.11/fs/nfsd/nfsproc.c	2005-03-14 14:50:31.000000000 +0100
+++ linux-2.6.11-09/fs/nfsd/nfsproc.c	2005-04-04 15:43:37.000000000 +0200
@@ -117,6 +117,7 @@
 				       struct nfsd_readres  *resp)
 {
 	int	nfserr;
+	char	addrbuf[MAX_ADDR_BUF];
 
 	dprintk("nfsd: READ    %s %d bytes at %d\n",
 		SVCFH_fmt(&argp->fh),
@@ -127,11 +128,10 @@
 	 */
 
 	if (NFSSVC_MAXBLKSIZE < argp->count) {
+		svc_print_addr((struct sockaddr *)&rqstp->rq_addr, addrbuf, sizeof(addrbuf));
 		printk(KERN_NOTICE
-			"oversized read request from %u.%u.%u.%u:%d (%d bytes)\n",
-				NIPQUAD(rqstp->rq_addr.sin_addr.s_addr),
-				ntohs(rqstp->rq_addr.sin_port),
-				argp->count);
+			"oversized read request from %s (%d bytes)\n",
+				addrbuf, argp->count);
 		argp->count = NFSSVC_MAXBLKSIZE;
 	}
 	svc_reserve(rqstp, (19<<2) + argp->count + 4);
diff -Nru linux-2.6.11/include/linux/nfs_fs_sb.h linux-2.6.11-09/include/linux/nfs_fs_sb.h
--- linux-2.6.11/include/linux/nfs_fs_sb.h	2005-03-14 14:51:31.000000000 +0100
+++ linux-2.6.11-09/include/linux/nfs_fs_sb.h	2005-04-08 09:04:11.000000000 +0200
@@ -33,14 +33,15 @@
 	unsigned int		namelen;
 	char *			hostname;	/* remote hostname */
 	struct nfs_fh		fh;
-	struct sockaddr_in	addr;
+	struct sockaddr *	addr;
+	unsigned int		addrlen;
 	struct nfs_fsid		fsid;
 	uint32_t		generation;
 #ifdef CONFIG_NFS_V4
 	/* Our own IP address, as a null-terminated string.
 	 * This is used to generate the clientid, and the callback address.
 	 */
-	char			ip_addr[16];
+	char			ip_addr[80];
 	char *			mnt_path;
 	struct nfs4_client *	nfs4_state;	/* all NFSv4 state starts here */
 	struct list_head	nfs4_siblings;	/* List of other nfs_server structs
diff -Nru linux-2.6.11/include/linux/nfs_ipv6.h linux-2.6.11-09/include/linux/nfs_ipv6.h
--- linux-2.6.11/include/linux/nfs_ipv6.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.11-09/include/linux/nfs_ipv6.h	2005-04-04 15:49:48.000000000 +0200
@@ -0,0 +1,83 @@
+/*
+ *  include/linux/nfs_ipv6.h
+ *
+ *  Macros used to manipulate IPv6 addreses
+ */
+
+#ifndef _LINUX_NFS_IPV6_H
+#define _LINUX_NFS_IPV6_H
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/in.h>
+#include <linux/in6.h>
+
+static inline void
+map_ipaddr_4to6(struct in_addr *addr, struct in6_addr *addr6)
+{
+	addr6->s6_addr32[0] = 0;
+	addr6->s6_addr32[1] = 0;
+	addr6->s6_addr32[2] = htonl(0xffff);
+	addr6->s6_addr32[3] = *(uint32_t *)addr;
+}
+
+static inline void
+map_sockaddr_4to6(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
+{
+	sin6->sin6_family = AF_INET6;
+	sin6->sin6_port = sin->sin_port;
+	sin6->sin6_flowinfo = 0;
+	map_ipaddr_4to6(&sin->sin_addr, &sin6->sin6_addr);
+	sin6->sin6_scope_id = 0;
+}
+
+static inline void
+map_ipaddr6_to_sockaddr6(struct in6_addr *addr6, __u16 port,
+			 struct sockaddr_in6 *sin6)
+{
+	sin6->sin6_family = AF_INET6;
+	sin6->sin6_port = htons(port);
+	sin6->sin6_flowinfo = 0;
+	memcpy(&sin6->sin6_addr, addr6, sizeof(struct in6_addr));
+	sin6->sin6_scope_id = 0;
+}
+
+static inline void
+init_ipaddr_loopback6(struct in6_addr *addr6)
+{
+	addr6->s6_addr32[0] = 0;
+	addr6->s6_addr32[1] = 0;
+	addr6->s6_addr32[2] = 0;
+	addr6->s6_addr32[3] = htonl(1);
+}
+
+static inline void
+init_sockaddr_loopback6(__u16 port, struct sockaddr_in6 *sin6)
+{
+	sin6->sin6_family = AF_INET6;
+	sin6->sin6_port = htons(port);
+	sin6->sin6_flowinfo = 0;
+	init_ipaddr_loopback6(&sin6->sin6_addr);
+	sin6->sin6_scope_id = 0;
+}
+
+#define IS_ADDR6_LOOPBACK(a) \
+	(((__const uint32_t *) (a))[0] == 0		\
+	 && ((__const uint32_t *) (a))[1] == 0		\
+	 && ((__const uint32_t *) (a))[2] == 0		\
+	 && ((__const uint32_t *) (a))[3] == htonl(1))
+
+#define IS_ADDR6_ANY(a) \
+	(((uint32_t *) (a))[0] == 0			\
+	 && ((uint32_t *) (a))[1] == 0			\
+	 && (((uint32_t *) (a))[2] == 0			\
+	     || ((uint32_t *) (a))[2] == htonl(0xffff))	\
+	 && ((uint32_t *) (a))[3] == 0)
+
+#define IS_ADDR_MAPPED(a) \
+       (((uint32_t *) (a))[0] == 0			\
+	&& ((uint32_t *) (a))[1] == 0			\
+	&& (((uint32_t *) (a))[2] == 0			\
+	    || ((uint32_t *) (a))[2] == htonl(0xffff)))
+
+#endif /* _LINUX_NFS_IPV6_H */
diff -Nru linux-2.6.11/include/linux/nfs_mount.h linux-2.6.11-09/include/linux/nfs_mount.h
--- linux-2.6.11/include/linux/nfs_mount.h	2005-03-29 09:17:06.000000000 +0200
+++ linux-2.6.11-09/include/linux/nfs_mount.h	2005-04-04 14:16:36.000000000 +0200
@@ -20,7 +20,7 @@
  * mount-to-kernel version compatibility.  Some of these aren't used yet
  * but here they are anyway.
  */
-#define NFS_MOUNT_VERSION	6
+#define NFS_MOUNT_VERSION	7
 #define NFS_MAX_CONTEXT_LEN	256
 
 struct nfs_mount_data {
@@ -36,13 +36,15 @@
 	int		acregmax;		/* 1 */
 	int		acdirmin;		/* 1 */
 	int		acdirmax;		/* 1 */
-	struct sockaddr_in addr;		/* 1 */
+	struct sockaddr_in old_addr;		/* 1 */
 	char		hostname[256];		/* 1 */
 	int		namlen;			/* 2 */
 	unsigned int	bsize;			/* 3 */
 	struct nfs3_fh	root;			/* 4 */
 	int		pseudoflavor;		/* 5 */
 	char		context[NFS_MAX_CONTEXT_LEN + 1];	/* 6 */
+	unsigned int	addrlen; 		/* 7 */
+	struct sockaddr_storage	addr;		/* 7 */
 };
 
 /* bits in the flags field */
diff -Nru linux-2.6.11/include/linux/nfs_xdr.h linux-2.6.11-09/include/linux/nfs_xdr.h
--- linux-2.6.11/include/linux/nfs_xdr.h	2005-03-14 14:51:31.000000000 +0100
+++ linux-2.6.11-09/include/linux/nfs_xdr.h	2005-04-08 09:04:11.000000000 +0200
@@ -616,12 +616,12 @@
 struct nfs4_setclientid {
 	const nfs4_verifier *		sc_verifier;      /* request */
 	unsigned int			sc_name_len;
-	char				sc_name[32];	  /* request */
+	char				sc_name[80];	  /* request */
 	u32				sc_prog;          /* request */
 	unsigned int			sc_netid_len;
-	char				sc_netid[4];	  /* request */
+	char				sc_netid[12];	  /* request */
 	unsigned int			sc_uaddr_len;
-	char				sc_uaddr[24];     /* request */
+	char				sc_uaddr[80];     /* request */
 	u32				sc_cb_ident;      /* request */
 };
 
diff -Nru linux-2.6.11/include/linux/sunrpc/clnt.h linux-2.6.11-09/include/linux/sunrpc/clnt.h
--- linux-2.6.11/include/linux/sunrpc/clnt.h	2005-03-14 14:51:31.000000000 +0100
+++ linux-2.6.11-09/include/linux/sunrpc/clnt.h	2005-04-04 13:37:13.000000000 +0200
@@ -133,6 +133,16 @@
 void		rpc_client_set_xprt(struct rpc_clnt *, struct rpc_xprt *);
 void		rpc_put_xprt(struct rpc_xprt *xprt);
 
+/*
+ * Values used by rpc_print_peeraddr().
+ */
+#define RPC_BUF_ADDR_MAX_SIZE	255
+#define ADDR_FMT		0x1
+#define PORT_FMT		0x2
+#define PROTO_FMT		0x4
+#define UADDR_FMT		0x8
+#define RAW_FMT			0x80
+
 static __inline__
 int rpc_call(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags)
 {
diff -Nru linux-2.6.11/include/linux/sunrpc/svc.h linux-2.6.11-09/include/linux/sunrpc/svc.h
--- linux-2.6.11/include/linux/sunrpc/svc.h	2005-03-14 14:50:31.000000000 +0100
+++ linux-2.6.11-09/include/linux/sunrpc/svc.h	2005-04-05 16:38:50.000000000 +0200
@@ -11,6 +11,7 @@
 #define SUNRPC_SVC_H
 
 #include <linux/in.h>
+#include <linux/in6.h>
 #include <linux/sunrpc/types.h>
 #include <linux/sunrpc/xdr.h>
 #include <linux/sunrpc/svcauth.h>
@@ -111,7 +112,7 @@
 struct svc_rqst {
 	struct list_head	rq_list;	/* idle list */
 	struct svc_sock *	rq_sock;	/* socket */
-	struct sockaddr_in	rq_addr;	/* peer address */
+	struct sockaddr_storage	rq_addr;	/* peer address */
 	int			rq_addrlen;
 
 	struct svc_serv *	rq_server;	/* RPC service definition */
@@ -138,8 +139,11 @@
 	unsigned short
 				rq_secure  : 1;	/* secure port */
 
-
-	__u32			rq_daddr;	/* dest addr of request - reply from here */
+	union {
+	    struct in_addr *	in_daddr;
+	    struct in6_addr *	in6_daddr;
+	    void *		daddr;
+	} rq_u_daddr;				/* dest addr of request - reply from here */
 
 	void *			rq_argp;	/* decoded arguments */
 	void *			rq_resp;	/* xdr'd results */
@@ -162,6 +166,9 @@
 
 	wait_queue_head_t	rq_wait;	/* synchronization */
 };
+#define rq_in_daddr	rq_u_daddr.in_daddr
+#define rq_in6_daddr	rq_u_daddr.in6_daddr
+#define rq_daddr	rq_u_daddr.daddr
 
 /*
  * Check buffer bounds after decoding arguments
@@ -230,9 +237,71 @@
 	}
 }
 
+static inline u_short svc_get_port(struct sockaddr *sin)
+{
+	u_short port;
+
+	if (sin->sa_family == AF_INET)
+		port = ((struct sockaddr_in *)sin)->sin_port;
+	else if (sin->sa_family == AF_INET6)
+		port = ((struct sockaddr_in6 *)sin)->sin6_port;
+	else
+		port = 0;
+	return htons(port);
+}
+
+static inline u_short svc_get_addrlen(struct sockaddr *sin)
+{
+	u_short len;
+
+	if (sin->sa_family == AF_INET)
+		len = sizeof(struct sockaddr_in);
+	else if (sin->sa_family == AF_INET6)
+		len = sizeof(struct sockaddr_in6);
+	else
+		len = 0;
+	return len;
+}
+
+#define MAX_ADDR_BUF		255
+
+static inline void svc_print_addr(struct sockaddr *addr, char *str, size_t len)
+{
+	if (addr->sa_family == AF_INET) {
+		struct sockaddr_in *sin = (struct sockaddr_in *)addr;
+		snprintf(str, len, "ip = %u.%u.%u.%u port = %d",
+			 NIPQUAD(((struct sockaddr_in *)sin)->sin_addr),
+			 htons(sin->sin_port));
+	} else if (addr->sa_family == AF_INET6) {
+		struct sockaddr_in6 *sin = (struct sockaddr_in6 *)addr;
+		snprintf(str, len, "ip = %x:%x:%x:%x:%x:%x:%x:%x port = %d",
+			 NIP6(((struct sockaddr_in6 *)sin)->sin6_addr),
+			 htons(sin->sin6_port));
+	}
+}
+
+static inline int is_valid_addr(struct sockaddr *addr)
+{
+	int	valid = 0;
+
+	if (addr->sa_family == AF_INET) {
+		struct sockaddr_in *sin = (struct sockaddr_in *)addr;
+		valid = (sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK) &&
+			 ntohs(sin->sin_port) < 1024);
+	} else if (addr->sa_family == AF_INET6) {
+		struct sockaddr_in6 *sin = (struct sockaddr_in6 *)addr;
+		valid = (sin->sin6_addr.s6_addr32[0] == 0 &&
+			 sin->sin6_addr.s6_addr32[1] == 0 &&
+			 sin->sin6_addr.s6_addr32[2] == 0 &&
+			 sin->sin6_addr.s6_addr32[3] == 1 &&
+			 ntohs(sin->sin6_port) < 1024);
+	}
+	return valid;
+}
+
 struct svc_deferred_req {
 	u32			prot;	/* protocol (UDP or TCP) */
-	struct sockaddr_in	addr;
+	struct sockaddr_storage	addr;
 	struct svc_sock		*svsk;	/* where reply must go */
 	struct cache_deferred_req handle;
 	int			argslen;
diff -Nru linux-2.6.11/include/linux/sunrpc/svcsock.h linux-2.6.11-09/include/linux/sunrpc/svcsock.h
--- linux-2.6.11/include/linux/sunrpc/svcsock.h	2005-04-08 09:03:01.000000000 +0200
+++ linux-2.6.11-09/include/linux/sunrpc/svcsock.h	2005-05-09 07:49:06.000000000 +0200
@@ -53,6 +53,13 @@
 };
 
 /*
+ * SOCK_PERM flag has been introduced to avoid callback connections to be registered in rpcbind
+ * SOCK_PMAP_REG replaces the pmap_register flag of previous versions
+ */
+#define SOCK_PMAP_REG	0x1
+#define SOCK_PERM	0x2
+
+/*
  * Function prototypes.
  */
 int		svc_makesock(struct svc_serv *, int, unsigned short);
diff -Nru linux-2.6.11/include/linux/sunrpc/xprt.h linux-2.6.11-09/include/linux/sunrpc/xprt.h
--- linux-2.6.11/include/linux/sunrpc/xprt.h	2005-03-14 14:51:31.000000000 +0100
+++ linux-2.6.11-09/include/linux/sunrpc/xprt.h	2005-04-05 11:26:29.000000000 +0200
@@ -174,6 +174,7 @@
 	unsigned char		shutdown   : 1,	/* being shut down */
 				need_bind  : 1, /* force a rebind */
 				resvport   : 1; /* use a reserved port */
+	unsigned int		bind_idx;	/* bind function index */
 
 	/*
 	 * Connection of transports
@@ -228,9 +229,9 @@
  * RPC bind helpers
  */
 int			pmap_register(u32, u32, int, unsigned short, int *);
-void			pmap_getport(struct rpc_task *, struct rpc_clnt *);
+void			rpcb_getport4(struct rpc_task *, struct rpc_clnt *);
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-void			pmap_getport6(struct rpc_task *, struct rpc_clnt *);
+void			rpcb_getport6(struct rpc_task *, struct rpc_clnt *);
 #endif
 int			pmap_getport_external(struct sockaddr_in *, u32,
 					u32, int);
diff -Nru linux-2.6.11/net/sunrpc/clnt.c linux-2.6.11-09/net/sunrpc/clnt.c
--- linux-2.6.11/net/sunrpc/clnt.c	2005-04-19 09:15:35.000000000 +0200
+++ linux-2.6.11-09/net/sunrpc/clnt.c	2005-05-25 08:01:04.000000000 +0200
@@ -777,7 +777,7 @@
 				task->tk_pid, task->tk_status);
 
 	task->tk_action = call_connect;
-
+	
 	if (!xprt_is_bound(xprt)) {
 		task->tk_action = call_bind_status;
 		task->tk_timeout = xprt->bind_timeout;
@@ -811,6 +811,11 @@
 		task->tk_action = call_bind;
 		rpc_delay(task, 3*HZ);
 		break;
+	case -ENOSYS:
+	  task->tk_action = call_bind;
+	  task->tk_xprt->bind_idx++;
+	  break;
+	  
 	default:
 		rpc_exit(task, -EIO);
 	}
@@ -947,7 +952,7 @@
 		break;
 	default:
 		if (clnt->cl_chatty)
-			dprintk("%s: RPC call returned error %d\n",
+			printk("%s: RPC call returned error %d\n",
 			       clnt->cl_protname, -status);
 		rpc_exit(task, status);
 		break;
@@ -1007,7 +1012,7 @@
 
 	dprintk("RPC: %5u call_decode (status %d)\n", 
 				task->tk_pid, task->tk_status);
-
+	 
 	if (clnt->cl_chatty && (task->tk_flags & RPC_CALL_MAJORSEEN)) {
 		printk(KERN_NOTICE "%s: server %s OK\n",
 			clnt->cl_protname, clnt->cl_server);
diff -Nru linux-2.6.11/net/sunrpc/clnt.c~ linux-2.6.11-09/net/sunrpc/clnt.c~
--- linux-2.6.11/net/sunrpc/clnt.c~	2005-03-14 14:51:31.000000000 +0100
+++ linux-2.6.11-09/net/sunrpc/clnt.c~	1970-01-01 01:00:00.000000000 +0100
@@ -1,1241 +0,0 @@
-/*
- *  linux/net/sunrpc/clnt.c
- *
- *  This file contains the high-level RPC interface.
- *  It is modeled as a finite state machine to support both synchronous
- *  and asynchronous requests.
- *
- *  -	RPC header generation and argument serialization.
- *  -	Credential refresh.
- *  -	TCP connect handling.
- *  -	Retry of operation when it is suspected the operation failed because
- *	of uid squashing on the server, or when the credentials were stale
- *	and need to be refreshed, or when a packet was damaged in transit.
- *	This may be have to be moved to the VFS layer.
- *
- *  NB: BSD uses a more intelligent approach to guessing when a request
- *  or reply has been lost by keeping the RTO estimate for each procedure.
- *  We currently make do with a constant timeout value.
- *
- *  Copyright (C) 1992,1993 Rick Sladkey <jrs@world.std.com>
- *  Copyright (C) 1995,1996 Olaf Kirch <okir@monad.swb.de>
- */
-
-#include <asm/system.h>
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/utsname.h>
-
-#include <linux/sunrpc/clnt.h>
-#include <linux/workqueue.h>
-#include <linux/sunrpc/rpc_pipe_fs.h>
-
-#include <linux/nfs.h>
-
-
-#define RPC_SLACK_SPACE		(1024)	/* total overkill */
-
-#ifdef RPC_DEBUG
-# define RPCDBG_FACILITY	RPCDBG_CALL
-#endif
-
-static DECLARE_WAIT_QUEUE_HEAD(destroy_wait);
-
-
-static void	call_start(struct rpc_task *task);
-static void	call_reserve(struct rpc_task *task);
-static void	call_reserveresult(struct rpc_task *task);
-static void	call_allocate(struct rpc_task *task);
-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_bind_status(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);
-static void	call_refreshresult(struct rpc_task *task);
-static void	call_timeout(struct rpc_task *task);
-static void	call_connect(struct rpc_task *task);
-static void	call_connect_status(struct rpc_task *task);
-static u32 *	call_header(struct rpc_task *task);
-static u32 *	call_verify(struct rpc_task *task);
-
-
-static int
-rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name)
-{
-	static uint32_t clntid;
-	int error;
-
-	if (dir_name == NULL)
-		return 0;
-	for (;;) {
-		snprintf(clnt->cl_pathname, sizeof(clnt->cl_pathname),
-				"%s/clnt%x", dir_name,
-				(unsigned int)clntid++);
-		clnt->cl_pathname[sizeof(clnt->cl_pathname) - 1] = '\0';
-		clnt->cl_dentry = rpc_mkdir(clnt->cl_pathname, clnt);
-		if (!IS_ERR(clnt->cl_dentry))
-			return 0;
-		error = PTR_ERR(clnt->cl_dentry);
-		if (error != -EEXIST) {
-			printk(KERN_INFO "RPC: Couldn't create pipefs entry %s, error %d\n",
-					clnt->cl_pathname, error);
-			return error;
-		}
-	}
-}
-
-/*
- * Create an RPC client
- * FIXME: This should also take a flags argument (as in task->tk_flags).
- * It's called (among others) from pmap_create_client, which may in
- * turn be called by an async task. In this case, rpciod should not be
- * made to sleep too long.
- */
-static struct rpc_clnt * rpc_create_client(struct rpc_xprt *xprt, char *servname, struct rpc_program *program, u32 vers, rpc_authflavor_t flavor)
-{
-	struct rpc_version	*version;
-	struct rpc_clnt		*clnt = NULL;
-	int err;
-	int len;
-
-	dprintk("RPC:       creating %s client for %s (xprt %p)\n",
-		program->name, servname, xprt);
-
-	err = -EINVAL;
-	if (!xprt)
-		goto out_err;
-	if (vers >= program->nrvers || !(version = program->version[vers]))
-		goto out_err;
-
-	err = -ENOMEM;
-	clnt = (struct rpc_clnt *) kmalloc(sizeof(*clnt), GFP_KERNEL);
-	if (!clnt)
-		goto out_err;
-	memset(clnt, 0, sizeof(*clnt));
-	atomic_set(&clnt->cl_users, 0);
-	atomic_set(&clnt->cl_count, 1);
-	clnt->cl_parent = clnt;
-
-	clnt->cl_server = clnt->cl_inline_name;
-	len = strlen(servname) + 1;
-	if (len > sizeof(clnt->cl_inline_name)) {
-		char *buf = kmalloc(len, GFP_KERNEL);
-		if (buf != 0)
-			clnt->cl_server = buf;
-		else
-			len = sizeof(clnt->cl_inline_name);
-	}
-	strlcpy(clnt->cl_server, servname, len);
-
-	clnt->cl_xprt     = xprt;
-	clnt->cl_procinfo = version->procs;
-	clnt->cl_maxproc  = version->nrprocs;
-	clnt->cl_protname = program->name;
-	clnt->cl_prog     = program->number;
-	clnt->cl_vers     = version->number;
-	clnt->cl_stats    = program->stats;
-
-	if (!xprt_is_bound(clnt->cl_xprt))
-		clnt->cl_autobind = 1;
-
-	clnt->cl_rtt = &clnt->cl_rtt_default;
-	rpc_init_rtt(&clnt->cl_rtt_default, xprt->timeout.to_initval);
-
-	err = rpc_setup_pipedir(clnt, program->pipe_dir_name);
-	if (err < 0)
-		goto out_no_path;
-
-	err = -ENOMEM;
-	if (!rpcauth_create(flavor, clnt)) {
-		printk(KERN_INFO "RPC: Couldn't create auth handle (flavor %u)\n",
-				flavor);
-		goto out_no_auth;
-	}
-
-	/* save the nodename */
-	clnt->cl_nodelen = strlen(system_utsname.nodename);
-	if (clnt->cl_nodelen > UNX_MAXNODENAME)
-		clnt->cl_nodelen = UNX_MAXNODENAME;
-	memcpy(clnt->cl_nodename, system_utsname.nodename, clnt->cl_nodelen);
-	return clnt;
-
-out_no_auth:
-	rpc_rmdir(clnt->cl_pathname);
-out_no_path:
-	if (clnt->cl_server != clnt->cl_inline_name)
-		kfree(clnt->cl_server);
-	kfree(clnt);
-out_err:
-	return ERR_PTR(err);
-}
-
-/*
- * Create an RPC client and transport with one call.
- */
-struct rpc_clnt *rpc_create(struct rpc_create_args *args)
-{
-	struct rpc_xprt *xprt;
-	struct rpc_clnt *clnt;
-
-	xprt = xprt_create_transport(args->protocol, args->address,
-					args->addrsize, args->timeout);
-	if (IS_ERR(xprt))
-		return (struct rpc_clnt *)xprt;
-
-	clnt = rpc_create_client(xprt, args->servername, args->program,
-					args->version, args->authflavor);
-
-	if (IS_ERR(clnt)) {
-		xprt_destroy(xprt);
-		return clnt;
-	}
-
-	if (args->behavior & RPC_CLNT_SOFTRTRY)
-		clnt->cl_softrtry = 1;
-	if (args->behavior & RPC_CLNT_INTR)
-		clnt->cl_intr = 1;
-	if (args->behavior & RPC_CLNT_CHATTY)
-		clnt->cl_chatty = 1;
-	if (args->behavior & RPC_CLNT_AUTOBIND)
-		clnt->cl_autobind = 1;
-	if (args->behavior & RPC_CLNT_ONESHOT)
-		clnt->cl_oneshot = 1;
-	if (args->behavior & RPC_CLNT_RESVPORT)
-		xprt->resvport = 1;
-
-	return clnt;
-}
-EXPORT_SYMBOL(rpc_create);
-
-/*
- * This function clones the RPC client structure. It allows us to share the
- * same transport while varying parameters such as the authentication
- * flavour.
- */
-struct rpc_clnt *
-rpc_clone_client(struct rpc_clnt *clnt)
-{
-	struct rpc_clnt *new;
-
-	new = (struct rpc_clnt *)kmalloc(sizeof(*new), GFP_KERNEL);
-	if (!new)
-		goto out_no_clnt;
-	memcpy(new, clnt, sizeof(*new));
-	atomic_set(&new->cl_count, 1);
-	atomic_set(&new->cl_users, 0);
-	new->cl_parent = clnt;
-	atomic_inc(&clnt->cl_count);
-	/* Turn off autobind on clones */
-	new->cl_autobind = 0;
-	new->cl_oneshot = 0;
-	new->cl_dead = 0;
-	rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval);
-	if (new->cl_auth)
-		atomic_inc(&new->cl_auth->au_count);
-	return new;
-out_no_clnt:
-	printk(KERN_INFO "RPC: out of memory in %s\n", __FUNCTION__);
-	return ERR_PTR(-ENOMEM);
-}
-
-/*
- * Properly shut down an RPC client, terminating all outstanding
- * requests. Note that we must be certain that cl_oneshot and
- * cl_dead are cleared, or else the client would be destroyed
- * when the last task releases it.
- */
-int
-rpc_shutdown_client(struct rpc_clnt *clnt)
-{
-	dprintk("RPC:       shutting down %s client for %s, tasks=%d\n",
-			clnt->cl_protname, clnt->cl_server,
-			atomic_read(&clnt->cl_users));
-
-	while (atomic_read(&clnt->cl_users) > 0) {
-		/* Don't let rpc_release_client destroy us */
-		clnt->cl_oneshot = 0;
-		clnt->cl_dead = 0;
-		rpc_killall_tasks(clnt);
-		sleep_on_timeout(&destroy_wait, 1*HZ);
-	}
-
-	if (atomic_read(&clnt->cl_users) < 0) {
-		printk(KERN_ERR "RPC: rpc_shutdown_client clnt %p tasks=%d\n",
-				clnt, atomic_read(&clnt->cl_users));
-#ifdef RPC_DEBUG
-		rpc_show_tasks();
-#endif
-		BUG();
-	}
-
-	return rpc_destroy_client(clnt);
-}
-
-/*
- * Delete an RPC client
- */
-int
-rpc_destroy_client(struct rpc_clnt *clnt)
-{
-	if (!atomic_dec_and_test(&clnt->cl_count))
-		return 1;
-	BUG_ON(atomic_read(&clnt->cl_users) != 0);
-
-	dprintk("RPC:       destroying %s client for %s\n",
-			clnt->cl_protname, clnt->cl_server);
-	if (clnt->cl_auth) {
-		rpcauth_destroy(clnt->cl_auth);
-		clnt->cl_auth = NULL;
-	}
-	if (clnt->cl_parent != clnt) {
-		rpc_destroy_client(clnt->cl_parent);
-		goto out_free;
-	}
-	if (clnt->cl_pathname[0])
-		rpc_rmdir(clnt->cl_pathname);
-	if (clnt->cl_xprt) {
-		rpc_put_xprt(clnt->cl_xprt);
-		clnt->cl_xprt = NULL;
-	}
-	if (clnt->cl_server != clnt->cl_inline_name)
-		kfree(clnt->cl_server);
-out_free:
-	kfree(clnt);
-	return 0;
-}
-
-/*
- * Release an RPC client
- */
-void
-rpc_release_client(struct rpc_clnt *clnt)
-{
-	dprintk("RPC:       rpc_release_client(%p, %d)\n",
-				clnt, atomic_read(&clnt->cl_users));
-
-	if (!atomic_dec_and_test(&clnt->cl_users))
-		return;
-	wake_up(&destroy_wait);
-	if (clnt->cl_oneshot || clnt->cl_dead)
-		rpc_destroy_client(clnt);
-}
-
-/*
- * Change the program of a (usually cloned) client
- */
-void
-rpc_change_program(struct rpc_clnt *clnt, struct rpc_program *program,
-		   int vers)
-{
-	struct rpc_version *version;
-
-	BUG_ON(vers >= program->nrvers || !program->version[vers]);
-	version = program->version[vers];
-	clnt->cl_procinfo = version->procs;
-	clnt->cl_maxproc  = version->nrprocs;
-	clnt->cl_protname = program->name;
-	clnt->cl_prog     = program->number;
-	clnt->cl_vers     = version->number;
-	clnt->cl_stats    = program->stats;
-}
-
-/*
- * Default callback for async RPC calls
- */
-static void
-rpc_default_callback(struct rpc_task *task)
-{
-}
-
-/*
- *	Export the signal mask handling for aysnchronous code that
- *	sleeps on RPC calls
- */
- 
-void rpc_clnt_sigmask(struct rpc_clnt *clnt, sigset_t *oldset)
-{
-	unsigned long	sigallow = sigmask(SIGKILL);
-	unsigned long	irqflags;
-	
-	/* Turn off various signals */
-	if (clnt->cl_intr) {
-		struct k_sigaction *action = current->sighand->action;
-		if (action[SIGINT-1].sa.sa_handler == SIG_DFL)
-			sigallow |= sigmask(SIGINT);
-		if (action[SIGQUIT-1].sa.sa_handler == SIG_DFL)
-			sigallow |= sigmask(SIGQUIT);
-	}
-	spin_lock_irqsave(&current->sighand->siglock, irqflags);
-	*oldset = current->blocked;
-	siginitsetinv(&current->blocked, sigallow & ~oldset->sig[0]);
-	recalc_sigpending();
-	spin_unlock_irqrestore(&current->sighand->siglock, irqflags);
-}
-
-void rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset)
-{
-	unsigned long	irqflags;
-	
-	spin_lock_irqsave(&current->sighand->siglock, irqflags);
-	current->blocked = *oldset;
-	recalc_sigpending();
-	spin_unlock_irqrestore(&current->sighand->siglock, irqflags);
-}
-
-/*
- * New rpc_call implementation
- */
-int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
-{
-	struct rpc_task	*task;
-	sigset_t	oldset;
-	int		status;
-
-	/* If this client is slain all further I/O fails */
-	if (clnt->cl_dead) 
-		return -EIO;
-
-	BUG_ON(flags & RPC_TASK_ASYNC);
-
-	rpc_clnt_sigmask(clnt, &oldset);		
-
-	status = -ENOMEM;
-	task = rpc_new_task(clnt, NULL, flags);
-	if (task == NULL)
-		goto out;
-
-	rpc_call_setup(task, msg, 0);
-
-	/* Set up the call info struct and execute the task */
-	if (task->tk_status == 0)
-		status = rpc_execute(task);
-	else {
-		status = task->tk_status;
-		rpc_release_task(task);
-	}
-
-out:
-	rpc_clnt_sigunmask(clnt, &oldset);		
-
-	return status;
-}
-
-/**
- * rpc_client_get_xprt() - Get reference to the RPC transport struct
- * @clnt - pointer to RPC client
- */
-struct rpc_xprt *rpc_client_get_xprt(struct rpc_clnt *clnt)
-{
-	struct rpc_xprt *xprt;
-
-	/* Synchronize w.r.t. rpc_client_set_xprt() */
-	rcu_read_lock();
-	xprt = clnt->cl_xprt;
-	atomic_inc(&xprt->count);
-	rcu_read_unlock();
-	return xprt;
-}
-
-/**
- * rpc_client_set_xprt() - Change the transport struct pointer on an in-use RPC client
- * @clnt - pointer to RPC client
- * @xprt - new transport
- *
- * This function should be called VERY infrequently, and is designed
- * to be called only in case of a failover mount.
- */
-void rpc_client_set_xprt(struct rpc_clnt *clnt, struct rpc_xprt *xprt)
-{
-	struct rpc_xprt *old;
-
-	old = xchg(&clnt->cl_xprt, xprt);
-	/* Wait for all reads of clnt->cl_xprt == old to complete */
-	synchronize_kernel();
-	rpc_put_xprt(old);
-}
-EXPORT_SYMBOL(rpc_client_set_xprt);
-
-/*
- * New rpc_call implementation
- */
-int
-rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags,
-	       rpc_action callback, void *data)
-{
-	struct rpc_task	*task;
-	sigset_t	oldset;
-	int		status;
-
-	/* If this client is slain all further I/O fails */
-	if (clnt->cl_dead) 
-		return -EIO;
-
-	flags |= RPC_TASK_ASYNC;
-
-	rpc_clnt_sigmask(clnt, &oldset);		
-
-	/* Create/initialize a new RPC task */
-	if (!callback)
-		callback = rpc_default_callback;
-	status = -ENOMEM;
-	if (!(task = rpc_new_task(clnt, callback, flags)))
-		goto out;
-	task->tk_calldata = data;
-
-	rpc_call_setup(task, msg, 0);
-
-	/* Set up the call info struct and execute the task */
-	status = task->tk_status;
-	if (status == 0)
-		rpc_execute(task);
-	else
-		rpc_release_task(task);
-
-out:
-	rpc_clnt_sigunmask(clnt, &oldset);		
-
-	return status;
-}
-
-
-void
-rpc_call_setup(struct rpc_task *task, struct rpc_message *msg, int flags)
-{
-	task->tk_msg   = *msg;
-	task->tk_flags |= flags;
-	/* Bind the user cred */
-	if (task->tk_msg.rpc_cred != NULL)
-		rpcauth_holdcred(task);
-	else
-		rpcauth_bindcred(task);
-
-	if (task->tk_status == 0)
-		task->tk_action = call_start;
-	else
-		task->tk_action = NULL;
-}
-
-void
-rpc_setbufsize(struct rpc_clnt *clnt, unsigned int sndsize, unsigned int rcvsize)
-{
-	struct rpc_xprt *xprt = rpc_client_get_xprt(clnt);
-	xprt->ops->setbufsize(xprt, sndsize, rcvsize);
-	rpc_put_xprt(xprt);
-}
-
-/*
- * Return size of largest payload RPC client can support, in bytes
- *
- * For stream transports, this is one RPC record fragment (see RFC
- * 1831), as we don't support multi-record requests yet.  For datagram
- * transports, this is the size of an IP packet minus the IP, UDP, and
- * RPC header sizes.
- */
-size_t rpc_max_payload(struct rpc_clnt *clnt)
-{
-	size_t result;
-	struct rpc_xprt *xprt = rpc_client_get_xprt(clnt);
-	result = xprt->max_payload;
-	rpc_put_xprt(xprt);
-	return result;
-}
-EXPORT_SYMBOL(rpc_max_payload);
-
-void rpc_force_rebind(struct rpc_clnt *clnt)
-{
-	struct rpc_xprt *xprt = rpc_client_get_xprt(clnt);
-	if (clnt->cl_autobind)
-		xprt->need_bind = 1;
-	rpc_put_xprt(xprt);
-}
-EXPORT_SYMBOL(rpc_force_rebind);
-
-void rpc_peeraddr(struct rpc_clnt *clnt, void *buf, size_t size)
-{
-	size_t bytes;
-	struct rpc_xprt *xprt = rpc_client_get_xprt(clnt);
-
-	bytes = sizeof(xprt->addr);
-	if (bytes > size)
-		bytes = size;
-	memcpy(buf, &clnt->cl_xprt->addr, bytes);
-	rpc_put_xprt(xprt);
-}
-EXPORT_SYMBOL(rpc_peeraddr);
-
-void rpc_print_peeraddr(struct rpc_clnt *clnt, char *buf, size_t size, int flags)
-{
-	struct rpc_xprt *xprt = rpc_client_get_xprt(clnt);
-	xprt->ops->print_addr(xprt, size, buf, flags);
-	rpc_put_xprt(xprt);
-}
-EXPORT_SYMBOL(rpc_print_peeraddr);
-
-int rpc_aux_protocol(struct rpc_clnt *clnt)
-{
-	int result;
-	struct rpc_xprt *xprt = rpc_client_get_xprt(clnt);
-	result = xprt->ops->aux_protocol(xprt);
-	rpc_put_xprt(xprt);
-	return result;
-}
-EXPORT_SYMBOL(rpc_aux_protocol);
-
-/*
- * Restart an (async) RPC call. Usually called from within the
- * exit handler.
- */
-void
-rpc_restart_call(struct rpc_task *task)
-{
-	if (RPC_ASSASSINATED(task))
-		return;
-
-	task->tk_action = call_start;
-}
-
-/*
- * 0.  Initial state
- *
- *     Other FSM states can be visited zero or more times, but
- *     this state is visited exactly once for each RPC.
- */
-static void
-call_start(struct rpc_task *task)
-{
-	struct rpc_clnt	*clnt = task->tk_client;
-
-	dprintk("RPC: %5u call_start %s%d proc %d (%s)\n", task->tk_pid,
-		clnt->cl_protname, clnt->cl_vers, task->tk_msg.rpc_proc->p_proc,
-		(RPC_IS_ASYNC(task) ? "async" : "sync"));
-
-	/* Increment call count */
-	task->tk_msg.rpc_proc->p_count++;
-	clnt->cl_stats->rpccnt++;
-	task->tk_action = call_reserve;
-}
-
-/*
- * 1.	Reserve an RPC call slot
- */
-static void
-call_reserve(struct rpc_task *task)
-{
-	dprintk("RPC: %5u call_reserve\n", task->tk_pid);
-
-	if (!rpcauth_uptodatecred(task)) {
-		task->tk_action = call_refresh;
-		return;
-	}
-
-	task->tk_status  = 0;
-	task->tk_action  = call_reserveresult;
-	xprt_reserve(task);
-}
-
-/*
- * 1b.	Grok the result of xprt_reserve()
- */
-static void
-call_reserveresult(struct rpc_task *task)
-{
-	int status = task->tk_status;
-
-	dprintk("RPC: %5u call_reserveresult (status %d)\n",
-				task->tk_pid, task->tk_status);
-
-	/*
-	 * After a call to xprt_reserve(), we must have either
-	 * a request slot or else an error status.
-	 */
-	task->tk_status = 0;
-	if (status >= 0) {
-		task->tk_action = call_allocate;
-		return;
-	}
-
-	switch (status) {
-	case -EAGAIN:	/* woken up; retry */
-		task->tk_action = call_reserve;
-		return;
-	case -EIO:	/* probably a shutdown */
-		break;
-	default:
-		printk(KERN_ERR "%s: unrecognized error %d, exiting\n",
-				__FUNCTION__, status);
-		break;
-	}
-	rpc_exit(task, status);
-}
-
-/*
- * 2.	Allocate the buffer. For details, see sched.c:rpc_malloc.
- *	(Note: buffer memory is freed in xprt_release).
- */
-static void
-call_allocate(struct rpc_task *task)
-{
-	struct rpc_rqst *req = &task->tk_rqst;
-	struct rpc_xprt *xprt = task->tk_xprt;
-	unsigned int	bufsiz;
-
-	dprintk("RPC: %5u call_allocate (status %d)\n", 
-				task->tk_pid, task->tk_status);
-	task->tk_action = call_bind;
-	if (req->rq_buffer)
-		return;
-
-	/* FIXME: compute buffer requirements more exactly using
-	 * auth->au_wslack */
-	bufsiz = task->tk_msg.rpc_proc->p_bufsiz + RPC_SLACK_SPACE;
-
-	if (xprt->ops->buf_alloc(task, bufsiz << 1) != NULL)
-		return;
-	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;
-		rpc_delay(task, HZ>>4);
-		return;
-	}
-
-	rpc_exit(task, -ERESTARTSYS);
-}
-
-/*
- * 3.	Encode arguments of an RPC call
- */
-static void
-call_encode(struct rpc_task *task)
-{
-	struct rpc_clnt	*clnt = task->tk_client;
-	struct rpc_rqst	*req = &task->tk_rqst;
-	struct xdr_buf *sndbuf = &req->rq_snd_buf;
-	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
-	unsigned int	bufsiz;
-	kxdrproc_t	encode;
-	int		status;
-	u32		*p;
-
-	dprintk("RPC: %5u call_encode (status %d)\n", 
-				task->tk_pid, task->tk_status);
-
-	/* Default buffer setup */
-	bufsiz = req->rq_bufsize >> 1;
-	sndbuf->head[0].iov_base = (void *)req->rq_buffer;
-	sndbuf->head[0].iov_len  = bufsiz;
-	sndbuf->tail[0].iov_len  = 0;
-	sndbuf->page_len	 = 0;
-	sndbuf->len		 = 0;
-	sndbuf->buflen		 = bufsiz;
-	rcvbuf->head[0].iov_base = (void *)((char *)req->rq_buffer + bufsiz);
-	rcvbuf->head[0].iov_len  = bufsiz;
-	rcvbuf->tail[0].iov_len  = 0;
-	rcvbuf->page_len	 = 0;
-	rcvbuf->len		 = 0;
-	rcvbuf->buflen		 = bufsiz;
-
-	/* Encode header and provided arguments */
-	encode = task->tk_msg.rpc_proc->p_encode;
-	if (!(p = call_header(task))) {
-		printk(KERN_INFO "RPC: call_header failed, exit EIO\n");
-		rpc_exit(task, -EIO);
-		return;
-	}
-	if (encode == NULL)
-		return;
-
-	status = rpcauth_wrap_req(task, encode, req, p, task->tk_msg.rpc_argp);
-	if (status == -ENOMEM) {
-		/* XXX: Is this sane? */
-		rpc_delay(task, 3*HZ);
-		task->tk_status = -EAGAIN;
-		return;
-	}
-	if (status < 0) {
-		printk(KERN_WARNING "%s: can't encode arguments: %d\n",
-				clnt->cl_protname, -status);
-		rpc_exit(task, status);
-	}
-}
-
-/*
- * 4.	Get the server port number if not yet set
- */
-static void
-call_bind(struct rpc_task *task)
-{
-	struct rpc_xprt *xprt = task->tk_xprt;
-
-	dprintk("RPC: %5u call_bind (status %d)\n", 
-				task->tk_pid, task->tk_status);
-
-	task->tk_action = call_connect;
-
-	if (!xprt_is_bound(xprt)) {
-		task->tk_action = call_bind_status;
-		task->tk_timeout = xprt->bind_timeout;
-		xprt->ops->rpcbind(task, task->tk_client);
-	}
-}
-
-/*
- * 4. Sort out bind result
- */
-static void
-call_bind_status(struct rpc_task *task)
-{
-	dprintk("RPC: %5u call_bind_status (status %d)\n", 
-				task->tk_pid, task->tk_status);
-
-	if (task->tk_status >= 0) {
-		task->tk_status = 0;
-		task->tk_action = call_connect;
-		return;
-	}
-
-	if (RPC_IS_SOFT(task)) {
-		rpc_exit(task, -EIO);
-		return;
-	}
-
-	switch (task->tk_status) {
-	case -ETIMEDOUT:
-	case -EACCES:	/* rpcbind version not available */
-		task->tk_action = call_bind;
-		rpc_delay(task, 3*HZ);
-		break;
-	default:
-		rpc_exit(task, -EIO);
-	}
-}
-
-/*
- * 4a.	Connect to the RPC server (TCP case)
- */
-static void
-call_connect(struct rpc_task *task)
-{
-	struct rpc_xprt *xprt = task->tk_xprt;
-
-	dprintk("RPC: %5u call_connect xprt %p %s connected\n",
-			task->tk_pid, xprt,
-			(xprt_connected(xprt) ? "is" : "is not"));
-
-	if (xprt_connected(xprt)) {
-		task->tk_action = call_transmit;
-		return;
-	}
-	task->tk_action = call_connect_status;
-	if (task->tk_status < 0)
-		return;
-	xprt_connect(task);
-}
-
-/*
- * 4a. Sort out connect result
- */
-static void
-call_connect_status(struct rpc_task *task)
-{
-	struct rpc_clnt *clnt = task->tk_client;
-	int status = task->tk_status;
-
-	dprintk("RPC: %5u call_connect_status (status %d)\n", 
-				task->tk_pid, task->tk_status);
-
-	task->tk_status = 0;
-	if (status >= 0) {
-		clnt->cl_stats->netreconn++;
-		task->tk_action = call_transmit;
-		return;
-	}
-
-	/* Something failed: we may have to rebind */
-	rpc_force_rebind(clnt);
-
-	if (RPC_IS_SOFT(task)) {
-		rpc_exit(task, -EIO);
-		return;
-	}
-
-	switch (status) {
-	case -ENOTCONN:
-	case -ETIMEDOUT:
-	case -EAGAIN:
-		task->tk_action = call_bind;
-		break;
-	default:
-		rpc_exit(task, -EIO);
-	}
-}
-
-/*
- * 5.	Transmit the RPC request, and wait for reply
- */
-static void
-call_transmit(struct rpc_task *task)
-{
-	dprintk("RPC: %5u call_transmit (status %d)\n", 
-				task->tk_pid, task->tk_status);
-
-	task->tk_action = call_status;
-	if (task->tk_status < 0)
-		return;
-	task->tk_status = xprt_prepare_transmit(task);
-	if (task->tk_status != 0)
-		return;
-	/* Encode here so that rpcsec_gss can use correct sequence number. */
-	if (!task->tk_rqst.rq_bytes_sent)
-		call_encode(task);
-	if (task->tk_status < 0)
-		return;
-	xprt_transmit(task);
-	if (task->tk_status < 0)
-		return;
-	if (!task->tk_msg.rpc_proc->p_decode) {
-		task->tk_action = NULL;
-		rpc_wake_up_task(task);
-	}
-}
-
-/*
- * 6.	Sort out the RPC call status
- */
-static void
-call_status(struct rpc_task *task)
-{
-	struct rpc_clnt	*clnt = task->tk_client;
-	struct rpc_rqst	*req = &task->tk_rqst;
-	int		status;
-
-	if (req->rq_received > 0 && !req->rq_bytes_sent)
-		task->tk_status = req->rq_received;
-
-	dprintk("RPC: %5u call_status (status %d)\n", 
-				task->tk_pid, task->tk_status);
-
-	status = task->tk_status;
-	if (status >= 0) {
-		task->tk_action = call_decode;
-		return;
-	}
-
-	task->tk_status = 0;
-	switch(status) {
-	case -ETIMEDOUT:
-		task->tk_action = call_timeout;
-		break;
-	case -ECONNREFUSED:
-	case -ENOTCONN:
-		req->rq_bytes_sent = 0;
-		rpc_force_rebind(clnt);
-		task->tk_action = call_bind;
-		break;
-	case -EAGAIN:
-		task->tk_action = call_transmit;
-		break;
-	case -EIO:
-		/* shutdown or soft timeout */
-		rpc_exit(task, status);
-		break;
-	default:
-		if (clnt->cl_chatty)
-			printk("%s: RPC call returned error %d\n",
-			       clnt->cl_protname, -status);
-		rpc_exit(task, status);
-		break;
-	}
-}
-
-/*
- * 6a.	Handle RPC timeout
- * 	We do not release the request slot, so we keep using the
- *	same XID for all retransmits.
- */
-static void
-call_timeout(struct rpc_task *task)
-{
-	struct rpc_clnt	*clnt = task->tk_client;
-	struct rpc_xprt *xprt = task->tk_xprt;
-
-	if (xprt_adjust_timeout(xprt, &task->tk_rqst) == 0) {
-		dprintk("RPC: %5u call_timeout (minor)\n", task->tk_pid);
-		goto retry;
-	}
-
-	dprintk("RPC: %5u call_timeout (major)\n", task->tk_pid);
-	xprt->ops->timeout(xprt);
-
-	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);
-		rpc_exit(task, -EIO);
-		return;
-	}
-
-	if (clnt->cl_chatty && !(task->tk_flags & RPC_CALL_MAJORSEEN)) {
-		task->tk_flags |= RPC_CALL_MAJORSEEN;
-		printk(KERN_NOTICE "%s: server %s not responding, still trying\n",
-			clnt->cl_protname, clnt->cl_server);
-	}
-	rpc_force_rebind(clnt);
-
-retry:
-	clnt->cl_stats->rpcretrans++;
-	task->tk_action = call_bind;
-	task->tk_status = 0;
-}
-
-/*
- * 7.	Decode the RPC reply
- */
-static void
-call_decode(struct rpc_task *task)
-{
-	struct rpc_clnt	*clnt = task->tk_client;
-	struct rpc_rqst	*req = &task->tk_rqst;
-	kxdrproc_t	decode = task->tk_msg.rpc_proc->p_decode;
-	u32		*p;
-
-	dprintk("RPC: %5u call_decode (status %d)\n", 
-				task->tk_pid, task->tk_status);
-
-	if (clnt->cl_chatty && (task->tk_flags & RPC_CALL_MAJORSEEN)) {
-		printk(KERN_NOTICE "%s: server %s OK\n",
-			clnt->cl_protname, clnt->cl_server);
-		task->tk_flags &= ~RPC_CALL_MAJORSEEN;
-	}
-
-	if (task->tk_status < 12) {
-		if (!RPC_IS_SOFT(task)) {
-			task->tk_action = call_bind;
-			clnt->cl_stats->rpcretrans++;
-			goto out_retry;
-		}
-		printk(KERN_WARNING "%s: too small RPC reply size (%d bytes)\n",
-			clnt->cl_protname, task->tk_status);
-		rpc_exit(task, -EIO);
-		return;
-	}
-
-	req->rq_rcv_buf.len = req->rq_private_buf.len;
-
-	/* Check that the softirq receive buffer is valid */
-	WARN_ON(memcmp(&req->rq_rcv_buf, &req->rq_private_buf,
-				sizeof(req->rq_rcv_buf)) != 0);
-
-	/* Verify the RPC header */
-	if (!(p = call_verify(task))) {
-		if (task->tk_action == NULL)
-			return;
-		goto out_retry;
-	}
-
-	task->tk_action = NULL;
-
-	if (decode)
-		task->tk_status = rpcauth_unwrap_resp(task, decode, req, p,
-						      task->tk_msg.rpc_resp);
-	dprintk("RPC: %5u call_decode result %d\n", task->tk_pid,
-					task->tk_status);
-	return;
-out_retry:
-	req->rq_received = req->rq_private_buf.len = 0;
-	task->tk_status = 0;
-}
-
-/*
- * 8.	Refresh the credentials if rejected by the server
- */
-static void
-call_refresh(struct rpc_task *task)
-{
-	dprintk("RPC: %5u call_refresh\n", task->tk_pid);
-
-	xprt_release(task);	/* Must do to obtain new XID */
-	task->tk_action = call_refreshresult;
-	task->tk_status = 0;
-	task->tk_client->cl_stats->rpcauthrefresh++;
-	rpcauth_refreshcred(task);
-}
-
-/*
- * 8a.	Process the results of a credential refresh
- */
-static void
-call_refreshresult(struct rpc_task *task)
-{
-	int status = task->tk_status;
-	dprintk("RPC: %5u call_refreshresult (status %d)\n", 
-				task->tk_pid, task->tk_status);
-
-	task->tk_status = 0;
-	task->tk_action = call_reserve;
-	if (status >= 0 && rpcauth_uptodatecred(task))
-		return;
-	if (status == -EACCES) {
-		rpc_exit(task, -EACCES);
-		return;
-	}
-	task->tk_action = call_refresh;
-	if (status != -ETIMEDOUT)
-		rpc_delay(task, 3*HZ);
-	return;
-}
-
-/*
- * Call header serialization
- */
-static u32 *
-call_header(struct rpc_task *task)
-{
-	struct rpc_clnt *clnt = task->tk_client;
-	struct rpc_rqst	*req = &task->tk_rqst;
-	u32		*p = req->rq_svec[0].iov_base;
-
-	/* FIXME: check buffer size? */
-	p += xprt_tsh_size(task->tk_xprt) / sizeof(*p);
-	*p++ = req->rq_xid;		/* XID */
-	*p++ = htonl(RPC_CALL);		/* CALL */
-	*p++ = htonl(RPC_VERSION);	/* RPC version */
-	*p++ = htonl(clnt->cl_prog);	/* program number */
-	*p++ = htonl(clnt->cl_vers);	/* program version */
-	*p++ = htonl(task->tk_msg.rpc_proc->p_proc);	/* procedure */
-	return rpcauth_marshcred(task, p);
-}
-
-/*
- * Reply header verification
- */
-static u32 *
-call_verify(struct rpc_task *task)
-{
-	struct kvec *iov = &task->tk_rqst.rq_rcv_buf.head[0];
-	int len = task->tk_rqst.rq_rcv_buf.len >> 2;
-	u32	*p = iov->iov_base, n;
-	int error = -EACCES;
-
-	if ((len -= 3) < 0)
-		goto out_overflow;
-	p += 1;	/* skip XID */
-
-	if ((n = ntohl(*p++)) != RPC_REPLY) {
-		printk(KERN_WARNING "call_verify: not an RPC reply: %x\n", n);
-		goto out_retry;
-	}
-	if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) {
-		if (--len < 0)
-			goto out_overflow;
-		switch ((n = ntohl(*p++))) {
-			case RPC_AUTH_ERROR:
-				break;
-			case RPC_MISMATCH:
-				printk(KERN_WARNING "%s: RPC call version mismatch!\n", __FUNCTION__);
-				error = -ENOSYS;
-				goto out_err;
-			default:
-				printk(KERN_WARNING "%s: RPC call rejected, unknown error: %x\n", __FUNCTION__, n);
-				goto out_eio;
-		}
-		if (--len < 0)
-			goto out_overflow;
-		switch ((n = ntohl(*p++))) {
-		case RPC_AUTH_REJECTEDCRED:
-		case RPC_AUTH_REJECTEDVERF:
-		case RPCSEC_GSS_CREDPROBLEM:
-		case RPCSEC_GSS_CTXPROBLEM:
-			if (!task->tk_cred_retry)
-				break;
-			task->tk_cred_retry--;
-			dprintk("RPC: %5u call_verify: retry stale creds\n",
-							task->tk_pid);
-			rpcauth_invalcred(task);
-			task->tk_action = call_refresh;
-			return NULL;
-		case RPC_AUTH_BADCRED:
-		case RPC_AUTH_BADVERF:
-			/* possibly garbled cred/verf? */
-			if (!task->tk_garb_retry)
-				break;
-			task->tk_garb_retry--;
-			dprintk("RPC: %5u call_verify: retry garbled creds\n",
-							task->tk_pid);
-			task->tk_action = call_bind;
-			return NULL;
-		case RPC_AUTH_TOOWEAK:
-			printk(KERN_NOTICE "call_verify: server requires stronger "
-			       "authentication.\n");
-			break;
-		default:
-			printk(KERN_WARNING "call_verify: unknown auth error: %x\n", n);
-			error = -EIO;
-		}
-		dprintk("RPC: %5u call_verify: call rejected %d\n",
-						task->tk_pid, n);
-		goto out_err;
-	}
-	if (!(p = rpcauth_checkverf(task, p))) {
-		printk(KERN_WARNING "call_verify: auth check failed\n");
-		goto out_retry;		/* bad verifier, retry */
-	}
-	len = p - (u32 *)iov->iov_base - 1;
-	if (len < 0)
-		goto out_overflow;
-	switch ((n = ntohl(*p++))) {
-	case RPC_SUCCESS:
-		return p;
-	case RPC_PROG_UNAVAIL:
-		dprintk("RPC: call_verify: program %u is unsupported by server %s\n",
-				(unsigned int)task->tk_client->cl_prog,
-				task->tk_client->cl_server);
-		error = -ENOSYS;
-		goto out_err;
-	case RPC_PROG_MISMATCH:
-		dprintk("RPC: call_verify: program %u, version %u unsupported by server %s\n",
-				(unsigned int)task->tk_client->cl_prog,
-				(unsigned int)task->tk_client->cl_vers,
-				task->tk_client->cl_server);
-		error = -ENOSYS;
-		goto out_err;
-	case RPC_PROC_UNAVAIL:
-		dprintk("RPC: call_verify: proc %p unsupported by program %u, version %u on server %s\n",
-				task->tk_msg.rpc_proc,
-				task->tk_client->cl_prog,
-				task->tk_client->cl_vers,
-				task->tk_client->cl_server);
-		error = -EOPNOTSUPP;
-		goto out_err;
-	case RPC_GARBAGE_ARGS:
-		dprintk("RPC: %5u %s: server saw garbage\n", task->tk_pid, __FUNCTION__);
-		break;			/* retry */
-	default:
-		printk(KERN_WARNING "call_verify: server accept status: %x\n", n);
-		/* Also retry */
-	}
-
-out_retry:
-	task->tk_client->cl_stats->rpcgarbage++;
-	if (task->tk_garb_retry) {
-		task->tk_garb_retry--;
-		dprintk("RPC %5u %s: retrying\n", task->tk_pid, __FUNCTION__);
-		task->tk_action = call_bind;
-		return NULL;
-	}
-	printk(KERN_WARNING "RPC %s: retry failed, exit EIO\n", __FUNCTION__);
-out_eio:
-	error = -EIO;
-out_err:
-	rpc_exit(task, error);
-	return NULL;
-out_overflow:
-	printk(KERN_WARNING "RPC %s: server reply was truncated.\n", __FUNCTION__);
-	goto out_retry;
-}
diff -Nru linux-2.6.11/net/sunrpc/Makefile linux-2.6.11-09/net/sunrpc/Makefile
--- linux-2.6.11/net/sunrpc/Makefile	2005-03-14 14:51:31.000000000 +0100
+++ linux-2.6.11-09/net/sunrpc/Makefile	2005-04-05 09:15:49.000000000 +0200
@@ -10,7 +10,7 @@
 sunrpc-y := clnt.o xprt.o socklib.o sched.o \
 	    auth.o auth_null.o auth_unix.o \
 	    svc.o svcsock.o svcauth.o svcauth_unix.o \
-	    pmap_clnt.o timer.o xdr.o \
+	    pmap_clnt.o rpcb_clnt.o timer.o xdr.o \
 	    sunrpc_syms.o cache.o rpc_pipe.o
 sunrpc-$(CONFIG_PROC_FS) += stats.o
 sunrpc-$(CONFIG_SYSCTL) += sysctl.o
diff -Nru linux-2.6.11/net/sunrpc/pmap_clnt.c linux-2.6.11-09/net/sunrpc/pmap_clnt.c
--- linux-2.6.11/net/sunrpc/pmap_clnt.c	2005-03-14 14:51:31.000000000 +0100
+++ linux-2.6.11-09/net/sunrpc/pmap_clnt.c	2005-04-21 13:16:39.000000000 +0200
@@ -41,9 +41,6 @@
 
 static struct rpc_procinfo	pmap_procedures[];
 static struct rpc_clnt *	pmap_create(char *, struct sockaddr_in *, int);
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-static struct rpc_clnt *	pmap_create6(char *, struct sockaddr_in6 *, int);
-#endif
 static void			pmap_getport_done(struct rpc_task *);
 static struct rpc_program	pmap_program;
 
@@ -85,7 +82,7 @@
 	if (xprt_is_bound(xprt)) {
 		rpc_exit(task, 0);
 		goto bailout_nofree;
-	}
+			}
 
 	map = kmalloc(sizeof(struct portmap_args), GFP_NOFS);
 	if (!map) {
@@ -133,93 +130,6 @@
 }
 EXPORT_SYMBOL_GPL(pmap_getport);
 
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-void pmap_getport6(struct rpc_task *task, struct rpc_clnt *clnt)
-{
-	int protocol = rpc_aux_protocol(clnt);
-	struct rpc_xprt *xprt = task->tk_xprt;
-	struct sockaddr_in6 addr;
-	struct rpc_message msg = {
-		.rpc_proc	= &pmap_procedures[PMAP_GETPORT],
-		.rpc_cred	= NULL
-	};
-	struct portmap_args *map;
-	struct rpc_clnt	*pmap_clnt;
-	struct rpc_task	*child;
-
-	dprintk("RPC: %5u pmap_getport6(%s, %u, %u, %d)\n",
-			task->tk_pid, clnt->cl_server,
-			clnt->cl_prog, clnt->cl_vers, protocol);
-
-	if (test_and_set_bit(XPRT_BINDING, &xprt->state)) {
-		rpc_sleep_on(&xprt->bindwait, task, NULL, NULL);
-		return;
-	}
-
-	/* Someone else may have bound if we slept */
-	if (xprt_is_bound(xprt)) {
-		rpc_exit(task, 0);
-		goto bailout_nofree;
-	}
-
-	map = kmalloc(sizeof(struct portmap_args), GFP_NOFS);
-	if (!map) {
-		rpc_exit(task, -ENOMEM);
-		goto bailout_nofree;
-	}
-	map->pm_prog = clnt->cl_prog;
-	map->pm_vers = clnt->cl_vers;
-	map->pm_prot = protocol;
-	map->pm_port = 0;
-	map->pm_wake = task;
-
-	rpc_peeraddr(clnt, &addr, sizeof(addr));
-	pmap_clnt = pmap_create6(clnt->cl_server, &addr, map->pm_prot);
-	if (IS_ERR(pmap_clnt)) {
-		rpc_exit(task, PTR_ERR(pmap_clnt));
-		goto bailout;
-	}
-
-	/* NB: rpc_new_child will release client after a failure. */
-	if (!(child = rpc_new_child(pmap_clnt, task))) {
-		rpc_exit(task, -EIO);
-		goto bailout;
-	}
-
-	/* Setup the call info struct */
-	msg.rpc_argp = map;
-	msg.rpc_resp = &map->pm_port;
-	rpc_call_setup(child, &msg, 0);
-	if (child->tk_status != 0) {
-		rpc_exit(task, child->tk_status);
-		goto bailout;
-	}
-
-	/* ... and run the child task */
-	child->tk_calldata = map;
-	child->tk_exit = pmap_getport_done;
-	rpc_run_child(task, child);
-	return;
-
-bailout:
-	kfree(map);
-bailout_nofree:
-	pmap_wake_portmap_waiters(xprt);
-}
-#else
-void pmap_getport6(struct rpc_task *task, struct rpc_clnt *clnt)
-{
-	int protocol = rpc_aux_protocol(clnt);
-
-	dprintk("RPC: %5u pmap_getport6(%s, %u, %u, %d) not supported.\n",
-			task->tk_pid, clnt->cl_server,
-			clnt->cl_prog, clnt->cl_vers, protocol);
-
-	rpc_exit(task, -EBADF);
-}
-#endif
-EXPORT_SYMBOL_GPL(pmap_getport6);
-
 #ifdef CONFIG_ROOT_NFS
 int pmap_getport_external(struct sockaddr_in *sin, u32 prog, u32 vers, int prot)
 {
@@ -344,26 +254,6 @@
 	return rpc_create(&args);
 }
 
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-static struct rpc_clnt * pmap_create6(char *hostname, struct sockaddr_in6 *srvaddr, int proto)
-{
-	struct rpc_create_args args = {
-		.protocol	= proto,
-		.address	= (struct sockaddr *)srvaddr,
-		.addrsize	= sizeof(*srvaddr),
-		.servername	= hostname,
-		.program	= &pmap_program,
-		.version	= RPC_PMAP_VERSION,
-		.authflavor	= RPC_AUTH_UNIX,
-		.behavior	= RPC_CLNT_SOFTRTRY | RPC_CLNT_CHATTY |
-					RPC_CLNT_ONESHOT,
-	};
-
-	srvaddr->sin6_port = htons(RPC_PMAP_PORT);
-	return rpc_create(&args);
-}
-#endif
-
 /*
  * XDR encode/decode functions for PMAP
  */
diff -Nru linux-2.6.11/net/sunrpc/rpcb_clnt.c linux-2.6.11-09/net/sunrpc/rpcb_clnt.c
--- linux-2.6.11/net/sunrpc/rpcb_clnt.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.11-09/net/sunrpc/rpcb_clnt.c	2005-05-25 08:01:12.000000000 +0200
@@ -0,0 +1,393 @@
+/*
+ * linux/net/sunrpc/rpcb_clnt.c
+ *
+ * Rpcbind client.
+ *
+ * Rpcbind supports versions 3 and 4 of the rpcbind protocol (RFC 1833).
+ *
+ * Added by Gilles Quillard, Bull Open Source, 2005 <gilles.quillard@bull.net>
+ * Only getaddr function of rpcbind version 3 is currently impelmented.
+ *
+ * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+
+#include <linux/types.h>
+#include <linux/socket.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+
+#include <linux/sunrpc/clnt.h>
+#include <linux/sunrpc/xprt.h>
+#include <linux/sunrpc/sched.h>
+
+#ifdef RPC_DEBUG
+# define RPCDBG_FACILITY	RPCDBG_PMAP
+#endif
+
+#define RPCB_SET		1
+#define RPCB_UNSET		2
+#define RPCB_GETPORT		3
+#define RPCB_GETADDR		3
+#define RPCB_GETVERSADDR	9
+
+static struct rpc_procinfo	rpcb_procedures[];
+static struct rpc_clnt *	rpcb_create(char *, struct sockaddr *, int, int);
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+static struct rpc_clnt *	rpcb_create6(char *, struct sockaddr *, int, int);
+#endif
+static void			rpcb_getport_done(struct rpc_task *);
+extern struct rpc_program	rpcb_program;
+
+struct rpcbind_args {
+	u32 			r_prog;
+	u32 			r_vers;
+	u32			r_prot;
+	unsigned short		r_port;
+	char 			r_addr[40];
+	struct rpc_task *       r_wake;
+};
+
+struct rpcb_info {
+	int			rpc_vers;
+	struct rpc_procinfo *	rpc_proc;
+};
+
+static struct rpc_procinfo	rpcb_procedures4[];
+static struct rpc_procinfo	rpcb_procedures3[];
+static struct rpc_procinfo	rpcb_procedures2[];
+
+struct rpcb_info rpc_info[] = {
+	{ 4, &rpcb_procedures4[RPCB_GETVERSADDR] },
+	{ 3, &rpcb_procedures3[RPCB_GETADDR] },
+	{ 2, &rpcb_procedures2[RPCB_GETPORT] }
+};
+
+static inline void rpcb_wake_up_rpcbind_waiters(struct rpc_xprt *xprt)
+{
+	smp_mb__before_clear_bit();
+	clear_bit(XPRT_BINDING, &xprt->state);
+	smp_mb__after_clear_bit();
+	rpc_wake_up(&xprt->bindwait);
+}
+
+static struct rpc_clnt * rpcb_create(char *hostname, struct sockaddr *srvaddr,
+	int proto, int version)
+{
+	struct rpc_create_args args = {
+		.protocol	= proto,
+		.address	= srvaddr,
+		.addrsize	= sizeof(struct sockaddr_in),
+		.servername	= hostname,
+		.program	= &rpcb_program,
+		.version	= version,
+		.authflavor	= RPC_AUTH_NULL,
+		.behavior	= RPC_CLNT_SOFTRTRY | RPC_CLNT_CHATTY |
+					RPC_CLNT_ONESHOT,
+	};
+
+	((struct sockaddr_in *)srvaddr)->sin_port = htons(RPC_PMAP_PORT);
+	return rpc_create(&args);
+}
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+static struct rpc_clnt * rpcb_create6(char *hostname, struct sockaddr *srvaddr,
+	int proto, int version)
+{
+	struct rpc_create_args args = {
+		.protocol	= proto,
+		.address	= srvaddr,
+		.addrsize	= sizeof(struct sockaddr_in6),
+		.servername	= hostname,
+		.program	= &rpcb_program,
+		.version	= version,
+		.authflavor	= RPC_AUTH_NULL,
+		.behavior	= RPC_CLNT_SOFTRTRY | RPC_CLNT_CHATTY |
+					RPC_CLNT_ONESHOT,
+	};
+
+	((struct sockaddr_in6 *)srvaddr)->sin6_port = htons(RPC_PMAP_PORT);
+	return rpc_create(&args);
+}
+#endif
+
+static void rpcb_getport(struct rpc_task *task, struct rpc_clnt *clnt,
+		struct rpc_clnt * (*rpcb_create_fct)(char *, struct sockaddr *, int, int))
+{
+	int protocol = rpc_aux_protocol(clnt);
+	struct rpc_xprt *xprt = task->tk_xprt;
+	struct sockaddr_storage addr;
+	struct rpc_message msg = {
+		.rpc_cred	= NULL
+	};
+	static struct rpcbind_args *map;
+	struct rpc_clnt	*rpcb_clnt = NULL;
+	struct rpc_task	*child;
+
+	dprintk("RPC: %5u rpcb_getport(%s, %u, %u, %d)\n",
+			task->tk_pid, clnt->cl_server,
+			clnt->cl_prog, clnt->cl_vers, protocol);
+
+	if (test_and_set_bit(XPRT_BINDING, &xprt->state)) {
+		rpc_sleep_on(&xprt->bindwait, task, NULL, NULL);
+		return;
+	}
+
+	/* Someone else may have bound if we slept */
+	if (xprt_is_bound(xprt)) {
+		rpc_exit(task, 0);
+		goto bailout_nofree;
+	}
+
+	if (xprt->bind_idx >= ARRAY_SIZE(rpc_info)) {
+		/* No more getport versions available */
+		rpc_exit(task, 0);
+		goto bailout_nofree;
+	}
+	msg.rpc_proc = rpc_info[xprt->bind_idx].rpc_proc;
+		
+	map = kmalloc(sizeof(struct rpcbind_args), GFP_NOFS);
+	if (!map) {
+		rpc_exit(task, -ENOMEM);
+		goto bailout_nofree;
+	}
+	map->r_prog = clnt->cl_prog;
+	map->r_vers = clnt->cl_vers;
+	map->r_prot = protocol;
+	map->r_port = 0;
+	map->r_wake = task;
+
+	rpc_peeraddr(clnt, (void *)&addr, sizeof(addr));
+	rpc_print_peeraddr(clnt, (void *)map->r_addr, strlen(map->r_addr), 0x1);
+
+	rpcb_clnt = rpcb_create_fct(clnt->cl_server, (struct sockaddr *)&addr,
+				    protocol,
+				    rpc_info[xprt->bind_idx].rpc_vers);
+
+	if (IS_ERR(rpcb_clnt)) {
+		task->tk_status = PTR_ERR(rpcb_clnt);
+		goto bailout;
+	}
+
+	/*
+	 * Note: rpc_new_child will release client after a failure.
+	 */
+	if (!(child = rpc_new_child(rpcb_clnt, task))) {
+		rpc_exit(task, -EIO);
+		goto bailout;
+	}
+
+	/* Setup the call info struct */
+	msg.rpc_argp = map;
+	msg.rpc_resp = &map->r_port;
+	rpc_call_setup(child, &msg, 0);
+	if (child->tk_status != 0) {
+		rpc_exit(task, child->tk_status);
+		goto bailout;
+	}
+
+	/* ... and run the child task */
+	child->tk_calldata = map;
+	child->tk_exit = rpcb_getport_done;
+	rpc_run_child(task, child);
+	return;
+
+bailout:
+	kfree(map);
+bailout_nofree:
+	rpcb_wake_up_rpcbind_waiters(xprt);
+}
+
+void rpcb_getport4(struct rpc_task *task, struct rpc_clnt *clnt)
+{
+	rpcb_getport(task, clnt, rpcb_create);
+}
+EXPORT_SYMBOL(rpcb_getport4);
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+void rpcb_getport6(struct rpc_task *task, struct rpc_clnt *clnt)
+{
+	rpcb_getport(task, clnt, rpcb_create6);
+}
+EXPORT_SYMBOL(rpcb_getport6);
+#endif
+
+/*
+ * Portmapper child task calls this callback via tk_exit.  This function is then
+ * responsible for waking the parent via rpc_child_exit.
+ */
+
+static void
+rpcb_getport_done(struct rpc_task *child)
+{
+	struct rpcbind_args *map = (struct rpcbind_args *) child->tk_calldata;
+	struct rpc_xprt *xprt = map->r_wake->tk_xprt;
+
+	if (child->tk_status < 0) {
+		/* Make the calling task exit with an error */
+		child->tk_action = NULL;
+	} else if (map->r_port == 0) {
+		/* Program not registered */
+		child->tk_status = -EACCES;
+		child->tk_action = NULL;
+	} else {
+		xprt->ops->set_port(xprt, map->r_port);
+		xprt->need_bind = 0;
+	}
+
+	dprintk("RPC: %5u rpcb_getport_done(status %d, port %u)\n",
+			child->tk_pid, child->tk_status, map->r_port);
+
+	xprt->ops->set_port(xprt, map->r_port);
+	rpcb_wake_up_rpcbind_waiters(xprt);
+	rpc_child_exit(map->r_wake, child);
+	kfree(map);
+}
+
+/*
+ * XDR encode/decode functions for RPCBIND
+ */
+static int
+xdr_encode_mapping(struct rpc_rqst *req, u32 *p, struct rpcbind_args *rpcb)
+{
+	dprintk("RPC:       xdr_encode_mapping(%u, %u, %d, %u)\n",
+		rpcb->r_prog, rpcb->r_vers, rpcb->r_prot, rpcb->r_port);
+	*p++ = htonl(rpcb->r_prog);
+	*p++ = htonl(rpcb->r_vers);
+	*p++ = htonl(rpcb->r_prot);
+	*p++ = htonl(rpcb->r_port);
+
+	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
+	return 0;
+}
+
+static void
+xdr_addr_len_value(u32 **p, char *val)
+{
+	int len, offset;
+	len = strlen(val);
+	**p = htonl(len);
+	*p += 1;
+	strcpy((char *)*p, val);
+	offset = len / 4;
+	if (len % 4)
+		offset++;
+	*p += offset;
+}
+
+static int
+xdr_encode_rpcb(struct rpc_rqst *req, u32 *p, struct rpcbind_args *rpcb)
+{
+	char netid[] = "tcp";
+	char owner[] = "rpcb";
+
+	dprintk("RPC:       xdr_encode_rpcb(%u, %u, %s)\n",
+		rpcb->r_prog, rpcb->r_vers, rpcb->r_addr);
+	*p++ = htonl(rpcb->r_prog);
+	*p++ = htonl(rpcb->r_vers);
+	xdr_addr_len_value(&p, netid);
+	xdr_addr_len_value(&p, rpcb->r_addr);
+	xdr_addr_len_value(&p, owner);
+
+	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
+	return 0;
+}
+
+static int
+xdr_decode_port(struct rpc_rqst *req, u32 *p, unsigned short *portp)
+{
+	char *addr;
+	int addr_len, c, i, f, first, val;
+
+	*portp = 0;
+	addr_len = (unsigned int) ntohl(*p++);
+	addr = (char *)p;
+	val = 0;
+	first = 1;
+	f = 1;
+	for (i = addr_len - 1; i > 0; i--) {
+		c = addr[i];
+		if (c >= '0' && c <= '9') {
+			val += (c - '0') * f;
+			f *= 10;
+		} else if (c == '.') {
+			if (first) {
+				*portp = val;
+				val = first = 0;
+				f = 1;
+			} else {
+			         *portp |= (val << 8);
+				 break;
+			}
+		}
+	}
+	return 0;
+}
+
+static struct rpc_procinfo	rpcb_procedures2[] = {
+[RPCB_GETADDR] = {
+	  .p_proc		= RPCB_GETPORT,
+	  .p_encode		= (kxdrproc_t) xdr_encode_mapping,
+	  .p_decode		= (kxdrproc_t) xdr_decode_port,
+	  .p_bufsiz		= 4,
+	  .p_count		= 1,
+	},
+};
+
+static struct rpc_procinfo	rpcb_procedures3[] = {
+[RPCB_GETADDR] = {
+	  .p_proc		= RPCB_GETADDR,
+	  .p_encode		= (kxdrproc_t) xdr_encode_rpcb,
+	  .p_decode		= (kxdrproc_t) xdr_decode_port,
+	  .p_bufsiz		= 4,
+	  .p_count		= 1,
+	},
+};
+
+static struct rpc_procinfo	rpcb_procedures4[] = {
+[RPCB_GETVERSADDR] = {
+	  .p_proc		= RPCB_GETVERSADDR,
+	  .p_encode		= (kxdrproc_t) xdr_encode_rpcb,
+	  .p_decode		= (kxdrproc_t) xdr_decode_port,
+	  .p_bufsiz		= 4,
+	  .p_count		= 1,
+	},
+};
+
+static struct rpc_version	rpcb_version2 = {
+	.number		= 2,
+	.nrprocs	= 4,
+	.procs		= rpcb_procedures2
+};
+
+static struct rpc_version	rpcb_version3 = {
+	.number		= 3,
+	.nrprocs	= 4,
+	.procs		= rpcb_procedures3
+};
+
+static struct rpc_version	rpcb_version4 = {
+	.number		= 4,
+	.nrprocs	= 10,
+	.procs		= rpcb_procedures4
+};
+
+static struct rpc_version *	rpcb_version[] = {
+	NULL,
+	NULL,
+	&rpcb_version2,
+	&rpcb_version3,
+	&rpcb_version4
+};
+
+static struct rpc_stat		rpcb_stats;
+
+struct rpc_program	rpcb_program = {
+	.name		= "rpcbind",
+	.number		= RPC_PMAP_PROGRAM,
+	.nrvers		= ARRAY_SIZE(rpcb_version),
+	.version	= rpcb_version,
+	.stats		= &rpcb_stats,
+};
diff -Nru linux-2.6.11/net/sunrpc/rpc_pipe.c linux-2.6.11-09/net/sunrpc/rpc_pipe.c
--- linux-2.6.11/net/sunrpc/rpc_pipe.c	2005-03-14 14:51:31.000000000 +0100
+++ linux-2.6.11-09/net/sunrpc/rpc_pipe.c	2005-04-04 13:37:13.000000000 +0200
@@ -297,7 +297,7 @@
 	seq_printf(m, "service: %s (%d) version %d\n", clnt->cl_protname,
 			clnt->cl_prog, clnt->cl_vers);
 
- 	rpc_print_peeraddr(clnt, buf, sizeof(buf), 0x5);
+ 	rpc_print_peeraddr(clnt, buf, sizeof(buf), ADDR_FMT|PROTO_FMT);
  	seq_printf(m, "%s\n", buf);
  
 	return 0;
diff -Nru linux-2.6.11/net/sunrpc/sched.c linux-2.6.11-09/net/sunrpc/sched.c
--- linux-2.6.11/net/sunrpc/sched.c	2005-05-25 08:11:10.000000000 +0200
+++ linux-2.6.11-09/net/sunrpc/sched.c	2005-05-25 08:12:23.000000000 +0200
@@ -747,6 +747,7 @@
 
 	task->tk_priority = RPC_PRIORITY_NORMAL;
 	task->tk_cookie = (unsigned long)current;
+	task->tk_xprt->bind_idx = 0;
 	/* Initialize workqueue for async tasks */
 	task->tk_workqueue = rpciod_workqueue;
 	if (!RPC_IS_ASYNC(task))
diff -Nru linux-2.6.11/net/sunrpc/sched.c~ linux-2.6.11-09/net/sunrpc/sched.c~
--- linux-2.6.11/net/sunrpc/sched.c~	2005-05-25 08:00:58.000000000 +0200
+++ linux-2.6.11-09/net/sunrpc/sched.c~	1970-01-01 01:00:00.000000000 +0100
@@ -1,1121 +0,0 @@
-/*
- * linux/net/sunrpc/sched.c
- *
- * Scheduling for synchronous and asynchronous RPC requests.
- *
- * Copyright (C) 1996 Olaf Kirch, <okir@monad.swb.de>
- * 
- * TCP NFS related read + write fixes
- * (C) 1999 Dave Airlie, University of Limerick, Ireland <airlied@linux.ie>
- */
-
-#include <linux/module.h>
-
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/mempool.h>
-#include <linux/spinlock.h>
-
-#include <linux/sunrpc/clnt.h>
-#include <linux/sunrpc/xprt.h>
-
-#ifdef RPC_DEBUG
-#define RPCDBG_FACILITY		RPCDBG_SCHED
-#define RPC_TASK_MAGIC_ID	0xf00baa
-static int			rpc_task_id;
-#endif
-
-/*
- * RPC slabs and memory pools
- */
-#define RPC_BUFFER_MAXSIZE	(2048)
-#define RPC_BUFFER_POOLSIZE	(8)
-#define RPC_TASK_POOLSIZE	(8)
-static kmem_cache_t	*rpc_task_slabp;
-static kmem_cache_t	*rpc_buffer_slabp;
-static mempool_t	*rpc_task_mempool;
-static mempool_t	*rpc_buffer_mempool;
-
-static void			__rpc_default_timer(struct rpc_task *task);
-static void			rpciod_killall(void);
-static void			rpc_async_schedule(void *);
-
-/*
- * RPC tasks that create another task (e.g. for contacting the portmapper)
- * will wait on this queue for their child's completion
- */
-static RPC_WAITQ(childq, "childq");
-
-/*
- * RPC tasks sit here while waiting for conditions to improve.
- */
-static RPC_WAITQ(delay_queue, "delayq");
-
-/*
- * All RPC tasks are linked into this list
- */
-static LIST_HEAD(all_tasks);
-
-/*
- * rpciod-related stuff
- */
-static DECLARE_MUTEX(rpciod_sema);
-static unsigned int		rpciod_users;
-static struct workqueue_struct *rpciod_workqueue;
-
-/*
- * Spinlock for other critical sections of code.
- */
-static DEFINE_SPINLOCK(rpc_sched_lock);
-
-/*
- * Disable the timer for a given RPC task. Should be called with
- * queue->lock and bh_disabled in order to avoid races within
- * rpc_run_timer().
- */
-static inline void
-__rpc_disable_timer(struct rpc_task *task)
-{
-	dprintk("RPC: %5u disabling timer\n", task->tk_pid);
-	task->tk_timeout_fn = NULL;
-	task->tk_timeout = 0;
-}
-
-/*
- * Run a timeout function.
- * We use the callback in order to allow __rpc_wake_up_task()
- * and friends to disable the timer synchronously on SMP systems
- * without calling del_timer_sync(). The latter could cause a
- * deadlock if called while we're holding spinlocks...
- */
-static void rpc_run_timer(struct rpc_task *task)
-{
-	void (*callback)(struct rpc_task *);
-
-	callback = task->tk_timeout_fn;
-	task->tk_timeout_fn = NULL;
-	if (callback && RPC_IS_QUEUED(task)) {
-		dprintk("RPC: %5u running timer\n", task->tk_pid);
-		callback(task);
-	}
-	smp_mb__before_clear_bit();
-	clear_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate);
-	smp_mb__after_clear_bit();
-}
-
-/*
- * Set up a timer for the current task.
- */
-static inline void
-__rpc_add_timer(struct rpc_task *task, rpc_action timer)
-{
-	if (!task->tk_timeout)
-		return;
-
-	dprintk("RPC: %5u setting alarm for %lu ms\n",
-			task->tk_pid, task->tk_timeout * 1000 / HZ);
-
-	if (timer)
-		task->tk_timeout_fn = timer;
-	else
-		task->tk_timeout_fn = __rpc_default_timer;
-	set_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate);
-	mod_timer(&task->tk_timer, jiffies + task->tk_timeout);
-}
-
-/*
- * Delete any timer for the current task. Because we use del_timer_sync(),
- * this function should never be called while holding queue->lock.
- */
-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: %5u deleting timer\n", task->tk_pid);
-	}
-}
-
-/*
- * Add new request to a priority queue.
- */
-static void __rpc_add_wait_queue_priority(struct rpc_wait_queue *queue, struct rpc_task *task)
-{
-	struct list_head *q;
-	struct rpc_task *t;
-
-	INIT_LIST_HEAD(&task->u.tk_wait.links);
-	q = &queue->tasks[task->tk_priority];
-	if (unlikely(task->tk_priority > queue->maxpriority))
-		q = &queue->tasks[queue->maxpriority];
-	list_for_each_entry(t, q, u.tk_wait.list) {
-		if (t->tk_cookie == task->tk_cookie) {
-			list_add_tail(&task->u.tk_wait.list, &t->u.tk_wait.links);
-			return;
-		}
-	}
-	list_add_tail(&task->u.tk_wait.list, q);
-}
-
-/*
- * Add new request to wait queue.
- *
- * Swapper tasks always get inserted at the head of the queue.
- * This should avoid many nasty memory deadlocks and hopefully
- * improve overall performance.
- * Everyone else gets appended to the queue to ensure proper FIFO behavior.
- */
-static void __rpc_add_wait_queue(struct rpc_wait_queue *queue, struct rpc_task *task)
-{
-	BUG_ON (RPC_IS_QUEUED(task));
-
-	if (RPC_IS_PRIORITY(queue))
-		__rpc_add_wait_queue_priority(queue, task);
-	else if (RPC_IS_SWAPPER(task))
-		list_add(&task->u.tk_wait.list, &queue->tasks[0]);
-	else
-		list_add_tail(&task->u.tk_wait.list, &queue->tasks[0]);
-	task->u.tk_wait.rpc_waitq = queue;
-	rpc_set_queued(task);
-
-	dprintk("RPC: %5u added to queue %p \"%s\"\n",
-				task->tk_pid, queue, rpc_qname(queue));
-}
-
-/*
- * Remove request from a priority queue.
- */
-static void __rpc_remove_wait_queue_priority(struct rpc_task *task)
-{
-	struct rpc_task *t;
-
-	if (!list_empty(&task->u.tk_wait.links)) {
-		t = list_entry(task->u.tk_wait.links.next, struct rpc_task, u.tk_wait.list);
-		list_move(&t->u.tk_wait.list, &task->u.tk_wait.list);
-		list_splice_init(&task->u.tk_wait.links, &t->u.tk_wait.links);
-	}
-	list_del(&task->u.tk_wait.list);
-}
-
-/*
- * Remove request from queue.
- * Note: must be called with spin lock held.
- */
-static void __rpc_remove_wait_queue(struct rpc_task *task)
-{
-	struct rpc_wait_queue *queue;
-	queue = task->u.tk_wait.rpc_waitq;
-
-	if (RPC_IS_PRIORITY(queue))
-		__rpc_remove_wait_queue_priority(task);
-	else
-		list_del(&task->u.tk_wait.list);
-	dprintk("RPC: %5u removed from queue %p \"%s\"\n",
-				task->tk_pid, queue, rpc_qname(queue));
-}
-
-static inline void rpc_set_waitqueue_priority(struct rpc_wait_queue *queue, int priority)
-{
-	queue->priority = priority;
-	queue->count = 1 << (priority * 2);
-}
-
-static inline void rpc_set_waitqueue_cookie(struct rpc_wait_queue *queue, unsigned long cookie)
-{
-	queue->cookie = cookie;
-	queue->nr = RPC_BATCH_COUNT;
-}
-
-static inline void rpc_reset_waitqueue_priority(struct rpc_wait_queue *queue)
-{
-	rpc_set_waitqueue_priority(queue, queue->maxpriority);
-	rpc_set_waitqueue_cookie(queue, 0);
-}
-
-static void __rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const char *qname, int maxprio)
-{
-	int i;
-
-	spin_lock_init(&queue->lock);
-	for (i = 0; i < ARRAY_SIZE(queue->tasks); i++)
-		INIT_LIST_HEAD(&queue->tasks[i]);
-	queue->maxpriority = maxprio;
-	rpc_reset_waitqueue_priority(queue);
-#ifdef RPC_DEBUG
-	queue->name = qname;
-#endif
-}
-
-void rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const char *qname)
-{
-	__rpc_init_priority_wait_queue(queue, qname, RPC_PRIORITY_HIGH);
-}
-
-void rpc_init_wait_queue(struct rpc_wait_queue *queue, const char *qname)
-{
-	__rpc_init_priority_wait_queue(queue, qname, 0);
-}
-EXPORT_SYMBOL(rpc_init_wait_queue);
-
-/*
- * Make an RPC task runnable.
- *
- * Note: If the task is ASYNC, this must be called with 
- * the spinlock held to protect the wait queue operation.
- */
-static void rpc_make_runnable(struct rpc_task *task)
-{
-	int do_ret;
-
-	BUG_ON(task->tk_timeout_fn);
-	do_ret = rpc_test_and_set_running(task);
-	rpc_clear_queued(task);
-	if (do_ret)
-		return;
-	if (RPC_IS_ASYNC(task)) {
-		int status;
-
-		INIT_WORK(&task->u.tk_work, rpc_async_schedule, (void *)task);
-		status = queue_work(task->tk_workqueue, &task->u.tk_work);
-		if (status < 0) {
-			printk(KERN_WARNING "RPC: failed to add task to queue: error: %d!\n", status);
-			task->tk_status = status;
-			return;
-		}
-	} else
-		wake_up(&task->u.tk_wait.waitq);
-}
-
-/*
- * Place a newly initialized task on the workqueue.
- */
-static inline void
-rpc_schedule_run(struct rpc_task *task)
-{
-	/* Don't run a child twice! */
-	if (RPC_IS_ACTIVATED(task))
-		return;
-	task->tk_active = 1;
-	rpc_make_runnable(task);
-}
-
-/*
- * Prepare for sleeping on a wait queue.
- * By always appending tasks to the list we ensure FIFO behavior.
- * NB: An RPC task will only receive interrupt-driven events as long
- * as it's on a wait queue.
- */
-static void __rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
-			rpc_action action, rpc_action timer)
-{
-	dprintk("RPC: %5u sleep_on(queue \"%s\" time %lu)\n", task->tk_pid,
-				rpc_qname(q), jiffies);
-
-	if (!RPC_IS_ASYNC(task) && !RPC_IS_ACTIVATED(task)) {
-		printk(KERN_ERR "RPC: Inactive synchronous task put to sleep!\n");
-		return;
-	}
-
-	/* Mark the task as being activated if so needed */
-	if (!RPC_IS_ACTIVATED(task))
-		task->tk_active = 1;
-
-	__rpc_add_wait_queue(q, task);
-
-	BUG_ON(task->tk_callback != NULL);
-	task->tk_callback = action;
-	__rpc_add_timer(task, timer);
-}
-
-void rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
-				rpc_action action, rpc_action timer)
-{
-	/*
-	 * Protect the queue operations.
-	 */
-	spin_lock_bh(&q->lock);
-	__rpc_sleep_on(q, task, action, timer);
-	spin_unlock_bh(&q->lock);
-}
-
-/**
- * __rpc_do_wake_up_task - wake up a single rpc_task
- * @task: task to be woken up
- *
- * Caller must hold queue->lock, and have cleared the task queued flag.
- */
-static void __rpc_do_wake_up_task(struct rpc_task *task)
-{
-	dprintk("RPC: %5u __rpc_wake_up_task (now %lu)\n", task->tk_pid, jiffies);
-
-#ifdef RPC_DEBUG
-	BUG_ON(task->tk_magic != RPC_TASK_MAGIC_ID);
-#endif
-	/* Has the task been executed yet? If not, we cannot wake it up! */
-	if (!RPC_IS_ACTIVATED(task)) {
-		printk(KERN_ERR "RPC: Inactive task (%p) being woken up!\n", task);
-		return;
-	}
-
-	__rpc_disable_timer(task);
-	__rpc_remove_wait_queue(task);
-
-	rpc_make_runnable(task);
-
-	dprintk("RPC:       __rpc_wake_up_task done\n");
-}
-
-/*
- * Wake up the specified task
- */
-static void __rpc_wake_up_task(struct rpc_task *task)
-{
-	if (rpc_start_wakeup(task)) {
-		if (RPC_IS_QUEUED(task))
-			__rpc_do_wake_up_task(task);
-		rpc_finish_wakeup(task);
-	}
-}
-
-/*
- * Default timeout handler if none specified by user
- */
-static void
-__rpc_default_timer(struct rpc_task *task)
-{
-	dprintk("RPC: %5u timeout (default timer)\n", task->tk_pid);
-	task->tk_status = -ETIMEDOUT;
-	rpc_wake_up_task(task);
-}
-
-/*
- * Wake up the specified task
- */
-void rpc_wake_up_task(struct rpc_task *task)
-{
-	if (rpc_start_wakeup(task)) {
-		if (RPC_IS_QUEUED(task)) {
-			struct rpc_wait_queue *queue = task->u.tk_wait.rpc_waitq;
-
-			spin_lock_bh(&queue->lock);
-			__rpc_do_wake_up_task(task);
-			spin_unlock_bh(&queue->lock);
-		}
-		rpc_finish_wakeup(task);
-	}
-}
-
-/*
- * Wake up the next task on a priority queue.
- */
-static struct rpc_task * __rpc_wake_up_next_priority(struct rpc_wait_queue *queue)
-{
-	struct list_head *q;
-	struct rpc_task *task;
-
-	/*
-	 * Service a batch of tasks from a single cookie.
-	 */
-	q = &queue->tasks[queue->priority];
-	if (!list_empty(q)) {
-		task = list_entry(q->next, struct rpc_task, u.tk_wait.list);
-		if (queue->cookie == task->tk_cookie) {
-			if (--queue->nr)
-				goto out;
-			list_move_tail(&task->u.tk_wait.list, q);
-		}
-		/*
-		 * Check if we need to switch queues.
-		 */
-		if (--queue->count)
-			goto new_cookie;
-	}
-
-	/*
-	 * Service the next queue.
-	 */
-	do {
-		if (q == &queue->tasks[0])
-			q = &queue->tasks[queue->maxpriority];
-		else
-			q = q - 1;
-		if (!list_empty(q)) {
-			task = list_entry(q->next, struct rpc_task, u.tk_wait.list);
-			goto new_queue;
-		}
-	} while (q != &queue->tasks[queue->priority]);
-
-	rpc_reset_waitqueue_priority(queue);
-	return NULL;
-
-new_queue:
-	rpc_set_waitqueue_priority(queue, (unsigned int)(q - &queue->tasks[0]));
-new_cookie:
-	rpc_set_waitqueue_cookie(queue, task->tk_cookie);
-out:
-	__rpc_wake_up_task(task);
-	return task;
-}
-
-/*
- * Wake up the next task on the wait queue.
- */
-struct rpc_task * rpc_wake_up_next(struct rpc_wait_queue *queue)
-{
-	struct rpc_task	*task = NULL;
-
-	dprintk("RPC:       wake_up_next(%p \"%s\")\n", queue, rpc_qname(queue));
-	spin_lock_bh(&queue->lock);
-	if (RPC_IS_PRIORITY(queue))
-		task = __rpc_wake_up_next_priority(queue);
-	else {
-		task_for_first(task, &queue->tasks[0])
-			__rpc_wake_up_task(task);
-	}
-	spin_unlock_bh(&queue->lock);
-
-	return task;
-}
-
-/**
- * rpc_wake_up - wake up all rpc_tasks
- * @queue: rpc_wait_queue on which the tasks are sleeping
- *
- * Grabs queue->lock
- */
-void rpc_wake_up(struct rpc_wait_queue *queue)
-{
-	struct rpc_task *task;
-
-	struct list_head *head;
-	spin_lock_bh(&queue->lock);
-	head = &queue->tasks[queue->maxpriority];
-	for (;;) {
-		while (!list_empty(head)) {
-			task = list_entry(head->next, struct rpc_task, u.tk_wait.list);
-			__rpc_wake_up_task(task);
-		}
-		if (head == &queue->tasks[0])
-			break;
-		head--;
-	}
-	spin_unlock_bh(&queue->lock);
-}
-
-/**
- * rpc_wake_up_status - wake up all rpc_tasks and set their status value.
- * @queue: rpc_wait_queue on which the tasks are sleeping
- * @status: status value to set
- *
- * Grabs queue->lock
- */
-void rpc_wake_up_status(struct rpc_wait_queue *queue, int status)
-{
-	struct list_head *head;
-	struct rpc_task *task;
-
-	spin_lock_bh(&queue->lock);
-	head = &queue->tasks[queue->maxpriority];
-	for (;;) {
-		while (!list_empty(head)) {
-			task = list_entry(head->next, struct rpc_task, u.tk_wait.list);
-			task->tk_status = status;
-			__rpc_wake_up_task(task);
-		}
-		if (head == &queue->tasks[0])
-			break;
-		head--;
-	}
-	spin_unlock_bh(&queue->lock);
-}
-
-/*
- * Run a task at a later time
- */
-static void	__rpc_atrun(struct rpc_task *);
-void
-rpc_delay(struct rpc_task *task, unsigned long delay)
-{
-	task->tk_timeout = delay;
-	rpc_sleep_on(&delay_queue, task, NULL, __rpc_atrun);
-}
-
-static void
-__rpc_atrun(struct rpc_task *task)
-{
-	task->tk_status = 0;
-	rpc_wake_up_task(task);
-}
-
-/*
- * This is the RPC `scheduler' (or rather, the finite state machine).
- */
-static int __rpc_execute(struct rpc_task *task)
-{
-	int		status = 0;
-
-	dprintk("RPC: %5u rpc_execute flgs %x\n",
-				task->tk_pid, task->tk_flags);
-
-	BUG_ON(RPC_IS_QUEUED(task));
-
- restarted:
-	while (1) {
-		/*
-		 * Garbage collection of pending timers...
-		 */
-		rpc_delete_timer(task);
-
-		/*
-		 * Execute any pending callback.
-		 */
-		if (RPC_DO_CALLBACK(task)) {
-			/* Define a callback save pointer */
-			void (*save_callback)(struct rpc_task *);
-	
-			/* 
-			 * If a callback exists, save it, reset it,
-			 * call it.
-			 * The save is needed to stop from resetting
-			 * another callback set within the callback handler
-			 * - Dave
-			 */
-			save_callback=task->tk_callback;
-			task->tk_callback=NULL;
-			save_callback(task);
-		}
-
-		/*
-		 * Perform the next FSM step.
-		 * tk_action may be NULL when the task has been killed
-		 * by someone else.
-		 */
-		if (!RPC_IS_QUEUED(task)) {
-			if (!task->tk_action)
-				break;
-			task->tk_action(task);
-		}
-
-		/*
-		 * Lockless check for whether task is sleeping or not.
-		 */
-		if (!RPC_IS_QUEUED(task))
-			continue;
-		rpc_clear_running(task);
-		if (RPC_IS_ASYNC(task)) {
-			/* Careful! we may have raced... */
-			if (RPC_IS_QUEUED(task))
-				return 0;
-			if (rpc_test_and_set_running(task))
-				return 0;
-			continue;
-		}
-
-		/* sync task: sleep here */
-		dprintk("RPC: %5u sync task going to sleep\n", task->tk_pid);
-		if (RPC_TASK_UNINTERRUPTIBLE(task)) {
-			__wait_event(task->u.tk_wait.waitq, !RPC_IS_QUEUED(task));
-		} else {
-			__wait_event_interruptible(task->u.tk_wait.waitq, !RPC_IS_QUEUED(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 (status == -ERESTARTSYS) {
-				dprintk("RPC: %5u got signal\n", task->tk_pid);
-				task->tk_flags |= RPC_TASK_KILLED;
-				rpc_exit(task, -ERESTARTSYS);
-				rpc_wake_up_task(task);
-			}
-		}
-		rpc_set_running(task);
-		dprintk("RPC: %5u sync task resuming\n", task->tk_pid);
-	}
-
-	if (task->tk_exit) {
-		task->tk_exit(task);
-
-		/* If tk_action is non-null, the user wants us to restart */
-		if (task->tk_action) {
-			if (!RPC_ASSASSINATED(task)) {
-				xprt_release(task);
-				goto restarted;
-			}
-			printk(KERN_ERR "RPC: dead task tries to walk away.\n");
-		}
-	}
-
-	dprintk("RPC: %5u exit() = %d\n", task->tk_pid, task->tk_status);
-	status = task->tk_status;
-
-	/* Release all resources associated with the task */
-	rpc_release_task(task);
-	return status;
-}
-
-/*
- * User-visible entry point to the scheduler.
- *
- * This may be called recursively if e.g. an async NFS task updates
- * the attributes and finds that dirty pages must be flushed.
- * NOTE: Upon exit of this function the task is guaranteed to be
- *	 released. In particular note that tk_release() will have
- *	 been called, so your task memory may have been freed.
- */
-int
-rpc_execute(struct rpc_task *task)
-{
-	BUG_ON(task->tk_active);
-
-	task->tk_active = 1;
-	rpc_set_running(task);
-	return __rpc_execute(task);
-}
-
-static void rpc_async_schedule(void *arg)
-{
-	__rpc_execute((struct rpc_task *)arg);
-}
-
-/*
- * Allocate memory for RPC purposes.
- *
- * We try to ensure that some NFS reads and writes can always proceed
- * by using a mempool when allocating 'small' buffers.
- * In order to avoid memory starvation triggering more writebacks of
- * NFS requests, we use GFP_NOFS rather than GFP_KERNEL.
- */
-void * rpc_malloc(struct rpc_task *task, size_t size)
-{
-	struct rpc_rqst *req = &task->tk_rqst;
-	int	gfp;
-
-	if (task->tk_flags & RPC_TASK_SWAPPER)
-		gfp = GFP_ATOMIC;
-	else
-		gfp = GFP_NOFS;
-
-	if (size > RPC_BUFFER_MAXSIZE) {
-		req->rq_buffer = kmalloc(size, gfp);
-		if (req->rq_buffer)
-			req->rq_bufsize = size;
-	} else {
-		req->rq_buffer = mempool_alloc(rpc_buffer_mempool, gfp);
-		if (req->rq_buffer)
-			req->rq_bufsize = RPC_BUFFER_MAXSIZE;
-	}
-	return req->rq_buffer;
-}
-EXPORT_SYMBOL(rpc_malloc);
-
-void rpc_free(struct rpc_task *task)
-{
-	struct rpc_rqst *req = &task->tk_rqst;
-
-	if (req->rq_buffer) {
-		if (req->rq_bufsize == RPC_BUFFER_MAXSIZE)
-			mempool_free(req->rq_buffer, rpc_buffer_mempool);
-		else
-			kfree(req->rq_buffer);
-		req->rq_buffer = NULL;
-		req->rq_bufsize = 0;
-	}
-}
-EXPORT_SYMBOL(rpc_free);
-
-/*
- * Creation and deletion of RPC task structures
- */
-void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, rpc_action callback, int flags)
-{
-	memset(task, 0, sizeof(*task));
-	init_timer(&task->tk_timer);
-	task->tk_timer.data     = (unsigned long) task;
-	task->tk_timer.function = (void (*)(unsigned long)) rpc_run_timer;
-	task->tk_client = clnt;
-	task->tk_flags  = flags;
-	task->tk_exit   = callback;
-
-	/* Initialize retry counters */
-	task->tk_garb_retry = 2;
-	task->tk_cred_retry = 2;
-
-	task->tk_priority = RPC_PRIORITY_NORMAL;
-	task->tk_cookie = (unsigned long)current;
-	task->tk_xprt->bind_idx = 0;
-	/* Initialize workqueue for async tasks */
-	task->tk_workqueue = rpciod_workqueue;
-	if (!RPC_IS_ASYNC(task))
-		init_waitqueue_head(&task->u.tk_wait.waitq);
-
-	if (clnt) {
-		atomic_inc(&clnt->cl_users);
-		if (clnt->cl_softrtry)
-			task->tk_flags |= RPC_TASK_SOFT;
-		if (!clnt->cl_intr)
-			task->tk_flags |= RPC_TASK_NOINTR;
-		task->tk_xprt = rpc_client_get_xprt(clnt);
-	}
-
-#ifdef RPC_DEBUG
-	task->tk_magic = RPC_TASK_MAGIC_ID;
-	task->tk_pid = rpc_task_id++;
-#endif
-	/* Add to global list of all tasks */
-	spin_lock(&rpc_sched_lock);
-	list_add_tail(&task->tk_task, &all_tasks);
-	spin_unlock(&rpc_sched_lock);
-
-	dprintk("RPC: %5u new task procpid %d\n", task->tk_pid,
-				current->pid);
-}
-
-static struct rpc_task *
-rpc_alloc_task(void)
-{
-	return (struct rpc_task *)mempool_alloc(rpc_task_mempool, GFP_NOFS);
-}
-
-static void
-rpc_default_free_task(struct rpc_task *task)
-{
-	dprintk("RPC: %5u freeing task\n", task->tk_pid);
-	mempool_free(task, rpc_task_mempool);
-}
-
-/*
- * Create a new task for the specified client.  We have to
- * clean up after an allocation failure, as the client may
- * have specified "oneshot".
- */
-struct rpc_task *
-rpc_new_task(struct rpc_clnt *clnt, rpc_action callback, int flags)
-{
-	struct rpc_task	*task;
-
-	task = rpc_alloc_task();
-	if (!task)
-		goto cleanup;
-
-	rpc_init_task(task, clnt, callback, flags);
-
-	/* Replace tk_release */
-	task->tk_release = rpc_default_free_task;
-
-	dprintk("RPC: %5u allocated task\n", task->tk_pid);
-	task->tk_flags |= RPC_TASK_DYNAMIC;
-out:
-	return task;
-
-cleanup:
-	/* Check whether to release the client */
-	if (clnt) {
-		printk("rpc_new_task: failed, users=%d, oneshot=%d\n",
-			atomic_read(&clnt->cl_users), clnt->cl_oneshot);
-		atomic_inc(&clnt->cl_users); /* pretend we were used ... */
-		rpc_release_client(clnt);
-	}
-	goto out;
-}
-
-void rpc_release_task(struct rpc_task *task)
-{
-	dprintk("RPC: %5u release task\n", task->tk_pid);
-
-#ifdef RPC_DEBUG
-	BUG_ON(task->tk_magic != RPC_TASK_MAGIC_ID);
-#endif
-
-	/* Remove from global task list */
-	spin_lock(&rpc_sched_lock);
-	list_del(&task->tk_task);
-	spin_unlock(&rpc_sched_lock);
-
-	BUG_ON (RPC_IS_QUEUED(task));
-	task->tk_active = 0;
-
-	/* Synchronously delete any running timer */
-	rpc_delete_timer(task);
-
-	/* Release resources */
-	xprt_release(task);
-	if (task->tk_msg.rpc_cred)
-		rpcauth_unbindcred(task);
-	if (task->tk_client) {
-		rpc_put_xprt(task->tk_xprt);
-		rpc_release_client(task->tk_client);
-		task->tk_client = NULL;
-	}
-
-#ifdef RPC_DEBUG
-	task->tk_magic = 0;
-#endif
-	if (task->tk_release)
-		task->tk_release(task);
-}
-
-/**
- * rpc_find_parent - find the parent of a child task.
- * @child: child task
- *
- * Checks that the parent task is still sleeping on the
- * queue 'childq'. If so returns a pointer to the parent.
- * Upon failure returns NULL.
- *
- * Caller must hold childq.lock
- */
-static int rpc_find_parent(struct rpc_task *parent)
-{
-	struct rpc_task	*task;
-	struct list_head *le;
-
-	task_for_each(task, le, &childq.tasks[0])
-		if (task == parent)
-			return 1;
-	return 0;
-}
-
-/**
- * rpc_child_exit - find and wake the parent of a child task.
- * @child: child task
- * @parent: potential sleeping parent
- *
- */
-void rpc_child_exit(struct rpc_task *parent, struct rpc_task *child)
-{
-	dprintk("RPC: %4d child exiting, trying to wake %d\n",
-			child->tk_pid, parent->tk_pid);
-
-	spin_lock_bh(&childq.lock);
-	if (rpc_find_parent(parent)) {
-		parent->tk_status = child->tk_status;
-		__rpc_wake_up_task(parent);
-	}
-	spin_unlock_bh(&childq.lock);
-}
-
-/*
- * Note: rpc_new_task releases the client after a failure.
- */
-struct rpc_task *rpc_new_child(struct rpc_clnt *clnt, struct rpc_task *parent)
-{
-	struct rpc_task	*task;
-
-	task = rpc_new_task(clnt, NULL, RPC_TASK_ASYNC | RPC_TASK_CHILD);
-	if (!task)
-		goto fail;
-	dprintk("RPC: %4d created new child: %d\n",
-			parent->tk_pid, task->tk_pid);
-	return task;
-
-fail:
-	parent->tk_status = -ENOMEM;
-	return NULL;
-}
-
-void rpc_run_child(struct rpc_task *task, struct rpc_task *child)
-{
-	dprintk("RPC: %4d going to sleep, running child task %d\n",
-			task->tk_pid, child->tk_pid);
-
-	spin_lock_bh(&childq.lock);
-	/* N.B. Is it possible for the child to have already finished? */
-	__rpc_sleep_on(&childq, task, NULL, NULL);
-	rpc_schedule_run(child);
-	spin_unlock_bh(&childq.lock);
-}
-
-/*
- * Kill all tasks for the given client.
- * XXX: kill their descendants as well?
- */
-void rpc_killall_tasks(struct rpc_clnt *clnt)
-{
-	struct rpc_task	*rovr;
-	struct list_head *le;
-
-	dprintk("RPC:       killing all tasks for client %p\n", clnt);
-
-	/*
-	 * Spin lock all_tasks to prevent changes...
-	 */
-	spin_lock(&rpc_sched_lock);
-	alltask_for_each(rovr, le, &all_tasks) {
-		if (! RPC_IS_ACTIVATED(rovr))
-			continue;
-		if (!clnt || rovr->tk_client == clnt) {
-			rovr->tk_flags |= RPC_TASK_KILLED;
-			rpc_exit(rovr, -EIO);
-			rpc_wake_up_task(rovr);
-		}
-	}
-	spin_unlock(&rpc_sched_lock);
-}
-
-static DECLARE_MUTEX_LOCKED(rpciod_running);
-
-static void rpciod_killall(void)
-{
-	unsigned long flags;
-
-	while (!list_empty(&all_tasks)) {
-		clear_thread_flag(TIF_SIGPENDING);
-		rpc_killall_tasks(NULL);
-		flush_workqueue(rpciod_workqueue);
-		if (!list_empty(&all_tasks)) {
-			dprintk("RPC:       rpciod_killall: waiting for tasks to exit\n");
-			yield();
-		}
-	}
-
-	spin_lock_irqsave(&current->sighand->siglock, flags);
-	recalc_sigpending();
-	spin_unlock_irqrestore(&current->sighand->siglock, flags);
-}
-
-/*
- * Start up the rpciod process if it's not already running.
- */
-int
-rpciod_up(void)
-{
-	struct workqueue_struct *wq;
-	int error = 0;
-
-	down(&rpciod_sema);
-	dprintk("rpciod_up: users %d\n", rpciod_users);
-	rpciod_users++;
-	if (rpciod_workqueue)
-		goto out;
-	/*
-	 * If there's no pid, we should be the first user.
-	 */
-	if (rpciod_users > 1)
-		printk(KERN_WARNING "rpciod_up: no workqueue, %d users??\n", rpciod_users);
-	/*
-	 * Create the rpciod thread and wait for it to start.
-	 */
-	error = -ENOMEM;
-	wq = create_workqueue("rpciod");
-	if (wq == NULL) {
-		printk(KERN_WARNING "rpciod_up: create workqueue failed, error=%d\n", error);
-		rpciod_users--;
-		goto out;
-	}
-	rpciod_workqueue = wq;
-	error = 0;
-out:
-	up(&rpciod_sema);
-	return error;
-}
-
-void
-rpciod_down(void)
-{
-	down(&rpciod_sema);
-	dprintk("rpciod_down sema %d\n", rpciod_users);
-	if (rpciod_users) {
-		if (--rpciod_users)
-			goto out;
-	} else
-		printk(KERN_WARNING "rpciod_down: no users??\n");
-
-	if (!rpciod_workqueue) {
-		dprintk("rpciod_down: Nothing to do!\n");
-		goto out;
-	}
-	rpciod_killall();
-
-	destroy_workqueue(rpciod_workqueue);
-	rpciod_workqueue = NULL;
- out:
-	up(&rpciod_sema);
-}
-
-#ifdef RPC_DEBUG
-void rpc_show_tasks(void)
-{
-	struct list_head *le;
-	struct rpc_task *t;
-
-	spin_lock(&rpc_sched_lock);
-	if (list_empty(&all_tasks)) {
-		spin_unlock(&rpc_sched_lock);
-		return;
-	}
-
-#if BITS_PER_LONG == 64
-	printk("-pid- proc flgs status -----client----- -prog- -timeout ---rpcwait-- -----action----- ------exit------\n");
-#else
-	printk("-pid- proc flgs status -client- -prog- -timeout ---rpcwait-- -action- --exit--\n");
-#endif
-	alltask_for_each(t, le, &all_tasks) {
-		const char *rpc_waitq = "none";
-
-		if (RPC_IS_QUEUED(t))
-			rpc_waitq = rpc_qname(t->u.tk_wait.rpc_waitq);
-
-		printk("%05u %04u %04x %06d %p %6u %08lu %12s %p %p\n",
-			t->tk_pid,
-			(t->tk_msg.rpc_proc ? t->tk_msg.rpc_proc->p_proc : -1),
-			t->tk_flags, t->tk_status,
-			t->tk_client,
-			(t->tk_client ? t->tk_client->cl_prog : 0),
-			t->tk_timeout,
-			rpc_waitq,
-			t->tk_action, t->tk_exit);
-	}
-	spin_unlock(&rpc_sched_lock);
-}
-#endif
-
-void
-rpc_destroy_mempool(void)
-{
-	if (rpc_buffer_mempool)
-		mempool_destroy(rpc_buffer_mempool);
-	if (rpc_task_mempool)
-		mempool_destroy(rpc_task_mempool);
-	if (rpc_task_slabp && kmem_cache_destroy(rpc_task_slabp))
-		printk(KERN_INFO "rpc_task: not all structures were freed\n");
-	if (rpc_buffer_slabp && kmem_cache_destroy(rpc_buffer_slabp))
-		printk(KERN_INFO "rpc_buffers: not all structures were freed\n");
-}
-
-int
-rpc_init_mempool(void)
-{
-	rpc_task_slabp = kmem_cache_create("rpc_tasks",
-					     sizeof(struct rpc_task),
-					     0, SLAB_HWCACHE_ALIGN,
-					     NULL, NULL);
-	if (!rpc_task_slabp)
-		goto err_nomem;
-	rpc_buffer_slabp = kmem_cache_create("rpc_buffers",
-					     RPC_BUFFER_MAXSIZE,
-					     0, SLAB_HWCACHE_ALIGN,
-					     NULL, NULL);
-	if (!rpc_buffer_slabp)
-		goto err_nomem;
-	rpc_task_mempool = mempool_create(RPC_TASK_POOLSIZE,
-					    mempool_alloc_slab,
-					    mempool_free_slab,
-					    rpc_task_slabp);
-	if (!rpc_task_mempool)
-		goto err_nomem;
-	rpc_buffer_mempool = mempool_create(RPC_BUFFER_POOLSIZE,
-					    mempool_alloc_slab,
-					    mempool_free_slab,
-					    rpc_buffer_slabp);
-	if (!rpc_buffer_mempool)
-		goto err_nomem;
-	return 0;
-err_nomem:
-	rpc_destroy_mempool();
-	return -ENOMEM;
-}
diff -Nru linux-2.6.11/net/sunrpc/svcauth_unix.c linux-2.6.11-09/net/sunrpc/svcauth_unix.c
--- linux-2.6.11/net/sunrpc/svcauth_unix.c	2005-03-22 17:02:01.000000000 +0100
+++ linux-2.6.11-09/net/sunrpc/svcauth_unix.c	2005-04-08 15:12:31.000000000 +0200
@@ -8,6 +8,7 @@
 #include <linux/err.h>
 #include <linux/seq_file.h>
 #include <linux/hash.h>
+#include <linux/nfs_ipv6.h>
 
 #define RPCDBG_FACILITY	RPCDBG_AUTH
 
@@ -91,7 +92,7 @@
 struct ip_map {
 	struct cache_head	h;
 	char			m_class[8]; /* e.g. "nfsd" */
-	struct in_addr		m_addr;
+	struct in6_addr		m_addr;
 	struct unix_domain	*m_client;
 	int			m_add_change;
 };
@@ -111,17 +112,20 @@
 static inline int ip_map_hash(struct ip_map *item)
 {
 	return hash_str(item->m_class, IP_HASHBITS) ^ 
-		hash_long((unsigned long)item->m_addr.s_addr, IP_HASHBITS);
+		hash_long((unsigned long)(item->m_addr.s6_addr32[0] ^
+			    item->m_addr.s6_addr32[1] ^
+			    item->m_addr.s6_addr32[2] ^
+			    item->m_addr.s6_addr32[3]), IP_HASHBITS);
 }
 static inline int ip_map_match(struct ip_map *item, struct ip_map *tmp)
 {
-	return strcmp(tmp->m_class, item->m_class) == 0
-		&& tmp->m_addr.s_addr == item->m_addr.s_addr;
+	return !strcmp(tmp->m_class, item->m_class) &&
+	       !memcmp(&tmp->m_addr, &item->m_addr, sizeof(struct in6_addr));
 }
 static inline void ip_map_init(struct ip_map *new, struct ip_map *item)
 {
 	strcpy(new->m_class, item->m_class);
-	new->m_addr.s_addr = item->m_addr.s_addr;
+	memcpy(&new->m_addr, &item->m_addr, sizeof(struct in6_addr));
 }
 static inline void ip_map_update(struct ip_map *new, struct ip_map *item)
 {
@@ -134,16 +138,16 @@
 				  struct cache_head *h,
 				  char **bpp, int *blen)
 {
-	char text_addr[20];
+	char text_addr[40];
 	struct ip_map *im = container_of(h, struct ip_map, h);
-	__u32 addr = im->m_addr.s_addr;
-	
-	snprintf(text_addr, 20, "%u.%u.%u.%u",
-		 ntohl(addr) >> 24 & 0xff,
-		 ntohl(addr) >> 16 & 0xff,
-		 ntohl(addr) >>  8 & 0xff,
-		 ntohl(addr) >>  0 & 0xff);
 
+	if (IS_ADDR_MAPPED(&im->m_addr)) {
+		snprintf(text_addr, 20, "%d.%d.%d.%d",
+			 NIPQUAD(im->m_addr.s6_addr32[3]));
+	} else {
+		snprintf(text_addr, 40, "%x:%x:%x:%x:%x:%x:%x:%x",
+			 NIP6(im->m_addr));
+	}
 	qword_add(bpp, blen, im->m_class);
 	qword_add(bpp, blen, text_addr);
 	(*bpp)[-1] = '\n';
@@ -159,7 +163,7 @@
 	 * for scratch: */
 	char *buf = mesg;
 	int len;
-	int b1,b2,b3,b4;
+	int b1,b2,b3,b4,b5,b6,b7,b8;
 	char c;
 	struct ip_map ipm, *ipmp;
 	struct auth_domain *dom;
@@ -177,9 +181,21 @@
 	len = qword_get(&mesg, buf, mlen);
 	if (len <= 0) return -EINVAL;
 
-	if (sscanf(buf, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) != 4)
+	if (sscanf(buf, "%d.%d.%d.%d%c", &b1, &b2, &b3, &b4, &c) == 4) {
+		ipm.m_addr.s6_addr32[0] = 0;
+		ipm.m_addr.s6_addr32[1] = 0;
+		ipm.m_addr.s6_addr32[2] = htonl(0xffff);
+		ipm.m_addr.s6_addr32[3] =
+				htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
+	} else if (sscanf(buf, "%x:%x:%x:%x:%x:%x:%x:%x%c",
+			  &b1, &b2, &b3, &b4, &b5, &b6, &b7, &b8, &c) == 8) {
+		ipm.m_addr.s6_addr32[0] = htonl((b1<<16)|b2);
+		ipm.m_addr.s6_addr32[1] = htonl((b3<<16)|b4);
+		ipm.m_addr.s6_addr32[2] = htonl((b5<<16)|b6);
+		ipm.m_addr.s6_addr32[3] = htonl((b7<<16)|b8);
+	} else
 		return -EINVAL;
-	
+
 	expiry = get_expiry(&mesg);
 	if (expiry ==0)
 		return -EINVAL;
@@ -195,8 +211,6 @@
 	} else
 		dom = NULL;
 
-	ipm.m_addr.s_addr =
-		htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
 	ipm.h.flags = 0;
 	if (dom) {
 		ipm.m_client = container_of(dom, struct unix_domain, h);
@@ -221,7 +235,6 @@
 		       struct cache_head *h)
 {
 	struct ip_map *im;
-	struct in_addr addr;
 	char *dom = "-no-domain-";
 
 	if (h == NULL) {
@@ -230,20 +243,17 @@
 	}
 	im = container_of(h, struct ip_map, h);
 	/* class addr domain */
-	addr = im->m_addr;
-
 	if (test_bit(CACHE_VALID, &h->flags) && 
 	    !test_bit(CACHE_NEGATIVE, &h->flags))
 		dom = im->m_client->h.name;
 
-	seq_printf(m, "%s %d.%d.%d.%d %s\n",
-		   im->m_class,
-		   htonl(addr.s_addr) >> 24 & 0xff,
-		   htonl(addr.s_addr) >> 16 & 0xff,
-		   htonl(addr.s_addr) >>  8 & 0xff,
-		   htonl(addr.s_addr) >>  0 & 0xff,
-		   dom
-		   );
+	if (IS_ADDR_MAPPED(&im->m_addr)) {
+		seq_printf(m, "%s %d.%d.%d.%d %s\n",
+			   im->m_class, NIPQUAD(im->m_addr.s6_addr32[3]), dom);
+	} else {
+		seq_printf(m, "%s %x:%x:%x:%x:%x:%x:%x:%x %s\n",
+			   im->m_class, NIP6(im->m_addr), dom);
+	}
 	return 0;
 }
 	
@@ -260,8 +270,7 @@
 
 static DefineSimpleCacheLookup(ip_map)
 
-
-int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom)
+int auth_unix_add_addr6(struct in6_addr *addr, struct auth_domain *dom)
 {
 	struct unix_domain *udom;
 	struct ip_map ip, *ipmp;
@@ -270,7 +279,7 @@
 		return -EINVAL;
 	udom = container_of(dom, struct unix_domain, h);
 	strcpy(ip.m_class, "nfsd");
-	ip.m_addr = addr;
+	memcpy((void *)&ip.m_addr, (void *)addr, sizeof(struct in6_addr));
 	ip.m_client = udom;
 	ip.m_add_change = udom->addr_changes+1;
 	ip.h.flags = 0;
@@ -285,6 +294,14 @@
 		return -ENOMEM;
 }
 
+int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom)
+{
+	struct in6_addr addr6;
+
+	map_ipaddr_4to6(&addr, &addr6);
+	return auth_unix_add_addr6(&addr6, dom);
+}
+
 int auth_unix_forget_old(struct auth_domain *dom)
 {
 	struct unix_domain *udom;
@@ -296,13 +313,13 @@
 	return 0;
 }
 
-struct auth_domain *auth_unix_lookup(struct in_addr addr)
+struct auth_domain *auth_unix_lookup6(struct in6_addr *addr)
 {
 	struct ip_map key, *ipm;
 	struct auth_domain *rv;
 
 	strcpy(key.m_class, "nfsd");
-	key.m_addr = addr;
+	memcpy((void *)&key.m_addr, (void *)addr, sizeof(struct in6_addr));
 
 	ipm = ip_map_lookup(&key, 0);
 
@@ -323,6 +340,14 @@
 	return rv;
 }
 
+struct auth_domain *auth_unix_lookup(struct in_addr addr)
+{
+	struct in6_addr addr6;
+
+	map_ipaddr_4to6(&addr, &addr6);
+	return auth_unix_lookup6(&addr6);
+}
+
 void svcauth_unix_purge(void)
 {
 	cache_purge(&ip_map_cache);
@@ -339,7 +364,14 @@
 		return SVC_OK;
 
 	strcpy(key.m_class, rqstp->rq_server->sv_program->pg_class);
-	key.m_addr = rqstp->rq_addr.sin_addr;
+	if (rqstp->rq_addr.ss_family == AF_INET) {
+		map_ipaddr_4to6(&((struct sockaddr_in *)&rqstp->rq_addr)->sin_addr,
+				&key.m_addr);
+	} else if (rqstp->rq_addr.ss_family == AF_INET6) {
+		memcpy(&key.m_addr,
+		       &((struct sockaddr_in6 *)&rqstp->rq_addr)->sin6_addr,
+		       sizeof(struct in6_addr));
+	}
 
 	ipm = ip_map_lookup(&key, 0);
 
diff -Nru linux-2.6.11/net/sunrpc/svc.c linux-2.6.11-09/net/sunrpc/svc.c
--- linux-2.6.11/net/sunrpc/svc.c	2005-03-14 14:51:31.000000000 +0100
+++ linux-2.6.11-09/net/sunrpc/svc.c	2005-04-04 15:43:37.000000000 +0200
@@ -194,6 +194,8 @@
 	struct svc_serv	*serv = rqstp->rq_server;
 
 	svc_release_buffer(rqstp);
+	if (rqstp->rq_daddr)
+		kfree(rqstp->rq_daddr);
 	if (rqstp->rq_resp)
 		kfree(rqstp->rq_resp);
 	if (rqstp->rq_argp)
diff -Nru linux-2.6.11/net/sunrpc/svcsock.c linux-2.6.11-09/net/sunrpc/svcsock.c
--- linux-2.6.11/net/sunrpc/svcsock.c	2005-03-14 14:51:31.000000000 +0100
+++ linux-2.6.11-09/net/sunrpc/svcsock.c	2005-04-19 09:43:21.000000000 +0200
@@ -64,7 +64,7 @@
 
 
 static struct svc_sock *svc_setup_socket(struct svc_serv *, struct socket *,
-					 int *errp, int pmap_reg);
+					 int *errp, int flags);
 static void		svc_udp_data_ready(struct sock *, int);
 static int		svc_udp_recvfrom(struct svc_rqst *);
 static int		svc_udp_sendto(struct svc_rqst *);
@@ -342,6 +342,28 @@
 	spin_unlock_bh(&serv->sv_lock);
 }
 
+static void
+set_ipv4_cmsg_data(struct svc_rqst *rqstp, struct cmsghdr *cmh)
+{
+	struct in_pktinfo *pki = (struct in_pktinfo *)CMSG_DATA(cmh);
+	cmh->cmsg_level = SOL_IP;
+	cmh->cmsg_type = IP_PKTINFO;
+	pki->ipi_ifindex = 0;
+	pki->ipi_spec_dst.s_addr = rqstp->rq_in_daddr->s_addr;
+	cmh->cmsg_len = CMSG_LEN(sizeof(*pki));
+}
+
+static void
+set_ipv6_cmsg_data(struct svc_rqst *rqstp, struct cmsghdr *cmh)
+{
+	struct in6_pktinfo *pki = (struct in6_pktinfo *)CMSG_DATA(cmh);
+	cmh->cmsg_level = SOL_IPV6;
+	cmh->cmsg_type = IPV6_PKTINFO;
+	pki->ipi6_ifindex = 0;
+	memcpy(&pki->ipi6_addr, rqstp->rq_in6_daddr, sizeof(struct in6_addr));
+	cmh->cmsg_len = CMSG_LEN(sizeof(*pki));
+}
+
 /*
  * Generic sendto routine
  */
@@ -351,9 +373,8 @@
 	struct svc_sock	*svsk = rqstp->rq_sock;
 	struct socket	*sock = svsk->sk_sock;
 	int		slen;
-	char 		buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
+	char 		buffer[CMSG_SPACE(sizeof(struct in6_pktinfo))];
 	struct cmsghdr *cmh = (struct cmsghdr *)buffer;
-	struct in_pktinfo *pki = (struct in_pktinfo *)CMSG_DATA(cmh);
 	int		len = 0;
 	int		result;
 	int		size;
@@ -361,6 +382,7 @@
 	size_t		base = xdr->page_base;
 	unsigned int	pglen = xdr->page_len;
 	unsigned int	flags = MSG_MORE;
+	char		addrbuf[MAX_ADDR_BUF];
 
 	slen = xdr->len;
 
@@ -368,18 +390,19 @@
 		/* set the source and destination */
 		struct msghdr	msg;
 		msg.msg_name    = &rqstp->rq_addr;
-		msg.msg_namelen = sizeof(rqstp->rq_addr);
+		msg.msg_namelen = rqstp->rq_addrlen;
 		msg.msg_iov     = NULL;
 		msg.msg_iovlen  = 0;
 		msg.msg_flags	= MSG_MORE;
 
 		msg.msg_control = cmh;
 		msg.msg_controllen = sizeof(buffer);
-		cmh->cmsg_len = CMSG_LEN(sizeof(*pki));
-		cmh->cmsg_level = SOL_IP;
-		cmh->cmsg_type = IP_PKTINFO;
-		pki->ipi_ifindex = 0;
-		pki->ipi_spec_dst.s_addr = rqstp->rq_daddr;
+		if (svsk->sk_sk->sk_family == AF_INET)
+			set_ipv4_cmsg_data(rqstp, cmh);
+		else if (svsk->sk_sk->sk_family == AF_INET6)
+			set_ipv6_cmsg_data(rqstp, cmh);
+		else
+			goto out;
 
 		if (sock_sendmsg(sock, &msg, 0) < 0)
 			goto out;
@@ -421,9 +444,10 @@
 			len += result;
 	}
 out:
-	dprintk("svc: socket %p sendto([%p %Zu... ], %d) = %d (addr %x)\n",
-			rqstp->rq_sock, xdr->head[0].iov_base, xdr->head[0].iov_len, xdr->len, len,
-		rqstp->rq_addr.sin_addr.s_addr);
+	svc_print_addr((struct sockaddr *)&rqstp->rq_addr, addrbuf, sizeof(addrbuf));
+	dprintk("svc: socket %p sendto([%p %Zu... ], %d) = %d (%s)\n",
+			rqstp->rq_sock, xdr->head[0].iov_base,
+			xdr->head[0].iov_len, xdr->len, len, addrbuf);
 
 	return len;
 }
@@ -453,7 +477,7 @@
 {
 	struct msghdr	msg;
 	struct socket	*sock;
-	int		len, alen;
+	int		len;
 
 	rqstp->rq_addrlen = sizeof(rqstp->rq_addr);
 	sock = rqstp->rq_sock->sk_sock;
@@ -471,8 +495,8 @@
 	 * possibly we should cache this in the svc_sock structure
 	 * at accept time. FIXME
 	 */
-	alen = sizeof(rqstp->rq_addr);
-	sock->ops->getname(sock, (struct sockaddr *)&rqstp->rq_addr, &alen, 1);
+	sock->ops->getname(sock, (struct sockaddr *)&rqstp->rq_addr,
+		&rqstp->rq_addrlen, 1);
 
 	dprintk("svc: socket %p recvfrom(%p, %Zu) = %d\n",
 		rqstp->rq_sock, iov[0].iov_base, iov[0].iov_len, len);
@@ -601,10 +625,37 @@
 	rqstp->rq_prot        = IPPROTO_UDP;
 
 	/* Get sender address */
-	rqstp->rq_addr.sin_family = AF_INET;
-	rqstp->rq_addr.sin_port = skb->h.uh->source;
-	rqstp->rq_addr.sin_addr.s_addr = skb->nh.iph->saddr;
-	rqstp->rq_daddr = skb->nh.iph->daddr;
+#define IP6VERSION	6
+	if (*skb->nh.raw == IPVERSION) {
+		struct sockaddr_in *sin = (struct sockaddr_in *)&rqstp->rq_addr;
+		sin->sin_family = AF_INET;
+		sin->sin_port = skb->h.uh->source;
+		sin->sin_addr.s_addr = skb->nh.iph->saddr;
+		rqstp->rq_in_daddr = (struct in_addr *)kmalloc(sizeof(struct in_addr), GFP_KERNEL);
+		if (rqstp->rq_in_daddr == NULL) {
+			skb_free_datagram(svsk->sk_sk, skb);
+			return 0;
+		}
+		rqstp->rq_in_daddr->s_addr = skb->nh.iph->daddr;
+		memcpy(&rqstp->rq_daddr, &skb->nh.iph->daddr,
+		       sizeof(struct in_addr));
+	} else if (*skb->nh.raw == IP6VERSION) {
+		struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&rqstp->rq_addr;
+		sin->sin6_family = AF_INET6;
+		sin->sin6_port = skb->h.uh->source;
+		memcpy(&sin->sin6_addr, &skb->nh.ipv6h->saddr,
+		       sizeof(struct in6_addr));
+		rqstp->rq_in6_daddr = (struct in6_addr *)kmalloc(sizeof(struct in6_addr), GFP_KERNEL);
+		if (rqstp->rq_in6_daddr == NULL) {
+			skb_free_datagram(svsk->sk_sk, skb);
+			return 0;
+		}
+		memcpy(rqstp->rq_in6_daddr, &skb->nh.ipv6h->daddr,
+		       sizeof(struct in6_addr));
+	} else {
+		skb_free_datagram(svsk->sk_sk, skb);
+		return 0;
+	}
 
 	if (skb_is_nonlinear(skb)) {
 		/* we have to copy */
@@ -759,19 +810,21 @@
 static void
 svc_tcp_accept(struct svc_sock *svsk)
 {
-	struct sockaddr_in sin;
+	struct sockaddr_storage sin;
 	struct svc_serv	*serv = svsk->sk_server;
 	struct socket	*sock = svsk->sk_sock;
 	struct socket	*newsock;
 	struct proto_ops *ops;
 	struct svc_sock	*newsvsk;
-	int		err, slen;
+	int		err, slen, port;
+	char		addrbuf[MAX_ADDR_BUF];
 
 	dprintk("svc: tcp_accept %p sock %p\n", svsk, sock);
 	if (!sock)
 		return;
 
-	err = sock_create_lite(PF_INET, SOCK_STREAM, IPPROTO_TCP, &newsock);
+	err = sock_create_lite(svsk->sk_sk->sk_family, SOCK_STREAM, IPPROTO_TCP,
+			       &newsock);
 	if (err) {
 		if (err == -ENOMEM)
 			printk(KERN_WARNING "%s: no more sockets!\n",
@@ -805,15 +858,15 @@
 	 * hosts here, but when we get encription, the IP of the host won't
 	 * tell us anything. For now just warn about unpriv connections.
 	 */
-	if (ntohs(sin.sin_port) >= 1024) {
+	port = svc_get_port((struct sockaddr *)&sin);
+	if (port >= 1024) {
 		dprintk(KERN_WARNING
-			"%s: connect from unprivileged port: %u.%u.%u.%u:%d\n",
-			serv->sv_name, 
-			NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
+			"%s: connect from unprivileged port: %d\n",
+			serv->sv_name, port);
 	}
 
-	dprintk("%s: connect from %u.%u.%u.%u:%04x\n", serv->sv_name,
-			NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
+	svc_print_addr((struct sockaddr*)&sin, addrbuf, sizeof(addrbuf));
+	dprintk("%s: connect from %s\n", serv->sv_name, addrbuf);
 
 	/* make sure that a write doesn't block forever when
 	 * low on memory
@@ -846,10 +899,7 @@
 					"number of nfsd threads\n",
 						   serv->sv_name);
 				printk(KERN_NOTICE "%s: last TCP connect from "
-					"%u.%u.%u.%u:%d\n",
-					serv->sv_name,
-					NIPQUAD(sin.sin_addr.s_addr),
-					ntohs(sin.sin_port));
+					"%s\n", serv->sv_name, addrbuf);
 			}
 			/*
 			 * Always select the oldest socket. It's not fair,
@@ -1142,6 +1192,7 @@
 	int 			pages;
 	struct xdr_buf		*arg;
 	DECLARE_WAITQUEUE(wait, current);
+	unsigned short		port;
 
 	dprintk("svc: server %p waiting for data (to = %ld)\n",
 		rqstp, timeout);
@@ -1257,7 +1308,8 @@
 		spin_unlock_bh(&serv->sv_lock);
 	}
 
-	rqstp->rq_secure  = ntohs(rqstp->rq_addr.sin_port) < 1024;
+	port = svc_get_port((struct sockaddr *)&rqstp->rq_addr);
+	rqstp->rq_secure = port < 1024;
 	rqstp->rq_chandle.defer = svc_defer;
 
 	if (serv->sv_stats)
@@ -1320,7 +1372,7 @@
  */
 static struct svc_sock *
 svc_setup_socket(struct svc_serv *serv, struct socket *sock,
-					int *errp, int pmap_register)
+					int *errp, int flags)
 {
 	struct svc_sock	*svsk;
 	struct sock	*inet;
@@ -1335,7 +1387,7 @@
 	inet = sock->sk;
 
 	/* Register socket with portmapper */
-	if (*errp >= 0 && pmap_register)
+	if (*errp >= 0 && (flags & SOCK_PMAP_REG))
 		*errp = svc_register(serv, inet->sk_protocol,
 				     ntohs(inet_sk(inet)->sport));
 
@@ -1364,7 +1416,7 @@
 		svc_tcp_init(svsk);
 
 	spin_lock_bh(&serv->sv_lock);
-	if (!pmap_register) {
+	if (!(flags & SOCK_PERM)) {
 		set_bit(SK_TEMP, &svsk->sk_flags);
 		list_add(&svsk->sk_list, &serv->sv_tempsocks);
 		serv->sv_tmpcnt++;
@@ -1386,17 +1438,18 @@
  * Create socket for RPC service.
  */
 static int
-svc_create_socket(struct svc_serv *serv, int protocol, struct sockaddr_in *sin)
+svc_create_socket(struct svc_serv *serv, int protocol, struct sockaddr *sin,
+		  int pmap_reg)
 {
 	struct svc_sock	*svsk;
 	struct socket	*sock;
 	int		error;
 	int		type;
+	char		addrbuf[MAX_ADDR_BUF];
 
-	dprintk("svc: svc_create_socket(%s, %d, %u.%u.%u.%u:%d)\n",
-				serv->sv_program->pg_name, protocol,
-				NIPQUAD(sin->sin_addr.s_addr),
-				ntohs(sin->sin_port));
+	svc_print_addr(sin, addrbuf, sizeof(addrbuf));
+	dprintk("svc: svc_create_socket(%s, %d, %s)\n",
+		serv->sv_program->pg_name, protocol, addrbuf);
 
 	if (protocol != IPPROTO_UDP && protocol != IPPROTO_TCP) {
 		printk(KERN_WARNING "svc: only UDP and TCP "
@@ -1405,14 +1458,14 @@
 	}
 	type = (protocol == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM;
 
-	if ((error = sock_create_kern(PF_INET, type, protocol, &sock)) < 0)
+	if ((error = sock_create_kern(sin->sa_family, type, protocol,
+			&sock)) < 0)
 		return error;
 
 	if (sin != NULL) {
 		if (type == SOCK_STREAM)
 			sock->sk->sk_reuse = 1; /* allow address reuse */
-		error = sock->ops->bind(sock, (struct sockaddr *) sin,
-						sizeof(*sin));
+		error = sock->ops->bind(sock, sin, svc_get_addrlen(sin));
 		if (error < 0)
 			goto bummer;
 	}
@@ -1422,7 +1475,7 @@
 			goto bummer;
 	}
 
-	if ((svsk = svc_setup_socket(serv, sock, &error, 1)) != NULL)
+	if ((svsk = svc_setup_socket(serv, sock, &error, pmap_reg | SOCK_PERM)) != NULL)
 		return 0;
 
 bummer:
@@ -1480,8 +1533,37 @@
 	sin.sin_family      = AF_INET;
 	sin.sin_addr.s_addr = INADDR_ANY;
 	sin.sin_port        = htons(port);
-	return svc_create_socket(serv, protocol, &sin);
+	return svc_create_socket(serv, protocol, (struct sockaddr *)&sin, 1);
+}
+
+/*
+ * Make a socket for nfs callback (will be then used by nfsd and lockd)
+ */
+int
+svc_makesock2(struct svc_serv *serv, int protocol, unsigned short port,
+	      int pmap_reg)
+{
+	struct sockaddr_in6     sin6;
+	struct sockaddr_in	sin;
+	int ret;
+
+	dprintk("svc: creating socket proto = %d\n", protocol);
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	memset(&sin6, '\0', sizeof(struct sockaddr_in6));
+	sin6.sin6_family    = AF_INET6;
+	sin6.sin6_port      = htons(port);
+	ret = svc_create_socket(serv, protocol, (struct sockaddr *)&sin6,
+				pmap_reg);
+	if (ret)
+		return ret;
+#endif
+	sin.sin_family      = AF_INET;
+	sin.sin_addr.s_addr = INADDR_ANY;
+	sin.sin_port        = htons(port);
+	return svc_create_socket(serv, protocol, (struct sockaddr *)&sin,
+				 pmap_reg);
 }
+EXPORT_SYMBOL(svc_makesock2);
 
 /*
  * Handle defer and revisit of requests 
@@ -1530,7 +1612,7 @@
 
 		dr->handle.owner = rqstp->rq_server;
 		dr->prot = rqstp->rq_prot;
-		dr->addr = rqstp->rq_addr;
+		memcpy(&dr->addr, &rqstp->rq_addr, sizeof(struct sockaddr_storage));
 		dr->argslen = rqstp->rq_arg.len >> 2;
 		memcpy(dr->args, rqstp->rq_arg.head[0].iov_base-skip, dr->argslen<<2);
 	}
@@ -1555,7 +1637,7 @@
 	rqstp->rq_arg.page_len = 0;
 	rqstp->rq_arg.len = dr->argslen<<2;
 	rqstp->rq_prot        = dr->prot;
-	rqstp->rq_addr        = dr->addr;
+	memcpy(&rqstp->rq_addr, &dr->addr, sizeof(struct sockaddr_storage));
 	return dr->argslen<<2;
 }
 
diff -Nru linux-2.6.11/net/sunrpc/xprtsock.c linux-2.6.11-09/net/sunrpc/xprtsock.c
--- linux-2.6.11/net/sunrpc/xprtsock.c	2005-03-14 14:51:31.000000000 +0100
+++ linux-2.6.11-09/net/sunrpc/xprtsock.c	2005-04-05 15:02:17.000000000 +0200
@@ -1125,22 +1125,61 @@
 }
 
 /**
- * xs_print_udp_ipv4_address - format an IPv4 address for printing
+ * xs_print_com_ipv4_address - format an IPv4 address for printing
  * @xprt: generic transport
  *
  */
-static void xs_print_udp_ipv4_address(struct rpc_xprt *xprt, size_t size, char *buffer, int flags)
+static void xs_print_com_ipv4_address(struct rpc_xprt *xprt, size_t size, char *buffer,
+				      int flags, char *proto)
 {
 	struct sockaddr_in *addr = (struct sockaddr_in *) &xprt->addr;
 
-	if (flags & 0x1)
-		buffer += snprintf(buffer, size, "ip=\"%u.%u.%u.%u\"",
-					NIPQUAD(addr->sin_addr.s_addr));
-	if (flags & 0x2)
-		buffer += snprintf(buffer, size, " port=\"%u\"",
-					ntohs(addr->sin_port));
-	if (flags & 0x4)
-		buffer += snprintf(buffer, size, " proto=\"udp\"");
+	if (flags & ADDR_FMT) {
+		if (flags & RAW_FMT)
+			buffer += snprintf(buffer, size, "%u.%u.%u.%u",
+						NIPQUAD(addr->sin_addr.s_addr));
+		else
+			buffer += snprintf(buffer, size, "ip=\"%u.%u.%u.%u\"",
+						NIPQUAD(addr->sin_addr.s_addr));
+	}
+	if (flags & PORT_FMT) {
+		if (flags & RAW_FMT)
+			buffer += snprintf(buffer, size, "%u",
+						ntohs(addr->sin_port));
+		else
+			buffer += snprintf(buffer, size, " port=\"%u\"",
+						ntohs(addr->sin_port));
+	}
+	if (flags & PROTO_FMT) {
+		if (flags & RAW_FMT)
+			buffer += snprintf(buffer, size, "%s", proto);
+		else
+			buffer += snprintf(buffer, size, " proto=\"%s\"",
+						proto);
+	}
+	if (flags & UADDR_FMT) {
+		if (flags & RAW_FMT)
+			buffer += snprintf(buffer, size, "%u.%u.%u.%u.%u.%u",
+					   NIPQUAD(addr->sin_addr.s_addr),
+					   ntohs(addr->sin_port) >> 