Module Name:    src
Committed By:   knakahara
Date:           Mon Jun 20 06:52:44 UTC 2016

Modified Files:
        src/sys/net: if_loop.c

Log Message:
make looutput() MP-safe, so that lo(4) can enable IFEF_OUTPUT_MPSAFE.

making MP-scalable is future work.


To generate a diff of this commit:
cvs rdiff -u -r1.87 -r1.88 src/sys/net/if_loop.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/net/if_loop.c
diff -u src/sys/net/if_loop.c:1.87 src/sys/net/if_loop.c:1.88
--- src/sys/net/if_loop.c:1.87	Fri Jun 10 13:27:16 2016
+++ src/sys/net/if_loop.c	Mon Jun 20 06:52:44 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_loop.c,v 1.87 2016/06/10 13:27:16 ozaki-r Exp $	*/
+/*	$NetBSD: if_loop.c,v 1.88 2016/06/20 06:52:44 knakahara Exp $	*/
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -65,7 +65,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_loop.c,v 1.87 2016/06/10 13:27:16 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_loop.c,v 1.88 2016/06/20 06:52:44 knakahara Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -157,6 +157,7 @@ loop_clone_create(struct if_clone *ifc, 
 
 	ifp->if_mtu = LOMTU;
 	ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST | IFF_RUNNING;
+	ifp->if_extflags = IFEF_OUTPUT_MPSAFE;
 	ifp->if_ioctl = loioctl;
 	ifp->if_output = looutput;
 #ifdef ALTQ
@@ -211,12 +212,12 @@ looutput(struct ifnet *ifp, struct mbuf 
 	struct ifqueue *ifq = NULL;
 	int s, isr = -1;
 	int csum_flags;
+	int error = 0;
 	size_t pktlen;
 
 	MCLAIM(m, ifp->if_mowner);
-#ifndef NET_MPSAFE
-	KASSERT(KERNEL_LOCKED_P());
-#endif
+
+	KERNEL_LOCK(1, NULL);
 
 	if ((m->m_flags & M_PKTHDR) == 0)
 		panic("looutput: no header mbuf");
@@ -226,8 +227,9 @@ looutput(struct ifnet *ifp, struct mbuf 
 
 	if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
 		m_freem(m);
-		return (rt->rt_flags & RTF_BLACKHOLE ? 0 :
+		error = (rt->rt_flags & RTF_BLACKHOLE ? 0 :
 			rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
+		goto out;
 	}
 
 	pktlen = m->m_pkthdr.len;
@@ -241,8 +243,6 @@ looutput(struct ifnet *ifp, struct mbuf 
 	 */
 	if ((ALTQ_IS_ENABLED(&ifp->if_snd) || TBR_IS_ENABLED(&ifp->if_snd)) &&
 	    ifp->if_start == lostart) {
-		int error;
-
 		/*
 		 * If the queueing discipline needs packet classification,
 		 * do it before prepending the link headers.
@@ -250,12 +250,14 @@ looutput(struct ifnet *ifp, struct mbuf 
 		IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family);
 
 		M_PREPEND(m, sizeof(uint32_t), M_DONTWAIT);
-		if (m == NULL)
-			return (ENOBUFS);
+		if (m == NULL) {
+			error = ENOBUFS;
+			goto out;
+		}
 		*(mtod(m, uint32_t *)) = dst->sa_family;
 
 		error = ifp->if_transmit(ifp, m);
-		return (error);
+		goto out;
 	}
 #endif /* ALTQ */
 
@@ -310,12 +312,13 @@ looutput(struct ifnet *ifp, struct mbuf 
 		printf("%s: can't handle af%d\n", ifp->if_xname,
 		    dst->sa_family);
 		m_freem(m);
-		return (EAFNOSUPPORT);
+		error = EAFNOSUPPORT;
+		goto out;
 	}
 
 	s = splnet();
 	if (__predict_true(pktq)) {
-		int error = 0;
+		error = 0;
 
 		if (__predict_true(pktq_enqueue(pktq, m, 0))) {
 			ifp->if_ipackets++;
@@ -325,20 +328,23 @@ looutput(struct ifnet *ifp, struct mbuf 
 			error = ENOBUFS;
 		}
 		splx(s);
-		return error;
+		goto out;
 	}
 	if (IF_QFULL(ifq)) {
 		IF_DROP(ifq);
 		m_freem(m);
 		splx(s);
-		return (ENOBUFS);
+		error = ENOBUFS;
+		goto out;
 	}
 	IF_ENQUEUE(ifq, m);
 	schednetisr(isr);
 	ifp->if_ipackets++;
 	ifp->if_ibytes += m->m_pkthdr.len;
 	splx(s);
-	return (0);
+out:
+	KERNEL_UNLOCK_ONE(NULL);
+	return error;
 }
 
 #ifdef ALTQ

Reply via email to