Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 25 Aug 2009 09:52:39 +0000 (UTC)
From:      Robert Watson <rwatson@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r196535 - in head/sys: net netinet netinet6
Message-ID:  <200908250952.n7P9qdhD022600@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rwatson
Date: Tue Aug 25 09:52:38 2009
New Revision: 196535
URL: http://svn.freebsd.org/changeset/base/196535

Log:
  Use locks specific to the lltable code, rather than borrow the ifnet
  list/index locks, to protect link layer address tables.  This avoids
  lock order issues during interface teardown, but maintains the bug that
  sysctl copy routines may be called while a non-sleepable lock is held.
  
  Reviewed by:	bz, kmacy
  MFC after:	3 days

Modified:
  head/sys/net/if_llatbl.c
  head/sys/net/if_llatbl.h
  head/sys/netinet/in.c
  head/sys/netinet6/in6.c

Modified: head/sys/net/if_llatbl.c
==============================================================================
--- head/sys/net/if_llatbl.c	Tue Aug 25 09:47:12 2009	(r196534)
+++ head/sys/net/if_llatbl.c	Tue Aug 25 09:52:38 2009	(r196535)
@@ -62,6 +62,9 @@ static	SLIST_HEAD(, lltable) lltables = 
 extern void arprequest(struct ifnet *, struct in_addr *, struct in_addr *,
 	u_char *);
 
+struct rwlock lltable_rwlock;
+RW_SYSINIT(lltable_rwlock, &lltable_rwlock, "lltable_rwlock");
+
 /*
  * Dump arp state for a specific address family.
  */
@@ -71,7 +74,7 @@ lltable_sysctl_dumparp(int af, struct sy
 	struct lltable *llt;
 	int error = 0;
 
-	IFNET_RLOCK();
+	LLTABLE_RLOCK();
 	SLIST_FOREACH(llt, &lltables, llt_link) {
 		if (llt->llt_af == af) {
 			error = llt->llt_dump(llt, wr);
@@ -80,7 +83,7 @@ lltable_sysctl_dumparp(int af, struct sy
 		}
 	}
 done:
-	IFNET_RUNLOCK();
+	LLTABLE_RUNLOCK();
 	return (error);
 }
 
@@ -144,8 +147,6 @@ llentry_update(struct llentry **llep, st
 
 /*
  * Free all entries from given table and free itself.
- * Since lltables collects from all of the intefaces,
- * the caller of this function must acquire IFNET_WLOCK().
  */
 void
 lltable_free(struct lltable *llt)
@@ -155,9 +156,9 @@ lltable_free(struct lltable *llt)
 
 	KASSERT(llt != NULL, ("%s: llt is NULL", __func__));
 
-	IFNET_WLOCK();
+	LLTABLE_WLOCK();
 	SLIST_REMOVE(&lltables, llt, lltable, llt_link);
-	IFNET_WUNLOCK();
+	LLTABLE_WUNLOCK();
 
 	for (i=0; i < LLTBL_HASHTBL_SIZE; i++) {
 		LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) {
@@ -178,7 +179,7 @@ lltable_drain(int af)
 	struct llentry	*lle;
 	register int i;
 
-	IFNET_RLOCK();
+	LLTABLE_RLOCK();
 	SLIST_FOREACH(llt, &lltables, llt_link) {
 		if (llt->llt_af != af)
 			continue;
@@ -192,7 +193,7 @@ lltable_drain(int af)
 			}
 		}
 	}
-	IFNET_RUNLOCK();
+	LLTABLE_RUNLOCK();
 }
 
 void
@@ -200,14 +201,14 @@ lltable_prefix_free(int af, struct socka
 {
 	struct lltable *llt;
 
-	IFNET_RLOCK_NOSLEEP();
+	LLTABLE_RLOCK();
 	SLIST_FOREACH(llt, &lltables, llt_link) {
 		if (llt->llt_af != af)
 			continue;
 
 		llt->llt_prefix_free(llt, prefix, mask);
 	}
-	IFNET_RUNLOCK_NOSLEEP();
+	LLTABLE_RUNLOCK();
 }
 
 
@@ -230,9 +231,9 @@ lltable_init(struct ifnet *ifp, int af)
 	for (i = 0; i < LLTBL_HASHTBL_SIZE; i++)
 		LIST_INIT(&llt->lle_head[i]);
 
-	IFNET_WLOCK();
+	LLTABLE_WLOCK();
 	SLIST_INSERT_HEAD(&lltables, llt, llt_link);
-	IFNET_WUNLOCK();
+	LLTABLE_WUNLOCK();
 
 	return (llt);
 }
@@ -300,13 +301,13 @@ lla_rt_output(struct rt_msghdr *rtm, str
 	}
 
 	/* XXX linked list may be too expensive */
-	IFNET_RLOCK_NOSLEEP();
+	LLTABLE_RLOCK();
 	SLIST_FOREACH(llt, &lltables, llt_link) {
 		if (llt->llt_af == dst->sa_family &&
 		    llt->llt_ifp == ifp)
 			break;
 	}
-	IFNET_RUNLOCK_NOSLEEP();
+	LLTABLE_RUNLOCK();
 	KASSERT(llt != NULL, ("Yep, ugly hacks are bad\n"));
 
 	if (flags && LLE_CREATE)

Modified: head/sys/net/if_llatbl.h
==============================================================================
--- head/sys/net/if_llatbl.h	Tue Aug 25 09:47:12 2009	(r196534)
+++ head/sys/net/if_llatbl.h	Tue Aug 25 09:52:38 2009	(r196535)
@@ -41,6 +41,13 @@ struct rt_addrinfo;
 struct llentry;
 LIST_HEAD(llentries, llentry);
 
+extern struct rwlock lltable_rwlock;
+#define	LLTABLE_RLOCK()		rw_rlock(&lltable_rwlock)
+#define	LLTABLE_RUNLOCK()	rw_runlock(&lltable_rwlock)
+#define	LLTABLE_WLOCK()		rw_wlock(&lltable_rwlock)
+#define	LLTABLE_WUNLOCK()	rw_wunlock(&lltable_rwlock)
+#define	LLTABLE_LOCK_ASSERT()	rw_assert(&lltable_rwlock, RA_LOCKED)
+
 /*
  * Code referencing llentry must at least hold
  * a shared lock

Modified: head/sys/netinet/in.c
==============================================================================
--- head/sys/netinet/in.c	Tue Aug 25 09:47:12 2009	(r196534)
+++ head/sys/netinet/in.c	Tue Aug 25 09:52:38 2009	(r196535)
@@ -1407,7 +1407,7 @@ in_lltable_dump(struct lltable *llt, str
 	} arpc;
 	int error, i;
 
-	IFNET_RLOCK_ASSERT();
+	LLTABLE_LOCK_ASSERT();
 
 	error = 0;
 	for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {

Modified: head/sys/netinet6/in6.c
==============================================================================
--- head/sys/netinet6/in6.c	Tue Aug 25 09:47:12 2009	(r196534)
+++ head/sys/netinet6/in6.c	Tue Aug 25 09:52:38 2009	(r196535)
@@ -2495,7 +2495,7 @@ in6_lltable_dump(struct lltable *llt, st
 	} ndpc;
 	int i, error;
 
-	IFNET_RLOCK_ASSERT();
+	LLTABLE_LOCK_ASSERT();
 
 	error = 0;
 	for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {



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