diff options
author | rwatson <rwatson@FreeBSD.org> | 2004-03-09 19:23:06 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2004-03-09 19:23:06 +0000 |
commit | 63f793ca249823f0c3812457a8342dd6702d0548 (patch) | |
tree | 5743f3bb6cfced802b5012a83e5038bc924598bd /sys/net/if_faith.c | |
parent | 696d0d4e7fdd6d7c8ef68038b94148e516ab1a1d (diff) | |
download | FreeBSD-src-63f793ca249823f0c3812457a8342dd6702d0548.zip FreeBSD-src-63f793ca249823f0c3812457a8342dd6702d0548.tar.gz |
Introduce faith_mtx to protect the if_faith global softc list.
Push if_faith softc destruction logic into faith_destroy() so that
it can be called after softc list removal in both the clone destroy
and module unload paths.
Diffstat (limited to 'sys/net/if_faith.c')
-rw-r--r-- | sys/net/if_faith.c | 34 |
1 files changed, 27 insertions, 7 deletions
diff --git a/sys/net/if_faith.c b/sys/net/if_faith.c index 06e60cd..6a46e86 100644 --- a/sys/net/if_faith.c +++ b/sys/net/if_faith.c @@ -99,11 +99,13 @@ static int faithprefix(struct in6_addr *); static int faithmodevent(module_t, int, void *); +static struct mtx faith_mtx; static MALLOC_DEFINE(M_FAITH, FAITHNAME, "Firewall Assisted Tunnel Interface"); static LIST_HEAD(, faith_softc) faith_softc_list; int faith_clone_create(struct if_clone *, int); void faith_clone_destroy(struct ifnet *); +static void faith_destroy(struct faith_softc *); struct if_clone faith_cloner = IF_CLONE_INITIALIZER(FAITHNAME, faith_clone_create, faith_clone_destroy, 0, IF_MAXUNIT); @@ -116,9 +118,11 @@ faithmodevent(mod, type, data) int type; void *data; { + struct faith_softc *sc; switch (type) { case MOD_LOAD: + mtx_init(&faith_mtx, "faith_mtx", NULL, MTX_DEF); LIST_INIT(&faith_softc_list); if_clone_attach(&faith_cloner); @@ -134,10 +138,15 @@ faithmodevent(mod, type, data) if_clone_detach(&faith_cloner); - while (!LIST_EMPTY(&faith_softc_list)) - faith_clone_destroy( - &LIST_FIRST(&faith_softc_list)->sc_if); - + mtx_lock(&faith_mtx); + while ((sc = LIST_FIRST(&faith_softc_list)) != NULL) { + LIST_REMOVE(sc, sc_list); + mtx_unlock(&faith_mtx); + faith_destroy(sc); + mtx_lock(&faith_mtx); + } + mtx_unlock(&faith_mtx); + mtx_destroy(&faith_mtx); break; } return 0; @@ -176,21 +185,32 @@ faith_clone_create(ifc, unit) sc->sc_if.if_snd.ifq_maxlen = ifqmaxlen; if_attach(&sc->sc_if); bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int)); + mtx_lock(&faith_mtx); LIST_INSERT_HEAD(&faith_softc_list, sc, sc_list); + mtx_unlock(&faith_mtx); return (0); } +static void +faith_destroy(struct faith_softc *sc) +{ + + bpfdetach(&sc->sc_if); + if_detach(&sc->sc_if); + free(sc, M_FAITH); +} + void faith_clone_destroy(ifp) struct ifnet *ifp; { struct faith_softc *sc = (void *) ifp; + mtx_lock(&faith_mtx); LIST_REMOVE(sc, sc_list); - bpfdetach(ifp); - if_detach(ifp); + mtx_unlock(&faith_mtx); - free(sc, M_FAITH); + faith_destroy(sc); } int |