Fix bugs mainly in the lock management.

Signed-off-by: Gilles Quillard <gilles.quillard@bull.net>
---

diff -Nru linux-2.6.9-cel5-gq-06/fs/lockd/host.c linux-2.6.9-cel5-gq-07/fs/lockd/host.c
--- linux-2.6.9-cel5-gq-06/fs/lockd/host.c	2005-01-21 17:09:59.000000000 +0100
+++ linux-2.6.9-cel5-gq-07/fs/lockd/host.c	2005-02-14 15:51:54.000000000 +0100
@@ -61,13 +61,13 @@
 					int proto, int version)
 {
 	struct nlm_host	*host, **hp;
-	struct in6_addr	addr;
+	struct in6_addr *addr = &sin->sin6_addr;
 	int		hash;
 
 	dprintk("lockd: nlm_lookup_host(%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x, p=%d, v=%d)\n",
-		NIP6(addr), proto, version);
+		NIP6(*addr), proto, version);
 
-	hash = NLM_ADDRHASH(addr.s6_addr32[3]);
+	hash = NLM_ADDRHASH(addr->s6_addr32[3]);
 
 	/* Lock hash table */
 	down(&nlm_host_sema);
@@ -83,7 +83,7 @@
 		if (host->h_server != server)
 			continue;
 
-		if (nlm_cmp_addr(&host->h_addr, sin)) {
+		if (!nlm_cmp_addr(&host->h_addr, sin)) {
 			if (hp != nlm_hosts + hash) {
 				*hp = host->h_next;
 				host->h_next = nlm_hosts[hash];
@@ -102,7 +102,7 @@
 		goto nohost;
 	memset(host, 0, sizeof(*host));
 
-	sprintf(host->h_name, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", NIP6(addr));
+	sprintf(host->h_name, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", NIP6(*addr));
 
 	host->h_addr       = *sin;
 	host->h_addr.sin6_port = 0;	/* ouch! */
diff -Nru linux-2.6.9-cel5-gq-06/fs/lockd/mon.c linux-2.6.9-cel5-gq-07/fs/lockd/mon.c
--- linux-2.6.9-cel5-gq-06/fs/lockd/mon.c	2005-01-21 17:09:59.000000000 +0100
+++ linux-2.6.9-cel5-gq-07/fs/lockd/mon.c	2005-02-14 15:51:54.000000000 +0100
@@ -106,7 +106,7 @@
 {
 	struct sockaddr_in6	sin = {
 		.sin6_family	= AF_INET6,
-		.sin6_port	= 0,
+		.sin6_port	= 0
 	};
 	struct rpc_create_args args = {
 		.protocol	= IPPROTO_UDP,
@@ -135,17 +135,17 @@
 static u32 *
 xdr_encode_common(struct rpc_rqst *rqstp, u32 *p, struct nsm_args *argp)
 {
-	char	buffer[20];
-	u32	addr = ntohl(argp->addr);
+	char		buffer[40];
+	struct in6_addr	addr = argp->addr;
 
 	/*
-	 * Use the dotted-quad IP address of the remote host as
+	 * Use the IPv6 address of the remote host as
 	 * identifier. Linux statd always looks up the canonical
 	 * hostname first for whatever remote hostname it receives,
 	 * so this works alright.
 	 */
-	sprintf(buffer, "%d.%d.%d.%d", (addr>>24) & 0xff, (addr>>16) & 0xff,
-				 	(addr>>8) & 0xff,  (addr) & 0xff);
+	sprintf(buffer, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
+		NIP6(addr));
 	if (!(p = xdr_encode_string(p, buffer))
 	 || !(p = xdr_encode_string(p, system_utsname.nodename)))
 		return ERR_PTR(-EIO);
@@ -162,7 +162,10 @@
 	p = xdr_encode_common(rqstp, p, argp);
 	if (IS_ERR(p))
 		return PTR_ERR(p);
-	*p++ = argp->addr;
+	*p++ = argp->addr.s6_addr32[0];
+	*p++ = argp->addr.s6_addr32[1];
+	*p++ = argp->addr.s6_addr32[2];
+	*p++ = argp->addr.s6_addr32[3];
 	*p++ = argp->vers;
 	*p++ = argp->proto;
 	*p++ = 0;
diff -Nru linux-2.6.9-cel5-gq-06/fs/nfs/dir.c linux-2.6.9-cel5-gq-07/fs/nfs/dir.c
--- linux-2.6.9-cel5-gq-06/fs/nfs/dir.c	2005-01-21 17:09:04.000000000 +0100
+++ linux-2.6.9-cel5-gq-07/fs/nfs/dir.c	2005-02-14 15:51:54.000000000 +0100
@@ -1382,7 +1382,7 @@
 	struct inode *old_inode = old_dentry->d_inode;
 	struct inode *new_inode = new_dentry->d_inode;
 	struct dentry *dentry = NULL, *rehash = NULL;
-	int error = -EBUSY;
+	int error;
 
 	/*
 	 * To prevent any new references to the target during the rename,
@@ -1409,6 +1409,12 @@
 	 */
 	if (!new_inode)
 		goto go_ahead;
+	/* If target is a hard link to the source, then noop */
+	error = 0;
+	if (NFS_FILEID(new_inode) == NFS_FILEID(old_inode))
+		goto out;
+
+	error = -EBUSY;
 	if (S_ISDIR(new_inode->i_mode))
 		goto out;
 	else if (atomic_read(&new_dentry->d_count) > 2) {
diff -Nru linux-2.6.9-cel5-gq-06/include/linux/lockd/lockd.h linux-2.6.9-cel5-gq-07/include/linux/lockd/lockd.h
--- linux-2.6.9-cel5-gq-06/include/linux/lockd/lockd.h	2005-01-21 17:09:59.000000000 +0100
+++ linux-2.6.9-cel5-gq-07/include/linux/lockd/lockd.h	2005-02-14 15:51:54.000000000 +0100
@@ -40,7 +40,7 @@
 	struct nlm_host *	h_next;		/* linked list (hash table) */
 	struct sockaddr_in6	h_addr;		/* peer address */
 	struct rpc_clnt	*	h_rpcclnt;	/* RPC client to talk to peer */
-	char			h_name[20];	/* remote hostname */
+	char			h_name[40];	/* remote hostname */
 	u32			h_version;	/* interface version */
 	rpc_authflavor_t	h_authflavor;	/* RPC authentication type */
 	unsigned short		h_proto;	/* transport proto */
diff -Nru linux-2.6.9-cel5-gq-06/include/linux/lockd/sm_inter.h linux-2.6.9-cel5-gq-07/include/linux/lockd/sm_inter.h
--- linux-2.6.9-cel5-gq-06/include/linux/lockd/sm_inter.h	2004-10-18 23:54:29.000000000 +0200
+++ linux-2.6.9-cel5-gq-07/include/linux/lockd/sm_inter.h	2005-02-14 15:51:54.000000000 +0100
@@ -24,7 +24,7 @@
  * Arguments for all calls to statd
  */
 struct nsm_args {
-	u32		addr;		/* remote address */
+	struct in6_addr	addr;		/* remote address */
 	u32		prog;		/* RPC callback info */
 	u32		vers;
 	u32		proc;
diff -Nru linux-2.6.9-cel5-gq-06/net/sunrpc/Makefile linux-2.6.9-cel5-gq-07/net/sunrpc/Makefile
--- linux-2.6.9-cel5-gq-06/net/sunrpc/Makefile	2004-12-13 14:36:38.000000000 +0100
+++ linux-2.6.9-cel5-gq-07/net/sunrpc/Makefile	2005-02-14 16:21:45.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.9-cel5-gq-06/net/sunrpc/pmap_clnt.c linux-2.6.9-cel5-gq-07/net/sunrpc/pmap_clnt.c
--- linux-2.6.9-cel5-gq-06/net/sunrpc/pmap_clnt.c	2005-01-21 17:04:43.000000000 +0100
+++ linux-2.6.9-cel5-gq-07/net/sunrpc/pmap_clnt.c	2005-02-14 15:51:54.000000000 +0100
@@ -31,7 +31,6 @@
 
 static struct rpc_procinfo	pmap_procedures[];
 static struct rpc_clnt *	pmap_create(char *, struct sockaddr_in *, int);
-static struct rpc_clnt *	pmap_create6(char *, struct sockaddr_in6 *, int);
 static void			pmap_getport_done(struct rpc_task *);
 extern struct rpc_program	pmap_program;
 
@@ -102,61 +101,6 @@
 }
 EXPORT_SYMBOL(rpc_getport);
 
-void rpc_getport6(struct rpc_task *task, struct rpc_clnt *clnt)
-{
-	struct rpc_xprt *xprt = clnt->cl_xprt;
-	struct rpc_portmap *map = &xprt->pmap;
-	struct sockaddr_in6 addr;
-	struct rpc_message msg = {
-		.rpc_proc	= &pmap_procedures[PMAP_GETPORT],
-		.rpc_argp	= map,
-		.rpc_resp	= &map->pm_port,
-		.rpc_cred	= NULL
-	};
-	struct rpc_clnt	*pmap_clnt;
-	struct rpc_task	*child;
-
-	dprintk("RPC: %5u rpc_getport6(%s, %u, %u, %d)\n",
-			task->tk_pid, clnt->cl_server, clnt->cl_prog,
-			clnt->cl_vers, xprt->prot);
-
-	if (test_and_set_bit(XPRT_BINDING, &xprt->state)) {
-		rpc_sleep_on(&xprt->bindwait, task, NULL, NULL);
-		return;
-	}
-
-	map->pm_prog = clnt->cl_prog;
-	map->pm_vers = clnt->cl_vers;
-	map->pm_prot = xprt->prot;
-
-	rpc_peeraddr(clnt, &addr, sizeof(addr));
-	pmap_clnt = pmap_create6(clnt->cl_server, &addr, xprt->prot);
-	if (IS_ERR(pmap_clnt)) {
-		task->tk_status = PTR_ERR(pmap_clnt);
-		goto bailout;
-	}
-	task->tk_status = 0;
-
-	/*
-	 * Note: rpc_new_child will release client after a failure.
-	 */
-	if (!(child = rpc_new_child(pmap_clnt, task)))
-		goto bailout;
-
-	/* Setup the call info struct */
-	rpc_call_setup(child, &msg, 0);
-
-	/* ... and run the child task */
-	rpc_run_child(task, child, pmap_getport_done);
-	return;
-
-bailout:
-	__wake_up_portmap_waiters(xprt);
-	task->tk_status = -EIO;
-	task->tk_action = NULL;
-}
-EXPORT_SYMBOL(rpc_getport6);
-
 #ifdef CONFIG_ROOT_NFS
 int
 rpc_getport_external(struct sockaddr_in *sin, __u32 prog, __u32 vers, int prot)
@@ -226,7 +170,7 @@
 	struct rpc_clnt		*pmap_clnt;
 	int error = 0;
 
-	dprintk("RPC:       registering (%u, %u, %d, %u) with IPv4 portmapper.\n",
+	dprintk("RPC:       registering (%u, %u, %d, %u) with portmapper.\n",
 			prog, vers, prot, port);
 
 	sin.sin_family = AF_INET;
@@ -257,48 +201,6 @@
 	return error;
 }
 
-int
-rpc_register6(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
-{
-	struct sockaddr_in6	sin6;
-	struct rpc_portmap	map;
-	struct rpc_clnt		*pmap_clnt;
-	int error = 0;
-
-	dprintk("RPC:       registering (%u, %u, %d, %u) with IPv6 portmapper.\n",
-			prog, vers, prot, port);
-
-	sin6.sin6_family = AF_INET6;
-	sin6.sin6_addr.s6_addr32[0] = 0;
-	sin6.sin6_addr.s6_addr32[1] = 0;
-	sin6.sin6_addr.s6_addr32[2] = htonl(0xffff);
-	sin6.sin6_addr.s6_addr32[3] = htonl(INADDR_LOOPBACK);
-	pmap_clnt = pmap_create6("localhost", &sin6, IPPROTO_UDP);
-	if (IS_ERR(pmap_clnt)) {
-		error = PTR_ERR(pmap_clnt);
-		dprintk("RPC:       couldn't create pmap client. Error = %d\n", error);
-		return error;
-	}
-
-	map.pm_prog = prog;
-	map.pm_vers = vers;
-	map.pm_prot = prot;
-	map.pm_port = port;
-
-	error = rpc_call(pmap_clnt, port? PMAP_SET : PMAP_UNSET,
-					&map, okay, 0);
-
-	if (error < 0) {
-		printk(KERN_WARNING
-			"RPC: failed to contact portmap (errno %d).\n",
-			error);
-	}
-	dprintk("RPC:       registration status %d/%d\n", error, *okay);
-
-	/* Client deleted automatically because cl_oneshot == 1 */
-	return error;
-}
-
 static struct rpc_clnt * pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto)
 {
 	struct rpc_create_args args = {
@@ -317,24 +219,6 @@
 	return rpc_create(&args);
 }
 
-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_NULL,
-		.behavior	= RPC_CLNT_SOFTRTRY | RPC_CLNT_CHATTY |
-					RPC_CLNT_ONESHOT,
-	};
-
-	srvaddr->sin6_port = htons(RPC_PMAP_PORT);
-	return rpc_create(&args);
-}
-
 /*
  * XDR encode/decode functions for PMAP
  */
diff -Nru linux-2.6.9-cel5-gq-06/net/sunrpc/rpcb_clnt.c linux-2.6.9-cel5-gq-07/net/sunrpc/rpcb_clnt.c
--- linux-2.6.9-cel5-gq-06/net/sunrpc/rpcb_clnt.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.9-cel5-gq-07/net/sunrpc/rpcb_clnt.c	2005-02-14 15:51:54.000000000 +0100
@@ -0,0 +1,287 @@
+/*
+ * linux/net/sunrpc/pmap.c
+ *
+ * Portmapper client.
+ *
+ * FIXME: In a secure environment, we may want to use an authentication
+ * flavor other than AUTH_NULL.
+ *
+ * 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_create6(char *, struct sockaddr_in6 *, int);
+static void			rpcb_getport_done(struct rpc_task *);
+extern struct rpc_program	rpcb_program;
+
+struct rpc_rpcb_req {
+	u32 r_prog;
+	u32 r_vers;
+	char r_addr[40];
+};
+
+static inline void __wake_up_portmap_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 rpc_getport6(struct rpc_task *task, struct rpc_clnt *clnt)
+{
+	struct rpc_xprt *xprt = clnt->cl_xprt;
+	struct rpc_portmap *map = &xprt->pmap;
+	static struct rpc_rpcb_req rpcb_req;
+	struct rpc_message msg = {
+		.rpc_proc	= &rpcb_procedures[RPCB_GETADDR],
+		.rpc_argp	= &rpcb_req,
+		.rpc_resp	= &map->pm_port,
+		.rpc_cred	= NULL
+	};
+	struct rpc_clnt	*rpcb_clnt;
+	struct rpc_task	*child;
+	struct sockaddr_in6 addr;
+	char str[40];
+
+	dprintk("RPC: %5u rpc_getport6(%s, %u, %u, %d)\n",
+			task->tk_pid, clnt->cl_server, clnt->cl_prog,
+			clnt->cl_vers, xprt->prot);
+
+	if (test_and_set_bit(XPRT_BINDING, &xprt->state)) {
+		rpc_sleep_on(&xprt->bindwait, task, NULL, NULL);
+		return;
+	}
+
+	map->pm_prog = rpcb_req.r_prog = clnt->cl_prog;
+	map->pm_vers = rpcb_req.r_vers = clnt->cl_vers;
+	map->pm_prot = xprt->prot;
+	rpc_peeraddr(clnt, &addr, sizeof(addr));
+	sprintf(str, "%x:%x:%x:%x:%x:%x:%x:%x",
+		NIP6(addr.sin6_addr));
+	memcpy(rpcb_req.r_addr, str, strlen(str));
+
+	rpcb_clnt = rpcb_create6(clnt->cl_server, &addr, xprt->prot);
+	if (IS_ERR(rpcb_clnt)) {
+		task->tk_status = PTR_ERR(rpcb_clnt);
+		goto bailout;
+	}
+	task->tk_status = 0;
+
+	/*
+	 * Note: rpc_new_child will release client after a failure.
+	 */
+	if (!(child = rpc_new_child(rpcb_clnt, task)))
+		goto bailout;
+
+	/* Setup the call info struct */
+	rpc_call_setup(child, &msg, 0);
+
+	/* ... and run the child task */
+	rpc_run_child(task, child, rpcb_getport_done);
+	return;
+
+bailout:
+	__wake_up_portmap_waiters(xprt);
+	task->tk_status = -EIO;
+	task->tk_action = NULL;
+}
+EXPORT_SYMBOL(rpc_getport6);
+
+static void
+rpcb_getport_done(struct rpc_task *task)
+{
+	struct rpc_clnt	*clnt = task->tk_client;
+	struct rpc_xprt *xprt = clnt->cl_xprt;
+	struct rpc_portmap *map = &xprt->pmap;
+
+	dprintk("RPC: %5u rpcb_getport_done(status %d, port %u)\n",
+			task->tk_pid, task->tk_status, map->pm_port);
+
+	xprt->ops->set_port(xprt, 0);
+	if (task->tk_status < 0) {
+		/* Make the calling task exit with an error */
+		task->tk_action = NULL;
+	} else if (map->pm_port == 0) {
+		/* Program not registered */
+		task->tk_status = -EACCES;
+		task->tk_action = NULL;
+	} else
+		xprt->ops->set_port(xprt, map->pm_port);
+
+	__wake_up_portmap_waiters(xprt);
+}
+
+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);
+}
+
+/*
+ * XDR encode/decode functions for PMAP
+ */
+static int
+xdr_encode_mapping(struct rpc_rqst *req, u32 *p, struct rpc_portmap *map)
+{
+	dprintk("RPC:       xdr_encode_mapping(%u, %u, %d, %u)\n",
+		map->pm_prog, map->pm_vers, map->pm_prot, map->pm_port);
+	*p++ = htonl(map->pm_prog);
+	*p++ = htonl(map->pm_vers);
+	*p++ = htonl(map->pm_prot);
+	*p++ = htonl(map->pm_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_getaddr(struct rpc_rqst *req, u32 *p, struct rpc_rpcb_req *rpcb)
+{
+	char netid[] = "tcp6";
+	char owner[] = "rpcb";
+
+	dprintk("RPC:       xdr_encode_getport(%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 int
+xdr_decode_bool(struct rpc_rqst *req, u32 *p, unsigned int *boolp)
+{
+	*boolp = (unsigned int) ntohl(*p++);
+	return 0;
+}
+
+static struct rpc_procinfo	rpcb_procedures[] = {
+[RPCB_SET] = {
+	  .p_proc		= RPCB_SET,
+	  .p_encode		= (kxdrproc_t) xdr_encode_mapping,	
+	  .p_decode		= (kxdrproc_t) xdr_decode_bool,
+	  .p_bufsiz		= 4,
+	  .p_count		= 1,
+	},
+[RPCB_UNSET] = {
+	  .p_proc		= RPCB_UNSET,
+	  .p_encode		= (kxdrproc_t) xdr_encode_mapping,	
+	  .p_decode		= (kxdrproc_t) xdr_decode_bool,
+	  .p_bufsiz		= 4,
+	  .p_count		= 1,
+	},
+[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.9-cel5-gq-06/net/sunrpc/svc.c linux-2.6.9-cel5-gq-07/net/sunrpc/svc.c
--- linux-2.6.9-cel5-gq-06/net/sunrpc/svc.c	2004-12-13 14:36:31.000000000 +0100
+++ linux-2.6.9-cel5-gq-07/net/sunrpc/svc.c	2005-02-15 09:53:54.641741808 +0100
@@ -452,7 +452,8 @@
 
 err_bad_vers:
 #ifdef RPC_PARANOIA
-	printk("svc: unknown version (%d)\n", vers);
+	printk("svc: unknown version (prog = %d, vers = %d, proc = %d)\n", prog,
+		vers, proc);
 #endif
 	serv->sv_stats->rpcbadfmt++;
 	svc_putu32(resv, rpc_prog_mismatch);
diff -Nru linux-2.6.9-cel5-gq-06/net/sunrpc/svcsock.c linux-2.6.9-cel5-gq-07/net/sunrpc/svcsock.c
--- linux-2.6.9-cel5-gq-06/net/sunrpc/svcsock.c	2005-01-21 17:04:43.000000000 +0100
+++ linux-2.6.9-cel5-gq-07/net/sunrpc/svcsock.c	2005-02-14 15:51:54.000000000 +0100
@@ -353,7 +353,7 @@
 	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 in6_pktinfo *pki = (struct in6_pktinfo *)CMSG_DATA(cmh);
 	int		len = 0;
diff -Nru linux-2.6.9-cel5-gq-06/net/sunrpc/xprtsock.c linux-2.6.9-cel5-gq-07/net/sunrpc/xprtsock.c
--- linux-2.6.9-cel5-gq-06/net/sunrpc/xprtsock.c	2005-01-21 17:04:43.000000000 +0100
+++ linux-2.6.9-cel5-gq-07/net/sunrpc/xprtsock.c	2005-02-14 15:51:54.000000000 +0100
@@ -369,7 +369,7 @@
 
 	clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
 	status = xs_sendpages(sock, (struct sockaddr *) &xprt->addr,
-			sizeof(struct sockaddr), xdr, req->rq_bytes_sent);
+			sizeof(xprt->addr), xdr, req->rq_bytes_sent);
 
 	dprintk("RPC:       xs_udp_send_request(%u) = %d\n",
 			xdr->len - req->rq_bytes_sent, status);
