This factors the guts of __blkdev_issue_discard into a helper that can be used by callers avoid the fatal_signal_pending check and to generally simplify the bio handling. Signed-off-by: Christoph Hellwig <hch@xxxxxx> --- block/blk-lib.c | 41 ++++++++++++++++++++++++----------------- include/linux/blkdev.h | 2 ++ 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/block/blk-lib.c b/block/blk-lib.c index 50923508a32466..4f2d52210b129c 100644 --- a/block/blk-lib.c +++ b/block/blk-lib.c @@ -55,28 +55,35 @@ static void await_bio_chain(struct bio *bio) blk_wait_io(&done); } +bool blk_next_discard_bio(struct block_device *bdev, struct bio **biop, + sector_t *sector, sector_t *nr_sects, gfp_t gfp_mask) +{ + sector_t bio_sects = min(*nr_sects, bio_discard_limit(bdev, *sector)); + + if (!bio_sects) + return false; + + *biop = blk_next_bio(*biop, bdev, 0, REQ_OP_DISCARD, gfp_mask); + (*biop)->bi_iter.bi_sector = *sector; + (*biop)->bi_iter.bi_size = bio_sects << SECTOR_SHIFT; + *sector += bio_sects; + *nr_sects -= bio_sects; + /* + * We can loop for a long time in here if someone does full device + * discards (like mkfs). Be nice and allow us to schedule out to avoid + * softlocking if preempt is disabled. + */ + cond_resched(); + return true; +} +EXPORT_SYMBOL_GPL(blk_next_discard_bio); + int __blkdev_issue_discard(struct block_device *bdev, sector_t sector, sector_t nr_sects, gfp_t gfp_mask, struct bio **biop) { struct bio *bio = *biop; - while (nr_sects) { - sector_t req_sects = - min(nr_sects, bio_discard_limit(bdev, sector)); - - bio = blk_next_bio(bio, bdev, 0, REQ_OP_DISCARD, gfp_mask); - bio->bi_iter.bi_sector = sector; - bio->bi_iter.bi_size = req_sects << 9; - sector += req_sects; - nr_sects -= req_sects; - - /* - * We can loop for a long time in here, if someone does - * full device discards (like mkfs). Be nice and allow - * us to schedule out to avoid softlocking if preempt - * is disabled. - */ - cond_resched(); + while (blk_next_discard_bio(bdev, &bio, §or, &nr_sects, gfp_mask)) { if (fatal_signal_pending(current)) { await_bio_chain(bio); return -EINTR; diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index a9a0bd6cac4aff..b87cd889008291 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1059,6 +1059,8 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, sector_t nr_sects, gfp_t gfp_mask); int __blkdev_issue_discard(struct block_device *bdev, sector_t sector, sector_t nr_sects, gfp_t gfp_mask, struct bio **biop); +bool blk_next_discard_bio(struct block_device *bdev, struct bio **biop, + sector_t *sector, sector_t *nr_sects, gfp_t gfp_mask); int blkdev_issue_secure_erase(struct block_device *bdev, sector_t sector, sector_t nr_sects, gfp_t gfp); -- 2.39.2