summaryrefslogtreecommitdiffstats
path: root/block/bfq-iosched.c
diff options
context:
space:
mode:
authorPaolo Valente <paolo.valente@linaro.org>2018-03-26 10:06:24 -0400
committerJens Axboe <axboe@kernel.dk>2018-03-26 12:18:27 -0400
commitbc56e2cafa3f80954a278d74bd18349ac3cb8fa5 (patch)
treebf66485253e3055c244b2475c063e66b90657bc3 /block/bfq-iosched.c
parentd558fb51ad3dc7d5f1287d55d0f2e0646af36253 (diff)
block, bfq: lower-bound the estimated peak rate to 1
If a storage device handled by BFQ happens to be slower than 7.5 KB/s for a certain amount of time (in the order of a second), then the estimated peak rate of the device, maintained in BFQ, becomes equal to 0. The reason is the limited precision with which the rate is represented (details on the range of representable values in the comments introduced by this commit). This leads to a division-by-zero error where the estimated peak rate is used as divisor. Such a type of failure has been reported in [1]. This commit addresses this issue by: 1. Lower-bounding the estimated peak rate to 1 2. Adding and improving comments on the range of rates representable [1] https://www.spinics.net/lists/kernel/msg2739205.html Signed-off-by: Konstantin Khlebnikov <khlebnikov@yandex-team.ru> Signed-off-by: Paolo Valente <paolo.valente@linaro.org> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block/bfq-iosched.c')
-rw-r--r--block/bfq-iosched.c25
1 files changed, 24 insertions, 1 deletions
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
index aeca22d91101..f0ecd98509d8 100644
--- a/block/bfq-iosched.c
+++ b/block/bfq-iosched.c
@@ -201,7 +201,20 @@ static struct kmem_cache *bfq_pool;
201/* Target observation time interval for a peak-rate update (ns) */ 201/* Target observation time interval for a peak-rate update (ns) */
202#define BFQ_RATE_REF_INTERVAL NSEC_PER_SEC 202#define BFQ_RATE_REF_INTERVAL NSEC_PER_SEC
203 203
204/* Shift used for peak rate fixed precision calculations. */ 204/*
205 * Shift used for peak-rate fixed precision calculations.
206 * With
207 * - the current shift: 16 positions
208 * - the current type used to store rate: u32
209 * - the current unit of measure for rate: [sectors/usec], or, more precisely,
210 * [(sectors/usec) / 2^BFQ_RATE_SHIFT] to take into account the shift,
211 * the range of rates that can be stored is
212 * [1 / 2^BFQ_RATE_SHIFT, 2^(32 - BFQ_RATE_SHIFT)] sectors/usec =
213 * [1 / 2^16, 2^16] sectors/usec = [15e-6, 65536] sectors/usec =
214 * [15, 65G] sectors/sec
215 * Which, assuming a sector size of 512B, corresponds to a range of
216 * [7.5K, 33T] B/sec
217 */
205#define BFQ_RATE_SHIFT 16 218#define BFQ_RATE_SHIFT 16
206 219
207/* 220/*
@@ -2637,6 +2650,16 @@ static void bfq_update_rate_reset(struct bfq_data *bfqd, struct request *rq)
2637 rate /= divisor; /* smoothing constant alpha = 1/divisor */ 2650 rate /= divisor; /* smoothing constant alpha = 1/divisor */
2638 2651
2639 bfqd->peak_rate += rate; 2652 bfqd->peak_rate += rate;
2653
2654 /*
2655 * For a very slow device, bfqd->peak_rate can reach 0 (see
2656 * the minimum representable values reported in the comments
2657 * on BFQ_RATE_SHIFT). Push to 1 if this happens, to avoid
2658 * divisions by zero where bfqd->peak_rate is used as a
2659 * divisor.
2660 */
2661 bfqd->peak_rate = max_t(u32, 1, bfqd->peak_rate);
2662
2640 update_thr_responsiveness_params(bfqd); 2663 update_thr_responsiveness_params(bfqd);
2641 2664
2642reset_computation: 2665reset_computation: