Changeset View
Changeset View
Standalone View
Standalone View
head/sys/netinet/tcp_timewait.c
Show First 20 Lines • Show All 701 Lines • ▼ Show 20 Lines | for (;;) { | ||||
} | } | ||||
KASSERT(tw->tw_inpcb != NULL, ("%s: tw->tw_inpcb == NULL", | KASSERT(tw->tw_inpcb != NULL, ("%s: tw->tw_inpcb == NULL", | ||||
__func__)); | __func__)); | ||||
inp = tw->tw_inpcb; | inp = tw->tw_inpcb; | ||||
in_pcbref(inp); | in_pcbref(inp); | ||||
TW_RUNLOCK(V_tw_lock); | TW_RUNLOCK(V_tw_lock); | ||||
if (INP_INFO_TRY_RLOCK(&V_tcbinfo)) { | INP_INFO_RLOCK(&V_tcbinfo); | ||||
INP_WLOCK(inp); | INP_WLOCK(inp); | ||||
tw = intotw(inp); | tw = intotw(inp); | ||||
if (in_pcbrele_wlocked(inp)) { | if (in_pcbrele_wlocked(inp)) { | ||||
if (__predict_true(tw == NULL)) { | if (__predict_true(tw == NULL)) { | ||||
INP_INFO_RUNLOCK(&V_tcbinfo); | INP_INFO_RUNLOCK(&V_tcbinfo); | ||||
continue; | continue; | ||||
} else { | } else { | ||||
/* This should not happen as in TIMEWAIT | /* This should not happen as in TIMEWAIT | ||||
* state the inp should not be destroyed | * state the inp should not be destroyed | ||||
* before its tcptw. If INVARIANTS is | * before its tcptw. If INVARIANTS is | ||||
* defined panic. | * defined panic. | ||||
*/ | */ | ||||
#ifdef INVARIANTS | #ifdef INVARIANTS | ||||
panic("%s: Panic before an infinite " | panic("%s: Panic before an infinite " | ||||
"loop: INP_TIMEWAIT && (INP_FREED " | "loop: INP_TIMEWAIT && (INP_FREED " | ||||
"|| inp last reference) && tw != " | "|| inp last reference) && tw != " | ||||
"NULL", __func__); | "NULL", __func__); | ||||
#else | #else | ||||
log(LOG_ERR, "%s: Avoid an infinite " | log(LOG_ERR, "%s: Avoid an infinite " | ||||
"loop: INP_TIMEWAIT && (INP_FREED " | "loop: INP_TIMEWAIT && (INP_FREED " | ||||
"|| inp last reference) && tw != " | "|| inp last reference) && tw != " | ||||
"NULL", __func__); | "NULL", __func__); | ||||
#endif | #endif | ||||
INP_INFO_RUNLOCK(&V_tcbinfo); | INP_INFO_RUNLOCK(&V_tcbinfo); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
if (tw == NULL) { | if (tw == NULL) { | ||||
/* tcp_twclose() has already been called */ | /* tcp_twclose() has already been called */ | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
INP_INFO_RUNLOCK(&V_tcbinfo); | INP_INFO_RUNLOCK(&V_tcbinfo); | ||||
continue; | continue; | ||||
} | } | ||||
tcp_twclose(tw, reuse); | tcp_twclose(tw, reuse); | ||||
INP_INFO_RUNLOCK(&V_tcbinfo); | INP_INFO_RUNLOCK(&V_tcbinfo); | ||||
if (reuse) | if (reuse) | ||||
return tw; | return tw; | ||||
} else { | |||||
/* INP_INFO lock is busy, continue later. */ | |||||
INP_WLOCK(inp); | |||||
if (!in_pcbrele_wlocked(inp)) | |||||
INP_WUNLOCK(inp); | |||||
break; | |||||
} | |||||
} | } | ||||
return NULL; | return NULL; | ||||
} | } |