Skip to content

Commit 51fdaa0

Browse files
damien-lemoalmartinkpetersen
authored andcommitted
scsi: sd_sbc: Fix sd_zbc_report_zones()
The block layer generic blk_revalidate_disk_zones() checks the validity of zone descriptors reported by a disk using the blk_revalidate_zone_cb() callback function executed for each zone descriptor. If a ZBC disk reports invalid zone descriptors, blk_revalidate_disk_zones() returns an error and sd_zbc_read_zones() changes the disk capacity to 0, which in turn results in the gendisk structure capacity to be set to 0. This all works well for the first revalidate pass on a disk and the block layer detects the capactiy change. On the second revalidate pass, blk_revalidate_disk_zones() is called again and sd_zbc_report_zones() executed to check the zones a second time. However, for this second pass, the gendisk capacity is now 0, which results in sd_zbc_report_zones() to do nothing and to report success and no zones. blk_revalidate_disk_zones() in turn returns success and sets the disk queue chunk_sectors limit with zero as no zones were checked, causing a oops to trigger on the BUG_ON(!is_power_of_2(chunk_sectors)) in blk_queue_chunk_sectors(). Fix this by using the sdkp capacity field rather than the gendisk capacity for the report zones loop in sd_zbc_report_zones(). Also add a check to return immediately an error if the sdkp capacity is 0. With this fix, invalid/buggy ZBC disk scan does not trigger a oops and are exposed with a 0 capacity. This change also preserve the chance for the disk to be correctly revalidated on the second revalidate pass as the scsi disk structure capacity field is always set to the disk reported value when sd_zbc_report_zones() is called. Link: https://lore.kernel.org/r/[email protected] Fixes: d410035 ("block: rework zone reporting") Cc: Cc: <[email protected]> # v5.5 Reviewed-by: Christoph Hellwig <[email protected]> Reviewed-by: Johannes Thumshirn <[email protected]> Signed-off-by: Damien Le Moal <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent ff6993b commit 51fdaa0

File tree

1 file changed

+6
-1
lines changed

1 file changed

+6
-1
lines changed

drivers/scsi/sd_zbc.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ int sd_zbc_report_zones(struct gendisk *disk, sector_t sector,
161161
unsigned int nr_zones, report_zones_cb cb, void *data)
162162
{
163163
struct scsi_disk *sdkp = scsi_disk(disk);
164+
sector_t capacity = logical_to_sectors(sdkp->device, sdkp->capacity);
164165
unsigned int nr, i;
165166
unsigned char *buf;
166167
size_t offset, buflen = 0;
@@ -171,11 +172,15 @@ int sd_zbc_report_zones(struct gendisk *disk, sector_t sector,
171172
/* Not a zoned device */
172173
return -EOPNOTSUPP;
173174

175+
if (!capacity)
176+
/* Device gone or invalid */
177+
return -ENODEV;
178+
174179
buf = sd_zbc_alloc_report_buffer(sdkp, nr_zones, &buflen);
175180
if (!buf)
176181
return -ENOMEM;
177182

178-
while (zone_idx < nr_zones && sector < get_capacity(disk)) {
183+
while (zone_idx < nr_zones && sector < capacity) {
179184
ret = sd_zbc_do_report_zones(sdkp, buf, buflen,
180185
sectors_to_logical(sdkp->device, sector), true);
181186
if (ret)

0 commit comments

Comments
 (0)