All of lore.kernel.org
 help / color / mirror / Atom feed
From: Damien Le Moal <dlemoal@kernel.org>
To: sashiko-reviews@lists.linux.dev
Cc: cassel@kernel.org, linux-ide@vger.kernel.org, linux-scsi@vger.kernel.org
Subject: Re: [PATCH v6 1/2] ata: libata-scsi: terminate deferred commands on time out
Date: Mon, 20 Jul 2026 18:33:01 +0900	[thread overview]
Message-ID: <8a4b58ca-c172-429d-8de3-34f92f5d2264@kernel.org> (raw)
In-Reply-To: <20260720073106.E10121F000E9@smtp.kernel.org>

On 7/20/26 16:31, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [High] A race condition between block layer timeout work and the SCSI EH thread causes deferred QCs to fail permanently, resulting in spurious I/O errors.
> --
> 
> --- Patch [1]: [PATCH v6 1/2] ata: libata-scsi: terminate deferred commands on time out ---
> commit 65621fb40c8a19c964f38c70891c67cb0a3f9251
> Author: Damien Le Moal <dlemoal@kernel.org>
> Subject: ata: libata-scsi: terminate deferred commands on time out
> 
> If a command timeout occurs while we have deferred non-NCQ commands
> waiting to be issued, the SCSI EH task is not immediately woken up as the
> waiting deferred commands are never issued nor completed. Avoid this
> unnecessary SCSI EH task wake-up additional time by scheduling a retry of
> all waiting deferred QCs, using the eh_timed_out SCSI host template
> operation.
> 
>> diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
>> index 5868526301a2b..b02b4ca5c09e2 100644
>> --- a/drivers/ata/libata-scsi.c
>> +++ b/drivers/ata/libata-scsi.c
> 
> [ ... ]
> 
>> -void ata_scsi_requeue_deferred_qc(struct ata_port *ap)
>> +void ata_scsi_requeue_deferred_qc(struct ata_port *ap,
>> +				  struct scsi_cmnd *timedout_scmd)
>>  {
>> +	struct ata_queued_cmd *qc;
>>  	struct ata_link *link;
>>  
>>  	lockdep_assert_held(ap->lock);
>>  
>>  	/*
>> -	 * If we have a deferred qc when a reset occurs or NCQ commands fail,
>> -	 * do not try to be smart about what to do with this deferred command
>> -	 * and simply requeue it by completing it with DID_REQUEUE.
>> +	 * Trigger EH for any deferred qc, to either retry them or handle one
>> +	 * that timed out.
>>  	 */
>>  	ata_for_each_link(link, ap, PMP_FIRST) {
>> -		struct ata_queued_cmd *qc = link->deferred_qc;
>> +		qc = link->deferred_qc;
>> +		if (!qc)
>> +			continue;
>>  
>> -		if (qc) {
>> -			link->deferred_qc = NULL;
>> -			cancel_work(&link->deferred_qc_work);
>> +		link->deferred_qc = NULL;
>> +		cancel_work(&link->deferred_qc_work);
>> +
>> +		if (!timedout_scmd) {
>> +			/*
>> +			 * We are retrying due to some error. Complete the
>> +			 * request and ask for a requeue. In this case, since EH
>> +			 * was scheduled already, the block layer attempting to
>> +			 * re-issue the command immediately will not lead to the
>> +			 * device being kept busy, thus allowing SCSI EH task to
>> +			 * run.
>> +			 */
>>  			ata_scsi_qc_done(qc, true, DID_REQUEUE << 16);
>> +			continue;
>>  		}
>> +
>> +		/*
>> +		 * We are being called from scsi_timeout(). scsi_eh_scmd_add()
>> +		 * will add the command to eh_work_q and it will be handled by
>> +		 * ata_scsi_cmd_error_handler(). So here, we only need to
>> +		 * indicate if we want a retry if the command did not timeout.
>> +		 */
>> +		if (qc->scsicmd != timedout_scmd)
>> +			qc->flags |= ATA_QCFLAG_RETRY;
>> +
>> +		/*
>> +		 * Schedule EH, but set EH pending on the port so that we do not
>> +		 * reenter this function from ata_eh_set_pending() with
>> +		 * timedout_scmd being NULL and erroneously retry deferred QCs
>> +		 * that have timed out on other links.
>> +		 */
>> +		ap->pflags |= ATA_PFLAG_EH_PENDING;
>> +		ata_qc_schedule_eh(qc);
> 
> [Severity: High]
> Does this introduce a race condition between the block layer timeout work and
> the SCSI EH thread that could cause deferred QCs to fail permanently with
> spurious I/O errors?
> 
> When a command times out, ata_scsi_eh_timed_out() calls this and triggers
> ata_qc_schedule_eh() on deferred QCs. This calls blk_abort_request(), which
> schedules the block layer timeout_work asynchronously.
> 
> Meanwhile, the original timed-out command is added to eh_cmd_q and immediately
> wakes up the SCSI EH thread. If the SCSI EH thread processes eh_cmd_q in
> ata_scsi_cmd_error_handler() before the asynchronous timeout_work for the
> deferred QCs runs, ata_scsi_cmd_error_handler() will miss the deferred QCs
> since they aren't in eh_work_q yet:

Somehow, this patch seems to be working, but yet, in view of this comment, I do
not see how the host busy counter is decremented for the deferred QCs. Something
is missing. We somehow need to call scsi_complete() with a status that leads to
the command disposition to fall to the default scsi_eh_scmd_add() so that we do
not immediately retry the command, since that also does not work (previous
version issue).

Spending the weekend on this was a waste of time. Back to the drawing board on this.

-- 
Damien Le Moal
Western Digital Research

  reply	other threads:[~2026-07-20  9:33 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-20  7:14 [PATCH v6 0/2] fixup handling of timeouts with deferred QCs Damien Le Moal
2026-07-20  7:14 ` [PATCH v6 1/2] ata: libata-scsi: terminate deferred commands on time out Damien Le Moal
2026-07-20  7:31   ` sashiko-bot
2026-07-20  9:33     ` Damien Le Moal [this message]
2026-07-20  7:14 ` [PATCH v6 2/2] scsi: libsas: " Damien Le Moal
2026-07-20  7:36   ` sashiko-bot

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=8a4b58ca-c172-429d-8de3-34f92f5d2264@kernel.org \
    --to=dlemoal@kernel.org \
    --cc=cassel@kernel.org \
    --cc=linux-ide@vger.kernel.org \
    --cc=linux-scsi@vger.kernel.org \
    --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.