summaryrefslogtreecommitdiffstats
path: root/sys/net
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2004-03-09 16:31:19 +0000
committerrwatson <rwatson@FreeBSD.org>2004-03-09 16:31:19 +0000
commit2895d8d1ead2cb27aa5b4e8936023131e85c8b1c (patch)
tree9a4b02608a664b4fa12b7995ed456e6312b690c5 /sys/net
parent97051410207dab26540eac36237466ff6f2f9be5 (diff)
downloadFreeBSD-src-2895d8d1ead2cb27aa5b4e8936023131e85c8b1c.zip
FreeBSD-src-2895d8d1ead2cb27aa5b4e8936023131e85c8b1c.tar.gz
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
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/if_disc.c37
1 files changed, 29 insertions, 8 deletions
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;
OpenPOWER on IntegriCloud