diff options
author | ume <ume@FreeBSD.org> | 2009-11-20 06:54:47 +0000 |
---|---|---|
committer | ume <ume@FreeBSD.org> | 2009-11-20 06:54:47 +0000 |
commit | 0a68974fb27195121871713d2b97ac1770815ea4 (patch) | |
tree | 24e6c30342bfae2df968950fece836d9196c4add /sys/netinet6/nd6.c | |
parent | 2e508f22fabaf3ac72d6b47337abe579519e49fd (diff) | |
download | FreeBSD-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.c | 21 |
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)); } |