* [PATCH 01/27] SUNRPC: rpc_create() default hostname should support AF_INET6 addresses
[not found] ` <20071210195106.2823.43884.stgit-meopP2rzCrTwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
@ 2007-12-10 19:56 ` Chuck Lever
[not found] ` <20071210195623.2823.13011.stgit-meopP2rzCrTwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
2007-12-10 19:56 ` [PATCH 02/27] SUNRPC: Fix socket address handling in rpcb_clnt Chuck Lever
` (25 subsequent siblings)
26 siblings, 1 reply; 31+ messages in thread
From: Chuck Lever @ 2007-12-10 19:56 UTC (permalink / raw)
To: trond.myklebust; +Cc: aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ, linux-nfs
If the ULP doesn't pass a hostname string to rpc_create(), it manufactures
one based on the passed-in address. Be smart enough to handle an AF_INET6
address properly in this case.
Move the default servername logic before the xprt_create_transport() call
to simplify error handling in rpc_create().
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
net/sunrpc/clnt.c | 32 +++++++++++++++++++++++++++-----
1 files changed, 27 insertions(+), 5 deletions(-)
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 76be83e..c297161 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -30,6 +30,7 @@
#include <linux/smp_lock.h>
#include <linux/utsname.h>
#include <linux/workqueue.h>
+#include <linux/in6.h>
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/rpc_pipe_fs.h>
@@ -247,7 +248,7 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
.addrlen = args->addrsize,
.timeout = args->timeout
};
- char servername[20];
+ char servername[48];
xprt = xprt_create_transport(&xprtargs);
if (IS_ERR(xprt))
@@ -258,13 +259,34 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
* up a string representation of the passed-in address.
*/
if (args->servername == NULL) {
- struct sockaddr_in *addr =
- (struct sockaddr_in *) args->address;
- snprintf(servername, sizeof(servername), NIPQUAD_FMT,
- NIPQUAD(addr->sin_addr.s_addr));
+ servername[0] = '\0';
+ switch (args->address->sa_family) {
+ case AF_INET: {
+ struct sockaddr_in *sin =
+ (struct sockaddr_in *)args->address;
+ snprintf(servername, sizeof(servername), NIPQUAD_FMT,
+ NIPQUAD(sin->sin_addr.s_addr));
+ break;
+ }
+ case AF_INET6: {
+ struct sockaddr_in6 *sin =
+ (struct sockaddr_in6 *)args->address;
+ snprintf(servername, sizeof(servername), NIP6_FMT,
+ NIP6(sin->sin6_addr));
+ break;
+ }
+ default:
+ /* caller wants default server name, but
+ * address family isn't recognized. */
+ return ERR_PTR(-EINVAL);
+ }
args->servername = servername;
}
+ xprt = xprt_create_transport(&xprtargs);
+ if (IS_ERR(xprt))
+ return (struct rpc_clnt *)xprt;
+
/*
* By default, kernel RPC client connects from a reserved port.
* CAP_NET_BIND_SERVICE will not be set for unprivileged requesters,
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 02/27] SUNRPC: Fix socket address handling in rpcb_clnt
[not found] ` <20071210195106.2823.43884.stgit-meopP2rzCrTwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
2007-12-10 19:56 ` [PATCH 01/27] SUNRPC: rpc_create() default hostname should support AF_INET6 addresses Chuck Lever
@ 2007-12-10 19:56 ` Chuck Lever
2007-12-10 19:56 ` [PATCH 03/27] SUNRPC: RPC version numbers are u32 Chuck Lever
` (24 subsequent siblings)
26 siblings, 0 replies; 31+ messages in thread
From: Chuck Lever @ 2007-12-10 19:56 UTC (permalink / raw)
To: trond.myklebust; +Cc: aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ, linux-nfs
Make sure rpcb_clnt passes the correct address length to rpc_create().
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
net/sunrpc/rpcb_clnt.c | 20 ++++++++++++--------
1 files changed, 12 insertions(+), 8 deletions(-)
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index a05493a..363106f 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -162,12 +162,13 @@ static void rpcb_wake_rpcbind_waiters(struct rpc_xprt *xprt, int status)
}
static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr,
- int proto, int version, int privileged)
+ size_t salen, int proto, int version,
+ int privileged)
{
struct rpc_create_args args = {
.protocol = proto,
.address = srvaddr,
- .addrsize = sizeof(struct sockaddr_in),
+ .addrsize = salen,
.servername = hostname,
.program = &rpcb_program,
.version = version,
@@ -230,7 +231,7 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
prog, vers, prot, port);
rpcb_clnt = rpcb_create("localhost", (struct sockaddr *) &sin,
- XPRT_TRANSPORT_UDP, 2, 1);
+ sizeof(sin), XPRT_TRANSPORT_UDP, 2, 1);
if (IS_ERR(rpcb_clnt))
return PTR_ERR(rpcb_clnt);
@@ -279,7 +280,8 @@ int rpcb_getport_sync(struct sockaddr_in *sin, __u32 prog,
__FUNCTION__, NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
sprintf(hostname, NIPQUAD_FMT, NIPQUAD(sin->sin_addr.s_addr));
- rpcb_clnt = rpcb_create(hostname, (struct sockaddr *)sin, prot, 2, 0);
+ rpcb_clnt = rpcb_create(hostname, (struct sockaddr *)sin,
+ sizeof(sin), prot, 2, 0);
if (IS_ERR(rpcb_clnt))
return PTR_ERR(rpcb_clnt);
@@ -310,7 +312,9 @@ void rpcb_getport_async(struct rpc_task *task)
struct rpc_clnt *rpcb_clnt;
static struct rpcbind_args *map;
struct rpc_task *child;
- struct sockaddr addr;
+ struct sockaddr_storage addr;
+ struct sockaddr *sap = (struct sockaddr *)&addr;
+ size_t salen;
int status;
struct rpcb_info *info;
@@ -340,10 +344,10 @@ void rpcb_getport_async(struct rpc_task *task)
goto bailout_nofree;
}
- rpc_peeraddr(clnt, (void *)&addr, sizeof(addr));
+ salen = rpc_peeraddr(clnt, sap, sizeof(addr));
/* Don't ever use rpcbind v2 for AF_INET6 requests */
- switch (addr.sa_family) {
+ switch (sap->sa_family) {
case AF_INET:
info = rpcb_next_version;
break;
@@ -368,7 +372,7 @@ void rpcb_getport_async(struct rpc_task *task)
dprintk("RPC: %5u %s: trying rpcbind version %u\n",
task->tk_pid, __FUNCTION__, bind_version);
- rpcb_clnt = rpcb_create(clnt->cl_server, &addr, xprt->prot,
+ rpcb_clnt = rpcb_create(clnt->cl_server, sap, salen, xprt->prot,
bind_version, 0);
if (IS_ERR(rpcb_clnt)) {
status = PTR_ERR(rpcb_clnt);
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 03/27] SUNRPC: RPC version numbers are u32
[not found] ` <20071210195106.2823.43884.stgit-meopP2rzCrTwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
2007-12-10 19:56 ` [PATCH 01/27] SUNRPC: rpc_create() default hostname should support AF_INET6 addresses Chuck Lever
2007-12-10 19:56 ` [PATCH 02/27] SUNRPC: Fix socket address handling in rpcb_clnt Chuck Lever
@ 2007-12-10 19:56 ` Chuck Lever
2007-12-10 19:56 ` [PATCH 04/27] SUNRPC: Move universal address definitions to global header Chuck Lever
` (23 subsequent siblings)
26 siblings, 0 replies; 31+ messages in thread
From: Chuck Lever @ 2007-12-10 19:56 UTC (permalink / raw)
To: trond.myklebust; +Cc: aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ, linux-nfs
Clean up: use correct type for RPC version numbers in rpcbind client.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
net/sunrpc/rpcb_clnt.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index 363106f..39844b7 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -162,7 +162,7 @@ static void rpcb_wake_rpcbind_waiters(struct rpc_xprt *xprt, int status)
}
static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr,
- size_t salen, int proto, int version,
+ size_t salen, int proto, u32 version,
int privileged)
{
struct rpc_create_args args = {
@@ -307,7 +307,7 @@ EXPORT_SYMBOL_GPL(rpcb_getport_sync);
void rpcb_getport_async(struct rpc_task *task)
{
struct rpc_clnt *clnt = task->tk_client;
- int bind_version;
+ u32 bind_version;
struct rpc_xprt *xprt = task->tk_xprt;
struct rpc_clnt *rpcb_clnt;
static struct rpcbind_args *map;
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 04/27] SUNRPC: Move universal address definitions to global header
[not found] ` <20071210195106.2823.43884.stgit-meopP2rzCrTwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (2 preceding siblings ...)
2007-12-10 19:56 ` [PATCH 03/27] SUNRPC: RPC version numbers are u32 Chuck Lever
@ 2007-12-10 19:56 ` Chuck Lever
2007-12-10 19:56 ` [PATCH 05/27] NFS: Ensure NFSv4 SETCLIENTID send buffer is large enough Chuck Lever
` (22 subsequent siblings)
26 siblings, 0 replies; 31+ messages in thread
From: Chuck Lever @ 2007-12-10 19:56 UTC (permalink / raw)
To: trond.myklebust; +Cc: aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ, linux-nfs
Universal addresses are defined in RFC 1833 and clarified in RFC 3530. We
need to use them in several places in the NFS and RPC clients, so move the
relevant definition and block comment to an appropriate global include
file.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
include/linux/sunrpc/msg_prot.h | 39 ++++++++++++++++++++++++++++++++++
net/sunrpc/rpcb_clnt.c | 45 +++------------------------------------
2 files changed, 42 insertions(+), 42 deletions(-)
diff --git a/include/linux/sunrpc/msg_prot.h b/include/linux/sunrpc/msg_prot.h
index c4beb57..70df4f1 100644
--- a/include/linux/sunrpc/msg_prot.h
+++ b/include/linux/sunrpc/msg_prot.h
@@ -152,5 +152,44 @@ typedef __be32 rpc_fraghdr;
*/
#define RPCBIND_MAXNETIDLEN (4u)
+/*
+ * Universal addresses are introduced in RFC 1833 and further spelled
+ * out in RFC 3530. RPCBIND_MAXUADDRLEN defines a maximum byte length
+ * of a universal address for use in allocating buffers and character
+ * arrays.
+ *
+ * Quoting RFC 3530, section 2.2:
+ *
+ * For TCP over IPv4 and for UDP over IPv4, the format of r_addr is the
+ * US-ASCII string:
+ *
+ * h1.h2.h3.h4.p1.p2
+ *
+ * The prefix, "h1.h2.h3.h4", is the standard textual form for
+ * representing an IPv4 address, which is always four octets long.
+ * Assuming big-endian ordering, h1, h2, h3, and h4, are respectively,
+ * the first through fourth octets each converted to ASCII-decimal.
+ * Assuming big-endian ordering, p1 and p2 are, respectively, the first
+ * and second octets each converted to ASCII-decimal. For example, if a
+ * host, in big-endian order, has an address of 0x0A010307 and there is
+ * a service listening on, in big endian order, port 0x020F (decimal
+ * 527), then the complete universal address is "10.1.3.7.2.15".
+ *
+ * ...
+ *
+ * For TCP over IPv6 and for UDP over IPv6, the format of r_addr is the
+ * US-ASCII string:
+ *
+ * x1:x2:x3:x4:x5:x6:x7:x8.p1.p2
+ *
+ * The suffix "p1.p2" is the service port, and is computed the same way
+ * as with universal addresses for TCP and UDP over IPv4. The prefix,
+ * "x1:x2:x3:x4:x5:x6:x7:x8", is the standard textual form for
+ * representing an IPv6 address as defined in Section 2.2 of [RFC2373].
+ * Additionally, the two alternative forms specified in Section 2.2 of
+ * [RFC2373] are also acceptable.
+ */
+#define RPCBIND_MAXUADDRLEN (56u)
+
#endif /* __KERNEL__ */
#endif /* _LINUX_SUNRPC_MSGPROT_H_ */
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index 39844b7..c56fb50 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -55,45 +55,6 @@ enum {
#define RPCB_HIGHPROC_4 RPCBPROC_GETSTAT
/*
- * r_addr
- *
- * Quoting RFC 3530, section 2.2:
- *
- * For TCP over IPv4 and for UDP over IPv4, the format of r_addr is the
- * US-ASCII string:
- *
- * h1.h2.h3.h4.p1.p2
- *
- * The prefix, "h1.h2.h3.h4", is the standard textual form for
- * representing an IPv4 address, which is always four octets long.
- * Assuming big-endian ordering, h1, h2, h3, and h4, are respectively,
- * the first through fourth octets each converted to ASCII-decimal.
- * Assuming big-endian ordering, p1 and p2 are, respectively, the first
- * and second octets each converted to ASCII-decimal. For example, if a
- * host, in big-endian order, has an address of 0x0A010307 and there is
- * a service listening on, in big endian order, port 0x020F (decimal
- * 527), then the complete universal address is "10.1.3.7.2.15".
- *
- * ...
- *
- * For TCP over IPv6 and for UDP over IPv6, the format of r_addr is the
- * US-ASCII string:
- *
- * x1:x2:x3:x4:x5:x6:x7:x8.p1.p2
- *
- * The suffix "p1.p2" is the service port, and is computed the same way
- * as with universal addresses for TCP and UDP over IPv4. The prefix,
- * "x1:x2:x3:x4:x5:x6:x7:x8", is the standard textual form for
- * representing an IPv6 address as defined in Section 2.2 of [RFC2373].
- * Additionally, the two alternative forms specified in Section 2.2 of
- * [RFC2373] are also acceptable.
- *
- * XXX: Currently this implementation does not explicitly convert the
- * stored address to US-ASCII on non-ASCII systems.
- */
-#define RPCB_MAXADDRLEN (128u)
-
-/*
* r_owner
*
* The "owner" is allowed to unset a service in the rpcbind database.
@@ -113,7 +74,7 @@ struct rpcbind_args {
u32 r_prot;
unsigned short r_port;
char * r_netid;
- char r_addr[RPCB_MAXADDRLEN];
+ char r_addr[RPCBIND_MAXUADDRLEN];
char * r_owner;
};
@@ -522,7 +483,7 @@ static int rpcb_decode_getaddr(struct rpc_rqst *req, __be32 *p,
* Simple sanity check. The smallest possible universal
* address is an IPv4 address string containing 11 bytes.
*/
- if (addr_len < 11 || addr_len > RPCB_MAXADDRLEN)
+ if (addr_len < 11 || addr_len > RPCBIND_MAXUADDRLEN)
goto out_err;
/*
@@ -573,7 +534,7 @@ out_err:
#define RPCB_boolean_sz (1u)
#define RPCB_netid_sz (1+XDR_QUADLEN(RPCBIND_MAXNETIDLEN))
-#define RPCB_addr_sz (1+XDR_QUADLEN(RPCB_MAXADDRLEN))
+#define RPCB_addr_sz (1+XDR_QUADLEN(RPCBIND_MAXUADDRLEN))
#define RPCB_ownerstring_sz (1+XDR_QUADLEN(RPCB_MAXOWNERLEN))
#define RPCB_mappingargs_sz RPCB_program_sz+RPCB_version_sz+ \
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 05/27] NFS: Ensure NFSv4 SETCLIENTID send buffer is large enough
[not found] ` <20071210195106.2823.43884.stgit-meopP2rzCrTwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (3 preceding siblings ...)
2007-12-10 19:56 ` [PATCH 04/27] SUNRPC: Move universal address definitions to global header Chuck Lever
@ 2007-12-10 19:56 ` Chuck Lever
2007-12-10 19:57 ` [PATCH 06/27] NFS: Increase size of cl_ipaddr field to hold IPv6 addresses Chuck Lever
` (21 subsequent siblings)
26 siblings, 0 replies; 31+ messages in thread
From: Chuck Lever @ 2007-12-10 19:56 UTC (permalink / raw)
To: trond.myklebust; +Cc: aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ, linux-nfs
Ensure that the RPC buffer size specified for NFSv4 SETCLIENTID procedures
matches what we are encoding into the buffer. See the definition of
struct nfs4_setclientid {} and the encode_setclientid() function.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfs/nfs4xdr.c | 10 ++++++----
include/linux/nfs_xdr.h | 13 +++++++------
2 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index eae46f0..db1ed9c 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -116,10 +116,12 @@ static int nfs4_stat_to_errno(int);
#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))
+ XDR_QUADLEN(NFS4_VERIFIER_SIZE) + \
+ XDR_QUADLEN(NFS4_SETCLIENTID_NAMELEN) + \
+ 1 /* sc_prog */ + \
+ XDR_QUADLEN(RPCBIND_MAXNETIDLEN) + \
+ XDR_QUADLEN(RPCBIND_MAXUADDRLEN) + \
+ 1) /* sc_cb_ident */
#define decode_setclientid_maxsz \
(op_decode_hdr_maxsz + \
2 + \
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 58751f3..d740dfa 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -666,16 +666,17 @@ struct nfs4_rename_res {
struct nfs_fattr * new_fattr;
};
+#define NFS4_SETCLIENTID_NAMELEN (48)
struct nfs4_setclientid {
- const nfs4_verifier * sc_verifier; /* request */
+ const nfs4_verifier * sc_verifier;
unsigned int sc_name_len;
- char sc_name[48]; /* request */
- u32 sc_prog; /* request */
+ char sc_name[NFS4_SETCLIENTID_NAMELEN];
+ u32 sc_prog;
unsigned int sc_netid_len;
- char sc_netid[4]; /* request */
+ char sc_netid[RPCBIND_MAXNETIDLEN];
unsigned int sc_uaddr_len;
- char sc_uaddr[24]; /* request */
- u32 sc_cb_ident; /* request */
+ char sc_uaddr[RPCBIND_MAXUADDRLEN];
+ u32 sc_cb_ident;
};
struct nfs4_statfs_arg {
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 06/27] NFS: Increase size of cl_ipaddr field to hold IPv6 addresses
[not found] ` <20071210195106.2823.43884.stgit-meopP2rzCrTwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (4 preceding siblings ...)
2007-12-10 19:56 ` [PATCH 05/27] NFS: Ensure NFSv4 SETCLIENTID send buffer is large enough Chuck Lever
@ 2007-12-10 19:57 ` Chuck Lever
2007-12-10 19:57 ` [PATCH 07/27] NFS: Enable NFS client to generate CLIENTID strings with " Chuck Lever
` (20 subsequent siblings)
26 siblings, 0 replies; 31+ messages in thread
From: Chuck Lever @ 2007-12-10 19:57 UTC (permalink / raw)
To: trond.myklebust; +Cc: aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ, linux-nfs
The nfs_client's cl_ipaddr field needs to be larger to hold strings that
represent IPv6 addresses.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Cc: Aurelien Charbon <aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ@public.gmane.org>
---
include/linux/nfs_fs_sb.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index 8a3061c..c64773f 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -63,7 +63,7 @@ struct nfs_client {
/* 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[48];
unsigned char cl_id_uniquifier;
#endif
};
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 07/27] NFS: Enable NFS client to generate CLIENTID strings with IPv6 addresses
[not found] ` <20071210195106.2823.43884.stgit-meopP2rzCrTwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (5 preceding siblings ...)
2007-12-10 19:57 ` [PATCH 06/27] NFS: Increase size of cl_ipaddr field to hold IPv6 addresses Chuck Lever
@ 2007-12-10 19:57 ` Chuck Lever
2007-12-10 19:57 ` [PATCH 08/27] NFS: eliminate NIPQUAD(clp->cl_addr.sin_addr) Chuck Lever
` (19 subsequent siblings)
26 siblings, 0 replies; 31+ messages in thread
From: Chuck Lever @ 2007-12-10 19:57 UTC (permalink / raw)
To: trond.myklebust; +Cc: aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ, linux-nfs
We recently added methods to RPC transports that provide string versions of
the remote peer address information. Convert the NFSv4 SETCLIENTID
procedure to use those methods instead of building the client ID out of
whole cloth.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Cc: Aurelien Charbon <aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ@public.gmane.org>
---
fs/nfs/nfs4proc.c | 12 ++++++++----
1 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index f03d9d5..ec58d1e 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2912,14 +2912,18 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, unsigned short po
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.sin_addr),
+ sizeof(setclientid.sc_name), "%s/%s %s %u",
+ clp->cl_ipaddr,
+ rpc_peeraddr2str(clp->cl_rpcclient,
+ RPC_DISPLAY_ADDR),
cred->cr_ops->cr_name,
clp->cl_id_uniquifier);
setclientid.sc_netid_len = scnprintf(setclientid.sc_netid,
- sizeof(setclientid.sc_netid), "tcp");
+ sizeof(setclientid.sc_netid),
+ rpc_peeraddr2str(clp->cl_rpcclient,
+ RPC_DISPLAY_NETID));
setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr,
- sizeof(setclientid.sc_uaddr), "%s.%d.%d",
+ sizeof(setclientid.sc_uaddr), "%s.%u.%u",
clp->cl_ipaddr, port >> 8, port & 255);
status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 08/27] NFS: eliminate NIPQUAD(clp->cl_addr.sin_addr)
[not found] ` <20071210195106.2823.43884.stgit-meopP2rzCrTwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (6 preceding siblings ...)
2007-12-10 19:57 ` [PATCH 07/27] NFS: Enable NFS client to generate CLIENTID strings with " Chuck Lever
@ 2007-12-10 19:57 ` Chuck Lever
2007-12-10 19:57 ` [PATCH 09/27] NFS: Move dprintks from callback.c to callback_proc.c Chuck Lever
` (18 subsequent siblings)
26 siblings, 0 replies; 31+ messages in thread
From: Chuck Lever @ 2007-12-10 19:57 UTC (permalink / raw)
To: trond.myklebust; +Cc: aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ, linux-nfs
To ensure the NFS client displays IPv6 addresses properly, replace
address family-specific NIPQUAD() invocations with a call to the RPC
client to get a formatted string representing the remote peer's
address.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Cc: Aurelien Charbon <aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ@public.gmane.org>
---
fs/nfs/client.c | 12 ++++++------
fs/nfs/delegation.c | 10 ++++++----
fs/nfs/nfs4state.c | 9 +++++----
fs/nfs/super.c | 5 +++--
4 files changed, 20 insertions(+), 16 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index b24b6db..5ab1ca1 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -1265,10 +1265,10 @@ static int nfs_server_list_show(struct seq_file *m, void *v)
/* display one transport per line on subsequent lines */
clp = list_entry(v, struct nfs_client, cl_share_link);
- seq_printf(m, "v%u %02x%02x%02x%02x %4hx %3d %s\n",
+ seq_printf(m, "v%u %s %s %3d %s\n",
clp->rpc_ops->version,
- NIPQUAD(clp->cl_addr.sin_addr),
- ntohs(clp->cl_addr.sin_port),
+ rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_ADDR),
+ rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_PORT),
atomic_read(&clp->cl_count),
clp->cl_hostname);
@@ -1344,10 +1344,10 @@ static int nfs_volume_list_show(struct seq_file *m, void *v)
(unsigned long long) server->fsid.major,
(unsigned long long) server->fsid.minor);
- seq_printf(m, "v%u %02x%02x%02x%02x %4hx %-7s %-17s\n",
+ seq_printf(m, "v%u %s %s %-7s %-17s\n",
clp->rpc_ops->version,
- NIPQUAD(clp->cl_addr.sin_addr),
- ntohs(clp->cl_addr.sin_port),
+ rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_ADDR),
+ rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_PORT),
dev,
fsid);
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 11833f4..b03dcd8 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -156,8 +156,9 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
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.sin_addr));
+ printk(KERN_WARNING "%s: server %s handed out "
+ "a duplicate delegation!\n",
+ __FUNCTION__, clp->cl_hostname);
status = -EIO;
}
}
@@ -314,8 +315,9 @@ void nfs_expire_all_delegations(struct nfs_client *clp)
__module_get(THIS_MODULE);
atomic_inc(&clp->cl_count);
task = kthread_run(nfs_do_expire_all_delegations, clp,
- "%u.%u.%u.%u-delegreturn",
- NIPQUAD(clp->cl_addr.sin_addr));
+ "%s-delegreturn",
+ rpc_peeraddr2str(clp->cl_rpcclient,
+ RPC_DISPLAY_ADDR));
if (!IS_ERR(task))
return;
nfs_put_client(clp);
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 23a9a36..86f95d4 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -755,8 +755,9 @@ static void nfs4_recover_state(struct nfs_client *clp)
__module_get(THIS_MODULE);
atomic_inc(&clp->cl_count);
- task = kthread_run(reclaimer, clp, "%u.%u.%u.%u-reclaim",
- NIPQUAD(clp->cl_addr.sin_addr));
+ task = kthread_run(reclaimer, clp, "%s-reclaim",
+ rpc_peeraddr2str(clp->cl_rpcclient,
+ RPC_DISPLAY_ADDR));
if (!IS_ERR(task))
return;
nfs4_clear_recover_bit(clp);
@@ -967,8 +968,8 @@ out:
module_put_and_exit(0);
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.sin_addr), -status);
+ printk(KERN_WARNING "Error: state recovery failed on NFSv4 server %s"
+ " with error %d\n", clp->cl_hostname, -status);
set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
goto out;
}
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 4fed577..6b004d8 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -467,8 +467,9 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
nfs_show_mount_options(m, nfss, 0);
- seq_printf(m, ",addr="NIPQUAD_FMT,
- NIPQUAD(nfss->nfs_client->cl_addr.sin_addr));
+ seq_printf(m, ",addr=%s",
+ rpc_peeraddr2str(nfss->nfs_client->cl_rpcclient,
+ RPC_DISPLAY_ADDR));
return 0;
}
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 09/27] NFS: Move dprintks from callback.c to callback_proc.c
[not found] ` <20071210195106.2823.43884.stgit-meopP2rzCrTwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (7 preceding siblings ...)
2007-12-10 19:57 ` [PATCH 08/27] NFS: eliminate NIPQUAD(clp->cl_addr.sin_addr) Chuck Lever
@ 2007-12-10 19:57 ` Chuck Lever
2007-12-10 19:57 ` [PATCH 10/27] NFS: Address a couple of nits in nfs_follow_referral() Chuck Lever
` (17 subsequent siblings)
26 siblings, 0 replies; 31+ messages in thread
From: Chuck Lever @ 2007-12-10 19:57 UTC (permalink / raw)
To: trond.myklebust; +Cc: aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ, linux-nfs
Clean up: The client side peer address is available in callback_proc.c,
so move a dprintk out of fs/nfs/callback.c and into
fs/nfs/callback_proc.c.
This is more consistent with other debugging messages, and the proc
routines have more information about each request to display.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Cc: Aurelien Charbon <aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ@public.gmane.org>
---
fs/nfs/callback.c | 4 ----
fs/nfs/callback_proc.c | 12 +++++++++++-
2 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index a796be5..bbf67f1 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -73,8 +73,6 @@ static void nfs_callback_svc(struct svc_rqst *rqstp)
complete(&nfs_callback_info.started);
for(;;) {
- char buf[RPC_MAX_ADDRBUFLEN];
-
if (signalled()) {
if (nfs_callback_info.users == 0)
break;
@@ -92,8 +90,6 @@ static void nfs_callback_svc(struct svc_rqst *rqstp)
__FUNCTION__, -err);
break;
}
- dprintk("%s: request from %s\n", __FUNCTION__,
- svc_print_addr(rqstp, buf, sizeof(buf)));
svc_process(rqstp);
}
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index 72e55d8..e89a900 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -12,7 +12,9 @@
#include "delegation.h"
#include "internal.h"
+#ifdef NFS_DEBUG
#define NFSDBG_FACILITY NFSDBG_CALLBACK
+#endif
__be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res)
{
@@ -20,12 +22,16 @@ __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *
struct nfs_delegation *delegation;
struct nfs_inode *nfsi;
struct inode *inode;
-
+
res->bitmap[0] = res->bitmap[1] = 0;
res->status = htonl(NFS4ERR_BADHANDLE);
clp = nfs_find_client(args->addr, 4);
if (clp == NULL)
goto out;
+
+ dprintk("NFS: GETATTR callback request from %s\n",
+ rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR));
+
inode = nfs_delegation_find_inode(clp, &args->fh);
if (inode == NULL)
goto out_putclient;
@@ -65,6 +71,10 @@ __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy)
clp = nfs_find_client(args->addr, 4);
if (clp == NULL)
goto out;
+
+ dprintk("NFS: RECALL callback request from %s\n",
+ rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR));
+
inode = nfs_delegation_find_inode(clp, &args->fh);
if (inode == NULL)
goto out_putclient;
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 10/27] NFS: Address a couple of nits in nfs_follow_referral()
[not found] ` <20071210195106.2823.43884.stgit-meopP2rzCrTwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (8 preceding siblings ...)
2007-12-10 19:57 ` [PATCH 09/27] NFS: Move dprintks from callback.c to callback_proc.c Chuck Lever
@ 2007-12-10 19:57 ` Chuck Lever
2007-12-10 19:57 ` [PATCH 11/27] NFS: Add support for AF_INET6 addresses in nfs_compare_super() Chuck Lever
` (16 subsequent siblings)
26 siblings, 0 replies; 31+ messages in thread
From: Chuck Lever @ 2007-12-10 19:57 UTC (permalink / raw)
To: trond.myklebust; +Cc: aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ, linux-nfs
Clean up: fix an outdated block comment, and address a comparison
between a signed and unsigned integer.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfs/nfs4namespace.c | 8 +++-----
1 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c
index dd5fef2..bd1b161 100644
--- a/fs/nfs/nfs4namespace.c
+++ b/fs/nfs/nfs4namespace.c
@@ -114,10 +114,7 @@ static inline int valid_ipaddr4(const char *buf)
* nfs_follow_referral - set up mountpoint when hitting a referral on moved error
* @mnt_parent - mountpoint of parent directory
* @dentry - parent directory
- * @fspath - fs path returned in fs_locations
- * @mntpath - mount path to new server
- * @hostname - hostname of new server
- * @addr - host addr of new server
+ * @locations - array of NFSv4 server location information
*
*/
static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent,
@@ -131,7 +128,8 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent,
.authflavor = NFS_SB(mnt_parent->mnt_sb)->client->cl_auth->au_flavor,
};
char *page = NULL, *page2 = NULL;
- int loc, s, error;
+ unsigned int s;
+ int loc, error;
if (locations == NULL || locations->nlocations <= 0)
goto out;
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 11/27] NFS: Add support for AF_INET6 addresses in nfs_compare_super()
[not found] ` <20071210195106.2823.43884.stgit-meopP2rzCrTwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (9 preceding siblings ...)
2007-12-10 19:57 ` [PATCH 10/27] NFS: Address a couple of nits in nfs_follow_referral() Chuck Lever
@ 2007-12-10 19:57 ` Chuck Lever
2007-12-10 19:57 ` [PATCH 12/27] NFS: Verify IPv6 addresses properly Chuck Lever
` (15 subsequent siblings)
26 siblings, 0 replies; 31+ messages in thread
From: Chuck Lever @ 2007-12-10 19:57 UTC (permalink / raw)
To: trond.myklebust; +Cc: aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ, linux-nfs
Refactor nfs_compare_super() and add AF_INET6 support.
Replace the generic memcmp() to document explicitly what parts of the
addresses must match in this check, and make the comparison independent
of the lengths of both addresses.
A side benefit is both tests are more computationally efficient than a
memcmp().
Note the "void *" casts are temporary.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfs/super.c | 43 ++++++++++++++++++++++++++++++++++++++++---
1 files changed, 40 insertions(+), 3 deletions(-)
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 6b004d8..6f1ed56 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -45,6 +45,8 @@
#include <linux/nfs_idmap.h>
#include <linux/vfs.h>
#include <linux/inet.h>
+#include <linux/in6.h>
+#include <net/ipv6.h>
#include <linux/nfs_xdr.h>
#include <linux/magic.h>
#include <linux/parser.h>
@@ -1302,15 +1304,50 @@ static int nfs_set_super(struct super_block *s, void *data)
return ret;
}
+static int nfs_compare_super_address(struct nfs_server *server1,
+ struct nfs_server *server2)
+{
+ struct sockaddr *sap1, *sap2;
+
+ sap1 = (struct sockaddr *)&server1->nfs_client->cl_addr;
+ sap2 = (struct sockaddr *)&server2->nfs_client->cl_addr;
+
+ if (sap1->sa_family != sap2->sa_family)
+ return 0;
+
+ switch (sap1->sa_family) {
+ case AF_INET: {
+ struct sockaddr_in *sin1 = (struct sockaddr_in *)sap1;
+ struct sockaddr_in *sin2 = (struct sockaddr_in *)sap2;
+ if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr)
+ return 0;
+ if (sin1->sin_port != sin2->sin_port)
+ return 0;
+ break;
+ }
+ case AF_INET6: {
+ struct sockaddr_in6 *sin1 = (struct sockaddr_in6 *)sap1;
+ struct sockaddr_in6 *sin2 = (struct sockaddr_in6 *)sap2;
+ if (!ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr))
+ return 0;
+ if (sin1->sin6_port != sin2->sin6_port)
+ return 0;
+ break;
+ }
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
static int nfs_compare_super(struct super_block *sb, void *data)
{
struct nfs_sb_mountdata *sb_mntdata = data;
struct nfs_server *server = sb_mntdata->server, *old = NFS_SB(sb);
int mntflags = sb_mntdata->mntflags;
- if (memcmp(&old->nfs_client->cl_addr,
- &server->nfs_client->cl_addr,
- sizeof(old->nfs_client->cl_addr)) != 0)
+ if (!nfs_compare_super_address(old, server))
return 0;
/* Note: NFS_MOUNT_UNSHARED == NFS4_MOUNT_UNSHARED */
if (old->flags & NFS_MOUNT_UNSHARED)
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 12/27] NFS: Verify IPv6 addresses properly
[not found] ` <20071210195106.2823.43884.stgit-meopP2rzCrTwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (10 preceding siblings ...)
2007-12-10 19:57 ` [PATCH 11/27] NFS: Add support for AF_INET6 addresses in nfs_compare_super() Chuck Lever
@ 2007-12-10 19:57 ` Chuck Lever
2007-12-10 19:57 ` [PATCH 13/27] NFS: Make setting a port number agostic Chuck Lever
` (14 subsequent siblings)
26 siblings, 0 replies; 31+ messages in thread
From: Chuck Lever @ 2007-12-10 19:57 UTC (permalink / raw)
To: trond.myklebust; +Cc: aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ, linux-nfs
Add support to nfs_verify_server_address for recognizing AF_INET6
addresses.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfs/super.c | 15 ++++++++++-----
1 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 6f1ed56..8bbdb85 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -576,16 +576,21 @@ static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags)
}
/*
- * Sanity-check a server address provided by the mount command
+ * Sanity-check a server address provided by the mount command.
+ *
+ * Address family must be initialized, and address must not be
+ * the ANY address for that family.
*/
static int nfs_verify_server_address(struct sockaddr *addr)
{
switch (addr->sa_family) {
case AF_INET: {
- struct sockaddr_in *sa = (struct sockaddr_in *) addr;
- if (sa->sin_addr.s_addr != INADDR_ANY)
- return 1;
- break;
+ struct sockaddr_in *sa = (struct sockaddr_in *)addr;
+ return sa->sin_addr.s_addr != INADDR_ANY;
+ }
+ case AF_INET6: {
+ struct in6_addr *sa = &((struct sockaddr_in6 *)addr)->sin6_addr;
+ return !ipv6_addr_any(sa);
}
}
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 13/27] NFS: Make setting a port number agostic
[not found] ` <20071210195106.2823.43884.stgit-meopP2rzCrTwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (11 preceding siblings ...)
2007-12-10 19:57 ` [PATCH 12/27] NFS: Verify IPv6 addresses properly Chuck Lever
@ 2007-12-10 19:57 ` Chuck Lever
2007-12-10 19:58 ` [PATCH 14/27] NFS: Set default port for NFSv4, with support for AF_INET6 Chuck Lever
` (13 subsequent siblings)
26 siblings, 0 replies; 31+ messages in thread
From: Chuck Lever @ 2007-12-10 19:57 UTC (permalink / raw)
To: trond.myklebust; +Cc: aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ, linux-nfs
We'll need to set the port number of an AF_INET or AF_INET6 address in
several places in fs/nfs/super.c, so introduce a helper that can manage
this for us. We put this helper to immediate use.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfs/super.c | 26 ++++++++++++++++++++++++--
1 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 8bbdb85..71eb5bc 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -576,6 +576,25 @@ static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags)
}
/*
+ * Set the port number in an address. Be agnostic about the address family.
+ */
+static void nfs_set_port(struct sockaddr *sap, unsigned short port)
+{
+ switch (sap->sa_family) {
+ case AF_INET: {
+ struct sockaddr_in *ap = (struct sockaddr_in *)sap;
+ ap->sin_port = htons(port);
+ break;
+ }
+ case AF_INET6: {
+ struct sockaddr_in6 *ap = (struct sockaddr_in6 *)sap;
+ ap->sin6_port = htons(port);
+ break;
+ }
+ }
+}
+
+/*
* Sanity-check a server address provided by the mount command.
*
* Address family must be initialized, and address must not be
@@ -605,6 +624,7 @@ static int nfs_parse_mount_options(char *raw,
struct nfs_parsed_mount_data *mnt)
{
char *p, *string;
+ unsigned short port = 0;
if (!raw) {
dfprintk(MOUNT, "NFS: mount options string was NULL.\n");
@@ -707,7 +727,7 @@ static int nfs_parse_mount_options(char *raw,
return 0;
if (option < 0 || option > 65535)
return 0;
- mnt->nfs_server.address.sin_port = htons(option);
+ port = option;
break;
case Opt_rsize:
if (match_int(args, &mnt->rsize))
@@ -949,6 +969,8 @@ static int nfs_parse_mount_options(char *raw,
}
}
+ nfs_set_port((struct sockaddr *)&mnt->nfs_server.address, port);
+
return 1;
out_nomem:
@@ -999,7 +1021,7 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args,
/*
* autobind will be used if mount_server.port == 0
*/
- sin.sin_port = htons(args->mount_server.port);
+ nfs_set_port((struct sockaddr *)&sin, args->mount_server.port);
/*
* Now ask the mount server to map our export path
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 14/27] NFS: Set default port for NFSv4, with support for AF_INET6
[not found] ` <20071210195106.2823.43884.stgit-meopP2rzCrTwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (12 preceding siblings ...)
2007-12-10 19:57 ` [PATCH 13/27] NFS: Make setting a port number agostic Chuck Lever
@ 2007-12-10 19:58 ` Chuck Lever
2007-12-10 19:58 ` [PATCH 15/27] NFS: Add support for AF_INET6 addresses in __nfs_find_client() Chuck Lever
` (12 subsequent siblings)
26 siblings, 0 replies; 31+ messages in thread
From: Chuck Lever @ 2007-12-10 19:58 UTC (permalink / raw)
To: trond.myklebust; +Cc: aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ, linux-nfs
Create a helper function to set the default NFS port for NFSv4 mount
points. The helper supports both AF_INET and AF_INET6 family addresses.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfs/super.c | 32 ++++++++++++++++++++++++++++----
1 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 71eb5bc..62ba379 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -1572,6 +1572,28 @@ static void nfs4_fill_super(struct super_block *sb)
}
/*
+ * If the user didn't specify a port, set the port number to
+ * the NFS version 4 default port.
+ */
+static void nfs4_default_port(struct sockaddr *sap)
+{
+ switch (sap->sa_family) {
+ case AF_INET: {
+ struct sockaddr_in *ap = (struct sockaddr_in *)sap;
+ if (ap->sin_port == 0)
+ ap->sin_port = htons(NFS_PORT);
+ break;
+ }
+ case AF_INET6: {
+ struct sockaddr_in6 *ap = (struct sockaddr_in6 *)sap;
+ if (ap->sin6_port == 0)
+ ap->sin6_port = htons(NFS_PORT);
+ break;
+ }
+ }
+}
+
+/*
* Validate NFSv4 mount options
*/
static int nfs4_validate_mount_data(void *options,
@@ -1604,12 +1626,13 @@ static int nfs4_validate_mount_data(void *options,
data->host_addr,
sizeof(args->nfs_server.address)))
return -EFAULT;
- if (args->nfs_server.address.sin_port == 0)
- args->nfs_server.address.sin_port = htons(NFS_PORT);
if (!nfs_verify_server_address((struct sockaddr *)
&args->nfs_server.address))
goto out_no_address;
+ nfs4_default_port((struct sockaddr *)
+ &args->nfs_server.address);
+
switch (data->auth_flavourlen) {
case 0:
args->auth_flavors[0] = RPC_AUTH_UNIX;
@@ -1663,12 +1686,13 @@ static int nfs4_validate_mount_data(void *options,
if (nfs_parse_mount_options((char *)options, args) == 0)
return -EINVAL;
- if (args->nfs_server.address.sin_port == 0)
- args->nfs_server.address.sin_port = htons(NFS_PORT);
if (!nfs_verify_server_address((struct sockaddr *)
&args->nfs_server.address))
return -EINVAL;
+ nfs4_default_port((struct sockaddr *)
+ &args->nfs_server.address);
+
switch (args->auth_flavor_len) {
case 0:
args->auth_flavors[0] = RPC_AUTH_UNIX;
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 15/27] NFS: Add support for AF_INET6 addresses in __nfs_find_client()
[not found] ` <20071210195106.2823.43884.stgit-meopP2rzCrTwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (13 preceding siblings ...)
2007-12-10 19:58 ` [PATCH 14/27] NFS: Set default port for NFSv4, with support for AF_INET6 Chuck Lever
@ 2007-12-10 19:58 ` Chuck Lever
2007-12-10 19:58 ` [PATCH 16/27] NFS: Expand server address storage in nfs_client struct Chuck Lever
` (11 subsequent siblings)
26 siblings, 0 replies; 31+ messages in thread
From: Chuck Lever @ 2007-12-10 19:58 UTC (permalink / raw)
To: trond.myklebust; +Cc: aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ, linux-nfs
Introduce AF_INET6-specific address checking to __nfs_find_client().
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Cc: Aurelien Charbon <aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ@public.gmane.org>
---
fs/nfs/client.c | 36 ++++++++++++++++++++++++++++++------
1 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 5ab1ca1..a37f01a 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -34,6 +34,8 @@
#include <linux/nfs_idmap.h>
#include <linux/vfs.h>
#include <linux/inet.h>
+#include <linux/in6.h>
+#include <net/ipv6.h>
#include <linux/nfs_xdr.h>
#include <asm/system.h>
@@ -207,13 +209,15 @@ void nfs_put_client(struct nfs_client *clp)
* Find a client by address
* - caller must hold nfs_client_lock
*/
-static struct nfs_client *__nfs_find_client(const struct sockaddr_in *addr,
+static struct nfs_client *__nfs_find_client(const struct sockaddr *addr,
unsigned int nfsversion,
int match_port)
{
struct nfs_client *clp;
list_for_each_entry(clp, &nfs_client_list, cl_share_link) {
+ struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr;
+
/* Don't match clients that failed to initialise properly */
if (clp->cl_cons_state < 0)
continue;
@@ -222,11 +226,31 @@ static struct nfs_client *__nfs_find_client(const struct sockaddr_in *addr,
if (clp->rpc_ops->version != nfsversion)
continue;
- if (clp->cl_addr.sin_addr.s_addr != addr->sin_addr.s_addr)
+ if (clap->sa_family != addr->sa_family)
continue;
- if (!match_port || clp->cl_addr.sin_port == addr->sin_port)
- goto found;
+ switch (addr->sa_family) {
+ case AF_INET: {
+ struct sockaddr_in *sap = (struct sockaddr_in *)clap;
+ struct sockaddr_in *ap = (struct sockaddr_in *)addr;
+ if (sap->sin_addr.s_addr != ap->sin_addr.s_addr)
+ continue;
+ if (!match_port || sap->sin_port == ap->sin_port)
+ goto found;
+ continue;
+ }
+ case AF_INET6: {
+ struct sockaddr_in6 *sap = (struct sockaddr_in6 *)clap;
+ struct sockaddr_in6 *ap = (struct sockaddr_in6 *)addr;
+ if (!ipv6_addr_equal(&sap->sin6_addr, &ap->sin6_addr))
+ continue;
+ if (!match_port || sap->sin6_port == ap->sin6_port)
+ goto found;
+ continue;
+ }
+ default:
+ BUG();
+ }
}
return NULL;
@@ -246,7 +270,7 @@ struct nfs_client *nfs_find_client(const struct sockaddr_in *addr,
struct nfs_client *clp;
spin_lock(&nfs_client_lock);
- clp = __nfs_find_client(addr, nfsversion, 0);
+ clp = __nfs_find_client((struct sockaddr *)addr, nfsversion, 0);
spin_unlock(&nfs_client_lock);
if (clp != NULL && clp->cl_cons_state != NFS_CS_READY) {
nfs_put_client(clp);
@@ -274,7 +298,7 @@ static struct nfs_client *nfs_get_client(const char *hostname,
do {
spin_lock(&nfs_client_lock);
- clp = __nfs_find_client(addr, nfsversion, 1);
+ clp = __nfs_find_client((struct sockaddr *)addr, nfsversion, 1);
if (clp)
goto found_client;
if (new)
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 16/27] NFS: Expand server address storage in nfs_client struct
[not found] ` <20071210195106.2823.43884.stgit-meopP2rzCrTwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (14 preceding siblings ...)
2007-12-10 19:58 ` [PATCH 15/27] NFS: Add support for AF_INET6 addresses in __nfs_find_client() Chuck Lever
@ 2007-12-10 19:58 ` Chuck Lever
2007-12-10 19:58 ` [PATCH 17/27] NFS: Change cb_getattrargs to pass "struct sockaddr *" instead of sockaddr_in Chuck Lever
` (10 subsequent siblings)
26 siblings, 0 replies; 31+ messages in thread
From: Chuck Lever @ 2007-12-10 19:58 UTC (permalink / raw)
To: trond.myklebust; +Cc: aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ, linux-nfs
Prepare for managing larger addresses in the NFS client by widening the
nfs_client struct's cl_addr field.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Cc: Aurelien Charbon <aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ@public.gmane.org>
---
fs/nfs/client.c | 5 +++--
include/linux/nfs_fs_sb.h | 3 ++-
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index a37f01a..4da1014 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -119,7 +119,8 @@ static struct nfs_client *nfs_alloc_client(const char *hostname,
atomic_set(&clp->cl_count, 1);
clp->cl_cons_state = NFS_CS_INITING;
- memcpy(&clp->cl_addr, addr, sizeof(clp->cl_addr));
+ memcpy(&clp->cl_addr, addr, sizeof(*addr));
+ clp->cl_addrlen = sizeof(*addr);
if (hostname) {
clp->cl_hostname = kstrdup(hostname, GFP_KERNEL);
@@ -404,7 +405,7 @@ static int nfs_create_rpc_client(struct nfs_client *clp, int proto,
struct rpc_create_args args = {
.protocol = proto,
.address = (struct sockaddr *)&clp->cl_addr,
- .addrsize = sizeof(clp->cl_addr),
+ .addrsize = clp->cl_addrlen,
.timeout = &timeparms,
.servername = clp->cl_hostname,
.program = &nfs_program,
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index c64773f..383abe0 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -20,7 +20,8 @@ struct nfs_client {
#define NFS_CS_IDMAP 2 /* - idmap started */
#define NFS_CS_RENEWD 3 /* - renewd started */
- struct sockaddr_in cl_addr; /* server identifier */
+ struct sockaddr_storage cl_addr; /* server identifier */
+ size_t cl_addrlen;
char * cl_hostname; /* hostname of server */
struct list_head cl_share_link; /* link in global client list */
struct list_head cl_superblocks; /* List of nfs_server structs */
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 17/27] NFS: Change cb_getattrargs to pass "struct sockaddr *" instead of sockaddr_in
[not found] ` <20071210195106.2823.43884.stgit-meopP2rzCrTwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (15 preceding siblings ...)
2007-12-10 19:58 ` [PATCH 16/27] NFS: Expand server address storage in nfs_client struct Chuck Lever
@ 2007-12-10 19:58 ` Chuck Lever
2007-12-10 19:58 ` [PATCH 18/27] NFS: Change cb_recallargs " Chuck Lever
` (9 subsequent siblings)
26 siblings, 0 replies; 31+ messages in thread
From: Chuck Lever @ 2007-12-10 19:58 UTC (permalink / raw)
To: trond.myklebust; +Cc: aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ, linux-nfs
Change the addr field in the cb_getattrargs struct to a "struct sockaddr *"
to support non-IPv4 addresses.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Cc: Aurelien Charbon <aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ@public.gmane.org>
---
fs/nfs/callback.h | 2 +-
fs/nfs/callback_proc.c | 2 +-
fs/nfs/callback_xdr.c | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
index c2bb14e..ec0ffd9 100644
--- a/fs/nfs/callback.h
+++ b/fs/nfs/callback.h
@@ -38,7 +38,7 @@ struct cb_compound_hdr_res {
};
struct cb_getattrargs {
- struct sockaddr_in *addr;
+ struct sockaddr *addr;
struct nfs_fh fh;
uint32_t bitmap[2];
};
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index e89a900..32f0df0 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -25,7 +25,7 @@ __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *
res->bitmap[0] = res->bitmap[1] = 0;
res->status = htonl(NFS4ERR_BADHANDLE);
- clp = nfs_find_client(args->addr, 4);
+ clp = nfs_find_client((struct sockaddr_in *)args->addr, 4);
if (clp == NULL)
goto out;
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index 97abd82..3eda1bc 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -176,7 +176,7 @@ static __be32 decode_getattr_args(struct svc_rqst *rqstp, struct xdr_stream *xdr
status = decode_fh(xdr, &args->fh);
if (unlikely(status != 0))
goto out;
- args->addr = svc_addr_in(rqstp);
+ args->addr = svc_addr(rqstp);
status = decode_bitmap(xdr, args->bitmap);
out:
dprintk("%s: exit with status = %d\n", __FUNCTION__, ntohl(status));
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 18/27] NFS: Change cb_recallargs to pass "struct sockaddr *" instead of sockaddr_in
[not found] ` <20071210195106.2823.43884.stgit-meopP2rzCrTwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (16 preceding siblings ...)
2007-12-10 19:58 ` [PATCH 17/27] NFS: Change cb_getattrargs to pass "struct sockaddr *" instead of sockaddr_in Chuck Lever
@ 2007-12-10 19:58 ` Chuck Lever
2007-12-10 19:58 ` [PATCH 19/27] NFS: Make nfs_alloc_client() take (sockaddr, len) " Chuck Lever
` (8 subsequent siblings)
26 siblings, 0 replies; 31+ messages in thread
From: Chuck Lever @ 2007-12-10 19:58 UTC (permalink / raw)
To: trond.myklebust; +Cc: aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ, linux-nfs
Change the addr field in the cb_recallargs struct to a "struct sockaddr *"
to support non-IPv4 addresses.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Cc: Aurelien Charbon <aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ@public.gmane.org>
---
fs/nfs/callback.h | 2 +-
fs/nfs/callback_proc.c | 2 +-
fs/nfs/callback_xdr.c | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
index ec0ffd9..bb25d21 100644
--- a/fs/nfs/callback.h
+++ b/fs/nfs/callback.h
@@ -53,7 +53,7 @@ struct cb_getattrres {
};
struct cb_recallargs {
- struct sockaddr_in *addr;
+ struct sockaddr *addr;
struct nfs_fh fh;
nfs4_stateid stateid;
uint32_t truncate;
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index 32f0df0..fa9586d 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -68,7 +68,7 @@ __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy)
__be32 res;
res = htonl(NFS4ERR_BADHANDLE);
- clp = nfs_find_client(args->addr, 4);
+ clp = nfs_find_client((struct sockaddr_in *)args->addr, 4);
if (clp == NULL)
goto out;
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index 3eda1bc..c63eb72 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -188,7 +188,7 @@ static __be32 decode_recall_args(struct svc_rqst *rqstp, struct xdr_stream *xdr,
__be32 *p;
__be32 status;
- args->addr = svc_addr_in(rqstp);
+ args->addr = svc_addr(rqstp);
status = decode_stateid(xdr, &args->stateid);
if (unlikely(status != 0))
goto out;
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 19/27] NFS: Make nfs_alloc_client() take (sockaddr, len) instead of sockaddr_in
[not found] ` <20071210195106.2823.43884.stgit-meopP2rzCrTwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (17 preceding siblings ...)
2007-12-10 19:58 ` [PATCH 18/27] NFS: Change cb_recallargs " Chuck Lever
@ 2007-12-10 19:58 ` Chuck Lever
2007-12-10 19:58 ` [PATCH 20/27] NFS: Change nfs_find_client() to take "struct sockaddr *" Chuck Lever
` (7 subsequent siblings)
26 siblings, 0 replies; 31+ messages in thread
From: Chuck Lever @ 2007-12-10 19:58 UTC (permalink / raw)
To: trond.myklebust; +Cc: aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ, linux-nfs
To support non-IPv4 addresses, adjust the arguments and callers of
nfs_alloc_client() to pass in a "struct sockaddr *" instead of a
"struct sockaddr_in *".
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Cc: Aurelien Charbon <aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ@public.gmane.org>
---
fs/nfs/client.c | 12 ++++++++----
1 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 4da1014..e904e5f 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -102,7 +102,8 @@ struct rpc_program nfsacl_program = {
* bother putting them in a slab cache...
*/
static struct nfs_client *nfs_alloc_client(const char *hostname,
- const struct sockaddr_in *addr,
+ const struct sockaddr *addr,
+ size_t addrlen,
unsigned int nfsversion)
{
struct nfs_client *clp;
@@ -119,8 +120,8 @@ static struct nfs_client *nfs_alloc_client(const char *hostname,
atomic_set(&clp->cl_count, 1);
clp->cl_cons_state = NFS_CS_INITING;
- memcpy(&clp->cl_addr, addr, sizeof(*addr));
- clp->cl_addrlen = sizeof(*addr);
+ memcpy(&clp->cl_addr, addr, addrlen);
+ clp->cl_addrlen = addrlen;
if (hostname) {
clp->cl_hostname = kstrdup(hostname, GFP_KERNEL);
@@ -307,7 +308,10 @@ static struct nfs_client *nfs_get_client(const char *hostname,
spin_unlock(&nfs_client_lock);
- new = nfs_alloc_client(hostname, addr, nfsversion);
+ new = nfs_alloc_client(hostname,
+ (const struct sockaddr *)addr,
+ sizeof(*addr),
+ nfsversion);
} while (new);
return ERR_PTR(-ENOMEM);
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 20/27] NFS: Change nfs_find_client() to take "struct sockaddr *"
[not found] ` <20071210195106.2823.43884.stgit-meopP2rzCrTwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (18 preceding siblings ...)
2007-12-10 19:58 ` [PATCH 19/27] NFS: Make nfs_alloc_client() take (sockaddr, len) " Chuck Lever
@ 2007-12-10 19:58 ` Chuck Lever
2007-12-10 19:58 ` [PATCH 21/27] NFS: Change nfs_get_client() to take sockaddr * Chuck Lever
` (6 subsequent siblings)
26 siblings, 0 replies; 31+ messages in thread
From: Chuck Lever @ 2007-12-10 19:58 UTC (permalink / raw)
To: trond.myklebust; +Cc: aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ, linux-nfs
Adjust arguments and callers of nfs_find_client() to pass a
"struct sockaddr *" instead of "struct sockaddr_in *" to support non-IPv4
addresses.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Cc: Aurelien Charbon <aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ@public.gmane.org>
---
fs/nfs/callback.c | 3 +--
fs/nfs/callback_proc.c | 4 ++--
fs/nfs/client.c | 4 ++--
fs/nfs/internal.h | 2 +-
4 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index bbf67f1..9b6bbf1 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -164,12 +164,11 @@ void nfs_callback_down(void)
static int nfs_callback_authenticate(struct svc_rqst *rqstp)
{
- struct sockaddr_in *addr = svc_addr_in(rqstp);
struct nfs_client *clp;
char buf[RPC_MAX_ADDRBUFLEN];
/* Don't talk to strangers */
- clp = nfs_find_client(addr, 4);
+ clp = nfs_find_client(svc_addr(rqstp), 4);
if (clp == NULL)
return SVC_DROP;
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index fa9586d..e89a900 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -25,7 +25,7 @@ __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *
res->bitmap[0] = res->bitmap[1] = 0;
res->status = htonl(NFS4ERR_BADHANDLE);
- clp = nfs_find_client((struct sockaddr_in *)args->addr, 4);
+ clp = nfs_find_client(args->addr, 4);
if (clp == NULL)
goto out;
@@ -68,7 +68,7 @@ __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy)
__be32 res;
res = htonl(NFS4ERR_BADHANDLE);
- clp = nfs_find_client((struct sockaddr_in *)args->addr, 4);
+ clp = nfs_find_client(args->addr, 4);
if (clp == NULL)
goto out;
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index e904e5f..48fbacd 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -266,13 +266,13 @@ found:
* Find a client by IP address and protocol version
* - returns NULL if no such client
*/
-struct nfs_client *nfs_find_client(const struct sockaddr_in *addr,
+struct nfs_client *nfs_find_client(const struct sockaddr *addr,
unsigned int nfsversion)
{
struct nfs_client *clp;
spin_lock(&nfs_client_lock);
- clp = __nfs_find_client((struct sockaddr *)addr, nfsversion, 0);
+ clp = __nfs_find_client(addr, nfsversion, 0);
spin_unlock(&nfs_client_lock);
if (clp != NULL && clp->cl_cons_state != NFS_CS_READY) {
nfs_put_client(clp);
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index c065dc3..8b96364 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -61,7 +61,7 @@ extern struct rpc_program nfs_program;
extern void nfs_put_client(struct nfs_client *);
extern struct nfs_client *nfs_find_client(
- const struct sockaddr_in *,
+ const struct sockaddr *,
unsigned int);
extern struct nfs_server *nfs_create_server(
const struct nfs_parsed_mount_data *,
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 21/27] NFS: Change nfs_get_client() to take sockaddr *
[not found] ` <20071210195106.2823.43884.stgit-meopP2rzCrTwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (19 preceding siblings ...)
2007-12-10 19:58 ` [PATCH 20/27] NFS: Change nfs_find_client() to take "struct sockaddr *" Chuck Lever
@ 2007-12-10 19:58 ` Chuck Lever
2007-12-10 19:58 ` [PATCH 22/27] NFS: Change nfs4_set_client() to accept struct " Chuck Lever
` (5 subsequent siblings)
26 siblings, 0 replies; 31+ messages in thread
From: Chuck Lever @ 2007-12-10 19:58 UTC (permalink / raw)
To: trond.myklebust; +Cc: aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ, linux-nfs
Adjust arguments and callers of nfs_get_client() to pass a
"struct sockaddr *" instead of "struct sockaddr_in *" to support
non-IPv4 addresses.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Cc: Aurelien Charbon <aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ@public.gmane.org>
---
fs/nfs/client.c | 22 +++++++++++-----------
1 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 48fbacd..6a49ae7 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -286,21 +286,21 @@ struct nfs_client *nfs_find_client(const struct sockaddr *addr,
* - creates a new record if one doesn't yet exist
*/
static struct nfs_client *nfs_get_client(const char *hostname,
- const struct sockaddr_in *addr,
+ const struct sockaddr *addr,
+ size_t addrlen,
unsigned int nfsversion)
{
struct nfs_client *clp, *new = NULL;
int error;
- dprintk("--> nfs_get_client(%s,"NIPQUAD_FMT":%d,%u)\n",
- hostname ?: "", NIPQUAD(addr->sin_addr),
- addr->sin_port, nfsversion);
+ dprintk("--> nfs_get_client(%s,v%u)\n",
+ hostname ?: "", nfsversion);
/* see if the client already exists */
do {
spin_lock(&nfs_client_lock);
- clp = __nfs_find_client((struct sockaddr *)addr, nfsversion, 1);
+ clp = __nfs_find_client(addr, nfsversion, 1);
if (clp)
goto found_client;
if (new)
@@ -308,10 +308,7 @@ static struct nfs_client *nfs_get_client(const char *hostname,
spin_unlock(&nfs_client_lock);
- new = nfs_alloc_client(hostname,
- (const struct sockaddr *)addr,
- sizeof(*addr),
- nfsversion);
+ new = nfs_alloc_client(hostname, addr, addrlen, nfsversion);
} while (new);
return ERR_PTR(-ENOMEM);
@@ -587,7 +584,9 @@ static int nfs_init_server(struct nfs_server *server,
/* Allocate or find a client reference we can use */
clp = nfs_get_client(data->nfs_server.hostname,
- &data->nfs_server.address, nfsvers);
+ (struct sockaddr *)&data->nfs_server.address,
+ sizeof(data->nfs_server.address),
+ nfsvers);
if (IS_ERR(clp)) {
dprintk("<-- nfs_init_server() = error %ld\n", PTR_ERR(clp));
return PTR_ERR(clp);
@@ -924,7 +923,8 @@ static int nfs4_set_client(struct nfs_server *server,
dprintk("--> nfs4_set_client()\n");
/* Allocate or find a client reference we can use */
- clp = nfs_get_client(hostname, addr, 4);
+ clp = nfs_get_client(hostname, (struct sockaddr *)addr,
+ sizeof(*addr), 4);
if (IS_ERR(clp)) {
error = PTR_ERR(clp);
goto error;
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 22/27] NFS: Change nfs4_set_client() to accept struct sockaddr *
[not found] ` <20071210195106.2823.43884.stgit-meopP2rzCrTwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (20 preceding siblings ...)
2007-12-10 19:58 ` [PATCH 21/27] NFS: Change nfs_get_client() to take sockaddr * Chuck Lever
@ 2007-12-10 19:58 ` Chuck Lever
2007-12-10 19:59 ` [PATCH 23/27] NFS: Adjust nfs_clone_mount structure to store "struct sockaddr *" Chuck Lever
` (4 subsequent siblings)
26 siblings, 0 replies; 31+ messages in thread
From: Chuck Lever @ 2007-12-10 19:58 UTC (permalink / raw)
To: trond.myklebust; +Cc: aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ, linux-nfs
Adjust the arguments and callers of nfs4_set_client() to pass a "struct
sockaddr *" instead of a "struct sockaddr_in *" to support non-IPv4
addresses in the NFS client.
Clean-up: remove a comment that suggests NFSv4 always uses TCP, since
that's not true. On Linux, it can use UDP. And RFC 3530, section 3.1
mandates only that the transport support congestion control.
Quote:
Where an NFS version 4 implementation supports operation over the IP
network protocol, the supported transports between NFS and IP MUST be
among the IETF-approved congestion control transport protocols, which
include TCP and SCTP.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Cc: Aurelien Charbon <aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ@public.gmane.org>
---
fs/nfs/client.c | 27 +++++++++++++++------------
1 files changed, 15 insertions(+), 12 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 6a49ae7..db703b0 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -912,7 +912,9 @@ error:
* Set up an NFS4 client
*/
static int nfs4_set_client(struct nfs_server *server,
- const char *hostname, const struct sockaddr_in *addr,
+ const char *hostname,
+ const struct sockaddr *addr,
+ const size_t addrlen,
const char *ip_addr,
rpc_authflavor_t authflavour,
int proto, int timeo, int retrans)
@@ -923,8 +925,7 @@ static int nfs4_set_client(struct nfs_server *server,
dprintk("--> nfs4_set_client()\n");
/* Allocate or find a client reference we can use */
- clp = nfs_get_client(hostname, (struct sockaddr *)addr,
- sizeof(*addr), 4);
+ clp = nfs_get_client(hostname, addr, addrlen, 4);
if (IS_ERR(clp)) {
error = PTR_ERR(clp);
goto error;
@@ -995,7 +996,8 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
/* Get a client record */
error = nfs4_set_client(server,
data->nfs_server.hostname,
- &data->nfs_server.address,
+ (struct sockaddr *)&data->nfs_server.address,
+ sizeof(data->nfs_server.address),
data->client_address,
data->auth_flavors[0],
data->nfs_server.protocol,
@@ -1068,14 +1070,15 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
parent_server = NFS_SB(data->sb);
parent_client = parent_server->nfs_client;
- /* Get a client representation.
- * Note: NFSv4 always uses TCP, */
- error = nfs4_set_client(server, data->hostname, data->addr,
- parent_client->cl_ipaddr,
- data->authflavor,
- parent_server->client->cl_xprt->prot,
- parent_client->retrans_timeo,
- parent_client->retrans_count);
+ /* Get a client representation */
+ error = nfs4_set_client(server, data->hostname,
+ (struct sockaddr *)data->addr,
+ sizeof(*data->addr),
+ parent_client->cl_ipaddr,
+ data->authflavor,
+ parent_server->client->cl_xprt->prot,
+ parent_client->retrans_timeo,
+ parent_client->retrans_count);
if (error < 0)
goto error;
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 23/27] NFS: Adjust nfs_clone_mount structure to store "struct sockaddr *"
[not found] ` <20071210195106.2823.43884.stgit-meopP2rzCrTwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (21 preceding siblings ...)
2007-12-10 19:58 ` [PATCH 22/27] NFS: Change nfs4_set_client() to accept struct " Chuck Lever
@ 2007-12-10 19:59 ` Chuck Lever
2007-12-10 19:59 ` [PATCH 24/27] NFS: Remove the NIPQUAD from nfs_try_mount Chuck Lever
` (3 subsequent siblings)
26 siblings, 0 replies; 31+ messages in thread
From: Chuck Lever @ 2007-12-10 19:59 UTC (permalink / raw)
To: trond.myklebust; +Cc: aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ, linux-nfs
Change the addr field in the nfs_clone_mount structure to store a "struct
sockaddr *" to support non-IPv4 addresses in the NFS client.
Note this is mostly a cosmetic change, and does not actually allow
referrals using IPv6 addresses. The existing referral code assumes that
the server returns a string that represents an IPv4 address. This code
needs to support hostnames and IPv6 addresses as well as IPv4 addresses,
thus it will need to be reorganized completely (to handle DNS resolution
in user space).
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Cc: Aurelien Charbon <aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ@public.gmane.org>
---
fs/nfs/client.c | 4 ++--
fs/nfs/internal.h | 3 ++-
fs/nfs/nfs4namespace.c | 12 +++++++-----
3 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index db703b0..5406410 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -1072,8 +1072,8 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
/* Get a client representation */
error = nfs4_set_client(server, data->hostname,
- (struct sockaddr *)data->addr,
- sizeof(*data->addr),
+ data->addr,
+ data->addrlen,
parent_client->cl_ipaddr,
data->authflavor,
parent_server->client->cl_xprt->prot,
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 8b96364..b54ed13 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -21,7 +21,8 @@ struct nfs_clone_mount {
struct nfs_fattr *fattr;
char *hostname;
char *mnt_path;
- struct sockaddr_in *addr;
+ struct sockaddr *addr;
+ size_t addrlen;
rpc_authflavor_t authflavor;
};
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c
index bd1b161..5f9ba41 100644
--- a/fs/nfs/nfs4namespace.c
+++ b/fs/nfs/nfs4namespace.c
@@ -172,7 +172,10 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent,
s = 0;
while (s < location->nservers) {
- struct sockaddr_in addr = {};
+ struct sockaddr_in addr = {
+ .sin_family = AF_INET,
+ .sin_port = htons(NFS_PORT),
+ };
if (location->servers[s].len <= 0 ||
valid_ipaddr4(location->servers[s].data) < 0) {
@@ -181,10 +184,9 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent,
}
mountdata.hostname = location->servers[s].data;
- addr.sin_addr.s_addr = in_aton(mountdata.hostname);
- addr.sin_family = AF_INET;
- addr.sin_port = htons(NFS_PORT);
- mountdata.addr = &addr;
+ addr.sin_addr.s_addr = in_aton(mountdata.hostname),
+ mountdata.addr = (struct sockaddr *)&addr;
+ mountdata.addrlen = sizeof(addr);
snprintf(page, PAGE_SIZE, "%s:%s",
mountdata.hostname,
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 24/27] NFS: Remove the NIPQUAD from nfs_try_mount
[not found] ` <20071210195106.2823.43884.stgit-meopP2rzCrTwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (22 preceding siblings ...)
2007-12-10 19:59 ` [PATCH 23/27] NFS: Adjust nfs_clone_mount structure to store "struct sockaddr *" Chuck Lever
@ 2007-12-10 19:59 ` Chuck Lever
2007-12-10 19:59 ` [PATCH 25/27] NFS: Refactor mount option address parsing into separate function Chuck Lever
` (2 subsequent siblings)
26 siblings, 0 replies; 31+ messages in thread
From: Chuck Lever @ 2007-12-10 19:59 UTC (permalink / raw)
To: trond.myklebust; +Cc: aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ, linux-nfs
In the name of address family compatibility, we can't have the NIP_FMT and
NIPQUAD macros in nfs_try_mount(). Instead, we can make use of an unused
mount option to display the mount server's hostname.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Cc: Aurelien Charbon <aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ@public.gmane.org>
---
fs/nfs/super.c | 23 ++++++++++++++++++-----
1 files changed, 18 insertions(+), 5 deletions(-)
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 62ba379..4a3a5c0 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -89,7 +89,7 @@ enum {
Opt_nfsvers,
/* Mount options that take string arguments */
- Opt_sec, Opt_proto, Opt_mountproto,
+ Opt_sec, Opt_proto, Opt_mountproto, Opt_mounthost,
Opt_addr, Opt_mountaddr, Opt_clientaddr,
/* Mount options that are ignored */
@@ -148,7 +148,7 @@ static match_table_t nfs_mount_option_tokens = {
{ Opt_mountproto, "mountproto=%s" },
{ Opt_addr, "addr=%s" },
{ Opt_clientaddr, "clientaddr=%s" },
- { Opt_userspace, "mounthost=%s" },
+ { Opt_mounthost, "mounthost=%s" },
{ Opt_mountaddr, "mountaddr=%s" },
{ Opt_err, NULL }
@@ -950,6 +950,12 @@ static int nfs_parse_mount_options(char *raw,
goto out_nomem;
mnt->client_address = string;
break;
+ case Opt_mounthost:
+ string = match_strdup(args);
+ if (string == NULL)
+ goto out_nomem;
+ mnt->mount_server.hostname = string;
+ break;
case Opt_mountaddr:
string = match_strdup(args);
if (string == NULL)
@@ -1003,6 +1009,7 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args,
{
struct sockaddr_in sin;
int status;
+ char *hostname;
if (args->mount_server.version == 0) {
if (args->flags & NFS_MOUNT_VER3)
@@ -1011,6 +1018,11 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args,
args->mount_server.version = NFS_MNT_VERSION;
}
+ if (args->mount_server.hostname)
+ hostname = args->mount_server.hostname;
+ else
+ hostname = args->nfs_server.hostname;
+
/*
* Construct the mount server's address.
*/
@@ -1029,7 +1041,7 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args,
*/
status = nfs_mount((struct sockaddr *) &sin,
sizeof(sin),
- args->nfs_server.hostname,
+ hostname,
args->nfs_server.export_path,
args->mount_server.version,
args->mount_server.protocol,
@@ -1037,8 +1049,8 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args,
if (status == 0)
return 0;
- dfprintk(MOUNT, "NFS: unable to mount server " NIPQUAD_FMT
- ", error %d\n", NIPQUAD(sin.sin_addr.s_addr), status);
+ dfprintk(MOUNT, "NFS: unable to mount server %s, error %d",
+ hostname, status);
return status;
}
@@ -1444,6 +1456,7 @@ static int nfs_get_sb(struct file_system_type *fs_type,
out:
kfree(data.nfs_server.hostname);
+ kfree(data.mount_server.hostname);
return error;
out_err_nosb:
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 25/27] NFS: Refactor mount option address parsing into separate function
[not found] ` <20071210195106.2823.43884.stgit-meopP2rzCrTwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (23 preceding siblings ...)
2007-12-10 19:59 ` [PATCH 24/27] NFS: Remove the NIPQUAD from nfs_try_mount Chuck Lever
@ 2007-12-10 19:59 ` Chuck Lever
2007-12-10 19:59 ` [PATCH 26/27] NFS: Support non-IPv4 addresses in nfs_parsed_mount_data Chuck Lever
2007-12-10 19:59 ` [PATCH 27/27] NFS: Pull covers off IPv6 address parsing Chuck Lever
26 siblings, 0 replies; 31+ messages in thread
From: Chuck Lever @ 2007-12-10 19:59 UTC (permalink / raw)
To: trond.myklebust; +Cc: aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ, linux-nfs
Refactor the logic to parse incoming text-based IP addresses. Use the
in4_pton() function instead of the older in_aton(), following the lead
of the in-kernel CIFS client.
Later we'll add IPv6 address parsing using the matching in6_pton()
function. For now we can't allow IPv6 address parsing: we must expand
the size of the address storage fields in the nfs_parsed_mount_options
struct before we can parse and store IPv6 addresses.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Cc: Aurelien Charbon <aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ@public.gmane.org>
---
fs/nfs/super.c | 30 ++++++++++++++++++++++++------
1 files changed, 24 insertions(+), 6 deletions(-)
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 4a3a5c0..bf98b8f 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -617,6 +617,26 @@ static int nfs_verify_server_address(struct sockaddr *addr)
}
/*
+ * Parse string addresses passed in via a mount option,
+ * and construct a sockaddr based on the result.
+ *
+ * If address parsing fails, set the sockaddr's address
+ * family to AF_UNSPEC to force nfs_verify_server_address()
+ * to punt the mount.
+ */
+static void nfs_parse_server_address(char *value,
+ struct sockaddr *sap)
+{
+ struct sockaddr_in *ap = (void *)sap;
+
+ ap->sin_family = AF_INET;
+ if (in4_pton(value, -1, (u8 *)&ap->sin_addr.s_addr, '\0', NULL))
+ return;
+
+ sap->sa_family = AF_UNSPEC;
+}
+
+/*
* Error-check and convert a string of mount options from user space into
* a data structure
*/
@@ -939,9 +959,8 @@ static int nfs_parse_mount_options(char *raw,
string = match_strdup(args);
if (string == NULL)
goto out_nomem;
- mnt->nfs_server.address.sin_family = AF_INET;
- mnt->nfs_server.address.sin_addr.s_addr =
- in_aton(string);
+ nfs_parse_server_address(string, (struct sockaddr *)
+ &mnt->nfs_server.address);
kfree(string);
break;
case Opt_clientaddr:
@@ -960,9 +979,8 @@ static int nfs_parse_mount_options(char *raw,
string = match_strdup(args);
if (string == NULL)
goto out_nomem;
- mnt->mount_server.address.sin_family = AF_INET;
- mnt->mount_server.address.sin_addr.s_addr =
- in_aton(string);
+ nfs_parse_server_address(string, (struct sockaddr *)
+ &mnt->mount_server.address);
kfree(string);
break;
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 26/27] NFS: Support non-IPv4 addresses in nfs_parsed_mount_data
[not found] ` <20071210195106.2823.43884.stgit-meopP2rzCrTwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (24 preceding siblings ...)
2007-12-10 19:59 ` [PATCH 25/27] NFS: Refactor mount option address parsing into separate function Chuck Lever
@ 2007-12-10 19:59 ` Chuck Lever
2007-12-10 19:59 ` [PATCH 27/27] NFS: Pull covers off IPv6 address parsing Chuck Lever
26 siblings, 0 replies; 31+ messages in thread
From: Chuck Lever @ 2007-12-10 19:59 UTC (permalink / raw)
To: trond.myklebust; +Cc: aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ, linux-nfs
Replace the nfs_server and mount_server address fields in the
nfs_parsed_mount_data structure with a "struct sockaddr_storage"
instead of a "struct sockaddr_in".
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Cc: Aurelien Charbon <aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ@public.gmane.org>
---
fs/nfs/client.c | 4 ++--
fs/nfs/internal.h | 6 ++++--
fs/nfs/super.c | 54 +++++++++++++++++++++++++++++++++--------------------
3 files changed, 40 insertions(+), 24 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 5406410..8652e5e 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -585,7 +585,7 @@ static int nfs_init_server(struct nfs_server *server,
/* Allocate or find a client reference we can use */
clp = nfs_get_client(data->nfs_server.hostname,
(struct sockaddr *)&data->nfs_server.address,
- sizeof(data->nfs_server.address),
+ data->nfs_server.addrlen,
nfsvers);
if (IS_ERR(clp)) {
dprintk("<-- nfs_init_server() = error %ld\n", PTR_ERR(clp));
@@ -997,7 +997,7 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
error = nfs4_set_client(server,
data->nfs_server.hostname,
(struct sockaddr *)&data->nfs_server.address,
- sizeof(data->nfs_server.address),
+ data->nfs_server.addrlen,
data->client_address,
data->auth_flavors[0],
data->nfs_server.protocol,
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index b54ed13..2e226d2 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -42,7 +42,8 @@ struct nfs_parsed_mount_data {
char *client_address;
struct {
- struct sockaddr_in address;
+ struct sockaddr_storage address;
+ size_t addrlen;
char *hostname;
unsigned int version;
unsigned short port;
@@ -50,7 +51,8 @@ struct nfs_parsed_mount_data {
} mount_server;
struct {
- struct sockaddr_in address;
+ struct sockaddr_storage address;
+ size_t addrlen;
char *hostname;
char *export_path;
int protocol;
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index bf98b8f..379841e 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -625,15 +625,18 @@ static int nfs_verify_server_address(struct sockaddr *addr)
* to punt the mount.
*/
static void nfs_parse_server_address(char *value,
- struct sockaddr *sap)
+ struct sockaddr *sap,
+ size_t *len)
{
struct sockaddr_in *ap = (void *)sap;
ap->sin_family = AF_INET;
+ *len = sizeof(*ap);
if (in4_pton(value, -1, (u8 *)&ap->sin_addr.s_addr, '\0', NULL))
return;
sap->sa_family = AF_UNSPEC;
+ *len = 0;
}
/*
@@ -960,7 +963,8 @@ static int nfs_parse_mount_options(char *raw,
if (string == NULL)
goto out_nomem;
nfs_parse_server_address(string, (struct sockaddr *)
- &mnt->nfs_server.address);
+ &mnt->nfs_server.address,
+ &mnt->nfs_server.addrlen);
kfree(string);
break;
case Opt_clientaddr:
@@ -980,7 +984,8 @@ static int nfs_parse_mount_options(char *raw,
if (string == NULL)
goto out_nomem;
nfs_parse_server_address(string, (struct sockaddr *)
- &mnt->mount_server.address);
+ &mnt->mount_server.address,
+ &mnt->mount_server.addrlen);
kfree(string);
break;
@@ -1025,9 +1030,9 @@ out_unknown:
static int nfs_try_mount(struct nfs_parsed_mount_data *args,
struct nfs_fh *root_fh)
{
- struct sockaddr_in sin;
- int status;
+ struct sockaddr *sap = (struct sockaddr *)&args->mount_server.address;
char *hostname;
+ int status;
if (args->mount_server.version == 0) {
if (args->flags & NFS_MOUNT_VER3)
@@ -1044,21 +1049,23 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args,
/*
* Construct the mount server's address.
*/
- if (args->mount_server.address.sin_addr.s_addr != INADDR_ANY)
- sin = args->mount_server.address;
- else
- sin = args->nfs_server.address;
+ if (args->mount_server.address.ss_family == AF_UNSPEC) {
+ memcpy(sap, &args->nfs_server.address,
+ args->nfs_server.addrlen);
+ args->mount_server.addrlen = args->nfs_server.addrlen;
+ }
+
/*
* autobind will be used if mount_server.port == 0
*/
- nfs_set_port((struct sockaddr *)&sin, args->mount_server.port);
+ nfs_set_port(sap, args->mount_server.port);
/*
* Now ask the mount server to map our export path
* to a file handle.
*/
- status = nfs_mount((struct sockaddr *) &sin,
- sizeof(sin),
+ status = nfs_mount(sap,
+ args->mount_server.addrlen,
hostname,
args->nfs_server.export_path,
args->mount_server.version,
@@ -1141,9 +1148,6 @@ static int nfs_validate_mount_data(void *options,
memset(mntfh->data + mntfh->size, 0,
sizeof(mntfh->data) - mntfh->size);
- if (!nfs_verify_server_address((struct sockaddr *) &data->addr))
- goto out_no_address;
-
/*
* Translate to nfs_parsed_mount_data, which nfs_fill_super
* can deal with.
@@ -1158,7 +1162,14 @@ static int nfs_validate_mount_data(void *options,
args->acregmax = data->acregmax;
args->acdirmin = data->acdirmin;
args->acdirmax = data->acdirmax;
- args->nfs_server.address = data->addr;
+
+ memcpy(&args->nfs_server.address, &data->addr,
+ sizeof(data->addr));
+ args->nfs_server.addrlen = sizeof(data->addr);
+ if (!nfs_verify_server_address((struct sockaddr *)
+ &args->nfs_server.address))
+ goto out_no_address;
+
if (!(data->flags & NFS_MOUNT_TCP))
args->nfs_server.protocol = XPRT_TRANSPORT_UDP;
/* N.B. caller will free nfs_server.hostname in all cases */
@@ -1631,6 +1642,7 @@ static int nfs4_validate_mount_data(void *options,
struct nfs_parsed_mount_data *args,
const char *dev_name)
{
+ struct sockaddr_in *ap;
struct nfs4_mount_data *data = (struct nfs4_mount_data *)options;
char *c;
@@ -1651,11 +1663,13 @@ static int nfs4_validate_mount_data(void *options,
switch (data->version) {
case 1:
- if (data->host_addrlen != sizeof(args->nfs_server.address))
+ ap = (struct sockaddr_in *)&args->nfs_server.address;
+ if (data->host_addrlen > sizeof(args->nfs_server.address))
+ goto out_no_address;
+ if (data->host_addrlen == 0)
goto out_no_address;
- if (copy_from_user(&args->nfs_server.address,
- data->host_addr,
- sizeof(args->nfs_server.address)))
+ args->nfs_server.addrlen = data->host_addrlen;
+ if (copy_from_user(ap, data->host_addr, data->host_addrlen))
return -EFAULT;
if (!nfs_verify_server_address((struct sockaddr *)
&args->nfs_server.address))
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 27/27] NFS: Pull covers off IPv6 address parsing
[not found] ` <20071210195106.2823.43884.stgit-meopP2rzCrTwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (25 preceding siblings ...)
2007-12-10 19:59 ` [PATCH 26/27] NFS: Support non-IPv4 addresses in nfs_parsed_mount_data Chuck Lever
@ 2007-12-10 19:59 ` Chuck Lever
26 siblings, 0 replies; 31+ messages in thread
From: Chuck Lever @ 2007-12-10 19:59 UTC (permalink / raw)
To: trond.myklebust; +Cc: aurelien.charbon-Z51IpKcfGtLk1uMJSBkQmQ, linux-nfs
Now that the needed IPv6 infrastructure is in place, allow the NFS client's
IP address parser to generate AF_INET6 addresses.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfs/super.c | 21 ++++++++++++++++-----
1 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 379841e..209d9c4 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -628,12 +628,23 @@ static void nfs_parse_server_address(char *value,
struct sockaddr *sap,
size_t *len)
{
- struct sockaddr_in *ap = (void *)sap;
+ if (strchr(value, ':')) {
+ struct sockaddr_in6 *ap = (struct sockaddr_in6 *)sap;
+ u8 *addr = (u8 *)&ap->sin6_addr.in6_u;
- ap->sin_family = AF_INET;
- *len = sizeof(*ap);
- if (in4_pton(value, -1, (u8 *)&ap->sin_addr.s_addr, '\0', NULL))
- return;
+ ap->sin6_family = AF_INET6;
+ *len = sizeof(*ap);
+ if (in6_pton(value, -1, addr, '\0', NULL))
+ return;
+ } else {
+ struct sockaddr_in *ap = (struct sockaddr_in *)sap;
+ u8 *addr = (u8 *)&ap->sin_addr.s_addr;
+
+ ap->sin_family = AF_INET;
+ *len = sizeof(*ap);
+ if (in4_pton(value, -1, addr, '\0', NULL))
+ return;
+ }
sap->sa_family = AF_UNSPEC;
*len = 0;
^ permalink raw reply related [flat|nested] 31+ messages in thread