summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorglebius <glebius@FreeBSD.org>2007-01-25 18:03:40 +0000
committerglebius <glebius@FreeBSD.org>2007-01-25 18:03:40 +0000
commit34079a8c028f16408396736a45b0ddd5f321b1d6 (patch)
treedc689bfb8d44619237853638dd66bc8386a02cad
parent94549ac2834c106a7c40edf6b5d0b8028181ea8b (diff)
downloadFreeBSD-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.c15
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);
}
}
OpenPOWER on IntegriCloud