Commit 530c4cbb authored by Paolo Valente's avatar Paolo Valente Committed by Jens Axboe

block, bfq: unconditionally plug I/O in asymmetric scenarios

bfq detects the creation of multiple bfq_queues shortly after each
other, namely a burst of queue creations in the terminology used in the
code. If the burst is large, then no queue in the burst is granted
- either I/O-dispatch plugging when the queue remains temporarily idle
  while in service;
- or weight raising, because it causes even longer plugging.

In fact, such a plugging tends to lower throughput, while these bursts
are typically due to applications or services that spawn multiple
processes, to reach a common goal as soon as possible. Examples are a
"git grep" or the booting of a system.

Unfortunately, disabling plugging may cause a loss of service guarantees
in asymmetric scenarios, i.e., if queue weights are differentiated or if
more than one group is active.

This commit addresses this issue by no longer disabling I/O-dispatch
plugging for queues in large bursts.
Signed-off-by: default avatarPaolo Valente <paolo.valente@linaro.org>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent ac8b0cb4
...@@ -3479,15 +3479,12 @@ static bool idling_boosts_thr_without_issues(struct bfq_data *bfqd, ...@@ -3479,15 +3479,12 @@ static bool idling_boosts_thr_without_issues(struct bfq_data *bfqd,
bfqd->wr_busy_queues == 0; bfqd->wr_busy_queues == 0;
} }
static bool idling_needed_for_service_guarantees(struct bfq_data *bfqd, /*
struct bfq_queue *bfqq)
{
/*
* There is a case where idling must be performed not for * There is a case where idling must be performed not for
* throughput concerns, but to preserve service guarantees. * throughput concerns, but to preserve service guarantees.
* *
* To introduce this case, we can note that allowing the drive * To introduce this case, we can note that allowing the drive
* to enqueue more than one request at a time, and thereby * to enqueue more than one request at a time, and hence
* delegating de facto final scheduling decisions to the * delegating de facto final scheduling decisions to the
* drive's internal scheduler, entails loss of control on the * drive's internal scheduler, entails loss of control on the
* actual request service order. In particular, the critical * actual request service order. In particular, the critical
...@@ -3644,26 +3641,13 @@ static bool idling_needed_for_service_guarantees(struct bfq_data *bfqd, ...@@ -3644,26 +3641,13 @@ static bool idling_needed_for_service_guarantees(struct bfq_data *bfqd,
* to let requests be served in the desired order until all * to let requests be served in the desired order until all
* the requests already queued in the device have been served. * the requests already queued in the device have been served.
*/ */
bool asymmetric_scenario = (bfqq->wr_coeff > 1 && static bool idling_needed_for_service_guarantees(struct bfq_data *bfqd,
struct bfq_queue *bfqq)
{
return (bfqq->wr_coeff > 1 &&
bfqd->wr_busy_queues < bfqd->wr_busy_queues <
bfq_tot_busy_queues(bfqd)) || bfq_tot_busy_queues(bfqd)) ||
!bfq_symmetric_scenario(bfqd); !bfq_symmetric_scenario(bfqd);
/*
* Finally, there is a case where maximizing throughput is the
* best choice even if it may cause unfairness toward
* bfqq. Such a case is when bfqq became active in a burst of
* queue activations. Queues that became active during a large
* burst benefit only from throughput, as discussed in the
* comments on bfq_handle_burst. Thus, if bfqq became active
* in a burst and not idling the device maximizes throughput,
* then the device must no be idled, because not idling the
* device provides bfqq and all other queues in the burst with
* maximum benefit. Combining this and the above case, we can
* now establish when idling is actually needed to preserve
* service guarantees.
*/
return asymmetric_scenario && !bfq_bfqq_in_large_burst(bfqq);
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment