Current code is based on the idea that the max number of SGL entries also determines the max size of an I/O request. While this idea was true in older versions of the storvsc driver when SGL entry length was limited to 4 Kbytes, commit 3d9c3dcc58e9 ("scsi: storvsc: Enable scatterlist entry lengths > 4Kbytes") removed that limitation. It's now theoretically possible for the block layer to send requests that exceed the maximum size supported by Hyper-V. This problem doesn't currently happen in practice because the block layer defaults to a 512 Kbyte maximum, while Hyper-V in Azure supports 2 Mbyte I/O sizes. But some future configuration of Hyper-V could have a smaller max I/O size, and the block layer could exceed that max. Fix this by correctly setting max_sectors as well as sg_tablesize to reflect the maximum I/O size that Hyper-V reports. While allowing I/O sizes larger than the block layer default of 512 Kbytes doesn’t provide any noticeable performance benefit in the tests we ran, it's still appropriate to report the correct underlying Hyper-V capabilities to the Linux block layer. Also tweak the virt_boundary_mask to reflect that the required alignment derives from Hyper-V communication using a 4 Kbyte page size, and not on the guest page size, which might be bigger (eg. ARM64).
Unified · Split
| @@ -1844,7 +1844,7 @@ static struct scsi_host_template scsi_driver = { · 1843 unmodified lines | |||
| 1844 | .cmd_per_lun = 2048, | 1844 | .cmd_per_lun = 2048, |
| 1845 | .this_id = -1, | 1845 | .this_id = -1, |
| 1846 | /* Ensure there are no gaps in presented sgls */ | 1846 | /* Ensure there are no gaps in presented sgls */ |
| 1847 | .virt_boundary_mask = PAGE_SIZE-1, | 1847 | .virt_boundary_mask = HV_HYP_PAGE_SIZE - 1, |
| 1848 | .no_write_same = 1, | 1848 | .no_write_same = 1, |
| 1849 | .track_queue_depth = 1, | 1849 | .track_queue_depth = 1, |
| 1850 | .change_queue_depth = storvsc_change_queue_depth, | 1850 | .change_queue_depth = storvsc_change_queue_depth, |
| @@ -1895,6 +1895,7 @@ static int storvsc_probe(struct hv_device *device, · 44 unmodified lines | |||
| 1895 | int target = 0; | 1895 | int target = 0; |
| 1896 | struct storvsc_device *stor_device; | 1896 | struct storvsc_device *stor_device; |
| 1897 | int max_sub_channels = 0; | 1897 | int max_sub_channels = 0; |
| 1898 | u32 max_xfer_bytes; | ||
| 1898 | 1899 | ||
| 1899 | /* | 1900 | /* |
| 1900 | * We support sub-channels for storage on SCSI and FC controllers. | 1901 | * We support sub-channels for storage on SCSI and FC controllers. |
| @@ -1968,12 +1969,28 @@ static int storvsc_probe(struct hv_device *device, · 67 unmodified lines | |||
| 1968 | } | 1969 | } |
| 1969 | /* max cmd length */ | 1970 | /* max cmd length */ |
| 1970 | host->max_cmd_len = STORVSC_MAX_CMD_LEN; | 1971 | host->max_cmd_len = STORVSC_MAX_CMD_LEN; |
| 1971 | |||
| 1972 | /* | 1972 | /* |
| 1973 | * set the table size based on the info we got | 1973 | * Any reasonable Hyper-V configuration should provide |
| 1974 | * from the host. | 1974 | * max_transfer_bytes value aligning to HV_HYP_PAGE_SIZE, |
| 1975 | * protecting it from any weird value. | ||
| 1976 | */ | ||
| 1977 | max_xfer_bytes = round_down(stor_device->max_transfer_bytes, HV_HYP_PAGE_SIZE); | ||
| 1978 | /* max_hw_sectors_kb */ | ||
| 1979 | host->max_sectors = max_xfer_bytes >> 9; | ||
| 1980 | /* | ||
| 1981 | * There are 2 requirements for Hyper-V storvsc sgl segments, | ||
| 1982 | * based on which the below calculation for max segments is | ||
| 1983 | * done: | ||
| 1984 | * | ||
| 1985 | * 1. Except for the first and last sgl segment, all sgl segments | ||
| 1986 | * should be align to HV_HYP_PAGE_SIZE, that also means the | ||
| 1987 | * maximum number of segments in a sgl can be calculated by | ||
| 1988 | * dividing the total max transfer length by HV_HYP_PAGE_SIZE. | ||
| 1989 | * | ||
| 1990 | * 2. Except for the first and last, each entry in the SGL must | ||
| 1991 | * have an offset that is a multiple of HV_HYP_PAGE_SIZE. | ||
| 1975 | */ | 1992 | */ |
| 1976 | host->sg_tablesize = (stor_device->max_transfer_bytes >> PAGE_SHIFT); | 1993 | host->sg_tablesize = (max_xfer_bytes >> HV_HYP_PAGE_SHIFT) + 1; |
| 1977 | /* | 1994 | /* |
| 1978 | * For non-IDE disks, the host supports multiple channels. | 1995 | * For non-IDE disks, the host supports multiple channels. |
| 1979 | * Set the number of HW queues we are supporting. | 1996 | * Set the number of HW queues we are supporting. |