Page MenuHomeFreeBSD

D4605.id11394.diff
No OneTemporary

D4605.id11394.diff

Index: sys/net/if_llatbl.h
===================================================================
--- sys/net/if_llatbl.h
+++ sys/net/if_llatbl.h
@@ -105,6 +105,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
@@ -415,6 +415,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.
*/
@@ -436,8 +473,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
@@ -175,28 +175,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);
@@ -259,7 +241,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);
@@ -268,6 +250,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);
}
@@ -465,14 +448,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);
@@ -1109,7 +1086,7 @@
static void
arp_mark_lle_reachable(struct llentry *la)
{
- int canceled, wtime;
+ int wtime;
LLE_WLOCK_ASSERT(la);
@@ -1117,15 +1094,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
@@ -1036,7 +1036,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);
}
@@ -1094,9 +1094,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);
Index: sys/netinet6/in6.c
===================================================================
--- sys/netinet6/in6.c
+++ sys/netinet6/in6.c
@@ -2082,7 +2082,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);
}
@@ -2136,9 +2136,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);
}
Index: sys/netinet6/nd6.c
===================================================================
--- sys/netinet6/nd6.c
+++ sys/netinet6/nd6.c
@@ -489,29 +489,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);
}
/*
@@ -715,28 +708,9 @@
KASSERT(arg != NULL, ("%s: arg NULL", __func__));
ln = (struct llentry *)arg;
- 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.
- */
- LLE_WUNLOCK(ln);
- return;
- }
+ LLE_WLOCK_ASSERT(ln);
ifp = ln->lle_tbl->llt_ifp;
+
CURVNET_SET(ifp->if_vnet);
ndi = ND_IFINFO(ifp);
send_ns = 0;
@@ -1364,6 +1338,7 @@
nd6_llinfo_settimer_locked(ln,
(long)V_nd6_gctimer * hz);
+ /* Drop reference so that timeout frees "ln" */
LLE_REMREF(ln);
LLE_WUNLOCK(ln);
return;
@@ -1439,12 +1414,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);
}

File Metadata

Mime Type
text/plain
Expires
Sat, Jan 31, 9:24 PM (8 h, 15 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28190093
Default Alt Text
D4605.id11394.diff (8 KB)

Event Timeline