The branch main has been updated by jhb:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=2eb0e53a6b5ec1a72be70e966d4e562e1a8d4e88

commit 2eb0e53a6b5ec1a72be70e966d4e562e1a8d4e88
Author:     John Baldwin <j...@freebsd.org>
AuthorDate: 2021-08-12 15:48:14 +0000
Commit:     John Baldwin <j...@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 {
_______________________________________________
dev-commits-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-all
To unsubscribe, send any mail to "dev-commits-src-all-unsubscr...@freebsd.org"

Reply via email to