From owner-svn-src-all@freebsd.org Thu Nov 2 10:38:10 2017 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 4E508E55DB3; Thu, 2 Nov 2017 10:38:10 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 27FC17541D; Thu, 2 Nov 2017 10:38:10 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id vA2Ac9YX061803; Thu, 2 Nov 2017 10:38:09 GMT (envelope-from mav@FreeBSD.org) Received: (from mav@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id vA2Ac9ER061802; Thu, 2 Nov 2017 10:38:09 GMT (envelope-from mav@FreeBSD.org) Message-Id: <201711021038.vA2Ac9ER061802@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mav set sender to mav@FreeBSD.org using -f From: Alexander Motin Date: Thu, 2 Nov 2017 10:38:09 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r325311 - stable/11/sys/netinet X-SVN-Group: stable-11 X-SVN-Commit-Author: mav X-SVN-Commit-Paths: stable/11/sys/netinet X-SVN-Commit-Revision: 325311 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 02 Nov 2017 10:38:10 -0000 Author: mav Date: Thu Nov 2 10:38:09 2017 New Revision: 325311 URL: https://svnweb.freebsd.org/changeset/base/325311 Log: MFC r324752: Relax per-ifnet cif_vrs list double locking in carp(4). In all cases where cif_vrs list is modified, two locks are held: per-ifnet CIF_LOCK and global carp_sx. It means to read that list only one of them is enough to be held, so we can skip CIF_LOCK when we already have carp_sx. This fixes kernel panic, caused by attempts of copyout() to sleep while holding non-sleepable CIF_LOCK mutex. Modified: stable/11/sys/netinet/ip_carp.c Directory Properties: stable/11/ (props changed) Modified: stable/11/sys/netinet/ip_carp.c ============================================================================== --- stable/11/sys/netinet/ip_carp.c Thu Nov 2 08:47:03 2017 (r325310) +++ stable/11/sys/netinet/ip_carp.c Thu Nov 2 10:38:09 2017 (r325311) @@ -175,8 +175,8 @@ static int proto_reg[] = {-1, -1}; * Each softc has a lock sc_mtx. It is used to synchronise carp_input_c(), * callout-driven events and ioctl()s. * - * To traverse the list of softcs on an ifnet we use CIF_LOCK(), to - * traverse the global list we use the mutex carp_mtx. + * To traverse the list of softcs on an ifnet we use CIF_LOCK() or carp_sx. + * To traverse the global list we use the mutex carp_mtx. * * Known issues with locking: * @@ -286,7 +286,8 @@ SYSCTL_VNET_PCPUSTAT(_net_inet_carp, OID_AUTO, stats, ++_i) #define IFNET_FOREACH_CARP(ifp, sc) \ - CIF_LOCK_ASSERT(ifp->if_carp); \ + KASSERT(mtx_owned(&ifp->if_carp->cif_mtx) || \ + sx_xlocked(&carp_sx), ("cif_vrs not locked")); \ TAILQ_FOREACH((sc), &(ifp)->if_carp->cif_vrs, sc_list) #define DEMOTE_ADVSKEW(sc) \ @@ -1468,6 +1469,8 @@ carp_alloc(struct ifnet *ifp) struct carp_softc *sc; struct carp_if *cif; + sx_assert(&carp_sx, SA_XLOCKED); + if ((cif = ifp->if_carp) == NULL) cif = carp_alloc_if(ifp); @@ -1657,11 +1660,9 @@ carp_ioctl(struct ifreq *ifr, u_long cmd, struct threa } if (ifp->if_carp) { - CIF_LOCK(ifp->if_carp); IFNET_FOREACH_CARP(ifp, sc) if (sc->sc_vhid == carpr.carpr_vhid) break; - CIF_UNLOCK(ifp->if_carp); } if (sc == NULL) { sc = carp_alloc(ifp); @@ -1732,11 +1733,9 @@ carp_ioctl(struct ifreq *ifr, u_long cmd, struct threa priveleged = (priv_check(td, PRIV_NETINET_CARP) == 0); if (carpr.carpr_vhid != 0) { - CIF_LOCK(ifp->if_carp); IFNET_FOREACH_CARP(ifp, sc) if (sc->sc_vhid == carpr.carpr_vhid) break; - CIF_UNLOCK(ifp->if_carp); if (sc == NULL) { error = ENOENT; break; @@ -1747,7 +1746,6 @@ carp_ioctl(struct ifreq *ifr, u_long cmd, struct threa int i, count; count = 0; - CIF_LOCK(ifp->if_carp); IFNET_FOREACH_CARP(ifp, sc) count++; @@ -1769,7 +1767,6 @@ carp_ioctl(struct ifreq *ifr, u_long cmd, struct threa } i++; } - CIF_UNLOCK(ifp->if_carp); } break; } @@ -1824,11 +1821,9 @@ carp_attach(struct ifaddr *ifa, int vhid) return (ENOPROTOOPT); } - CIF_LOCK(cif); IFNET_FOREACH_CARP(ifp, sc) if (sc->sc_vhid == vhid) break; - CIF_UNLOCK(cif); if (sc == NULL) { sx_xunlock(&carp_sx); return (ENOENT);