The complete set of patches combined into one patch.

Signed-off-by: Gilles Quillard <Gilles.Quillard@bull.net>
Signed-off-by: Aurelien Charbon <Aurelien.Charbon@ext.bull.net>

---

 fs/lockd/svclock.c          |    2 
 fs/nfs/callback.c           |   11 -
 fs/nfs/callback_proc.c      |   12 +
 fs/nfs/delegation.c         |    7 
 fs/nfs/inode.c              |   89 ++++++++----
 fs/nfs/nfs4_fs.h            |    9 -
 fs/nfs/nfs4proc.c           |    7 
 fs/nfs/nfs4state.c          |   29 ++-
 fs/nfs/nfs4xdr.c            |    9 -
 include/linux/nfs_fs_sb.h   |    5 
 include/linux/nfs_mount.h   |    4 
 include/linux/nfs_xdr.h     |    6 
 include/linux/sunrpc/clnt.h |   10 +
 include/linux/sunrpc/xprt.h |    7 
 net/sunrpc/Makefile         |    2 
 net/sunrpc/clnt.c           |    7 
 net/sunrpc/pmap_clnt.c      |  106 ++------------
 net/sunrpc/rpc_pipe.c       |    2 
 net/sunrpc/rpcb_clnt.c      |  321 ++++++++++++++++++++++++++++++++++++++++++++
 net/sunrpc/xprtsock.c       |  209 +++++++++++++++++++++++-----
 20 files changed, 660 insertions(+), 194 deletions(-)

---

diff -Nru linux-2.6.11/fs/lockd/svclock.c linux-2.6.11-07/fs/lockd/svclock.c
--- linux-2.6.11/fs/lockd/svclock.c	2005-03-14 14:51:31.000000000 +0100
+++ linux-2.6.11-07/fs/lockd/svclock.c	2005-03-21 10:13:23.000000000 +0100
@@ -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",
diff -Nru linux-2.6.11/fs/nfs/callback.c linux-2.6.11-07/fs/nfs/callback.c
--- linux-2.6.11/fs/nfs/callback.c	2005-03-14 14:50:30.000000000 +0100
+++ linux-2.6.11-07/fs/nfs/callback.c	2005-03-21 10:13:23.000000000 +0100
@@ -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);
 	}
 
@@ -142,14 +140,17 @@
 
 static int nfs_callback_authenticate(struct svc_rqst *rqstp)
 {
-	struct in_addr *addr = &rqstp->rq_addr.sin_addr;
+	struct sockaddr_in *addr = &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);
+	clp = nfs4_find_client((struct sockaddr *)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_proc.c linux-2.6.11-07/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-07/fs/nfs/callback_proc.c	2005-03-21 10:13:23.000000000 +0100
@@ -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((struct sockaddr *)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((struct sockaddr *)&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/delegation.c linux-2.6.11-07/fs/nfs/delegation.c
--- linux-2.6.11/fs/nfs/delegation.c	2005-03-14 14:50:30.000000000 +0100
+++ linux-2.6.11-07/fs/nfs/delegation.c	2005-03-21 10:13:23.000000000 +0100
@@ -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-07/fs/nfs/inode.c
--- linux-2.6.11/fs/nfs/inode.c	2005-03-14 14:51:31.000000000 +0100
+++ linux-2.6.11-07/fs/nfs/inode.c	2005-03-21 10:13:24.000000000 +0100
@@ -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);
 }
@@ -1784,33 +1782,49 @@
 		root->size = NFS2_FHSIZE;
 	if (root->size > sizeof(root->data)) {
 		printk("nfs_get_sb: invalid root filehandle\n");
-		kfree(server);
-		return ERR_PTR(-EINVAL);
+		s = ERR_PTR(-EINVAL);
+		goto out_free;
 	}
 	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");
-		kfree(server);
-		return ERR_PTR(-EINVAL);
+	if (data->version < 7) {
+		server->addrlen = sizeof(struct sockaddr_in);
+		server->addr = kmalloc(server->addrlen, GFP_KERNEL);
+		if (!server->addr) {
+			s = ERR_PTR(-ENOMEM);
+			goto out_free;
+		}
+		memcpy(server->addr, &data->addr, server->addrlen);
+	} else {
+		if (data->host_addrlen > sizeof(struct sockaddr_storage)) {
+			s = ERR_PTR(-EINVAL);
+			goto out_free;
+		}
+		server->addrlen = data->host_addrlen;
+		server->addr = kmalloc(server->addrlen, GFP_KERNEL);
+		if (!server->addr) {
+			s = ERR_PTR(-ENOMEM);
+			goto out_free;
+		}
+		if (copy_from_user(server->addr, data->host_addr, server->addrlen)) {
+			s = ERR_PTR(-EFAULT);
+			goto out_free;
+		}
 	}
 
 	s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
 
-	if (IS_ERR(s) || s->s_root) {
-		kfree(server);
-		return s;
-	}
+	if (IS_ERR(s) || s->s_root)
+		goto out_free;
 
 	s->s_flags = flags;
 
 	/* Fire up rpciod if not yet running */
 	if (rpciod_up() != 0) {
 		printk(KERN_WARNING "NFS: couldn't start rpciod!\n");
-		kfree(server);
-		return ERR_PTR(-EIO);
+		s = ERR_PTR(-EIO);
+		goto out_free;
 	}
 
 	error = nfs_fill_super(s, data, flags & MS_VERBOSE ? 1 : 0);
@@ -1821,6 +1835,11 @@
 	}
 	s->s_flags |= MS_ACTIVE;
 	return s;
+out_free:
+	if (server->addr)
+		kfree(server->addr);
+	kfree(server);
+	return s;
 }
 
 static void nfs_kill_super(struct super_block *s)
@@ -1842,6 +1861,8 @@
 	if (server->hostname != NULL)
 		kfree(server->hostname);
 	nfs_free_iostats(server->io_stats);
+	if (server->addr)
+		kfree(server->addr);
 	kfree(server);
 	nfs_release_automount_timer();
 }
@@ -1999,7 +2020,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 +2041,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 +2191,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 +2231,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 +2258,8 @@
 
 	if (server->hostname != NULL)
 		kfree(server->hostname);
+	if (server->addr != NULL)
+		kfree(server->addr);
 	kfree(server);
 	nfs_release_automount_timer();
 }
@@ -2350,10 +2375,14 @@
 	if (server->hostname == NULL)
 		goto free_server;
 	memcpy(server->hostname, parent->hostname, len);
+	server->addr = kmalloc(parent->addrlen, GFP_KERNEL);
+	if (server->addr == NULL)
+		goto free_hostname;
+	memcpy(server->addr, parent->addr, parent->addrlen);
 	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 +2429,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-07/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-07/fs/nfs/nfs4_fs.h	2005-03-21 10:13:25.000000000 +0100
@@ -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-07/fs/nfs/nfs4proc.c
--- linux-2.6.11/fs/nfs/nfs4proc.c	2005-03-14 14:51:31.000000000 +0100
+++ linux-2.6.11-07/fs/nfs/nfs4proc.c	2005-03-21 10:13:23.000000000 +0100
@@ -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-07/fs/nfs/nfs4state.c
--- linux-2.6.11/fs/nfs/nfs4state.c	2005-03-14 14:50:30.000000000 +0100
+++ linux-2.6.11-07/fs/nfs/nfs4state.c	2005-03-21 10:13:23.000000000 +0100
@@ -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-07/fs/nfs/nfs4xdr.c
--- linux-2.6.11/fs/nfs/nfs4xdr.c	2005-03-14 14:51:31.000000000 +0100
+++ linux-2.6.11-07/fs/nfs/nfs4xdr.c	2005-03-21 10:13:25.000000000 +0100
@@ -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/include/linux/nfs_fs_sb.h linux-2.6.11-07/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-07/include/linux/nfs_fs_sb.h	2005-03-21 10:13:25.000000000 +0100
@@ -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_mount.h linux-2.6.11-07/include/linux/nfs_mount.h
--- linux-2.6.11/include/linux/nfs_mount.h	2005-03-15 11:02:05.000000000 +0100
+++ linux-2.6.11-07/include/linux/nfs_mount.h	2005-03-21 10:13:24.000000000 +0100
@@ -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 {
@@ -43,6 +43,8 @@
 	struct nfs3_fh	root;			/* 4 */
 	int		pseudoflavor;		/* 5 */
 	char		context[NFS_MAX_CONTEXT_LEN + 1];	/* 6 */
+	unsigned int host_addrlen;		/* 7 */
+	struct sockaddr __user * host_addr;	/* 7 */
 
 };
 
diff -Nru linux-2.6.11/include/linux/nfs_xdr.h linux-2.6.11-07/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-07/include/linux/nfs_xdr.h	2005-03-21 10:13:25.000000000 +0100
@@ -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-07/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-07/include/linux/sunrpc/clnt.h	2005-03-21 10:13:23.000000000 +0100
@@ -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/xprt.h linux-2.6.11-07/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-07/include/linux/sunrpc/xprt.h	2005-03-21 10:13:24.000000000 +0100
@@ -173,7 +173,8 @@
 	unsigned long		state;		/* transport state */
 	unsigned char		shutdown   : 1,	/* being shut down */
 				need_bind  : 1, /* force a rebind */
-				resvport   : 1; /* use a reserved port */
+				resvport   : 1, /* use a reserved port */
+				alt_getport : 1; /* use alternate getport */
 
 	/*
 	 * Connection of transports
@@ -229,11 +230,9 @@
  */
 int			pmap_register(u32, u32, int, unsigned short, int *);
 void			pmap_getport(struct rpc_task *, struct rpc_clnt *);
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-void			pmap_getport6(struct rpc_task *, struct rpc_clnt *);
-#endif
 int			pmap_getport_external(struct sockaddr_in *, u32,
 					u32, int);
+void			rpcb_getport(struct rpc_task *, struct rpc_clnt *);
 
 static inline size_t xprt_tsh_size(struct rpc_xprt *xprt)
 {
diff -Nru linux-2.6.11/net/sunrpc/clnt.c linux-2.6.11-07/net/sunrpc/clnt.c
--- linux-2.6.11/net/sunrpc/clnt.c	2005-03-14 14:51:31.000000000 +0100
+++ linux-2.6.11-07/net/sunrpc/clnt.c	2005-03-21 10:13:24.000000000 +0100
@@ -1203,6 +1203,13 @@
 				(unsigned int)task->tk_client->cl_prog,
 				(unsigned int)task->tk_client->cl_vers,
 				task->tk_client->cl_server);
+		/* If the portmapper doesn't support the specified version,
+	 	 * try an other one if any */
+		if (task->tk_xprt->alt_getport) {
+			dprintk("RPC %5u %s: try another version\n", task->tk_pid, __FUNCTION__);
+			task->tk_action = call_bind;
+			return NULL;
+		}
 		error = -ENOSYS;
 		goto out_err;
 	case RPC_PROC_UNAVAIL:
diff -Nru linux-2.6.11/net/sunrpc/Makefile linux-2.6.11-07/net/sunrpc/Makefile
--- linux-2.6.11/net/sunrpc/Makefile	2005-03-14 14:51:31.000000000 +0100
+++ linux-2.6.11-07/net/sunrpc/Makefile	2005-03-21 10:13:24.000000000 +0100
@@ -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-07/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-07/net/sunrpc/pmap_clnt.c	2005-03-21 10:13:24.000000000 +0100
@@ -37,6 +37,7 @@
 	u32			pm_prot;
 	unsigned short		pm_port;
 	struct rpc_task *	pm_wake;
+	struct rpc_clnt *	pm_clnt;
 };
 
 static struct rpc_procinfo	pmap_procedures[];
@@ -63,13 +64,13 @@
 {
 	int protocol = rpc_aux_protocol(clnt);
 	struct rpc_xprt *xprt = task->tk_xprt;
-	struct sockaddr_in addr;
+	struct sockaddr_storage 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_clnt	*pmap_clnt = NULL;
 	struct rpc_task	*child;
 
 	dprintk("RPC: %5u pmap_getport(%s, %u, %u, %d)\n",
@@ -98,87 +99,28 @@
 	map->pm_port = 0;
 	map->pm_wake = task;
 
-	rpc_peeraddr(clnt, &addr, sizeof(addr));
-	pmap_clnt = pmap_create(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);
-}
-EXPORT_SYMBOL_GPL(pmap_getport);
-
+	rpc_peeraddr(clnt, (void *)&addr, sizeof(addr));
+	if (addr.ss_family == AF_INET) {
+		pmap_clnt = pmap_create(clnt->cl_server,
+					(struct sockaddr_in *)&addr,
+					map->pm_prot);
 #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",
+	} else if (addr.ss_family == AF_INET6) {
+		pmap_clnt = pmap_create6(clnt->cl_server,
+					 (struct sockaddr_in6 *)&addr,
+					 map->pm_prot);
+#endif
+	} else {
+		dprintk("RPC: %5u pmap_getport(%s, %u, %u, %d) address family not supported.\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;
+		rpc_exit(task, -EBADF);
 	}
-
-	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;
 	}
+	map->pm_clnt = pmap_clnt;
 
 	/* NB: rpc_new_child will release client after a failure. */
 	if (!(child = rpc_new_child(pmap_clnt, task))) {
@@ -206,19 +148,7 @@
 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);
+EXPORT_SYMBOL_GPL(pmap_getport);
 
 #ifdef CONFIG_ROOT_NFS
 int pmap_getport_external(struct sockaddr_in *sin, u32 prog, u32 vers, int prot)
diff -Nru linux-2.6.11/net/sunrpc/rpcb_clnt.c linux-2.6.11-07/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-07/net/sunrpc/rpcb_clnt.c	2005-03-21 10:13:24.000000000 +0100
@@ -0,0 +1,321 @@
+/*
+ * 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_GETADDR		3
+
+#define RPC_RPCB_VERSION	3
+
+static struct rpc_procinfo	rpcb_procedures[];
+static struct rpc_clnt *	rpcb_create(char *, struct sockaddr_in *, int);
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+static struct rpc_clnt *	rpcb_create6(char *, struct sockaddr_in6 *, 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;
+	unsigned short		r_port;
+	char 			r_addr[40];
+	struct rpc_task *       r_wake;
+};
+
+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);
+}
+
+void rpcb_getport(struct rpc_task *task, struct rpc_clnt *clnt)
+{
+	int protocol = rpc_aux_protocol(clnt);
+	struct rpc_xprt *xprt = task->tk_xprt;
+	struct sockaddr_storage addr;
+	struct rpc_message msg = {
+		.rpc_proc	= &rpcb_procedures[RPCB_GETADDR],
+		.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;
+	}
+
+	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_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);
+
+	if (addr.ss_family == AF_INET) {
+		rpcb_clnt = rpcb_create(clnt->cl_server,
+					(struct sockaddr_in *)&addr,
+					protocol);
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+
+	}  else if (addr.ss_family == AF_INET6) {
+		rpcb_clnt = rpcb_create6(clnt->cl_server,
+					 (struct sockaddr_in6 *)&addr,
+					 protocol);
+#endif
+	} else {
+		dprintk("RPC: %5u rpcb_getport(%s, %u, %u, %d) address family not supported.\n",
+			task->tk_pid, clnt->cl_server,
+			clnt->cl_prog, clnt->cl_vers, protocol);
+		rpc_exit(task, -EBADF);
+	}
+
+	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);
+}
+EXPORT_SYMBOL(rpcb_getport);
+
+/*
+ * 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);
+}
+
+static struct rpc_clnt * rpcb_create(char *hostname, struct sockaddr_in *srvaddr, int proto)
+{
+	struct rpc_create_args args = {
+		.protocol	= proto,
+		.address	= (struct sockaddr *)srvaddr,
+		.addrsize	= sizeof(*srvaddr),
+		.servername	= hostname,
+		.program	= &rpcb_program,
+		.version	= RPC_RPCB_VERSION,
+		.authflavor	= RPC_AUTH_NULL,
+		.behavior	= RPC_CLNT_SOFTRTRY | RPC_CLNT_CHATTY |
+					RPC_CLNT_ONESHOT,
+	};
+
+	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_in6 *srvaddr, int proto)
+{
+	struct rpc_create_args args = {
+		.protocol	= proto,
+		.address	= (struct sockaddr *)srvaddr,
+		.addrsize	= sizeof(*srvaddr),
+		.servername	= hostname,
+		.program	= &rpcb_program,
+		.version	= RPC_RPCB_VERSION,
+		.authflavor	= RPC_AUTH_NULL,
+		.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 RPCBIND
+ */
+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_getaddr(struct rpc_rqst *req, u32 *p, struct rpcbind_args *rpcb)
+{
+	char netid[] = "tcp";
+	char owner[] = "rpcb";
+
+	dprintk("RPC:       xdr_encode_getaddr(%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_procedures[] = {
+[RPCB_GETADDR] = {
+	  .p_proc		= RPCB_GETADDR,
+	  .p_encode		= (kxdrproc_t) xdr_encode_getaddr,
+	  .p_decode		= (kxdrproc_t) xdr_decode_port,
+	  .p_bufsiz		= 4,
+	  .p_count		= 1,
+	},
+};
+
+static struct rpc_version	rpcb_version3 = {
+	.number		= 3,
+	.nrprocs	= 4,
+	.procs		= rpcb_procedures
+};
+
+static struct rpc_version *	rpcb_version[] = {
+	NULL,
+	NULL,
+	NULL,
+	&rpcb_version3
+};
+
+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-07/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-07/net/sunrpc/rpc_pipe.c	2005-03-21 10:13:23.000000000 +0100
@@ -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/xprtsock.c linux-2.6.11-07/net/sunrpc/xprtsock.c
--- linux-2.6.11/net/sunrpc/xprtsock.c	2005-03-14 14:51:31.000000000 +0100
+++ linux-2.6.11-07/net/sunrpc/xprtsock.c	2005-03-21 10:13:24.000000000 +0100
@@ -1133,14 +1133,40 @@
 {
 	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, "udp");
+		else
+			buffer += snprintf(buffer, size, " proto=\"udp\"");
+	}
+	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) >> 8,
+					   ntohs(addr->sin_port) & 0xff);
+		else
+			buffer += snprintf(buffer, size, "uaddr=\"%u.%u.%u.%u.%u.%u\"",
+					   NIPQUAD(addr->sin_addr.s_addr),
+					   ntohs(addr->sin_port) >> 8,
+					   ntohs(addr->sin_port) & 0xff);
+	}
 }
 
 /**
@@ -1152,14 +1178,40 @@
 {
 	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=\"tcp\"");
+	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, "tcp");
+		else
+			buffer += snprintf(buffer, size, " proto=\"tcp\"");
+	}
+	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) >> 8,
+					  ntohs(addr->sin_port) & 0xff);
+		else
+			buffer += snprintf(buffer, size, "uaddr=\"%u.%u.%u.%u.%u.%u\"",
+					  NIPQUAD(addr->sin_addr.s_addr),
+					  ntohs(addr->sin_port) >> 8,
+					  ntohs(addr->sin_port) & 0xff);
+	}
 }
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
@@ -1172,14 +1224,41 @@
 {
 	struct sockaddr_in6 *addr = (struct sockaddr_in6 *) &xprt->addr;
 
-	if (flags & 0x1)
-		buffer += snprintf(buffer, size, "ip=\"%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\"",
-					NIP6(addr->sin6_addr));
-	if (flags & 0x2)
-		buffer += snprintf(buffer, size, " port=\"%u\"",
-					ntohs(addr->sin6_port));
-	if (flags & 0x4)
-		buffer += snprintf(buffer, size, " proto=\"udp\"");
+	if (flags & ADDR_FMT) {
+		if (flags & RAW_FMT)
+			buffer += snprintf(buffer, size, "%x:%x:%x:%x:%x:%x:%x:%x",
+					   NIP6(addr->sin6_addr));
+		else
+			buffer += snprintf(buffer, size, "ip=\"%x:%x:%x:%x:%x:%x:%x:%x\"",
+					   NIP6(addr->sin6_addr));
+	}
+	if (flags & PORT_FMT) {
+		if (flags & RAW_FMT)
+			buffer += snprintf(buffer, size, "%u",
+					   ntohs(addr->sin6_port));
+		else
+			buffer += snprintf(buffer, size, " port=\"%u\"",
+					   ntohs(addr->sin6_port));
+	}
+	if (flags & PROTO_FMT) {
+		if (flags & RAW_FMT)
+			buffer += snprintf(buffer, size, "udp");
+		else
+			buffer += snprintf(buffer, size, " proto=\"udp\"");
+	}
+	if (flags & UADDR_FMT) {
+		if (flags & RAW_FMT)
+			buffer += snprintf(buffer, size, "%x:%x:%x:%x:%x:%x:%x:%x.%u.%u",
+					   NIP6(addr->sin6_addr),
+					   ntohs(addr->sin6_port) >> 8,
+					   ntohs(addr->sin6_port) & 0xff);
+		else
+			buffer += snprintf(buffer, size,
+					   "uaddr=\"%x:%x:%x:%x:%x:%x:%x:%x.%u.%u\"",
+					   NIP6(addr->sin6_addr),
+					   ntohs(addr->sin6_port) >> 8,
+					   ntohs(addr->sin6_port) & 0xff);
+	}
 }
 
 /**
@@ -1191,14 +1270,41 @@
 {
 	struct sockaddr_in6 *addr = (struct sockaddr_in6 *) &xprt->addr;
 
-	if (flags & 0x1)
-		buffer += snprintf(buffer, size, "ip=\"%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\"",
-					NIP6(addr->sin6_addr));
-	if (flags & 0x2)
-		buffer += snprintf(buffer, size, " port=\"%u\"",
-					ntohs(addr->sin6_port));
-	if (flags & 0x4)
-		buffer += snprintf(buffer, size, " proto=\"tcp\"");
+	if (flags & ADDR_FMT) {
+		if (flags & RAW_FMT)
+			buffer += snprintf(buffer, size, "%x:%x:%x:%x:%x:%x:%x:%x",
+					   NIP6(addr->sin6_addr));
+		else
+			buffer += snprintf(buffer, size, "ip=\"%x:%x:%x:%x:%x:%x:%x:%x\"",
+					   NIP6(addr->sin6_addr));
+	}
+	if (flags & PORT_FMT) {
+		if (flags & RAW_FMT)
+			buffer += snprintf(buffer, size, "%u",
+					   ntohs(addr->sin6_port));
+		else
+			buffer += snprintf(buffer, size, " port=\"%u\"",
+					   ntohs(addr->sin6_port));
+	}
+	if (flags & PROTO_FMT) {
+		if (flags & RAW_FMT)
+			buffer += snprintf(buffer, size, "tcp");
+		else
+			buffer += snprintf(buffer, size, " proto=\"tcp\"");
+	}
+	if (flags & UADDR_FMT) {
+		if (flags & RAW_FMT)
+			buffer += snprintf(buffer, size, "%x:%x:%x:%x:%x:%x:%x:%x.%u.%u",
+					   NIP6(addr->sin6_addr),
+					   ntohs(addr->sin6_port) >> 8,
+					   ntohs(addr->sin6_port) & 0xff);
+		else
+			buffer += snprintf(buffer, size,
+					   "uaddr=\"%x:%x:%x:%x:%x:%x:%x:%x.%u.%u\"",
+					   NIP6(addr->sin6_addr),
+					   ntohs(addr->sin6_port) >> 8,
+					   ntohs(addr->sin6_port) & 0xff);
+	}
 }
 #endif
 
@@ -1753,11 +1859,22 @@
 	}
 }
 
+static void xs_getport(struct rpc_task *task, struct rpc_clnt *clnt)
+{
+	if (task->tk_xprt->alt_getport == 0) {
+		task->tk_xprt->alt_getport = 1;
+		rpcb_getport(task, clnt);
+	} else {
+		task->tk_xprt->alt_getport = 0;
+		pmap_getport(task, clnt);
+	}
+}
+
 static struct rpc_xprt_ops xs_udp_ops = {
 	.setbufsize	= xs_udp_setbufsize,
 	.print_addr	= xs_print_udp_ipv4_address,
 	.is_bound	= xs_is_bound,
-	.rpcbind	= pmap_getport,
+	.rpcbind	= xs_getport,
 	.set_port	= xs_set_port,
 	.connect	= xs_connect,
 	.aux_protocol	= xs_udp_aux_protocol,
@@ -1775,7 +1892,7 @@
 	.setbufsize	= xs_tcp_setbufsize,
 	.print_addr	= xs_print_tcp_ipv4_address,
 	.is_bound	= xs_is_bound,
-	.rpcbind	= pmap_getport,
+	.rpcbind	= xs_getport,
 	.set_port	= xs_set_port,
 	.connect	= xs_connect,
 	.aux_protocol	= xs_tcp_aux_protocol,
@@ -1794,7 +1911,7 @@
 	.setbufsize	= xs_udp_setbufsize,
 	.print_addr	= xs_print_udp_ipv6_address,
 	.is_bound	= xs_is_bound6,
-	.rpcbind	= pmap_getport6,
+	.rpcbind	= xs_getport,
 	.set_port	= xs_set_port6,
 	.connect	= xs_connect,
 	.aux_protocol	= xs_udp_aux_protocol,
@@ -1812,7 +1929,7 @@
 	.setbufsize	= xs_tcp_setbufsize,
 	.print_addr	= xs_print_tcp_ipv6_address,
 	.is_bound	= xs_is_bound6,
-	.rpcbind	= pmap_getport6,
+	.rpcbind	= xs_getport,
 	.set_port	= xs_set_port6,
 	.connect	= xs_connect,
 	.aux_protocol	= xs_tcp_aux_protocol,
@@ -1835,12 +1952,16 @@
  */
 static int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to)
 {
+	struct sockaddr_in *sap = (struct sockaddr_in *) &xprt->addr;
 	struct xs_private *priv;
 	char buf[256];
 
 	xs_print_udp_ipv4_address(xprt, sizeof(buf), buf, 0x7);
 	dprintk("RPC:       setting up transport to address %s\n", buf);
 
+	if (sap->sin_addr.s_addr == INADDR_ANY)
+		return -EINVAL;
+
 	xprt->max_reqs = xprt_udp_slot_table_entries;
 
  	priv = kmalloc(sizeof(struct xs_private), GFP_KERNEL);
@@ -1886,12 +2007,16 @@
  */
 static int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to)
 {
+	struct sockaddr_in *sap = (struct sockaddr_in *) &xprt->addr;
 	struct xs_private *priv;
 	char buf[256];
 
 	xs_print_tcp_ipv4_address(xprt, sizeof(buf), buf, 0x7);
 	dprintk("RPC:       setting up transport to address %s\n", buf);
 
+	if (sap->sin_addr.s_addr == INADDR_ANY)
+		return -EINVAL;
+
 	xprt->max_reqs = xprt_tcp_slot_table_entries;
 
  	priv = kmalloc(sizeof(struct xs_private), GFP_KERNEL);
@@ -1936,12 +2061,18 @@
  */
 static int xs_setup_udp6(struct rpc_xprt *xprt, struct rpc_timeout *to)
 {
+	struct sockaddr_in6 *sap = (struct sockaddr_in6 *) &xprt->addr;
+	struct in6_addr *addr = &sap->sin6_addr;
 	struct xs_private *priv;
 	char buf[256];
 
 	xs_print_udp_ipv6_address(xprt, sizeof(buf), buf, 0x7);
 	dprintk("RPC:       setting up transport to address %s\n", buf);
 
+	if (addr->s6_addr32[0] == 0 && addr->s6_addr32[1] == 0 &&
+	    addr->s6_addr32[2] == 0 && addr->s6_addr32[3] == 0)
+		return -EINVAL;
+
 	xprt->max_reqs = xprt_udp_slot_table_entries;
 
 	priv = kmalloc(sizeof(struct xs_private), GFP_KERNEL);
@@ -1987,12 +2118,18 @@
  */
 static int xs_setup_tcp6(struct rpc_xprt *xprt, struct rpc_timeout *to)
 {
+	struct sockaddr_in6 *sap = (struct sockaddr_in6 *) &xprt->addr;
+	struct in6_addr *addr = &sap->sin6_addr;
 	struct xs_private *priv;
 	char buf[256];
 
 	xs_print_tcp_ipv6_address(xprt, sizeof(buf), buf, 0x7);
 	dprintk("RPC:       setting up transport to address %s\n", buf);
 
+	if (addr->s6_addr32[0] == 0 && addr->s6_addr32[1] == 0 &&
+	    addr->s6_addr32[2] == 0 && addr->s6_addr32[3] == 0)
+		return -EINVAL;
+
 	xprt->max_reqs = xprt_tcp_slot_table_entries;
 
 	priv = kmalloc(sizeof(struct xs_private), GFP_KERNEL);
