This converts the SCSI errors we commonly see during PR handling to PT_STS errors, so pr_ops callers can handle scsi and nvme errors without knowing the device types. Signed-off-by: Mike Christie <michael.christie@xxxxxxxxxx> --- drivers/scsi/sd.c | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index eb76ba055021..667477d1e4b7 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1701,6 +1701,44 @@ static char sd_pr_type(enum pr_type type) } }; +static enum pr_status sd_scsi_to_block_pr_err(struct scsi_sense_hdr *sshdr, + int result) +{ + enum pr_status sts = PR_STS_IOERR; + + switch host_byte(result) { + case DID_TRANSPORT_MARGINAL: + case DID_TRANSPORT_DISRUPTED: + case DID_BUS_BUSY: + sts = PR_STS_RETRY_PATH_FAILURE; + goto done; + case DID_NO_CONNECT: + sts = PR_STS_PATH_FAILED; + goto done; + case DID_TRANSPORT_FAILFAST: + sts = PR_STS_PATH_FAST_FAILED; + goto done; + } + + switch (__get_status_byte(result)) { + case SAM_STAT_RESERVATION_CONFLICT: + sts = PR_STS_RESERVATION_CONFLICT; + goto done; + case SAM_STAT_CHECK_CONDITION: + if (!scsi_sense_valid(sshdr)) + goto done; + + if (sshdr->sense_key == ILLEGAL_REQUEST && + (sshdr->asc == 0x26 || sshdr->asc == 0x24)) { + sts = PR_STS_OP_INVALID; + goto done; + } + } + +done: + return sts; +} + static int sd_pr_command(struct block_device *bdev, u8 sa, u64 key, u64 sa_key, u8 type, u8 flags) { @@ -1729,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_block_pr_err(&sshdr, result); } static int sd_pr_register(struct block_device *bdev, u64 old_key, u64 new_key, -- 2.25.1