Since dp->dom_ifattach calls malloc() with M_WAITOK, we cannot

use mutex lock directly here.  Protect ifp->if_afdata instead.

Reported by:	grehan
This commit is contained in:
Hajimu UMEMOTO 2003-10-24 16:57:59 +00:00
parent 7298db81fe
commit 234a35c714
2 changed files with 30 additions and 2 deletions

View File

@ -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);
}

View File

@ -180,6 +180,8 @@ struct ifnet {
struct label if_label; /* interface MAC label */
void *if_afdata[AF_MAX];
int if_afdata_initialized;
struct mtx if_afdata_mtx;
};
typedef void if_init_f_t(void *);
@ -289,6 +291,13 @@ typedef void if_init_f_t(void *);
} while (0)
#ifdef _KERNEL
#define IF_AFDATA_LOCK_INIT(ifp) \
mtx_init(&(ifp)->if_afdata_mtx, "if_afdata", NULL, MTX_DEF)
#define IF_AFDATA_LOCK(ifp) mtx_lock(&(ifp)->if_afdata_mtx)
#define IF_AFDATA_TRYLOCK(ifp) mtx_trylock(&(ifp)->if_afdata_mtx)
#define IF_AFDATA_UNLOCK(ifp) mtx_unlock(&(ifp)->if_afdata_mtx)
#define IF_AFDATA_DESTROY(ifp) mtx_destroy(&(ifp)->if_afdata_mtx)
#define IF_HANDOFF(ifq, m, ifp) if_handoff(ifq, m, ifp, 0)
#define IF_HANDOFF_ADJ(ifq, m, ifp, adj) if_handoff(ifq, m, ifp, adj)