Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 1 Feb 2017 21:44:50 +0000 (UTC)
From:      Kristof Provost <kp@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r313066 - stable/10/sys/net
Message-ID:  <201702012144.v11Liooa004371@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kp
Date: Wed Feb  1 21:44:50 2017
New Revision: 313066
URL: https://svnweb.freebsd.org/changeset/base/313066

Log:
  MFC 312782
  
  bridge: Release the bridge lock when calling bridge_set_ifcap()
  
  This calls ioctl() handlers for the different interfaces in the bridge.
  These handlers expect to get called in an ioctl context where it's safe
  for them to sleep. We may not sleep with the bridge lock held.
  
  However, we still need to protect the interface list, to ensure it
  doesn't get changed while we iterate over it.
  Use BRIDGE_XLOCK(), which prevents bridge members from being removed.
  Adding bridge members is safe, because it uses LIST_INSERT_HEAD().
  
  This caused panics when adding xen interfaces to a bridge.
  
  PR:		216304
  Reviewed by:	ae
  Sponsored by:	RootBSD
  Differential Revision:	https://reviews.freebsd.org/D9290

Modified:
  stable/10/sys/net/if_bridge.c
  stable/10/sys/net/if_bridgevar.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/net/if_bridge.c
==============================================================================
--- stable/10/sys/net/if_bridge.c	Wed Feb  1 21:35:25 2017	(r313065)
+++ stable/10/sys/net/if_bridge.c	Wed Feb  1 21:44:50 2017	(r313066)
@@ -860,14 +860,18 @@ bridge_mutecaps(struct bridge_softc *sc)
 		mask &= bif->bif_savedcaps;
 	}
 
+	BRIDGE_XLOCK(sc);
 	LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
 		enabled = bif->bif_ifp->if_capenable;
 		enabled &= ~BRIDGE_IFCAPS_STRIP;
 		/* strip off mask bits and enable them again if allowed */
 		enabled &= ~BRIDGE_IFCAPS_MASK;
 		enabled |= mask;
+		BRIDGE_UNLOCK(sc);
 		bridge_set_ifcap(sc, bif, enabled);
+		BRIDGE_LOCK(sc);
 	}
+	BRIDGE_XDROP(sc);
 
 }
 
@@ -878,6 +882,8 @@ bridge_set_ifcap(struct bridge_softc *sc
 	struct ifreq ifr;
 	int error;
 
+	BRIDGE_UNLOCK_ASSERT(sc);
+
 	bzero(&ifr, sizeof(ifr));
 	ifr.ifr_reqcap = set;
 

Modified: stable/10/sys/net/if_bridgevar.h
==============================================================================
--- stable/10/sys/net/if_bridgevar.h	Wed Feb  1 21:35:25 2017	(r313065)
+++ stable/10/sys/net/if_bridgevar.h	Wed Feb  1 21:44:50 2017	(r313066)
@@ -280,6 +280,7 @@ struct ifbpstpconf {
 #define BRIDGE_LOCK(_sc)		mtx_lock(&(_sc)->sc_mtx)
 #define BRIDGE_UNLOCK(_sc)		mtx_unlock(&(_sc)->sc_mtx)
 #define BRIDGE_LOCK_ASSERT(_sc)		mtx_assert(&(_sc)->sc_mtx, MA_OWNED)
+#define BRIDGE_UNLOCK_ASSERT(_sc)	mtx_assert(&(_sc)->sc_mtx, MA_NOTOWNED)
 #define	BRIDGE_LOCK2REF(_sc, _err)	do {	\
 	mtx_assert(&(_sc)->sc_mtx, MA_OWNED);	\
 	if ((_sc)->sc_iflist_xcnt > 0)		\



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201702012144.v11Liooa004371>