All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Nilesh Javali" <njavali@marvell.com>
Cc: linux-scsi@vger.kernel.org
Subject: Re: [PATCH v2 06/13] scsi: qla2xxx: Fix scan state machine race and IRQ-unsafe sp_unmap
Date: Fri, 23 Oct 2026 10:34:16 +0000	[thread overview]
Message-ID: <sashiko-outbox-182693@kernel.org> (raw)
In-Reply-To: <20261023101600.1431179-7-njavali@marvell.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] scsi: qla2xxx: incomplete scan.step race fix in qla_async_scan_sp_done()
- [High] scsi: qla2xxx: sp and DMA leak in qla_async_scan_sp_done() on work alloc fail
--

commit e9cd982d25a90416902027b8c35c59ac8e31a64e
Author: Manish Rangankar <mrangankar@marvell.com>

scsi: qla2xxx: Fix scan state machine race and IRQ-unsafe sp_unmap

This commit saves vha->scan.step into a local variable under work_lock in
qla_async_scan_sp_done() and defers qla24xx_sp_unmap() to process context via
QLA_EVT_UNMAP when posting scan work fails.

> diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
> index 20b1aef455c4f..efe98609c149d 100644
> --- a/drivers/scsi/qla2xxx/qla_gs.c
> +++ b/drivers/scsi/qla2xxx/qla_gs.c
> @@ -3512,6 +3512,8 @@ static void qla2x00_find_free_fcp_nvme_slot(struct scsi_qla_host *vha,
>  static void qla_async_scan_sp_done(srb_t *sp, int res)
>  {
>  	struct scsi_qla_host *vha = sp->vha;
> +	struct qla_work_evt *e;
> +	enum scan_step step;
>  	unsigned long flags;
>  	int rc;
>  
> @@ -3544,8 +3546,16 @@ static void qla_async_scan_sp_done(srb_t *sp, int res)
>  		 */
>  		rc = qla2x00_post_next_scan_work(vha, sp, QLA_EVT_SCAN_FINISH);
>  		if (rc) {
> -			/* Cleanup here to prevent memory leak */
> -			qla24xx_sp_unmap(vha, sp);
> +			/* Defer sp_unmap to process context -- we are in IRQ */
> +			e = qla2x00_alloc_work(vha, QLA_EVT_UNMAP);
> +			if (e) {
> +				e->u.iosb.sp = sp;
> +				qla2x00_post_work(vha, e);
> +			} else {
> +				ql_log(ql_log_warn, vha, 0x2029,
> +				       "%s: Failed to schedule sp_unmap, sp leaked\n",
> +				       name);
> +			}
>  
>  			spin_lock_irqsave(&vha->work_lock, flags);
>  			vha->scan.scan_flags &= ~SF_SCANNING;
> @@ -3568,10 +3578,11 @@ static void qla_async_scan_sp_done(srb_t *sp, int res)
>  	qla2x00_find_free_fcp_nvme_slot(vha, sp);
>  
>  	spin_lock_irqsave(&vha->work_lock, flags);
> +	step = vha->scan.step;
>  	vha->scan.scan_flags &= ~SF_SCANNING;
>  	spin_unlock_irqrestore(&vha->work_lock, flags);
>  
> -	switch (vha->scan.step) {
> +	switch (step) {

[Severity: High]
Does saving vha->scan.step into a local variable while clearing SF_SCANNING
between scan steps allow two fabric scans to run concurrently and corrupt
vha->scan?

In the race described by the commit message, as soon as SF_SCANNING is
cleared here in qla_async_scan_sp_done(), another CPU calling
qla_fab_scan_start() -> qla_fab_async_scan(vha, NULL) can see SF_SCANNING
clear, set SF_SCANNING, reset vha->scan.step to FAB_SCAN_START, and zero
vha->scan.l:

drivers/scsi/qla2xxx/qla_gs.c:qla_fab_async_scan() {
	spin_lock_irqsave(&vha->work_lock, flags);
	if (vha->scan.scan_flags & SF_SCANNING) {
		spin_unlock_irqrestore(&vha->work_lock, flags);
		ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x2012,
		    "%s: scan active for sp:%p\n", __func__, sp);
		goto done_free_sp;
	}
	vha->scan.scan_flags |= SF_SCANNING;
	if (!sp)
		vha->scan.step = FAB_SCAN_START;

	spin_unlock_irqrestore(&vha->work_lock, flags);
	...
		memset(vha->scan.l, 0, vha->scan.size);
}

With this change, qla_async_scan_sp_done() switches on the saved step and
posts QLA_EVT_SCAN_CMD or QLA_EVT_SCAN_FINISH for the first scan while the
second scan is also running:

1. If step was FAB_SCAN_GNNFT_NVME (or FAB_SCAN_GNNFT_FCP without NVMe),
   qla_fab_scan_finish() runs on the workqueue concurrently with the new
   scan, reads vha->scan.l while the new scan zeroes or overwrites it (which
   can leave online ports in QLA_FCPORT_SCAN and schedule them for deletion
   via qlt_schedule_sess_for_deletion()), and then clears SF_SCANNING at the
   out label while the second scan's SRB is in flight.

2. If step was an intermediate step, qla_fab_async_scan(vha, sp) runs with
   the first scan's non-NULL sp. If the second scan failed an allocation in
   FAB_SCAN_START (which clears SF_SCANNING while leaving vha->scan.step as
   FAB_SCAN_START), the first scan enters case FAB_SCAN_START and overwrites
   sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL), leaking the first scan's sp
   and its coherent DMA buffers ctarg.req and ctarg.rsp.

3. Conversely, if qla_fab_async_scan() is entered while SF_SCANNING is
   already set, it jumps to done_free_sp, which unconditionally clears
   SF_SCANNING:

drivers/scsi/qla2xxx/qla_gs.c:qla_fab_async_scan() {
done_free_sp:
	...
	spin_lock_irqsave(&vha->work_lock, flags);
	vha->scan.scan_flags &= ~SF_SCANNING;
}

   Once SF_SCANNING is cleared while an SRB is still in flight, another
   qla_fab_scan_start() call can set vha->scan.step = FAB_SCAN_START before
   qla_async_scan_sp_done() runs, so qla2x00_find_free_fcp_nvme_slot() (which
   reads vha->scan.step outside work_lock) and step = vha->scan.step in
   qla_async_scan_sp_done() will still see FAB_SCAN_START and hit WARN_ON(1).

>  	case FAB_SCAN_GPNFT_FCP:
>  	case FAB_SCAN_GPNFT_NVME:
>  		rc = qla2x00_post_next_scan_work(vha, sp, QLA_EVT_SCAN_CMD);
> @@ -3594,7 +3605,16 @@ static void qla_async_scan_sp_done(srb_t *sp, int res)
>  	}
>  
>  	if (rc) {
> -		qla24xx_sp_unmap(vha, sp);
> +		/* Defer sp_unmap to process context -- we are in IRQ */
> +		e = qla2x00_alloc_work(vha, QLA_EVT_UNMAP);
> +		if (e) {
> +			e->u.iosb.sp = sp;
> +			qla2x00_post_work(vha, e);
> +		} else {
> +			ql_log(ql_log_warn, vha, 0x202a,
> +			       "%s: Failed to schedule sp_unmap, sp leaked\n",
> +			       __func__);
> +		}

[Severity: High]
Can qla2x00_alloc_work(vha, QLA_EVT_UNMAP) ever succeed here or in the error
path above when qla2x00_post_next_scan_work() just failed, and does this leak
sp, its DMA buffers, and its vha and qpair references during unload or vport
deletion?

Looking at qla2x00_post_next_scan_work():

drivers/scsi/qla2xxx/qla_gs.c:qla2x00_post_next_scan_work() {
	e = qla2x00_alloc_work(vha, cmd);
	if (!e)
		return QLA_FUNCTION_FAILED;

	e->u.iosb.sp = sp;

	return qla2x00_post_work(vha, e);
}

Since qla2x00_post_work() always returns QLA_SUCCESS,
qla2x00_post_next_scan_work() only fails when qla2x00_alloc_work() returns
NULL:

drivers/scsi/qla2xxx/qla_os.c:qla2x00_alloc_work() {
	if (test_bit(UNLOADING, &vha->dpc_flags))
		return NULL;

	if (qla_vha_mark_busy(vha))
		return NULL;

	e = kzalloc_obj(struct qla_work_evt, GFP_ATOMIC);
	...
}

When an in-flight scan SRB is aborted during driver unload (where UNLOADING
is set before qla2x00_abort_all_cmds() invokes sp->done()) or vport deletion
(where delete_progress causes qla_vha_mark_busy() to fail),
qla2x00_post_next_scan_work() fails because qla2x00_alloc_work() returns
NULL. Calling qla2x00_alloc_work(vha, QLA_EVT_UNMAP) immediately afterwards
checks the exact same conditions and will also return NULL (and under
GFP_ATOMIC allocation failure, retries the identical allocation in the same
hard IRQ context).

When the else branch is taken, sp, sp->u.iocb_cmd.u.ctarg.req, and
sp->u.iocb_cmd.u.ctarg.rsp are leaked, and kref_put(&sp->cmd_kref,
qla2x00_sp_release) is never called, leaving vha->vref_count elevated (which
stalls qla24xx_deallocate_vp_id()) and leaving objects allocated in
srb_cachep when kmem_cache_destroy(srb_cachep) runs in qla2x00_module_exit().

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261023101600.1431179-1-njavali@marvell.com?part=6

  reply	other threads:[~2026-10-23 10:34 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-23 10:15 [PATCH v2 00/13] scsi: qla2xxx: Misc. Bug fixes Nilesh Javali
2026-10-23 10:15 ` [PATCH v2 01/13] scsi: qla2xxx: Update MAINTAINERS with new FC storage alias Nilesh Javali
2026-10-23 10:15 ` [PATCH v2 02/13] scsi: qla2xxx: Update few AENs for 29xx handling Nilesh Javali
2026-10-23 10:36   ` sashiko-bot
2026-10-23 10:15 ` [PATCH v2 03/13] Revert "scsi: qla2xxx: Validate BSG request_len before reading vendor_cmd[]" Nilesh Javali
2026-10-23 10:33   ` sashiko-bot
2026-10-23 10:15 ` [PATCH v2 04/13] scsi: qla2xxx: Wait for session deletion before full-login LIP Nilesh Javali
2026-10-23 10:35   ` sashiko-bot
2026-10-23 10:15 ` [PATCH v2 05/13] scsi: qla2xxx: Fix double addition of fcport to gnl.fcport list Nilesh Javali
2026-10-23 10:38   ` sashiko-bot
2026-10-23 10:15 ` [PATCH v2 06/13] scsi: qla2xxx: Fix scan state machine race and IRQ-unsafe sp_unmap Nilesh Javali
2026-10-23 10:34   ` sashiko-bot [this message]
2026-10-23 10:15 ` [PATCH v2 07/13] scsi: qla2xxx: Skip vport DPC processing during vport deletion Nilesh Javali
2026-10-23 10:15 ` [PATCH v2 08/13] scsi: qla2xxx: Add validation check for base vport index during delete Nilesh Javali
2026-10-23 10:15 ` [PATCH v2 09/13] scsi: qla2xxx: Validate vport before deletion Nilesh Javali
2026-10-23 10:15 ` [PATCH v2 10/13] scsi: qla2xxx: Fix use-after-free races during vport deletion Nilesh Javali
2026-10-23 10:53   ` sashiko-bot
2026-10-23 10:15 ` [PATCH v2 11/13] scsi: qla2xxx: Re-acquire vport_slock and refresh tvp during vport DPC Nilesh Javali
2026-10-23 10:53   ` sashiko-bot
2026-10-23 10:15 ` [PATCH v2 12/13] scsi: qla2xxx: Fix purex IOCB copy size on non-29xx adapters Nilesh Javali
2026-10-23 10:43   ` sashiko-bot
2026-10-23 10:16 ` [PATCH v2 13/13] scsi: qla2xxx: Update version to 12.00.00.2610b1 Nilesh Javali

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-182693@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=linux-scsi@vger.kernel.org \
    --cc=njavali@marvell.com \
    --cc=sashiko-reviews@lists.linux.dev \
    /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.