Skip to content

Commit 2645672

Browse files
committed
block: pop cached rq before potentially blocking rq_qos_throttle()
If rq_qos_throttle() ends up blocking, then we will have invalidated and flushed our current plug. Since blk_mq_get_cached_request() hasn't popped the cached request off the plug list just yet, we end holding a pointer to a request that is no longer valid. This insta-crashes with rq->mq_hctx being NULL in the validity checks just after. Pop the request off the cached list before doing rq_qos_throttle() to avoid using a potentially stale request. Fixes: 0a5aa8d ("block: fix blk_mq_attempt_bio_merge and rq_qos_throttle protection") Reported-by: Dylan Yudaken <dylany@fb.com> Tested-by: Dylan Yudaken <dylany@fb.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 9243fc4 commit 2645672

File tree

1 file changed

+8
-3
lines changed

1 file changed

+8
-3
lines changed

block/blk-mq.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2765,15 +2765,20 @@ static inline struct request *blk_mq_get_cached_request(struct request_queue *q,
27652765
return NULL;
27662766
}
27672767

2768-
rq_qos_throttle(q, *bio);
2769-
27702768
if (blk_mq_get_hctx_type((*bio)->bi_opf) != rq->mq_hctx->type)
27712769
return NULL;
27722770
if (op_is_flush(rq->cmd_flags) != op_is_flush((*bio)->bi_opf))
27732771
return NULL;
27742772

2775-
rq->cmd_flags = (*bio)->bi_opf;
2773+
/*
2774+
* If any qos ->throttle() end up blocking, we will have flushed the
2775+
* plug and hence killed the cached_rq list as well. Pop this entry
2776+
* before we throttle.
2777+
*/
27762778
plug->cached_rq = rq_list_next(rq);
2779+
rq_qos_throttle(q, *bio);
2780+
2781+
rq->cmd_flags = (*bio)->bi_opf;
27772782
INIT_LIST_HEAD(&rq->queuelist);
27782783
return rq;
27792784
}

0 commit comments

Comments
 (0)