]>
Commit | Line | Data |
---|---|---|
ba172962 SL |
1 | From 14a5279754eea932b7719e108e8c0835f6aa2a54 Mon Sep 17 00:00:00 2001 |
2 | From: Paolo Valente <paolo.valente@linaro.org> | |
3 | Date: Tue, 29 Jan 2019 12:06:38 +0100 | |
4 | Subject: block, bfq: fix in-service-queue check for queue merging | |
5 | ||
6 | [ Upstream commit 058fdecc6de7cdecbf4c59b851e80eb2d6c5295f ] | |
7 | ||
8 | When a new I/O request arrives for a bfq_queue, say Q, bfq checks | |
9 | whether that request is close to | |
10 | (a) the head request of some other queue waiting to be served, or | |
11 | (b) the last request dispatched for the in-service queue (in case Q | |
12 | itself is not the in-service queue) | |
13 | ||
14 | If a queue, say Q2, is found for which the above condition holds, then | |
15 | bfq merges Q and Q2, to hopefully get a more sequential I/O in the | |
16 | resulting merged queue, and thus a possibly higher throughput. | |
17 | ||
18 | Case (b) is checked by comparing the new request for Q with the last | |
19 | request dispatched, assuming that the latter necessarily belonged to the | |
20 | in-service queue. Unfortunately, this assumption is no longer always | |
21 | correct, since commit d0edc2473be9 ("block, bfq: inject other-queue I/O | |
22 | into seeky idle queues on NCQ flash"). | |
23 | ||
24 | When the assumption does not hold, queues that must not be merged may be | |
25 | merged, causing unexpected loss of control on per-queue service | |
26 | guarantees. | |
27 | ||
28 | This commit solves this problem by adding an extra field, which stores | |
29 | the actual last request dispatched for the in-service queue, and by | |
30 | using this new field to correctly check case (b). | |
31 | ||
32 | Signed-off-by: Paolo Valente <paolo.valente@linaro.org> | |
33 | Signed-off-by: Jens Axboe <axboe@kernel.dk> | |
34 | Signed-off-by: Sasha Levin <sashal@kernel.org> | |
35 | --- | |
36 | block/bfq-iosched.c | 5 ++++- | |
37 | block/bfq-iosched.h | 3 +++ | |
38 | 2 files changed, 7 insertions(+), 1 deletion(-) | |
39 | ||
40 | diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c | |
41 | index 653100fb719e..c5e2c5a01182 100644 | |
42 | --- a/block/bfq-iosched.c | |
43 | +++ b/block/bfq-iosched.c | |
44 | @@ -2215,7 +2215,8 @@ bfq_setup_cooperator(struct bfq_data *bfqd, struct bfq_queue *bfqq, | |
45 | ||
46 | if (in_service_bfqq && in_service_bfqq != bfqq && | |
47 | likely(in_service_bfqq != &bfqd->oom_bfqq) && | |
48 | - bfq_rq_close_to_sector(io_struct, request, bfqd->last_position) && | |
49 | + bfq_rq_close_to_sector(io_struct, request, | |
50 | + bfqd->in_serv_last_pos) && | |
51 | bfqq->entity.parent == in_service_bfqq->entity.parent && | |
52 | bfq_may_be_close_cooperator(bfqq, in_service_bfqq)) { | |
53 | new_bfqq = bfq_setup_merge(bfqq, in_service_bfqq); | |
54 | @@ -2755,6 +2756,8 @@ update_rate_and_reset: | |
55 | bfq_update_rate_reset(bfqd, rq); | |
56 | update_last_values: | |
57 | bfqd->last_position = blk_rq_pos(rq) + blk_rq_sectors(rq); | |
58 | + if (RQ_BFQQ(rq) == bfqd->in_service_queue) | |
59 | + bfqd->in_serv_last_pos = bfqd->last_position; | |
60 | bfqd->last_dispatch = now_ns; | |
61 | } | |
62 | ||
63 | diff --git a/block/bfq-iosched.h b/block/bfq-iosched.h | |
64 | index a8a2e5aca4d4..d5e9e60cb1a5 100644 | |
65 | --- a/block/bfq-iosched.h | |
66 | +++ b/block/bfq-iosched.h | |
67 | @@ -469,6 +469,9 @@ struct bfq_data { | |
68 | /* on-disk position of the last served request */ | |
69 | sector_t last_position; | |
70 | ||
71 | + /* position of the last served request for the in-service queue */ | |
72 | + sector_t in_serv_last_pos; | |
73 | + | |
74 | /* time of last request completion (ns) */ | |
75 | u64 last_completion; | |
76 | ||
77 | -- | |
78 | 2.19.1 | |
79 |