diff options
author | Christoph Hellwig <hch@lst.de> | 2019-11-11 03:39:30 +0100 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2019-11-13 03:12:07 +0100 |
commit | d41003513e61dd9d4974cb441d30b63650b85654 (patch) | |
tree | c55164e7ccf02f6e7e936757ed178b06109fcca2 /drivers/block | |
parent | scsi: sd_zbc: Cleanup sd_zbc_alloc_report_buffer() (diff) | |
download | linux-d41003513e61dd9d4974cb441d30b63650b85654.tar.xz linux-d41003513e61dd9d4974cb441d30b63650b85654.zip |
block: rework zone reporting
Avoid the need to allocate a potentially large array of struct blk_zone
in the block layer by switching the ->report_zones method interface to
a callback model. Now the caller simply supplies a callback that is
executed on each reported zone, and private data for it.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Mike Snitzer <snitzer@redhat.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/null_blk.h | 2 | ||||
-rw-r--r-- | drivers/block/null_blk_zoned.c | 31 |
2 files changed, 23 insertions, 10 deletions
diff --git a/drivers/block/null_blk.h b/drivers/block/null_blk.h index 9bf56fbab091..bc837862b767 100644 --- a/drivers/block/null_blk.h +++ b/drivers/block/null_blk.h @@ -92,7 +92,7 @@ struct nullb { int null_zone_init(struct nullb_device *dev); void null_zone_exit(struct nullb_device *dev); int null_report_zones(struct gendisk *disk, sector_t sector, - struct blk_zone *zones, unsigned int *nr_zones); + unsigned int nr_zones, report_zones_cb cb, void *data); blk_status_t null_handle_zoned(struct nullb_cmd *cmd, enum req_opf op, sector_t sector, sector_t nr_sectors); diff --git a/drivers/block/null_blk_zoned.c b/drivers/block/null_blk_zoned.c index 00696f16664b..d4d88b581822 100644 --- a/drivers/block/null_blk_zoned.c +++ b/drivers/block/null_blk_zoned.c @@ -67,21 +67,34 @@ void null_zone_exit(struct nullb_device *dev) } int null_report_zones(struct gendisk *disk, sector_t sector, - struct blk_zone *zones, unsigned int *nr_zones) + unsigned int nr_zones, report_zones_cb cb, void *data) { struct nullb *nullb = disk->private_data; struct nullb_device *dev = nullb->dev; - unsigned int zno, nrz = 0; + unsigned int first_zone, i; + struct blk_zone zone; + int error; - zno = null_zone_no(dev, sector); - if (zno < dev->nr_zones) { - nrz = min_t(unsigned int, *nr_zones, dev->nr_zones - zno); - memcpy(zones, &dev->zones[zno], nrz * sizeof(struct blk_zone)); - } + first_zone = null_zone_no(dev, sector); + if (first_zone >= dev->nr_zones) + return 0; - *nr_zones = nrz; + nr_zones = min(nr_zones, dev->nr_zones - first_zone); + for (i = 0; i < nr_zones; i++) { + /* + * Stacked DM target drivers will remap the zone information by + * modifying the zone information passed to the report callback. + * So use a local copy to avoid corruption of the device zone + * array. + */ + memcpy(&zone, &dev->zones[first_zone + i], + sizeof(struct blk_zone)); + error = cb(&zone, i, data); + if (error) + return error; + } - return 0; + return nr_zones; } size_t null_zone_valid_read_len(struct nullb *nullb, |