aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorBart Van Assche <bvanassche@acm.org>2026-08-18 12:52:29 +0900
committerLeon Romanovsky <leon@kernel.org>2026-09-02 08:58:55 -0400
commit9cdfad5dd5529e1700f51feaed5e8a90044d7e35 (patch)
tree8b7ead01094d0f43127b37d9f083cb7f09a5b5d9
parentIB/mlx4: Fix use-after-free on pkey sysfs registration failure (diff)
RDMA/srp: Fix srp_remove_target()
Remove all logical units before disconnecting the transport because one or more SCSI commands may be submitted while removing logical units. Remove the SCSI host after the transport has been disconnected because the code that disconnects the transport needs resources that are freed by the code that removes the SCSI host (SCSI host tag set). Remove the srp_rport_get() and srp_rport_put() calls because the purpose of these calls was to keep the rport until tl_err_work is cancelled. Reported-by: Yehyeong Lee <yhlee@isslab.korea.ac.kr> Closes: https://lore.kernel.org/linux-rdma/20260812190418.200337-1-yhlee@isslab.korea.ac.kr/ Signed-off-by: Bart Van Assche <bvanassche@acm.org> Signed-off-by: Yehyeong Lee <yhlee@isslab.korea.ac.kr> Signed-off-by: Leon Romanovsky <leon@kernel.org>
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 6b429ef63f8f..955f36efeebd 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -1038,15 +1038,20 @@ static void srp_del_scsi_host_attr(struct Scsi_Host *shost)
static void srp_remove_target(struct srp_target_port *target)
{
+ struct scsi_device *sdev;
struct srp_rdma_ch *ch;
int i;
WARN_ON_ONCE(target->state != SRP_TARGET_REMOVED);
srp_del_scsi_host_attr(target->scsi_host);
- srp_rport_get(target->rport);
- srp_remove_host(target->scsi_host);
- scsi_remove_host(target->scsi_host);
+ /*
+ * Remove all logical units. This must happen before the
+ * srp_disconnect_target() call because scsi_remove_device() may trigger
+ * submission of SCSI commands. See also sd_shutdown().
+ */
+ shost_for_each_device(sdev, target->scsi_host)
+ scsi_remove_device(sdev);
srp_stop_rport_timers(target->rport);
srp_disconnect_target(target);
kobj_ns_drop(KOBJ_NS_TYPE_NET, to_ns_common(target->net));
@@ -1055,7 +1060,8 @@ static void srp_remove_target(struct srp_target_port *target)
srp_free_ch_ib(target, ch);
}
cancel_work_sync(&target->tl_err_work);
- srp_rport_put(target->rport);
+ srp_remove_host(target->scsi_host);
+ scsi_remove_host(target->scsi_host);
kfree(target->ch);
target->ch = NULL;