Skip to content

Commit a08ed9a

Browse files
committed
block: fix double bio queue when merging in cached request path
When we attempt to merge off the cached request path, we return NULL if successful. This makes the caller believe that it's should allocate a new request, and hence we end up with the bio both merged and associated with a new request. This, predictably, leads to all sorts of crashes. Pass in a pointer to the bio pointer, and clear it for the merge case. Then the caller knows that the bio is already queued, and no new requests need to get allocated. Fixes: 5b13bc8 ("blk-mq: cleanup request allocation") Reviewed-by: Ming Lei <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent 373b541 commit a08ed9a

File tree

1 file changed

+12
-8
lines changed

1 file changed

+12
-8
lines changed

block/blk-mq.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2731,7 +2731,7 @@ static struct request *blk_mq_get_new_requests(struct request_queue *q,
27312731
}
27322732

27332733
static inline struct request *blk_mq_get_cached_request(struct request_queue *q,
2734-
struct blk_plug *plug, struct bio *bio, unsigned int nsegs)
2734+
struct blk_plug *plug, struct bio **bio, unsigned int nsegs)
27352735
{
27362736
struct request *rq;
27372737

@@ -2741,19 +2741,21 @@ static inline struct request *blk_mq_get_cached_request(struct request_queue *q,
27412741
if (!rq || rq->q != q)
27422742
return NULL;
27432743

2744-
if (unlikely(!submit_bio_checks(bio)))
2744+
if (unlikely(!submit_bio_checks(*bio)))
27452745
return NULL;
2746-
if (blk_mq_attempt_bio_merge(q, bio, nsegs))
2746+
if (blk_mq_attempt_bio_merge(q, *bio, nsegs)) {
2747+
*bio = NULL;
27472748
return NULL;
2748-
if (blk_mq_get_hctx_type(bio->bi_opf) != rq->mq_hctx->type)
2749+
}
2750+
if (blk_mq_get_hctx_type((*bio)->bi_opf) != rq->mq_hctx->type)
27492751
return NULL;
2750-
if (op_is_flush(rq->cmd_flags) != op_is_flush(bio->bi_opf))
2752+
if (op_is_flush(rq->cmd_flags) != op_is_flush((*bio)->bi_opf))
27512753
return NULL;
27522754

2753-
rq->cmd_flags = bio->bi_opf;
2755+
rq->cmd_flags = (*bio)->bi_opf;
27542756
plug->cached_rq = rq_list_next(rq);
27552757
INIT_LIST_HEAD(&rq->queuelist);
2756-
rq_qos_throttle(q, bio);
2758+
rq_qos_throttle(q, *bio);
27572759
return rq;
27582760
}
27592761

@@ -2789,8 +2791,10 @@ void blk_mq_submit_bio(struct bio *bio)
27892791
if (!bio_integrity_prep(bio))
27902792
return;
27912793

2792-
rq = blk_mq_get_cached_request(q, plug, bio, nr_segs);
2794+
rq = blk_mq_get_cached_request(q, plug, &bio, nr_segs);
27932795
if (!rq) {
2796+
if (!bio)
2797+
return;
27942798
rq = blk_mq_get_new_requests(q, plug, bio, nr_segs);
27952799
if (unlikely(!rq))
27962800
return;

0 commit comments

Comments
 (0)