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:
parent
7298db81fe
commit
234a35c714
23
sys/net/if.c
23
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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user