Merge patch series "scsi: sshdr and retry fixes"
Mike Christie <michael.christie@oracle.com> says: The following patches were made over Linus tree (Martin's 6.7 branch was missing some changes to sd.c). They only contain the sshdr and rdac retry fixes from the "Allow scsi_execute users to control retries" patchset. The patches in this set are reviewed and tested but the changes to how we do retries will take a little longer and require more testing, so I broke up the series to make them easier to review. Link: https://lore.kernel.org/r/20231004210013.5601-1-michael.christie@oracle.com Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
commit
bd7f0ef293
@ -82,7 +82,7 @@ static int hp_sw_tur(struct scsi_device *sdev, struct hp_sw_dh_data *h)
|
||||
{
|
||||
unsigned char cmd[6] = { TEST_UNIT_READY };
|
||||
struct scsi_sense_hdr sshdr;
|
||||
int ret = SCSI_DH_OK, res;
|
||||
int ret, res;
|
||||
blk_opf_t opf = REQ_OP_DRV_IN | REQ_FAILFAST_DEV |
|
||||
REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER;
|
||||
const struct scsi_exec_args exec_args = {
|
||||
@ -92,19 +92,18 @@ static int hp_sw_tur(struct scsi_device *sdev, struct hp_sw_dh_data *h)
|
||||
retry:
|
||||
res = scsi_execute_cmd(sdev, cmd, opf, NULL, 0, HP_SW_TIMEOUT,
|
||||
HP_SW_RETRIES, &exec_args);
|
||||
if (res) {
|
||||
if (scsi_sense_valid(&sshdr))
|
||||
ret = tur_done(sdev, h, &sshdr);
|
||||
else {
|
||||
sdev_printk(KERN_WARNING, sdev,
|
||||
"%s: sending tur failed with %x\n",
|
||||
HP_SW_NAME, res);
|
||||
ret = SCSI_DH_IO;
|
||||
}
|
||||
} else {
|
||||
if (res > 0 && scsi_sense_valid(&sshdr)) {
|
||||
ret = tur_done(sdev, h, &sshdr);
|
||||
} else if (res == 0) {
|
||||
h->path_state = HP_SW_PATH_ACTIVE;
|
||||
ret = SCSI_DH_OK;
|
||||
} else {
|
||||
sdev_printk(KERN_WARNING, sdev,
|
||||
"%s: sending tur failed with %x\n",
|
||||
HP_SW_NAME, res);
|
||||
ret = SCSI_DH_IO;
|
||||
}
|
||||
|
||||
if (ret == SCSI_DH_IMM_RETRY)
|
||||
goto retry;
|
||||
|
||||
@ -122,7 +121,7 @@ static int hp_sw_start_stop(struct hp_sw_dh_data *h)
|
||||
unsigned char cmd[6] = { START_STOP, 0, 0, 0, 1, 0 };
|
||||
struct scsi_sense_hdr sshdr;
|
||||
struct scsi_device *sdev = h->sdev;
|
||||
int res, rc = SCSI_DH_OK;
|
||||
int res, rc;
|
||||
int retry_cnt = HP_SW_RETRIES;
|
||||
blk_opf_t opf = REQ_OP_DRV_IN | REQ_FAILFAST_DEV |
|
||||
REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER;
|
||||
@ -133,35 +132,37 @@ static int hp_sw_start_stop(struct hp_sw_dh_data *h)
|
||||
retry:
|
||||
res = scsi_execute_cmd(sdev, cmd, opf, NULL, 0, HP_SW_TIMEOUT,
|
||||
HP_SW_RETRIES, &exec_args);
|
||||
if (res) {
|
||||
if (!scsi_sense_valid(&sshdr)) {
|
||||
sdev_printk(KERN_WARNING, sdev,
|
||||
"%s: sending start_stop_unit failed, "
|
||||
"no sense available\n", HP_SW_NAME);
|
||||
return SCSI_DH_IO;
|
||||
}
|
||||
switch (sshdr.sense_key) {
|
||||
case NOT_READY:
|
||||
if (sshdr.asc == 0x04 && sshdr.ascq == 3) {
|
||||
/*
|
||||
* LUN not ready - manual intervention required
|
||||
*
|
||||
* Switch-over in progress, retry.
|
||||
*/
|
||||
if (--retry_cnt)
|
||||
goto retry;
|
||||
rc = SCSI_DH_RETRY;
|
||||
break;
|
||||
}
|
||||
fallthrough;
|
||||
default:
|
||||
sdev_printk(KERN_WARNING, sdev,
|
||||
"%s: sending start_stop_unit failed, "
|
||||
"sense %x/%x/%x\n", HP_SW_NAME,
|
||||
sshdr.sense_key, sshdr.asc, sshdr.ascq);
|
||||
rc = SCSI_DH_IO;
|
||||
}
|
||||
if (!res) {
|
||||
return SCSI_DH_OK;
|
||||
} else if (res < 0 || !scsi_sense_valid(&sshdr)) {
|
||||
sdev_printk(KERN_WARNING, sdev,
|
||||
"%s: sending start_stop_unit failed, "
|
||||
"no sense available\n", HP_SW_NAME);
|
||||
return SCSI_DH_IO;
|
||||
}
|
||||
|
||||
switch (sshdr.sense_key) {
|
||||
case NOT_READY:
|
||||
if (sshdr.asc == 0x04 && sshdr.ascq == 3) {
|
||||
/*
|
||||
* LUN not ready - manual intervention required
|
||||
*
|
||||
* Switch-over in progress, retry.
|
||||
*/
|
||||
if (--retry_cnt)
|
||||
goto retry;
|
||||
rc = SCSI_DH_RETRY;
|
||||
break;
|
||||
}
|
||||
fallthrough;
|
||||
default:
|
||||
sdev_printk(KERN_WARNING, sdev,
|
||||
"%s: sending start_stop_unit failed, "
|
||||
"sense %x/%x/%x\n", HP_SW_NAME,
|
||||
sshdr.sense_key, sshdr.asc, sshdr.ascq);
|
||||
rc = SCSI_DH_IO;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -530,7 +530,7 @@ static void send_mode_select(struct work_struct *work)
|
||||
container_of(work, struct rdac_controller, ms_work);
|
||||
struct scsi_device *sdev = ctlr->ms_sdev;
|
||||
struct rdac_dh_data *h = sdev->handler_data;
|
||||
int err = SCSI_DH_OK, retry_cnt = RDAC_RETRY_COUNT;
|
||||
int rc, err, retry_cnt = RDAC_RETRY_COUNT;
|
||||
struct rdac_queue_data *tmp, *qdata;
|
||||
LIST_HEAD(list);
|
||||
unsigned char cdb[MAX_COMMAND_SIZE];
|
||||
@ -558,20 +558,23 @@ static void send_mode_select(struct work_struct *work)
|
||||
(char *) h->ctlr->array_name, h->ctlr->index,
|
||||
(retry_cnt == RDAC_RETRY_COUNT) ? "queueing" : "retrying");
|
||||
|
||||
if (scsi_execute_cmd(sdev, cdb, opf, &h->ctlr->mode_select, data_size,
|
||||
RDAC_TIMEOUT * HZ, RDAC_RETRIES, &exec_args)) {
|
||||
rc = scsi_execute_cmd(sdev, cdb, opf, &h->ctlr->mode_select, data_size,
|
||||
RDAC_TIMEOUT * HZ, RDAC_RETRIES, &exec_args);
|
||||
if (!rc) {
|
||||
h->state = RDAC_STATE_ACTIVE;
|
||||
RDAC_LOG(RDAC_LOG_FAILOVER, sdev, "array %s, ctlr %d, "
|
||||
"MODE_SELECT completed",
|
||||
(char *) h->ctlr->array_name, h->ctlr->index);
|
||||
err = SCSI_DH_OK;
|
||||
} else if (rc < 0) {
|
||||
err = SCSI_DH_IO;
|
||||
} else {
|
||||
err = mode_select_handle_sense(sdev, &sshdr);
|
||||
if (err == SCSI_DH_RETRY && retry_cnt--)
|
||||
goto retry;
|
||||
if (err == SCSI_DH_IMM_RETRY)
|
||||
goto retry;
|
||||
}
|
||||
if (err == SCSI_DH_OK) {
|
||||
h->state = RDAC_STATE_ACTIVE;
|
||||
RDAC_LOG(RDAC_LOG_FAILOVER, sdev, "array %s, ctlr %d, "
|
||||
"MODE_SELECT completed",
|
||||
(char *) h->ctlr->array_name, h->ctlr->index);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(qdata, tmp, &list, entry) {
|
||||
list_del(&qdata->entry);
|
||||
|
@ -692,7 +692,7 @@ int scsi_cdl_enable(struct scsi_device *sdev, bool enable)
|
||||
ret = scsi_mode_select(sdev, 1, 0, buf_data, len, 5 * HZ, 3,
|
||||
&data, &sshdr);
|
||||
if (ret) {
|
||||
if (scsi_sense_valid(&sshdr))
|
||||
if (ret > 0 && scsi_sense_valid(&sshdr))
|
||||
scsi_print_sense_hdr(sdev,
|
||||
dev_name(&sdev->sdev_gendev), &sshdr);
|
||||
return ret;
|
||||
|
@ -2299,10 +2299,10 @@ scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries,
|
||||
do {
|
||||
result = scsi_execute_cmd(sdev, cmd, REQ_OP_DRV_IN, NULL, 0,
|
||||
timeout, 1, &exec_args);
|
||||
if (sdev->removable && scsi_sense_valid(sshdr) &&
|
||||
if (sdev->removable && result > 0 && scsi_sense_valid(sshdr) &&
|
||||
sshdr->sense_key == UNIT_ATTENTION)
|
||||
sdev->changed = 1;
|
||||
} while (scsi_sense_valid(sshdr) &&
|
||||
} while (result > 0 && scsi_sense_valid(sshdr) &&
|
||||
sshdr->sense_key == UNIT_ATTENTION && --retries);
|
||||
|
||||
return result;
|
||||
|
@ -676,10 +676,10 @@ spi_dv_device_echo_buffer(struct scsi_device *sdev, u8 *buffer,
|
||||
for (r = 0; r < retries; r++) {
|
||||
result = spi_execute(sdev, spi_write_buffer, REQ_OP_DRV_OUT,
|
||||
buffer, len, &sshdr);
|
||||
if(result || !scsi_device_online(sdev)) {
|
||||
if (result || !scsi_device_online(sdev)) {
|
||||
|
||||
scsi_device_set_state(sdev, SDEV_QUIESCE);
|
||||
if (scsi_sense_valid(&sshdr)
|
||||
if (result > 0 && scsi_sense_valid(&sshdr)
|
||||
&& sshdr.sense_key == ILLEGAL_REQUEST
|
||||
/* INVALID FIELD IN CDB */
|
||||
&& sshdr.asc == 0x24 && sshdr.ascq == 0x00)
|
||||
|
@ -143,7 +143,7 @@ cache_type_store(struct device *dev, struct device_attribute *attr,
|
||||
struct scsi_mode_data data;
|
||||
struct scsi_sense_hdr sshdr;
|
||||
static const char temp[] = "temporary ";
|
||||
int len;
|
||||
int len, ret;
|
||||
|
||||
if (sdp->type != TYPE_DISK && sdp->type != TYPE_ZBC)
|
||||
/* no cache control on RBC devices; theoretically they
|
||||
@ -190,9 +190,10 @@ cache_type_store(struct device *dev, struct device_attribute *attr,
|
||||
*/
|
||||
data.device_specific = 0;
|
||||
|
||||
if (scsi_mode_select(sdp, 1, sp, buffer_data, len, SD_TIMEOUT,
|
||||
sdkp->max_retries, &data, &sshdr)) {
|
||||
if (scsi_sense_valid(&sshdr))
|
||||
ret = scsi_mode_select(sdp, 1, sp, buffer_data, len, SD_TIMEOUT,
|
||||
sdkp->max_retries, &data, &sshdr);
|
||||
if (ret) {
|
||||
if (ret > 0 && scsi_sense_valid(&sshdr))
|
||||
sd_print_sense_hdr(sdkp, &sshdr);
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -2180,19 +2181,21 @@ sd_spinup_disk(struct scsi_disk *sdkp)
|
||||
sdkp->max_retries,
|
||||
&exec_args);
|
||||
|
||||
/*
|
||||
* If the drive has indicated to us that it
|
||||
* doesn't have any media in it, don't bother
|
||||
* with any more polling.
|
||||
*/
|
||||
if (media_not_present(sdkp, &sshdr)) {
|
||||
if (media_was_present)
|
||||
sd_printk(KERN_NOTICE, sdkp, "Media removed, stopped polling\n");
|
||||
return;
|
||||
}
|
||||
if (the_result > 0) {
|
||||
/*
|
||||
* If the drive has indicated to us that it
|
||||
* doesn't have any media in it, don't bother
|
||||
* with any more polling.
|
||||
*/
|
||||
if (media_not_present(sdkp, &sshdr)) {
|
||||
if (media_was_present)
|
||||
sd_printk(KERN_NOTICE, sdkp,
|
||||
"Media removed, stopped polling\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (the_result)
|
||||
sense_valid = scsi_sense_valid(&sshdr);
|
||||
}
|
||||
retries++;
|
||||
} while (retries < 3 &&
|
||||
(!scsi_status_is_good(the_result) ||
|
||||
@ -2388,11 +2391,10 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
|
||||
the_result = scsi_execute_cmd(sdp, cmd, REQ_OP_DRV_IN,
|
||||
buffer, RC16_LEN, SD_TIMEOUT,
|
||||
sdkp->max_retries, &exec_args);
|
||||
|
||||
if (media_not_present(sdkp, &sshdr))
|
||||
return -ENODEV;
|
||||
|
||||
if (the_result > 0) {
|
||||
if (media_not_present(sdkp, &sshdr))
|
||||
return -ENODEV;
|
||||
|
||||
sense_valid = scsi_sense_valid(&sshdr);
|
||||
if (sense_valid &&
|
||||
sshdr.sense_key == ILLEGAL_REQUEST &&
|
||||
@ -2889,7 +2891,7 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
|
||||
}
|
||||
|
||||
bad_sense:
|
||||
if (scsi_sense_valid(&sshdr) &&
|
||||
if (res == -EIO && scsi_sense_valid(&sshdr) &&
|
||||
sshdr.sense_key == ILLEGAL_REQUEST &&
|
||||
sshdr.asc == 0x24 && sshdr.ascq == 0x0)
|
||||
/* Invalid field in CDB */
|
||||
@ -2937,7 +2939,7 @@ static void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer)
|
||||
sd_first_printk(KERN_WARNING, sdkp,
|
||||
"getting Control mode page failed, assume no ATO\n");
|
||||
|
||||
if (scsi_sense_valid(&sshdr))
|
||||
if (res == -EIO && scsi_sense_valid(&sshdr))
|
||||
sd_print_sense_hdr(sdkp, &sshdr);
|
||||
|
||||
return;
|
||||
|
@ -177,7 +177,8 @@ static unsigned int sr_get_events(struct scsi_device *sdev)
|
||||
|
||||
result = scsi_execute_cmd(sdev, cmd, REQ_OP_DRV_IN, buf, sizeof(buf),
|
||||
SR_TIMEOUT, MAX_RETRIES, &exec_args);
|
||||
if (scsi_sense_valid(&sshdr) && sshdr.sense_key == UNIT_ATTENTION)
|
||||
if (result > 0 && scsi_sense_valid(&sshdr) &&
|
||||
sshdr.sense_key == UNIT_ATTENTION)
|
||||
return DISK_EVENT_MEDIA_CHANGE;
|
||||
|
||||
if (result || be16_to_cpu(eh->data_len) < sizeof(*med))
|
||||
|
Loading…
Reference in New Issue
Block a user