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;