aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorChaitanya Kulkarni <chaitanya.kulkarni@wdc.com>2019-08-01 13:26:36 -0400
committerJens Axboe <axboe@kernel.dk>2019-08-04 23:41:29 -0400
commit6e33dbf280d60db8c1c11dbf99c0bc475946f9c8 (patch)
tree94c560cca9c4f000b07bdb21ec45b7a759778feb /block
parente84e8f0663956f45c747df5629046794cff93893 (diff)
blk-zoned: implement REQ_OP_ZONE_RESET_ALL
This implements REQ_OP_ZONE_RESET_ALL as a special case of the block device zone reset operations where we just simply issue bio with the newly introduced req op. We issue this req op when the number of sectors is equal to the device's partition's number of sectors and device has no partitions. We also add support so that blk_op_str() can print the new reset-all zone operation. This patch also adds a generic make request check for newly introduced REQ_OP_ZONE_RESET_ALL req_opf. We simply return error when queue is zoned and reset-all flag is not set for REQ_OP_ZONE_RESET_ALL. Reviewed-by: Hannes Reinecke <hare@suse.com> Reviewed-by: Damien Le Moal <damien.lemoal@wdc.com> Signed-off-by: Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block')
-rw-r--r--block/blk-core.c5
-rw-r--r--block/blk-zoned.c39
2 files changed, 44 insertions, 0 deletions
diff --git a/block/blk-core.c b/block/blk-core.c
index 5878504a29af..919629ce4015 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -129,6 +129,7 @@ static const char *const blk_op_name[] = {
129 REQ_OP_NAME(DISCARD), 129 REQ_OP_NAME(DISCARD),
130 REQ_OP_NAME(SECURE_ERASE), 130 REQ_OP_NAME(SECURE_ERASE),
131 REQ_OP_NAME(ZONE_RESET), 131 REQ_OP_NAME(ZONE_RESET),
132 REQ_OP_NAME(ZONE_RESET_ALL),
132 REQ_OP_NAME(WRITE_SAME), 133 REQ_OP_NAME(WRITE_SAME),
133 REQ_OP_NAME(WRITE_ZEROES), 134 REQ_OP_NAME(WRITE_ZEROES),
134 REQ_OP_NAME(SCSI_IN), 135 REQ_OP_NAME(SCSI_IN),
@@ -932,6 +933,10 @@ generic_make_request_checks(struct bio *bio)
932 if (!blk_queue_is_zoned(q)) 933 if (!blk_queue_is_zoned(q))
933 goto not_supported; 934 goto not_supported;
934 break; 935 break;
936 case REQ_OP_ZONE_RESET_ALL:
937 if (!blk_queue_is_zoned(q) || !blk_queue_zone_resetall(q))
938 goto not_supported;
939 break;
935 case REQ_OP_WRITE_ZEROES: 940 case REQ_OP_WRITE_ZEROES:
936 if (!q->limits.max_write_zeroes_sectors) 941 if (!q->limits.max_write_zeroes_sectors)
937 goto not_supported; 942 goto not_supported;
diff --git a/block/blk-zoned.c b/block/blk-zoned.c
index 6c503824ba3f..4bc5f260248a 100644
--- a/block/blk-zoned.c
+++ b/block/blk-zoned.c
@@ -202,6 +202,42 @@ int blkdev_report_zones(struct block_device *bdev, sector_t sector,
202} 202}
203EXPORT_SYMBOL_GPL(blkdev_report_zones); 203EXPORT_SYMBOL_GPL(blkdev_report_zones);
204 204
205/*
206 * Special case of zone reset operation to reset all zones in one command,
207 * useful for applications like mkfs.
208 */
209static int __blkdev_reset_all_zones(struct block_device *bdev, gfp_t gfp_mask)
210{
211 struct bio *bio = bio_alloc(gfp_mask, 0);
212 int ret;
213
214 /* across the zones operations, don't need any sectors */
215 bio_set_dev(bio, bdev);
216 bio_set_op_attrs(bio, REQ_OP_ZONE_RESET_ALL, 0);
217
218 ret = submit_bio_wait(bio);
219 bio_put(bio);
220
221 return ret;
222}
223
224static inline bool blkdev_allow_reset_all_zones(struct block_device *bdev,
225 sector_t nr_sectors)
226{
227 if (!blk_queue_zone_resetall(bdev_get_queue(bdev)))
228 return false;
229
230 if (nr_sectors != part_nr_sects_read(bdev->bd_part))
231 return false;
232 /*
233 * REQ_OP_ZONE_RESET_ALL can be executed only if the block device is
234 * the entire disk, that is, if the blocks device start offset is 0 and
235 * its capacity is the same as the entire disk.
236 */
237 return get_start_sect(bdev) == 0 &&
238 part_nr_sects_read(bdev->bd_part) == get_capacity(bdev->bd_disk);
239}
240
205/** 241/**
206 * blkdev_reset_zones - Reset zones write pointer 242 * blkdev_reset_zones - Reset zones write pointer
207 * @bdev: Target block device 243 * @bdev: Target block device
@@ -235,6 +271,9 @@ int blkdev_reset_zones(struct block_device *bdev,
235 /* Out of range */ 271 /* Out of range */
236 return -EINVAL; 272 return -EINVAL;
237 273
274 if (blkdev_allow_reset_all_zones(bdev, nr_sectors))
275 return __blkdev_reset_all_zones(bdev, gfp_mask);
276
238 /* Check alignment (handle eventual smaller last zone) */ 277 /* Check alignment (handle eventual smaller last zone) */
239 zone_sectors = blk_queue_zone_sectors(q); 278 zone_sectors = blk_queue_zone_sectors(q);
240 if (sector & (zone_sectors - 1)) 279 if (sector & (zone_sectors - 1))