[PATCH] blk-mq: auto-start hw queue in requeue

From: Ming Lei
Date: Fri Sep 19 2014 - 10:23:04 EST


Requests often need to be retried because of timeout, hardware
busy or sort of reasons via blk_mq_requeue_request(), but at
that time dispatch queue may have been stopped.

This patch starts the dispatch queue automatically in requeue's
work handler, and fixes scsi-mq's timeout issue, which can be
triggered if there are two or more requests timedout.

Suggested-by: Christoph Hellwig <hch@xxxxxx>
Signed-off-by: Ming Lei <ming.lei@xxxxxxxxxxxxx>
---
block/blk-mq.c | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/block/blk-mq.c b/block/blk-mq.c
index 80ade9f..edd0ece 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -33,6 +33,8 @@ static DEFINE_MUTEX(all_q_mutex);
static LIST_HEAD(all_q_list);

static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx);
+static void __blk_mq_run_queues(struct request_queue *q, bool async,
+ bool restart);

/*
* Check if any of the ctx's have pending work in this hardware queue
@@ -473,7 +475,7 @@ static void blk_mq_requeue_work(struct work_struct *work)
blk_mq_insert_request(rq, false, false, false);
}

- blk_mq_run_queues(q, false);
+ __blk_mq_run_queues(q, false, true);
}

void blk_mq_add_to_requeue_list(struct request *rq, bool at_head)
@@ -806,15 +808,21 @@ void blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx, bool async)
}
}

-void blk_mq_run_queues(struct request_queue *q, bool async)
+static void __blk_mq_run_queues(struct request_queue *q, bool async,
+ bool restart)
{
struct blk_mq_hw_ctx *hctx;
int i;

queue_for_each_hw_ctx(q, hctx, i) {
+ bool stopped = test_bit(BLK_MQ_S_STOPPED, &hctx->state);
+
+ if (restart && stopped)
+ clear_bit(BLK_MQ_S_STOPPED, &hctx->state);
+
if ((!blk_mq_hctx_has_pending(hctx) &&
list_empty_careful(&hctx->dispatch)) ||
- test_bit(BLK_MQ_S_STOPPED, &hctx->state))
+ (stopped && !restart))
continue;

preempt_disable();
@@ -822,6 +830,11 @@ void blk_mq_run_queues(struct request_queue *q, bool async)
preempt_enable();
}
}
+
+void blk_mq_run_queues(struct request_queue *q, bool async)
+{
+ __blk_mq_run_queues(q, async, false);
+}
EXPORT_SYMBOL(blk_mq_run_queues);

void blk_mq_stop_hw_queue(struct blk_mq_hw_ctx *hctx)
--
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/