diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -1536,15 +1536,15 @@ in_pcbrele_rlocked(inp) : in_pcbrele_wlocked(inp)); } -bool -inp_smr_lock(struct inpcb *inp, const inp_lookup_t lock) +static inline bool +_inp_smr_lock(struct inpcb *inp, const inp_lookup_t lock, const int ignflags) { MPASS(lock == INPLOOKUP_RLOCKPCB || lock == INPLOOKUP_WLOCKPCB); SMR_ASSERT_ENTERED(inp->inp_pcbinfo->ipi_smr); if (__predict_true(inp_trylock(inp, lock))) { - if (__predict_false(inp->inp_flags & INP_FREED)) { + if (__predict_false(inp->inp_flags & ignflags)) { smr_exit(inp->inp_pcbinfo->ipi_smr); inp_unlock(inp, lock); return (false); @@ -1564,7 +1564,7 @@ * through in_pcbfree() and has another reference, that * prevented its release by our in_pcbrele(). */ - if (__predict_false(inp->inp_flags & INP_FREED)) { + if (__predict_false(inp->inp_flags & ignflags)) { inp_unlock(inp, lock); return (false); } @@ -1575,6 +1575,18 @@ } } +bool +inp_smr_lock(struct inpcb *inp, const inp_lookup_t lock) +{ + + /* + * in_pcblookup() family of functions ignore not only freed entries, + * that may be found due to lockless access to the hash, but dropped + * entries, too. + */ + return (_inp_smr_lock(inp, lock, INP_FREED | INP_DROPPED)); +} + /* * inp_next() - inpcb hash/list traversal iterator * @@ -1631,7 +1643,7 @@ inp = II_LIST_NEXT(inp, hash)) { if (match != NULL && (match)(inp, ctx) == false) continue; - if (__predict_true(inp_smr_lock(inp, lock))) + if (__predict_true(_inp_smr_lock(inp, lock, INP_FREED))) break; else { smr_enter(ipi->ipi_smr); diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -937,16 +937,7 @@ goto dropwithreset; } INP_LOCK_ASSERT(inp); - /* - * While waiting for inp lock during the lookup, another thread - * can have dropped the inpcb, in which case we need to loop back - * and try to find a new inpcb to deliver to. - */ - if (inp->inp_flags & INP_DROPPED) { - INP_UNLOCK(inp); - inp = NULL; - goto findpcb; - } + if ((inp->inp_flowtype == M_HASHTYPE_NONE) && (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) && ((inp->inp_socket == NULL) || !SOLISTENING(inp->inp_socket))) { diff --git a/sys/netinet/tcp_lro.c b/sys/netinet/tcp_lro.c --- a/sys/netinet/tcp_lro.c +++ b/sys/netinet/tcp_lro.c @@ -1360,9 +1360,7 @@ tp = intotcpcb(inp); /* Check if the inp is dead, Jim. */ - if (tp == NULL || - (inp->inp_flags & INP_DROPPED) || - (tp->t_state == TCPS_TIME_WAIT)) { + if (tp->t_state == TCPS_TIME_WAIT) { INP_WUNLOCK(inp); return (TCP_LRO_CANNOT); } diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -2878,8 +2878,7 @@ inp = in_pcblookup(&V_tcbinfo, ip->ip_dst, th->th_dport, ip->ip_src, th->th_sport, INPLOOKUP_WLOCKPCB, NULL); if (inp != NULL) { - if (!(inp->inp_flags & INP_DROPPED) && - !(inp->inp_socket == NULL)) { + if (inp->inp_socket != NULL) { tp = intotcpcb(inp); #ifdef TCP_OFFLOAD if (tp->t_flags & TF_TOE && errno == EMSGSIZE) { @@ -3071,8 +3070,7 @@ } m_copydata(m, off, sizeof(tcp_seq), (caddr_t)&icmp_tcp_seq); if (inp != NULL) { - if (!(inp->inp_flags & INP_DROPPED) && - !(inp->inp_socket == NULL)) { + if (inp->inp_socket != NULL) { tp = intotcpcb(inp); #ifdef TCP_OFFLOAD if (tp->t_flags & TF_TOE && errno == EMSGSIZE) { @@ -3697,8 +3695,7 @@ #endif } if (inp != NULL) { - if ((inp->inp_flags & INP_DROPPED) == 0 && - !SOLISTENING(inp->inp_socket)) { + if (!SOLISTENING(inp->inp_socket)) { tp = intotcpcb(inp); tp = tcp_drop(tp, ECONNABORTED); if (tp != NULL) @@ -3817,8 +3814,7 @@ } NET_EPOCH_EXIT(et); if (inp != NULL) { - if ((inp->inp_flags & INP_DROPPED) != 0 || - inp->inp_socket == NULL) { + if (inp->inp_socket == NULL) { error = ECONNRESET; INP_WUNLOCK(inp); } else {