scsi: sd: Have midlayer retry sd_sync_cache() errors
authorMike Christie <michael.christie@oracle.com>
Tue, 23 Jan 2024 00:22:10 +0000 (18:22 -0600)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 30 Jan 2024 02:20:53 +0000 (21:20 -0500)
This has sd_sync_cache() have the SCSI midlayer retry errors instead of
driving them itself.

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 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.

Signed-off-by: Mike Christie <michael.christie@oracle.com>
Link: https://lore.kernel.org/r/20240123002220.129141-10-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 cb240015bde5cce8f2e20358aee8fb73b56b0956..c2068d83c812a32736cb89715e8e7501ca07fe92 100644 (file)
@@ -1645,36 +1645,35 @@ out:
 
 static int sd_sync_cache(struct scsi_disk *sdkp)
 {
-       int retries, res;
+       int res;
        struct scsi_device *sdp = sdkp->device;
        const int timeout = sdp->request_queue->rq_timeout
                * SD_FLUSH_TIMEOUT_MULTIPLIER;
+       /* Leave the rest of the command zero to indicate flush everything. */
+       const unsigned char cmd[16] = { sdp->use_16_for_sync ?
+                               SYNCHRONIZE_CACHE_16 : SYNCHRONIZE_CACHE };
        struct scsi_sense_hdr sshdr;
+       struct scsi_failure failure_defs[] = {
+               {
+                       .allowed = 3,
+                       .result = SCMD_FAILURE_RESULT_ANY,
+               },
+               {}
+       };
+       struct scsi_failures failures = {
+               .failure_definitions = failure_defs,
+       };
        const struct scsi_exec_args exec_args = {
                .req_flags = BLK_MQ_REQ_PM,
                .sshdr = &sshdr,
+               .failures = &failures,
        };
 
        if (!scsi_device_online(sdp))
                return -ENODEV;
 
-       for (retries = 3; retries > 0; --retries) {
-               unsigned char cmd[16] = { 0 };
-
-               if (sdp->use_16_for_sync)
-                       cmd[0] = SYNCHRONIZE_CACHE_16;
-               else
-                       cmd[0] = SYNCHRONIZE_CACHE;
-               /*
-                * Leave the rest of the command zero to indicate
-                * flush everything.
-                */
-               res = scsi_execute_cmd(sdp, cmd, REQ_OP_DRV_IN, NULL, 0,
-                                      timeout, sdkp->max_retries, &exec_args);
-               if (res == 0)
-                       break;
-       }
-
+       res = scsi_execute_cmd(sdp, cmd, REQ_OP_DRV_IN, NULL, 0, timeout,
+                              sdkp->max_retries, &exec_args);
        if (res) {
                sd_print_result(sdkp, "Synchronize Cache(10) failed", res);