Commit 946dd71e authored by Damien Le Moal's avatar Damien Le Moal Committed by Jens Axboe

block: Allow BIO-based drivers to use blk_revalidate_disk_zones()

In preparation for allowing BIO based device drivers to use zone write
plugging and its zone append emulation, allow these drivers to call
blk_revalidate_disk_zones() so that all zone resources necessary to zone
write plugging can be initialized.

To do so, remove the check in blk_revalidate_disk_zones() restricting
the use of this function to mq request-based drivers to allow also
BIO-based drivers to use it. This is safe to do as long as the
BIO-based block device queue is already setup and usable, as it should,
and can be safely frozen.

The helper function disk_need_zone_resources() is added to control the
allocation and initialization of the zone write plug hash table and
of the conventional zone bitmap only for mq devices and for BIO-based
devices that require zone append emulation.
Signed-off-by: default avatarDamien Le Moal <dlemoal@kernel.org>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarHannes Reinecke <hare@suse.de>
Reviewed-by: default avatarBart Van Assche <bvanassche@acm.org>
Tested-by: default avatarHans Holmberg <hans.holmberg@wdc.com>
Tested-by: default avatarDennis Maisenbacher <dennis.maisenbacher@wdc.com>
Reviewed-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
Link: https://lore.kernel.org/r/20240408014128.205141-12-dlemoal@kernel.orgSigned-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 9b1ce7f0
...@@ -1512,12 +1512,28 @@ void disk_free_zone_resources(struct gendisk *disk) ...@@ -1512,12 +1512,28 @@ void disk_free_zone_resources(struct gendisk *disk)
disk->nr_zones = 0; disk->nr_zones = 0;
} }
static inline bool disk_need_zone_resources(struct gendisk *disk)
{
/*
* All mq zoned devices need zone resources so that the block layer
* can automatically handle write BIO plugging. BIO-based device drivers
* (e.g. DM devices) are normally responsible for handling zone write
* ordering and do not need zone resources, unless the driver requires
* zone append emulation.
*/
return queue_is_mq(disk->queue) ||
queue_emulates_zone_append(disk->queue);
}
static int disk_revalidate_zone_resources(struct gendisk *disk, static int disk_revalidate_zone_resources(struct gendisk *disk,
unsigned int nr_zones) unsigned int nr_zones)
{ {
struct queue_limits *lim = &disk->queue->limits; struct queue_limits *lim = &disk->queue->limits;
unsigned int pool_size; unsigned int pool_size;
if (!disk_need_zone_resources(disk))
return 0;
/* /*
* If the device has no limit on the maximum number of open and active * If the device has no limit on the maximum number of open and active
* zones, use BLK_ZONE_WPLUG_DEFAULT_POOL_SIZE. * zones, use BLK_ZONE_WPLUG_DEFAULT_POOL_SIZE.
...@@ -1635,6 +1651,9 @@ static int blk_revalidate_zone_cb(struct blk_zone *zone, unsigned int idx, ...@@ -1635,6 +1651,9 @@ static int blk_revalidate_zone_cb(struct blk_zone *zone, unsigned int idx,
disk->disk_name); disk->disk_name);
return -ENODEV; return -ENODEV;
} }
if (!disk_need_zone_resources(disk))
break;
if (!args->conv_zones_bitmap) { if (!args->conv_zones_bitmap) {
args->conv_zones_bitmap = args->conv_zones_bitmap =
blk_alloc_zone_bitmap(q->node, args->nr_zones); blk_alloc_zone_bitmap(q->node, args->nr_zones);
...@@ -1666,10 +1685,11 @@ static int blk_revalidate_zone_cb(struct blk_zone *zone, unsigned int idx, ...@@ -1666,10 +1685,11 @@ static int blk_revalidate_zone_cb(struct blk_zone *zone, unsigned int idx,
/* /*
* We need to track the write pointer of all zones that are not * We need to track the write pointer of all zones that are not
* empty nor full. So make sure we have a zone write plug for * empty nor full. So make sure we have a zone write plug for
* such zone. * such zone if the device has a zone write plug hash table.
*/ */
wp_offset = blk_zone_wp_offset(zone); wp_offset = blk_zone_wp_offset(zone);
if (wp_offset && wp_offset < zone_sectors) { if (disk->zone_wplugs_hash &&
wp_offset && wp_offset < zone_sectors) {
zwplug = disk_get_and_lock_zone_wplug(disk, zone->start, zwplug = disk_get_and_lock_zone_wplug(disk, zone->start,
GFP_NOIO, &flags); GFP_NOIO, &flags);
if (!zwplug) if (!zwplug)
...@@ -1700,8 +1720,8 @@ static int blk_revalidate_zone_cb(struct blk_zone *zone, unsigned int idx, ...@@ -1700,8 +1720,8 @@ static int blk_revalidate_zone_cb(struct blk_zone *zone, unsigned int idx,
* be called within the disk ->revalidate method for blk-mq based drivers. * be called within the disk ->revalidate method for blk-mq based drivers.
* Before calling this function, the device driver must already have set the * Before calling this function, the device driver must already have set the
* device zone size (chunk_sector limit) and the max zone append limit. * device zone size (chunk_sector limit) and the max zone append limit.
* For BIO based drivers, this function cannot be used. BIO based device drivers * BIO based drivers can also use this function as long as the device queue
* only need to set disk->nr_zones so that the sysfs exposed value is correct. * can be safely frozen.
* If the @update_driver_data callback function is not NULL, the callback is * If the @update_driver_data callback function is not NULL, the callback is
* executed with the device request queue frozen after all zones have been * executed with the device request queue frozen after all zones have been
* checked. * checked.
...@@ -1718,8 +1738,6 @@ int blk_revalidate_disk_zones(struct gendisk *disk, ...@@ -1718,8 +1738,6 @@ int blk_revalidate_disk_zones(struct gendisk *disk,
if (WARN_ON_ONCE(!blk_queue_is_zoned(q))) if (WARN_ON_ONCE(!blk_queue_is_zoned(q)))
return -EIO; return -EIO;
if (WARN_ON_ONCE(!queue_is_mq(q)))
return -EIO;
if (!capacity) if (!capacity)
return -ENODEV; return -ENODEV;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment