Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 5 Nov 2014 00:58:01 +0000 (UTC)
From:      "Alexander V. Chernikov" <melifaro@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r274118 - in head/sys: kern netinet netinet6 sys
Message-ID:  <201411050058.sA50w1Vc018668@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: melifaro
Date: Wed Nov  5 00:58:01 2014
New Revision: 274118
URL: https://svnweb.freebsd.org/changeset/base/274118

Log:
  Remove old hack abusing domattach from NFS code.
  
  According to IANA RPC uaddr registry, there are no AFs
  except IPv4 and IPv6, so it's not worth being too abstract here.
  
  Remove ne_rtable[AF_MAX+1] and use explicit per-AF radix tries.
  Use own initialization without relying on domattach code.
  
  While I admit that this was one of the rare places in kernel
  networking code which really was capable of doing multi-AF
  without any AF-depended code, it is not possible anymore to
  rely on dom* code.
  
  While here, change terrifying "Invalid radix node head, rn:" message,
  to different non-understandable "netcred already exists for given addr/mask",
  but less terrifying. Since we know that rn_addaddr() returns NULL if
  the same record already exists, we should provide more friendly error.
  
  MFC after:	1 month

Modified:
  head/sys/kern/vfs_export.c
  head/sys/netinet/in_rmx.c
  head/sys/netinet6/in6_rmx.c
  head/sys/sys/domain.h

Modified: head/sys/kern/vfs_export.c
==============================================================================
--- head/sys/kern/vfs_export.c	Tue Nov  4 23:51:35 2014	(r274117)
+++ head/sys/kern/vfs_export.c	Wed Nov  5 00:58:01 2014	(r274118)
@@ -37,9 +37,11 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include "opt_inet.h"
+#include "opt_inet6.h"
+
 #include <sys/param.h>
 #include <sys/dirent.h>
-#include <sys/domain.h>
 #include <sys/jail.h>
 #include <sys/kernel.h>
 #include <sys/lock.h>
@@ -54,12 +56,16 @@ __FBSDID("$FreeBSD$");
 #include <sys/systm.h>
 #include <sys/vnode.h>
 
+#include <netinet/in.h>
 #include <net/radix.h>
 
 static MALLOC_DEFINE(M_NETADDR, "export_host", "Export host address structure");
 
+static struct radix_node_head *vfs_create_addrlist_af(
+		    struct radix_node_head **prnh, int off);
 static void	vfs_free_addrlist(struct netexport *nep);
 static int	vfs_free_netcred(struct radix_node *rn, void *w);
+static void	vfs_free_addrlist_af(struct radix_node_head **prnh);
 static int	vfs_hang_addrlist(struct mount *mp, struct netexport *nep,
 		    struct export_args *argp);
 static struct netcred *vfs_export_lookup(struct mount *, struct sockaddr *);
@@ -80,7 +86,8 @@ struct netcred {
  */
 struct netexport {
 	struct	netcred ne_defexported;		      /* Default export */
-	struct	radix_node_head *ne_rtable[AF_MAX+1]; /* Individual exports */
+	struct 	radix_node_head	*ne4;
+	struct 	radix_node_head	*ne6;
 };
 
 /*
@@ -96,7 +103,7 @@ vfs_hang_addrlist(struct mount *mp, stru
 	register int i;
 	struct radix_node *rn;
 	struct sockaddr *saddr, *smask = 0;
-	struct domain *dom;
+	int off;
 	int error;
 
 	/*
@@ -163,46 +170,39 @@ vfs_hang_addrlist(struct mount *mp, stru
 		if (smask->sa_len > argp->ex_masklen)
 			smask->sa_len = argp->ex_masklen;
 	}
-	i = saddr->sa_family;
-	if ((rnh = nep->ne_rtable[i]) == NULL) {
-		/*
-		 * Seems silly to initialize every AF when most are not used,
-		 * do so on demand here
-		 */
-		for (dom = domains; dom; dom = dom->dom_next) {
-			KASSERT(((i == AF_INET) || (i == AF_INET6)), 
-			    ("unexpected protocol in vfs_hang_addrlist"));
-			if (dom->dom_family == i && dom->dom_rtattach) {
-				/*
-				 * XXX MRT 
-				 * The INET and INET6 domains know the
-				 * offset already. We don't need to send it
-				 * So we just use it as a flag to say that
-				 * we are or are not setting up a real routing
-				 * table. Only IP and IPV6 need have this
-				 * be 0 so all other protocols can stay the 
-				 * same (ABI compatible).
-				 */ 
-				dom->dom_rtattach(
-				    (void **) &nep->ne_rtable[i], 0);
-				break;
-			}
+	rnh = NULL;
+	switch (saddr->sa_family) {
+#ifdef INET
+	case AF_INET:
+		if ((rnh = nep->ne4) == NULL) {
+			off = offsetof(struct sockaddr_in, sin_addr) << 3;
+			rnh = vfs_create_addrlist_af(&nep->ne4, off);
 		}
-		if ((rnh = nep->ne_rtable[i]) == NULL) {
-			error = ENOBUFS;
-			vfs_mount_error(mp, "%s %s %d",
-			    "Unable to initialize radix node head ",
-			    "for address family", i);
-			goto out;
+		break;
+#endif
+#ifdef INET6
+	case AF_INET6:
+		if ((rnh = nep->ne6) == NULL) {
+			off = offsetof(struct sockaddr_in6, sin6_addr) << 3;
+			rnh = vfs_create_addrlist_af(&nep->ne6, off);
 		}
+		break;
+#endif
+	}
+	if (rnh == NULL) {
+		error = ENOBUFS;
+		vfs_mount_error(mp, "%s %s %d",
+		    "Unable to initialize radix node head ",
+		    "for address family", saddr->sa_family);
+		goto out;
 	}
 	RADIX_NODE_HEAD_LOCK(rnh);
 	rn = (*rnh->rnh_addaddr)(saddr, smask, rnh, np->netc_rnodes);
 	RADIX_NODE_HEAD_UNLOCK(rnh);
 	if (rn == NULL || np != (struct netcred *)rn) {	/* already exists */
 		error = EPERM;
-		vfs_mount_error(mp, "Invalid radix node head, rn: %p %p",
-		    rn, np);
+		vfs_mount_error(mp,
+		    "netcred already exists for given addr/mask");
 		goto out;
 	}
 	np->netc_exflags = argp->ex_flags;
@@ -237,26 +237,43 @@ vfs_free_netcred(struct radix_node *rn, 
 	return (0);
 }
 
+static struct radix_node_head *
+vfs_create_addrlist_af(struct radix_node_head **prnh, int off)
+{
+
+	if (rn_inithead((void **)prnh, off) == 0)
+		return (NULL);
+	RADIX_NODE_HEAD_LOCK_INIT(*prnh);
+	return (*prnh);
+}
+
+static void
+vfs_free_addrlist_af(struct radix_node_head **prnh)
+{
+	struct radix_node_head *rnh;
+
+	rnh = *prnh;
+	RADIX_NODE_HEAD_LOCK(rnh);
+	(*rnh->rnh_walktree) (rnh, vfs_free_netcred, rnh);
+	RADIX_NODE_HEAD_UNLOCK(rnh);
+	RADIX_NODE_HEAD_DESTROY(rnh);
+	free(rnh, M_RTABLE);
+	prnh = NULL;
+}
+
 /*
  * Free the net address hash lists that are hanging off the mount points.
  */
 static void
 vfs_free_addrlist(struct netexport *nep)
 {
-	int i;
-	struct radix_node_head *rnh;
 	struct ucred *cred;
 
-	for (i = 0; i <= AF_MAX; i++) {
-		if ((rnh = nep->ne_rtable[i])) {
-			RADIX_NODE_HEAD_LOCK(rnh);
-			(*rnh->rnh_walktree) (rnh, vfs_free_netcred, rnh);
-			RADIX_NODE_HEAD_UNLOCK(rnh);
-			RADIX_NODE_HEAD_DESTROY(rnh);
-			free(rnh, M_RTABLE);
-			nep->ne_rtable[i] = NULL;	/* not SMP safe XXX */
-		}
-	}
+	if (nep->ne4 != NULL)
+		vfs_free_addrlist_af(&nep->ne4);
+	if (nep->ne6 != NULL)
+		vfs_free_addrlist_af(&nep->ne6);
+
 	cred = nep->ne_defexported.netc_anon;
 	if (cred != NULL)
 		crfree(cred);
@@ -439,7 +456,15 @@ vfs_export_lookup(struct mount *mp, stru
 		 */
 		if (nam != NULL) {
 			saddr = nam;
-			rnh = nep->ne_rtable[saddr->sa_family];
+			rnh = NULL;
+			switch (saddr->sa_family) {
+			case AF_INET:
+				rnh = nep->ne4;
+				break;
+			case AF_INET6:
+				rnh = nep->ne6;
+				break;
+			}
 			if (rnh != NULL) {
 				RADIX_NODE_HEAD_RLOCK(rnh);
 				np = (struct netcred *)

Modified: head/sys/netinet/in_rmx.c
==============================================================================
--- head/sys/netinet/in_rmx.c	Tue Nov  4 23:51:35 2014	(r274117)
+++ head/sys/netinet/in_rmx.c	Wed Nov  5 00:58:01 2014	(r274118)
@@ -341,23 +341,12 @@ in_inithead(void **head, int off)
 {
 	struct radix_node_head *rnh;
 
-	/* XXX MRT
-	 * This can be called from vfs_export.c too in which case 'off'
-	 * will be 0. We know the correct value so just use that and
-	 * return directly if it was 0.
-	 * This is a hack that replaces an even worse hack on a bad hack
-	 * on a bad design. After RELENG_7 this should be fixed but that
-	 * will change the ABI, so for now do it this way.
-	 */
 	if (!rn_inithead(head, 32))
 		return 0;
 
 	rnh = *head;
 	RADIX_NODE_HEAD_LOCK_INIT(rnh);
 
-	if (off == 0)		/* XXX MRT  see above */
-		return 1;	/* only do the rest for a real routing table */
-
 	rnh->rnh_addaddr = in_addroute;
 	in_setmatchfunc(rnh, V_drop_redirect);
 	rnh->rnh_close = in_clsroute;

Modified: head/sys/netinet6/in6_rmx.c
==============================================================================
--- head/sys/netinet6/in6_rmx.c	Tue Nov  4 23:51:35 2014	(r274117)
+++ head/sys/netinet6/in6_rmx.c	Wed Nov  5 00:58:01 2014	(r274118)
@@ -254,10 +254,6 @@ in6_mtutimo(void *rock)
 
 /*
  * Initialize our routing tree.
- * XXX MRT When off == 0, we are being called from vfs_export.c
- * so just set up their table and leave. (we know what the correct
- * value should be so just use that).. FIX AFTER RELENG_7 is MFC'd
- * see also comments in in_inithead() vfs_export.c and domain.h
  */
 static VNET_DEFINE(int, _in6_rt_was_here);
 #define	V__in6_rt_was_here	VNET(_in6_rt_was_here)
@@ -268,14 +264,11 @@ in6_inithead(void **head, int off)
 	struct radix_node_head *rnh;
 
 	if (!rn_inithead(head, offsetof(struct sockaddr_in6, sin6_addr) << 3))
-		return 0;		/* See above */
+		return (0);
 
 	rnh = *head;
 	RADIX_NODE_HEAD_LOCK_INIT(rnh);
 
-	if (off == 0)		/* See above */
-		return 1;	/* only do the rest for the real thing */
-
 	rnh->rnh_addaddr = in6_addroute;
 
 	if (V__in6_rt_was_here == 0) {
@@ -284,7 +277,7 @@ in6_inithead(void **head, int off)
 		V__in6_rt_was_here = 1;
 	}
 
-	return 1;
+	return (1);
 }
 
 #ifdef VIMAGE

Modified: head/sys/sys/domain.h
==============================================================================
--- head/sys/sys/domain.h	Tue Nov  4 23:51:35 2014	(r274117)
+++ head/sys/sys/domain.h	Wed Nov  5 00:58:01 2014	(r274118)
@@ -61,12 +61,6 @@ struct domain {
 	int	(*dom_rtdetach)		/* clean up routing table */
 		(void **, int);
 	int	dom_rtoffset;		/* an arg to rtattach, in bits */
-		/* XXX MRT.
-		 * rtoffset May be 0 if the domain supplies its own rtattach(),
-		 * in which case, a 0 indicates it's being called from 
-		 * vfs_export.c (HACK)  Only for AF_INET{,6} at this time.
-		 * Temporary ABI compat hack.. fix post RELENG_7
-		 */
 	int	dom_maxrtkey;		/* for routing layer */
 	void	*(*dom_ifattach)(struct ifnet *);
 	void	(*dom_ifdetach)(struct ifnet *, void *);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201411050058.sA50w1Vc018668>