Skip to content

Commit

Permalink
block, bfq: do not expire a queue when it is the only busy one
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Paolo Valente <[email protected]>
Signed-off-by: Jens Axboe <[email protected]>
  • Loading branch information
Algodev-github authored and axboe committed Jan 25, 2021
1 parent 3c33769 commit 2391d13
Showing 1 changed file with 20 additions and 2 deletions.
22 changes: 20 additions & 2 deletions block/bfq-iosched.c
Original file line number Diff line number Diff line change
Expand Up @@ -3464,20 +3464,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,
Expand Down

0 comments on commit 2391d13

Please sign in to comment.