mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2024-12-29 17:22:07 +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)
|
if (lim->max_user_sectors < PAGE_SIZE / SECTOR_SIZE)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
lim->max_sectors = min(max_hw_sectors, lim->max_user_sectors);
|
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 {
|
} else {
|
||||||
lim->max_sectors = min(max_hw_sectors, BLK_DEF_MAX_SECTORS_CAP);
|
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 = {
|
struct queue_limits lim = {
|
||||||
.max_hw_sectors = 65536,
|
.max_hw_sectors = 65536,
|
||||||
.max_user_sectors = 256,
|
.io_opt = 256 << SECTOR_SHIFT,
|
||||||
.max_segments = USHRT_MAX,
|
.max_segments = USHRT_MAX,
|
||||||
.max_segment_size = UINT_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;
|
rbd_dev->layout.object_size * rbd_dev->layout.stripe_count;
|
||||||
struct queue_limits lim = {
|
struct queue_limits lim = {
|
||||||
.max_hw_sectors = objset_bytes >> SECTOR_SHIFT,
|
.max_hw_sectors = objset_bytes >> SECTOR_SHIFT,
|
||||||
.max_user_sectors = objset_bytes >> SECTOR_SHIFT,
|
|
||||||
.io_opt = objset_bytes,
|
.io_opt = objset_bytes,
|
||||||
.io_min = rbd_dev->opts->alloc_size,
|
.io_min = rbd_dev->opts->alloc_size,
|
||||||
.max_segments = USHRT_MAX,
|
.max_segments = USHRT_MAX,
|
||||||
|
@ -3593,7 +3593,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
|
|||||||
struct request_queue *q = sdkp->disk->queue;
|
struct request_queue *q = sdkp->disk->queue;
|
||||||
sector_t old_capacity = sdkp->capacity;
|
sector_t old_capacity = sdkp->capacity;
|
||||||
unsigned char *buffer;
|
unsigned char *buffer;
|
||||||
unsigned int dev_max, rw_max;
|
unsigned int dev_max;
|
||||||
|
|
||||||
SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp,
|
SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp,
|
||||||
"sd_revalidate_disk\n"));
|
"sd_revalidate_disk\n"));
|
||||||
@ -3675,34 +3675,15 @@ static int sd_revalidate_disk(struct gendisk *disk)
|
|||||||
else
|
else
|
||||||
blk_queue_io_min(sdkp->disk->queue, 0);
|
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
|
* 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
|
* an impact on performance for when the size of a request exceeds this
|
||||||
* host limit.
|
* host limit.
|
||||||
*/
|
*/
|
||||||
rw_max = min_not_zero(rw_max, sdp->host->opt_sectors);
|
q->limits.io_opt = sdp->host->opt_sectors << SECTOR_SHIFT;
|
||||||
|
if (sd_validate_opt_xfer_size(sdkp, dev_max)) {
|
||||||
/* Do not exceed controller limit */
|
q->limits.io_opt = min_not_zero(q->limits.io_opt,
|
||||||
rw_max = min(rw_max, queue_max_hw_sectors(q));
|
logical_to_bytes(sdp, sdkp->opt_xfer_blocks));
|
||||||
|
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sdkp->first_scan = 0;
|
sdkp->first_scan = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user