Change the server address in the 'struct server' to be transport independent.
The type of the '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.

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

---

 fs/nfs/inode.c            |   46 +++++++++++++++++++++++++++++++++++-----------
 include/linux/nfs_fs_sb.h |    3 ++-
 2 files changed, 37 insertions(+), 12 deletions(-)

---

diff -Nru linux-2.6.11-01/fs/nfs/inode.c linux-2.6.11-02/fs/nfs/inode.c
--- linux-2.6.11-01/fs/nfs/inode.c	2005-03-14 16:27:37.000000000 +0100
+++ linux-2.6.11-02/fs/nfs/inode.c	2005-03-15 10:51:55.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,8 +1733,7 @@
 	struct nfs_server *server = data;
 	struct nfs_server *old = NFS_SB(sb);
 
-	if (memcmp((void *)&old->addr, (void *)&server->addr,
-		   sizeof(struct sockaddr_in)))
+	if (memcmp((void *)&old->addr, (void *)server->addr, server->addrlen))
 		return 0;
 	return !nfs_compare_fh(&old->fh, &server->fh);
 }
@@ -1789,11 +1788,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));
+	server->addrlen = sizeof(struct sockaddr_in);
+	server->addr = kmalloc(server->addrlen, GFP_KERNEL);
+	if (!server->addr) {
+		kfree(server);
+		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;
 	}
@@ -1803,6 +1809,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);
 	}
@@ -1993,7 +2000,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(&((struct sockaddr_in *)server->addr)->sin_addr);
 	if (!clp) {
 		printk(KERN_WARNING "NFS: failed to create NFS4 client.\n");
 		return -EIO;
@@ -2014,8 +2021,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,
@@ -2164,11 +2171,17 @@
 		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))) {
+	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;
 	}
@@ -2198,6 +2211,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)
@@ -2223,6 +2238,8 @@
 
 	if (server->hostname != NULL)
 		kfree(server->hostname);
+	if (server->addr != NULL)
+		kfree(server->addr);
 	kfree(server);
 	nfs_release_automount_timer();
 }
@@ -2338,10 +2355,15 @@
 	if (server->hostname == NULL)
 		goto free_server;
 	memcpy(server->hostname, parent->hostname, len);
+	len = strlen(parent->addrlen) + 1;
+	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:
@@ -2388,6 +2410,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-01/include/linux/nfs_fs_sb.h linux-2.6.11-02/include/linux/nfs_fs_sb.h
--- linux-2.6.11-01/include/linux/nfs_fs_sb.h	2005-03-14 14:51:31.000000000 +0100
+++ linux-2.6.11-02/include/linux/nfs_fs_sb.h	2005-03-14 16:27:37.000000000 +0100
@@ -33,7 +33,8 @@
 	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
