Module Name: src Committed By: knakahara Date: Fri Nov 18 06:50:04 UTC 2016
Modified Files: src/sys/netinet: tcp_usrreq.c udp_usrreq.c src/sys/netinet6: dccp6_usrreq.c in6.c mld6.c raw_ip6.c sctp6_usrreq.c udp6_usrreq.c Log Message: fix: "ifconfig destory" can stalls when "ifconfig" is done parallel. This problem occurs only if NET_MPSAFE on. ifconfig destroy side: kernel entry point is ifioctl => if_clone_destroy. pr_purgeif() acquires softnet_lock, and then ifa_remove() calls pserialize_perform() holding softnet_lock. ifconfig side: kernel entry point is socreate. pr_attach()(udp_attach_wrapper()) calls sosetlock(). In this call path, sosetlock() try to acquire softnet_lock. These can cause dead lock. To generate a diff of this commit: cvs rdiff -u -r1.212 -r1.213 src/sys/netinet/tcp_usrreq.c cvs rdiff -u -r1.228 -r1.229 src/sys/netinet/udp_usrreq.c cvs rdiff -u -r1.8 -r1.9 src/sys/netinet6/dccp6_usrreq.c \ src/sys/netinet6/sctp6_usrreq.c cvs rdiff -u -r1.221 -r1.222 src/sys/netinet6/in6.c cvs rdiff -u -r1.74 -r1.75 src/sys/netinet6/mld6.c cvs rdiff -u -r1.152 -r1.153 src/sys/netinet6/raw_ip6.c cvs rdiff -u -r1.125 -r1.126 src/sys/netinet6/udp6_usrreq.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/netinet/tcp_usrreq.c diff -u src/sys/netinet/tcp_usrreq.c:1.212 src/sys/netinet/tcp_usrreq.c:1.213 --- src/sys/netinet/tcp_usrreq.c:1.212 Tue Apr 26 08:44:45 2016 +++ src/sys/netinet/tcp_usrreq.c Fri Nov 18 06:50:04 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: tcp_usrreq.c,v 1.212 2016/04/26 08:44:45 ozaki-r Exp $ */ +/* $NetBSD: tcp_usrreq.c,v 1.213 2016/11/18 06:50:04 knakahara Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -99,13 +99,14 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: tcp_usrreq.c,v 1.212 2016/04/26 08:44:45 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tcp_usrreq.c,v 1.213 2016/11/18 06:50:04 knakahara Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" #include "opt_tcp_debug.h" #include "opt_mbuftrace.h" #include "opt_tcp_space.h" +#include "opt_net_mpsafe.h" #endif #include <sys/param.h> @@ -1205,9 +1206,13 @@ static int tcp_purgeif(struct socket *so, struct ifnet *ifp) { int s; + int error = 0; s = splsoftnet(); + +#ifndef NET_MPSAFE mutex_enter(softnet_lock); +#endif switch (so->so_proto->pr_domain->dom_family) { #ifdef INET case PF_INET: @@ -1224,14 +1229,15 @@ tcp_purgeif(struct socket *so, struct if break; #endif default: - mutex_exit(softnet_lock); - splx(s); - return EAFNOSUPPORT; + error = EAFNOSUPPORT; + break; } +#ifndef NET_MPSAFE mutex_exit(softnet_lock); +#endif splx(s); - return 0; + return error; } /* Index: src/sys/netinet/udp_usrreq.c diff -u src/sys/netinet/udp_usrreq.c:1.228 src/sys/netinet/udp_usrreq.c:1.229 --- src/sys/netinet/udp_usrreq.c:1.228 Tue Nov 15 20:50:28 2016 +++ src/sys/netinet/udp_usrreq.c Fri Nov 18 06:50:04 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: udp_usrreq.c,v 1.228 2016/11/15 20:50:28 mlelstv Exp $ */ +/* $NetBSD: udp_usrreq.c,v 1.229 2016/11/18 06:50:04 knakahara Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -66,7 +66,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c,v 1.228 2016/11/15 20:50:28 mlelstv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c,v 1.229 2016/11/18 06:50:04 knakahara Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -75,6 +75,7 @@ __KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c #include "opt_inet_csum.h" #include "opt_ipkdb.h" #include "opt_mbuftrace.h" +#include "opt_net_mpsafe.h" #endif #include <sys/param.h> @@ -1139,11 +1140,15 @@ udp_purgeif(struct socket *so, struct if int s; s = splsoftnet(); +#ifndef NET_MPSAFE mutex_enter(softnet_lock); +#endif in_pcbpurgeif0(&udbtable, ifp); in_purgeif(ifp); in_pcbpurgeif(&udbtable, ifp); +#ifndef NET_MPSAFE mutex_exit(softnet_lock); +#endif splx(s); return 0; Index: src/sys/netinet6/dccp6_usrreq.c diff -u src/sys/netinet6/dccp6_usrreq.c:1.8 src/sys/netinet6/dccp6_usrreq.c:1.9 --- src/sys/netinet6/dccp6_usrreq.c:1.8 Tue Apr 26 08:44:45 2016 +++ src/sys/netinet6/dccp6_usrreq.c Fri Nov 18 06:50:04 2016 @@ -1,5 +1,5 @@ /* $KAME: dccp6_usrreq.c,v 1.13 2005/07/27 08:42:56 nishida Exp $ */ -/* $NetBSD: dccp6_usrreq.c,v 1.8 2016/04/26 08:44:45 ozaki-r Exp $ */ +/* $NetBSD: dccp6_usrreq.c,v 1.9 2016/11/18 06:50:04 knakahara Exp $ */ /* * Copyright (C) 2003 WIDE Project. @@ -31,11 +31,12 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: dccp6_usrreq.c,v 1.8 2016/04/26 08:44:45 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: dccp6_usrreq.c,v 1.9 2016/11/18 06:50:04 knakahara Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" #include "opt_dccp.h" +#include "opt_net_mpsafe.h" #endif #include <sys/param.h> @@ -318,11 +319,15 @@ dccp6_purgeif(struct socket *so, struct int s; s = splsoftnet(); +#ifndef NET_MPSAFE mutex_enter(softnet_lock); +#endif in6_pcbpurgeif0(&dccpbtable, ifp); in6_purgeif(ifp); in6_pcbpurgeif(&dccpbtable, ifp); +#ifndef NET_MPSAFE mutex_exit(softnet_lock); +#endif splx(s); return 0; Index: src/sys/netinet6/sctp6_usrreq.c diff -u src/sys/netinet6/sctp6_usrreq.c:1.8 src/sys/netinet6/sctp6_usrreq.c:1.9 --- src/sys/netinet6/sctp6_usrreq.c:1.8 Mon Aug 1 03:15:31 2016 +++ src/sys/netinet6/sctp6_usrreq.c Fri Nov 18 06:50:04 2016 @@ -1,5 +1,5 @@ /* $KAME: sctp6_usrreq.c,v 1.38 2005/08/24 08:08:56 suz Exp $ */ -/* $NetBSD: sctp6_usrreq.c,v 1.8 2016/08/01 03:15:31 ozaki-r Exp $ */ +/* $NetBSD: sctp6_usrreq.c,v 1.9 2016/11/18 06:50:04 knakahara Exp $ */ /* * Copyright (c) 2001, 2002, 2003, 2004 Cisco Systems, Inc. @@ -33,12 +33,13 @@ * SUCH DAMAGE. */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sctp6_usrreq.c,v 1.8 2016/08/01 03:15:31 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sctp6_usrreq.c,v 1.9 2016/11/18 06:50:04 knakahara Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" #include "opt_ipsec.h" #include "opt_sctp.h" +#include "opt_net_mpsafe.h" #endif /* _KERNEL_OPT */ #include <sys/param.h> @@ -1301,9 +1302,13 @@ sctp6_purgeif(struct socket *so, struct } } +#ifndef NET_MPSAFE mutex_enter(softnet_lock); +#endif in6_purgeif(ifp); +#ifndef NET_MPSAFE mutex_exit(softnet_lock); +#endif return 0; } Index: src/sys/netinet6/in6.c diff -u src/sys/netinet6/in6.c:1.221 src/sys/netinet6/in6.c:1.222 --- src/sys/netinet6/in6.c:1.221 Tue Oct 18 07:30:31 2016 +++ src/sys/netinet6/in6.c Fri Nov 18 06:50:04 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: in6.c,v 1.221 2016/10/18 07:30:31 ozaki-r Exp $ */ +/* $NetBSD: in6.c,v 1.222 2016/11/18 06:50:04 knakahara Exp $ */ /* $KAME: in6.c,v 1.198 2001/07/18 09:12:38 itojun Exp $ */ /* @@ -62,7 +62,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.221 2016/10/18 07:30:31 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.222 2016/11/18 06:50:04 knakahara Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -2376,8 +2376,12 @@ in6_lltable_free_entry(struct lltable *l lltable_unlink_entry(llt, lle); } +#ifdef NET_MPSAFE + callout_halt(&lle->lle_timer, NULL); +#else KASSERT(mutex_owned(softnet_lock)); callout_halt(&lle->lle_timer, softnet_lock); +#endif LLE_REMREF(lle); llentry_free(lle); Index: src/sys/netinet6/mld6.c diff -u src/sys/netinet6/mld6.c:1.74 src/sys/netinet6/mld6.c:1.75 --- src/sys/netinet6/mld6.c:1.74 Mon Aug 1 03:15:31 2016 +++ src/sys/netinet6/mld6.c Fri Nov 18 06:50:04 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: mld6.c,v 1.74 2016/08/01 03:15:31 ozaki-r Exp $ */ +/* $NetBSD: mld6.c,v 1.75 2016/11/18 06:50:04 knakahara Exp $ */ /* $KAME: mld6.c,v 1.25 2001/01/16 14:14:18 itojun Exp $ */ /* @@ -102,10 +102,11 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: mld6.c,v 1.74 2016/08/01 03:15:31 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mld6.c,v 1.75 2016/11/18 06:50:04 knakahara Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" +#include "opt_net_mpsafe.h" #endif #include <sys/param.h> @@ -789,7 +790,11 @@ in6_delmulti(struct in6_multi *in6m) /* Tell mld_timeo we're halting the timer */ in6m->in6m_timer = IN6M_TIMER_UNDEF; +#ifdef NET_MPSAFE + callout_halt(&in6m->in6m_timer_ch, NULL); +#else callout_halt(&in6m->in6m_timer_ch, softnet_lock); +#endif callout_destroy(&in6m->in6m_timer_ch); free(in6m, M_IPMADDR); Index: src/sys/netinet6/raw_ip6.c diff -u src/sys/netinet6/raw_ip6.c:1.152 src/sys/netinet6/raw_ip6.c:1.153 --- src/sys/netinet6/raw_ip6.c:1.152 Mon Oct 31 04:16:25 2016 +++ src/sys/netinet6/raw_ip6.c Fri Nov 18 06:50:04 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: raw_ip6.c,v 1.152 2016/10/31 04:16:25 ozaki-r Exp $ */ +/* $NetBSD: raw_ip6.c,v 1.153 2016/11/18 06:50:04 knakahara Exp $ */ /* $KAME: raw_ip6.c,v 1.82 2001/07/23 18:57:56 jinmei Exp $ */ /* @@ -62,10 +62,11 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: raw_ip6.c,v 1.152 2016/10/31 04:16:25 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: raw_ip6.c,v 1.153 2016/11/18 06:50:04 knakahara Exp $"); #ifdef _KERNEL_OPT #include "opt_ipsec.h" +#include "opt_net_mpsafe.h" #endif #include <sys/param.h> @@ -935,11 +936,15 @@ static int rip6_purgeif(struct socket *so, struct ifnet *ifp) { +#ifndef NET_MPSAFE mutex_enter(softnet_lock); +#endif in6_pcbpurgeif0(&raw6cbtable, ifp); in6_purgeif(ifp); in6_pcbpurgeif(&raw6cbtable, ifp); +#ifndef NET_MPSAFE mutex_exit(softnet_lock); +#endif return 0; } Index: src/sys/netinet6/udp6_usrreq.c diff -u src/sys/netinet6/udp6_usrreq.c:1.125 src/sys/netinet6/udp6_usrreq.c:1.126 --- src/sys/netinet6/udp6_usrreq.c:1.125 Tue Nov 15 20:50:28 2016 +++ src/sys/netinet6/udp6_usrreq.c Fri Nov 18 06:50:04 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: udp6_usrreq.c,v 1.125 2016/11/15 20:50:28 mlelstv Exp $ */ +/* $NetBSD: udp6_usrreq.c,v 1.126 2016/11/18 06:50:04 knakahara Exp $ */ /* $KAME: udp6_usrreq.c,v 1.86 2001/05/27 17:33:00 itojun Exp $ */ /* @@ -62,12 +62,13 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: udp6_usrreq.c,v 1.125 2016/11/15 20:50:28 mlelstv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: udp6_usrreq.c,v 1.126 2016/11/18 06:50:04 knakahara Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" #include "opt_inet_csum.h" #include "opt_ipsec.h" +#include "opt_net_mpsafe.h" #endif #include <sys/param.h> @@ -911,11 +912,15 @@ static int udp6_purgeif(struct socket *so, struct ifnet *ifp) { +#ifndef NET_MPSAFE mutex_enter(softnet_lock); +#endif in6_pcbpurgeif0(&udbtable, ifp); in6_purgeif(ifp); in6_pcbpurgeif(&udbtable, ifp); +#ifndef NET_MPSAFE mutex_exit(softnet_lock); +#endif return 0; }