svn commit: r248852 - in stable/9/sys: net netinet netinet6
Ed Maste
emaste at FreeBSD.org
Thu Mar 28 20:48:41 UTC 2013
Author: emaste
Date: Thu Mar 28 20:48:40 2013
New Revision: 248852
URL: http://svnweb.freebsd.org/changeset/base/248852
Log:
MFC r244183 by glebius:
Fix problem in r238990 (MFC'd in r240313). The LLE_LINKED flag should be
tested prior to entering llentry_free(), and in case if we lose the race,
we should simply perform LLE_FREE_LOCKED(). Otherwise, if the race is
lost by the thread performing arptimer(), it will remove two references
from the lle instead of one.
Reported by: Ian FREISLICH <ianf clue.co.za>
Modified:
stable/9/sys/net/if_llatbl.c
stable/9/sys/netinet/if_ether.c
stable/9/sys/netinet6/nd6.c
Directory Properties:
stable/9/sys/ (props changed)
stable/9/sys/net/ (props changed)
Modified: stable/9/sys/net/if_llatbl.c
==============================================================================
--- stable/9/sys/net/if_llatbl.c Thu Mar 28 20:37:07 2013 (r248851)
+++ stable/9/sys/net/if_llatbl.c Thu Mar 28 20:48:40 2013 (r248852)
@@ -112,12 +112,6 @@ llentry_free(struct llentry *lle)
IF_AFDATA_WLOCK_ASSERT(lle->lle_tbl->llt_ifp);
LLE_WLOCK_ASSERT(lle);
- /* XXX: guard against race with other llentry_free(). */
- if (!(lle->la_flags & LLE_LINKED)) {
- LLE_FREE_LOCKED(lle);
- return (0);
- }
-
LIST_REMOVE(lle, lle_next);
lle->la_flags &= ~(LLE_VALID | LLE_LINKED);
Modified: stable/9/sys/netinet/if_ether.c
==============================================================================
--- stable/9/sys/netinet/if_ether.c Thu Mar 28 20:37:07 2013 (r248851)
+++ stable/9/sys/netinet/if_ether.c Thu Mar 28 20:48:40 2013 (r248852)
@@ -169,7 +169,6 @@ arptimer(void *arg)
{
struct llentry *lle = (struct llentry *)arg;
struct ifnet *ifp;
- size_t pkts_dropped;
if (lle->la_flags & LLE_STATIC) {
LLE_WUNLOCK(lle);
@@ -186,11 +185,20 @@ arptimer(void *arg)
IF_AFDATA_LOCK(ifp);
LLE_WLOCK(lle);
- LLE_REMREF(lle);
- pkts_dropped = llentry_free(lle);
+ /* Guard against race with other llentry_free(). */
+ if (lle->la_flags & LLE_LINKED) {
+ size_t pkts_dropped;
+
+ LLE_REMREF(lle);
+ pkts_dropped = llentry_free(lle);
+ ARPSTAT_ADD(dropped, pkts_dropped);
+ } else
+ LLE_FREE_LOCKED(lle);
+
IF_AFDATA_UNLOCK(ifp);
- ARPSTAT_ADD(dropped, pkts_dropped);
+
ARPSTAT_INC(timeouts);
+
CURVNET_RESTORE();
}
Modified: stable/9/sys/netinet6/nd6.c
==============================================================================
--- stable/9/sys/netinet6/nd6.c Thu Mar 28 20:37:07 2013 (r248851)
+++ stable/9/sys/netinet6/nd6.c Thu Mar 28 20:48:40 2013 (r248852)
@@ -1111,8 +1111,14 @@ nd6_free(struct llentry *ln, int gc)
LLE_WUNLOCK(ln);
IF_AFDATA_LOCK(ifp);
LLE_WLOCK(ln);
- LLE_REMREF(ln);
- llentry_free(ln);
+
+ /* Guard against race with other llentry_free(). */
+ if (ln->la_flags & LLE_LINKED) {
+ LLE_REMREF(ln);
+ llentry_free(ln);
+ } else
+ LLE_FREE_LOCKED(ln);
+
IF_AFDATA_UNLOCK(ifp);
return (next);
More information about the svn-src-stable
mailing list