diff options
author | Mike Christie <michael.christie@oracle.com> | 2024-01-22 18:22:16 -0600 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2024-01-29 21:20:54 -0500 |
commit | 0f11328f2f46618c8c4734041fdb2aacfa99b802 (patch) | |
tree | a94c2d8e7a0370face1ede3925220b1519cfa630 /drivers/scsi/sd.c | |
parent | eea6ef3792e34bd9476bef2fad074a8ce24915ec (diff) |
scsi: sd: Have midlayer retry read_capacity_10() errors
This has read_capacity_10() have the SCSI midlayer retry errors instead of
driving them itself.
There are 2 behavior changes with this patch:
1. There is one behavior change where we no longer retry when
scsi_execute_cmd() returns < 0, but we should be ok. We don't need to
retry for failures like the queue being removed, and for the case where
there are no tags/reqs since the block layer waits/retries for us. For
possible memory allocation failures from blk_rq_map_kern() we use
GFP_NOIO, so retrying will probably not help.
2. For the specific UAs we checked for and retried, we would get
READ_CAPACITY_RETRIES_ON_RESET retries plus whatever retries were left
from the main loop's retries. Each UA now gets
READ_CAPACITY_RETRIES_ON_RESET retries, and the other errors get up to
3 retries. This is most likely ok, because
READ_CAPACITY_RETRIES_ON_RESET is already 10 and is not based on
anything specific like a spec or device, so the extra 3 we got from the
main loop was probably just an accident and is not going to help.
Signed-off-by: Mike Christie <michael.christie@oracle.com>
Link: https://lore.kernel.org/r/20240123002220.129141-16-michael.christie@oracle.com
Acked-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/sd.c')
-rw-r--r-- | drivers/scsi/sd.c | 62 |
1 files changed, 39 insertions, 23 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 4196f722c3f6..49159dcd638d 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -2588,42 +2588,58 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp, static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp, unsigned char *buffer) { - unsigned char cmd[16]; + static const u8 cmd[10] = { READ_CAPACITY }; struct scsi_sense_hdr sshdr; + struct scsi_failure failure_defs[] = { + /* Do not retry Medium Not Present */ + { + .sense = UNIT_ATTENTION, + .asc = 0x3A, + .result = SAM_STAT_CHECK_CONDITION, + }, + { + .sense = NOT_READY, + .asc = 0x3A, + .result = SAM_STAT_CHECK_CONDITION, + }, + /* Device reset might occur several times so retry a lot */ + { + .sense = UNIT_ATTENTION, + .asc = 0x29, + .allowed = READ_CAPACITY_RETRIES_ON_RESET, + .result = SAM_STAT_CHECK_CONDITION, + }, + /* Any other error not listed above retry 3 times */ + { + .result = SCMD_FAILURE_RESULT_ANY, + .allowed = 3, + }, + {} + }; + struct scsi_failures failures = { + .failure_definitions = failure_defs, + }; const struct scsi_exec_args exec_args = { .sshdr = &sshdr, + .failures = &failures, }; int sense_valid = 0; int the_result; - int retries = 3, reset_retries = READ_CAPACITY_RETRIES_ON_RESET; sector_t lba; unsigned sector_size; - do { - cmd[0] = READ_CAPACITY; - memset(&cmd[1], 0, 9); - memset(buffer, 0, 8); + memset(buffer, 0, 8); - the_result = scsi_execute_cmd(sdp, cmd, REQ_OP_DRV_IN, buffer, - 8, SD_TIMEOUT, sdkp->max_retries, - &exec_args); + the_result = scsi_execute_cmd(sdp, cmd, REQ_OP_DRV_IN, buffer, + 8, SD_TIMEOUT, sdkp->max_retries, + &exec_args); + + if (the_result > 0) { + sense_valid = scsi_sense_valid(&sshdr); if (media_not_present(sdkp, &sshdr)) return -ENODEV; - - if (the_result > 0) { - sense_valid = scsi_sense_valid(&sshdr); - if (sense_valid && - sshdr.sense_key == UNIT_ATTENTION && - sshdr.asc == 0x29 && sshdr.ascq == 0x00) - /* Device reset might occur several times, - * give it one more chance */ - if (--reset_retries > 0) - continue; - } - retries--; - - } while (the_result && retries); + } if (the_result) { sd_print_result(sdkp, "Read Capacity(10) failed", the_result); |