Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 29 Oct 2021 23:58:32 GMT
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: 37c5daa85596 - stable/13 - cxgbei: Wait for the final CPL to be received in icl_cxgbei_conn_close.
Message-ID:  <202110292358.19TNwW3a003899@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202110292358.19TNwW3a003899>