Message ID | 20240523182618.602003-2-hch@lst.de (mailing list archive) |
---|---|
State | Not Applicable |
Headers | show |
Series | [1/2] sd: also set max_user_sectors when setting max_sectors | expand |
Christoph, > sd can set a max_sectors value that is lower than the max_hw_sectors > limit based on the block limits VPD page. While this is rather > unusual, It's not particularly unusual. Virtually all arrays have a much smaller stripe or cache line size than what the average HBA can handle in one transfer. Using the device's preferred I/O size to configure max_sectors made a substantial difference performance-wise. > it used to work until the max_user_sectors field was split out to > cleanly deal with conflicting hardware and user limits when the > hardware limit changes. Also set max_user_sectors to ensure the limit > can properly be stacked. Fine for a quick fix. Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
On Thu, May 23, 2024 at 02:53:40PM -0400, Martin K. Petersen wrote: > > Christoph, > > > sd can set a max_sectors value that is lower than the max_hw_sectors > > limit based on the block limits VPD page. While this is rather > > unusual, > > It's not particularly unusual. Virtually all arrays have a much smaller > stripe or cache line size than what the average HBA can handle in one > transfer. Using the device's preferred I/O size to configure max_sectors > made a substantial difference performance-wise. Well, in terms of Linux it is weird in that drivers weren't ever supposed to set max_sectors directly but only provide max_hw_sectors (although nbd also decreases it and rbd increases it in odd ways). Especially as we already have an opt_in limit for the optimal size. I'll find a way to sort it out and build a grand unified and somewhat coherent theory out of it..
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 332eb9dac22d91..f6c822c9cbd2d3 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -3700,8 +3700,10 @@ static int sd_revalidate_disk(struct gendisk *disk) */ if (sdkp->first_scan || q->limits.max_sectors > q->limits.max_dev_sectors || - q->limits.max_sectors > q->limits.max_hw_sectors) + q->limits.max_sectors > q->limits.max_hw_sectors) { q->limits.max_sectors = rw_max; + q->limits.max_user_sectors = rw_max; + } sdkp->first_scan = 0;