diff options
| author | Li Tian <litian@redhat.com> | 2026-04-06 04:53:44 +0300 |
|---|---|---|
| committer | Martin K. Petersen <martin.petersen@oracle.com> | 2026-04-09 04:52:06 +0300 |
| commit | 9cf351b289fb2be22491fa3964f99126db67aa08 (patch) | |
| tree | ef154be4181d8c6bbb40170799443281c51f53ce | |
| parent | 7aa0f56d4b48fb1a1ed3af11b53ba19901092e0a (diff) | |
| download | linux-9cf351b289fb2be22491fa3964f99126db67aa08.tar.xz | |
scsi: storvsc: Handle PERSISTENT_RESERVE_IN truncation for Hyper-V vFC
The storvsc driver has become stricter in handling SRB status codes
returned by the Hyper-V host. When using Virtual Fibre Channel (vFC)
passthrough, the host may return SRB_STATUS_DATA_OVERRUN for
PERSISTENT_RESERVE_IN commands if the allocation length in the CDB does
not match the host's expected response size.
Currently, this status is treated as a fatal error, propagating
Host_status=0x07 [DID_ERROR] to the SCSI mid-layer. This causes
userspace storage utilities (such as sg_persist) to fail with transport
errors, even when the host has actually returned the requested
reservation data in the buffer.
Refactor the existing command-specific workarounds into a new helper
function, storvsc_host_mishandles_cmd(), and add PERSISTENT_RESERVE_IN
to the list of commands where SRB status errors should be suppressed for
vFC devices. This ensures that the SCSI mid-layer processes the returned
data buffer instead of terminating the command.
Signed-off-by: Li Tian <litian@redhat.com>
Reviewed-by: Long Li <longli@microsoft.com>
Reviewed-by: Laurence Oberman <loberman@redhat.com>
Link: https://patch.msgid.link/20260406015344.12566-1-litian@redhat.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
| -rw-r--r-- | drivers/scsi/storvsc_drv.c | 32 |
1 files changed, 21 insertions, 11 deletions
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index ae1abab97835..6977ca8a0658 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1131,6 +1131,26 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request, kfree(payload); } +/* + * The current SCSI handling on the host side does not correctly handle: + * INQUIRY with page code 0x80, MODE_SENSE / MODE_SENSE_10 with cmd[2] == 0x1c, + * and (for FC) MAINTENANCE_IN / PERSISTENT_RESERVE_IN passthrough. + */ +static bool storvsc_host_mishandles_cmd(u8 opcode, struct hv_device *device) +{ + switch (opcode) { + case INQUIRY: + case MODE_SENSE: + case MODE_SENSE_10: + return true; + case MAINTENANCE_IN: + case PERSISTENT_RESERVE_IN: + return hv_dev_is_fc(device); + default: + return false; + } +} + static void storvsc_on_io_completion(struct storvsc_device *stor_device, struct vstor_packet *vstor_packet, struct storvsc_cmd_request *request) @@ -1141,22 +1161,12 @@ static void storvsc_on_io_completion(struct storvsc_device *stor_device, stor_pkt = &request->vstor_packet; /* - * The current SCSI handling on the host side does - * not correctly handle: - * INQUIRY command with page code parameter set to 0x80 - * MODE_SENSE and MODE_SENSE_10 command with cmd[2] == 0x1c - * MAINTENANCE_IN is not supported by HyperV FC passthrough - * * Setup srb and scsi status so this won't be fatal. * We do this so we can distinguish truly fatal failues * (srb status == 0x4) and off-line the device in that case. */ - if ((stor_pkt->vm_srb.cdb[0] == INQUIRY) || - (stor_pkt->vm_srb.cdb[0] == MODE_SENSE) || - (stor_pkt->vm_srb.cdb[0] == MODE_SENSE_10) || - (stor_pkt->vm_srb.cdb[0] == MAINTENANCE_IN && - hv_dev_is_fc(device))) { + if (storvsc_host_mishandles_cmd(stor_pkt->vm_srb.cdb[0], device)) { vstor_packet->vm_srb.scsi_status = 0; vstor_packet->vm_srb.srb_status = SRB_STATUS_SUCCESS; } |
