From owner-svn-src-head@FreeBSD.ORG Mon Jun 11 20:12:14 2012 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 868D5106566B; Mon, 11 Jun 2012 20:12:14 +0000 (UTC) (envelope-from thompsa@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 679C58FC0A; Mon, 11 Jun 2012 20:12:14 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q5BKCEUE007480; Mon, 11 Jun 2012 20:12:14 GMT (envelope-from thompsa@svn.freebsd.org) Received: (from thompsa@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q5BKCE0c007478; Mon, 11 Jun 2012 20:12:14 GMT (envelope-from thompsa@svn.freebsd.org) Message-Id: <201206112012.q5BKCE0c007478@svn.freebsd.org> From: Andrew Thompson Date: Mon, 11 Jun 2012 20:12:14 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r236916 - head/sys/net X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 11 Jun 2012 20:12:14 -0000 Author: thompsa Date: Mon Jun 11 20:12:13 2012 New Revision: 236916 URL: http://svn.freebsd.org/changeset/base/236916 Log: Fix a panic I introduced in r234487, the bridge softc pointer is set to null early in the detach so rearrange things not to explode. Reported by: David Roffiaen, Gustau Perez Querol Tested by: David Roffiaen MFC after: 3 days Modified: head/sys/net/if_bridge.c Modified: head/sys/net/if_bridge.c ============================================================================== --- head/sys/net/if_bridge.c Mon Jun 11 20:01:50 2012 (r236915) +++ head/sys/net/if_bridge.c Mon Jun 11 20:12:13 2012 (r236916) @@ -334,6 +334,7 @@ static int bridge_ip6_checkbasic(struct static int bridge_fragment(struct ifnet *, struct mbuf *, struct ether_header *, int, struct llc *); static void bridge_linkstate(struct ifnet *ifp); +static void bridge_linkcheck(struct bridge_softc *sc); extern void (*bridge_linkstate_p)(struct ifnet *ifp); @@ -964,6 +965,7 @@ bridge_delete_member(struct bridge_softc EVENTHANDLER_INVOKE(iflladdr_event, sc->sc_ifp); } + bridge_linkcheck(sc); bridge_mutecaps(sc); /* recalcuate now this interface is removed */ bridge_rtdelete(sc, ifs, IFBF_FLUSHALL); KASSERT(bif->bif_addrcnt == 0, @@ -993,7 +995,6 @@ bridge_delete_member(struct bridge_softc bridge_set_ifcap(sc, bif, bif->bif_savedcaps); } bstp_destroy(&bif->bif_stp); /* prepare to free */ - bridge_linkstate(ifs); BRIDGE_LOCK(sc); free(bif, M_DEVBUF); } @@ -1092,18 +1093,17 @@ bridge_ioctl_add(struct bridge_softc *sc /* Set interface capabilities to the intersection set of all members */ bridge_mutecaps(sc); + bridge_linkcheck(sc); - BRIDGE_UNLOCK(sc); - /* Update the linkstate for the bridge */ - bridge_linkstate(ifs); /* Place the interface into promiscuous mode */ switch (ifs->if_type) { case IFT_ETHER: case IFT_L2VLAN: + BRIDGE_UNLOCK(sc); error = ifpromisc(ifs, 1); + BRIDGE_LOCK(sc); break; } - BRIDGE_LOCK(sc); if (error) bridge_delete_member(sc, bif, 0); out: @@ -3486,8 +3486,7 @@ static void bridge_linkstate(struct ifnet *ifp) { struct bridge_softc *sc = ifp->if_bridge; - struct bridge_iflist *bif, *bif2; - int new_link, hasls; + struct bridge_iflist *bif; BRIDGE_LOCK(sc); bif = bridge_lookup_member_if(sc, ifp); @@ -3495,13 +3494,26 @@ bridge_linkstate(struct ifnet *ifp) BRIDGE_UNLOCK(sc); return; } + bridge_linkcheck(sc); + BRIDGE_UNLOCK(sc); + + bstp_linkstate(&bif->bif_stp); +} + +static void +bridge_linkcheck(struct bridge_softc *sc) +{ + struct bridge_iflist *bif; + int new_link, hasls; + + BRIDGE_LOCK_ASSERT(sc); new_link = LINK_STATE_DOWN; hasls = 0; /* Our link is considered up if at least one of our ports is active */ - LIST_FOREACH(bif2, &sc->sc_iflist, bif_next) { - if (bif2->bif_ifp->if_capabilities & IFCAP_LINKSTATE) + LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { + if (bif->bif_ifp->if_capabilities & IFCAP_LINKSTATE) hasls++; - if (bif2->bif_ifp->if_link_state == LINK_STATE_UP) { + if (bif->bif_ifp->if_link_state == LINK_STATE_UP) { new_link = LINK_STATE_UP; break; } @@ -3511,8 +3523,4 @@ bridge_linkstate(struct ifnet *ifp) new_link = LINK_STATE_UP; } if_link_state_change(sc->sc_ifp, new_link); - BRIDGE_UNLOCK(sc); - - bstp_linkstate(&bif->bif_stp); } -