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: Paolo Valente <paolo.valente@linaro.org> Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
ac8b0cb415
commit
530c4cbb3c
|
@ -3479,15 +3479,12 @@ static bool idling_boosts_thr_without_issues(struct bfq_data *bfqd,
|
|||
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
|
||||
* throughput concerns, but to preserve service guarantees.
|
||||
*
|
||||
* 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
|
||||
* drive's internal scheduler, entails loss of control on the
|
||||
* actual request service order. In particular, the critical
|
||||
|
@ -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
|
||||
* 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 <
|
||||
bfq_tot_busy_queues(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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue