svn commit: r194602 - in head/sys: net netatalk netinet netinet6 netipx

Robert Watson rwatson at FreeBSD.org
Sun Jun 21 19:30:34 UTC 2009


Author: rwatson
Date: Sun Jun 21 19:30:33 2009
New Revision: 194602
URL: http://svn.freebsd.org/changeset/base/194602

Log:
  Clean up common ifaddr management:
  
  - Unify reference count and lock initialization in a single function,
    ifa_init().
  - Move tear-down from a macro (IFAFREE) to a function ifa_free().
  - Move reference count bump from a macro (IFAREF) to a function ifa_ref().
  - Instead of using a u_int protected by a mutex to refcount(9) for
    reference count management.
  
  The ifa_mtx is now used for exactly one ioctl, and possibly should be
  removed.
  
  MFC after:	3 weeks

Modified:
  head/sys/net/if.c
  head/sys/net/if_var.h
  head/sys/net/route.c
  head/sys/net/rtsock.c
  head/sys/netatalk/at_control.c
  head/sys/netinet/in.c
  head/sys/netinet6/in6.c
  head/sys/netinet6/in6_ifattach.c
  head/sys/netinet6/nd6_nbr.c
  head/sys/netipx/ipx.c

Modified: head/sys/net/if.c
==============================================================================
--- head/sys/net/if.c	Sun Jun 21 19:21:01 2009	(r194601)
+++ head/sys/net/if.c	Sun Jun 21 19:30:33 2009	(r194602)
@@ -758,7 +758,7 @@ if_attach_internal(struct ifnet *ifp, in
 		socksize = roundup2(socksize, sizeof(long));
 		ifasize = sizeof(*ifa) + 2 * socksize;
 		ifa = malloc(ifasize, M_IFADDR, M_WAITOK | M_ZERO);
-		IFA_LOCK_INIT(ifa);
+		ifa_init(ifa);
 		sdl = (struct sockaddr_dl *)(ifa + 1);
 		sdl->sdl_len = socksize;
 		sdl->sdl_family = AF_LINK;
@@ -775,7 +775,6 @@ if_attach_internal(struct ifnet *ifp, in
 		sdl->sdl_len = masklen;
 		while (namelen != 0)
 			sdl->sdl_data[--namelen] = 0xff;
-		ifa->ifa_refcnt = 1;
 		TAILQ_INSERT_HEAD(&ifp->if_addrhead, ifa, ifa_link);
 		/* Reliably crash if used uninitialized. */
 		ifp->if_broadcastaddr = NULL;
@@ -896,7 +895,7 @@ if_purgeaddrs(struct ifnet *ifp)
 		}
 #endif /* INET6 */
 		TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
-		IFAFREE(ifa);
+		ifa_free(ifa);
 	}
 }
 
@@ -1013,7 +1012,7 @@ if_detach_internal(struct ifnet *ifp, in
 		if (!TAILQ_EMPTY(&ifp->if_addrhead)) {
 			ifa = TAILQ_FIRST(&ifp->if_addrhead);
 			TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
-			IFAFREE(ifa);
+			ifa_free(ifa);
 		}
 	}
 
@@ -1420,6 +1419,34 @@ if_rtdel(struct radix_node *rn, void *ar
 }
 
 /*
+ * Reference count functions for ifaddrs.
+ */
+void
+ifa_init(struct ifaddr *ifa)
+{
+
+	mtx_init(&ifa->ifa_mtx, "ifaddr", NULL, MTX_DEF);
+	refcount_init(&ifa->ifa_refcnt, 1);
+}
+
+void
+ifa_ref(struct ifaddr *ifa)
+{
+
+	refcount_acquire(&ifa->ifa_refcnt);
+}
+
+void
+ifa_free(struct ifaddr *ifa)
+{
+
+	if (refcount_release(&ifa->ifa_refcnt)) {
+		mtx_destroy(&ifa->ifa_mtx);
+		free(ifa, M_IFADDR);
+	}
+}
+
+/*
  * XXX: Because sockaddr_dl has deeper structure than the sockaddr
  * structs used to represent other address families, it is necessary
  * to perform a different comparison.
@@ -1711,10 +1738,10 @@ link_rtrequest(int cmd, struct rtentry *
 		return;
 	ifa = ifaof_ifpforaddr(dst, ifp);
 	if (ifa) {
-		IFAREF(ifa);		/* XXX */
+		ifa_ref(ifa);		/* XXX */
 		oifa = rt->rt_ifa;
 		rt->rt_ifa = ifa;
-		IFAFREE(oifa);
+		ifa_free(oifa);
 		if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
 			ifa->ifa_rtrequest(cmd, rt, info);
 	}

Modified: head/sys/net/if_var.h
==============================================================================
--- head/sys/net/if_var.h	Sun Jun 21 19:21:01 2009	(r194601)
+++ head/sys/net/if_var.h	Sun Jun 21 19:30:33 2009	(r194602)
@@ -706,11 +706,14 @@ struct ifaddr {
 /* for compatibility with other BSDs */
 #define	ifa_list	ifa_link
 
-#define	IFA_LOCK_INIT(ifa)	\
-    mtx_init(&(ifa)->ifa_mtx, "ifaddr", NULL, MTX_DEF)
+#ifdef _KERNEL
 #define	IFA_LOCK(ifa)		mtx_lock(&(ifa)->ifa_mtx)
 #define	IFA_UNLOCK(ifa)		mtx_unlock(&(ifa)->ifa_mtx)
-#define	IFA_DESTROY(ifa)	mtx_destroy(&(ifa)->ifa_mtx)
+
+void	ifa_free(struct ifaddr *ifa);
+void	ifa_init(struct ifaddr *ifa);
+void	ifa_ref(struct ifaddr *ifa);
+#endif
 
 /*
  * The prefix structure contains information about one prefix
@@ -741,24 +744,6 @@ struct ifmultiaddr {
 };
 
 #ifdef _KERNEL
-#define	IFAFREE(ifa)					\
-	do {						\
-		IFA_LOCK(ifa);				\
-		KASSERT((ifa)->ifa_refcnt > 0,		\
-		    ("ifa %p !(ifa_refcnt > 0)", ifa));	\
-		if (--(ifa)->ifa_refcnt == 0) {		\
-			IFA_DESTROY(ifa);		\
-			free(ifa, M_IFADDR);		\
-		} else 					\
-			IFA_UNLOCK(ifa);		\
-	} while (0)
-
-#define IFAREF(ifa)					\
-	do {						\
-		IFA_LOCK(ifa);				\
-		++(ifa)->ifa_refcnt;			\
-		IFA_UNLOCK(ifa);			\
-	} while (0)
 
 extern	struct rwlock ifnet_lock;
 #define	IFNET_LOCK_INIT() \

Modified: head/sys/net/route.c
==============================================================================
--- head/sys/net/route.c	Sun Jun 21 19:21:01 2009	(r194601)
+++ head/sys/net/route.c	Sun Jun 21 19:30:33 2009	(r194602)
@@ -474,7 +474,7 @@ rtfree(struct rtentry *rt)
 		 * e.g other routes and ifaddrs.
 		 */
 		if (rt->rt_ifa)
-			IFAFREE(rt->rt_ifa);
+			ifa_free(rt->rt_ifa);
 		/*
 		 * The key is separatly alloc'd so free it (see rt_setgate()).
 		 * This also frees the gateway, as they are always malloc'd
@@ -1126,7 +1126,7 @@ rtrequest1_fib(int req, struct rt_addrin
 		 * This moved from below so that rnh->rnh_addaddr() can
 		 * examine the ifa and  ifa->ifa_ifp if it so desires.
 		 */
-		IFAREF(ifa);
+		ifa_ref(ifa);
 		rt->rt_ifa = ifa;
 		rt->rt_ifp = ifa->ifa_ifp;
 		rt->rt_rmx.rmx_weight = 1;
@@ -1136,7 +1136,7 @@ rtrequest1_fib(int req, struct rt_addrin
 		if (rn_mpath_capable(rnh) &&
 			rt_mpath_conflict(rnh, rt, netmask)) {
 			if (rt->rt_ifa) {
-				IFAFREE(rt->rt_ifa);
+				ifa_free(rt->rt_ifa);
 			}
 			Free(rt_key(rt));
 			RT_LOCK_DESTROY(rt);
@@ -1153,7 +1153,7 @@ rtrequest1_fib(int req, struct rt_addrin
 		 */
 		if (rn == NULL) {
 			if (rt->rt_ifa)
-				IFAFREE(rt->rt_ifa);
+				ifa_free(rt->rt_ifa);
 			Free(rt_key(rt));
 			RT_LOCK_DESTROY(rt);
 			uma_zfree(V_rtzone, rt);
@@ -1409,8 +1409,8 @@ rtinit1(struct ifaddr *ifa, int cmd, int
 			 */
 			if (memcmp(rt->rt_ifa->ifa_addr,
 			    ifa->ifa_addr, ifa->ifa_addr->sa_len)) {
-				IFAFREE(rt->rt_ifa);
-				IFAREF(ifa);
+				ifa_free(rt->rt_ifa);
+				ifa_ref(ifa);
 				rt->rt_ifp = ifa->ifa_ifp;
 				rt->rt_ifa = ifa;
 			}

Modified: head/sys/net/rtsock.c
==============================================================================
--- head/sys/net/rtsock.c	Sun Jun 21 19:21:01 2009	(r194601)
+++ head/sys/net/rtsock.c	Sun Jun 21 19:30:33 2009	(r194602)
@@ -694,7 +694,7 @@ route_output(struct mbuf *m, struct sock
 			    rt->rt_ifa->ifa_rtrequest != NULL) {
 				rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt,
 				    &info);
-				IFAFREE(rt->rt_ifa);
+				ifa_free(rt->rt_ifa);
 			}
 			if (info.rti_info[RTAX_GATEWAY] != NULL) {
 				RT_UNLOCK(rt);
@@ -712,7 +712,7 @@ route_output(struct mbuf *m, struct sock
 			}
 			if (info.rti_ifa != NULL &&
 			    info.rti_ifa != rt->rt_ifa) {
-				IFAREF(info.rti_ifa);
+				ifa_ref(info.rti_ifa);
 				rt->rt_ifa = info.rti_ifa;
 				rt->rt_ifp = info.rti_ifp;
 			}

Modified: head/sys/netatalk/at_control.c
==============================================================================
--- head/sys/netatalk/at_control.c	Sun Jun 21 19:21:01 2009	(r194601)
+++ head/sys/netatalk/at_control.c	Sun Jun 21 19:30:33 2009	(r194602)
@@ -189,8 +189,7 @@ at_control(struct socket *so, u_long cmd
 			 * and link our new one on the end 
 			 */
 			ifa = (struct ifaddr *)aa;
-			IFA_LOCK_INIT(ifa);
-			ifa->ifa_refcnt = 1;
+			ifa_init(ifa);
 
 			/*
 			 * As the at_ifaddr contains the actual sockaddrs,
@@ -325,7 +324,7 @@ at_control(struct socket *so, u_long cmd
 		/*
 		 * Now reclaim the reference.
 		 */
-		IFAFREE(ifa0);
+		ifa_free(ifa0);
 		break;
 
 	default:

Modified: head/sys/netinet/in.c
==============================================================================
--- head/sys/netinet/in.c	Sun Jun 21 19:21:01 2009	(r194601)
+++ head/sys/netinet/in.c	Sun Jun 21 19:30:33 2009	(r194602)
@@ -377,11 +377,10 @@ in_control(struct socket *so, u_long cmd
 			}
 
 			ifa = &ia->ia_ifa;
-			IFA_LOCK_INIT(ifa);
+			ifa_init(ifa);
 			ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr;
 			ifa->ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
 			ifa->ifa_netmask = (struct sockaddr *)&ia->ia_sockmask;
-			ifa->ifa_refcnt = 1;
 
 			ia->ia_sockmask.sin_len = 8;
 			ia->ia_sockmask.sin_family = AF_INET;
@@ -617,7 +616,7 @@ in_control(struct socket *so, u_long cmd
 			IN_MULTI_UNLOCK();
 		}
 	}
-	IFAFREE(&ia->ia_ifa);
+	ifa_free(&ia->ia_ifa);
 	splx(s);
 
 	return (error);

Modified: head/sys/netinet6/in6.c
==============================================================================
--- head/sys/netinet6/in6.c	Sun Jun 21 19:21:01 2009	(r194601)
+++ head/sys/netinet6/in6.c	Sun Jun 21 19:30:33 2009	(r194602)
@@ -784,9 +784,9 @@ in6_update_ifa(struct ifnet *ifp, struct
 		if (ia == NULL)
 			return (ENOBUFS);
 		bzero((caddr_t)ia, sizeof(*ia));
+		ifa_init(&ia->ia_ifa);
 		LIST_INIT(&ia->ia6_memberships);
 		/* Initialize the address and masks, and put time stamp */
-		IFA_LOCK_INIT(&ia->ia_ifa);
 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
 		ia->ia_addr.sin6_family = AF_INET6;
 		ia->ia_addr.sin6_len = sizeof(ia->ia_addr);
@@ -811,7 +811,6 @@ in6_update_ifa(struct ifnet *ifp, struct
 		} else
 			V_in6_ifaddr = ia;
 
-		ia->ia_ifa.ifa_refcnt = 1;
 		IF_ADDR_LOCK(ifp);
 		TAILQ_INSERT_TAIL(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
 		IF_ADDR_UNLOCK(ifp);
@@ -1387,7 +1386,7 @@ in6_unlink_ifa(struct in6_ifaddr *ia, st
 	 * release another refcnt for the link from in6_ifaddr.
 	 * Note that we should decrement the refcnt at least once for all *BSD.
 	 */
-	IFAFREE(&oia->ia_ifa);
+	ifa_free(&oia->ia_ifa);
 
 	splx(s);
 }

Modified: head/sys/netinet6/in6_ifattach.c
==============================================================================
--- head/sys/netinet6/in6_ifattach.c	Sun Jun 21 19:21:01 2009	(r194601)
+++ head/sys/netinet6/in6_ifattach.c	Sun Jun 21 19:30:33 2009	(r194602)
@@ -827,7 +827,7 @@ in6_ifdetach(struct ifnet *ifp)
 		IF_ADDR_LOCK(ifp);
 		TAILQ_REMOVE(&ifp->if_addrhead, (struct ifaddr *)ia, ifa_link);
 		IF_ADDR_UNLOCK(ifp);
-		IFAFREE(&ia->ia_ifa);
+		ifa_free(&ia->ia_ifa);
 
 		/* also remove from the IPv6 address chain(itojun&jinmei) */
 		oia = ia;
@@ -845,7 +845,7 @@ in6_ifdetach(struct ifnet *ifp)
 			}
 		}
 
-		IFAFREE(&oia->ia_ifa);
+		ifa_free(&oia->ia_ifa);
 	}
 
 	in6_pcbpurgeif0(&V_udbinfo, ifp);

Modified: head/sys/netinet6/nd6_nbr.c
==============================================================================
--- head/sys/netinet6/nd6_nbr.c	Sun Jun 21 19:21:01 2009	(r194601)
+++ head/sys/netinet6/nd6_nbr.c	Sun Jun 21 19:30:33 2009	(r194602)
@@ -1223,7 +1223,7 @@ nd6_dad_start(struct ifaddr *ifa, int de
 	 * (re)initialization.
 	 */
 	dp->dad_ifa = ifa;
-	IFAREF(ifa);	/* just for safety */
+	ifa_ref(ifa);	/* just for safety */
 	dp->dad_count = V_ip6_dad_count;
 	dp->dad_ns_icount = dp->dad_na_icount = 0;
 	dp->dad_ns_ocount = dp->dad_ns_tcount = 0;
@@ -1258,7 +1258,7 @@ nd6_dad_stop(struct ifaddr *ifa)
 	TAILQ_REMOVE(&V_dadq, (struct dadq *)dp, dad_list);
 	free(dp, M_IP6NDP);
 	dp = NULL;
-	IFAFREE(ifa);
+	ifa_free(ifa);
 }
 
 static void
@@ -1301,7 +1301,7 @@ nd6_dad_timer(struct dadq *dp)
 		TAILQ_REMOVE(&V_dadq, (struct dadq *)dp, dad_list);
 		free(dp, M_IP6NDP);
 		dp = NULL;
-		IFAFREE(ifa);
+		ifa_free(ifa);
 		goto done;
 	}
 
@@ -1354,7 +1354,7 @@ nd6_dad_timer(struct dadq *dp)
 			TAILQ_REMOVE(&V_dadq, (struct dadq *)dp, dad_list);
 			free(dp, M_IP6NDP);
 			dp = NULL;
-			IFAFREE(ifa);
+			ifa_free(ifa);
 		}
 	}
 
@@ -1432,7 +1432,7 @@ nd6_dad_duplicated(struct ifaddr *ifa)
 	TAILQ_REMOVE(&V_dadq, (struct dadq *)dp, dad_list);
 	free(dp, M_IP6NDP);
 	dp = NULL;
-	IFAFREE(ifa);
+	ifa_free(ifa);
 }
 
 static void

Modified: head/sys/netipx/ipx.c
==============================================================================
--- head/sys/netipx/ipx.c	Sun Jun 21 19:21:01 2009	(r194601)
+++ head/sys/netipx/ipx.c	Sun Jun 21 19:30:33 2009	(r194602)
@@ -170,8 +170,7 @@ ipx_control(struct socket *so, u_long cm
 				ipx_ifaddr = oia;
 			ia = oia;
 			ifa = (struct ifaddr *)ia;
-			IFA_LOCK_INIT(ifa);
-			ifa->ifa_refcnt = 1;
+			ifa_init(ifa);
 			TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
 			ia->ia_ifp = ifp;
 			ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr;
@@ -231,7 +230,7 @@ ipx_control(struct socket *so, u_long cm
 			else
 				printf("Didn't unlink ipxifadr from list\n");
 		}
-		IFAFREE((&oia->ia_ifa));
+		ifa_free(&oia->ia_ifa);
 		return (0);
 
 	case SIOCAIFADDR:


More information about the svn-src-all mailing list