[PATCH v2] scsi: storvsc: Support manual scans for all Hyper-V targets
From: Laurence Oberman <hidden>
Date: 2026-07-23 16:37:56
Also in:
linux-scsi, lkml
Subsystem:
hyper-v/azure core and drivers, scsi subsystem, the rest · Maintainers:
"K. Y. Srinivasan", Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li, "James E.J. Bottomley", "Martin K. Petersen", Linus Torvalds
The Fibre Channel transport topology created by storvsc exposes only one dummy remote port per SCSI host. Its scsi_target_id is always zero. As a result, the FC transport user-scan path looks up the remote port using target ID 0. It cannot initiate a scan for Target 1 or higher. No SCSI command is therefore sent to Hyper-V when userspace explicitly requests a scan of one of these targets. storvsc itself supports up to STORVSC_FC_MAX_TARGETS and already passes scmnd->device->id to Hyper-V as vm_srb->target_id. Devices on Target 1 and higher work when initially discovered. They can also be rediscovered by a full host scan, such as the scan triggered after an FC port bounce. Provide a storvsc-specific user_scan callback that uses the exported scsi_scan_target() interface. Iterate over the requested channel and target ranges so that wildcard and explicitly addressed scans retain the expected SCSI sysfs scan semantics. This bypasses the single-rport lookup in fc_user_scan() and allows userspace to explicitly scan any target supported by storvsc without requiring one synthetic fc_rport for every Hyper-V target. Signed-off-by: Laurence Oberman <redacted> --- Changes in v2: - Replace the private, unexported scsi_scan_host_selected() helper with the exported scsi_scan_target() interface. - Preserve wildcard channel and target scan behavior. - Verify that storvsc_eh_timed_out() does not use the FC error-handler helpers; the reported missing-rport dereference is not present. drivers/scsi/storvsc_drv.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+)
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 571ea549152b..58b6ae96d03f 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c@@ -520,6 +520,36 @@ static void storvsc_host_scan(struct work_struct *work) scsi_scan_host(host); } +#if IS_ENABLED(CONFIG_SCSI_FC_ATTRS) +static int storvsc_user_scan(struct Scsi_Host *host, + unsigned int channel, + unsigned int id, + u64 lun) +{ + unsigned int first_channel, last_channel; + unsigned int first_id, end_id; + unsigned int ch, target; + + if ((channel != SCAN_WILD_CARD && channel > host->max_channel) || + (id != SCAN_WILD_CARD && id >= host->max_id) || + (lun != SCAN_WILD_CARD && lun >= host->max_lun)) + return -EINVAL; + + first_channel = channel == SCAN_WILD_CARD ? 0 : channel; + last_channel = channel == SCAN_WILD_CARD ? host->max_channel : channel; + first_id = id == SCAN_WILD_CARD ? 0 : id; + end_id = id == SCAN_WILD_CARD ? host->max_id : id + 1; + + for (ch = first_channel; ch <= last_channel; ch++) { + for (target = first_id; target < end_id; target++) + scsi_scan_target(&host->shost_gendev, ch, target, lun, + SCSI_SCAN_MANUAL); + } + + return 0; +} +#endif + static void storvsc_remove_lun(struct work_struct *work) { struct storvsc_scan_work *wrk;
@@ -2232,6 +2262,8 @@ static int __init storvsc_drv_init(void) fc_transport_template = fc_attach_transport(&fc_transport_functions); if (!fc_transport_template) return -ENODEV; + + fc_transport_template->user_scan = storvsc_user_scan; #endif ret = vmbus_driver_register(&storvsc_drv);
--
2.55.0