Commit f718b093 authored by Paolo Valente's avatar Paolo Valente Committed by Jens Axboe

block, bfq: do not plug I/O for bfq_queues with no proc refs

Commit 478de338 ("block, bfq: deschedule empty bfq_queues not
referred by any process") fixed commit 3726112e ("block, bfq:
re-schedule empty queues if they deserve I/O plugging") by
descheduling an empty bfq_queue when it remains with not process
reference. Yet, this still left a case uncovered: an empty bfq_queue
with not process reference that remains in service. This happens for
an in-service sync bfq_queue that is deemed to deserve I/O-dispatch
plugging when it remains empty. Yet no new requests will arrive for
such a bfq_queue if no process sends requests to it any longer. Even
worse, the bfq_queue may happen to be prematurely freed while still in
service (because there may remain no reference to it any longer).

This commit solves this problem by preventing I/O dispatch from being
plugged for the in-service bfq_queue, if the latter has no process
reference (the bfq_queue is then prevented from remaining in service).

Fixes: 3726112e ("block, bfq: re-schedule empty queues if they deserve I/O plugging")
Tested-by: default avatarOleksandr Natalenko <oleksandr@natalenko.name>
Reported-by: default avatarPatrick Dung <patdung100@gmail.com>
Tested-by: default avatarPatrick Dung <patdung100@gmail.com>
Signed-off-by: default avatarPaolo Valente <paolo.valente@linaro.org>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 49d08d59
...@@ -3443,6 +3443,10 @@ static void bfq_dispatch_remove(struct request_queue *q, struct request *rq) ...@@ -3443,6 +3443,10 @@ static void bfq_dispatch_remove(struct request_queue *q, struct request *rq)
static bool idling_needed_for_service_guarantees(struct bfq_data *bfqd, static bool idling_needed_for_service_guarantees(struct bfq_data *bfqd,
struct bfq_queue *bfqq) struct bfq_queue *bfqq)
{ {
/* 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 && return (bfqq->wr_coeff > 1 &&
(bfqd->wr_busy_queues < (bfqd->wr_busy_queues <
bfq_tot_busy_queues(bfqd) || bfq_tot_busy_queues(bfqd) ||
...@@ -4076,6 +4080,10 @@ static bool idling_boosts_thr_without_issues(struct bfq_data *bfqd, ...@@ -4076,6 +4080,10 @@ static bool idling_boosts_thr_without_issues(struct bfq_data *bfqd,
bfqq_sequential_and_IO_bound, bfqq_sequential_and_IO_bound,
idling_boosts_thr; idling_boosts_thr;
/* No point in idling for bfqq if it won't get requests any longer */
if (unlikely(!bfqq_process_refs(bfqq)))
return false;
bfqq_sequential_and_IO_bound = !BFQQ_SEEKY(bfqq) && bfqq_sequential_and_IO_bound = !BFQQ_SEEKY(bfqq) &&
bfq_bfqq_IO_bound(bfqq) && bfq_bfqq_has_short_ttime(bfqq); bfq_bfqq_IO_bound(bfqq) && bfq_bfqq_has_short_ttime(bfqq);
...@@ -4169,6 +4177,10 @@ static bool bfq_better_to_idle(struct bfq_queue *bfqq) ...@@ -4169,6 +4177,10 @@ static bool bfq_better_to_idle(struct bfq_queue *bfqq)
struct bfq_data *bfqd = bfqq->bfqd; struct bfq_data *bfqd = bfqq->bfqd;
bool idling_boosts_thr_with_no_issue, idling_needed_for_service_guar; bool idling_boosts_thr_with_no_issue, idling_needed_for_service_guar;
/* No point in idling for bfqq if it won't get requests any longer */
if (unlikely(!bfqq_process_refs(bfqq)))
return false;
if (unlikely(bfqd->strict_guarantees)) if (unlikely(bfqd->strict_guarantees))
return true; return true;
......
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