svn commit: r191528 - head/sys/netinet

Robert Watson rwatson at FreeBSD.org
Sun Apr 26 19:05:40 UTC 2009


Author: rwatson
Date: Sun Apr 26 19:05:40 2009
New Revision: 191528
URL: http://svn.freebsd.org/changeset/base/191528

Log:
  Acquire IF_ADDR_LOCK() around most iterations over ifp->if_addrhead
  (colloquially known as if_addrlist).  Currently not acquired around
  interface address loops that call out to the routing code due to
  potential lock order issues.
  
  MFC after:	3 weeks

Modified:
  head/sys/netinet/ip_carp.c

Modified: head/sys/netinet/ip_carp.c
==============================================================================
--- head/sys/netinet/ip_carp.c	Sun Apr 26 18:57:50 2009	(r191527)
+++ head/sys/netinet/ip_carp.c	Sun Apr 26 19:05:40 2009	(r191528)
@@ -275,6 +275,7 @@ carp_hmac_prepare(struct carp_softc *sc)
 		found = 0;
 		last = cur;
 		cur.s_addr = 0xffffffff;
+		IF_ADDR_LOCK(SC2IFP(sc));
 		TAILQ_FOREACH(ifa, &SC2IFP(sc)->if_addrlist, ifa_list) {
 			in.s_addr = ifatoia(ifa)->ia_addr.sin_addr.s_addr;
 			if (ifa->ifa_addr->sa_family == AF_INET &&
@@ -284,6 +285,7 @@ carp_hmac_prepare(struct carp_softc *sc)
 				found++;
 			}
 		}
+		IF_ADDR_UNLOCK(SC2IFP(sc));
 		if (found)
 			SHA1Update(&sc->sc_sha1, (void *)&cur, sizeof(cur));
 	} while (found);
@@ -294,6 +296,7 @@ carp_hmac_prepare(struct carp_softc *sc)
 		found = 0;
 		last6 = cur6;
 		memset(&cur6, 0xff, sizeof(cur6));
+		IF_ADDR_LOCK(SC2IFP(sc));
 		TAILQ_FOREACH(ifa, &SC2IFP(sc)->if_addrlist, ifa_list) {
 			in6 = ifatoia6(ifa)->ia_addr.sin6_addr;
 			if (IN6_IS_SCOPE_EMBED(&in6))
@@ -305,6 +308,7 @@ carp_hmac_prepare(struct carp_softc *sc)
 				found++;
 			}
 		}
+		IF_ADDR_UNLOCK(SC2IFP(sc));
 		if (found)
 			SHA1Update(&sc->sc_sha1, (void *)&cur6, sizeof(cur6));
 	} while (found);
@@ -1121,6 +1125,7 @@ carp_addrcount(struct carp_if *cif, stru
 		    (SC2IFP(vh)->if_flags & IFF_UP) &&
 		    (SC2IFP(vh)->if_drv_flags & IFF_DRV_RUNNING)) ||
 		    (type == CARP_COUNT_MASTER && vh->sc_state == MASTER)) {
+			IF_ADDR_LOCK(SC2IFP(vh));
 			TAILQ_FOREACH(ifa, &SC2IFP(vh)->if_addrlist,
 			    ifa_list) {
 				if (ifa->ifa_addr->sa_family == AF_INET &&
@@ -1128,6 +1133,7 @@ carp_addrcount(struct carp_if *cif, stru
 				    ifatoia(ifa)->ia_addr.sin_addr.s_addr)
 					count++;
 			}
+			IF_ADDR_UNLOCK(SC2IFP(vh));
 		}
 	}
 	return (count);
@@ -1166,6 +1172,7 @@ carp_iamatch(void *v, struct in_ifaddr *
 		TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list) {
 			if ((SC2IFP(vh)->if_flags & IFF_UP) &&
 			    (SC2IFP(vh)->if_drv_flags & IFF_DRV_RUNNING)) {
+				IF_ADDR_LOCK(SC2IFP(vh));
 				TAILQ_FOREACH(ifa, &SC2IFP(vh)->if_addrlist,
 				    ifa_list) {
 					if (ifa->ifa_addr->sa_family ==
@@ -1176,9 +1183,11 @@ carp_iamatch(void *v, struct in_ifaddr *
 							if (vh->sc_state ==
 							    MASTER) {
 								*enaddr = IF_LLADDR(vh->sc_ifp);
+								IF_ADDR_UNLOCK(SC2IFP(vh));
 								CARP_UNLOCK(cif);
 								return (1);
 							} else {
+								IF_ADDR_UNLOCK(SC2IFP(vh));
 								CARP_UNLOCK(cif);
 								return (0);
 							}
@@ -1186,6 +1195,7 @@ carp_iamatch(void *v, struct in_ifaddr *
 						count++;
 					}
 				}
+				IF_ADDR_UNLOCK(SC2IFP(vh));
 			}
 		}
 	} else {
@@ -1214,16 +1224,19 @@ carp_iamatch6(void *v, struct in6_addr *
 
 	CARP_LOCK(cif);
 	TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list) {
+		IF_ADDR_LOCK(SC2IFP(vh));
 		TAILQ_FOREACH(ifa, &SC2IFP(vh)->if_addrlist, ifa_list) {
 			if (IN6_ARE_ADDR_EQUAL(taddr,
 			    &ifatoia6(ifa)->ia_addr.sin6_addr) &&
  			    (SC2IFP(vh)->if_flags & IFF_UP) &&
 			    (SC2IFP(vh)->if_drv_flags & IFF_DRV_RUNNING) &&
 			    vh->sc_state == MASTER) {
+				IF_ADDR_UNLOCK(SC2IFP(vh));
 			    	CARP_UNLOCK(cif);
 				return (ifa);
 			}
 		}
+		IF_ADDR_UNLOCK(SC2IFP(vh));
 	}
 	CARP_UNLOCK(cif);
 	
@@ -1240,6 +1253,7 @@ carp_macmatch6(void *v, struct mbuf *m, 
 
 	CARP_LOCK(cif);
 	TAILQ_FOREACH(sc, &cif->vhif_vrs, sc_list) {
+		IF_ADDR_LOCK(SC2IFP(sc));
 		TAILQ_FOREACH(ifa, &SC2IFP(sc)->if_addrlist, ifa_list) {
 			if (IN6_ARE_ADDR_EQUAL(taddr,
 			    &ifatoia6(ifa)->ia_addr.sin6_addr) &&
@@ -1250,6 +1264,7 @@ carp_macmatch6(void *v, struct mbuf *m, 
 				    sizeof(struct ifnet *), M_NOWAIT);
 				if (mtag == NULL) {
 					/* better a bit than nothing */
+					IF_ADDR_UNLOCK(SC2IFP(sc));
 					CARP_UNLOCK(cif);
 					return (IF_LLADDR(sc->sc_ifp));
 				}
@@ -1257,10 +1272,12 @@ carp_macmatch6(void *v, struct mbuf *m, 
 				    sizeof(struct ifnet *));
 				m_tag_prepend(m, mtag);
 
+				IF_ADDR_UNLOCK(SC2IFP(sc));
 				CARP_UNLOCK(cif);
 				return (IF_LLADDR(sc->sc_ifp));
 			}
 		}
+		IF_ADDR_UNLOCK(SC2IFP(sc));
 	}
 	CARP_UNLOCK(cif);
 


More information about the svn-src-all mailing list