Module Name:    src
Committed By:   thorpej
Date:           Fri Sep  2 04:34:58 UTC 2022

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

Log Message:
f_detach(): Drain the protocol input queues before the pr_purgeif()
calls; pktq_barrier() doesn't remove packets from the queue, it waits
for the packets enqueued before the barrier to drain.  This, in turn,
may cause the protocols to gain additional references to the interface
that's detaching.  By draining the queues first, we ensure that no
additional references will be taken after calling pr_purgeif().


To generate a diff of this commit:
cvs rdiff -u -r1.521 -r1.522 src/sys/net/if.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.c
diff -u src/sys/net/if.c:1.521 src/sys/net/if.c:1.522
--- src/sys/net/if.c:1.521	Fri Sep  2 03:50:00 2022
+++ src/sys/net/if.c	Fri Sep  2 04:34:58 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: if.c,v 1.521 2022/09/02 03:50:00 thorpej Exp $	*/
+/*	$NetBSD: if.c,v 1.522 2022/09/02 04:34:58 thorpej Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc.
@@ -90,7 +90,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.521 2022/09/02 03:50:00 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.522 2022/09/02 04:34:58 thorpej Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_inet.h"
@@ -1399,6 +1399,33 @@ if_detach(struct ifnet *ifp)
 #endif
 
 	/*
+	 * remove packets that came from ifp, from software interrupt queues.
+	 */
+	DOMAIN_FOREACH(dp) {
+		for (i = 0; i < __arraycount(dp->dom_ifqueues); i++) {
+			struct ifqueue *iq = dp->dom_ifqueues[i];
+			if (iq == NULL)
+				break;
+			dp->dom_ifqueues[i] = NULL;
+			if_detach_queues(ifp, iq);
+		}
+	}
+
+	/*
+	 * IP queues have to be processed separately: net-queue barrier
+	 * ensures that the packets are dequeued while a cross-call will
+	 * ensure that the interrupts have completed. FIXME: not quite..
+	 */
+#ifdef INET
+	pktq_barrier(ip_pktq);
+#endif
+#ifdef INET6
+	if (in6_present)
+		pktq_barrier(ip6_pktq);
+#endif
+	xc_barrier(0);
+
+	/*
 	 * Rip all the addresses off the interface.  This should make
 	 * all of the routes go away.
 	 *
@@ -1518,33 +1545,6 @@ restart:
 
 	IF_AFDATA_LOCK_DESTROY(ifp);
 
-	/*
-	 * remove packets that came from ifp, from software interrupt queues.
-	 */
-	DOMAIN_FOREACH(dp) {
-		for (i = 0; i < __arraycount(dp->dom_ifqueues); i++) {
-			struct ifqueue *iq = dp->dom_ifqueues[i];
-			if (iq == NULL)
-				break;
-			dp->dom_ifqueues[i] = NULL;
-			if_detach_queues(ifp, iq);
-		}
-	}
-
-	/*
-	 * IP queues have to be processed separately: net-queue barrier
-	 * ensures that the packets are dequeued while a cross-call will
-	 * ensure that the interrupts have completed. FIXME: not quite..
-	 */
-#ifdef INET
-	pktq_barrier(ip_pktq);
-#endif
-#ifdef INET6
-	if (in6_present)
-		pktq_barrier(ip6_pktq);
-#endif
-	xc_barrier(0);
-
 	if (ifp->if_percpuq != NULL) {
 		if_percpuq_destroy(ifp->if_percpuq);
 		ifp->if_percpuq = NULL;

Reply via email to