All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] nfsd: add support for NFSv4 callbacks over IPv6
@ 2009-06-17 18:15 Jeff Layton
  2009-06-17 18:15 ` [PATCH 1/4] nfsd: convert nfs4_callback struct to hold address in sockaddr_storage Jeff Layton
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Jeff Layton @ 2009-06-17 18:15 UTC (permalink / raw)
  To: linux-nfs; +Cc: chuck.lever, bfields

This patchset is a first pass at adding IPv6 callback channel support
for knfsd. The set is fairly straightforward, but it does require a
number of changes to server side NFSv4 related structs that store
addresses in places that are only suitable for IPv4 addresses.

I've tested this by having Linux and OpenSolaris clients mount the
server over an IPv6 socket, get a delegation and ensure that the server
can recall that delegation. It all seems to work as expected. IPv4
callbacks also seem to continue to work correctly.

This patchset does change the some of the new 4.1 functions
(nfsd4_exchange_id in particular). Those changes are untested as of yet
but I'll see if I can do so if the approach in this set seems
reasonable.

Comments welcome...

Jeff Layton (4):
  nfsd: convert nfs4_callback struct to hold address in
    sockaddr_storage
  nfsd: break out setclientid port parsing into separate routine
  nfsd: make nfs4_client->cl_addr a struct sockaddr_storage
  nfsd: add support for NFSv4 callbacks over IPv6

 fs/nfsd/nfs4callback.c     |   11 +--
 fs/nfsd/nfs4state.c        |  220 ++++++++++++++++++++++++++++++++++++-------
 include/linux/nfsd/state.h |    6 +-
 3 files changed, 189 insertions(+), 48 deletions(-)


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/4] nfsd: convert nfs4_callback struct to hold address in sockaddr_storage
  2009-06-17 18:15 [PATCH 0/4] nfsd: add support for NFSv4 callbacks over IPv6 Jeff Layton
@ 2009-06-17 18:15 ` Jeff Layton
  2009-06-17 18:15 ` [PATCH 2/4] nfsd: break out setclientid port parsing into separate routine Jeff Layton
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Jeff Layton @ 2009-06-17 18:15 UTC (permalink / raw)
  To: linux-nfs; +Cc: chuck.lever, bfields

...rather than as a separate address and port fields. This will be
necessary for implementing callbacks over IPv6.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
 fs/nfsd/nfs4callback.c     |   11 ++---------
 fs/nfsd/nfs4state.c        |   13 +++++++++----
 include/linux/nfsd/state.h |    4 ++--
 3 files changed, 13 insertions(+), 15 deletions(-)

diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index f4fab69..0358563 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -368,7 +368,6 @@ static int max_cb_time(void)
 
 int setup_callback_client(struct nfs4_client *clp)
 {
-	struct sockaddr_in	addr;
 	struct nfs4_cb_conn *cb = &clp->cl_cb_conn;
 	struct rpc_timeout	timeparms = {
 		.to_initval	= max_cb_time(),
@@ -376,8 +375,8 @@ int setup_callback_client(struct nfs4_client *clp)
 	};
 	struct rpc_create_args args = {
 		.protocol	= IPPROTO_TCP,
-		.address	= (struct sockaddr *)&addr,
-		.addrsize	= sizeof(addr),
+		.address	= (struct sockaddr *) &cb->cb_addr,
+		.addrsize	= cb->cb_addrlen,
 		.timeout	= &timeparms,
 		.program	= &cb_program,
 		.prognumber	= cb->cb_prog,
@@ -391,12 +390,6 @@ int setup_callback_client(struct nfs4_client *clp)
 	if (!clp->cl_principal && (clp->cl_flavor >= RPC_AUTH_GSS_KRB5))
 		return -EINVAL;
 
-	/* Initialize address */
-	memset(&addr, 0, sizeof(addr));
-	addr.sin_family = AF_INET;
-	addr.sin_port = htons(cb->cb_port);
-	addr.sin_addr.s_addr = htonl(cb->cb_addr);
-
 	/* Create RPC client */
 	client = rpc_create(&args);
 	if (IS_ERR(client)) {
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index d5caf2a..edb03d4 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -932,7 +932,7 @@ parse_octet(unsigned int *lenp, char **addrp)
 
 /* parse and set the setclientid ipv4 callback address */
 static int
-parse_ipv4(unsigned int addr_len, char *addr_val, unsigned int *cbaddrp, unsigned short *cbportp)
+parse_ipv4(unsigned int addr_len, char *addr_val, struct sockaddr_in *s4)
 {
 	int temp = 0;
 	u32 cbaddr = 0;
@@ -941,6 +941,8 @@ parse_ipv4(unsigned int addr_len, char *addr_val, unsigned int *cbaddrp, unsigne
 	char *addr = addr_val;
 	int i, shift;
 
+	s4->sin_family = AF_INET;
+
 	/* ipaddress */
 	shift = 24;
 	for(i = 4; i > 0  ; i--) {
@@ -951,7 +953,7 @@ parse_ipv4(unsigned int addr_len, char *addr_val, unsigned int *cbaddrp, unsigne
 		if (shift > 0)
 		shift -= 8;
 	}
-	*cbaddrp = cbaddr;
+	s4->sin_addr.s_addr = htonl(cbaddr);
 
 	/* port */
 	shift = 8;
@@ -963,7 +965,7 @@ parse_ipv4(unsigned int addr_len, char *addr_val, unsigned int *cbaddrp, unsigne
 		if (shift > 0)
 			shift -= 8;
 	}
-	*cbportp = cbport;
+	s4->sin_port = htons(cbport);
 	return 1;
 }
 
@@ -977,12 +979,15 @@ gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se)
 		goto out_err;
 
 	if ( !(parse_ipv4(se->se_callback_addr_len, se->se_callback_addr_val,
-	                 &cb->cb_addr, &cb->cb_port)))
+			  (struct sockaddr_in *) &cb->cb_addr)))
 		goto out_err;
+	cb->cb_addrlen = sizeof(struct sockaddr_in);
 	cb->cb_prog = se->se_callback_prog;
 	cb->cb_ident = se->se_callback_ident;
 	return;
 out_err:
+	cb->cb_addr.ss_family = AF_UNSPEC;
+	cb->cb_addrlen = 0;
 	dprintk(KERN_INFO "NFSD: this client (clientid %08x/%08x) "
 		"will not receive delegations\n",
 		clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
index 0ae4752..95a925c 100644
--- a/include/linux/nfsd/state.h
+++ b/include/linux/nfsd/state.h
@@ -81,8 +81,8 @@ struct nfs4_delegation {
 /* client delegation callback info */
 struct nfs4_cb_conn {
 	/* SETCLIENTID info */
-	u32                     cb_addr;
-	unsigned short          cb_port;
+	struct sockaddr_storage	cb_addr;
+	size_t			cb_addrlen;
 	u32                     cb_prog;
 	u32                     cb_ident;
 	/* RPC client info */
-- 
1.6.0.6


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/4] nfsd: break out setclientid port parsing into separate routine
  2009-06-17 18:15 [PATCH 0/4] nfsd: add support for NFSv4 callbacks over IPv6 Jeff Layton
  2009-06-17 18:15 ` [PATCH 1/4] nfsd: convert nfs4_callback struct to hold address in sockaddr_storage Jeff Layton
@ 2009-06-17 18:15 ` Jeff Layton
  2009-06-17 18:15 ` [PATCH 3/4] nfsd: make nfs4_client->cl_addr a struct sockaddr_storage Jeff Layton
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Jeff Layton @ 2009-06-17 18:15 UTC (permalink / raw)
  To: linux-nfs; +Cc: chuck.lever, bfields

...and change the parse_ipv4 routine to be a little more efficient with
the stack.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
 fs/nfsd/nfs4state.c |   46 ++++++++++++++++++++++++++++++----------------
 1 files changed, 30 insertions(+), 16 deletions(-)

diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index edb03d4..6a12219 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -930,15 +930,40 @@ parse_octet(unsigned int *lenp, char **addrp)
 	return n;
 }
 
+/*
+ * Parse port out of setclientid callback address
+ *
+ * @addrlen: remaining length of address string
+ * @addr: pointer to first port octet in address string
+ * @sa: pointer to port field in sockaddr
+ *
+ * Parse the port portion of a setclientid callback address. Returns true on
+ * success and false on failure.
+ */
+static bool
+parse_port(unsigned int addrlen, char *addr, __be16 *port)
+{
+	int temp = 0, i, shift = 8;
+	u16 cbport = 0;
+
+	for (i = 2; i > 0; i--) {
+		temp = parse_octet(&addrlen, &addr);
+		if (temp < 0)
+			return 0;
+		cbport |= (temp << shift);
+		if (shift > 0)
+			shift -= 8;
+	}
+	*port = htons(cbport);
+	return 1;
+}
+
 /* parse and set the setclientid ipv4 callback address */
 static int
-parse_ipv4(unsigned int addr_len, char *addr_val, struct sockaddr_in *s4)
+parse_ipv4(unsigned int addrlen, char *addr, struct sockaddr_in *s4)
 {
 	int temp = 0;
 	u32 cbaddr = 0;
-	u16 cbport = 0;
-	u32 addrlen = addr_len;
-	char *addr = addr_val;
 	int i, shift;
 
 	s4->sin_family = AF_INET;
@@ -955,18 +980,7 @@ parse_ipv4(unsigned int addr_len, char *addr_val, struct sockaddr_in *s4)
 	}
 	s4->sin_addr.s_addr = htonl(cbaddr);
 
-	/* port */
-	shift = 8;
-	for(i = 2; i > 0  ; i--) {
-		if ((temp = parse_octet(&addrlen, &addr)) < 0) {
-			return 0;
-		}
-		cbport |= (temp << shift);
-		if (shift > 0)
-			shift -= 8;
-	}
-	s4->sin_port = htons(cbport);
-	return 1;
+	return parse_port(addrlen, addr, &s4->sin_port);
 }
 
 static void
-- 
1.6.0.6


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/4] nfsd: make nfs4_client->cl_addr a struct sockaddr_storage
  2009-06-17 18:15 [PATCH 0/4] nfsd: add support for NFSv4 callbacks over IPv6 Jeff Layton
  2009-06-17 18:15 ` [PATCH 1/4] nfsd: convert nfs4_callback struct to hold address in sockaddr_storage Jeff Layton
  2009-06-17 18:15 ` [PATCH 2/4] nfsd: break out setclientid port parsing into separate routine Jeff Layton
@ 2009-06-17 18:15 ` Jeff Layton
  2009-06-17 18:15 ` [PATCH 4/4] nfsd: add support for NFSv4 callbacks over IPv6 Jeff Layton
  2009-06-17 18:47 ` [PATCH 0/4] " J. Bruce Fields
  4 siblings, 0 replies; 10+ messages in thread
From: Jeff Layton @ 2009-06-17 18:15 UTC (permalink / raw)
  To: linux-nfs; +Cc: chuck.lever, bfields

It's currently a __be32, which isn't big enough to hold an IPv6 address.
While we're at it, add some new routines for comparing and copying
cl_addr's, and a function for formatting a cl_addr into a string.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
 fs/nfsd/nfs4state.c        |   89 +++++++++++++++++++++++++++++++++++++-------
 include/linux/nfsd/state.h |    2 +-
 2 files changed, 76 insertions(+), 15 deletions(-)

diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 6a12219..f1caddd 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1198,6 +1198,62 @@ nfsd4_set_ex_flags(struct nfs4_client *new, struct nfsd4_exchange_id *clid)
 	clid->flags = new->cl_exchange_flags;
 }
 
+/* Returns true if addresses are equal (ignoring port, scope, etc) */
+static bool
+cl_addr_equal(struct sockaddr *a, struct sockaddr *b)
+{
+	struct sockaddr_in *a4, *b4;
+
+	if (a->sa_family != b->sa_family)
+		return false;
+
+	switch (a->sa_family) {
+	case AF_INET:
+		a4 = (struct sockaddr_in *) a;
+		b4 = (struct sockaddr_in *) b;
+		return (a4->sin_addr.s_addr == b4->sin_addr.s_addr);
+	}
+
+	/* not sure how to compare, so just return false */
+	return false;
+}
+
+/* Given a sockaddr, fill in the cl_addr -- ignore port, scope, etc */
+static void
+cl_addr_copy(struct sockaddr *dst, struct sockaddr *src)
+{
+	struct sockaddr_in *s4, *d4;
+
+	dst->sa_family = src->sa_family;
+
+	switch (dst->sa_family) {
+	case AF_INET:
+		s4 = (struct sockaddr_in *) src;
+		d4 = (struct sockaddr_in *) dst;
+		d4->sin_addr.s_addr = s4->sin_addr.s_addr;
+		return;
+	default:
+		dst->sa_family = AF_UNSPEC;
+	}
+}
+
+/* format the cl_addr as text and stuff it into buf. Don't go beyond size. */
+static void
+cl_addr_snprintf(char *buf, size_t size, struct sockaddr *sa)
+{
+	switch (sa->sa_family) {
+	case AF_INET:
+		snprintf(buf, size, "%pI4",
+			 &((struct sockaddr_in *) sa)->sin_addr.s_addr);
+		break;
+	default:
+		snprintf(buf, size, "(family=%hu)", sa->sa_family);
+	}
+
+	/* forcibly NULL terminate string, just in case */
+	buf[size - 1] = '\0';
+}
+
 __be32
 nfsd4_exchange_id(struct svc_rqst *rqstp,
 		  struct nfsd4_compound_state *cstate,
@@ -1207,13 +1263,15 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
 	int status;
 	unsigned int		strhashval;
 	char			dname[HEXDIR_LEN];
+	char			addr_str[INET_ADDRSTRLEN];
 	nfs4_verifier		verf = exid->verifier;
-	u32			ip_addr = svc_addr_in(rqstp)->sin_addr.s_addr;
+	struct sockaddr		*sa = svc_addr(rqstp);
 
+	cl_addr_snprintf(addr_str, INET_ADDRSTRLEN, sa);
 	dprintk("%s rqstp=%p exid=%p clname.len=%u clname.data=%p "
-		" ip_addr=%u flags %x, spa_how %d\n",
+		"ip_addr=%s flags %x, spa_how %d\n",
 		__func__, rqstp, exid, exid->clname.len, exid->clname.data,
-		ip_addr, exid->flags, exid->spa_how);
+		addr_str, exid->flags, exid->spa_how);
 
 	if (!check_name(exid->clname) || (exid->flags & ~EXCHGID4_FLAG_MASK_A))
 		return nfserr_inval;
@@ -1261,7 +1319,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
 			expire_client(conf);
 			goto out_new;
 		}
-		if (ip_addr != conf->cl_addr &&
+		if (!cl_addr_equal((struct sockaddr *) &conf->cl_addr, sa) &&
 		    !(exid->flags & EXCHGID4_FLAG_UPD_CONFIRMED_REC_A)) {
 			/* Client collision. 18.35.4 case 3 */
 			status = nfserr_clid_inuse;
@@ -1308,7 +1366,7 @@ out_new:
 
 	copy_verf(new, &verf);
 	copy_cred(&new->cl_cred, &rqstp->rq_cred);
-	new->cl_addr = ip_addr;
+	cl_addr_copy((struct sockaddr *) &new->cl_addr, sa);
 	gen_clid(new);
 	gen_confirm(new);
 	add_to_unconfirmed(new, strhashval);
@@ -1362,7 +1420,7 @@ nfsd4_create_session(struct svc_rqst *rqstp,
 		     struct nfsd4_compound_state *cstate,
 		     struct nfsd4_create_session *cr_ses)
 {
-	u32 ip_addr = svc_addr_in(rqstp)->sin_addr.s_addr;
+	struct sockaddr *sa = svc_addr(rqstp);
 	struct nfsd4_compoundres *resp = rqstp->rq_resp;
 	struct nfs4_client *conf, *unconf;
 	struct nfsd4_slot *slot = NULL;
@@ -1393,7 +1451,7 @@ nfsd4_create_session(struct svc_rqst *rqstp,
 		conf->cl_slot.sl_seqid++;
 	} else if (unconf) {
 		if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred) ||
-		    (ip_addr != unconf->cl_addr)) {
+		    !cl_addr_equal(sa, (struct sockaddr *) &unconf->cl_addr)) {
 			status = nfserr_clid_inuse;
 			goto out;
 		}
@@ -1541,7 +1599,7 @@ __be32
 nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 		  struct nfsd4_setclientid *setclid)
 {
-	struct sockaddr_in	*sin = svc_addr_in(rqstp);
+	struct sockaddr		*sa = svc_addr(rqstp);
 	struct xdr_netobj 	clname = { 
 		.len = setclid->se_namelen,
 		.data = setclid->se_name,
@@ -1573,8 +1631,11 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 		/* RFC 3530 14.2.33 CASE 0: */
 		status = nfserr_clid_inuse;
 		if (!same_creds(&conf->cl_cred, &rqstp->rq_cred)) {
-			dprintk("NFSD: setclientid: string in use by client"
-				" at %pI4\n", &conf->cl_addr);
+			char addr_str[INET_ADDRSTRLEN];
+			cl_addr_snprintf(addr_str, INET_ADDRSTRLEN,
+					 (struct sockaddr *) &conf->cl_addr);
+			dprintk("NFSD: setclientid: string in use by client "
+				"at %s\n", addr_str);
 			goto out;
 		}
 	}
@@ -1636,7 +1697,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 		gen_clid(new);
 	}
 	copy_verf(new, &clverifier);
-	new->cl_addr = sin->sin_addr.s_addr;
+	cl_addr_copy((struct sockaddr *) &new->cl_addr, sa);
 	new->cl_flavor = rqstp->rq_flavor;
 	princ = svc_gss_principal(rqstp);
 	if (princ) {
@@ -1670,7 +1731,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
 			 struct nfsd4_compound_state *cstate,
 			 struct nfsd4_setclientid_confirm *setclientid_confirm)
 {
-	struct sockaddr_in *sin = svc_addr_in(rqstp);
+	struct sockaddr *sa = svc_addr(rqstp);
 	struct nfs4_client *conf, *unconf;
 	nfs4_verifier confirm = setclientid_confirm->sc_confirm; 
 	clientid_t * clid = &setclientid_confirm->sc_clientid;
@@ -1689,9 +1750,9 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
 	unconf = find_unconfirmed_client(clid);
 
 	status = nfserr_clid_inuse;
-	if (conf && conf->cl_addr != sin->sin_addr.s_addr)
+	if (conf && !cl_addr_equal((struct sockaddr *) &conf->cl_addr, sa))
 		goto out;
-	if (unconf && unconf->cl_addr != sin->sin_addr.s_addr)
+	if (unconf && !cl_addr_equal((struct sockaddr *) &unconf->cl_addr, sa))
 		goto out;
 
 	/*
diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
index 95a925c..d9728b9 100644
--- a/include/linux/nfsd/state.h
+++ b/include/linux/nfsd/state.h
@@ -179,7 +179,7 @@ struct nfs4_client {
 	char                    cl_recdir[HEXDIR_LEN]; /* recovery dir */
 	nfs4_verifier		cl_verifier; 	/* generated by client */
 	time_t                  cl_time;        /* time of last lease renewal */
-	__be32			cl_addr; 	/* client ipaddress */
+	struct sockaddr_storage	cl_addr; 	/* client ipaddress */
 	u32			cl_flavor;	/* setclientid pseudoflavor */
 	char			*cl_principal;	/* setclientid principal name */
 	struct svc_cred		cl_cred; 	/* setclientid principal */
-- 
1.6.0.6


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 4/4] nfsd: add support for NFSv4 callbacks over IPv6
  2009-06-17 18:15 [PATCH 0/4] nfsd: add support for NFSv4 callbacks over IPv6 Jeff Layton
                   ` (2 preceding siblings ...)
  2009-06-17 18:15 ` [PATCH 3/4] nfsd: make nfs4_client->cl_addr a struct sockaddr_storage Jeff Layton
@ 2009-06-17 18:15 ` Jeff Layton
  2009-06-17 18:47 ` [PATCH 0/4] " J. Bruce Fields
  4 siblings, 0 replies; 10+ messages in thread
From: Jeff Layton @ 2009-06-17 18:15 UTC (permalink / raw)
  To: linux-nfs; +Cc: chuck.lever, bfields

The framework to add this is all in place. Now, add the code to allow
support for establishing a callback channel on an IPv6 socket.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
---
 fs/nfsd/nfs4state.c |   88 +++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 78 insertions(+), 10 deletions(-)

diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index f1caddd..6c6799d 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -55,6 +55,8 @@
 #include <linux/lockd/bind.h>
 #include <linux/module.h>
 #include <linux/sunrpc/svcauth_gss.h>
+#include <linux/inet.h>
+#include <net/ipv6.h>
 
 #define NFSDDBG_FACILITY                NFSDDBG_PROC
 
@@ -73,6 +75,12 @@ static u64 current_sessionid = 1;
 #define ZERO_STATEID(stateid) (!memcmp((stateid), &zerostateid, sizeof(stateid_t)))
 #define ONE_STATEID(stateid)  (!memcmp((stateid), &onestateid, sizeof(stateid_t)))
 
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#define ADDR_STRLEN INET6_ADDRSTRLEN
+#else /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
+#define ADDR_STRLEN INET_ADDRSTRLEN
+#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
+
 /* forward declarations */
 static struct nfs4_stateid * find_stateid(stateid_t *stid, int flags);
 static struct nfs4_delegation * find_delegation_stateid(struct inode *ino, stateid_t *stid);
@@ -983,19 +991,58 @@ parse_ipv4(unsigned int addrlen, char *addr, struct sockaddr_in *s4)
 	return parse_port(addrlen, addr, &s4->sin_port);
 }
 
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+static int
+parse_ipv6(unsigned int addrlen, char *addr, struct sockaddr_in6 *s6)
+{
+	char *dot;
+
+	s6->sin6_family = AF_INET6;
+
+	if (!in6_pton(addr, addrlen, (u8 *) &s6->sin6_addr.s6_addr, '.',
+		      (const char **) &dot))
+		return 0;
+
+	if ((addr + addrlen) <= dot)
+		return 0;
+
+	if (*dot++ != '.')
+		return 0;
+
+	return parse_port(addrlen - (dot - addr), dot, &s6->sin6_port);
+}
+#else /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
+static int
+parse_ipv6(unsigned int addrlen, char *addr, struct sockaddr_in6 *s6)
+{
+	return 0;
+}
+#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
+
 static void
 gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se)
 {
 	struct nfs4_cb_conn *cb = &clp->cl_cb_conn;
 
-	/* Currently, we only support tcp for the callback channel */
-	if ((se->se_callback_netid_len != 3) || memcmp((char *)se->se_callback_netid_val, "tcp", 3))
+	/* Currently, we only support tcp and tcp6 for the callback channel */
+	if (se->se_callback_netid_len == 3 &&
+	    !memcmp(se->se_callback_netid_val, "tcp", 3)) {
+		if (!parse_ipv4(se->se_callback_addr_len,
+				se->se_callback_addr_val,
+				(struct sockaddr_in *) &cb->cb_addr))
+			goto out_err;
+		cb->cb_addrlen = sizeof(struct sockaddr_in);
+	} else if (se->se_callback_netid_len == 4 &&
+		   !memcmp(se->se_callback_netid_val, "tcp6", 4)) {
+		if (!parse_ipv6(se->se_callback_addr_len,
+				se->se_callback_addr_val,
+				(struct sockaddr_in6 *) &cb->cb_addr))
+			goto out_err;
+		cb->cb_addrlen = sizeof(struct sockaddr_in6);
+	} else {
 		goto out_err;
+	}
 
-	if ( !(parse_ipv4(se->se_callback_addr_len, se->se_callback_addr_val,
-			  (struct sockaddr_in *) &cb->cb_addr)))
-		goto out_err;
-	cb->cb_addrlen = sizeof(struct sockaddr_in);
 	cb->cb_prog = se->se_callback_prog;
 	cb->cb_ident = se->se_callback_ident;
 	return;
@@ -1203,6 +1250,7 @@ static bool
 cl_addr_equal(struct sockaddr *a, struct sockaddr *b)
 {
 	struct sockaddr_in *a4, *b4;
+	struct sockaddr_in6 *a6, *b6;
 
 	if (a->sa_family != b->sa_family)
 		return false;
@@ -1212,6 +1260,12 @@ cl_addr_equal(struct sockaddr *a, struct sockaddr *b)
 		a4 = (struct sockaddr_in *) a;
 		b4 = (struct sockaddr_in *) b;
 		return (a4->sin_addr.s_addr == b4->sin_addr.s_addr);
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	case AF_INET6:
+		a6 = (struct sockaddr_in6 *) a;
+		b6 = (struct sockaddr_in6 *) b;
+		return ipv6_addr_equal(&a6->sin6_addr, &b6->sin6_addr);
+#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
 	}
 
 	/* not sure how to compare, so just return false */
@@ -1223,6 +1277,7 @@ static void
 cl_addr_copy(struct sockaddr *dst, struct sockaddr *src)
 {
 	struct sockaddr_in *s4, *d4;
+	struct sockaddr_in6 *s6, *d6;
 
 	dst->sa_family = src->sa_family;
 
@@ -1232,6 +1287,13 @@ cl_addr_copy(struct sockaddr *dst, struct sockaddr *src)
 		d4 = (struct sockaddr_in *) dst;
 		d4->sin_addr.s_addr = s4->sin_addr.s_addr;
 		return;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	case AF_INET6:
+		s6 = (struct sockaddr_in6 *) src;
+		d6 = (struct sockaddr_in6 *) dst;
+		ipv6_addr_copy(&d6->sin6_addr, &s6->sin6_addr);
+		return;
+#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
 	default:
 		dst->sa_family = AF_UNSPEC;
 	}
@@ -1246,6 +1308,12 @@ cl_addr_snprintf(char *buf, size_t size, struct sockaddr *sa)
 		snprintf(buf, size, "%pI4",
 			 &((struct sockaddr_in *) sa)->sin_addr.s_addr);
 		break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	case AF_INET6:
+		snprintf(buf, size, "%pI6",
+			 &((struct sockaddr_in6 *) sa)->sin6_addr.s6_addr);
+		break;
+#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
 	default:
 		snprintf(buf, size, "(family=%hu)", sa->sa_family);
 	}
@@ -1263,11 +1331,11 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
 	int status;
 	unsigned int		strhashval;
 	char			dname[HEXDIR_LEN];
-	char			addr_str[INET_ADDRSTRLEN];
+	char			addr_str[ADDR_STRLEN];
 	nfs4_verifier		verf = exid->verifier;
 	struct sockaddr		*sa = svc_addr(rqstp);
 
-	cl_addr_snprintf(addr_str, INET_ADDRSTRLEN, sa);
+	cl_addr_snprintf(addr_str, ADDR_STRLEN, sa);
 	dprintk("%s rqstp=%p exid=%p clname.len=%u clname.data=%p "
 		"ip_addr=%s flags %x, spa_how %d\n",
 		__func__, rqstp, exid, exid->clname.len, exid->clname.data,
@@ -1631,8 +1699,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 		/* RFC 3530 14.2.33 CASE 0: */
 		status = nfserr_clid_inuse;
 		if (!same_creds(&conf->cl_cred, &rqstp->rq_cred)) {
-			char addr_str[INET_ADDRSTRLEN];
-			cl_addr_snprintf(addr_str, INET_ADDRSTRLEN,
+			char addr_str[ADDR_STRLEN];
+			cl_addr_snprintf(addr_str, ADDR_STRLEN,
 					 (struct sockaddr *) &conf->cl_addr);
 			dprintk("NFSD: setclientid: string in use by client "
 				"at %s\n", addr_str);
-- 
1.6.0.6


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/4] nfsd: add support for NFSv4 callbacks over IPv6
  2009-06-17 18:15 [PATCH 0/4] nfsd: add support for NFSv4 callbacks over IPv6 Jeff Layton
                   ` (3 preceding siblings ...)
  2009-06-17 18:15 ` [PATCH 4/4] nfsd: add support for NFSv4 callbacks over IPv6 Jeff Layton
@ 2009-06-17 18:47 ` J. Bruce Fields
  2009-06-17 19:01   ` Jeff Layton
  4 siblings, 1 reply; 10+ messages in thread
From: J. Bruce Fields @ 2009-06-17 18:47 UTC (permalink / raw)
  To: Jeff Layton; +Cc: linux-nfs, chuck.lever

On Wed, Jun 17, 2009 at 02:15:37PM -0400, Jeff Layton wrote:
> This patchset is a first pass at adding IPv6 callback channel support
> for knfsd. The set is fairly straightforward, but it does require a
> number of changes to server side NFSv4 related structs that store
> addresses in places that are only suitable for IPv4 addresses.
> 
> I've tested this by having Linux and OpenSolaris clients mount the
> server over an IPv6 socket, get a delegation and ensure that the server
> can recall that delegation. It all seems to work as expected. IPv4
> callbacks also seem to continue to work correctly.
> 
> This patchset does change the some of the new 4.1 functions
> (nfsd4_exchange_id in particular). Those changes are untested as of yet
> but I'll see if I can do so if the approach in this set seems
> reasonable.

Thanks, just two quick comments:

	1. I've been working on the callback code, so check that this
	applies against for-2.6.31 (at
	git://linux-nfs.org/~bfields/linux.git).
	2. Any IP address checks in setclientid or exchange_id are
	probably bogus; the former should be gone, the latter may still
	be there but there'll be a patch queued up for 2.6.31 to fix
	that.

--b.

> 
> Comments welcome...
> 
> Jeff Layton (4):
>   nfsd: convert nfs4_callback struct to hold address in
>     sockaddr_storage
>   nfsd: break out setclientid port parsing into separate routine
>   nfsd: make nfs4_client->cl_addr a struct sockaddr_storage
>   nfsd: add support for NFSv4 callbacks over IPv6
> 
>  fs/nfsd/nfs4callback.c     |   11 +--
>  fs/nfsd/nfs4state.c        |  220 ++++++++++++++++++++++++++++++++++++-------
>  include/linux/nfsd/state.h |    6 +-
>  3 files changed, 189 insertions(+), 48 deletions(-)
> 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/4] nfsd: add support for NFSv4 callbacks over IPv6
  2009-06-17 18:47 ` [PATCH 0/4] " J. Bruce Fields
@ 2009-06-17 19:01   ` Jeff Layton
  0 siblings, 0 replies; 10+ messages in thread
From: Jeff Layton @ 2009-06-17 19:01 UTC (permalink / raw)
  To: J. Bruce Fields; +Cc: linux-nfs, chuck.lever

On Wed, 17 Jun 2009 14:47:01 -0400
"J. Bruce Fields" <bfields@fieldses.org> wrote:

> On Wed, Jun 17, 2009 at 02:15:37PM -0400, Jeff Layton wrote:
> > This patchset is a first pass at adding IPv6 callback channel support
> > for knfsd. The set is fairly straightforward, but it does require a
> > number of changes to server side NFSv4 related structs that store
> > addresses in places that are only suitable for IPv4 addresses.
> > 
> > I've tested this by having Linux and OpenSolaris clients mount the
> > server over an IPv6 socket, get a delegation and ensure that the server
> > can recall that delegation. It all seems to work as expected. IPv4
> > callbacks also seem to continue to work correctly.
> > 
> > This patchset does change the some of the new 4.1 functions
> > (nfsd4_exchange_id in particular). Those changes are untested as of yet
> > but I'll see if I can do so if the approach in this set seems
> > reasonable.
> 
> Thanks, just two quick comments:
> 
> 	1. I've been working on the callback code, so check that this
> 	applies against for-2.6.31 (at
> 	git://linux-nfs.org/~bfields/linux.git).

Sorry, I should have made it clear in the original email. This patchset
applies cleanly to your master branch. I just checked and it also
applies cleanly to your for-2.6.31 branch.

> 	2. Any IP address checks in setclientid or exchange_id are
> 	probably bogus; the former should be gone, the latter may still
> 	be there but there'll be a patch queued up for 2.6.31 to fix
> 	that.
> 

There are definitely still IP address comparisons in those functions,
though I confess I didn't look closely at the logic. My main concern
with this set was to move the IPv4 specific address containers to
sockaddr_storage, and to make the comparisons work for alternate
address families. I tried not to alter the logic however.

Thanks,
-- 
Jeff Layton <jlayton@redhat.com>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/4] nfsd: add support for NFSv4 callbacks over IPv6
       [not found]           ` <20090617210623.4c7860fb-9yPaYZwiELC+kQycOl6kW4xkIHaj4LzF@public.gmane.org>
@ 2009-06-18  4:28             ` Chuck Lever
  0 siblings, 0 replies; 10+ messages in thread
From: Chuck Lever @ 2009-06-18  4:28 UTC (permalink / raw)
  To: Jeff Layton; +Cc: Linux NFS Mailing list


On Jun 17, 2009, at 6:06 PM, Jeff Layton wrote:

> On Wed, 17 Jun 2009 14:32:16 -0700
> Chuck Lever <chucklever@gmail.com> wrote:
>
>> On Wed, Jun 17, 2009 at 1:55 PM, Jeff Layton <jlayton@redhat.com>  
>> wrote:
>>
>>> Site local addresses are considered deprecated but AFAIK, they are
>>> indistinguishable from "normal" IPv6 addresses.
>>
>>
>> My impression was site-local addresses may also use a scope ID.
>
> I don't think so. Site local addresses are considered routable and
> should be unique within a "site". I think the intent with them was to
> provide an address space analogous to RFC 1918 addresses.

RFC 3879, which deprecates site local addresses, does discuss the  
concept of using a scope ID with a site-local address (to distinguish  
which site the address belongs to, as a router could be connected to  
two separate subnets that contain hosts with the same site-local  
address).  The wikipedia page you cite below indicates that the  
administrative oversight for ULAs has not been established yet.  So  
the deprecation may or may not be entirely premature.

Anyway, this is all pretty academic at this point.  By the time we get  
global IPv6 address support working, we may come back to do link-local  
and discover the standards have all been changed again.

> There should be no need for a scopeid with them since it's not likely
> that 2 interfaces would have the same subnet ID (doing so would be
> silly given the large address space) and site-local addresses are not
> autoconfigured like link-local ones.
>
> In any case, site-local is deprecated and is supposedly being replaced
> by ULA's which are also routable within cooperating sites:
>
> http://en.wikipedia.org/wiki/Unique_local_address
>
> AFAICT, ULA's also have no need for a scope id.
>
>>> They just have a
>>> designated prefix which should really only have meaning to  
>>> routers. I
>>> don't think that we have to do anything special in order to support
>>> them.
>>>
>>> We really can't reasonably support link-local addresses with this.  
>>> To
>>> use a link-local address you need to know the scopeid. That value  
>>> only
>>> has meaning within a single host. The client has no way to know what
>>> scopeid to send to the server, so it can't send that information  
>>> along
>>> in the callback address.
>>
>> Right.  The callback presentation address string passed via  
>> SETCLIENTID is
>> an RPC universal address, which doesn't have the ability to  
>> represent a
>> scope ID.  However, there are ways around this limitation.  An  
>> incoming
>> site- or link-local universal address in an RPCB_GETADDR inherits  
>> the scope
>> ID from the address used to send the RPCB_GETADDR request, for  
>> example.
>>
>
> Yes, that's the only real way to do that. At the end of the day (at
> least on linux and windows), scopeid == interface number.

That's one way to write a scope ID.  Another is to use a device name.   
Scope ID support, such as it is now in the NFS client, supports both.

> A machine
> will have no idea what the interface number will be in another  
> machine.
> Therefore that info can only reasonably be filled out by the host that
> intends to connect to the remote link-local address.
>
> What we should probably do here for the server is to make sure that
> when a SETCLIENTID call comes in, that we can get the number of the
> interface that received the call and then stuff that info into the
> scopeid if the clientaddr has a link-local prefix.
>
>>> knfsd *might* be able to look for link-local prefixes and  
>>> determine the
>>> scopeid if it knows what interface the connection came in on. I'm  
>>> not
>>> clear if that information bubbles up from the RPC layer however.
>>>
>>> I don't think there's anything in this work that prevents us from
>>> adding link local support later, but it'll probably take some  
>>> research
>>> and work to determine how to make it happen.
>>>
>>> There are client-side implications here too. We'll have to  
>>> consider how
>>> to generate callback addresses when the server's address is a
>>> link-local address (mostly, make sure you use the link-local  
>>> callback
>>> address for the correct interface).
>>
>> See mount.nfs.  It strips the scope ID off of link-local  
>> clientaddr=, and
>> assumes the server will know how to glue an appropriate scope ID  
>> back in.
>> (Or, it _should_ do that... it probably does something that only
>> approximates this now).
>
> That's probably the right thing to do.
>
> The only real trick for mount.nfs is to make sure that when the
> server's address is a link-local addr, that it autogenerates the
> clientaddr= with the link-local address of the interface that matches
> the provided scopeid.


mount.nfs relies on the network layer to do that, I think.  It  
connects a socket to the server address, then scrapes the source  
address off the connected socket.

--
Chuck Lever
chuck[dot]lever[at]oracle[dot]com

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/4] nfsd: add support for NFSv4 callbacks over IPv6
       [not found]       ` <76bd70e30906171432m29b3f179y6d0f2111e205114c-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2009-06-18  1:06         ` Jeff Layton
       [not found]           ` <20090617210623.4c7860fb-9yPaYZwiELC+kQycOl6kW4xkIHaj4LzF@public.gmane.org>
  0 siblings, 1 reply; 10+ messages in thread
From: Jeff Layton @ 2009-06-18  1:06 UTC (permalink / raw)
  To: Chuck Lever; +Cc: linux-nfs

On Wed, 17 Jun 2009 14:32:16 -0700
Chuck Lever <chucklever@gmail.com> wrote:

> On Wed, Jun 17, 2009 at 1:55 PM, Jeff Layton <jlayton@redhat.com> wrote:
> 
> >
> > Site local addresses are considered deprecated but AFAIK, they are
> > indistinguishable from "normal" IPv6 addresses.
> 
> 
> My impression was site-local addresses may also use a scope ID.
> 

I don't think so. Site local addresses are considered routable and
should be unique within a "site". I think the intent with them was to
provide an address space analogous to RFC 1918 addresses.

There should be no need for a scopeid with them since it's not likely
that 2 interfaces would have the same subnet ID (doing so would be
silly given the large address space) and site-local addresses are not
autoconfigured like link-local ones.

In any case, site-local is deprecated and is supposedly being replaced
by ULA's which are also routable within cooperating sites:

http://en.wikipedia.org/wiki/Unique_local_address

AFAICT, ULA's also have no need for a scope id.

> 
> > They just have a
> > designated prefix which should really only have meaning to routers. I
> > don't think that we have to do anything special in order to support
> > them.
> >
> > We really can't reasonably support link-local addresses with this. To
> > use a link-local address you need to know the scopeid. That value only
> > has meaning within a single host. The client has no way to know what
> > scopeid to send to the server, so it can't send that information along
> > in the callback address.
> 
> 
> Right.  The callback presentation address string passed via SETCLIENTID is
> an RPC universal address, which doesn't have the ability to represent a
> scope ID.  However, there are ways around this limitation.  An incoming
> site- or link-local universal address in an RPCB_GETADDR inherits the scope
> ID from the address used to send the RPCB_GETADDR request, for example.
> 

Yes, that's the only real way to do that. At the end of the day (at
least on linux and windows), scopeid == interface number. A machine
will have no idea what the interface number will be in another machine.
Therefore that info can only reasonably be filled out by the host that
intends to connect to the remote link-local address.

What we should probably do here for the server is to make sure that
when a SETCLIENTID call comes in, that we can get the number of the
interface that received the call and then stuff that info into the
scopeid if the clientaddr has a link-local prefix.

> 
> > knfsd *might* be able to look for link-local prefixes and determine the
> > scopeid if it knows what interface the connection came in on. I'm not
> > clear if that information bubbles up from the RPC layer however.
> >
> > I don't think there's anything in this work that prevents us from
> > adding link local support later, but it'll probably take some research
> > and work to determine how to make it happen.
> >
> > There are client-side implications here too. We'll have to consider how
> > to generate callback addresses when the server's address is a
> > link-local address (mostly, make sure you use the link-local callback
> > address for the correct interface).
> 
> 
> See mount.nfs.  It strips the scope ID off of link-local clientaddr=, and
> assumes the server will know how to glue an appropriate scope ID back in.
>  (Or, it _should_ do that... it probably does something that only
> approximates this now).
> 
> 

That's probably the right thing to do.

The only real trick for mount.nfs is to make sure that when the
server's address is a link-local addr, that it autogenerates the
clientaddr= with the link-local address of the interface that matches
the provided scopeid.

PS: I think you can post to linux-nfs@vger.kernel.org from
non-subscribed addresses.

-- 
Jeff Layton <jlayton@redhat.com>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/4] nfsd: add support for NFSv4 callbacks over IPv6
       [not found] ` <76bd70e30906171223r1f286d0eg1e64510f106d3027-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2009-06-17 20:55   ` Jeff Layton
       [not found]     ` <76bd70e30906171432m29b3f179y6d0f2111e205114c@mail.gmail.com>
  0 siblings, 1 reply; 10+ messages in thread
From: Jeff Layton @ 2009-06-17 20:55 UTC (permalink / raw)
  To: Chuck Lever; +Cc: linux-nfs

On Wed, 17 Jun 2009 12:23:00 -0700
Chuck Lever <chucklever@gmail.com> wrote:

> Still no outgoing e-mail here.  Feel free to copy your reply to
> linux-nfs@vger.kernel.org (as chucklever@gmail.com is not subscribed
> to that list).
> 
> My two major comments are:
> 
> 1.  The CONFIG_IPV6 stuff in 4/4 is pretty messy.  Are you sure you
> need every one of those switches?  And, can you combine some of this
> into helper functions whose definition changes depending on how the
> kernel is built?
> 

Agreed, I'll see what I can do to clean it up.

I could probably eliminate some of the switches. Combining that into
helper functions will lead to a lot of "code sprawl" though (a lot of
little tiny functions).

> 2.  Does this implementation support link-local and site-local
> addresses?  Perhaps that's not important for your initial submission,
> but we should try to ensure that nothing in this design excludes
> support for the local address types.
> 

Site local addresses are considered deprecated but AFAIK, they are
indistinguishable from "normal" IPv6 addresses. They just have a
designated prefix which should really only have meaning to routers. I
don't think that we have to do anything special in order to support
them.

We really can't reasonably support link-local addresses with this. To
use a link-local address you need to know the scopeid. That value only
has meaning within a single host. The client has no way to know what
scopeid to send to the server, so it can't send that information along
in the callback address.

knfsd *might* be able to look for link-local prefixes and determine the
scopeid if it knows what interface the connection came in on. I'm not
clear if that information bubbles up from the RPC layer however.

I don't think there's anything in this work that prevents us from
adding link local support later, but it'll probably take some research
and work to determine how to make it happen.

There are client-side implications here too. We'll have to consider how
to generate callback addresses when the server's address is a
link-local address (mostly, make sure you use the link-local callback
address for the correct interface).

-- 
Jeff Layton <jlayton@redhat.com>

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2009-06-18  4:28 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-06-17 18:15 [PATCH 0/4] nfsd: add support for NFSv4 callbacks over IPv6 Jeff Layton
2009-06-17 18:15 ` [PATCH 1/4] nfsd: convert nfs4_callback struct to hold address in sockaddr_storage Jeff Layton
2009-06-17 18:15 ` [PATCH 2/4] nfsd: break out setclientid port parsing into separate routine Jeff Layton
2009-06-17 18:15 ` [PATCH 3/4] nfsd: make nfs4_client->cl_addr a struct sockaddr_storage Jeff Layton
2009-06-17 18:15 ` [PATCH 4/4] nfsd: add support for NFSv4 callbacks over IPv6 Jeff Layton
2009-06-17 18:47 ` [PATCH 0/4] " J. Bruce Fields
2009-06-17 19:01   ` Jeff Layton
     [not found] <76bd70e30906171223r1f286d0eg1e64510f106d3027@mail.gmail.com>
     [not found] ` <76bd70e30906171223r1f286d0eg1e64510f106d3027-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2009-06-17 20:55   ` Jeff Layton
     [not found]     ` <76bd70e30906171432m29b3f179y6d0f2111e205114c@mail.gmail.com>
     [not found]       ` <76bd70e30906171432m29b3f179y6d0f2111e205114c-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2009-06-18  1:06         ` Jeff Layton
     [not found]           ` <20090617210623.4c7860fb-9yPaYZwiELC+kQycOl6kW4xkIHaj4LzF@public.gmane.org>
2009-06-18  4:28             ` Chuck Lever

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.