Page MenuHomeFreeBSD

D4605.id18333.diff
No OneTemporary

D4605.id18333.diff

Index: sys/net/if_llatbl.h
===================================================================
--- sys/net/if_llatbl.h
+++ sys/net/if_llatbl.h
@@ -104,6 +104,9 @@
#define LLE_REQ_LOCK(lle) mtx_lock(&(lle)->req_mtx)
#define LLE_REQ_UNLOCK(lle) mtx_unlock(&(lle)->req_mtx)
+#define LLE_TIMER_INIT(lle) callout_init_rw(&(lle)->lle_timer, \
+ &(lle)->lle_lock, CALLOUT_RETURNUNLOCKED)
+
#define LLE_IS_VALID(lle) (((lle) != NULL) && ((lle) != (void *)-1))
#define LLE_ADDREF(lle) do { \
@@ -216,6 +219,9 @@
#endif
int lltable_sysctl_dumparp(int, struct sysctl_req *);
+void llentry_timer_start(struct llentry *, int, void (*)(void *));
+void llentry_timer_stop(struct llentry *);
+void llentry_timer_uninit(struct llentry *);
size_t llentry_free(struct llentry *);
struct llentry *llentry_alloc(struct ifnet *, struct lltable *,
struct sockaddr_storage *);
Index: sys/net/if_llatbl.c
===================================================================
--- sys/net/if_llatbl.c
+++ sys/net/if_llatbl.c
@@ -494,6 +494,43 @@
return (0);
}
+void
+llentry_timer_start(struct llentry *lle, int timeout, void (*func)(void *))
+{
+
+ if (callout_reset(&lle->lle_timer, timeout, func, lle) <= 0)
+ LLE_ADDREF(lle);
+}
+
+void
+llentry_timer_stop(struct llentry *lle)
+{
+
+ if (callout_stop(&lle->lle_timer) > 0)
+ LLE_REMREF(lle);
+}
+
+static void
+llentry_timer_drain_callback(void *arg)
+{
+ struct llentry *lle = arg;
+
+ LLE_FREE(lle);
+}
+
+void
+llentry_timer_uninit(struct llentry *lle)
+{
+ int cancelled;
+
+ cancelled = callout_async_drain(&lle->lle_timer,
+ &llentry_timer_drain_callback);
+ if (cancelled > 0)
+ LLE_REMREF(lle); /* was stopped */
+ else if (cancelled == 0)
+ LLE_ADDREF(lle); /* needs drain */
+}
+
/*
* Free all entries from given table and free itself.
*/
@@ -515,8 +552,7 @@
IF_AFDATA_WUNLOCK(llt->llt_ifp);
LIST_FOREACH_SAFE(lle, &dchain, lle_chain, next) {
- if (callout_stop(&lle->lle_timer) > 0)
- LLE_REMREF(lle);
+ llentry_timer_uninit(lle);
llentry_free(lle);
}
Index: sys/netinet/if_ether.c
===================================================================
--- sys/netinet/if_ether.c
+++ sys/netinet/if_ether.c
@@ -174,28 +174,10 @@
int r_skip_req;
if (lle->la_flags & LLE_STATIC) {
+ LLE_WUNLOCK(lle);
return;
}
- LLE_WLOCK(lle);
- if (callout_pending(&lle->lle_timer)) {
- /*
- * Here we are a bit odd here in the treatment of
- * active/pending. If the pending bit is set, it got
- * rescheduled before I ran. The active
- * bit we ignore, since if it was stopped
- * in ll_tablefree() and was currently running
- * it would have return 0 so the code would
- * not have deleted it since the callout could
- * not be stopped so we want to go through
- * with the delete here now. If the callout
- * was restarted, the pending bit will be back on and
- * we just want to bail since the callout_reset would
- * return 1 and our reference would have been removed
- * by arpresolve() below.
- */
- LLE_WUNLOCK(lle);
- return;
- }
+
ifp = lle->lle_tbl->llt_ifp;
CURVNET_SET(ifp->if_vnet);
@@ -258,7 +240,7 @@
EVENTHANDLER_INVOKE(lle_event, lle, evt);
}
- callout_stop(&lle->lle_timer);
+ llentry_timer_stop(lle);
/* XXX: LOR avoidance. We still have ref on lle. */
LLE_WUNLOCK(lle);
@@ -267,6 +249,7 @@
/* Guard against race with other llentry_free(). */
if (lle->la_flags & LLE_LINKED) {
+ /* Remove our reference */
LLE_REMREF(lle);
lltable_unlink_entry(lle->lle_tbl, lle);
}
@@ -531,14 +514,8 @@
error = is_gw != 0 ? EHOSTUNREACH : EHOSTDOWN;
if (renew) {
- int canceled;
-
- LLE_ADDREF(la);
la->la_expire = time_uptime;
- canceled = callout_reset(&la->lle_timer, hz * V_arpt_down,
- arptimer, la);
- if (canceled)
- LLE_REMREF(la);
+ llentry_timer_start(la, hz * V_arpt_down, arptimer);
la->la_asked++;
LLE_WUNLOCK(la);
arprequest(ifp, NULL, &SIN(dst)->sin_addr, NULL);
@@ -1219,7 +1196,7 @@
static void
arp_mark_lle_reachable(struct llentry *la)
{
- int canceled, wtime;
+ int wtime;
LLE_WLOCK_ASSERT(la);
@@ -1227,15 +1204,11 @@
EVENTHANDLER_INVOKE(lle_event, la, LLENTRY_RESOLVED);
if (!(la->la_flags & LLE_STATIC)) {
- LLE_ADDREF(la);
la->la_expire = time_uptime + V_arpt_keep;
wtime = V_arpt_keep - V_arp_maxtries * V_arpt_rexmit;
if (wtime < 0)
wtime = V_arpt_keep;
- canceled = callout_reset(&la->lle_timer,
- hz * wtime, arptimer, la);
- if (canceled)
- LLE_REMREF(la);
+ llentry_timer_start(la, hz * wtime, arptimer);
}
la->la_asked = 0;
la->la_preempt = V_arp_maxtries;
Index: sys/netinet/in.c
===================================================================
--- sys/netinet/in.c
+++ sys/netinet/in.c
@@ -1078,7 +1078,7 @@
lle->base.lle_free = in_lltable_destroy_lle;
LLE_LOCK_INIT(&lle->base);
LLE_REQ_INIT(&lle->base);
- callout_init(&lle->base.lle_timer, 1);
+ LLE_TIMER_INIT(&lle->base);
return (&lle->base);
}
@@ -1136,9 +1136,8 @@
lltable_unlink_entry(llt, lle);
}
- /* cancel timer */
- if (callout_stop(&lle->lle_timer) > 0)
- LLE_REMREF(lle);
+ /* Cancel timer */
+ llentry_timer_uninit(lle);
/* Drop hold queue */
pkts_dropped = llentry_free(lle);
@@ -1283,6 +1282,8 @@
#ifdef DIAGNOSTIC
log(LOG_INFO, "ifaddr cache = %p is deleted\n", lle);
#endif
+ /* Cancel timer */
+ llentry_timer_uninit(lle);
llentry_free(lle);
}
Index: sys/netinet6/in6.c
===================================================================
--- sys/netinet6/in6.c
+++ sys/netinet6/in6.c
@@ -2039,7 +2039,7 @@
lle->base.lle_free = in6_lltable_destroy_lle;
LLE_LOCK_INIT(&lle->base);
LLE_REQ_INIT(&lle->base);
- callout_init(&lle->base.lle_timer, 1);
+ LLE_TIMER_INIT(&lle->base);
return (&lle->base);
}
@@ -2093,9 +2093,8 @@
lltable_unlink_entry(llt, lle);
}
- if (callout_stop(&lle->lle_timer) > 0)
- LLE_REMREF(lle);
-
+ /* Cancel timer */
+ llentry_timer_uninit(lle);
llentry_free(lle);
}
@@ -2191,6 +2190,8 @@
#ifdef DIAGNOSTIC
log(LOG_INFO, "ifaddr cache = %p is deleted\n", lle);
#endif
+ /* Cancel timer */
+ llentry_timer_uninit(lle);
llentry_free(lle);
}
Index: sys/netinet6/nd6.c
===================================================================
--- sys/netinet6/nd6.c
+++ sys/netinet6/nd6.c
@@ -520,29 +520,22 @@
static void
nd6_llinfo_settimer_locked(struct llentry *ln, long tick)
{
- int canceled;
-
LLE_WLOCK_ASSERT(ln);
if (tick < 0) {
ln->la_expire = 0;
ln->ln_ntick = 0;
- canceled = callout_stop(&ln->lle_timer);
+ llentry_timer_stop(ln);
} else {
ln->la_expire = time_uptime + tick / hz;
- LLE_ADDREF(ln);
if (tick > INT_MAX) {
ln->ln_ntick = tick - INT_MAX;
- canceled = callout_reset(&ln->lle_timer, INT_MAX,
- nd6_llinfo_timer, ln);
+ llentry_timer_start(ln, INT_MAX, nd6_llinfo_timer);
} else {
ln->ln_ntick = 0;
- canceled = callout_reset(&ln->lle_timer, tick,
- nd6_llinfo_timer, ln);
+ llentry_timer_start(ln, tick, nd6_llinfo_timer);
}
}
- if (canceled > 0)
- LLE_REMREF(ln);
}
/*
@@ -746,29 +739,23 @@
KASSERT(arg != NULL, ("%s: arg NULL", __func__));
ln = (struct llentry *)arg;
+ LLE_WLOCK_ASSERT(ln);
ifp = lltable_get_ifp(ln->lle_tbl);
CURVNET_SET(ifp->if_vnet);
+ /* XXX swap locks */
+ LLE_WUNLOCK(ln);
ND6_RLOCK();
LLE_WLOCK(ln);
+
if (callout_pending(&ln->lle_timer)) {
/*
- * Here we are a bit odd here in the treatment of
- * active/pending. If the pending bit is set, it got
- * rescheduled before I ran. The active
- * bit we ignore, since if it was stopped
- * in ll_tablefree() and was currently running
- * it would have return 0 so the code would
- * not have deleted it since the callout could
- * not be stopped so we want to go through
- * with the delete here now. If the callout
- * was restarted, the pending bit will be back on and
- * we just want to bail since the callout_reset would
- * return 1 and our reference would have been removed
- * by nd6_llinfo_settimer_locked above since canceled
- * would have been 1.
+ * Because this callout is protected by a lock
+ * callout_reset() won't return 1 when we get into
+ * this function and we need to drop our reference if
+ * there was callout reset in between.
*/
- LLE_WUNLOCK(ln);
+ LLE_FREE_LOCKED(ln);
ND6_RUNLOCK();
CURVNET_RESTORE();
return;
@@ -1414,6 +1401,7 @@
nd6_llinfo_settimer_locked(ln,
(long)V_nd6_gctimer * hz);
+ /* Drop reference so that timeout frees "ln" */
LLE_REMREF(ln);
LLE_WUNLOCK(ln);
defrouter_rele(dr);
@@ -1490,12 +1478,14 @@
LLE_WLOCK(ln);
/* Guard against race with other llentry_free(). */
if (ln->la_flags & LLE_LINKED) {
- /* Remove callout reference */
+ /* Remove our reference */
LLE_REMREF(ln);
lltable_unlink_entry(ln->lle_tbl, ln);
}
IF_AFDATA_UNLOCK(ifp);
+ /* Cancel timer */
+ llentry_timer_uninit(ln);
llentry_free(ln);
if (dr != NULL)
defrouter_rele(dr);

File Metadata

Mime Type
text/plain
Expires
Sun, Feb 1, 12:14 AM (11 h, 5 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28225110
Default Alt Text
D4605.id18333.diff (8 KB)

Event Timeline