Commit ced202f7 authored by Hannes Reinecke's avatar Hannes Reinecke Committed by Martin K. Petersen

scsi: core: Stop using DRIVER_ERROR

Return the actual error code in __scsi_execute() (which, according to the
documentation, should have happened anyway).  And audit all callers to cope
with negative return values from __scsi_execute() and friends.

[mkp: resolve conflict and return bool]

Link: https://lore.kernel.org/r/20210427083046.31620-7-hare@suse.deReviewed-by: default avatarBart Van Assche <bvanassche@acm.org>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarHannes Reinecke <hare@suse.de>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 7e26e3ea
...@@ -409,6 +409,10 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg) ...@@ -409,6 +409,10 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
cmd_result = scsi_execute(scsidev, scsi_cmd, data_dir, argbuf, argsize, cmd_result = scsi_execute(scsidev, scsi_cmd, data_dir, argbuf, argsize,
sensebuf, &sshdr, (10*HZ), 5, 0, 0, NULL); sensebuf, &sshdr, (10*HZ), 5, 0, 0, NULL);
if (cmd_result < 0) {
rc = cmd_result;
goto error;
}
if (driver_byte(cmd_result) == DRIVER_SENSE) {/* sense data available */ if (driver_byte(cmd_result) == DRIVER_SENSE) {/* sense data available */
u8 *desc = sensebuf + 8; u8 *desc = sensebuf + 8;
cmd_result &= ~(0xFF<<24); /* DRIVER_SENSE is not an error */ cmd_result &= ~(0xFF<<24); /* DRIVER_SENSE is not an error */
...@@ -490,6 +494,10 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg) ...@@ -490,6 +494,10 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
cmd_result = scsi_execute(scsidev, scsi_cmd, DMA_NONE, NULL, 0, cmd_result = scsi_execute(scsidev, scsi_cmd, DMA_NONE, NULL, 0,
sensebuf, &sshdr, (10*HZ), 5, 0, 0, NULL); sensebuf, &sshdr, (10*HZ), 5, 0, 0, NULL);
if (cmd_result < 0) {
rc = cmd_result;
goto error;
}
if (driver_byte(cmd_result) == DRIVER_SENSE) {/* sense data available */ if (driver_byte(cmd_result) == DRIVER_SENSE) {/* sense data available */
u8 *desc = sensebuf + 8; u8 *desc = sensebuf + 8;
cmd_result &= ~(0xFF<<24); /* DRIVER_SENSE is not an error */ cmd_result &= ~(0xFF<<24); /* DRIVER_SENSE is not an error */
......
...@@ -198,7 +198,8 @@ ch_do_scsi(scsi_changer *ch, unsigned char *cmd, int cmd_len, ...@@ -198,7 +198,8 @@ ch_do_scsi(scsi_changer *ch, unsigned char *cmd, int cmd_len,
result = scsi_execute_req(ch->device, cmd, direction, buffer, result = scsi_execute_req(ch->device, cmd, direction, buffer,
buflength, &sshdr, timeout * HZ, buflength, &sshdr, timeout * HZ,
MAX_RETRIES, NULL); MAX_RETRIES, NULL);
if (result < 0)
return result;
if (driver_byte(result) == DRIVER_SENSE) { if (driver_byte(result) == DRIVER_SENSE) {
if (debug) if (debug)
scsi_print_sense_hdr(ch->device, ch->name, &sshdr); scsi_print_sense_hdr(ch->device, ch->name, &sshdr);
......
...@@ -369,7 +369,7 @@ static int read_cap16(struct scsi_device *sdev, struct llun_info *lli) ...@@ -369,7 +369,7 @@ static int read_cap16(struct scsi_device *sdev, struct llun_info *lli)
goto out; goto out;
} }
if (driver_byte(result) == DRIVER_SENSE) { if (result > 0 && driver_byte(result) == DRIVER_SENSE) {
result &= ~(0xFF<<24); /* DRIVER_SENSE is not an error */ result &= ~(0xFF<<24); /* DRIVER_SENSE is not an error */
if (result & SAM_STAT_CHECK_CONDITION) { if (result & SAM_STAT_CHECK_CONDITION) {
switch (sshdr.sense_key) { switch (sshdr.sense_key) {
......
...@@ -508,6 +508,8 @@ int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer, ...@@ -508,6 +508,8 @@ int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer,
result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer, len, result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer, len,
&sshdr, 30 * HZ, 3, NULL); &sshdr, 30 * HZ, 3, NULL);
if (result < 0)
return result;
if (result && scsi_sense_valid(&sshdr) && if (result && scsi_sense_valid(&sshdr) &&
sshdr.sense_key == ILLEGAL_REQUEST && sshdr.sense_key == ILLEGAL_REQUEST &&
(sshdr.asc == 0x20 || sshdr.asc == 0x24) && sshdr.ascq == 0x00) (sshdr.asc == 0x20 || sshdr.asc == 0x24) && sshdr.ascq == 0x00)
......
...@@ -101,6 +101,8 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, ...@@ -101,6 +101,8 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd,
SCSI_LOG_IOCTL(2, sdev_printk(KERN_INFO, sdev, SCSI_LOG_IOCTL(2, sdev_printk(KERN_INFO, sdev,
"Ioctl returned 0x%x\n", result)); "Ioctl returned 0x%x\n", result));
if (result < 0)
goto out;
if (driver_byte(result) == DRIVER_SENSE && if (driver_byte(result) == DRIVER_SENSE &&
scsi_sense_valid(&sshdr)) { scsi_sense_valid(&sshdr)) {
switch (sshdr.sense_key) { switch (sshdr.sense_key) {
...@@ -133,7 +135,7 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, ...@@ -133,7 +135,7 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd,
break; break;
} }
} }
out:
SCSI_LOG_IOCTL(2, sdev_printk(KERN_INFO, sdev, SCSI_LOG_IOCTL(2, sdev_printk(KERN_INFO, sdev,
"IOCTL Releasing command\n")); "IOCTL Releasing command\n"));
return result; return result;
......
...@@ -211,20 +211,23 @@ int __scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, ...@@ -211,20 +211,23 @@ int __scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
{ {
struct request *req; struct request *req;
struct scsi_request *rq; struct scsi_request *rq;
int ret = DRIVER_ERROR << 24; int ret;
req = blk_get_request(sdev->request_queue, req = blk_get_request(sdev->request_queue,
data_direction == DMA_TO_DEVICE ? data_direction == DMA_TO_DEVICE ?
REQ_OP_SCSI_OUT : REQ_OP_SCSI_IN, REQ_OP_SCSI_OUT : REQ_OP_SCSI_IN,
rq_flags & RQF_PM ? BLK_MQ_REQ_PM : 0); rq_flags & RQF_PM ? BLK_MQ_REQ_PM : 0);
if (IS_ERR(req)) if (IS_ERR(req))
return ret; return PTR_ERR(req);
rq = scsi_req(req);
if (bufflen && blk_rq_map_kern(sdev->request_queue, req, rq = scsi_req(req);
buffer, bufflen, GFP_NOIO))
goto out;
if (bufflen) {
ret = blk_rq_map_kern(sdev->request_queue, req,
buffer, bufflen, GFP_NOIO);
if (ret)
goto out;
}
rq->cmd_len = COMMAND_SIZE(cmd[0]); rq->cmd_len = COMMAND_SIZE(cmd[0]);
memcpy(rq->cmd, cmd, rq->cmd_len); memcpy(rq->cmd, cmd, rq->cmd_len);
rq->retries = retries; rq->retries = retries;
......
...@@ -616,7 +616,7 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result, ...@@ -616,7 +616,7 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result,
"scsi scan: INQUIRY %s with code 0x%x\n", "scsi scan: INQUIRY %s with code 0x%x\n",
result ? "failed" : "successful", result)); result ? "failed" : "successful", result));
if (result) { if (result > 0) {
/* /*
* not-ready to ready transition [asc/ascq=0x28/0x0] * not-ready to ready transition [asc/ascq=0x28/0x0]
* or power-on, reset [asc/ascq=0x29/0x0], continue. * or power-on, reset [asc/ascq=0x29/0x0], continue.
...@@ -631,7 +631,7 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result, ...@@ -631,7 +631,7 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result,
(sshdr.ascq == 0)) (sshdr.ascq == 0))
continue; continue;
} }
} else { } else if (result == 0) {
/* /*
* if nothing was transferred, we try * if nothing was transferred, we try
* again. It's a workaround for some USB * again. It's a workaround for some USB
......
...@@ -127,7 +127,7 @@ static int spi_execute(struct scsi_device *sdev, const void *cmd, ...@@ -127,7 +127,7 @@ static int spi_execute(struct scsi_device *sdev, const void *cmd,
REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_TRANSPORT |
REQ_FAILFAST_DRIVER, REQ_FAILFAST_DRIVER,
RQF_PM, NULL); RQF_PM, NULL);
if (driver_byte(result) != DRIVER_SENSE || if (result < 0 || driver_byte(result) != DRIVER_SENSE ||
sshdr->sense_key != UNIT_ATTENTION) sshdr->sense_key != UNIT_ATTENTION)
break; break;
} }
......
...@@ -1658,7 +1658,7 @@ static unsigned int sd_check_events(struct gendisk *disk, unsigned int clearing) ...@@ -1658,7 +1658,7 @@ static unsigned int sd_check_events(struct gendisk *disk, unsigned int clearing)
&sshdr); &sshdr);
/* failed to execute TUR, assume media not present */ /* failed to execute TUR, assume media not present */
if (host_byte(retval)) { if (retval < 0 || host_byte(retval)) {
set_media_not_present(sdkp); set_media_not_present(sdkp);
goto out; goto out;
} }
...@@ -1719,6 +1719,9 @@ static int sd_sync_cache(struct scsi_disk *sdkp, struct scsi_sense_hdr *sshdr) ...@@ -1719,6 +1719,9 @@ static int sd_sync_cache(struct scsi_disk *sdkp, struct scsi_sense_hdr *sshdr)
if (res) { if (res) {
sd_print_result(sdkp, "Synchronize Cache(10) failed", res); sd_print_result(sdkp, "Synchronize Cache(10) failed", res);
if (res < 0)
return res;
if (driver_byte(res) == DRIVER_SENSE) if (driver_byte(res) == DRIVER_SENSE)
sd_print_sense_hdr(sdkp, sshdr); sd_print_sense_hdr(sdkp, sshdr);
...@@ -1825,7 +1828,7 @@ static int sd_pr_command(struct block_device *bdev, u8 sa, ...@@ -1825,7 +1828,7 @@ static int sd_pr_command(struct block_device *bdev, u8 sa,
result = scsi_execute_req(sdev, cmd, DMA_TO_DEVICE, &data, sizeof(data), result = scsi_execute_req(sdev, cmd, DMA_TO_DEVICE, &data, sizeof(data),
&sshdr, SD_TIMEOUT, sdkp->max_retries, NULL); &sshdr, SD_TIMEOUT, sdkp->max_retries, NULL);
if (driver_byte(result) == DRIVER_SENSE && if (result > 0 && driver_byte(result) == DRIVER_SENSE &&
scsi_sense_valid(&sshdr)) { scsi_sense_valid(&sshdr)) {
sdev_printk(KERN_INFO, sdev, "PR command failed: %d\n", result); sdev_printk(KERN_INFO, sdev, "PR command failed: %d\n", result);
scsi_print_sense_hdr(sdev, NULL, &sshdr); scsi_print_sense_hdr(sdev, NULL, &sshdr);
...@@ -2177,7 +2180,7 @@ sd_spinup_disk(struct scsi_disk *sdkp) ...@@ -2177,7 +2180,7 @@ sd_spinup_disk(struct scsi_disk *sdkp)
((driver_byte(the_result) == DRIVER_SENSE) && ((driver_byte(the_result) == DRIVER_SENSE) &&
sense_valid && sshdr.sense_key == UNIT_ATTENTION))); sense_valid && sshdr.sense_key == UNIT_ATTENTION)));
if (driver_byte(the_result) != DRIVER_SENSE) { if (the_result < 0 || driver_byte(the_result) != DRIVER_SENSE) {
/* no sense, TUR either succeeded or failed /* no sense, TUR either succeeded or failed
* with a status error */ * with a status error */
if(!spintime && !scsi_status_is_good(the_result)) { if(!spintime && !scsi_status_is_good(the_result)) {
...@@ -2362,7 +2365,7 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp, ...@@ -2362,7 +2365,7 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
if (media_not_present(sdkp, &sshdr)) if (media_not_present(sdkp, &sshdr))
return -ENODEV; return -ENODEV;
if (the_result) { if (the_result > 0) {
sense_valid = scsi_sense_valid(&sshdr); sense_valid = scsi_sense_valid(&sshdr);
if (sense_valid && if (sense_valid &&
sshdr.sense_key == ILLEGAL_REQUEST && sshdr.sense_key == ILLEGAL_REQUEST &&
...@@ -2447,7 +2450,7 @@ static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp, ...@@ -2447,7 +2450,7 @@ static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp,
if (media_not_present(sdkp, &sshdr)) if (media_not_present(sdkp, &sshdr))
return -ENODEV; return -ENODEV;
if (the_result) { if (the_result > 0) {
sense_valid = scsi_sense_valid(&sshdr); sense_valid = scsi_sense_valid(&sshdr);
if (sense_valid && if (sense_valid &&
sshdr.sense_key == UNIT_ATTENTION && sshdr.sense_key == UNIT_ATTENTION &&
...@@ -3591,7 +3594,7 @@ static int sd_start_stop_device(struct scsi_disk *sdkp, int start) ...@@ -3591,7 +3594,7 @@ static int sd_start_stop_device(struct scsi_disk *sdkp, int start)
SD_TIMEOUT, sdkp->max_retries, 0, RQF_PM, NULL); SD_TIMEOUT, sdkp->max_retries, 0, RQF_PM, NULL);
if (res) { if (res) {
sd_print_result(sdkp, "Start/Stop Unit failed", res); sd_print_result(sdkp, "Start/Stop Unit failed", res);
if (driver_byte(res) == DRIVER_SENSE) if (res > 0 && driver_byte(res) == DRIVER_SENSE)
sd_print_sense_hdr(sdkp, &sshdr); sd_print_sense_hdr(sdkp, &sshdr);
if (scsi_sense_valid(&sshdr) && if (scsi_sense_valid(&sshdr) &&
/* 0x3a is medium not present */ /* 0x3a is medium not present */
......
...@@ -116,7 +116,7 @@ static int sd_zbc_do_report_zones(struct scsi_disk *sdkp, unsigned char *buf, ...@@ -116,7 +116,7 @@ static int sd_zbc_do_report_zones(struct scsi_disk *sdkp, unsigned char *buf,
sd_printk(KERN_ERR, sdkp, sd_printk(KERN_ERR, sdkp,
"REPORT ZONES start lba %llu failed\n", lba); "REPORT ZONES start lba %llu failed\n", lba);
sd_print_result(sdkp, "REPORT ZONES", result); sd_print_result(sdkp, "REPORT ZONES", result);
if (driver_byte(result) == DRIVER_SENSE && if (result > 0 && driver_byte(result) == DRIVER_SENSE &&
scsi_sense_valid(&sshdr)) scsi_sense_valid(&sshdr))
sd_print_sense_hdr(sdkp, &sshdr); sd_print_sense_hdr(sdkp, &sshdr);
return -EIO; return -EIO;
......
...@@ -201,6 +201,10 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc) ...@@ -201,6 +201,10 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc)
cgc->timeout, IOCTL_RETRIES, 0, 0, NULL); cgc->timeout, IOCTL_RETRIES, 0, 0, NULL);
/* Minimal error checking. Ignore cases we know about, and report the rest. */ /* Minimal error checking. Ignore cases we know about, and report the rest. */
if (result < 0) {
err = result;
goto out;
}
if (driver_byte(result) != 0) { if (driver_byte(result) != 0) {
switch (sshdr->sense_key) { switch (sshdr->sense_key) {
case UNIT_ATTENTION: case UNIT_ATTENTION:
......
...@@ -8604,7 +8604,7 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba, ...@@ -8604,7 +8604,7 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba,
sdev_printk(KERN_WARNING, sdp, sdev_printk(KERN_WARNING, sdp,
"START_STOP failed for power mode: %d, result %x\n", "START_STOP failed for power mode: %d, result %x\n",
pwr_mode, ret); pwr_mode, ret);
if (driver_byte(ret) == DRIVER_SENSE) if (ret > 0 && driver_byte(ret) == DRIVER_SENSE)
scsi_print_sense_hdr(sdp, NULL, &sshdr); scsi_print_sense_hdr(sdp, NULL, &sshdr);
} }
......
...@@ -355,7 +355,7 @@ static void virtscsi_rescan_hotunplug(struct virtio_scsi *vscsi) ...@@ -355,7 +355,7 @@ static void virtscsi_rescan_hotunplug(struct virtio_scsi *vscsi)
if (result == 0 && inq_result[0] >> 5) { if (result == 0 && inq_result[0] >> 5) {
/* PQ indicates the LUN is not attached */ /* PQ indicates the LUN is not attached */
scsi_remove_device(sdev); scsi_remove_device(sdev);
} else if (host_byte(result) == DID_BAD_TARGET) { } else if (result > 0 && host_byte(result) == DID_BAD_TARGET) {
/* /*
* If all LUNs of a virtio-scsi device are unplugged * If all LUNs of a virtio-scsi device are unplugged
* it will respond with BAD TARGET on any INQUIRY * it will respond with BAD TARGET on any INQUIRY
......
...@@ -259,10 +259,13 @@ enum scsi_disposition { ...@@ -259,10 +259,13 @@ enum scsi_disposition {
* This returns true for known good conditions that may be treated as * This returns true for known good conditions that may be treated as
* command completed normally * command completed normally
*/ */
static inline int scsi_status_is_good(int status) static inline bool scsi_status_is_good(int status)
{ {
if (status < 0)
return false;
if (host_byte(status) == DID_NO_CONNECT) if (host_byte(status) == DID_NO_CONNECT)
return 0; return false;
/* /*
* FIXME: bit0 is listed as reserved in SCSI-2, but is * FIXME: bit0 is listed as reserved in SCSI-2, but is
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment