From 255c4f4a6d5b60cfcd218d8fdae517b886ff155a Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Mon, 21 Nov 2022 21:26:00 -0600 Subject: block: Add error codes for common PR failures If a PR operation fails we can return a device-specific error which is impossible to handle in some cases because we could have a mix of devices when DM is used, or future users like LIO only knows it's interacting with a block device so it doesn't know the type. This patch adds a new pr_status enum so drivers can convert errors to a common type which can be handled by the caller. Signed-off-by: Mike Christie Link: https://lore.kernel.org/r/20221122032603.32766-2-michael.christie@oracle.com Reviewed-by: Christoph Hellwig Reviewed-by: Chaitanya Kulkarni Signed-off-by: Martin K. Petersen --- include/uapi/linux/pr.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'include') diff --git a/include/uapi/linux/pr.h b/include/uapi/linux/pr.h index ccc78cbf1221..d8126415966f 100644 --- a/include/uapi/linux/pr.h +++ b/include/uapi/linux/pr.h @@ -4,6 +4,23 @@ #include +enum pr_status { + PR_STS_SUCCESS = 0x0, + /* + * The following error codes are based on SCSI, because the interface + * was originally created for it and has existing users. + */ + /* Generic device failure. */ + PR_STS_IOERR = 0x2, + PR_STS_RESERVATION_CONFLICT = 0x18, + /* Temporary path failure that can be retried. */ + PR_STS_RETRY_PATH_FAILURE = 0xe0000, + /* The request was failed due to a fast failure timer. */ + PR_STS_PATH_FAST_FAILED = 0xf0000, + /* The path cannot be reached and has been marked as failed. */ + PR_STS_PATH_FAILED = 0x10000, +}; + enum pr_type { PR_WRITE_EXCLUSIVE = 1, PR_EXCLUSIVE_ACCESS = 2, -- cgit v1.2.3-70-g09d2 From c9293c1199ecd3cfa07931ec3630f37dba1ca1b8 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Mon, 21 Nov 2022 21:26:01 -0600 Subject: scsi: core: Rename status_byte to sg_status_byte The next patch adds a helper status_byte function that works like host_byte, so this patch renames the old status_byte to sg_status_byte since it's only used for SG IO. Signed-off-by: Mike Christie Link: https://lore.kernel.org/r/20221122032603.32766-3-michael.christie@oracle.com Reviewed-by: Chaitanya Kulkarni Reviewed-by: Christoph Hellwig Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_ioctl.c | 2 +- drivers/scsi/sg.c | 2 +- include/scsi/sg.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index fdd47565a311..1126a265d5ee 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c @@ -376,7 +376,7 @@ static int scsi_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr, * fill in all the output members */ hdr->status = scmd->result & 0xff; - hdr->masked_status = status_byte(scmd->result); + hdr->masked_status = sg_status_byte(scmd->result); hdr->msg_status = COMMAND_COMPLETE; hdr->host_status = host_byte(scmd->result); hdr->driver_status = 0; diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index ce34a8ad53b4..d61d8d0d1658 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1349,7 +1349,7 @@ sg_rq_end_io(struct request *rq, blk_status_t status) struct scsi_sense_hdr sshdr; srp->header.status = 0xff & result; - srp->header.masked_status = status_byte(result); + srp->header.masked_status = sg_status_byte(result); srp->header.msg_status = COMMAND_COMPLETE; srp->header.host_status = host_byte(result); srp->header.driver_status = driver_byte(result); diff --git a/include/scsi/sg.h b/include/scsi/sg.h index 068e35d36557..af31cecd9012 100644 --- a/include/scsi/sg.h +++ b/include/scsi/sg.h @@ -159,7 +159,7 @@ struct compat_sg_io_hdr { #define TASK_ABORTED 0x20 /* Obsolete status_byte() declaration */ -#define status_byte(result) (((result) >> 1) & 0x7f) +#define sg_status_byte(result) (((result) >> 1) & 0x7f) typedef struct sg_scsi_id { /* used by SG_GET_SCSI_ID ioctl() */ int host_no; /* as in "scsi" where 'n' is one of 0, 1, 2 etc */ -- cgit v1.2.3-70-g09d2 From 04b3c8c0025a1d91a0e133e9b2734a002960f472 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Mon, 21 Nov 2022 21:26:02 -0600 Subject: scsi: sd: Convert SCSI errors to PR errors This converts the SCSI errors we commonly see during PR handling to PR_STS errors or -Exyz errors. pr_ops callers can then handle SCSI and NVMe errors without knowing the device types. Signed-off-by: Mike Christie Link: https://lore.kernel.org/r/20221122032603.32766-4-michael.christie@oracle.com Reviewed-by: Christoph Hellwig Reviewed-by: Chaitanya Kulkarni Signed-off-by: Martin K. Petersen --- drivers/scsi/sd.c | 35 ++++++++++++++++++++++++++++++++++- include/scsi/scsi.h | 1 + 2 files changed, 35 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index faa2b55d1a21..47dafe6b8a66 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1709,6 +1709,36 @@ static char sd_pr_type(enum pr_type type) } }; +static int sd_scsi_to_pr_err(struct scsi_sense_hdr *sshdr, int result) +{ + switch (host_byte(result)) { + case DID_TRANSPORT_MARGINAL: + case DID_TRANSPORT_DISRUPTED: + case DID_BUS_BUSY: + return PR_STS_RETRY_PATH_FAILURE; + case DID_NO_CONNECT: + return PR_STS_PATH_FAILED; + case DID_TRANSPORT_FAILFAST: + return PR_STS_PATH_FAST_FAILED; + } + + switch (status_byte(result)) { + case SAM_STAT_RESERVATION_CONFLICT: + return PR_STS_RESERVATION_CONFLICT; + case SAM_STAT_CHECK_CONDITION: + if (!scsi_sense_valid(sshdr)) + return PR_STS_IOERR; + + if (sshdr->sense_key == ILLEGAL_REQUEST && + (sshdr->asc == 0x26 || sshdr->asc == 0x24)) + return -EINVAL; + + fallthrough; + default: + return PR_STS_IOERR; + } +} + static int sd_pr_command(struct block_device *bdev, u8 sa, u64 key, u64 sa_key, u8 type, u8 flags) { @@ -1737,7 +1767,10 @@ static int sd_pr_command(struct block_device *bdev, u8 sa, scsi_print_sense_hdr(sdev, NULL, &sshdr); } - return result; + if (result <= 0) + return result; + + return sd_scsi_to_pr_err(&sshdr, result); } static int sd_pr_register(struct block_device *bdev, u64 old_key, u64 new_key, diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index 3e46859774c8..ec093594ba53 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -121,6 +121,7 @@ enum scsi_disposition { * msg_byte (unused) * host_byte = set by low-level driver to indicate status. */ +#define status_byte(result) (result & 0xff) #define host_byte(result) (((result) >> 16) & 0xff) #define sense_class(sense) (((sense) >> 4) & 0x7) -- cgit v1.2.3-70-g09d2