Skip to content

Commit

Permalink
block: fix double bio queue when merging in cached request path
Browse files Browse the repository at this point in the history
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 <ming.lei@redhat.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
  • Loading branch information
Jens Axboe committed Dec 3, 2021
1 parent 373b541 commit a08ed9a
Showing 1 changed file with 12 additions and 8 deletions.
20 changes: 12 additions & 8 deletions block/blk-mq.c
Original file line number Diff line number Diff line change
Expand Up @@ -2731,7 +2731,7 @@ static struct request *blk_mq_get_new_requests(struct request_queue *q,
}

static inline struct request *blk_mq_get_cached_request(struct request_queue *q,
struct blk_plug *plug, struct bio *bio, unsigned int nsegs)
struct blk_plug *plug, struct bio **bio, unsigned int nsegs)
{
struct request *rq;

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

if (unlikely(!submit_bio_checks(bio)))
if (unlikely(!submit_bio_checks(*bio)))
return NULL;
if (blk_mq_attempt_bio_merge(q, bio, nsegs))
if (blk_mq_attempt_bio_merge(q, *bio, nsegs)) {
*bio = NULL;
return NULL;
if (blk_mq_get_hctx_type(bio->bi_opf) != rq->mq_hctx->type)
}
if (blk_mq_get_hctx_type((*bio)->bi_opf) != rq->mq_hctx->type)
return NULL;
if (op_is_flush(rq->cmd_flags) != op_is_flush(bio->bi_opf))
if (op_is_flush(rq->cmd_flags) != op_is_flush((*bio)->bi_opf))
return NULL;

rq->cmd_flags = bio->bi_opf;
rq->cmd_flags = (*bio)->bi_opf;
plug->cached_rq = rq_list_next(rq);
INIT_LIST_HEAD(&rq->queuelist);
rq_qos_throttle(q, bio);
rq_qos_throttle(q, *bio);
return rq;
}

Expand Down Expand Up @@ -2789,8 +2791,10 @@ void blk_mq_submit_bio(struct bio *bio)
if (!bio_integrity_prep(bio))
return;

rq = blk_mq_get_cached_request(q, plug, bio, nr_segs);
rq = blk_mq_get_cached_request(q, plug, &bio, nr_segs);
if (!rq) {
if (!bio)
return;
rq = blk_mq_get_new_requests(q, plug, bio, nr_segs);
if (unlikely(!rq))
return;
Expand Down

0 comments on commit a08ed9a

Please sign in to comment.