[PATCH v4 2/2] IB/isert: post the full-feature receive buffers after session registration
From: Yehyeong Lee
Date: Fri Jul 31 2026 - 00:15:03 EST
isert_put_login_tx() posts the full-feature receive buffers before
__transport_register_session() runs, so an initiator that does not wait
for the final Login Response can still have a SCSI command executed
against an se_session whose se_tpg is NULL - the same oops as the
previous patch, at target_submit+0xbe.
Post them from isert_get_rx_pdu(), which the previous patch already uses
to send that response, and post them before that send: the receive queue
is filled at the moment the initiator is told it may use it. Allocating
there keeps the existing property that a memory allocation failure cannot
happen once the final Login Response is on the wire.
The receive queue is already empty between the final Login Request and
isert_post_recvm(); this moves the second point later, from a median of
92 us to 172 us over 1200 logins. Only an initiator that sends before it
has been told to can reach that window, and on IB and RoCE its send is
retried there until the buffers appear - isert_rdma_accept() asks for
rnr_retry_count = 7. iWARP has no RNR flow control, so there the same
send terminates the connection instead.
Measured over rxe, 400 login cycles per run, with an initiator that does
not wait: an instrumented build counted no entries to isert_recv_done()
before the buffers are posted in 10 runs, where that initiator oopsed
8 of 10 unpatched runs and 5 of 10 with only the previous patch.
Not tested: iWARP, discovery sessions over iSER, and real HCAs.
Fixes: b8d26b3be8b3 ("iser-target: Add iSCSI Extensions for RDMA (iSER) target driver")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Yehyeong Lee <yhlee@xxxxxxxxxxxxxxxxxx>
---
v4: 2/2 replaced. v3's version rejected such PDUs from isert_recv_done()
and reinstated the connection, which strands both iscsi kthreads because
conn->conn_state is still TARG_CONN_STATE_IN_LOGIN when it runs; dropping
the PDU instead leaves a gap in the CmdSN stream that
iscsit_close_connection() then waits on. Both reproduce; this does
neither.
v3: https://lore.kernel.org/all/20260730135110.1647384-1-yhlee@xxxxxxxxxxxxxxxxxx/
drivers/infiniband/ulp/isert/ib_isert.c | 41 ++++++++++++-------------
1 file changed, 20 insertions(+), 21 deletions(-)
diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c
index e117cd2e62c9..545212ae4792 100644
--- a/drivers/infiniband/ulp/isert/ib_isert.c
+++ b/drivers/infiniband/ulp/isert/ib_isert.c
@@ -947,21 +947,7 @@ isert_put_login_tx(struct iscsit_conn *conn, struct iscsi_login *login,
}
if (!login->login_failed) {
if (login->login_complete) {
- ret = isert_alloc_rx_descriptors(isert_conn);
- if (ret)
- return ret;
-
- ret = isert_post_recvm(isert_conn,
- ISERT_QP_MAX_RECV_DTOS);
- if (ret)
- return ret;
-
- /* Now we are in FULL_FEATURE phase */
- mutex_lock(&isert_conn->mutex);
- isert_conn->state = ISER_CONN_FULL_FEATURE;
- mutex_unlock(&isert_conn->mutex);
-
- /* Sent from isert_get_rx_pdu() after registration. */
+ /* Posted and sent from isert_get_rx_pdu(). */
isert_conn->login_rsp_pending = true;
return 0;
}
@@ -2595,13 +2581,26 @@ static void isert_get_rx_pdu(struct iscsit_conn *conn)
struct isert_conn *isert_conn = conn->context;
struct completion comp;
+ /* The login timeout timer can fail the login after isert_put_login_tx(). */
+ if (!isert_conn->login_rsp_pending)
+ return;
+
+ isert_conn->login_rsp_pending = false;
+
/* The session is registered by now; see isert_put_login_tx(). */
- if (isert_conn->login_rsp_pending) {
- isert_conn->login_rsp_pending = false;
- if (isert_login_post_send(isert_conn,
- &isert_conn->login_tx_desc))
- return;
- }
+ if (isert_alloc_rx_descriptors(isert_conn))
+ return;
+
+ if (isert_post_recvm(isert_conn, ISERT_QP_MAX_RECV_DTOS))
+ return;
+
+ /* Now we are in FULL_FEATURE phase */
+ mutex_lock(&isert_conn->mutex);
+ isert_conn->state = ISER_CONN_FULL_FEATURE;
+ mutex_unlock(&isert_conn->mutex);
+
+ if (isert_login_post_send(isert_conn, &isert_conn->login_tx_desc))
+ return;
init_completion(&comp);
--
2.43.0