block, bfq: do not expire a queue when it is the only busy one
This commits preserves I/O-dispatch plugging for a special symmetric case that may suddenly turn into asymmetric: the case where only one bfq_queue, say bfqq, is busy. In this case, not expiring bfqq does not cause any harm to any other queues in terms of service guarantees. In contrast, it avoids the following unlucky sequence of events: (1) bfqq is expired, (2) a new queue with a lower weight than bfqq becomes busy (or more queues), (3) the new queue is served until a new request arrives for bfqq, (4) when bfqq is finally served, there are so many requests of the new queue in the drive that the pending requests for bfqq take a lot of time to be served. In particular, event (2) may case even already dispatched requests of bfqq to be delayed, inside the drive. So, to avoid this series of events, the scenario is preventively declared as asymmetric also if bfqq is the only busy queues. By doing so, I/O-dispatch plugging is performed for bfqq. Tested-by: Jan Kara <jack@suse.cz> Signed-off-by: Paolo Valente <paolo.valente@linaro.org> Signed-off-by: Jens Axboe <axboe@kernel.dk> (cherry picked from commit 2391d13ed484df1515f0025458e1f82317823fab) (cherry picked from commit 79827eb41d8fb0f838a2c592775a8e63caeb7c57) (cherry picked from commit 41720669259995fb7f064fc0f988c9d228750b37) (cherry picked from commit 07d273c955ea2c34a42f6de0f1e3f1bfb00c6ce1) (cherry picked from commit 8034c856b8fcafbef405eedddc12bb0625e52a42) (cherry picked from commit f49083d304bda30647196b550a109f528c8266dc) (cherry picked from commit 8a597f0ab5e7e83bfa426d071185c3d3ce5fa535)
This commit is contained in:
parent
5238084cd8
commit
4b23f1e69b
1 changed files with 20 additions and 2 deletions
|
@ -3500,20 +3500,38 @@ static void bfq_dispatch_remove(struct request_queue *q, struct request *rq)
|
|||
* order until all the requests already queued in the device have been
|
||||
* served. The last sub-condition commented above somewhat mitigates
|
||||
* this problem for weight-raised queues.
|
||||
*
|
||||
* However, as an additional mitigation for this problem, we preserve
|
||||
* plugging for a special symmetric case that may suddenly turn into
|
||||
* asymmetric: the case where only bfqq is busy. In this case, not
|
||||
* expiring bfqq does not cause any harm to any other queues in terms
|
||||
* of service guarantees. In contrast, it avoids the following unlucky
|
||||
* sequence of events: (1) bfqq is expired, (2) a new queue with a
|
||||
* lower weight than bfqq becomes busy (or more queues), (3) the new
|
||||
* queue is served until a new request arrives for bfqq, (4) when bfqq
|
||||
* is finally served, there are so many requests of the new queue in
|
||||
* the drive that the pending requests for bfqq take a lot of time to
|
||||
* be served. In particular, event (2) may case even already
|
||||
* dispatched requests of bfqq to be delayed, inside the drive. So, to
|
||||
* avoid this series of events, the scenario is preventively declared
|
||||
* as asymmetric also if bfqq is the only busy queues
|
||||
*/
|
||||
static bool idling_needed_for_service_guarantees(struct bfq_data *bfqd,
|
||||
struct bfq_queue *bfqq)
|
||||
{
|
||||
int tot_busy_queues = bfq_tot_busy_queues(bfqd);
|
||||
|
||||
/* No point in idling for bfqq if it won't get requests any longer */
|
||||
if (unlikely(!bfqq_process_refs(bfqq)))
|
||||
return false;
|
||||
|
||||
return (bfqq->wr_coeff > 1 &&
|
||||
(bfqd->wr_busy_queues <
|
||||
bfq_tot_busy_queues(bfqd) ||
|
||||
tot_busy_queues ||
|
||||
bfqd->rq_in_driver >=
|
||||
bfqq->dispatched + 4)) ||
|
||||
bfq_asymmetric_scenario(bfqd, bfqq);
|
||||
bfq_asymmetric_scenario(bfqd, bfqq) ||
|
||||
tot_busy_queues == 1;
|
||||
}
|
||||
|
||||
static bool __bfq_bfqq_expire(struct bfq_data *bfqd, struct bfq_queue *bfqq,
|
||||
|
|
Loading…
Add table
Reference in a new issue