]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
block, bfq: fix in-service-queue check for queue merging
authorPaolo Valente <paolo.valente@linaro.org>
Tue, 29 Jan 2019 11:06:38 +0000 (12:06 +0100)
committerJens Axboe <axboe@kernel.dk>
Thu, 31 Jan 2019 19:50:24 +0000 (12:50 -0700)
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>
block/bfq-iosched.c
block/bfq-iosched.h

index 06268449d2cadd751069cea7ed06c5700bf5af0a..4c592496a16a21655dcd8616ae4b3181111b3956 100644 (file)
@@ -2251,7 +2251,8 @@ bfq_setup_cooperator(struct bfq_data *bfqd, struct bfq_queue *bfqq,
 
        if (in_service_bfqq && in_service_bfqq != bfqq &&
            likely(in_service_bfqq != &bfqd->oom_bfqq) &&
-           bfq_rq_close_to_sector(io_struct, request, bfqd->last_position) &&
+           bfq_rq_close_to_sector(io_struct, request,
+                                  bfqd->in_serv_last_pos) &&
            bfqq->entity.parent == in_service_bfqq->entity.parent &&
            bfq_may_be_close_cooperator(bfqq, in_service_bfqq)) {
                new_bfqq = bfq_setup_merge(bfqq, in_service_bfqq);
@@ -2791,6 +2792,8 @@ update_rate_and_reset:
        bfq_update_rate_reset(bfqd, rq);
 update_last_values:
        bfqd->last_position = blk_rq_pos(rq) + blk_rq_sectors(rq);
+       if (RQ_BFQQ(rq) == bfqd->in_service_queue)
+               bfqd->in_serv_last_pos = bfqd->last_position;
        bfqd->last_dispatch = now_ns;
 }
 
index 30be669be465f5c8901b8c9aa148a8c690a115be..062e1c4787f4a9e66ac4df54d24c17d9f92c6577 100644 (file)
@@ -538,6 +538,9 @@ struct bfq_data {
        /* on-disk position of the last served request */
        sector_t last_position;
 
+       /* position of the last served request for the in-service queue */
+       sector_t in_serv_last_pos;
+
        /* time of last request completion (ns) */
        u64 last_completion;