OSDN Git Service

scsi: sd: sd_zbc: Introduce struct zoned_disk_info
authorBart Van Assche <bvanassche@acm.org>
Thu, 21 Apr 2022 18:30:18 +0000 (11:30 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 26 Apr 2022 03:23:04 +0000 (23:23 -0400)
Deriving the meaning of the nr_zones, rev_nr_zones, zone_blocks and
rev_zone_blocks member variables requires careful analysis of the source
code. Make the meaning of these member variables easier to understand by
introducing struct zoned_disk_info.

Link: https://lore.kernel.org/r/20220421183023.3462291-5-bvanassche@acm.org
Reviewed-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Acked-by: Douglas Gilbert <dgilbert@interlog.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/sd.h
drivers/scsi/sd_zbc.c

index 4849cbe..47434f9 100644 (file)
@@ -67,6 +67,20 @@ enum {
        SD_ZERO_WS10_UNMAP,     /* Use WRITE SAME(10) with UNMAP */
 };
 
+/**
+ * struct zoned_disk_info - Specific properties of a ZBC SCSI device.
+ * @nr_zones: number of zones.
+ * @zone_blocks: number of logical blocks per zone.
+ *
+ * This data structure holds the ZBC SCSI device properties that are retrieved
+ * twice: a first time before the gendisk capacity is known and a second time
+ * after the gendisk capacity is known.
+ */
+struct zoned_disk_info {
+       u32             nr_zones;
+       u32             zone_blocks;
+};
+
 struct scsi_disk {
        struct scsi_device *device;
 
@@ -78,10 +92,10 @@ struct scsi_disk {
        struct gendisk  *disk;
        struct opal_dev *opal_dev;
 #ifdef CONFIG_BLK_DEV_ZONED
-       u32             nr_zones;
-       u32             rev_nr_zones;
-       u32             zone_blocks;
-       u32             rev_zone_blocks;
+       /* Updated during revalidation before the gendisk capacity is known. */
+       struct zoned_disk_info  early_zone_info;
+       /* Updated during revalidation after the gendisk capacity is known. */
+       struct zoned_disk_info  zone_info;
        u32             zones_optimal_open;
        u32             zones_optimal_nonseq;
        u32             zones_max_open;
index e76bcbf..ac557a5 100644 (file)
@@ -181,7 +181,7 @@ static void *sd_zbc_alloc_report_buffer(struct scsi_disk *sdkp,
         * sure that the allocated buffer can always be mapped by limiting the
         * number of pages allocated to the HBA max segments limit.
         */
-       nr_zones = min(nr_zones, sdkp->nr_zones);
+       nr_zones = min(nr_zones, sdkp->zone_info.nr_zones);
        bufsize = roundup((nr_zones + 1) * 64, SECTOR_SIZE);
        bufsize = min_t(size_t, bufsize,
                        queue_max_hw_sectors(q) << SECTOR_SHIFT);
@@ -206,7 +206,7 @@ static void *sd_zbc_alloc_report_buffer(struct scsi_disk *sdkp,
  */
 static inline sector_t sd_zbc_zone_sectors(struct scsi_disk *sdkp)
 {
-       return logical_to_sectors(sdkp->device, sdkp->zone_blocks);
+       return logical_to_sectors(sdkp->device, sdkp->zone_info.zone_blocks);
 }
 
 /**
@@ -262,7 +262,7 @@ int sd_zbc_report_zones(struct gendisk *disk, sector_t sector,
                        zone_idx++;
                }
 
-               lba += sdkp->zone_blocks * i;
+               lba += sdkp->zone_info.zone_blocks * i;
        }
 
        ret = zone_idx;
@@ -320,14 +320,14 @@ static void sd_zbc_update_wp_offset_workfn(struct work_struct *work)
        sdkp = container_of(work, struct scsi_disk, zone_wp_offset_work);
 
        spin_lock_irqsave(&sdkp->zones_wp_offset_lock, flags);
-       for (zno = 0; zno < sdkp->nr_zones; zno++) {
+       for (zno = 0; zno < sdkp->zone_info.nr_zones; zno++) {
                if (sdkp->zones_wp_offset[zno] != SD_ZBC_UPDATING_WP_OFST)
                        continue;
 
                spin_unlock_irqrestore(&sdkp->zones_wp_offset_lock, flags);
                ret = sd_zbc_do_report_zones(sdkp, sdkp->zone_wp_update_buf,
                                             SD_BUF_SIZE,
-                                            zno * sdkp->zone_blocks, true);
+                                            zno * sdkp->zone_info.zone_blocks, true);
                spin_lock_irqsave(&sdkp->zones_wp_offset_lock, flags);
                if (!ret)
                        sd_zbc_parse_report(sdkp, sdkp->zone_wp_update_buf + 64,
@@ -394,7 +394,7 @@ blk_status_t sd_zbc_prepare_zone_append(struct scsi_cmnd *cmd, sector_t *lba,
                break;
        default:
                wp_offset = sectors_to_logical(sdkp->device, wp_offset);
-               if (wp_offset + nr_blocks > sdkp->zone_blocks) {
+               if (wp_offset + nr_blocks > sdkp->zone_info.zone_blocks) {
                        ret = BLK_STS_IOERR;
                        break;
                }
@@ -523,7 +523,7 @@ static unsigned int sd_zbc_zone_wp_update(struct scsi_cmnd *cmd,
                break;
        case REQ_OP_ZONE_RESET_ALL:
                memset(sdkp->zones_wp_offset, 0,
-                      sdkp->nr_zones * sizeof(unsigned int));
+                      sdkp->zone_info.nr_zones * sizeof(unsigned int));
                break;
        default:
                break;
@@ -680,16 +680,16 @@ static void sd_zbc_print_zones(struct scsi_disk *sdkp)
        if (!sd_is_zoned(sdkp) || !sdkp->capacity)
                return;
 
-       if (sdkp->capacity & (sdkp->zone_blocks - 1))
+       if (sdkp->capacity & (sdkp->zone_info.zone_blocks - 1))
                sd_printk(KERN_NOTICE, sdkp,
                          "%u zones of %u logical blocks + 1 runt zone\n",
-                         sdkp->nr_zones - 1,
-                         sdkp->zone_blocks);
+                         sdkp->zone_info.nr_zones - 1,
+                         sdkp->zone_info.zone_blocks);
        else
                sd_printk(KERN_NOTICE, sdkp,
                          "%u zones of %u logical blocks\n",
-                         sdkp->nr_zones,
-                         sdkp->zone_blocks);
+                         sdkp->zone_info.nr_zones,
+                         sdkp->zone_info.zone_blocks);
 }
 
 static int sd_zbc_init_disk(struct scsi_disk *sdkp)
@@ -716,10 +716,8 @@ static void sd_zbc_clear_zone_info(struct scsi_disk *sdkp)
        kfree(sdkp->zone_wp_update_buf);
        sdkp->zone_wp_update_buf = NULL;
 
-       sdkp->nr_zones = 0;
-       sdkp->rev_nr_zones = 0;
-       sdkp->zone_blocks = 0;
-       sdkp->rev_zone_blocks = 0;
+       sdkp->early_zone_info = (struct zoned_disk_info){ };
+       sdkp->zone_info = (struct zoned_disk_info){ };
 
        mutex_unlock(&sdkp->rev_mutex);
 }
@@ -746,8 +744,8 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp)
 {
        struct gendisk *disk = sdkp->disk;
        struct request_queue *q = disk->queue;
-       u32 zone_blocks = sdkp->rev_zone_blocks;
-       unsigned int nr_zones = sdkp->rev_nr_zones;
+       u32 zone_blocks = sdkp->early_zone_info.zone_blocks;
+       unsigned int nr_zones = sdkp->early_zone_info.nr_zones;
        u32 max_append;
        int ret = 0;
        unsigned int flags;
@@ -778,14 +776,14 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp)
         */
        mutex_lock(&sdkp->rev_mutex);
 
-       if (sdkp->zone_blocks == zone_blocks &&
-           sdkp->nr_zones == nr_zones &&
+       if (sdkp->zone_info.zone_blocks == zone_blocks &&
+           sdkp->zone_info.nr_zones == nr_zones &&
            disk->queue->nr_zones == nr_zones)
                goto unlock;
 
        flags = memalloc_noio_save();
-       sdkp->zone_blocks = zone_blocks;
-       sdkp->nr_zones = nr_zones;
+       sdkp->zone_info.zone_blocks = zone_blocks;
+       sdkp->zone_info.nr_zones = nr_zones;
        sdkp->rev_wp_offset = kvcalloc(nr_zones, sizeof(u32), GFP_KERNEL);
        if (!sdkp->rev_wp_offset) {
                ret = -ENOMEM;
@@ -800,8 +798,7 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp)
        sdkp->rev_wp_offset = NULL;
 
        if (ret) {
-               sdkp->zone_blocks = 0;
-               sdkp->nr_zones = 0;
+               sdkp->zone_info = (struct zoned_disk_info){ };
                sdkp->capacity = 0;
                goto unlock;
        }
@@ -887,8 +884,8 @@ int sd_zbc_read_zones(struct scsi_disk *sdkp, u8 buf[SD_BUF_SIZE])
        if (blk_queue_zoned_model(q) == BLK_ZONED_HM)
                blk_queue_zone_write_granularity(q, sdkp->physical_block_size);
 
-       sdkp->rev_nr_zones = nr_zones;
-       sdkp->rev_zone_blocks = zone_blocks;
+       sdkp->early_zone_info.nr_zones = nr_zones;
+       sdkp->early_zone_info.zone_blocks = zone_blocks;
 
        return 0;