summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorume <ume@FreeBSD.org>2009-11-12 14:48:36 +0000
committerume <ume@FreeBSD.org>2009-11-12 14:48:36 +0000
commitff25cdd646326ab0ebb33402740d6cd4386a45f4 (patch)
tree1eeee38539269f2ee45ff61803d0deca5bc7e6f6
parentd3a4a741549e830fd38f124392e7929d8417fe52 (diff)
downloadFreeBSD-src-ff25cdd646326ab0ebb33402740d6cd4386a45f4.zip
FreeBSD-src-ff25cdd646326ab0ebb33402740d6cd4386a45f4.tar.gz
- 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. MFC after: 1 week
-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 3225b82..575ff25 100644
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -439,31 +439,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
@@ -1048,6 +1044,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