mbox series

[v4,00/10] Fix a deadlock in the UFS driver

Message ID 20221018202958.1902564-1-bvanassche@acm.org
Headers show
Series Fix a deadlock in the UFS driver | expand

Message

Bart Van Assche Oct. 18, 2022, 8:29 p.m. UTC
Hi Martin,

This patch series fixes a deadlock in the UFS driver between the suspend/resume
code and the SCSI error handler. Please consider this patch series for the next
merge window.

Thanks,

Bart.

Changes compared to v3:
* Added two patches: one patch to reduce the START STOP UNIT timeout and another
  patch that introduces the ufshcd_execute_start_stop() function.
* Modified patch 3 such that it introduces a new flag (SCMD_FAIL_IF_RECOVERING)
  instead of modifying the behavior for the REQ_FAILFAST flags.

Changes compared to v2:
* Replaced the custom error handling code in ufshcd_eh_timed_out() with a call
  to ufshcd_link_recovery().

Changes compared to v1:
* Added support in the SCSI core for failing SCSI commands quickly during host
  recovery.
* Removed the patch that splits the ufshcd_err_handler() function.
* Fixed the code in ufshcd_eh_timed_out() for handling command timeouts.
* Removed the power management notifier again.

Bart Van Assche (10):
  scsi: core: Fix a race between scsi_done() and scsi_timeout()
  scsi: core: Change the return type of .eh_timed_out()
  scsi: core: Support failing requests while recovering
  scsi: ufs: Remove an outdated comment
  scsi: ufs: Use 'else' in ufshcd_set_dev_pwr_mode()
  scsi: ufs: Reduce the START STOP UNIT timeout
  scsi: ufs: Try harder to change the power mode
  scsi: ufs: Track system suspend / resume activity
  scsi: ufs: Introduce the function ufshcd_execute_start_stop()
  scsi: ufs: Fix a deadlock between PM and the SCSI error handler

 Documentation/scsi/scsi_eh.rst            |  7 +-
 drivers/message/fusion/mptsas.c           |  8 +--
 drivers/scsi/libiscsi.c                   | 26 +++----
 drivers/scsi/megaraid/megaraid_sas_base.c |  7 +-
 drivers/scsi/mvumi.c                      |  4 +-
 drivers/scsi/qla4xxx/ql4_os.c             |  8 +--
 drivers/scsi/scsi_error.c                 | 41 +++++------
 drivers/scsi/scsi_lib.c                   |  8 ++-
 drivers/scsi/scsi_transport_fc.c          |  7 +-
 drivers/scsi/scsi_transport_srp.c         |  8 +--
 drivers/scsi/storvsc_drv.c                |  4 +-
 drivers/scsi/virtio_scsi.c                |  4 +-
 drivers/ufs/core/ufshcd.c                 | 86 ++++++++++++++++++-----
 include/scsi/libiscsi.h                   |  2 +-
 include/scsi/scsi_cmnd.h                  |  3 +-
 include/scsi/scsi_host.h                  | 14 +++-
 include/scsi/scsi_transport_fc.h          |  2 +-
 include/scsi/scsi_transport_srp.h         |  2 +-
 include/ufs/ufshcd.h                      |  5 +-
 19 files changed, 155 insertions(+), 91 deletions(-)

Comments

Bart Van Assche Oct. 19, 2022, 9:13 p.m. UTC | #1
On 10/19/22 12:57, Mike Christie wrote:
> On 10/18/22 3:29 PM, Bart Van Assche wrote:
>> Open-code scsi_execute() because a later patch will modify scmd->flags
>> and because scsi_execute() does not support setting scmd->flags. No
>> functionality is changed.
>>
>> Signed-off-by: Bart Van Assche <bvanassche@acm.org>
>> ---
>>   drivers/ufs/core/ufshcd.c | 39 ++++++++++++++++++++++++++++++++++-----
>>   1 file changed, 34 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
>> index 2a32bcc93d2e..c5ccc7ba583b 100644
>> --- a/drivers/ufs/core/ufshcd.c
>> +++ b/drivers/ufs/core/ufshcd.c
>> @@ -8729,6 +8729,39 @@ static void ufshcd_hba_exit(struct ufs_hba *hba)
>>   	}
>>   }
>>   
>> +static int ufshcd_execute_start_stop(struct scsi_device *sdev,
>> +				     enum ufs_dev_pwr_mode pwr_mode,
>> +				     struct scsi_sense_hdr *sshdr)
>> +{
>> +	unsigned char cdb[6] = { START_STOP, 0, 0, 0, pwr_mode << 4, 0 };
>> +	struct request *req;
>> +	struct scsi_cmnd *scmd;
>> +	int ret;
>> +
>> +	req = scsi_alloc_request(sdev->request_queue, REQ_OP_DRV_IN,
>> +				 BLK_MQ_REQ_PM);
>>
> 
> Can you hit a case where we have run out of tags (__blk_mq_alloc_requests
> is hitting the blk_mq_get_tag == BLK_MQ_NO_TAG check), the host has gone
> into recovery and so commands are completing to add a tag back and then we
> try to call this and get stuck waiting on a tag? Or for passthrough do we
> have some special reserve?
> 
> If so do you need to use BLK_MQ_REQ_NOWAIT here? Maybe do the retry loop
> yourself like:
> 
> retry:
> 	if host is in recovery
> 		return failure
> 
> 	req = scsi_alloc_request(.... BLK_MQ_REQ_NOWAIT)
> 	if (!req and we have not hit some retry limit)
> 		goto retry
> 
> 
> or have some special reserve command/tag.

Hi Mike,

No other SCSI commands should be in progress when 
ufshcd_execute_start_stop() is called because that function is only 
called during system suspend and resume and no other I/O should be in 
progress at that time. Additionally, there is a mutual exclusion 
mechanism in the UFS driver to serialize system suspend/resume activity 
and error handling.

Thanks,

Bart.
Mike Christie Oct. 20, 2022, 5:21 p.m. UTC | #2
On 10/19/22 4:13 PM, Bart Van Assche wrote:
> On 10/19/22 12:57, Mike Christie wrote:
>> On 10/18/22 3:29 PM, Bart Van Assche wrote:
>>> Open-code scsi_execute() because a later patch will modify scmd->flags
>>> and because scsi_execute() does not support setting scmd->flags. No
>>> functionality is changed.
>>>
>>> Signed-off-by: Bart Van Assche <bvanassche@acm.org>
>>> ---
>>>   drivers/ufs/core/ufshcd.c | 39 ++++++++++++++++++++++++++++++++++-----
>>>   1 file changed, 34 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
>>> index 2a32bcc93d2e..c5ccc7ba583b 100644
>>> --- a/drivers/ufs/core/ufshcd.c
>>> +++ b/drivers/ufs/core/ufshcd.c
>>> @@ -8729,6 +8729,39 @@ static void ufshcd_hba_exit(struct ufs_hba *hba)
>>>       }
>>>   }
>>>   +static int ufshcd_execute_start_stop(struct scsi_device *sdev,
>>> +                     enum ufs_dev_pwr_mode pwr_mode,
>>> +                     struct scsi_sense_hdr *sshdr)
>>> +{
>>> +    unsigned char cdb[6] = { START_STOP, 0, 0, 0, pwr_mode << 4, 0 };
>>> +    struct request *req;
>>> +    struct scsi_cmnd *scmd;
>>> +    int ret;
>>> +
>>> +    req = scsi_alloc_request(sdev->request_queue, REQ_OP_DRV_IN,
>>> +                 BLK_MQ_REQ_PM);
>>>
>>
>> Can you hit a case where we have run out of tags (__blk_mq_alloc_requests
>> is hitting the blk_mq_get_tag == BLK_MQ_NO_TAG check), the host has gone
>> into recovery and so commands are completing to add a tag back and then we
>> try to call this and get stuck waiting on a tag? Or for passthrough do we
>> have some special reserve?
>>
>> If so do you need to use BLK_MQ_REQ_NOWAIT here? Maybe do the retry loop
>> yourself like:
>>
>> retry:
>>     if host is in recovery
>>         return failure
>>
>>     req = scsi_alloc_request(.... BLK_MQ_REQ_NOWAIT)
>>     if (!req and we have not hit some retry limit)
>>         goto retry
>>
>>
>> or have some special reserve command/tag.
> 
> Hi Mike,
> 
> No other SCSI commands should be in progress when ufshcd_execute_start_stop() is called because that function is only called during system suspend and resume and no other I/O should be in progress at that time. Additionally, there is a mutual exclusion mechanism in the UFS driver to serialize system suspend/resume activity and error handling.

Looks ok to me then.

Reviewed-by: Mike Christie <michael.christie@oracle.com>
Martin K. Petersen Oct. 22, 2022, 3:27 a.m. UTC | #3
Bart,

> This patch series fixes a deadlock in the UFS driver between the
> suspend/resume code and the SCSI error handler. Please consider this
> patch series for the next merge window.

Applied to 6.2/scsi-staging, thanks!
Avri Altman Oct. 23, 2022, 6:16 a.m. UTC | #4
Martin Hi, 
> Bart,
> 
> > This patch series fixes a deadlock in the UFS driver between the
> > suspend/resume code and the SCSI error handler. Please consider this
> > patch series for the next merge window.
> 
> Applied to 6.2/scsi-staging, thanks!
Patch #6: dcd5b7637c6d (scsi: ufs: Reduce the START STOP UNIT timeout) wasn't acked by any device manufacturer.
This timeout is now reduced from 10 seconds to 3 seconds, after it was reduced from 3x60 on August.
Please allow few more days to verify it internally.

Thanks,
Avri

> 
> --
> Martin K. Petersen      Oracle Linux Engineering
Bart Van Assche Oct. 24, 2022, 11:27 p.m. UTC | #5
On 10/22/22 23:16, Avri Altman wrote:
> Patch #6: dcd5b7637c6d (scsi: ufs: Reduce the START STOP UNIT
> timeout) wasn't acked by any device manufacturer. This timeout is now
> reduced from 10 seconds to 3 seconds, after it was reduced from 3x60
> on August. Please allow few more days to verify it internally.

Thanks Avri for the additional testing. If the timeout value would have 
to be modified I think that can be done easily with a follow-up patch.

Bart.
Martin K. Petersen Oct. 27, 2022, 2:58 a.m. UTC | #6
On Tue, 18 Oct 2022 13:29:48 -0700, Bart Van Assche wrote:

> This patch series fixes a deadlock in the UFS driver between the suspend/resume
> code and the SCSI error handler. Please consider this patch series for the next
> merge window.
> 
> Thanks,
> 
> Bart.
> 
> [...]

Applied to 6.2/scsi-queue, thanks!

[01/10] scsi: core: Fix a race between scsi_done() and scsi_timeout()
        https://git.kernel.org/mkp/scsi/c/978b7922d3dc
[02/10] scsi: core: Change the return type of .eh_timed_out()
        https://git.kernel.org/mkp/scsi/c/dee7121e8c0a
[03/10] scsi: core: Support failing requests while recovering
        https://git.kernel.org/mkp/scsi/c/310bcaef6d7e
[04/10] scsi: ufs: Remove an outdated comment
        https://git.kernel.org/mkp/scsi/c/1626c7bba1c4
[05/10] scsi: ufs: Use 'else' in ufshcd_set_dev_pwr_mode()
        https://git.kernel.org/mkp/scsi/c/836d322d73cb
[06/10] scsi: ufs: Reduce the START STOP UNIT timeout
        https://git.kernel.org/mkp/scsi/c/dcd5b7637c6d
[07/10] scsi: ufs: Try harder to change the power mode
        https://git.kernel.org/mkp/scsi/c/579a4e9dbd53
[08/10] scsi: ufs: Track system suspend / resume activity
        https://git.kernel.org/mkp/scsi/c/1a547cbc6fdd
[09/10] scsi: ufs: Introduce the function ufshcd_execute_start_stop()
        https://git.kernel.org/mkp/scsi/c/6a354a7e740e
[10/10] scsi: ufs: Fix a deadlock between PM and the SCSI error handler
        https://git.kernel.org/mkp/scsi/c/7029e2151a7c