Skip to content

Commit

Permalink
scsi: storvsc: Correct reporting of Hyper-V I/O size limits
Browse files Browse the repository at this point in the history
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 3d9c3dc ("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).

Link: https://lore.kernel.org/r/1655190355-28722-1-git-send-email-ssengar@linux.microsoft.com
Fixes: 3d9c3dc ("scsi: storvsc: Enable scatter list entry lengths > 4Kbytes")
Reviewed-by: Michael Kelley <mikelley@microsoft.com>
Signed-off-by: Saurabh Sengar <ssengar@linux.microsoft.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
  • Loading branch information
Saurabh Sengar authored and Martin K. Petersen committed Jun 17, 2022
1 parent 2acd76e commit 1d3e098
Showing 1 changed file with 22 additions and 5 deletions.
27 changes: 22 additions & 5 deletions drivers/scsi/storvsc_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1844,7 +1844,7 @@ static struct scsi_host_template scsi_driver = {
.cmd_per_lun = 2048,
.this_id = -1,
/* Ensure there are no gaps in presented sgls */
.virt_boundary_mask = PAGE_SIZE-1,
.virt_boundary_mask = HV_HYP_PAGE_SIZE - 1,
.no_write_same = 1,
.track_queue_depth = 1,
.change_queue_depth = storvsc_change_queue_depth,
Expand Down Expand Up @@ -1895,6 +1895,7 @@ static int storvsc_probe(struct hv_device *device,
int target = 0;
struct storvsc_device *stor_device;
int max_sub_channels = 0;
u32 max_xfer_bytes;

/*
* We support sub-channels for storage on SCSI and FC controllers.
Expand Down Expand Up @@ -1968,12 +1969,28 @@ static int storvsc_probe(struct hv_device *device,
}
/* max cmd length */
host->max_cmd_len = STORVSC_MAX_CMD_LEN;

/*
* set the table size based on the info we got
* from the host.
* Any reasonable Hyper-V configuration should provide
* max_transfer_bytes value aligning to HV_HYP_PAGE_SIZE,
* protecting it from any weird value.
*/
max_xfer_bytes = round_down(stor_device->max_transfer_bytes, HV_HYP_PAGE_SIZE);
/* max_hw_sectors_kb */
host->max_sectors = max_xfer_bytes >> 9;
/*
* There are 2 requirements for Hyper-V storvsc sgl segments,
* based on which the below calculation for max segments is
* done:
*
* 1. Except for the first and last sgl segment, all sgl segments
* should be align to HV_HYP_PAGE_SIZE, that also means the
* maximum number of segments in a sgl can be calculated by
* dividing the total max transfer length by HV_HYP_PAGE_SIZE.
*
* 2. Except for the first and last, each entry in the SGL must
* have an offset that is a multiple of HV_HYP_PAGE_SIZE.
*/
host->sg_tablesize = (stor_device->max_transfer_bytes >> PAGE_SHIFT);
host->sg_tablesize = (max_xfer_bytes >> HV_HYP_PAGE_SHIFT) + 1;
/*
* For non-IDE disks, the host supports multiple channels.
* Set the number of HW queues we are supporting.
Expand Down

0 comments on commit 1d3e098

Please sign in to comment.