git: 37c5daa85596 - stable/13 - cxgbei: Wait for the final CPL to be received in icl_cxgbei_conn_close.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 29 Oct 2021 23:58:32 UTC
The branch stable/13 has been updated by jhb: URL: https://cgit.FreeBSD.org/src/commit/?id=37c5daa855966118e99bca7f5c79f7c20c61529c commit 37c5daa855966118e99bca7f5c79f7c20c61529c Author: John Baldwin <jhb@FreeBSD.org> AuthorDate: 2021-08-12 15:48:14 +0000 Commit: John Baldwin <jhb@FreeBSD.org> CommitDate: 2021-10-29 23:27:31 +0000 cxgbei: Wait for the final CPL to be received in icl_cxgbei_conn_close. A socket in the FIN_WAIT_1 state is marked disconnected by do_close_con_rpl() even though there might still receive data pending. This is because the socket at that point has set SBS_CANTRCVMORE which causes the protocol layer to discard any data received before the FIN. However, icl_cxgbei_conn_close needs to wait until all the data has been discarded. Replace the wait for SS_ISDISCONNECTED with instead waiting for final_cpl_received() to be called. Reported by: Jithesh Arakkan @ Chelsio Sponsored by: Chelsio Communications (cherry picked from commit 2eb0e53a6b5ec1a72be70e966d4e562e1a8d4e88) --- sys/dev/cxgbe/cxgbei/icl_cxgbei.c | 28 +++++++++++++++++++++------- sys/dev/cxgbe/tom/t4_tom.c | 12 +++++++++++- sys/dev/cxgbe/tom/t4_tom.h | 1 + 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/sys/dev/cxgbe/cxgbei/icl_cxgbei.c b/sys/dev/cxgbe/cxgbei/icl_cxgbei.c index a57d26ae21b8..5526388915f7 100644 --- a/sys/dev/cxgbe/cxgbei/icl_cxgbei.c +++ b/sys/dev/cxgbe/cxgbei/icl_cxgbei.c @@ -947,6 +947,18 @@ icl_cxgbei_conn_close(struct icl_conn *ic) icl_cxgbei_pdu_done(ip, ENOTCONN); } SOCKBUF_UNLOCK(sb); + + /* + * Grab a reference to use when waiting for the final + * CPL to be received. If toep->inp is NULL, then + * final_cpl_received() has already been called (e.g. + * due to the peer sending a RST). + */ + if (toep->inp != NULL) { + toep = hold_toepcb(toep); + toep->flags |= TPF_WAITING_FOR_FINAL; + } else + toep = NULL; } INP_WUNLOCK(inp); @@ -959,7 +971,6 @@ icl_cxgbei_conn_close(struct icl_conn *ic) * queues were purged instead of delivered reliably but soabort isn't * really general purpose and wouldn't do the right thing here. */ - soref(so); soclose(so); /* @@ -969,12 +980,15 @@ icl_cxgbei_conn_close(struct icl_conn *ic) * Callers assume that it is safe to free buffers for tasks * and transfers after this function returns. */ - SOCK_LOCK(so); - while ((so->so_state & SS_ISDISCONNECTED) == 0) - mtx_sleep(&so->so_timeo, SOCK_MTX(so), PSOCK, "conclo2", 0); - CURVNET_SET(so->so_vnet); - sorele(so); - CURVNET_RESTORE(); + if (toep != NULL) { + struct mtx *lock = mtx_pool_find(mtxpool_sleep, toep); + + mtx_lock(lock); + while ((toep->flags & TPF_WAITING_FOR_FINAL) != 0) + mtx_sleep(toep, lock, PSOCK, "conclo2", 0); + mtx_unlock(lock); + free_toepcb(toep); + } } static void diff --git a/sys/dev/cxgbe/tom/t4_tom.c b/sys/dev/cxgbe/tom/t4_tom.c index f3cd8270d24d..fdd0ab870f43 100644 --- a/sys/dev/cxgbe/tom/t4_tom.c +++ b/sys/dev/cxgbe/tom/t4_tom.c @@ -848,6 +848,7 @@ void final_cpl_received(struct toepcb *toep) { struct inpcb *inp = toep->inp; + bool need_wakeup; KASSERT(inp != NULL, ("%s: inp is NULL", __func__)); INP_WLOCK_ASSERT(inp); @@ -862,7 +863,8 @@ final_cpl_received(struct toepcb *toep) else if (ulp_mode(toep) == ULP_MODE_TLS) tls_detach(toep); toep->inp = NULL; - toep->flags &= ~TPF_CPL_PENDING; + need_wakeup = (toep->flags & TPF_WAITING_FOR_FINAL) != 0; + toep->flags &= ~(TPF_CPL_PENDING | TPF_WAITING_FOR_FINAL); mbufq_drain(&toep->ulp_pduq); mbufq_drain(&toep->ulp_pdu_reclaimq); @@ -871,6 +873,14 @@ final_cpl_received(struct toepcb *toep) if (!in_pcbrele_wlocked(inp)) INP_WUNLOCK(inp); + + if (need_wakeup) { + struct mtx *lock = mtx_pool_find(mtxpool_sleep, toep); + + mtx_lock(lock); + wakeup(toep); + mtx_unlock(lock); + } } void diff --git a/sys/dev/cxgbe/tom/t4_tom.h b/sys/dev/cxgbe/tom/t4_tom.h index 89c38f8c988a..2224ece20c38 100644 --- a/sys/dev/cxgbe/tom/t4_tom.h +++ b/sys/dev/cxgbe/tom/t4_tom.h @@ -76,6 +76,7 @@ enum { TPF_INITIALIZED = (1 << 12), /* init_toepcb has been called */ TPF_TLS_RECEIVE = (1 << 13), /* should receive TLS records */ TPF_TLS_ESTABLISHED = (1 << 14), /* TLS handshake timer initialized */ + TPF_WAITING_FOR_FINAL = (1<< 15), /* waiting for wakeup on final CPL */ }; enum {