mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 21:21:41 +00:00
block: take io_opt and io_min into account for max_sectors
The soft max_sectors limit is normally capped by the hardware limits and an arbitrary upper limit enforced by the kernel, but can be modified by the user. A few drivers want to increase this limit (nbd, rbd) or adjust it up or down based on hardware capabilities (sd). Change blk_validate_limits to default max_sectors to the optimal I/O size, or upgrade it to the preferred minimal I/O size if that is larger than the kernel default if no optimal I/O size is provided based on the logic in the SD driver. This keeps the existing kernel default for drivers that do not provide an io_opt or very big io_min value, but picks a much more useful default for those who provide these hints, and allows to remove the hacks to set the user max_sectors limit in nbd, rbd and sd. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Bart Van Assche <bvanassche@acm.org> Reviewed-by: Damien Le Moal <dlemoal@kernel.org> Acked-by: Ilya Dryomov <idryomov@gmail.com> Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com> Link: https://lore.kernel.org/r/20240531074837.1648501-5-hch@lst.de Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
a00d4bfce7
commit
a23634644a
@ -153,6 +153,13 @@ static int blk_validate_limits(struct queue_limits *lim)
|
||||
if (lim->max_user_sectors < PAGE_SIZE / SECTOR_SIZE)
|
||||
return -EINVAL;
|
||||
lim->max_sectors = min(max_hw_sectors, lim->max_user_sectors);
|
||||
} else if (lim->io_opt) {
|
||||
lim->max_sectors =
|
||||
min(max_hw_sectors, lim->io_opt >> SECTOR_SHIFT);
|
||||
} else if (lim->io_min &&
|
||||
lim->io_min > (BLK_DEF_MAX_SECTORS_CAP << SECTOR_SHIFT)) {
|
||||
lim->max_sectors =
|
||||
min(max_hw_sectors, lim->io_min >> SECTOR_SHIFT);
|
||||
} else {
|
||||
lim->max_sectors = min(max_hw_sectors, BLK_DEF_MAX_SECTORS_CAP);
|
||||
}
|
||||
|
@ -1808,7 +1808,7 @@ static struct nbd_device *nbd_dev_add(int index, unsigned int refs)
|
||||
{
|
||||
struct queue_limits lim = {
|
||||
.max_hw_sectors = 65536,
|
||||
.max_user_sectors = 256,
|
||||
.io_opt = 256 << SECTOR_SHIFT,
|
||||
.max_segments = USHRT_MAX,
|
||||
.max_segment_size = UINT_MAX,
|
||||
};
|
||||
|
@ -4954,7 +4954,6 @@ static int rbd_init_disk(struct rbd_device *rbd_dev)
|
||||
rbd_dev->layout.object_size * rbd_dev->layout.stripe_count;
|
||||
struct queue_limits lim = {
|
||||
.max_hw_sectors = objset_bytes >> SECTOR_SHIFT,
|
||||
.max_user_sectors = objset_bytes >> SECTOR_SHIFT,
|
||||
.io_opt = objset_bytes,
|
||||
.io_min = rbd_dev->opts->alloc_size,
|
||||
.max_segments = USHRT_MAX,
|
||||
|
@ -3593,7 +3593,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
|
||||
struct request_queue *q = sdkp->disk->queue;
|
||||
sector_t old_capacity = sdkp->capacity;
|
||||
unsigned char *buffer;
|
||||
unsigned int dev_max, rw_max;
|
||||
unsigned int dev_max;
|
||||
|
||||
SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp,
|
||||
"sd_revalidate_disk\n"));
|
||||
@ -3675,34 +3675,15 @@ static int sd_revalidate_disk(struct gendisk *disk)
|
||||
else
|
||||
blk_queue_io_min(sdkp->disk->queue, 0);
|
||||
|
||||
if (sd_validate_opt_xfer_size(sdkp, dev_max)) {
|
||||
q->limits.io_opt = logical_to_bytes(sdp, sdkp->opt_xfer_blocks);
|
||||
rw_max = logical_to_sectors(sdp, sdkp->opt_xfer_blocks);
|
||||
} else {
|
||||
q->limits.io_opt = 0;
|
||||
rw_max = min_not_zero(logical_to_sectors(sdp, dev_max),
|
||||
(sector_t)BLK_DEF_MAX_SECTORS_CAP);
|
||||
}
|
||||
|
||||
/*
|
||||
* Limit default to SCSI host optimal sector limit if set. There may be
|
||||
* an impact on performance for when the size of a request exceeds this
|
||||
* host limit.
|
||||
*/
|
||||
rw_max = min_not_zero(rw_max, sdp->host->opt_sectors);
|
||||
|
||||
/* Do not exceed controller limit */
|
||||
rw_max = min(rw_max, queue_max_hw_sectors(q));
|
||||
|
||||
/*
|
||||
* Only update max_sectors if previously unset or if the current value
|
||||
* exceeds the capabilities of the hardware.
|
||||
*/
|
||||
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 = rw_max;
|
||||
q->limits.max_user_sectors = rw_max;
|
||||
q->limits.io_opt = sdp->host->opt_sectors << SECTOR_SHIFT;
|
||||
if (sd_validate_opt_xfer_size(sdkp, dev_max)) {
|
||||
q->limits.io_opt = min_not_zero(q->limits.io_opt,
|
||||
logical_to_bytes(sdp, sdkp->opt_xfer_blocks));
|
||||
}
|
||||
|
||||
sdkp->first_scan = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user