summaryrefslogtreecommitdiffstats
path: root/block/bfq-iosched.c
diff options
context:
space:
mode:
authorPaolo Valente <paolo.valente@linaro.org>2017-09-21 05:04:01 -0400
committerJens Axboe <axboe@kernel.dk>2017-10-03 10:40:56 -0400
commit3e2bdd6dff239afd8386e8758eee69ad61e5a3d6 (patch)
tree3ccfb0f7d06d7022e801b06f0d5fece31a054044 /block/bfq-iosched.c
parent4baa8bb13f41307f3eb62fe91f93a1a798ebef53 (diff)
block, bfq: check and switch back to interactive wr also on queue split
As already explained in the message of commit "block, bfq: fix wrong init of saved start time for weight raising", if a soft real-time weight-raising period happens to be nested in a larger interactive weight-raising period, then BFQ restores the interactive weight raising at the end of the soft real-time weight raising. In particular, BFQ checks whether the latter has ended only on request dispatches. Unfortunately, the above scheme fails to restore interactive weight raising in the following corner case: if a bfq_queue, say Q, 1) Is merged with another bfq_queue while it is in a nested soft real-time weight-raising period. The weight-raising state of Q is then saved, and not considered any longer until a split occurs. 2) Is split from the other bfq_queue(s) at a time instant when its soft real-time weight raising is already finished. On the split, while resuming the previous, soft real-time weight-raised state of the bfq_queue Q, BFQ checks whether the current soft real-time weight-raising period is actually over. If so, BFQ switches weight raising off for Q, *without* checking whether the soft real-time period was actually nested in a non-yet-finished interactive weight-raising period. This commit addresses this issue by adding the above missing check in bfq_queue splits, and restoring interactive weight raising if needed. Signed-off-by: Paolo Valente <paolo.valente@linaro.org> Tested-by: Angelo Ruocco <angeloruocco90@gmail.com> Tested-by: Mirko Montanari <mirkomontanari91@gmail.com> Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name> Tested-by: Lee Tibbert <lee.tibbert@gmail.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block/bfq-iosched.c')
-rw-r--r--block/bfq-iosched.c87
1 files changed, 49 insertions, 38 deletions
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
index c25955c25e03..33b63bc4a64b 100644
--- a/block/bfq-iosched.c
+++ b/block/bfq-iosched.c
@@ -724,6 +724,44 @@ static void bfq_updated_next_req(struct bfq_data *bfqd,
724 } 724 }
725} 725}
726 726
727static unsigned int bfq_wr_duration(struct bfq_data *bfqd)
728{
729 u64 dur;
730
731 if (bfqd->bfq_wr_max_time > 0)
732 return bfqd->bfq_wr_max_time;
733
734 dur = bfqd->RT_prod;
735 do_div(dur, bfqd->peak_rate);
736
737 /*
738 * Limit duration between 3 and 13 seconds. Tests show that
739 * higher values than 13 seconds often yield the opposite of
740 * the desired result, i.e., worsen responsiveness by letting
741 * non-interactive and non-soft-real-time applications
742 * preserve weight raising for a too long time interval.
743 *
744 * On the other end, lower values than 3 seconds make it
745 * difficult for most interactive tasks to complete their jobs
746 * before weight-raising finishes.
747 */
748 if (dur > msecs_to_jiffies(13000))
749 dur = msecs_to_jiffies(13000);
750 else if (dur < msecs_to_jiffies(3000))
751 dur = msecs_to_jiffies(3000);
752
753 return dur;
754}
755
756/* switch back from soft real-time to interactive weight raising */
757static void switch_back_to_interactive_wr(struct bfq_queue *bfqq,
758 struct bfq_data *bfqd)
759{
760 bfqq->wr_coeff = bfqd->bfq_wr_coeff;
761 bfqq->wr_cur_max_time = bfq_wr_duration(bfqd);
762 bfqq->last_wr_start_finish = bfqq->wr_start_at_switch_to_srt;
763}
764
727static void 765static void
728bfq_bfqq_resume_state(struct bfq_queue *bfqq, struct bfq_data *bfqd, 766bfq_bfqq_resume_state(struct bfq_queue *bfqq, struct bfq_data *bfqd,
729 struct bfq_io_cq *bic, bool bfq_already_existing) 767 struct bfq_io_cq *bic, bool bfq_already_existing)
@@ -750,10 +788,16 @@ bfq_bfqq_resume_state(struct bfq_queue *bfqq, struct bfq_data *bfqd,
750 if (bfqq->wr_coeff > 1 && (bfq_bfqq_in_large_burst(bfqq) || 788 if (bfqq->wr_coeff > 1 && (bfq_bfqq_in_large_burst(bfqq) ||
751 time_is_before_jiffies(bfqq->last_wr_start_finish + 789 time_is_before_jiffies(bfqq->last_wr_start_finish +
752 bfqq->wr_cur_max_time))) { 790 bfqq->wr_cur_max_time))) {
753 bfq_log_bfqq(bfqq->bfqd, bfqq, 791 if (bfqq->wr_cur_max_time == bfqd->bfq_wr_rt_max_time &&
754 "resume state: switching off wr"); 792 !bfq_bfqq_in_large_burst(bfqq) &&
755 793 time_is_after_eq_jiffies(bfqq->wr_start_at_switch_to_srt +
756 bfqq->wr_coeff = 1; 794 bfq_wr_duration(bfqd))) {
795 switch_back_to_interactive_wr(bfqq, bfqd);
796 } else {
797 bfqq->wr_coeff = 1;
798 bfq_log_bfqq(bfqq->bfqd, bfqq,
799 "resume state: switching off wr");
800 }
757 } 801 }
758 802
759 /* make sure weight will be updated, however we got here */ 803 /* make sure weight will be updated, however we got here */
@@ -1173,35 +1217,6 @@ static bool bfq_bfqq_update_budg_for_activation(struct bfq_data *bfqd,
1173 return wr_or_deserves_wr; 1217 return wr_or_deserves_wr;
1174} 1218}
1175 1219
1176static unsigned int bfq_wr_duration(struct bfq_data *bfqd)
1177{
1178 u64 dur;
1179
1180 if (bfqd->bfq_wr_max_time > 0)
1181 return bfqd->bfq_wr_max_time;
1182
1183 dur = bfqd->RT_prod;
1184 do_div(dur, bfqd->peak_rate);
1185
1186 /*
1187 * Limit duration between 3 and 13 seconds. Tests show that
1188 * higher values than 13 seconds often yield the opposite of
1189 * the desired result, i.e., worsen responsiveness by letting
1190 * non-interactive and non-soft-real-time applications
1191 * preserve weight raising for a too long time interval.
1192 *
1193 * On the other end, lower values than 3 seconds make it
1194 * difficult for most interactive tasks to complete their jobs
1195 * before weight-raising finishes.
1196 */
1197 if (dur > msecs_to_jiffies(13000))
1198 dur = msecs_to_jiffies(13000);
1199 else if (dur < msecs_to_jiffies(3000))
1200 dur = msecs_to_jiffies(3000);
1201
1202 return dur;
1203}
1204
1205/* 1220/*
1206 * Return the farthest future time instant according to jiffies 1221 * Return the farthest future time instant according to jiffies
1207 * macros. 1222 * macros.
@@ -3501,11 +3516,7 @@ static void bfq_update_wr_data(struct bfq_data *bfqd, struct bfq_queue *bfqq)
3501 bfq_wr_duration(bfqd))) 3516 bfq_wr_duration(bfqd)))
3502 bfq_bfqq_end_wr(bfqq); 3517 bfq_bfqq_end_wr(bfqq);
3503 else { 3518 else {
3504 /* switch back to interactive wr */ 3519 switch_back_to_interactive_wr(bfqq, bfqd);
3505 bfqq->wr_coeff = bfqd->bfq_wr_coeff;
3506 bfqq->wr_cur_max_time = bfq_wr_duration(bfqd);
3507 bfqq->last_wr_start_finish =
3508 bfqq->wr_start_at_switch_to_srt;
3509 bfqq->entity.prio_changed = 1; 3520 bfqq->entity.prio_changed = 1;
3510 } 3521 }
3511 } 3522 }