]> www.infradead.org Git - users/willy/xarray.git/commitdiff
scsi: sd: Have midlayer retry read_capacity_10() errors
authorMike Christie <michael.christie@oracle.com>
Tue, 23 Jan 2024 00:22:16 +0000 (18:22 -0600)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 30 Jan 2024 02:20:54 +0000 (21:20 -0500)
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>
drivers/scsi/sd.c

index 4196f722c3f6e3acd76c7f5b4cee25e1e3ba290d..49159dcd638d7c5fb70ae8e72c3f8330e03c9343 100644 (file)
@@ -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);