summaryrefslogtreecommitdiffstats
path: root/sys/net/if.c
diff options
context:
space:
mode:
authorume <ume@FreeBSD.org>2003-10-24 16:57:59 +0000
committerume <ume@FreeBSD.org>2003-10-24 16:57:59 +0000
commiteae980f878292d49d725e3ef2b1b3b15c2914013 (patch)
tree750fae5cf23a0f412dffeec3d6ebb79f018f0334 /sys/net/if.c
parentb220e7e690bce5c495774572990e4de021ab2598 (diff)
downloadFreeBSD-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.c23
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);
}
OpenPOWER on IntegriCloud