svn commit: r346300 - in stable: 11/sys/net 12/sys/net

Kyle Evans kevans at FreeBSD.org
Tue Apr 16 20:56:53 UTC 2019


Author: kevans
Date: Tue Apr 16 20:56:51 2019
New Revision: 346300
URL: https://svnweb.freebsd.org/changeset/base/346300

Log:
  MFC r345180, r345187: if_bridge(4): Fix module teardown
  
  r345180: if_bridge(4): Fix module teardown
  
  bridge_rtnode_zone still has outstanding allocations at the time of
  destruction in the current model because all of the interface teardown
  happens in a VNET_SYSUNINIT, -after- the MOD_UNLOAD has already been
  processed.  The SYSUNINIT triggers destruction of the interfaces, which then
  attempts to free the memory from the zone that's already been destroyed, and
  we hit a panic.
  
  Solve this by virtualizing the uma_zone we allocate the rtnodes from to fix
  the ordering. bridge_rtable_fini should also take care to flush any
  remaining routes that weren't taken care of when dynamic routes were flushed
  in bridge_stop.
  
  r345187: bridge: Fix STP-related panic
  
  After r345180 we need to have the appropriate vnet context set to delete an
  rtnode in bridge_rtnode_destroy().
  That's usually the case, but not when it's called by the STP code (through
  bstp_notify_rtage()).
  
  We have to set the vnet context in bridge_rtable_expire() just as we do in the
  other STP callback bridge_state_change().

Modified:
  stable/12/sys/net/if_bridge.c
Directory Properties:
  stable/12/   (props changed)

Changes in other areas also in this revision:
Modified:
  stable/11/sys/net/if_bridge.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/12/sys/net/if_bridge.c
==============================================================================
--- stable/12/sys/net/if_bridge.c	Tue Apr 16 20:41:04 2019	(r346299)
+++ stable/12/sys/net/if_bridge.c	Tue Apr 16 20:56:51 2019	(r346300)
@@ -235,7 +235,8 @@ static eventhandler_tag bridge_detach_cookie;
 
 int	bridge_rtable_prune_period = BRIDGE_RTABLE_PRUNE_PERIOD;
 
-uma_zone_t bridge_rtnode_zone;
+VNET_DEFINE_STATIC(uma_zone_t, bridge_rtnode_zone);
+#define	V_bridge_rtnode_zone	VNET(bridge_rtnode_zone)
 
 static int	bridge_clone_create(struct if_clone *, int, caddr_t);
 static void	bridge_clone_destroy(struct ifnet *);
@@ -527,6 +528,9 @@ static void
 vnet_bridge_init(const void *unused __unused)
 {
 
+	V_bridge_rtnode_zone = uma_zcreate("bridge_rtnode",
+	    sizeof(struct bridge_rtnode), NULL, NULL, NULL, NULL,
+	    UMA_ALIGN_PTR, 0);
 	BRIDGE_LIST_LOCK_INIT();
 	LIST_INIT(&V_bridge_list);
 	V_bridge_cloner = if_clone_simple(bridge_name,
@@ -542,6 +546,7 @@ vnet_bridge_uninit(const void *unused __unused)
 	if_clone_detach(V_bridge_cloner);
 	V_bridge_cloner = NULL;
 	BRIDGE_LIST_LOCK_DESTROY();
+	uma_zdestroy(V_bridge_rtnode_zone);
 }
 VNET_SYSUNINIT(vnet_bridge_uninit, SI_SUB_PSEUDO, SI_ORDER_ANY,
     vnet_bridge_uninit, NULL);
@@ -552,9 +557,6 @@ bridge_modevent(module_t mod, int type, void *data)
 
 	switch (type) {
 	case MOD_LOAD:
-		bridge_rtnode_zone = uma_zcreate("bridge_rtnode",
-		    sizeof(struct bridge_rtnode), NULL, NULL, NULL, NULL,
-		    UMA_ALIGN_PTR, 0);
 		bridge_dn_p = bridge_dummynet;
 		bridge_detach_cookie = EVENTHANDLER_REGISTER(
 		    ifnet_departure_event, bridge_ifdetach, NULL,
@@ -563,7 +565,6 @@ bridge_modevent(module_t mod, int type, void *data)
 	case MOD_UNLOAD:
 		EVENTHANDLER_DEREGISTER(ifnet_departure_event,
 		    bridge_detach_cookie);
-		uma_zdestroy(bridge_rtnode_zone);
 		bridge_dn_p = NULL;
 		break;
 	default:
@@ -732,6 +733,9 @@ bridge_clone_destroy(struct ifnet *ifp)
 		bridge_delete_span(sc, bif);
 	}
 
+	/* Tear down the routing table. */
+	bridge_rtable_fini(sc);
+
 	BRIDGE_UNLOCK(sc);
 
 	callout_drain(&sc->sc_brcallout);
@@ -744,9 +748,6 @@ bridge_clone_destroy(struct ifnet *ifp)
 	ether_ifdetach(ifp);
 	if_free(ifp);
 
-	/* Tear down the routing table. */
-	bridge_rtable_fini(sc);
-
 	BRIDGE_LOCK_DESTROY(sc);
 	free(sc, M_DEVBUF);
 }
@@ -2671,7 +2672,7 @@ bridge_rtupdate(struct bridge_softc *sc, const uint8_t
 		 * initialize the expiration time and Ethernet
 		 * address.
 		 */
-		brt = uma_zalloc(bridge_rtnode_zone, M_NOWAIT | M_ZERO);
+		brt = uma_zalloc(V_bridge_rtnode_zone, M_NOWAIT | M_ZERO);
 		if (brt == NULL)
 			return (ENOMEM);
 
@@ -2684,7 +2685,7 @@ bridge_rtupdate(struct bridge_softc *sc, const uint8_t
 		brt->brt_vlan = vlan;
 
 		if ((error = bridge_rtnode_insert(sc, brt)) != 0) {
-			uma_zfree(bridge_rtnode_zone, brt);
+			uma_zfree(V_bridge_rtnode_zone, brt);
 			return (error);
 		}
 		brt->brt_dst = bif;
@@ -2768,11 +2769,14 @@ bridge_timer(void *arg)
 
 	BRIDGE_LOCK_ASSERT(sc);
 
+	/* Destruction of rtnodes requires a proper vnet context */
+	CURVNET_SET(sc->sc_ifp->if_vnet);
 	bridge_rtage(sc);
 
 	if (sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING)
 		callout_reset(&sc->sc_brcallout,
 		    bridge_rtable_prune_period * hz, bridge_timer, sc);
+	CURVNET_RESTORE();
 }
 
 /*
@@ -2888,6 +2892,7 @@ bridge_rtable_fini(struct bridge_softc *sc)
 
 	KASSERT(sc->sc_brtcnt == 0,
 	    ("%s: %d bridge routes referenced", __func__, sc->sc_brtcnt));
+	bridge_rtflush(sc, 1);
 	free(sc->sc_rthash, M_DEVBUF);
 }
 
@@ -3030,7 +3035,7 @@ bridge_rtnode_destroy(struct bridge_softc *sc, struct 
 	LIST_REMOVE(brt, brt_list);
 	sc->sc_brtcnt--;
 	brt->brt_dst->bif_addrcnt--;
-	uma_zfree(bridge_rtnode_zone, brt);
+	uma_zfree(V_bridge_rtnode_zone, brt);
 }
 
 /*
@@ -3044,6 +3049,7 @@ bridge_rtable_expire(struct ifnet *ifp, int age)
 	struct bridge_softc *sc = ifp->if_bridge;
 	struct bridge_rtnode *brt;
 
+	CURVNET_SET(ifp->if_vnet);
 	BRIDGE_LOCK(sc);
 
 	/*
@@ -3062,6 +3068,7 @@ bridge_rtable_expire(struct ifnet *ifp, int age)
 		}
 	}
 	BRIDGE_UNLOCK(sc);
+	CURVNET_RESTORE();
 }
 
 /*


More information about the svn-src-all mailing list