blk-mq: Don't reserve a tag for flush request
Reserving a tag (request) for flush to avoid dead lock is a overkill. A tag is valuable resource. We can track the number of flush requests and disallow having too many pending flush requests allocated. With this patch, blk_mq_alloc_request_pinned() could do a busy nop (but not a dead loop) if too many pending requests are allocated and new flush request is allocated. But this should not be a problem, too many pending flush requests are very rare case. I verified this can fix the deadlock caused by too many pending flush requests. Signed-off-by: Shaohua Li <shli@fusionio.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
@@ -284,9 +284,8 @@ static void mq_flush_work(struct work_struct *work)
|
||||
|
||||
q = container_of(work, struct request_queue, mq_flush_work);
|
||||
|
||||
/* We don't need set REQ_FLUSH_SEQ, it's for consistency */
|
||||
rq = blk_mq_alloc_request(q, WRITE_FLUSH|REQ_FLUSH_SEQ,
|
||||
__GFP_WAIT|GFP_ATOMIC, true);
|
||||
__GFP_WAIT|GFP_ATOMIC, false);
|
||||
rq->cmd_type = REQ_TYPE_FS;
|
||||
rq->end_io = flush_end_io;
|
||||
|
||||
@@ -408,8 +407,11 @@ void blk_insert_flush(struct request *rq)
|
||||
/*
|
||||
* @policy now records what operations need to be done. Adjust
|
||||
* REQ_FLUSH and FUA for the driver.
|
||||
* We keep REQ_FLUSH for mq to track flush requests. For !FUA,
|
||||
* we never dispatch the request directly.
|
||||
*/
|
||||
rq->cmd_flags &= ~REQ_FLUSH;
|
||||
if (rq->cmd_flags & REQ_FUA)
|
||||
rq->cmd_flags &= ~REQ_FLUSH;
|
||||
if (!(fflags & REQ_FUA))
|
||||
rq->cmd_flags &= ~REQ_FUA;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user