diff options
author | Mike Snitzer <snitzer@redhat.com> | 2015-08-18 10:31:09 -0400 |
---|---|---|
committer | Mike Snitzer <snitzer@redhat.com> | 2015-08-18 11:36:11 -0400 |
commit | 84f8bd86cc8977c344df572169f7ec10b8188cfa (patch) | |
tree | 4b6ee470a653ac073289e8b333d479a383a85a74 | |
parent | 76c44f6d80e151d230844db7ffc058ac21b9e3f2 (diff) |
dm thin: optimize async discard submission
__blkdev_issue_discard_async() doesn't need to worry about further
splitting because the upper layer blkdev_issue_discard() will have
already handled splitting bios such that the bi_size isn't
overflowed.
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Acked-by: Joe Thornber <ejt@redhat.com>
-rw-r--r-- | drivers/md/dm-thin.c | 89 |
1 files changed, 15 insertions, 74 deletions
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index d2bbe8cc1e97..49e358a0c22f 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c | |||
@@ -332,9 +332,6 @@ struct thin_c { | |||
332 | * | 332 | * |
333 | * Description: | 333 | * Description: |
334 | * Asynchronously issue a discard request for the sectors in question. | 334 | * Asynchronously issue a discard request for the sectors in question. |
335 | * NOTE: this variant of blk-core's blkdev_issue_discard() is a stop-gap | ||
336 | * that is being kept local to DM thinp until the block changes to allow | ||
337 | * late bio splitting land upstream. | ||
338 | */ | 335 | */ |
339 | static int __blkdev_issue_discard_async(struct block_device *bdev, sector_t sector, | 336 | static int __blkdev_issue_discard_async(struct block_device *bdev, sector_t sector, |
340 | sector_t nr_sects, gfp_t gfp_mask, unsigned long flags, | 337 | sector_t nr_sects, gfp_t gfp_mask, unsigned long flags, |
@@ -342,91 +339,36 @@ static int __blkdev_issue_discard_async(struct block_device *bdev, sector_t sect | |||
342 | { | 339 | { |
343 | struct request_queue *q = bdev_get_queue(bdev); | 340 | struct request_queue *q = bdev_get_queue(bdev); |
344 | int type = REQ_WRITE | REQ_DISCARD; | 341 | int type = REQ_WRITE | REQ_DISCARD; |
345 | unsigned int max_discard_sectors, granularity; | ||
346 | int alignment; | ||
347 | struct bio *bio; | 342 | struct bio *bio; |
348 | int ret = 0; | ||
349 | struct blk_plug plug; | ||
350 | 343 | ||
351 | if (!q) | 344 | if (!q || !nr_sects) |
352 | return -ENXIO; | 345 | return -ENXIO; |
353 | 346 | ||
354 | if (!blk_queue_discard(q)) | 347 | if (!blk_queue_discard(q)) |
355 | return -EOPNOTSUPP; | 348 | return -EOPNOTSUPP; |
356 | 349 | ||
357 | /* Zero-sector (unknown) and one-sector granularities are the same. */ | ||
358 | granularity = max(q->limits.discard_granularity >> 9, 1U); | ||
359 | alignment = (bdev_discard_alignment(bdev) >> 9) % granularity; | ||
360 | |||
361 | /* | ||
362 | * Ensure that max_discard_sectors is of the proper | ||
363 | * granularity, so that requests stay aligned after a split. | ||
364 | */ | ||
365 | max_discard_sectors = min(q->limits.max_discard_sectors, UINT_MAX >> 9); | ||
366 | max_discard_sectors -= max_discard_sectors % granularity; | ||
367 | if (unlikely(!max_discard_sectors)) { | ||
368 | /* Avoid infinite loop below. Being cautious never hurts. */ | ||
369 | return -EOPNOTSUPP; | ||
370 | } | ||
371 | |||
372 | if (flags & BLKDEV_DISCARD_SECURE) { | 350 | if (flags & BLKDEV_DISCARD_SECURE) { |
373 | if (!blk_queue_secdiscard(q)) | 351 | if (!blk_queue_secdiscard(q)) |
374 | return -EOPNOTSUPP; | 352 | return -EOPNOTSUPP; |
375 | type |= REQ_SECURE; | 353 | type |= REQ_SECURE; |
376 | } | 354 | } |
377 | 355 | ||
378 | blk_start_plug(&plug); | 356 | /* |
379 | while (nr_sects) { | 357 | * Required bio_put occurs in bio_endio thanks to bio_chain below |
380 | unsigned int req_sects; | 358 | */ |
381 | sector_t end_sect, tmp; | 359 | bio = bio_alloc(gfp_mask, 1); |
382 | 360 | if (!bio) | |
383 | /* | 361 | return -ENOMEM; |
384 | * Required bio_put occurs in bio_endio thanks to bio_chain below | ||
385 | */ | ||
386 | bio = bio_alloc(gfp_mask, 1); | ||
387 | if (!bio) { | ||
388 | ret = -ENOMEM; | ||
389 | break; | ||
390 | } | ||
391 | |||
392 | req_sects = min_t(sector_t, nr_sects, max_discard_sectors); | ||
393 | |||
394 | /* | ||
395 | * If splitting a request, and the next starting sector would be | ||
396 | * misaligned, stop the discard at the previous aligned sector. | ||
397 | */ | ||
398 | end_sect = sector + req_sects; | ||
399 | tmp = end_sect; | ||
400 | if (req_sects < nr_sects && | ||
401 | sector_div(tmp, granularity) != alignment) { | ||
402 | end_sect = end_sect - alignment; | ||
403 | sector_div(end_sect, granularity); | ||
404 | end_sect = end_sect * granularity + alignment; | ||
405 | req_sects = end_sect - sector; | ||
406 | } | ||
407 | |||
408 | bio_chain(bio, parent_bio); | ||
409 | |||
410 | bio->bi_iter.bi_sector = sector; | ||
411 | bio->bi_bdev = bdev; | ||
412 | 362 | ||
413 | bio->bi_iter.bi_size = req_sects << 9; | 363 | bio_chain(bio, parent_bio); |
414 | nr_sects -= req_sects; | ||
415 | sector = end_sect; | ||
416 | 364 | ||
417 | submit_bio(type, bio); | 365 | bio->bi_iter.bi_sector = sector; |
366 | bio->bi_bdev = bdev; | ||
367 | bio->bi_iter.bi_size = nr_sects << 9; | ||
418 | 368 | ||
419 | /* | 369 | submit_bio(type, bio); |
420 | * We can loop for a long time in here, if someone does | ||
421 | * full device discards (like mkfs). Be nice and allow | ||
422 | * us to schedule out to avoid softlocking if preempt | ||
423 | * is disabled. | ||
424 | */ | ||
425 | cond_resched(); | ||
426 | } | ||
427 | blk_finish_plug(&plug); | ||
428 | 370 | ||
429 | return ret; | 371 | return 0; |
430 | } | 372 | } |
431 | 373 | ||
432 | static bool block_size_is_power_of_two(struct pool *pool) | 374 | static bool block_size_is_power_of_two(struct pool *pool) |
@@ -1539,9 +1481,8 @@ static void process_discard_cell_no_passdown(struct thin_c *tc, | |||
1539 | } | 1481 | } |
1540 | 1482 | ||
1541 | /* | 1483 | /* |
1542 | * FIXME: DM local hack to defer parent bios's end_io until we | 1484 | * __bio_inc_remaining() is used to defer parent bios's end_io until |
1543 | * _know_ all chained sub range discard bios have completed. | 1485 | * we _know_ all chained sub range discard bios have completed. |
1544 | * Will go away once late bio splitting lands upstream! | ||
1545 | */ | 1486 | */ |
1546 | static inline void __bio_inc_remaining(struct bio *bio) | 1487 | static inline void __bio_inc_remaining(struct bio *bio) |
1547 | { | 1488 | { |