From: "Ed Schouten" <ed@il.fontys.nl>

At the moment, the NLM cookie length is fixed to 8 bytes, while 1024 is the
theoretical maximum.  FreeBSD uses 16 bytes, Mac OS X uses 20 bytes. 
Therefore we need to make the length dynamic (which I set to 32 bytes).

This patch is based on an old patch for Linux 2.4.23-pre9, which I changed
to patch properly (also added some stylish NIPQUAD fixes).

Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/fs/lockd/svclock.c          |   16 +++++++--------
 25-akpm/fs/lockd/xdr.c              |   37 ++++++++++++++++++++++++++++++++----
 25-akpm/fs/lockd/xdr4.c             |    6 ++---
 25-akpm/include/linux/lockd/debug.h |    9 ++++++++
 25-akpm/include/linux/lockd/xdr.h   |    8 ++++---
 5 files changed, 58 insertions(+), 18 deletions(-)

diff -puN fs/lockd/svclock.c~lockd-remove-hardcoded-maximum-nlm-cookie-length fs/lockd/svclock.c
--- 25/fs/lockd/svclock.c~lockd-remove-hardcoded-maximum-nlm-cookie-length	2004-10-10 23:34:19.524094216 -0700
+++ 25-akpm/fs/lockd/svclock.c	2004-10-10 23:34:19.535092544 -0700
@@ -112,11 +112,11 @@ nlmsvc_lookup_block(struct nlm_file *fil
 				(long long)lock->fl.fl_end, lock->fl.fl_type);
 	for (head = &nlm_blocked; (block = *head) != 0; head = &block->b_next) {
 		fl = &block->b_call.a_args.lock.fl;
-		dprintk("lockd: check f=%p pd=%d %Ld-%Ld ty=%d cookie=%x\n",
+		dprintk("lockd: check f=%p pd=%d %Ld-%Ld ty=%d cookie=%s\n",
 				block->b_file, fl->fl_pid,
 				(long long)fl->fl_start,
 				(long long)fl->fl_end, fl->fl_type,
-				*(unsigned int*)(block->b_call.a_args.cookie.data));
+				nlmdbg_cookie2a(&block->b_call.a_args.cookie));
 		if (block->b_file == file && nlm_compare_locks(fl, &lock->fl)) {
 			if (remove) {
 				*head = block->b_next;
@@ -584,13 +584,13 @@ nlmsvc_grant_callback(struct rpc_task *t
 	struct sockaddr_in	*peer_addr = RPC_PEERADDR(task->tk_client);
 
 	dprintk("lockd: GRANT_MSG RPC callback\n");
-	dprintk("callback: looking for cookie %x, host (%08x)\n", 
-		*(unsigned int *)(call->a_args.cookie.data),
-		ntohl(peer_addr->sin_addr.s_addr));
+	dprintk("callback: looking for cookie %s, host (%u.%u.%u.%u)\n",
+		nlmdbg_cookie2a(&call->a_args.cookie),
+		NIPQUAD(peer_addr->sin_addr.s_addr));
 	if (!(block = nlmsvc_find_block(&call->a_args.cookie, peer_addr))) {
-		dprintk("lockd: no block for cookie %x, host (%08x)\n",
-			*(u32 *)(call->a_args.cookie.data),
-			ntohl(peer_addr->sin_addr.s_addr));
+		dprintk("lockd: no block for cookie %s, host (%u.%u.%u.%u)\n",
+			nlmdbg_cookie2a(&call->a_args.cookie),
+			NIPQUAD(peer_addr->sin_addr.s_addr));
 		return;
 	}
 
diff -puN fs/lockd/xdr4.c~lockd-remove-hardcoded-maximum-nlm-cookie-length fs/lockd/xdr4.c
--- 25/fs/lockd/xdr4.c~lockd-remove-hardcoded-maximum-nlm-cookie-length	2004-10-10 23:34:19.526093912 -0700
+++ 25-akpm/fs/lockd/xdr4.c	2004-10-10 23:34:19.536092392 -0700
@@ -56,7 +56,7 @@ nlm4_decode_cookie(u32 *p, struct nlm_co
 		c->len=4;
 		memset(c->data, 0, 4);	/* hockeypux brain damage */
 	}
-	else if(len<=8)
+	else if(len<=NLM_MAXCOOKIELEN)
 	{
 		c->len=len;
 		memcpy(c->data, p, len);
@@ -65,7 +65,7 @@ nlm4_decode_cookie(u32 *p, struct nlm_co
 	else 
 	{
 		printk(KERN_NOTICE
-			"lockd: bad cookie size %d (only cookies under 8 bytes are supported.)\n", len);
+			"lockd: bad cookie size %d (only cookies under %d bytes are supported.)\n", len, NLM_MAXCOOKIELEN);
 		return NULL;
 	}
 	return p;
@@ -515,7 +515,7 @@ nlm4clt_decode_res(struct rpc_rqst *req,
  * Buffer requirements for NLM
  */
 #define NLM4_void_sz		0
-#define NLM4_cookie_sz		3	/* 1 len , 2 data */
+#define NLM4_cookie_sz		1+XDR_QUADLEN(NLM_MAXCOOKIELEN)
 #define NLM4_caller_sz		1+XDR_QUADLEN(NLM_MAXSTRLEN)
 #define NLM4_netobj_sz		1+XDR_QUADLEN(XDR_MAX_NETOBJ)
 /* #define NLM4_owner_sz		1+XDR_QUADLEN(NLM4_MAXOWNER) */
diff -puN fs/lockd/xdr.c~lockd-remove-hardcoded-maximum-nlm-cookie-length fs/lockd/xdr.c
--- 25/fs/lockd/xdr.c~lockd-remove-hardcoded-maximum-nlm-cookie-length	2004-10-10 23:34:19.527093760 -0700
+++ 25-akpm/fs/lockd/xdr.c	2004-10-10 23:34:19.535092544 -0700
@@ -55,7 +55,7 @@ static inline u32 *nlm_decode_cookie(u32
 		c->len=4;
 		memset(c->data, 0, 4);	/* hockeypux brain damage */
 	}
-	else if(len<=8)
+	else if(len<=NLM_MAXCOOKIELEN)
 	{
 		c->len=len;
 		memcpy(c->data, p, len);
@@ -64,7 +64,7 @@ static inline u32 *nlm_decode_cookie(u32
 	else 
 	{
 		printk(KERN_NOTICE
-			"lockd: bad cookie size %d (only cookies under 8 bytes are supported.)\n", len);
+			"lockd: bad cookie size %d (only cookies under %d bytes are supported.)\n", len, NLM_MAXCOOKIELEN);
 		return NULL;
 	}
 	return p;
@@ -86,7 +86,7 @@ nlm_decode_fh(u32 *p, struct nfs_fh *f)
 
 	if ((len = ntohl(*p++)) != NFS2_FHSIZE) {
 		printk(KERN_NOTICE
-			"lockd: bad fhandle size %x (should be %d)\n",
+			"lockd: bad fhandle size %d (should be %d)\n",
 			len, NFS2_FHSIZE);
 		return NULL;
 	}
@@ -512,7 +512,7 @@ nlmclt_decode_res(struct rpc_rqst *req, 
  * Buffer requirements for NLM
  */
 #define NLM_void_sz		0
-#define NLM_cookie_sz		3	/* 1 len , 2 data */
+#define NLM_cookie_sz		1+QUADLEN(NLM_MAXCOOKIELEN)
 #define NLM_caller_sz		1+QUADLEN(sizeof(system_utsname.nodename))
 #define NLM_netobj_sz		1+QUADLEN(XDR_MAX_NETOBJ)
 /* #define NLM_owner_sz		1+QUADLEN(NLM_MAXOWNER) */
@@ -604,3 +604,32 @@ struct rpc_program		nlm_program = {
 		.stats		= &nlm_stats,
 };
 
+#ifdef RPC_DEBUG
+const char *nlmdbg_cookie2a(const struct nlm_cookie *cookie)
+{
+	/*
+	 * We can get away with a static buffer because we're only
+	 * called with BKL held.
+	 */
+	static char buf[2*NLM_MAXCOOKIELEN+1];
+	int i;
+	int len = sizeof(buf);
+	char *p = buf;
+
+	len--;	/* allow for trailing \0 */
+	if (len < 3)
+		return "???";
+	for (i = 0 ; i < cookie->len ; i++) {
+		if (len < 2) {
+			strcpy(p-3, "...");
+			break;
+		}
+		sprintf(p, "%02x", cookie->data[i]);
+		p += 2;
+		len -= 2;
+	}
+	*p = '\0';
+
+	return buf;
+}
+#endif
diff -puN include/linux/lockd/debug.h~lockd-remove-hardcoded-maximum-nlm-cookie-length include/linux/lockd/debug.h
--- 25/include/linux/lockd/debug.h~lockd-remove-hardcoded-maximum-nlm-cookie-length	2004-10-10 23:34:19.529093456 -0700
+++ 25-akpm/include/linux/lockd/debug.h	2004-10-10 23:34:19.536092392 -0700
@@ -45,4 +45,13 @@
 #define NLMDBG_ALL		0x7fff
 
 
+/*
+ * Support for printing NLM cookies in dprintk()
+ */
+#ifdef RPC_DEBUG
+struct nlm_cookie;
+/* Call this function with the BKL held (it uses a static buffer) */
+extern const char *nlmdbg_cookie2a(const struct nlm_cookie *);
+#endif
+
 #endif /* LINUX_LOCKD_DEBUG_H */
diff -puN include/linux/lockd/xdr.h~lockd-remove-hardcoded-maximum-nlm-cookie-length include/linux/lockd/xdr.h
--- 25/include/linux/lockd/xdr.h~lockd-remove-hardcoded-maximum-nlm-cookie-length	2004-10-10 23:34:19.531093152 -0700
+++ 25-akpm/include/linux/lockd/xdr.h	2004-10-10 23:34:19.537092240 -0700
@@ -13,6 +13,7 @@
 #include <linux/nfs.h>
 #include <linux/sunrpc/xdr.h>
 
+#define NLM_MAXCOOKIELEN    	32
 #define NLM_MAXSTRLEN		1024
 
 #define QUADLEN(len)		(((len) + 3) >> 2)
@@ -33,13 +34,14 @@ struct nlm_lock {
 };
 
 /*
- *	NLM cookies. Technically they can be 1K, Nobody uses over 8 bytes
- *	however.
+ *	NLM cookies. Technically they can be 1K, but Linux only uses 8 bytes.
+ *	FreeBSD uses 16, Apple Mac OS X 10.3 uses 20. Therefore we set it to
+ *	32 bytes.
  */
  
 struct nlm_cookie
 {
-	unsigned char data[8];
+	unsigned char data[NLM_MAXCOOKIELEN];
 	unsigned int len;
 };
 
_