diff options
author | Damien Le Moal <damien.lemoal@wdc.com> | 2018-10-12 06:08:47 -0400 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2018-10-25 13:17:40 -0400 |
commit | a2d6b3a2d39005ab4d4a83481a7db092ebf0e9d6 (patch) | |
tree | d099578f43e9d1136c792485f4231a7fe1dc71b3 | |
parent | 65e4e3eee83d7a4ad7e8c5175b2a0ddfd3b5685f (diff) |
block: Improve zone reset execution
There is no need to synchronously execute all REQ_OP_ZONE_RESET BIOs
necessary to reset a range of zones. Similarly to what is done for
discard BIOs in blk-lib.c, all zone reset BIOs can be chained and
executed asynchronously and a synchronous call done only for the last
BIO of the chain.
Modify blkdev_reset_zones() to operate similarly to
blkdev_issue_discard() using the next_bio() helper for chaining BIOs. To
avoid code duplication of that function in blk_zoned.c, rename
next_bio() into blk_next_bio() and declare it as a block internal
function in blk.h.
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r-- | block/blk-lib.c | 13 | ||||
-rw-r--r-- | block/blk-zoned.c | 29 | ||||
-rw-r--r-- | block/blk.h | 2 |
3 files changed, 24 insertions, 20 deletions
diff --git a/block/blk-lib.c b/block/blk-lib.c index bbd44666f2b5..76f867ea9a9b 100644 --- a/block/blk-lib.c +++ b/block/blk-lib.c | |||
@@ -10,8 +10,7 @@ | |||
10 | 10 | ||
11 | #include "blk.h" | 11 | #include "blk.h" |
12 | 12 | ||
13 | static struct bio *next_bio(struct bio *bio, unsigned int nr_pages, | 13 | struct bio *blk_next_bio(struct bio *bio, unsigned int nr_pages, gfp_t gfp) |
14 | gfp_t gfp) | ||
15 | { | 14 | { |
16 | struct bio *new = bio_alloc(gfp, nr_pages); | 15 | struct bio *new = bio_alloc(gfp, nr_pages); |
17 | 16 | ||
@@ -63,7 +62,7 @@ int __blkdev_issue_discard(struct block_device *bdev, sector_t sector, | |||
63 | 62 | ||
64 | end_sect = sector + req_sects; | 63 | end_sect = sector + req_sects; |
65 | 64 | ||
66 | bio = next_bio(bio, 0, gfp_mask); | 65 | bio = blk_next_bio(bio, 0, gfp_mask); |
67 | bio->bi_iter.bi_sector = sector; | 66 | bio->bi_iter.bi_sector = sector; |
68 | bio_set_dev(bio, bdev); | 67 | bio_set_dev(bio, bdev); |
69 | bio_set_op_attrs(bio, op, 0); | 68 | bio_set_op_attrs(bio, op, 0); |
@@ -165,7 +164,7 @@ static int __blkdev_issue_write_same(struct block_device *bdev, sector_t sector, | |||
165 | max_write_same_sectors = UINT_MAX >> 9; | 164 | max_write_same_sectors = UINT_MAX >> 9; |
166 | 165 | ||
167 | while (nr_sects) { | 166 | while (nr_sects) { |
168 | bio = next_bio(bio, 1, gfp_mask); | 167 | bio = blk_next_bio(bio, 1, gfp_mask); |
169 | bio->bi_iter.bi_sector = sector; | 168 | bio->bi_iter.bi_sector = sector; |
170 | bio_set_dev(bio, bdev); | 169 | bio_set_dev(bio, bdev); |
171 | bio->bi_vcnt = 1; | 170 | bio->bi_vcnt = 1; |
@@ -241,7 +240,7 @@ static int __blkdev_issue_write_zeroes(struct block_device *bdev, | |||
241 | return -EOPNOTSUPP; | 240 | return -EOPNOTSUPP; |
242 | 241 | ||
243 | while (nr_sects) { | 242 | while (nr_sects) { |
244 | bio = next_bio(bio, 0, gfp_mask); | 243 | bio = blk_next_bio(bio, 0, gfp_mask); |
245 | bio->bi_iter.bi_sector = sector; | 244 | bio->bi_iter.bi_sector = sector; |
246 | bio_set_dev(bio, bdev); | 245 | bio_set_dev(bio, bdev); |
247 | bio->bi_opf = REQ_OP_WRITE_ZEROES; | 246 | bio->bi_opf = REQ_OP_WRITE_ZEROES; |
@@ -292,8 +291,8 @@ static int __blkdev_issue_zero_pages(struct block_device *bdev, | |||
292 | return -EPERM; | 291 | return -EPERM; |
293 | 292 | ||
294 | while (nr_sects != 0) { | 293 | while (nr_sects != 0) { |
295 | bio = next_bio(bio, __blkdev_sectors_to_bio_pages(nr_sects), | 294 | bio = blk_next_bio(bio, __blkdev_sectors_to_bio_pages(nr_sects), |
296 | gfp_mask); | 295 | gfp_mask); |
297 | bio->bi_iter.bi_sector = sector; | 296 | bio->bi_iter.bi_sector = sector; |
298 | bio_set_dev(bio, bdev); | 297 | bio_set_dev(bio, bdev); |
299 | bio_set_op_attrs(bio, REQ_OP_WRITE, 0); | 298 | bio_set_op_attrs(bio, REQ_OP_WRITE, 0); |
diff --git a/block/blk-zoned.c b/block/blk-zoned.c index bb4ed69f917f..5d967fd39fbd 100644 --- a/block/blk-zoned.c +++ b/block/blk-zoned.c | |||
@@ -13,6 +13,8 @@ | |||
13 | #include <linux/rbtree.h> | 13 | #include <linux/rbtree.h> |
14 | #include <linux/blkdev.h> | 14 | #include <linux/blkdev.h> |
15 | 15 | ||
16 | #include "blk.h" | ||
17 | |||
16 | static inline sector_t blk_zone_start(struct request_queue *q, | 18 | static inline sector_t blk_zone_start(struct request_queue *q, |
17 | sector_t sector) | 19 | sector_t sector) |
18 | { | 20 | { |
@@ -277,16 +279,17 @@ int blkdev_reset_zones(struct block_device *bdev, | |||
277 | struct request_queue *q = bdev_get_queue(bdev); | 279 | struct request_queue *q = bdev_get_queue(bdev); |
278 | sector_t zone_sectors; | 280 | sector_t zone_sectors; |
279 | sector_t end_sector = sector + nr_sectors; | 281 | sector_t end_sector = sector + nr_sectors; |
280 | struct bio *bio; | 282 | struct bio *bio = NULL; |
283 | struct blk_plug plug; | ||
281 | int ret; | 284 | int ret; |
282 | 285 | ||
283 | if (!q) | ||
284 | return -ENXIO; | ||
285 | |||
286 | if (!blk_queue_is_zoned(q)) | 286 | if (!blk_queue_is_zoned(q)) |
287 | return -EOPNOTSUPP; | 287 | return -EOPNOTSUPP; |
288 | 288 | ||
289 | if (end_sector > bdev->bd_part->nr_sects) | 289 | if (bdev_read_only(bdev)) |
290 | return -EPERM; | ||
291 | |||
292 | if (!nr_sectors || end_sector > bdev->bd_part->nr_sects) | ||
290 | /* Out of range */ | 293 | /* Out of range */ |
291 | return -EINVAL; | 294 | return -EINVAL; |
292 | 295 | ||
@@ -299,19 +302,14 @@ int blkdev_reset_zones(struct block_device *bdev, | |||
299 | end_sector != bdev->bd_part->nr_sects) | 302 | end_sector != bdev->bd_part->nr_sects) |
300 | return -EINVAL; | 303 | return -EINVAL; |
301 | 304 | ||
305 | blk_start_plug(&plug); | ||
302 | while (sector < end_sector) { | 306 | while (sector < end_sector) { |
303 | 307 | ||
304 | bio = bio_alloc(gfp_mask, 0); | 308 | bio = blk_next_bio(bio, 0, gfp_mask); |
305 | bio->bi_iter.bi_sector = sector; | 309 | bio->bi_iter.bi_sector = sector; |
306 | bio_set_dev(bio, bdev); | 310 | bio_set_dev(bio, bdev); |
307 | bio_set_op_attrs(bio, REQ_OP_ZONE_RESET, 0); | 311 | bio_set_op_attrs(bio, REQ_OP_ZONE_RESET, 0); |
308 | 312 | ||
309 | ret = submit_bio_wait(bio); | ||
310 | bio_put(bio); | ||
311 | |||
312 | if (ret) | ||
313 | return ret; | ||
314 | |||
315 | sector += zone_sectors; | 313 | sector += zone_sectors; |
316 | 314 | ||
317 | /* This may take a while, so be nice to others */ | 315 | /* This may take a while, so be nice to others */ |
@@ -319,7 +317,12 @@ int blkdev_reset_zones(struct block_device *bdev, | |||
319 | 317 | ||
320 | } | 318 | } |
321 | 319 | ||
322 | return 0; | 320 | ret = submit_bio_wait(bio); |
321 | bio_put(bio); | ||
322 | |||
323 | blk_finish_plug(&plug); | ||
324 | |||
325 | return ret; | ||
323 | } | 326 | } |
324 | EXPORT_SYMBOL_GPL(blkdev_reset_zones); | 327 | EXPORT_SYMBOL_GPL(blkdev_reset_zones); |
325 | 328 | ||
diff --git a/block/blk.h b/block/blk.h index 3d2aecba96a4..93574baaa6b8 100644 --- a/block/blk.h +++ b/block/blk.h | |||
@@ -488,4 +488,6 @@ extern int blk_iolatency_init(struct request_queue *q); | |||
488 | static inline int blk_iolatency_init(struct request_queue *q) { return 0; } | 488 | static inline int blk_iolatency_init(struct request_queue *q) { return 0; } |
489 | #endif | 489 | #endif |
490 | 490 | ||
491 | struct bio *blk_next_bio(struct bio *bio, unsigned int nr_pages, gfp_t gfp); | ||
492 | |||
491 | #endif /* BLK_INTERNAL_H */ | 493 | #endif /* BLK_INTERNAL_H */ |