Fix problem in r238990. 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>
This commit is contained in:
parent
01487e405c
commit
b1ec2940af
@ -109,12 +109,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);
|
||||
|
||||
|
@ -165,7 +165,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);
|
||||
@ -192,11 +191,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();
|
||||
}
|
||||
|
||||
|
@ -1108,8 +1108,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);
|
||||
|
Loading…
Reference in New Issue
Block a user