From: Damien Le Moal <damien.lemoal@xxxxxxx> Modify the interface of blk_revalidate_disk_zones() to add an optional revalidation callback function that a driver can use to extend checks and processing done during zone revalidation. The callback, if defined, is executed once for each zone inspected and a final time after all zones are inspected. blk_revalidate_disk_zones() is renamed as __blk_revalidate_disk_zones() and blk_revalidate_disk_zones() implemented as an inline function calling __blk_revalidate_disk_zones() without no revalidation callback specified, resulting in an unchanged behavior for all callers of blk_revalidate_disk_zones(). Signed-off-by: Damien Le Moal <damien.lemoal@xxxxxxx> --- block/blk-zoned.c | 38 +++++++++++++++++++++++++++----------- include/linux/blkdev.h | 11 ++++++++++- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/block/blk-zoned.c b/block/blk-zoned.c index 00b025b8b7c0..a5fed0fa1504 100644 --- a/block/blk-zoned.c +++ b/block/blk-zoned.c @@ -353,12 +353,14 @@ void blk_queue_free_zone_bitmaps(struct request_queue *q) } struct blk_revalidate_zone_args { - struct gendisk *disk; - unsigned long *conv_zones_bitmap; - unsigned long *seq_zones_wlock; - unsigned int nr_zones; - sector_t zone_sectors; - sector_t sector; + struct gendisk *disk; + revalidate_zones_cb revalidate_cb; + void *revalidate_data; + unsigned long *conv_zones_bitmap; + unsigned long *seq_zones_wlock; + unsigned int nr_zones; + sector_t zone_sectors; + sector_t sector; }; /* @@ -432,25 +434,37 @@ static int blk_revalidate_zone_cb(struct blk_zone *zone, unsigned int idx, return -ENODEV; } + if (args->revalidate_cb) + args->revalidate_cb(zone, idx, args->revalidate_data); + args->sector += zone->len; return 0; } /** - * blk_revalidate_disk_zones - (re)allocate and initialize zone bitmaps - * @disk: Target disk + * __blk_revalidate_disk_zones - (re)allocate and initialize zone bitmaps + * @disk: Target disk + * @revalidate_cb: LLD callback + * @revalidate_data: LLD callback argument * * Helper function for low-level device drivers to (re) allocate and initialize * a disk request queue zone bitmaps. This functions should normally be called * within the disk ->revalidate method for blk-mq based drivers. For BIO based * drivers only q->nr_zones needs to be updated so that the sysfs exposed value * is correct. + * If driver @revalidate_cb callback function is not NULL, the callback will be + * executed for each zone inspected as well as a final time to apply changes + * under with the device request queue frozen. */ -int blk_revalidate_disk_zones(struct gendisk *disk) +int __blk_revalidate_disk_zones(struct gendisk *disk, + revalidate_zones_cb revalidate_cb, + void *revalidate_data) { struct request_queue *q = disk->queue; struct blk_revalidate_zone_args args = { - .disk = disk, + .disk = disk, + .revalidate_cb = revalidate_cb, + .revalidate_data = revalidate_data, }; unsigned int noio_flag; int ret; @@ -480,6 +494,8 @@ int blk_revalidate_disk_zones(struct gendisk *disk) q->nr_zones = args.nr_zones; swap(q->seq_zones_wlock, args.seq_zones_wlock); swap(q->conv_zones_bitmap, args.conv_zones_bitmap); + if (revalidate_cb) + revalidate_cb(NULL, 0, revalidate_data); ret = 0; } else { pr_warn("%s: failed to revalidate zones\n", disk->disk_name); @@ -491,4 +507,4 @@ int blk_revalidate_disk_zones(struct gendisk *disk) kfree(args.conv_zones_bitmap); return ret; } -EXPORT_SYMBOL_GPL(blk_revalidate_disk_zones); +EXPORT_SYMBOL_GPL(__blk_revalidate_disk_zones); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index e591b22ace03..49f41562b3f9 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -353,6 +353,9 @@ struct queue_limits { typedef int (*report_zones_cb)(struct blk_zone *zone, unsigned int idx, void *data); +typedef void (*revalidate_zones_cb)(struct blk_zone *zone, unsigned int idx, + void *data); + #ifdef CONFIG_BLK_DEV_ZONED #define BLK_ALL_ZONES ((unsigned int)-1) @@ -362,7 +365,13 @@ unsigned int blkdev_nr_zones(struct gendisk *disk); extern int blkdev_zone_mgmt(struct block_device *bdev, enum req_opf op, sector_t sectors, sector_t nr_sectors, gfp_t gfp_mask); -extern int blk_revalidate_disk_zones(struct gendisk *disk); +int __blk_revalidate_disk_zones(struct gendisk *disk, + revalidate_zones_cb revalidate_cb, + void *revalidate_data); +static inline int blk_revalidate_disk_zones(struct gendisk *disk) +{ + return __blk_revalidate_disk_zones(disk, NULL, NULL); +} extern int blkdev_report_zones_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg); -- 2.24.1