summaryrefslogtreecommitdiffstats
path: root/block/bfq-iosched.c
diff options
context:
space:
mode:
authorPaolo Valente <paolo.valente@linaro.org>2018-06-25 15:55:35 -0400
committerJens Axboe <axboe@kernel.dk>2018-07-09 11:07:52 -0400
commit4420b095cc474759f6fbdb6351648c7ff9833a54 (patch)
tree6cda6a5d78a993bf317ac1ba734f1d0f18420d9e /block/bfq-iosched.c
parent0471559c2fbd2c19d183fc0f51ce88aefa0a13c8 (diff)
block, bfq: do not expire a queue that will deserve dispatch plugging
For some bfq_queues, BFQ plugs I/O dispatching when the queue becomes idle, and keeps the plug until a new request of the queue arrives, or a timeout fires. BFQ does so either to boost throughput or to preserve service guarantees for the queue. More precisely, for such a queue, plugging starts when the queue happens to have either no request enqueued, or no request in flight, that is, no request already dispatched but not yet completed. On the opposite end, BFQ may happen to expire a queue with no request enqueued, without doing any plugging, if the queue still has some request in flight. Unfortunately, such a premature expiration causes the queue to lose its chance to enjoy dispatch plugging a moment later, i.e., when its in-flight requests finally get completed. This breaks service guarantees for the queue. This commit prevents BFQ from expiring an empty queue if the latter still has in-flight requests. Tested-by: Holger Hoffstätte <holger@applied-asynchrony.com> Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name> 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.c36
1 files changed, 33 insertions, 3 deletions
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
index 3f32e88c7e9b..4fd4f1996498 100644
--- a/block/bfq-iosched.c
+++ b/block/bfq-iosched.c
@@ -3597,8 +3597,14 @@ static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd)
3597 3597
3598 bfq_log_bfqq(bfqd, bfqq, "select_queue: already in-service queue"); 3598 bfq_log_bfqq(bfqd, bfqq, "select_queue: already in-service queue");
3599 3599
3600 /*
3601 * Do not expire bfqq for budget timeout if bfqq may be about
3602 * to enjoy device idling. The reason why, in this case, we
3603 * prevent bfqq from expiring is the same as in the comments
3604 * on the case where bfq_bfqq_must_idle() returns true, in
3605 * bfq_completed_request().
3606 */
3600 if (bfq_may_expire_for_budg_timeout(bfqq) && 3607 if (bfq_may_expire_for_budg_timeout(bfqq) &&
3601 !bfq_bfqq_wait_request(bfqq) &&
3602 !bfq_bfqq_must_idle(bfqq)) 3608 !bfq_bfqq_must_idle(bfqq))
3603 goto expire; 3609 goto expire;
3604 3610
@@ -4674,8 +4680,32 @@ static void bfq_completed_request(struct bfq_queue *bfqq, struct bfq_data *bfqd)
4674 * or if we want to idle in case it has no pending requests. 4680 * or if we want to idle in case it has no pending requests.
4675 */ 4681 */
4676 if (bfqd->in_service_queue == bfqq) { 4682 if (bfqd->in_service_queue == bfqq) {
4677 if (bfqq->dispatched == 0 && bfq_bfqq_must_idle(bfqq)) { 4683 if (bfq_bfqq_must_idle(bfqq)) {
4678 bfq_arm_slice_timer(bfqd); 4684 if (bfqq->dispatched == 0)
4685 bfq_arm_slice_timer(bfqd);
4686 /*
4687 * If we get here, we do not expire bfqq, even
4688 * if bfqq was in budget timeout or had no
4689 * more requests (as controlled in the next
4690 * conditional instructions). The reason for
4691 * not expiring bfqq is as follows.
4692 *
4693 * Here bfqq->dispatched > 0 holds, but
4694 * bfq_bfqq_must_idle() returned true. This
4695 * implies that, even if no request arrives
4696 * for bfqq before bfqq->dispatched reaches 0,
4697 * bfqq will, however, not be expired on the
4698 * completion event that causes bfqq->dispatch
4699 * to reach zero. In contrast, on this event,
4700 * bfqq will start enjoying device idling
4701 * (I/O-dispatch plugging).
4702 *
4703 * But, if we expired bfqq here, bfqq would
4704 * not have the chance to enjoy device idling
4705 * when bfqq->dispatched finally reaches
4706 * zero. This would expose bfqq to violation
4707 * of its reserved service guarantees.
4708 */
4679 return; 4709 return;
4680 } else if (bfq_may_expire_for_budg_timeout(bfqq)) 4710 } else if (bfq_may_expire_for_budg_timeout(bfqq))
4681 bfq_bfqq_expire(bfqd, bfqq, false, 4711 bfq_bfqq_expire(bfqd, bfqq, false,