]> Git Repo - linux.git/commitdiff
block: Remember zone capacity when revalidating zones
authorDamien Le Moal <[email protected]>
Mon, 8 Apr 2024 01:41:06 +0000 (10:41 +0900)
committerJens Axboe <[email protected]>
Wed, 17 Apr 2024 14:44:02 +0000 (08:44 -0600)
In preparation for adding zone write plugging, modify
blk_revalidate_disk_zones() to get the capacity of zones of a zoned
block device. This capacity value as a number of 512B sectors is stored
in the gendisk zone_capacity field.

Given that host-managed SMR disks (including zoned UFS drives) and all
known NVMe ZNS devices have the same zone capacity for all zones
blk_revalidate_disk_zones() returns an error if different capacities are
detected for different zones.

This also adds check to verify that the values reported by the device
for zone capacities are correct, that is, that the zone capacity is
never 0, does not exceed the zone size and is equal to the zone size for
conventional zones.

Signed-off-by: Damien Le Moal <[email protected]>
Reviewed-by: Christoph Hellwig <[email protected]>
Reviewed-by: Hannes Reinecke <[email protected]>
Reviewed-by: Bart Van Assche <[email protected]>
Tested-by: Hans Holmberg <[email protected]>
Tested-by: Dennis Maisenbacher <[email protected]>
Reviewed-by: Martin K. Petersen <[email protected]>
Reviewed-by: Johannes Thumshirn <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Jens Axboe <[email protected]>
block/blk-zoned.c
include/linux/blkdev.h

index da0f4b2a8fa09330bdc71bf545ed2dc688326392..23d9bb21c45996c30932027e6a6cadd22b1a68db 100644 (file)
@@ -438,6 +438,7 @@ struct blk_revalidate_zone_args {
        unsigned long   *conv_zones_bitmap;
        unsigned long   *seq_zones_wlock;
        unsigned int    nr_zones;
+       unsigned int    zone_capacity;
        sector_t        sector;
 };
 
@@ -482,9 +483,20 @@ static int blk_revalidate_zone_cb(struct blk_zone *zone, unsigned int idx,
                return -ENODEV;
        }
 
+       if (!zone->capacity || zone->capacity > zone->len) {
+               pr_warn("%s: Invalid zone capacity\n",
+                       disk->disk_name);
+               return -ENODEV;
+       }
+
        /* Check zone type */
        switch (zone->type) {
        case BLK_ZONE_TYPE_CONVENTIONAL:
+               if (zone->capacity != zone->len) {
+                       pr_warn("%s: Invalid conventional zone capacity\n",
+                               disk->disk_name);
+                       return -ENODEV;
+               }
                if (!args->conv_zones_bitmap) {
                        args->conv_zones_bitmap =
                                blk_alloc_zone_bitmap(q->node, args->nr_zones);
@@ -500,6 +512,18 @@ static int blk_revalidate_zone_cb(struct blk_zone *zone, unsigned int idx,
                        if (!args->seq_zones_wlock)
                                return -ENOMEM;
                }
+
+               /*
+                * Remember the capacity of the first sequential zone and check
+                * if it is constant for all zones.
+                */
+               if (!args->zone_capacity)
+                       args->zone_capacity = zone->capacity;
+               if (zone->capacity != args->zone_capacity) {
+                       pr_warn("%s: Invalid variable zone capacity\n",
+                               disk->disk_name);
+                       return -ENODEV;
+               }
                break;
        case BLK_ZONE_TYPE_SEQWRITE_PREF:
        default:
@@ -595,6 +619,7 @@ int blk_revalidate_disk_zones(struct gendisk *disk,
        blk_mq_freeze_queue(q);
        if (ret > 0) {
                disk->nr_zones = args.nr_zones;
+               disk->zone_capacity = args.zone_capacity;
                swap(disk->seq_zones_wlock, args.seq_zones_wlock);
                swap(disk->conv_zones_bitmap, args.conv_zones_bitmap);
                if (update_driver_data)
@@ -608,6 +633,7 @@ int blk_revalidate_disk_zones(struct gendisk *disk,
 
        kfree(args.seq_zones_wlock);
        kfree(args.conv_zones_bitmap);
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(blk_revalidate_disk_zones);
index ec7bd7091467d4410af3d6a9966af4f04d8a2aa0..4e81f714cca75e5da6ffaf4f80a823c93d55c7f1 100644 (file)
@@ -191,6 +191,7 @@ struct gendisk {
         * blk_mq_unfreeze_queue().
         */
        unsigned int            nr_zones;
+       unsigned int            zone_capacity;
        unsigned long           *conv_zones_bitmap;
        unsigned long           *seq_zones_wlock;
 #endif /* CONFIG_BLK_DEV_ZONED */
This page took 0.079702 seconds and 4 git commands to generate.