[v4,04/10] block: Modify revalidate zones
diff mbox series

Message ID 20200403101250.33245-5-johannes.thumshirn@wdc.com
State New
Headers show
Series
  • Introduce Zone Append for writing to zoned block devices
Related show

Commit Message

Johannes Thumshirn April 3, 2020, 10:12 a.m. UTC
From: Damien Le Moal <damien.lemoal@wdc.com>

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@wdc.com>
---
 block/blk-zoned.c      | 38 +++++++++++++++++++++++++++-----------
 include/linux/blkdev.h | 11 ++++++++++-
 2 files changed, 37 insertions(+), 12 deletions(-)

Patch
diff mbox series

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);