From 2895d8d1ead2cb27aa5b4e8936023131e85c8b1c Mon Sep 17 00:00:00 2001 From: rwatson Date: Tue, 9 Mar 2004 16:31:19 +0000 Subject: Introduce disc_mtx to protect the global softc list in if_disc. Since there are two destroy paths for if_disc interfaces -- module unload and cloan interface destroy, create a new utility function disc_destroy(), which is callded on a softc after it has been removed from the global softc list; the cloaner and module unload entry paths will both remove it before calling disc_destroy(). Reviewed by: pjd --- sys/net/if_disc.c | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) (limited to 'sys/net') diff --git a/sys/net/if_disc.c b/sys/net/if_disc.c index bc1f0ad..701c24d 100644 --- a/sys/net/if_disc.c +++ b/sys/net/if_disc.c @@ -76,6 +76,7 @@ static int discioctl(struct ifnet *, u_long, caddr_t); static int disc_clone_create(struct if_clone *, int); static void disc_clone_destroy(struct ifnet *); +static struct mtx disc_mtx; static MALLOC_DEFINE(M_DISC, DISCNAME, "Discard interface"); static LIST_HEAD(, disc_softc) disc_softc_list; static struct if_clone disc_cloner = IF_CLONE_INITIALIZER(DISCNAME, @@ -104,39 +105,59 @@ disc_clone_create(struct if_clone *ifc, int unit) ifp->if_snd.ifq_maxlen = 20; if_attach(ifp); bpfattach(ifp, DLT_NULL, sizeof(u_int)); + mtx_lock(&disc_mtx); LIST_INSERT_HEAD(&disc_softc_list, sc, sc_list); + mtx_unlock(&disc_mtx); return (0); } static void +disc_destroy(struct disc_softc *sc) +{ + + bpfdetach(&sc->sc_if); + if_detach(&sc->sc_if); + + free(sc, M_DISC); +} + +static void disc_clone_destroy(struct ifnet *ifp) { struct disc_softc *sc; sc = ifp->if_softc; - + mtx_lock(&disc_mtx); LIST_REMOVE(sc, sc_list); - bpfdetach(ifp); - if_detach(ifp); + mtx_unlock(&disc_mtx); - free(sc, M_DISC); + disc_destroy(sc); } static int disc_modevent(module_t mod, int type, void *data) -{ +{ + struct disc_softc *sc; + switch (type) { case MOD_LOAD: + mtx_init(&disc_mtx, "disc_mtx", NULL, MTX_DEF); LIST_INIT(&disc_softc_list); if_clone_attach(&disc_cloner); break; case MOD_UNLOAD: if_clone_detach(&disc_cloner); - while (!LIST_EMPTY(&disc_softc_list)) - disc_clone_destroy( - &LIST_FIRST(&disc_softc_list)->sc_if); + mtx_lock(&disc_mtx); + while ((sc = LIST_FIRST(&disc_softc_list)) != NULL) { + LIST_REMOVE(sc, sc_list); + mtx_unlock(&disc_mtx); + disc_destroy(sc); + mtx_lock(&disc_mtx); + } + mtx_unlock(&disc_mtx); + mtx_destroy(&disc_mtx); break; } return 0; -- cgit v1.1