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