From 2dffc600ca38d7eee8e595ecd9bd6a55d0977561 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 13 Jan 2023 13:55:50 -0800 Subject: [PATCH] ANDROID: scsi: core: Delay unaligned write error retries Host-managed zoned block devices report the sense code 21h/04h (UNALIGNED WRITE COMMAND) when attempting to write data at another LBA than the write pointer. Retry unaligned writes after all other pending commands have completed instead of retrying these immediately. The change in this patch makes the following function decide to queue the failed command to the error handler instead of retrying it immediately: static void scsi_complete(struct request *rq) { [ ... ] switch (disposition) { case SUCCESS: scsi_finish_command(cmd); break; case NEEDS_RETRY: scsi_queue_insert(cmd, SCSI_MLQUEUE_EH_RETRY); break; case ADD_TO_MLQUEUE: scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY); break; default: scsi_eh_scmd_add(cmd); break; } } This patch has not been posted on any Linux kernel mailing list since there is agreement that another approach will be taken to preserve the order of WRITE commands for zoned devices. However, the implementation of that new approach is not yet available. Bug: 197782466 Change-Id: I3529ce4f01ff166a0c8ac321eb31b0e7771906ac Signed-off-by: Bart Van Assche --- drivers/scsi/scsi_error.c | 6 +++--- include/scsi/scsi.h | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index c8fc8487e910..e45f8652867c 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -672,11 +672,11 @@ enum scsi_disposition scsi_check_sense(struct scsi_cmnd *scmd) case ILLEGAL_REQUEST: /* - * Unaligned write command. Retry immediately to handle - * out-of-order zoned writes. + * Unaligned write command. This indicates that zoned writes got + * reordered. Retry after all pending commands have completed. */ if (sshdr.asc == 0x21 && sshdr.ascq == 0x04) - return NEEDS_RETRY; + return NEEDS_DELAYED_RETRY; if (sshdr.asc == 0x20 || /* Invalid command operation code */ sshdr.asc == 0x21 || /* Logical block address out of range */ sshdr.asc == 0x22 || /* Invalid function */ diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index 3e46859774c8..dc67020aa557 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -93,6 +93,7 @@ static inline int scsi_status_is_check_condition(int status) * Internal return values. */ enum scsi_disposition { + NEEDS_DELAYED_RETRY = 0x2000, NEEDS_RETRY = 0x2001, SUCCESS = 0x2002, FAILED = 0x2003,