Skip to content

Commit

Permalink
scsi: sd: sd_zbc: Fix ZBC disk initialization
Browse files Browse the repository at this point in the history
Make sure to call sd_zbc_init_disk() when the sdkp->zoned field is known,
that is, once sd_read_block_characteristics() is executed in
sd_revalidate_disk(), so that host-aware disks also get initialized.  To do
so, move sd_zbc_init_disk() call in sd_zbc_revalidate_zones() and make sure
to execute it for all zoned disks, including for host-aware disks used as
regular disks as these disk zoned model may be changed back to BLK_ZONED_HA
when partitions are deleted.

Link: https://lore.kernel.org/r/[email protected]
Fixes: 5795eb4 ("scsi: sd_zbc: emulate ZONE_APPEND commands")
Cc: <[email protected]> # v5.8+
Reported-by: Borislav Petkov <[email protected]>
Tested-by: Borislav Petkov <[email protected]>
Reviewed-by: Johannes Thumshirn <[email protected]>
Reviewed-by: Christoph Hellwig <[email protected]>
Signed-off-by: Damien Le Moal <[email protected]>
Signed-off-by: Martin K. Petersen <[email protected]>
  • Loading branch information
damien-lemoal authored and martinkpetersen committed Sep 16, 2020
1 parent 27ba3e8 commit 6c5dee1
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 35 deletions.
4 changes: 0 additions & 4 deletions drivers/scsi/sd.c
Original file line number Diff line number Diff line change
Expand Up @@ -3410,10 +3410,6 @@ static int sd_probe(struct device *dev)
sdkp->first_scan = 1;
sdkp->max_medium_access_timeouts = SD_MAX_MEDIUM_TIMEOUTS;

error = sd_zbc_init_disk(sdkp);
if (error)
goto out_free_index;

sd_revalidate_disk(gd);

gd->flags = GENHD_FL_EXT_DEVT;
Expand Down
6 changes: 0 additions & 6 deletions drivers/scsi/sd.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,6 @@ static inline int sd_is_zoned(struct scsi_disk *sdkp)

#ifdef CONFIG_BLK_DEV_ZONED

int sd_zbc_init_disk(struct scsi_disk *sdkp);
void sd_zbc_release_disk(struct scsi_disk *sdkp);
int sd_zbc_read_zones(struct scsi_disk *sdkp, unsigned char *buffer);
int sd_zbc_revalidate_zones(struct scsi_disk *sdkp);
Expand All @@ -231,11 +230,6 @@ blk_status_t sd_zbc_prepare_zone_append(struct scsi_cmnd *cmd, sector_t *lba,

#else /* CONFIG_BLK_DEV_ZONED */

static inline int sd_zbc_init_disk(struct scsi_disk *sdkp)
{
return 0;
}

static inline void sd_zbc_release_disk(struct scsi_disk *sdkp) {}

static inline int sd_zbc_read_zones(struct scsi_disk *sdkp,
Expand Down
60 changes: 35 additions & 25 deletions drivers/scsi/sd_zbc.c
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,28 @@ static void sd_zbc_print_zones(struct scsi_disk *sdkp)
sdkp->zone_blocks);
}

static int sd_zbc_init_disk(struct scsi_disk *sdkp)
{
sdkp->zones_wp_offset = NULL;
spin_lock_init(&sdkp->zones_wp_offset_lock);
sdkp->rev_wp_offset = NULL;
mutex_init(&sdkp->rev_mutex);
INIT_WORK(&sdkp->zone_wp_offset_work, sd_zbc_update_wp_offset_workfn);
sdkp->zone_wp_update_buf = kzalloc(SD_BUF_SIZE, GFP_KERNEL);
if (!sdkp->zone_wp_update_buf)
return -ENOMEM;

return 0;
}

void sd_zbc_release_disk(struct scsi_disk *sdkp)
{
kvfree(sdkp->zones_wp_offset);
sdkp->zones_wp_offset = NULL;
kfree(sdkp->zone_wp_update_buf);
sdkp->zone_wp_update_buf = NULL;
}

static void sd_zbc_revalidate_zones_cb(struct gendisk *disk)
{
struct scsi_disk *sdkp = scsi_disk(disk);
Expand All @@ -667,6 +689,19 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp)
u32 max_append;
int ret = 0;

/*
* For all zoned disks, initialize zone append emulation data if not
* already done. This is necessary also for host-aware disks used as
* regular disks due to the presence of partitions as these partitions
* may be deleted and the disk zoned model changed back from
* BLK_ZONED_NONE to BLK_ZONED_HA.
*/
if (sd_is_zoned(sdkp) && !sdkp->zone_wp_update_buf) {
ret = sd_zbc_init_disk(sdkp);
if (ret)
return ret;
}

/*
* There is nothing to do for regular disks, including host-aware disks
* that have partitions.
Expand Down Expand Up @@ -768,28 +803,3 @@ int sd_zbc_read_zones(struct scsi_disk *sdkp, unsigned char *buf)

return ret;
}

int sd_zbc_init_disk(struct scsi_disk *sdkp)
{
if (!sd_is_zoned(sdkp))
return 0;

sdkp->zones_wp_offset = NULL;
spin_lock_init(&sdkp->zones_wp_offset_lock);
sdkp->rev_wp_offset = NULL;
mutex_init(&sdkp->rev_mutex);
INIT_WORK(&sdkp->zone_wp_offset_work, sd_zbc_update_wp_offset_workfn);
sdkp->zone_wp_update_buf = kzalloc(SD_BUF_SIZE, GFP_KERNEL);
if (!sdkp->zone_wp_update_buf)
return -ENOMEM;

return 0;
}

void sd_zbc_release_disk(struct scsi_disk *sdkp)
{
kvfree(sdkp->zones_wp_offset);
sdkp->zones_wp_offset = NULL;
kfree(sdkp->zone_wp_update_buf);
sdkp->zone_wp_update_buf = NULL;
}

0 comments on commit 6c5dee1

Please sign in to comment.