PERFORCE change 140224 for review

Sam Leffler sam at FreeBSD.org
Fri Apr 18 20:07:45 UTC 2008


http://perforce.freebsd.org/chv.cgi?CH=140224

Change 140224 by sam at sam_ebb on 2008/04/18 20:07:02

	o back out use of rwlock for node table and iterator; it was
	  wrong for several reasons.  Restore the 2 mtx's; one for the
	  node table contents and one for the scan generation #; we
	  must have two since we need to drop the node table lock over
	  the callback and must guard against scangen being changed by
	  colliding iterators.
	o cleanup the lock name stuff by encapsulating the char buffer
	  that holds the constructed lock name in the lock types.
	o eliminate some unnecessary recursive locking in mlme ops
	o correct the LOR in the mlme op to deauth/diassoc station(s)
	  by holding the node table lock only for the single-address
	  case and using ieee80211_iterate_nodes otherwise

Affected files ...

.. //depot/projects/vap/sys/net80211/ieee80211_freebsd.h#25 edit
.. //depot/projects/vap/sys/net80211/ieee80211_ioctl.c#55 edit
.. //depot/projects/vap/sys/net80211/ieee80211_node.c#29 edit
.. //depot/projects/vap/sys/net80211/ieee80211_node.h#19 edit

Differences ...

==== //depot/projects/vap/sys/net80211/ieee80211_freebsd.h#25 (text+ko) ====

@@ -49,22 +49,46 @@
 /*
  * Node locking definitions.
  */
-typedef struct rwlock ieee80211_node_lock_t;
-#define	IEEE80211_NODE_LOCK_INIT(_nt, _name) \
-	rw_init_flags(&(_nt)->nt_nodelock, _name, RW_RECURSE)
-#define	IEEE80211_NODE_LOCK_DESTROY(_nt)	rw_destroy(&(_nt)->nt_nodelock)
-#define	IEEE80211_NODE_LOCK(_nt)		rw_wlock(&(_nt)->nt_nodelock)
-#define	IEEE80211_NODE_IS_LOCKED(_nt)		rw_wowned(&(_nt)->nt_nodelock)
-#define	IEEE80211_NODE_UNLOCK(_nt)		rw_wunlock(&(_nt)->nt_nodelock)
+typedef struct {
+	char		name[16];		/* e.g. "ath0_node_lock" */
+	struct mtx	mtx;
+} ieee80211_node_lock_t;
+#define	IEEE80211_NODE_LOCK_INIT(_nt, _name) do {			\
+	ieee80211_node_lock_t *nl = &(_nt)->nt_nodelock;		\
+	snprintf(nl->name, sizeof(nl->name), "%s_node_lock", _name);	\
+	mtx_init(&nl->mtx, NULL, nl->name, MTX_DEF | MTX_RECURSE);	\
+} while (0)
+#define	IEEE80211_NODE_LOCK_DESTROY(_nt) \
+	mtx_destroy(&(_nt)->nt_nodelock.mtx)
+#define	IEEE80211_NODE_LOCK(_nt) \
+	mtx_lock(&(_nt)->nt_nodelock.mtx)
+#define	IEEE80211_NODE_IS_LOCKED(_nt) \
+	mtx_owned(&(_nt)->nt_nodelock.mtx)
+#define	IEEE80211_NODE_UNLOCK(_nt) \
+	mtx_unlock(&(_nt)->nt_nodelock.mtx)
 #define	IEEE80211_NODE_LOCK_ASSERT(_nt)	\
-	rw_assert(&(_nt)->nt_nodelock, RA_WLOCKED)
+	mtx_assert(&(_nt)->nt_nodelock.mtx, MA_OWNED)
 
 /*
- * Node table iteration locking definitions; we piggyback on the node
- * table lock by using a read/shared acquisition.
+ * Node table iteration locking definitions; this protects the
+ * scan generation # used to iterate over the station table
+ * while grabbing+releasing the node lock.
  */
-#define	IEEE80211_NODE_ITERATE_LOCK(_nt)	rw_rlock(&(_nt)->nt_nodelock)
-#define	IEEE80211_NODE_ITERATE_UNLOCK(_nt)	rw_runlock(&(_nt)->nt_nodelock)
+typedef struct {
+	char		name[16];		/* e.g. "ath0_scan_lock" */
+	struct mtx	mtx;
+} ieee80211_scan_lock_t;
+#define	IEEE80211_NODE_ITERATE_LOCK_INIT(_nt, _name) do {		\
+	ieee80211_scan_lock_t *sl = &(_nt)->nt_scanlock;		\
+	snprintf(sl->name, sizeof(sl->name), "%s_scan_lock", _name);	\
+	mtx_init(&sl->mtx, NULL, sl->name, MTX_DEF);			\
+} while (0)
+#define	IEEE80211_NODE_ITERATE_LOCK_DESTROY(_nt) \
+	mtx_destroy(&(_nt)->nt_scanlock.mtx)
+#define	IEEE80211_NODE_ITERATE_LOCK(_nt) \
+	mtx_lock(&(_nt)->nt_scanlock.mtx)
+#define	IEEE80211_NODE_ITERATE_UNLOCK(_nt) \
+	mtx_unlock(&(_nt)->nt_scanlock.mtx)
 
 #define	_AGEQ_ENQUEUE(_ifq, _m, _qlen, _age) do {		\
 	(_m)->m_nextpkt = NULL;					\

==== //depot/projects/vap/sys/net80211/ieee80211_ioctl.c#55 (text+ko) ====

@@ -1261,6 +1261,31 @@
 	ieee80211_node_leave(ni);
 }
 
+static int
+setmlme_dropsta(struct ieee80211vap *vap,
+	const uint8_t mac[IEEE80211_ADDR_LEN], struct mlmeop *mlmeop)
+{
+	struct ieee80211com *ic = vap->iv_ic;
+	struct ieee80211_node_table *nt = &ic->ic_sta;
+	struct ieee80211_node *ni;
+	int error = 0;
+
+	/* NB: the broadcast address means do 'em all */
+	if (!IEEE80211_ADDR_EQ(mac, ic->ic_ifp->if_broadcastaddr)) {
+		IEEE80211_NODE_LOCK(nt);
+		ni = ieee80211_find_node_locked(nt, mac);
+		if (ni != NULL) {
+			domlme(mlmeop, ni);
+			ieee80211_free_node(ni);
+		} else
+			error = ENOENT;
+		IEEE80211_NODE_UNLOCK(nt);
+	} else {
+		ieee80211_iterate_nodes(nt, domlme, mlmeop);
+	}
+	return error;
+}
+
 static __noinline int
 setmlme_common(struct ieee80211vap *vap, int op,
 	const uint8_t mac[IEEE80211_ADDR_LEN], int reason)
@@ -1285,20 +1310,7 @@
 			mlmeop.vap = vap;
 			mlmeop.op = op;
 			mlmeop.reason = reason;
-			IEEE80211_NODE_LOCK(nt);
-			/* NB: the broadcast address means do 'em all */
-			if (!IEEE80211_ADDR_EQ(mac, ic->ic_ifp->if_broadcastaddr)) {
-				ni = ieee80211_find_node_locked(nt, mac);
-				if (ni != NULL) {
-					domlme(&mlmeop, ni);
-					ieee80211_free_node(ni);
-				} else
-					error = ENOENT;
-			} else {
-				ieee80211_iterate_nodes(&ic->ic_sta,
-						domlme, &mlmeop);
-			}
-			IEEE80211_NODE_UNLOCK(nt);
+			error = setmlme_dropsta(vap, mac, &mlmeop);
 			break;
 		case IEEE80211_M_WDS:
 			/* XXX user app should send raw frame? */
@@ -1332,7 +1344,7 @@
 			break;
 		}
 		IEEE80211_NODE_LOCK(nt);
-		ni = ieee80211_find_vap_node(&ic->ic_sta, vap, mac);
+		ni = ieee80211_find_vap_node_locked(nt, vap, mac);
 		if (ni != NULL) {
 			mlmedebug(vap, mac, op, reason);
 			if (op == IEEE80211_MLME_AUTHORIZE)
@@ -1350,7 +1362,7 @@
 			break;
 		}
 		IEEE80211_NODE_LOCK(nt);
-		ni = ieee80211_find_vap_node(&ic->ic_sta, vap, mac);
+		ni = ieee80211_find_vap_node_locked(nt, vap, mac);
 		if (ni != NULL) {
 			mlmedebug(vap, mac, op, reason);
 			if (reason == IEEE80211_STATUS_SUCCESS) {

==== //depot/projects/vap/sys/net80211/ieee80211_node.c#29 (text+ko) ====

@@ -1698,10 +1698,11 @@
 	struct ieee80211_node_table *nt,
 	const char *name, int inact, int keyixmax)
 {
+	struct ifnet *ifp = ic->ic_ifp;
+
 	nt->nt_ic = ic;
-	snprintf(nt->nt_lockname, sizeof(nt->nt_lockname), "%s_node_lock",
-	    ic->ic_ifp->if_xname);
-	IEEE80211_NODE_LOCK_INIT(nt, nt->nt_lockname);
+	IEEE80211_NODE_LOCK_INIT(nt, ifp->if_xname);
+	IEEE80211_NODE_ITERATE_LOCK_INIT(nt, ifp->if_xname);
 	TAILQ_INIT(&nt->nt_node);
 	nt->nt_name = name;
 	nt->nt_scangen = 1;
@@ -1772,6 +1773,7 @@
 		FREE(nt->nt_keyixmap, M_80211_NODE);
 		nt->nt_keyixmap = NULL;
 	}
+	IEEE80211_NODE_ITERATE_LOCK_DESTROY(nt);
 	IEEE80211_NODE_LOCK_DESTROY(nt);
 }
 
@@ -1793,13 +1795,10 @@
 	struct ieee80211_node *ni;
 	int gen = 0;
 
+	IEEE80211_NODE_ITERATE_LOCK(nt);
+	gen = ++nt->nt_scangen;
 restart:
 	IEEE80211_NODE_LOCK(nt);
-	if (gen == 0) {
-		gen = ++nt->nt_scangen;
-		if (nt->nt_scangen == 0)	/* NB: 0 is never used */
-			nt->nt_scangen++;
-	}
 	TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {
 		if (ni->ni_scangen == gen)	/* previously handled */
 			continue;
@@ -1920,6 +1919,8 @@
 		}
 	}
 	IEEE80211_NODE_UNLOCK(nt);
+
+	IEEE80211_NODE_ITERATE_UNLOCK(nt);
 }
 
 /*
@@ -2003,28 +2004,28 @@
 }
 
 void
-ieee80211_iterate_nodes(struct ieee80211_node_table *nt, ieee80211_iter_func *f, void *arg)
+ieee80211_iterate_nodes(struct ieee80211_node_table *nt,
+	ieee80211_iter_func *f, void *arg)
 {
 	struct ieee80211_node *ni;
-	u_int gen = 0;
+	u_int gen;
 
+	IEEE80211_NODE_ITERATE_LOCK(nt);
+	gen = ++nt->nt_scangen;
 restart:
-	IEEE80211_NODE_ITERATE_LOCK(nt);
-	if (gen == 0) {
-		gen = ++nt->nt_scangen;
-		if (nt->nt_scangen == 0)	/* NB: 0 is never used */
-			nt->nt_scangen++;
-	}
+	IEEE80211_NODE_LOCK(nt);
 	TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {
 		if (ni->ni_scangen != gen) {
 			ni->ni_scangen = gen;
 			(void) ieee80211_ref_node(ni);
-			IEEE80211_NODE_ITERATE_UNLOCK(nt);
+			IEEE80211_NODE_UNLOCK(nt);
 			(*f)(arg, ni);
 			ieee80211_free_node(ni);
 			goto restart;
 		}
 	}
+	IEEE80211_NODE_UNLOCK(nt);
+
 	IEEE80211_NODE_ITERATE_UNLOCK(nt);
 }
 
@@ -2070,6 +2071,8 @@
 {
 	struct ieee80211vap *vap;
 
+	IEEE80211_LOCK_ASSERT(ic);
+
 	TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
 		if (vap->iv_opmode == IEEE80211_M_HOSTAP)
 			ieee80211_beacon_notify(vap, IEEE80211_BEACON_ERP);

==== //depot/projects/vap/sys/net80211/ieee80211_node.h#19 (text+ko) ====

@@ -295,14 +295,14 @@
  */
 struct ieee80211_node_table {
 	struct ieee80211com	*nt_ic;		/* back reference */
-	char			nt_lockname[16];/* e.g. "ath0_node_lock" */
 	ieee80211_node_lock_t	nt_nodelock;	/* on node table */
 	TAILQ_HEAD(, ieee80211_node) nt_node;	/* information of all nodes */
 	LIST_HEAD(, ieee80211_node) nt_hash[IEEE80211_NODE_HASHSIZE];
 	struct ieee80211_node	**nt_keyixmap;	/* key ix -> node map */
 	int			nt_keyixmax;	/* keyixmap size */
-	const char		*nt_name;	/* for debugging */
-	u_int			nt_scangen;	/* gen# for timeout scan */
+	const char		*nt_name;	/* table name for debug msgs */
+	ieee80211_scan_lock_t	nt_scanlock;	/* on nt_scangen */
+	u_int			nt_scangen;	/* gen# for iterators */
 	int			nt_inact_init;	/* initial node inact setting */
 };
 


More information about the p4-projects mailing list