diff options
author | ume <ume@FreeBSD.org> | 2003-10-24 16:57:59 +0000 |
---|---|---|
committer | ume <ume@FreeBSD.org> | 2003-10-24 16:57:59 +0000 |
commit | eae980f878292d49d725e3ef2b1b3b15c2914013 (patch) | |
tree | 750fae5cf23a0f412dffeec3d6ebb79f018f0334 /sys/net/if.c | |
parent | b220e7e690bce5c495774572990e4de021ab2598 (diff) | |
download | FreeBSD-src-eae980f878292d49d725e3ef2b1b3b15c2914013.zip FreeBSD-src-eae980f878292d49d725e3ef2b1b3b15c2914013.tar.gz |
Since dp->dom_ifattach calls malloc() with M_WAITOK, we cannot
use mutex lock directly here. Protect ifp->if_afdata instead.
Reported by: grehan
Diffstat (limited to 'sys/net/if.c')
-rw-r--r-- | sys/net/if.c | 23 |
1 files changed, 21 insertions, 2 deletions
diff --git a/sys/net/if.c b/sys/net/if.c index d59cde8..0d1738f 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -369,6 +369,8 @@ if_attach(struct ifnet *ifp) struct sockaddr_dl *sdl; struct ifaddr *ifa; + IF_AFDATA_LOCK_INIT(ifp); + ifp->if_afdata_initialized = 0; IFNET_WLOCK(); TAILQ_INSERT_TAIL(&ifnet, ifp, if_link); IFNET_WUNLOCK(); @@ -456,10 +458,8 @@ if_attachdomain(void *dummy) int s; s = splnet(); - IFNET_RLOCK(); for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list)) if_attachdomain1(ifp); - IFNET_RUNLOCK(); splx(s); } SYSINIT(domainifattach, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_FIRST, @@ -473,6 +473,22 @@ if_attachdomain1(struct ifnet *ifp) s = splnet(); + /* + * Since dp->dom_ifattach calls malloc() with M_WAITOK, we + * cannot lock ifp->if_afdata initialization, entirely. + */ + if (IF_AFDATA_TRYLOCK(ifp) == 0) { + splx(s); + return; + } + if (ifp->if_afdata_initialized) { + IF_AFDATA_UNLOCK(ifp); + splx(s); + return; + } + ifp->if_afdata_initialized = 1; + IF_AFDATA_UNLOCK(ifp); + /* address family dependent data region */ bzero(ifp->if_afdata, sizeof(ifp->if_afdata)); for (dp = domains; dp; dp = dp->dom_next) { @@ -576,11 +592,13 @@ if_detach(struct ifnet *ifp) /* Announce that the interface is gone. */ rt_ifannouncemsg(ifp, IFAN_DEPARTURE); + IF_AFDATA_LOCK(ifp); for (dp = domains; dp; dp = dp->dom_next) { if (dp->dom_ifdetach && ifp->if_afdata[dp->dom_family]) (*dp->dom_ifdetach)(ifp, ifp->if_afdata[dp->dom_family]); } + IF_AFDATA_UNLOCK(ifp); #ifdef MAC mac_destroy_ifnet(ifp); @@ -590,6 +608,7 @@ if_detach(struct ifnet *ifp) TAILQ_REMOVE(&ifnet, ifp, if_link); IFNET_WUNLOCK(); mtx_destroy(&ifp->if_snd.ifq_mtx); + IF_AFDATA_DESTROY(ifp); splx(s); } |