git: 8ad5619ec3b8 - stable/13 - ng_bridge: Use M_NOWAIT when allocating memory in the newhook routine

Mark Johnston markj at FreeBSD.org
Fri Aug 20 12:42:53 UTC 2021


The branch stable/13 has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=8ad5619ec3b848844cb278582e9a4a32ed0f863d

commit 8ad5619ec3b848844cb278582e9a4a32ed0f863d
Author:     Mark Johnston <markj at FreeBSD.org>
AuthorDate: 2021-08-13 13:49:43 +0000
Commit:     Mark Johnston <markj at FreeBSD.org>
CommitDate: 2021-08-20 12:42:43 +0000

    ng_bridge: Use M_NOWAIT when allocating memory in the newhook routine
    
    newhook can be invoked by ngthread, which runs in a network epoch
    section and is thus not permitted to perform M_WAITOK allocations.
    
    Reported by:    Jenkins
    Reviewed by:    donner, afedorov
    Sponsored by:   The FreeBSD Foundation
    
    (cherry picked from commit e0e3ded78a5d0859f3520c541726b815897ba7b0)
---
 sys/netgraph/ng_bridge.c | 84 ++++++++++++++++++++++++++++++------------------
 1 file changed, 52 insertions(+), 32 deletions(-)

diff --git a/sys/netgraph/ng_bridge.c b/sys/netgraph/ng_bridge.c
index 3f3d8b3c406e..9bcc7aac271b 100644
--- a/sys/netgraph/ng_bridge.c
+++ b/sys/netgraph/ng_bridge.c
@@ -154,6 +154,7 @@ static ng_rcvdata_t	ng_bridge_rcvdata;
 static ng_disconnect_t	ng_bridge_disconnect;
 
 /* Other internal functions */
+static void	ng_bridge_free_link(link_p link);
 static struct	ng_bridge_host *ng_bridge_get(priv_cp priv, const u_char *addr);
 static int	ng_bridge_put(priv_p priv, const u_char *addr, link_p link);
 static void	ng_bridge_rehash(priv_p priv);
@@ -395,28 +396,36 @@ ng_bridge_newhook(node_p node, hook_p hook, const char *name)
 	if(NG_PEER_NODE(hook) == node)
 	        return (ELOOP);
 
-	link = malloc(sizeof(*link), M_NETGRAPH_BRIDGE, M_WAITOK | M_ZERO);
-
-	link->stats.recvOctets = counter_u64_alloc(M_WAITOK);
-	link->stats.recvPackets = counter_u64_alloc(M_WAITOK);
-	link->stats.recvMulticasts = counter_u64_alloc(M_WAITOK);
-	link->stats.recvBroadcasts = counter_u64_alloc(M_WAITOK);
-	link->stats.recvUnknown = counter_u64_alloc(M_WAITOK);
-	link->stats.recvRunts = counter_u64_alloc(M_WAITOK);
-	link->stats.recvInvalid = counter_u64_alloc(M_WAITOK);
-	link->stats.xmitOctets = counter_u64_alloc(M_WAITOK);
-	link->stats.xmitPackets = counter_u64_alloc(M_WAITOK);
-	link->stats.xmitMulticasts = counter_u64_alloc(M_WAITOK);
-	link->stats.xmitBroadcasts = counter_u64_alloc(M_WAITOK);
-	link->stats.loopDrops = counter_u64_alloc(M_WAITOK);
-	link->stats.memoryFailures = counter_u64_alloc(M_WAITOK);
+	link = malloc(sizeof(*link), M_NETGRAPH_BRIDGE, M_NOWAIT | M_ZERO);
+	if (link == NULL)
+		return (ENOMEM);
+
+#define	NG_BRIDGE_COUNTER_ALLOC(f) do {			\
+	link->stats.f = counter_u64_alloc(M_NOWAIT);	\
+	if (link->stats.f == NULL)			\
+		goto nomem;				\
+} while (0)
+	NG_BRIDGE_COUNTER_ALLOC(recvOctets);
+	NG_BRIDGE_COUNTER_ALLOC(recvPackets);
+	NG_BRIDGE_COUNTER_ALLOC(recvMulticasts);
+	NG_BRIDGE_COUNTER_ALLOC(recvBroadcasts);
+	NG_BRIDGE_COUNTER_ALLOC(recvUnknown);
+	NG_BRIDGE_COUNTER_ALLOC(recvRunts);
+	NG_BRIDGE_COUNTER_ALLOC(recvInvalid);
+	NG_BRIDGE_COUNTER_ALLOC(xmitOctets);
+	NG_BRIDGE_COUNTER_ALLOC(xmitPackets);
+	NG_BRIDGE_COUNTER_ALLOC(xmitMulticasts);
+	NG_BRIDGE_COUNTER_ALLOC(xmitBroadcasts);
+	NG_BRIDGE_COUNTER_ALLOC(loopDrops);
+	NG_BRIDGE_COUNTER_ALLOC(memoryFailures);
+#undef NG_BRIDGE_COUNTER_ALLOC
 
 	link->hook = hook;
 	if (isUplink) {
 		link->learnMac = 0;
 		link->sendUnknown = 1;
 		if (priv->numLinks == 0)	/* if the first link is an uplink */
-		    priv->sendUnknown = 0;	/* switch to restrictive mode */
+			priv->sendUnknown = 0;	/* switch to restrictive mode */
 	} else {
 		link->learnMac = 1;
 		link->sendUnknown = priv->sendUnknown;
@@ -425,12 +434,17 @@ ng_bridge_newhook(node_p node, hook_p hook, const char *name)
 	NG_HOOK_SET_PRIVATE(hook, link);
 	priv->numLinks++;
 	return (0);
+
+nomem:
+	ng_bridge_free_link(link);
+	return (ENOMEM);
 }
 
 /*
  * Receive a control message
  */
-static void ng_bridge_clear_link_stats(struct ng_bridge_link_kernel_stats * p)
+static void
+ng_bridge_clear_link_stats(struct ng_bridge_link_kernel_stats *p)
 {
 	counter_u64_zero(p->recvOctets);
 	counter_u64_zero(p->recvPackets);
@@ -446,7 +460,26 @@ static void ng_bridge_clear_link_stats(struct ng_bridge_link_kernel_stats * p)
 	counter_u64_zero(p->loopDrops);
 	p->loopDetects = 0;
 	counter_u64_zero(p->memoryFailures);
-};
+}
+
+static void
+ng_bridge_free_link(link_p link)
+{
+	counter_u64_free(link->stats.recvOctets);
+	counter_u64_free(link->stats.recvPackets);
+	counter_u64_free(link->stats.recvMulticasts);
+	counter_u64_free(link->stats.recvBroadcasts);
+	counter_u64_free(link->stats.recvUnknown);
+	counter_u64_free(link->stats.recvRunts);
+	counter_u64_free(link->stats.recvInvalid);
+	counter_u64_free(link->stats.xmitOctets);
+	counter_u64_free(link->stats.xmitPackets);
+	counter_u64_free(link->stats.xmitMulticasts);
+	counter_u64_free(link->stats.xmitBroadcasts);
+	counter_u64_free(link->stats.loopDrops);
+	counter_u64_free(link->stats.memoryFailures);
+	free(link, M_NETGRAPH_BRIDGE);
+}
 
 static int
 ng_bridge_reset_link(hook_p hook, void *arg __unused)
@@ -984,20 +1017,7 @@ ng_bridge_disconnect(hook_p hook)
 	ng_bridge_remove_hosts(priv, link);
 
 	/* Free associated link information */
-	counter_u64_free(link->stats.recvOctets);
-	counter_u64_free(link->stats.recvPackets);
-	counter_u64_free(link->stats.recvMulticasts);
-	counter_u64_free(link->stats.recvBroadcasts);
-	counter_u64_free(link->stats.recvUnknown);
-	counter_u64_free(link->stats.recvRunts);
-	counter_u64_free(link->stats.recvInvalid);
-	counter_u64_free(link->stats.xmitOctets);
-	counter_u64_free(link->stats.xmitPackets);
-	counter_u64_free(link->stats.xmitMulticasts);
-	counter_u64_free(link->stats.xmitBroadcasts);
-	counter_u64_free(link->stats.loopDrops);
-	counter_u64_free(link->stats.memoryFailures);
-	free(link, M_NETGRAPH_BRIDGE);
+	ng_bridge_free_link(link);
 	priv->numLinks--;
 
 	/* If no more hooks, go away */


More information about the dev-commits-src-branches mailing list