summaryrefslogtreecommitdiffstats
path: root/block/bfq-iosched.c
diff options
context:
space:
mode:
authorPaolo Valente <paolo.valente@linaro.org>2019-01-29 06:06:38 -0500
committerJens Axboe <axboe@kernel.dk>2019-01-31 14:50:24 -0500
commit058fdecc6de7cdecbf4c59b851e80eb2d6c5295f (patch)
treee48869ade51d46200381586259daf112a14302d3 /block/bfq-iosched.c
parent02a6d787f4afc8be2d3d52ab0a1df0c6a2d99e7b (diff)
block, bfq: fix in-service-queue check for queue merging
When a new I/O request arrives for a bfq_queue, say Q, bfq checks whether that request is close to (a) the head request of some other queue waiting to be served, or (b) the last request dispatched for the in-service queue (in case Q itself is not the in-service queue) If a queue, say Q2, is found for which the above condition holds, then bfq merges Q and Q2, to hopefully get a more sequential I/O in the resulting merged queue, and thus a possibly higher throughput. Case (b) is checked by comparing the new request for Q with the last request dispatched, assuming that the latter necessarily belonged to the in-service queue. Unfortunately, this assumption is no longer always correct, since commit d0edc2473be9 ("block, bfq: inject other-queue I/O into seeky idle queues on NCQ flash"). When the assumption does not hold, queues that must not be merged may be merged, causing unexpected loss of control on per-queue service guarantees. This commit solves this problem by adding an extra field, which stores the actual last request dispatched for the in-service queue, and by using this new field to correctly check case (b). Signed-off-by: Paolo Valente <paolo.valente@linaro.org> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block/bfq-iosched.c')
-rw-r--r--block/bfq-iosched.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
index 06268449d2ca..4c592496a16a 100644
--- a/block/bfq-iosched.c
+++ b/block/bfq-iosched.c
@@ -2251,7 +2251,8 @@ bfq_setup_cooperator(struct bfq_data *bfqd, struct bfq_queue *bfqq,
2251 2251
2252 if (in_service_bfqq && in_service_bfqq != bfqq && 2252 if (in_service_bfqq && in_service_bfqq != bfqq &&
2253 likely(in_service_bfqq != &bfqd->oom_bfqq) && 2253 likely(in_service_bfqq != &bfqd->oom_bfqq) &&
2254 bfq_rq_close_to_sector(io_struct, request, bfqd->last_position) && 2254 bfq_rq_close_to_sector(io_struct, request,
2255 bfqd->in_serv_last_pos) &&
2255 bfqq->entity.parent == in_service_bfqq->entity.parent && 2256 bfqq->entity.parent == in_service_bfqq->entity.parent &&
2256 bfq_may_be_close_cooperator(bfqq, in_service_bfqq)) { 2257 bfq_may_be_close_cooperator(bfqq, in_service_bfqq)) {
2257 new_bfqq = bfq_setup_merge(bfqq, in_service_bfqq); 2258 new_bfqq = bfq_setup_merge(bfqq, in_service_bfqq);
@@ -2791,6 +2792,8 @@ update_rate_and_reset:
2791 bfq_update_rate_reset(bfqd, rq); 2792 bfq_update_rate_reset(bfqd, rq);
2792update_last_values: 2793update_last_values:
2793 bfqd->last_position = blk_rq_pos(rq) + blk_rq_sectors(rq); 2794 bfqd->last_position = blk_rq_pos(rq) + blk_rq_sectors(rq);
2795 if (RQ_BFQQ(rq) == bfqd->in_service_queue)
2796 bfqd->in_serv_last_pos = bfqd->last_position;
2794 bfqd->last_dispatch = now_ns; 2797 bfqd->last_dispatch = now_ns;
2795} 2798}
2796 2799