diff options
Diffstat (limited to 'block')
| -rw-r--r-- | block/bio.c | 34 | ||||
| -rw-r--r-- | block/blk-mq.c | 2 | ||||
| -rw-r--r-- | block/blk-zoned.c | 1 |
3 files changed, 36 insertions, 1 deletions
diff --git a/block/bio.c b/block/bio.c index 2359c0723b88..1e31ca495d8d 100644 --- a/block/bio.c +++ b/block/bio.c @@ -314,6 +314,40 @@ void bio_reset(struct bio *bio, struct block_device *bdev, blk_opf_t opf) } EXPORT_SYMBOL(bio_reset); +/** + * bio_reuse - reuse a bio with the payload left intact + * @bio: bio to reuse + * @opf: operation and flags for the next I/O + * + * Allow reusing an existing bio for another operation with all set up + * fields including the payload, device and end_io handler left intact. + * + * Typically used when @bio is first used to read data which is then written + * to another location without modification. @bio must not be in-flight and + * owned by the caller. Can't be used for cloned bios. + * + * Note: Can't be used when @bio has integrity or blk-crypto contexts for now. + * Feel free to add that support when you need it, though. + */ +void bio_reuse(struct bio *bio, blk_opf_t opf) +{ + unsigned short vcnt = bio->bi_vcnt, i; + bio_end_io_t *end_io = bio->bi_end_io; + void *private = bio->bi_private; + + WARN_ON_ONCE(bio_flagged(bio, BIO_CLONED)); + WARN_ON_ONCE(bio_integrity(bio)); + WARN_ON_ONCE(bio_has_crypt_ctx(bio)); + + bio_reset(bio, bio->bi_bdev, opf); + for (i = 0; i < vcnt; i++) + bio->bi_iter.bi_size += bio->bi_io_vec[i].bv_len; + bio->bi_vcnt = vcnt; + bio->bi_private = private; + bio->bi_end_io = end_io; +} +EXPORT_SYMBOL_GPL(bio_reuse); + static struct bio *__bio_chain_endio(struct bio *bio) { struct bio *parent = bio->bi_private; diff --git a/block/blk-mq.c b/block/blk-mq.c index 0ad3dd3329db..5ae83d3e210f 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -1493,7 +1493,7 @@ EXPORT_SYMBOL_GPL(blk_rq_is_poll); static void blk_rq_poll_completion(struct request *rq, struct completion *wait) { do { - blk_hctx_poll(rq->q, rq->mq_hctx, NULL, 0); + blk_hctx_poll(rq->q, rq->mq_hctx, NULL, BLK_POLL_ONESHOT); cond_resched(); } while (!completion_done(wait)); } diff --git a/block/blk-zoned.c b/block/blk-zoned.c index ef3872c53244..846b8844f04a 100644 --- a/block/blk-zoned.c +++ b/block/blk-zoned.c @@ -1957,6 +1957,7 @@ static int disk_update_zone_resources(struct gendisk *disk, disk->nr_zones = args->nr_zones; if (args->nr_conv_zones >= disk->nr_zones) { + queue_limits_cancel_update(q); pr_warn("%s: Invalid number of conventional zones %u / %u\n", disk->disk_name, args->nr_conv_zones, disk->nr_zones); ret = -ENODEV; |
