Date: Thu, 2 Nov 2017 10:38:09 +0000 (UTC) From: Alexander Motin <mav@FreeBSD.org> 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 Message-ID: <201711021038.vA2Ac9ER061802@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201711021038.vA2Ac9ER061802>