From: sashiko-bot@kernel.org
To: "Yehyeong Lee" <yhlee@isslab.korea.ac.kr>
Cc: linux-rdma@vger.kernel.org, target-devel@vger.kernel.org
Subject: Re: [PATCH v4 2/3] IB/isert: drain the QP without holding isert_conn->mutex
Date: Tue, 03 Nov 2026 03:52:56 +0000 [thread overview]
Message-ID: <sashiko-outbox-194544@kernel.org> (raw)
In-Reply-To: <20261103032924.1073138-3-yhlee@isslab.korea.ac.kr>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] IB/isert: race with isert_accept_np() when draining QP unlocked
- [Low] IB/isert: missing colon in Return section of isert_conn_terminate() kernel-doc
--
commit 563514f12bfc26c4edaed45f85db0c8c5f4ade31
Author: Yehyeong Lee <yhlee@isslab.korea.ac.kr>
IB/isert: drain the QP without holding isert_conn->mutex
This commit changes isert_conn_terminate() to return whether it moved the
connection to ISER_CONN_TERMINATING, and moves ib_drain_qp() and
isert_handle_unbound_conn() outside isert_conn->mutex in
isert_disconnected_handler() to avoid deadlocking with
isert_login_recv_done().
> diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c
> index 8255208e30c7d..c6f417bb20690 100644
> --- a/drivers/infiniband/ulp/isert/ib_isert.c
> +++ b/drivers/infiniband/ulp/isert/ib_isert.c
> @@ -578,21 +578,17 @@ isert_handle_unbound_conn(struct isert_conn *isert_conn)
> * isert_conn_terminate() - Initiate connection termination
> * @isert_conn: isert connection struct
> *
> - * Notes:
> - * In case the connection state is BOUND, move state
> - * to TEMINATING and start teardown sequence (rdma_disconnect).
> - * In case the connection state is UP, complete flush as well.
> - *
> - * This routine must be called with mutex held. Thus it is
> - * safe to call multiple times.
> + * Returns true if this caller moved the connection to ISER_CONN_TERMINATING.
> */
[Severity: Low]
This isn't a bug, but kernel-doc requires a colon after Returns (Returns:)
to recognize the return value section when building with W=2.
> -static void
> +static bool
> isert_conn_terminate(struct isert_conn *isert_conn)
> {
> int err;
>
> + lockdep_assert_held(&isert_conn->mutex);
> +
> if (isert_conn->state >= ISER_CONN_TERMINATING)
> - return;
> + return false;
>
> isert_info("Terminating conn %p state %d\n",
> isert_conn, isert_conn->state);
> @@ -601,6 +597,8 @@ isert_conn_terminate(struct isert_conn *isert_conn)
> if (err)
> isert_warn("Failed rdma_disconnect isert_conn %p\n",
> isert_conn);
> +
> + return true;
> }
>
> static int
> @@ -635,15 +633,14 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id,
> enum rdma_cm_event_type event)
> {
> struct isert_conn *isert_conn = cma_id->qp->qp_context;
> + bool terminated = false;
>
> mutex_lock(&isert_conn->mutex);
> switch (isert_conn->state) {
> case ISER_CONN_TERMINATING:
> break;
> case ISER_CONN_UP:
> - isert_conn_terminate(isert_conn);
> - ib_drain_qp(isert_conn->qp);
> - isert_handle_unbound_conn(isert_conn);
> + terminated = isert_conn_terminate(isert_conn);
> break;
> case ISER_CONN_BOUND:
> case ISER_CONN_FULL_FEATURE: /* FALLTHRU */
> @@ -655,6 +652,11 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id,
> }
> mutex_unlock(&isert_conn->mutex);
>
> + if (terminated) {
> + ib_drain_qp(isert_conn->qp);
> + isert_handle_unbound_conn(isert_conn);
> + }
[Severity: High]
Can dropping isert_conn->mutex before ib_drain_qp() and
isert_handle_unbound_conn() race with isert_accept_np()?
When a connection reaches isert_connected_handler(), its state is set to
ISER_CONN_UP, isert_conn->node is placed on isert_np->pending, and
up(&isert_np->sem) wakes the login thread in isert_accept_np().
If a disconnect arrives while the connection is still in ISER_CONN_UP,
isert_disconnected_handler() sets isert_conn->state to
ISER_CONN_TERMINATING and now unlocks isert_conn->mutex before removing
isert_conn->node from isert_np->pending in isert_handle_unbound_conn().
While ib_drain_qp() is waiting in isert_disconnected_handler(),
isert_login_recv_done() can complete isert_conn->login_req_comp for a login
PDU received just before the disconnect, and isert_accept_np() can dequeue
isert_conn from isert_np->pending and overwrite isert_conn->state without
holding isert_conn->mutex:
drivers/infiniband/ulp/isert/ib_isert.c:isert_accept_np() {
...
isert_conn = list_first_entry(&isert_np->pending,
struct isert_conn, node);
list_del_init(&isert_conn->node);
mutex_unlock(&isert_np->mutex);
conn->context = isert_conn;
isert_conn->conn = conn;
isert_conn->state = ISER_CONN_BOUND;
...
}
Once list_del_init(&isert_conn->node) has run in isert_accept_np(),
isert_handle_unbound_conn() sees list_empty(&isert_conn->node) and becomes
a no-op.
If login then fails or times out, iscsi_target_login_sess_out() calls
isert_wait_conn() and isert_free_conn():
drivers/infiniband/ulp/isert/ib_isert.c:isert_wait_conn() {
...
mutex_lock(&isert_conn->mutex);
isert_conn_terminate(isert_conn);
mutex_unlock(&isert_conn->mutex);
ib_drain_qp(isert_conn->qp);
isert_put_conn(isert_conn);
queue_work(isert_release_wq, &isert_conn->release_work);
}
Because isert_conn->state was reset to ISER_CONN_BOUND and
isert_conn->mutex is no longer held across ib_drain_qp(), wouldn't
isert_wait_conn() call ib_drain_qp(isert_conn->qp) a second time
concurrently with isert_disconnected_handler(), and allow both kref
references on isert_conn to be dropped while isert_disconnected_handler()
is still running?
Alternatively, if single-stage login succeeds in memory without posting to
the QP (isert_put_login_tx() sets isert_conn->login_rsp_pending = true),
wouldn't isert_get_rx_pdu() set isert_conn->state to ISER_CONN_FULL_FEATURE,
post to the already-disconnected QP, and block indefinitely in
wait_for_completion_interruptible(&comp) because the disconnect event was
already handled?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261103032924.1073138-1-yhlee@isslab.korea.ac.kr?part=2
next prev parent reply other threads:[~2026-11-03 3:52 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-03 3:29 [PATCH v4 0/3] IB/isert: fix the device removal use-after-free Yehyeong Lee
2026-11-03 3:29 ` [PATCH v4 1/3] IB/isert: do not publish connections being released on a second list Yehyeong Lee
2026-11-03 3:53 ` sashiko-bot
2026-11-03 3:29 ` [PATCH v4 2/3] IB/isert: drain the QP without holding isert_conn->mutex Yehyeong Lee
2026-11-03 3:52 ` sashiko-bot [this message]
2026-11-03 3:29 ` [PATCH v4 3/3] IB/isert: tear connections down from an ib_client on device removal Yehyeong Lee
2026-11-03 3:56 ` sashiko-bot
2026-11-03 13:04 ` [PATCH v4 0/3] IB/isert: fix the device removal use-after-free Yehyeong Lee
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=sashiko-outbox-194544@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=linux-rdma@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=target-devel@vger.kernel.org \
--cc=yhlee@isslab.korea.ac.kr \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.