Change the client address in the 'struct nfs4_client' to be transport independent.
The type of the 'cl_addr' field is changed from sockaddr_in to sockaddr *.
A 'addrlen' field is added to contain the length of the address.

With this solution, the space needed to store the address is allocated
according to the family of the address. This avoids to use a sockaddr_storage
structure with a large unused space.

Adapt the prototypage of the nfs4_find_client() and nfs4_get_client().

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

---

 callback.c      |    7 ++++---
 callback_proc.c |    4 ++--
 delegation.c    |    3 ++-
 inode.c         |    2 +-
 nfs4_fs.h       |    7 ++++---
 nfs4proc.c      |    3 ++-
 nfs4state.c     |   26 ++++++++++++++++++--------
 7 files changed, 33 insertions(+), 19 deletions(-)

---

diff -Nru linux-2.6.11-02/fs/nfs/callback.c linux-2.6.11-03/fs/nfs/callback.c
--- linux-2.6.11-02/fs/nfs/callback.c	2005-03-14 14:50:30.000000000 +0100
+++ linux-2.6.11-03/fs/nfs/callback.c	2005-03-14 16:49:08.000000000 +0100
@@ -142,14 +142,15 @@
 
 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;
 
 	/* 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));
+	dprintk("%s: %u.%u.%u.%u NFSv4 callback!\n", __FUNCTION__,
+		NIPQUAD(addr->sin_addr));
 	nfs4_put_client(clp);
 	switch (rqstp->rq_authop->flavour) {
 		case RPC_AUTH_NULL:
diff -Nru linux-2.6.11-02/fs/nfs/callback_proc.c linux-2.6.11-03/fs/nfs/callback_proc.c
--- linux-2.6.11-02/fs/nfs/callback_proc.c	2005-03-14 14:50:30.000000000 +0100
+++ linux-2.6.11-03/fs/nfs/callback_proc.c	2005-03-14 16:27:38.000000000 +0100
@@ -23,7 +23,7 @@
 	
 	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;
 	inode = nfs_delegation_find_inode(clp, &args->fh);
@@ -60,7 +60,7 @@
 	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;
 	inode = nfs_delegation_find_inode(clp, &args->fh);
diff -Nru linux-2.6.11-02/fs/nfs/delegation.c linux-2.6.11-03/fs/nfs/delegation.c
--- linux-2.6.11-02/fs/nfs/delegation.c	2005-03-14 14:50:30.000000000 +0100
+++ linux-2.6.11-03/fs/nfs/delegation.c	2005-03-14 16:27:38.000000000 +0100
@@ -106,7 +106,8 @@
 					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));
+					__FUNCTION__,
+					NIPQUAD(((struct sockaddr_in *)clp->cl_addr)->sin_addr));
 			status = -EIO;
 		}
 	}
diff -Nru linux-2.6.11-02/fs/nfs/inode.c linux-2.6.11-03/fs/nfs/inode.c
--- linux-2.6.11-02/fs/nfs/inode.c	2005-03-15 09:00:40.000000000 +0100
+++ linux-2.6.11-03/fs/nfs/inode.c	2005-03-15 09:03:10.000000000 +0100
@@ -2000,7 +2000,7 @@
 	server->retrans_timeo = timeparms.to_initval;
 	server->retrans_count = timeparms.to_retries;
 
-	clp = nfs4_get_client(&((struct sockaddr_in *)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;
diff -Nru linux-2.6.11-02/fs/nfs/nfs4_fs.h linux-2.6.11-03/fs/nfs/nfs4_fs.h
--- linux-2.6.11-02/fs/nfs/nfs4_fs.h	2005-03-14 14:50:30.000000000 +0100
+++ linux-2.6.11-03/fs/nfs/nfs4_fs.h	2005-03-14 16:27:38.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;
@@ -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-02/fs/nfs/nfs4proc.c linux-2.6.11-03/fs/nfs/nfs4proc.c
--- linux-2.6.11-02/fs/nfs/nfs4proc.c	2005-03-14 14:51:31.000000000 +0100
+++ linux-2.6.11-03/fs/nfs/nfs4proc.c	2005-03-14 16:27:38.000000000 +0100
@@ -2503,7 +2503,8 @@
 	for(;;) {
 		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),
+				clp->cl_ipaddr,
+				NIPQUAD(((struct sockaddr_in *)clp->cl_addr)->sin_addr),
 				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-02/fs/nfs/nfs4state.c linux-2.6.11-03/fs/nfs/nfs4state.c
--- linux-2.6.11-02/fs/nfs/nfs4state.c	2005-03-14 14:50:30.000000000 +0100
+++ linux-2.6.11-03/fs/nfs/nfs4state.c	2005-03-14 16:27:38.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;
@@ -860,7 +868,8 @@
 	struct nfs4_state_recovery_ops *ops;
 	int status = 0;
 
-	daemonize("%u.%u.%u.%u-reclaim", NIPQUAD(clp->cl_addr));
+	daemonize("%u.%u.%u.%u-reclaim",
+		  NIPQUAD(((struct sockaddr_in *)clp->cl_addr)->sin_addr));
 	allow_signal(SIGKILL);
 
 	atomic_inc(&clp->cl_count);
@@ -917,7 +926,8 @@
 	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);
+			NIPQUAD(((struct sockaddr_in *)clp->cl_addr)->sin_addr),
+			-status);
 	goto out;
 }
 
