Commit 628617be authored by Bart Van Assche's avatar Bart Van Assche Committed by Martin K. Petersen

scsi: sd: sd_zbc: Introduce struct zoned_disk_info

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.orgReviewed-by: default avatarDamien Le Moal <damien.lemoal@opensource.wdc.com>
Reviewed-by: default avatarHimanshu Madhani <himanshu.madhani@oracle.com>
Acked-by: default avatarDouglas Gilbert <dgilbert@interlog.com>
Signed-off-by: default avatarBart Van Assche <bvanassche@acm.org>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 43af5da0
...@@ -67,6 +67,20 @@ enum { ...@@ -67,6 +67,20 @@ enum {
SD_ZERO_WS10_UNMAP, /* Use WRITE SAME(10) with UNMAP */ 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_disk {
struct scsi_device *device; struct scsi_device *device;
...@@ -78,10 +92,10 @@ struct scsi_disk { ...@@ -78,10 +92,10 @@ struct scsi_disk {
struct gendisk *disk; struct gendisk *disk;
struct opal_dev *opal_dev; struct opal_dev *opal_dev;
#ifdef CONFIG_BLK_DEV_ZONED #ifdef CONFIG_BLK_DEV_ZONED
u32 nr_zones; /* Updated during revalidation before the gendisk capacity is known. */
u32 rev_nr_zones; struct zoned_disk_info early_zone_info;
u32 zone_blocks; /* Updated during revalidation after the gendisk capacity is known. */
u32 rev_zone_blocks; struct zoned_disk_info zone_info;
u32 zones_optimal_open; u32 zones_optimal_open;
u32 zones_optimal_nonseq; u32 zones_optimal_nonseq;
u32 zones_max_open; u32 zones_max_open;
......
...@@ -181,7 +181,7 @@ static void *sd_zbc_alloc_report_buffer(struct scsi_disk *sdkp, ...@@ -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 * sure that the allocated buffer can always be mapped by limiting the
* number of pages allocated to the HBA max segments limit. * 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 = roundup((nr_zones + 1) * 64, SECTOR_SIZE);
bufsize = min_t(size_t, bufsize, bufsize = min_t(size_t, bufsize,
queue_max_hw_sectors(q) << SECTOR_SHIFT); queue_max_hw_sectors(q) << SECTOR_SHIFT);
...@@ -206,7 +206,7 @@ static void *sd_zbc_alloc_report_buffer(struct scsi_disk *sdkp, ...@@ -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) 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, ...@@ -262,7 +262,7 @@ int sd_zbc_report_zones(struct gendisk *disk, sector_t sector,
zone_idx++; zone_idx++;
} }
lba += sdkp->zone_blocks * i; lba += sdkp->zone_info.zone_blocks * i;
} }
ret = zone_idx; ret = zone_idx;
...@@ -320,14 +320,14 @@ static void sd_zbc_update_wp_offset_workfn(struct work_struct *work) ...@@ -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); sdkp = container_of(work, struct scsi_disk, zone_wp_offset_work);
spin_lock_irqsave(&sdkp->zones_wp_offset_lock, flags); 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) if (sdkp->zones_wp_offset[zno] != SD_ZBC_UPDATING_WP_OFST)
continue; continue;
spin_unlock_irqrestore(&sdkp->zones_wp_offset_lock, flags); spin_unlock_irqrestore(&sdkp->zones_wp_offset_lock, flags);
ret = sd_zbc_do_report_zones(sdkp, sdkp->zone_wp_update_buf, ret = sd_zbc_do_report_zones(sdkp, sdkp->zone_wp_update_buf,
SD_BUF_SIZE, SD_BUF_SIZE,
zno * sdkp->zone_blocks, true); zno * sdkp->zone_info.zone_blocks, true);
spin_lock_irqsave(&sdkp->zones_wp_offset_lock, flags); spin_lock_irqsave(&sdkp->zones_wp_offset_lock, flags);
if (!ret) if (!ret)
sd_zbc_parse_report(sdkp, sdkp->zone_wp_update_buf + 64, 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, ...@@ -394,7 +394,7 @@ blk_status_t sd_zbc_prepare_zone_append(struct scsi_cmnd *cmd, sector_t *lba,
break; break;
default: default:
wp_offset = sectors_to_logical(sdkp->device, wp_offset); 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; ret = BLK_STS_IOERR;
break; break;
} }
...@@ -523,7 +523,7 @@ static unsigned int sd_zbc_zone_wp_update(struct scsi_cmnd *cmd, ...@@ -523,7 +523,7 @@ static unsigned int sd_zbc_zone_wp_update(struct scsi_cmnd *cmd,
break; break;
case REQ_OP_ZONE_RESET_ALL: case REQ_OP_ZONE_RESET_ALL:
memset(sdkp->zones_wp_offset, 0, memset(sdkp->zones_wp_offset, 0,
sdkp->nr_zones * sizeof(unsigned int)); sdkp->zone_info.nr_zones * sizeof(unsigned int));
break; break;
default: default:
break; break;
...@@ -680,16 +680,16 @@ static void sd_zbc_print_zones(struct scsi_disk *sdkp) ...@@ -680,16 +680,16 @@ static void sd_zbc_print_zones(struct scsi_disk *sdkp)
if (!sd_is_zoned(sdkp) || !sdkp->capacity) if (!sd_is_zoned(sdkp) || !sdkp->capacity)
return; return;
if (sdkp->capacity & (sdkp->zone_blocks - 1)) if (sdkp->capacity & (sdkp->zone_info.zone_blocks - 1))
sd_printk(KERN_NOTICE, sdkp, sd_printk(KERN_NOTICE, sdkp,
"%u zones of %u logical blocks + 1 runt zone\n", "%u zones of %u logical blocks + 1 runt zone\n",
sdkp->nr_zones - 1, sdkp->zone_info.nr_zones - 1,
sdkp->zone_blocks); sdkp->zone_info.zone_blocks);
else else
sd_printk(KERN_NOTICE, sdkp, sd_printk(KERN_NOTICE, sdkp,
"%u zones of %u logical blocks\n", "%u zones of %u logical blocks\n",
sdkp->nr_zones, sdkp->zone_info.nr_zones,
sdkp->zone_blocks); sdkp->zone_info.zone_blocks);
} }
static int sd_zbc_init_disk(struct scsi_disk *sdkp) 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) ...@@ -716,10 +716,8 @@ static void sd_zbc_clear_zone_info(struct scsi_disk *sdkp)
kfree(sdkp->zone_wp_update_buf); kfree(sdkp->zone_wp_update_buf);
sdkp->zone_wp_update_buf = NULL; sdkp->zone_wp_update_buf = NULL;
sdkp->nr_zones = 0; sdkp->early_zone_info = (struct zoned_disk_info){ };
sdkp->rev_nr_zones = 0; sdkp->zone_info = (struct zoned_disk_info){ };
sdkp->zone_blocks = 0;
sdkp->rev_zone_blocks = 0;
mutex_unlock(&sdkp->rev_mutex); mutex_unlock(&sdkp->rev_mutex);
} }
...@@ -746,8 +744,8 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp) ...@@ -746,8 +744,8 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp)
{ {
struct gendisk *disk = sdkp->disk; struct gendisk *disk = sdkp->disk;
struct request_queue *q = disk->queue; struct request_queue *q = disk->queue;
u32 zone_blocks = sdkp->rev_zone_blocks; u32 zone_blocks = sdkp->early_zone_info.zone_blocks;
unsigned int nr_zones = sdkp->rev_nr_zones; unsigned int nr_zones = sdkp->early_zone_info.nr_zones;
u32 max_append; u32 max_append;
int ret = 0; int ret = 0;
unsigned int flags; unsigned int flags;
...@@ -778,14 +776,14 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp) ...@@ -778,14 +776,14 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp)
*/ */
mutex_lock(&sdkp->rev_mutex); mutex_lock(&sdkp->rev_mutex);
if (sdkp->zone_blocks == zone_blocks && if (sdkp->zone_info.zone_blocks == zone_blocks &&
sdkp->nr_zones == nr_zones && sdkp->zone_info.nr_zones == nr_zones &&
disk->queue->nr_zones == nr_zones) disk->queue->nr_zones == nr_zones)
goto unlock; goto unlock;
flags = memalloc_noio_save(); flags = memalloc_noio_save();
sdkp->zone_blocks = zone_blocks; sdkp->zone_info.zone_blocks = zone_blocks;
sdkp->nr_zones = nr_zones; sdkp->zone_info.nr_zones = nr_zones;
sdkp->rev_wp_offset = kvcalloc(nr_zones, sizeof(u32), GFP_KERNEL); sdkp->rev_wp_offset = kvcalloc(nr_zones, sizeof(u32), GFP_KERNEL);
if (!sdkp->rev_wp_offset) { if (!sdkp->rev_wp_offset) {
ret = -ENOMEM; ret = -ENOMEM;
...@@ -800,8 +798,7 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp) ...@@ -800,8 +798,7 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp)
sdkp->rev_wp_offset = NULL; sdkp->rev_wp_offset = NULL;
if (ret) { if (ret) {
sdkp->zone_blocks = 0; sdkp->zone_info = (struct zoned_disk_info){ };
sdkp->nr_zones = 0;
sdkp->capacity = 0; sdkp->capacity = 0;
goto unlock; goto unlock;
} }
...@@ -887,8 +884,8 @@ int sd_zbc_read_zones(struct scsi_disk *sdkp, u8 buf[SD_BUF_SIZE]) ...@@ -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) if (blk_queue_zoned_model(q) == BLK_ZONED_HM)
blk_queue_zone_write_granularity(q, sdkp->physical_block_size); blk_queue_zone_write_granularity(q, sdkp->physical_block_size);
sdkp->rev_nr_zones = nr_zones; sdkp->early_zone_info.nr_zones = nr_zones;
sdkp->rev_zone_blocks = zone_blocks; sdkp->early_zone_info.zone_blocks = zone_blocks;
return 0; return 0;
......
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