block, bfq: re-schedule empty queues if they deserve I/O plugging
authorPaolo Valente <paolo.valente@linaro.org>
Tue, 25 Jun 2019 05:12:49 +0000 (07:12 +0200)
committerJens Axboe <axboe@kernel.dk>
Tue, 25 Jun 2019 15:07:35 +0000 (09:07 -0600)
commit3726112ec7316068625a1adefa101b9522c588ba
treef5ad1ad4c346988934097ebea81cceafcde834fc
parent96a291c38c329910738c002de83a9e3f6bf8c6e7
block, bfq: re-schedule empty queues if they deserve I/O plugging

Consider, on one side, a bfq_queue Q that remains empty while in
service, and, on the other side, the pending I/O of bfq_queues that,
according to their timestamps, have to be served after Q.  If an
uncontrolled amount of I/O from the latter bfq_queues were dispatched
while Q is waiting for its new I/O to arrive, then Q's bandwidth
guarantees would be violated. To prevent this, I/O dispatch is plugged
until Q receives new I/O (except for a properly controlled amount of
injected I/O). Unfortunately, preemption breaks I/O-dispatch plugging,
for the following reason.

Preemption is performed in two steps. First, Q is expired and
re-scheduled. Second, the new bfq_queue to serve is chosen. The first
step is needed by the second, as the second can be performed only
after Q's timestamps have been properly updated (done in the
expiration step), and Q has been re-queued for service. This
dependency is a consequence of the way how BFQ's scheduling algorithm
is currently implemented.

But Q is not re-scheduled at all in the first step, because Q is
empty. As a consequence, an uncontrolled amount of I/O may be
dispatched until Q becomes non empty again. This breaks Q's service
guarantees.

This commit addresses this issue by re-scheduling Q even if it is
empty. This in turn breaks the assumption that all scheduled queues
are non empty. Then a few extra checks are now needed.

Signed-off-by: Paolo Valente <paolo.valente@linaro.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
block/bfq-iosched.c