1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
From 67845bd98cd08aa18a07c884263aea0110273e51 Mon Sep 17 00:00:00 2001
From: Valentine Barshak <valentine.barshak@cogentembedded.com>
Date: Fri, 1 Mar 2019 22:22:04 +0300
Subject: [PATCH 071/122] block: blk-mq: Fix IO hang
Sometimes IO hangs are observed on Samsung Pro 960 NVME device.
If driver returns BLK_STS_RESOURCE and SCHED_RESTART is set,
rerun queue after a delay (BLK_MQ_DELAY_QUEUE) to avoid IO stalls.
BLK_MQ_DELAY_QUEUE is 3 ms because both scsi-mq and nvmefc are using
that magic value.
This is part of the commit 86ff7c2a80cd357f6156a53b354f6a0b357dc0c9
"blk-mq: introduce BLK_STS_DEV_RESOURCE" found in
https://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git.
Signed-off-by: Valentine Barshak <valentine.barshak@cogentembedded.com>
---
block/blk-mq.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 49979c0..0d923ea 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -1037,11 +1037,14 @@ static bool blk_mq_dispatch_wait_add(struct blk_mq_hw_ctx *hctx)
return true;
}
+#define BLK_MQ_RESOURCE_DELAY 3 /* ms units */
+
bool blk_mq_dispatch_rq_list(struct request_queue *q, struct list_head *list)
{
struct blk_mq_hw_ctx *hctx;
struct request *rq;
int errors, queued;
+ blk_status_t ret = BLK_STS_OK;
if (list_empty(list))
return false;
@@ -1052,7 +1055,6 @@ bool blk_mq_dispatch_rq_list(struct request_queue *q, struct list_head *list)
errors = queued = 0;
do {
struct blk_mq_queue_data bd;
- blk_status_t ret;
rq = list_first_entry(list, struct request, queuelist);
if (!blk_mq_get_driver_tag(rq, &hctx, false)) {
@@ -1116,6 +1118,8 @@ bool blk_mq_dispatch_rq_list(struct request_queue *q, struct list_head *list)
* that is where we will continue on next queue run.
*/
if (!list_empty(list)) {
+ bool needs_restart;
+
/*
* If an I/O scheduler has been configured and we got a driver
* tag for the next request already, free it again.
@@ -1146,10 +1150,17 @@ bool blk_mq_dispatch_rq_list(struct request_queue *q, struct list_head *list)
* - Some but not all block drivers stop a queue before
* returning BLK_STS_RESOURCE. Two exceptions are scsi-mq
* and dm-rq.
+ *
+ * If driver returns BLK_STS_RESOURCE and SCHED_RESTART
+ * bit is set, run queue after a delay to avoid IO stalls
+ * that could otherwise occur if the queue is idle.
*/
- if (!blk_mq_sched_needs_restart(hctx) &&
+ needs_restart = blk_mq_sched_needs_restart(hctx);
+ if (!needs_restart &&
!test_bit(BLK_MQ_S_TAG_WAITING, &hctx->state))
blk_mq_run_hw_queue(hctx, true);
+ else if (needs_restart && (ret == BLK_STS_RESOURCE))
+ blk_mq_delay_run_hw_queue(hctx, BLK_MQ_RESOURCE_DELAY);
}
return (queued + errors) != 0;
--
2.7.4
|