diff options
author | glebius <glebius@FreeBSD.org> | 2007-01-25 18:03:40 +0000 |
---|---|---|
committer | glebius <glebius@FreeBSD.org> | 2007-01-25 18:03:40 +0000 |
commit | 34079a8c028f16408396736a45b0ddd5f321b1d6 (patch) | |
tree | dc689bfb8d44619237853638dd66bc8386a02cad | |
parent | 94549ac2834c106a7c40edf6b5d0b8028181ea8b (diff) | |
download | FreeBSD-src-34079a8c028f16408396736a45b0ddd5f321b1d6.zip FreeBSD-src-34079a8c028f16408396736a45b0ddd5f321b1d6.tar.gz |
Make it possible that carpdetach() unlocks on return. Then, in
carp_clone_destroy() we are on a safe side, we don't need to
unlock the cif, that can me already non-existent at this point.
Reported by: Anton Yuzhaninov <citrin rambler-co.ru>
-rw-r--r-- | sys/netinet/ip_carp.c | 15 |
1 files changed, 7 insertions, 8 deletions
diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c index 8a3dfd1..87bb1c9 100644 --- a/sys/netinet/ip_carp.c +++ b/sys/netinet/ip_carp.c @@ -192,7 +192,7 @@ static void carp_setroute(struct carp_softc *, int); static void carp_input_c(struct mbuf *, struct carp_header *, sa_family_t); static int carp_clone_create(struct if_clone *, int, caddr_t); static void carp_clone_destroy(struct ifnet *); -static void carpdetach(struct carp_softc *); +static void carpdetach(struct carp_softc *, int); static int carp_prepare_ad(struct mbuf *, struct carp_softc *, struct carp_header *); static void carp_send_ad_all(void); @@ -411,9 +411,7 @@ carp_clone_destroy(struct ifnet *ifp) if (sc->sc_carpdev) CARP_SCLOCK(sc); - carpdetach(sc); - if (sc->sc_carpdev) - CARP_SCUNLOCK(sc); + carpdetach(sc, 1); /* Returns unlocked. */ mtx_lock(&carp_mtx); LIST_REMOVE(sc, sc_next); @@ -426,7 +424,7 @@ carp_clone_destroy(struct ifnet *ifp) } static void -carpdetach(struct carp_softc *sc) +carpdetach(struct carp_softc *sc, int unlock) { struct carp_if *cif; @@ -456,9 +454,10 @@ carpdetach(struct carp_softc *sc) sc->sc_carpdev->if_carp = NULL; CARP_LOCK_DESTROY(cif); FREE(cif, M_IFADDR); - } + } else if (unlock) + CARP_UNLOCK(cif); + sc->sc_carpdev = NULL; } - sc->sc_carpdev = NULL; } /* Detach an interface from the carp. */ @@ -477,7 +476,7 @@ carp_ifdetach(void *arg __unused, struct ifnet *ifp) CARP_LOCK(cif); for (sc = TAILQ_FIRST(&cif->vhif_vrs); sc; sc = nextsc) { nextsc = TAILQ_NEXT(sc, sc_list); - carpdetach(sc); + carpdetach(sc, 0); } } |