diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2021-07-03 00:14:36 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-07-03 00:14:36 +0200 |
commit | bd31b9efbf549d9630bf2f269a3a56dcb29fcac1 (patch) | |
tree | 677abd40f1f86276199e68c098e48120671ec851 /drivers/scsi/storvsc_drv.c | |
parent | Merge tag 'xfs-5.14-merge-6' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux (diff) | |
parent | scsi: aha1740: Avoid over-read of sense buffer (diff) | |
download | linux-bd31b9efbf549d9630bf2f269a3a56dcb29fcac1.tar.xz linux-bd31b9efbf549d9630bf2f269a3a56dcb29fcac1.zip |
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley:
"This series consists of the usual driver updates (ufs, ibmvfc,
megaraid_sas, lpfc, elx, mpi3mr, qedi, iscsi, storvsc, mpt3sas) with
elx and mpi3mr being new drivers.
The major core change is a rework to drop the status byte handling
macros and the old bit shifted definitions and the rest of the updates
are minor fixes"
* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (287 commits)
scsi: aha1740: Avoid over-read of sense buffer
scsi: arcmsr: Avoid over-read of sense buffer
scsi: ips: Avoid over-read of sense buffer
scsi: ufs: ufs-mediatek: Add missing of_node_put() in ufs_mtk_probe()
scsi: elx: libefc: Fix IRQ restore in efc_domain_dispatch_frame()
scsi: elx: libefc: Fix less than zero comparison of a unsigned int
scsi: elx: efct: Fix pointer error checking in debugfs init
scsi: elx: efct: Fix is_originator return code type
scsi: elx: efct: Fix link error for _bad_cmpxchg
scsi: elx: efct: Eliminate unnecessary boolean check in efct_hw_command_cancel()
scsi: elx: efct: Do not use id uninitialized in efct_lio_setup_session()
scsi: elx: efct: Fix error handling in efct_hw_init()
scsi: elx: efct: Remove redundant initialization of variable lun
scsi: elx: efct: Fix spelling mistake "Unexected" -> "Unexpected"
scsi: lpfc: Fix build error in lpfc_scsi.c
scsi: target: iscsi: Remove redundant continue statement
scsi: qla4xxx: Remove redundant continue statement
scsi: ppa: Switch to use module_parport_driver()
scsi: imm: Switch to use module_parport_driver()
scsi: mpt3sas: Fix error return value in _scsih_expander_add()
...
Diffstat (limited to 'drivers/scsi/storvsc_drv.c')
-rw-r--r-- | drivers/scsi/storvsc_drv.c | 119 |
1 files changed, 56 insertions, 63 deletions
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 403753929320..328bb961c281 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1031,17 +1031,40 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb, struct storvsc_scan_work *wrk; void (*process_err_fn)(struct work_struct *work); struct hv_host_device *host_dev = shost_priv(host); - bool do_work = false; - switch (SRB_STATUS(vm_srb->srb_status)) { - case SRB_STATUS_ERROR: + /* + * In some situations, Hyper-V sets multiple bits in the + * srb_status, such as ABORTED and ERROR. So process them + * individually, with the most specific bits first. + */ + + if (vm_srb->srb_status & SRB_STATUS_INVALID_LUN) { + set_host_byte(scmnd, DID_NO_CONNECT); + process_err_fn = storvsc_remove_lun; + goto do_work; + } + + if (vm_srb->srb_status & SRB_STATUS_ABORTED) { + if (vm_srb->srb_status & SRB_STATUS_AUTOSENSE_VALID && + /* Capacity data has changed */ + (asc == 0x2a) && (ascq == 0x9)) { + process_err_fn = storvsc_device_scan; + /* + * Retry the I/O that triggered this. + */ + set_host_byte(scmnd, DID_REQUEUE); + goto do_work; + } + } + + if (vm_srb->srb_status & SRB_STATUS_ERROR) { /* * Let upper layer deal with error when * sense message is present. */ - if (vm_srb->srb_status & SRB_STATUS_AUTOSENSE_VALID) - break; + return; + /* * If there is an error; offline the device since all * error recovery strategies would have already been @@ -1054,37 +1077,19 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb, set_host_byte(scmnd, DID_PASSTHROUGH); break; /* - * On Some Windows hosts TEST_UNIT_READY command can return - * SRB_STATUS_ERROR, let the upper level code deal with it - * based on the sense information. + * On some Hyper-V hosts TEST_UNIT_READY command can + * return SRB_STATUS_ERROR. Let the upper level code + * deal with it based on the sense information. */ case TEST_UNIT_READY: break; default: set_host_byte(scmnd, DID_ERROR); } - break; - case SRB_STATUS_INVALID_LUN: - set_host_byte(scmnd, DID_NO_CONNECT); - do_work = true; - process_err_fn = storvsc_remove_lun; - break; - case SRB_STATUS_ABORTED: - if (vm_srb->srb_status & SRB_STATUS_AUTOSENSE_VALID && - (asc == 0x2a) && (ascq == 0x9)) { - do_work = true; - process_err_fn = storvsc_device_scan; - /* - * Retry the I/O that triggered this. - */ - set_host_byte(scmnd, DID_REQUEUE); - } - break; } + return; - if (!do_work) - return; - +do_work: /* * We need to schedule work to process this error; schedule it. */ @@ -1112,6 +1117,7 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request, struct Scsi_Host *host; u32 payload_sz = cmd_request->payload_sz; void *payload = cmd_request->payload; + bool sense_ok; host = stor_dev->host; @@ -1121,11 +1127,10 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request, scmnd->result = vm_srb->scsi_status; if (scmnd->result) { - if (scsi_normalize_sense(scmnd->sense_buffer, - SCSI_SENSE_BUFFERSIZE, &sense_hdr) && - !(sense_hdr.sense_key == NOT_READY && - sense_hdr.asc == 0x03A) && - do_logging(STORVSC_LOGGING_ERROR)) + sense_ok = scsi_normalize_sense(scmnd->sense_buffer, + SCSI_SENSE_BUFFERSIZE, &sense_hdr); + + if (sense_ok && do_logging(STORVSC_LOGGING_WARN)) scsi_print_sense_hdr(scmnd->device, "storvsc", &sense_hdr); } @@ -1182,53 +1187,41 @@ static void storvsc_on_io_completion(struct storvsc_device *stor_device, vstor_packet->vm_srb.srb_status = SRB_STATUS_SUCCESS; } - /* Copy over the status...etc */ stor_pkt->vm_srb.scsi_status = vstor_packet->vm_srb.scsi_status; stor_pkt->vm_srb.srb_status = vstor_packet->vm_srb.srb_status; - /* Validate sense_info_length (from Hyper-V) */ - if (vstor_packet->vm_srb.sense_info_length > sense_buffer_size) - vstor_packet->vm_srb.sense_info_length = sense_buffer_size; - - stor_pkt->vm_srb.sense_info_length = - vstor_packet->vm_srb.sense_info_length; + /* + * Copy over the sense_info_length, but limit to the known max + * size if Hyper-V returns a bad value. + */ + stor_pkt->vm_srb.sense_info_length = min_t(u8, sense_buffer_size, + vstor_packet->vm_srb.sense_info_length); if (vstor_packet->vm_srb.scsi_status != 0 || vstor_packet->vm_srb.srb_status != SRB_STATUS_SUCCESS) - storvsc_log(device, STORVSC_LOGGING_WARN, - "cmd 0x%x scsi status 0x%x srb status 0x%x\n", + storvsc_log(device, STORVSC_LOGGING_ERROR, + "tag#%d cmd 0x%x status: scsi 0x%x srb 0x%x hv 0x%x\n", + request->cmd->request->tag, stor_pkt->vm_srb.cdb[0], vstor_packet->vm_srb.scsi_status, - vstor_packet->vm_srb.srb_status); - - if ((vstor_packet->vm_srb.scsi_status & 0xFF) == 0x02) { - /* CHECK_CONDITION */ - if (vstor_packet->vm_srb.srb_status & - SRB_STATUS_AUTOSENSE_VALID) { - /* autosense data available */ - - storvsc_log(device, STORVSC_LOGGING_WARN, - "stor pkt %p autosense data valid - len %d\n", - request, vstor_packet->vm_srb.sense_info_length); - - memcpy(request->cmd->sense_buffer, - vstor_packet->vm_srb.sense_data, - vstor_packet->vm_srb.sense_info_length); + vstor_packet->vm_srb.srb_status, + vstor_packet->status); - } - } + if (vstor_packet->vm_srb.scsi_status == SAM_STAT_CHECK_CONDITION && + (vstor_packet->vm_srb.srb_status & SRB_STATUS_AUTOSENSE_VALID)) + memcpy(request->cmd->sense_buffer, + vstor_packet->vm_srb.sense_data, + stor_pkt->vm_srb.sense_info_length); stor_pkt->vm_srb.data_transfer_length = - vstor_packet->vm_srb.data_transfer_length; + vstor_packet->vm_srb.data_transfer_length; storvsc_command_completion(request, stor_device); if (atomic_dec_and_test(&stor_device->num_outstanding_req) && stor_device->drain_notify) wake_up(&stor_device->waiting_to_drain); - - } static void storvsc_on_receive(struct storvsc_device *stor_device, @@ -1717,7 +1710,7 @@ static bool storvsc_scsi_cmd_ok(struct scsi_cmnd *scmnd) * this. So, don't send it. */ case SET_WINDOW: - scmnd->result = DID_ERROR << 16; + set_host_byte(scmnd, DID_ERROR); allowed = false; break; default: |