summaryrefslogtreecommitdiffstats
path: root/block/blk-mq.c
diff options
context:
space:
mode:
authorJens Axboe <axboe@kernel.dk>2018-06-28 13:54:01 -0400
committerJens Axboe <axboe@kernel.dk>2018-06-29 09:52:31 -0400
commit1f57f8d442f8017587eeebd8617913bfc3661d3d (patch)
tree43058155d51cacd8a255d2ddc5b0f53d28d76004 /block/blk-mq.c
parent297ba57dcdec7ea37e702bcf1a577ac32a034e21 (diff)
blk-mq: don't queue more if we get a busy return
Some devices have different queue limits depending on the type of IO. A classic case is SATA NCQ, where some commands can queue, but others cannot. If we have NCQ commands inflight and encounter a non-queueable command, the driver returns busy. Currently we attempt to dispatch more from the scheduler, if we were able to queue some commands. But for the case where we ended up stopping due to BUSY, we should not attempt to retrieve more from the scheduler. If we do, we can get into a situation where we attempt to queue a non-queueable command, get BUSY, then successfully retrieve more commands from that scheduler and queue those. This can repeat forever, starving the non-queuable command indefinitely. Fix this by NOT attempting to pull more commands from the scheduler, if we get a BUSY return. This should also be more optimal in terms of letting requests stay in the scheduler for as long as possible, if we get a BUSY due to the regular out-of-tags condition. Reviewed-by: Omar Sandoval <osandov@fb.com> Reviewed-by: Ming Lei <ming.lei@redhat.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block/blk-mq.c')
-rw-r--r--block/blk-mq.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/block/blk-mq.c b/block/blk-mq.c
index b6888ff556cf..d394cdd8d8c6 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -1075,6 +1075,9 @@ static bool blk_mq_mark_tag_wait(struct blk_mq_hw_ctx **hctx,
1075 1075
1076#define BLK_MQ_RESOURCE_DELAY 3 /* ms units */ 1076#define BLK_MQ_RESOURCE_DELAY 3 /* ms units */
1077 1077
1078/*
1079 * Returns true if we did some work AND can potentially do more.
1080 */
1078bool blk_mq_dispatch_rq_list(struct request_queue *q, struct list_head *list, 1081bool blk_mq_dispatch_rq_list(struct request_queue *q, struct list_head *list,
1079 bool got_budget) 1082 bool got_budget)
1080{ 1083{
@@ -1205,8 +1208,17 @@ bool blk_mq_dispatch_rq_list(struct request_queue *q, struct list_head *list,
1205 blk_mq_run_hw_queue(hctx, true); 1208 blk_mq_run_hw_queue(hctx, true);
1206 else if (needs_restart && (ret == BLK_STS_RESOURCE)) 1209 else if (needs_restart && (ret == BLK_STS_RESOURCE))
1207 blk_mq_delay_run_hw_queue(hctx, BLK_MQ_RESOURCE_DELAY); 1210 blk_mq_delay_run_hw_queue(hctx, BLK_MQ_RESOURCE_DELAY);
1211
1212 return false;
1208 } 1213 }
1209 1214
1215 /*
1216 * If the host/device is unable to accept more work, inform the
1217 * caller of that.
1218 */
1219 if (ret == BLK_STS_RESOURCE || ret == BLK_STS_DEV_RESOURCE)
1220 return false;
1221
1210 return (queued + errors) != 0; 1222 return (queued + errors) != 0;
1211} 1223}
1212 1224