git: 2eb0e53a6b5e - main - cxgbei: Wait for the final CPL to be received in icl_cxgbei_conn_close.
John Baldwin
jhb at FreeBSD.org
Thu Aug 12 16:06:16 UTC 2021
The branch main has been updated by jhb:
URL: https://cgit.FreeBSD.org/src/commit/?id=2eb0e53a6b5ec1a72be70e966d4e562e1a8d4e88
commit 2eb0e53a6b5ec1a72be70e966d4e562e1a8d4e88
Author: John Baldwin <jhb at FreeBSD.org>
AuthorDate: 2021-08-12 15:48:14 +0000
Commit: John Baldwin <jhb at FreeBSD.org>
CommitDate: 2021-08-12 15:48:35 +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
---
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 1d065ade77c4..a444f0c9d690 100644
--- a/sys/dev/cxgbe/tom/t4_tom.c
+++ b/sys/dev/cxgbe/tom/t4_tom.c
@@ -1008,6 +1008,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);
@@ -1022,7 +1023,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);
@@ -1031,6 +1033,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 10d9cfe87960..dc462d4b4a66 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 {
More information about the dev-commits-src-main
mailing list