Sat Apr 18 15:56:26 2020 UTC ()
In _if_down(), release the link state change lock before calling
workqueue_wait().  Add a comment explaining how the locking here
works.

PR kern/55018.


(thorpej)
diff -r1.473 -r1.474 src/sys/net/if.c

cvs diff -r1.473 -r1.474 src/sys/net/if.c (expand / switch to unified diff)

--- src/sys/net/if.c 2020/02/21 00:26:23 1.473
+++ src/sys/net/if.c 2020/04/18 15:56:26 1.474
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: if.c,v 1.473 2020/02/21 00:26:23 joerg Exp $ */ 1/* $NetBSD: if.c,v 1.474 2020/04/18 15:56:26 thorpej Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc. 4 * Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by William Studenmund and Jason R. Thorpe. 8 * by William Studenmund and Jason R. Thorpe.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -80,27 +80,27 @@ @@ -80,27 +80,27 @@
80 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 80 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
81 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 81 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
82 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 82 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
83 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 83 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
84 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 84 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
85 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 85 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
86 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 86 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
87 * SUCH DAMAGE. 87 * SUCH DAMAGE.
88 * 88 *
89 * @(#)if.c 8.5 (Berkeley) 1/9/95 89 * @(#)if.c 8.5 (Berkeley) 1/9/95
90 */ 90 */
91 91
92#include <sys/cdefs.h> 92#include <sys/cdefs.h>
93__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.473 2020/02/21 00:26:23 joerg Exp $"); 93__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.474 2020/04/18 15:56:26 thorpej Exp $");
94 94
95#if defined(_KERNEL_OPT) 95#if defined(_KERNEL_OPT)
96#include "opt_inet.h" 96#include "opt_inet.h"
97#include "opt_ipsec.h" 97#include "opt_ipsec.h"
98#include "opt_atalk.h" 98#include "opt_atalk.h"
99#include "opt_wlan.h" 99#include "opt_wlan.h"
100#include "opt_net_mpsafe.h" 100#include "opt_net_mpsafe.h"
101#include "opt_mrouting.h" 101#include "opt_mrouting.h"
102#endif 102#endif
103 103
104#include <sys/param.h> 104#include <sys/param.h>
105#include <sys/mbuf.h> 105#include <sys/mbuf.h>
106#include <sys/systm.h> 106#include <sys/systm.h>
@@ -2509,31 +2509,42 @@ _if_down(struct ifnet *ifp) @@ -2509,31 +2509,42 @@ _if_down(struct ifnet *ifp)
2509 s = pserialize_read_enter(); 2509 s = pserialize_read_enter();
2510 IFADDR_READER_FOREACH(ifa, ifp) { 2510 IFADDR_READER_FOREACH(ifa, ifp) {
2511 ifa_acquire(ifa, &psref); 2511 ifa_acquire(ifa, &psref);
2512 pserialize_read_exit(s); 2512 pserialize_read_exit(s);
2513 2513
2514 pfctlinput(PRC_IFDOWN, ifa->ifa_addr); 2514 pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
2515 2515
2516 s = pserialize_read_enter(); 2516 s = pserialize_read_enter();
2517 ifa_release(ifa, &psref); 2517 ifa_release(ifa, &psref);
2518 } 2518 }
2519 pserialize_read_exit(s); 2519 pserialize_read_exit(s);
2520 curlwp_bindx(bound); 2520 curlwp_bindx(bound);
2521 2521
 2522 /*
 2523 * Modification of if_link_cansched is serialized with the
 2524 * ifnet ioctl lock.
 2525 *
 2526 * The link state change lock is taken to synchronize with the
 2527 * read in if_link_state_change_work_schedule(). Once we set
 2528 * this to false, our if_link_work won't be scheduled. But
 2529 * we need to wait for our if_link_work to drain in case we
 2530 * lost that race.
 2531 */
2522 IF_LINK_STATE_CHANGE_LOCK(ifp); 2532 IF_LINK_STATE_CHANGE_LOCK(ifp);
2523 ifp->if_link_cansched = false; 2533 ifp->if_link_cansched = false;
2524 workqueue_wait(ifnet_link_state_wq, &ifp->if_link_work); 
2525 IF_LINK_STATE_CHANGE_UNLOCK(ifp); 2534 IF_LINK_STATE_CHANGE_UNLOCK(ifp);
2526 2535
 2536 workqueue_wait(ifnet_link_state_wq, &ifp->if_link_work);
 2537
2527 IFQ_PURGE(&ifp->if_snd); 2538 IFQ_PURGE(&ifp->if_snd);
2528#if NCARP > 0 2539#if NCARP > 0
2529 if (ifp->if_carp) 2540 if (ifp->if_carp)
2530 carp_carpdev_state(ifp); 2541 carp_carpdev_state(ifp);
2531#endif 2542#endif
2532 rt_ifmsg(ifp); 2543 rt_ifmsg(ifp);
2533 DOMAIN_FOREACH(dp) { 2544 DOMAIN_FOREACH(dp) {
2534 if (dp->dom_if_down) 2545 if (dp->dom_if_down)
2535 dp->dom_if_down(ifp); 2546 dp->dom_if_down(ifp);
2536 } 2547 }
2537} 2548}
2538 2549
2539static void 2550static void