Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/tcp_input.c
Show First 20 Lines • Show All 954 Lines • ▼ Show 20 Lines | #endif | ||||
* acquire it, or if that fails, acquire a reference on the inpcb, | * acquire it, or if that fails, acquire a reference on the inpcb, | ||||
* drop all locks, acquire a global write lock, and then re-acquire | * drop all locks, acquire a global write lock, and then re-acquire | ||||
* the inpcb lock. We may at that point discover that another thread | * the inpcb lock. We may at that point discover that another thread | ||||
* has tried to free the inpcb, in which case we need to loop back | * has tried to free the inpcb, in which case we need to loop back | ||||
* and try to find a new inpcb to deliver to. | * and try to find a new inpcb to deliver to. | ||||
* | * | ||||
* XXXRW: It may be time to rethink timewait locking. | * XXXRW: It may be time to rethink timewait locking. | ||||
*/ | */ | ||||
relocked: | |||||
if (inp->inp_flags & INP_TIMEWAIT) { | if (inp->inp_flags & INP_TIMEWAIT) { | ||||
if (ti_locked == TI_UNLOCKED) { | if (ti_locked == TI_UNLOCKED) { | ||||
if (INP_INFO_TRY_RLOCK(&V_tcbinfo) == 0) { | INP_INFO_RLOCK(); | ||||
in_pcbref(inp); | |||||
INP_WUNLOCK(inp); | |||||
INP_INFO_RLOCK(&V_tcbinfo); | |||||
ti_locked = TI_RLOCKED; | ti_locked = TI_RLOCKED; | ||||
INP_WLOCK(inp); | |||||
if (in_pcbrele_wlocked(inp)) { | |||||
inp = NULL; | |||||
goto findpcb; | |||||
} else if (inp->inp_flags & INP_DROPPED) { | |||||
INP_WUNLOCK(inp); | |||||
inp = NULL; | |||||
goto findpcb; | |||||
} | } | ||||
} else | |||||
ti_locked = TI_RLOCKED; | |||||
} | |||||
INP_INFO_RLOCK_ASSERT(&V_tcbinfo); | INP_INFO_RLOCK_ASSERT(&V_tcbinfo); | ||||
if (thflags & TH_SYN) | if (thflags & TH_SYN) | ||||
tcp_dooptions(&to, optp, optlen, TO_SYN); | tcp_dooptions(&to, optp, optlen, TO_SYN); | ||||
/* | /* | ||||
* NB: tcp_twcheck unlocks the INP and frees the mbuf. | * NB: tcp_twcheck unlocks the INP and frees the mbuf. | ||||
*/ | */ | ||||
if (tcp_twcheck(inp, &to, th, m, tlen)) | if (tcp_twcheck(inp, &to, th, m, tlen)) | ||||
Show All 30 Lines | |||||
#ifdef INVARIANTS | #ifdef INVARIANTS | ||||
if ((thflags & (TH_FIN | TH_RST)) != 0) | if ((thflags & (TH_FIN | TH_RST)) != 0) | ||||
INP_INFO_RLOCK_ASSERT(&V_tcbinfo); | INP_INFO_RLOCK_ASSERT(&V_tcbinfo); | ||||
#endif | #endif | ||||
if (!((tp->t_state == TCPS_ESTABLISHED && (thflags & TH_SYN) == 0) || | if (!((tp->t_state == TCPS_ESTABLISHED && (thflags & TH_SYN) == 0) || | ||||
(tp->t_state == TCPS_LISTEN && (thflags & TH_SYN) && | (tp->t_state == TCPS_LISTEN && (thflags & TH_SYN) && | ||||
!IS_FASTOPEN(tp->t_flags)))) { | !IS_FASTOPEN(tp->t_flags)))) { | ||||
if (ti_locked == TI_UNLOCKED) { | if (ti_locked == TI_UNLOCKED) { | ||||
if (INP_INFO_TRY_RLOCK(&V_tcbinfo) == 0) { | INP_INFO_RLOCK(); | ||||
in_pcbref(inp); | |||||
INP_WUNLOCK(inp); | |||||
INP_INFO_RLOCK(&V_tcbinfo); | |||||
ti_locked = TI_RLOCKED; | |||||
INP_WLOCK(inp); | |||||
if (in_pcbrele_wlocked(inp)) { | |||||
inp = NULL; | |||||
goto findpcb; | |||||
} else if (inp->inp_flags & INP_DROPPED) { | |||||
INP_WUNLOCK(inp); | |||||
inp = NULL; | |||||
goto findpcb; | |||||
} | |||||
goto relocked; | |||||
} else | |||||
ti_locked = TI_RLOCKED; | ti_locked = TI_RLOCKED; | ||||
} | } | ||||
INP_INFO_RLOCK_ASSERT(&V_tcbinfo); | INP_INFO_RLOCK_ASSERT(&V_tcbinfo); | ||||
} | } | ||||
#ifdef MAC | #ifdef MAC | ||||
INP_WLOCK_ASSERT(inp); | INP_WLOCK_ASSERT(inp); | ||||
if (mac_inpcb_check_deliver(inp, m)) | if (mac_inpcb_check_deliver(inp, m)) | ||||
goto dropunlock; | goto dropunlock; | ||||
▲ Show 20 Lines • Show All 2,842 Lines • Show Last 20 Lines |