summaryrefslogtreecommitdiffstats
path: root/sys/netinet6/nd6.c
diff options
context:
space:
mode:
authorume <ume@FreeBSD.org>2009-11-20 06:54:47 +0000
committerume <ume@FreeBSD.org>2009-11-20 06:54:47 +0000
commit0a68974fb27195121871713d2b97ac1770815ea4 (patch)
tree24e6c30342bfae2df968950fece836d9196c4add /sys/netinet6/nd6.c
parent2e508f22fabaf3ac72d6b47337abe579519e49fd (diff)
downloadFreeBSD-src-0a68974fb27195121871713d2b97ac1770815ea4.zip
FreeBSD-src-0a68974fb27195121871713d2b97ac1770815ea4.tar.gz
MFC r199225:
- We are not guaranteed that we're not dropping a reference that we did not add. Call LLE_REMREF() only when callout_stop() actually canceled a pending callout. - callout_reset() may cancel a pending callout. When callout_reset() canceled a pending callout, call LLE_REMREF() to drop a reference for the canceled callout.
Diffstat (limited to 'sys/netinet6/nd6.c')
-rw-r--r--sys/netinet6/nd6.c21
1 files changed, 10 insertions, 11 deletions
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
index e9c15e1..0297972 100644
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -434,31 +434,27 @@ skip1:
void
nd6_llinfo_settimer_locked(struct llentry *ln, long tick)
{
+ int canceled;
+
if (tick < 0) {
ln->la_expire = 0;
ln->ln_ntick = 0;
- callout_stop(&ln->ln_timer_ch);
- /*
- * XXX - do we know that there is
- * callout installed? i.e. are we
- * guaranteed that we're not dropping
- * a reference that we did not add?
- * KMM
- */
- LLE_REMREF(ln);
+ canceled = callout_stop(&ln->ln_timer_ch);
} else {
ln->la_expire = time_second + tick / hz;
LLE_ADDREF(ln);
if (tick > INT_MAX) {
ln->ln_ntick = tick - INT_MAX;
- callout_reset(&ln->ln_timer_ch, INT_MAX,
+ canceled = callout_reset(&ln->ln_timer_ch, INT_MAX,
nd6_llinfo_timer, ln);
} else {
ln->ln_ntick = 0;
- callout_reset(&ln->ln_timer_ch, tick,
+ canceled = callout_reset(&ln->ln_timer_ch, tick,
nd6_llinfo_timer, ln);
}
}
+ if (canceled)
+ LLE_REMREF(ln);
}
void
@@ -1047,6 +1043,9 @@ nd6_free(struct llentry *ln, int gc)
else
nd6_llinfo_settimer(ln, (long)V_nd6_gctimer * hz);
splx(s);
+ LLE_WLOCK(ln);
+ LLE_REMREF(ln);
+ LLE_WUNLOCK(ln);
return (LIST_NEXT(ln, lle_next));
}
OpenPOWER on IntegriCloud