1 |
From 3e2bdd6dff239afd8386e8758eee69ad61e5a3d6 Mon Sep 17 00:00:00 2001 |
2 |
From: Paolo Valente <paolo.valente@linaro.org> |
3 |
Date: Thu, 21 Sep 2017 11:04:01 +0200 |
4 |
Subject: [PATCH] block, bfq: check and switch back to interactive wr also on |
5 |
queue split |
6 |
|
7 |
As already explained in the message of commit "block, bfq: fix |
8 |
wrong init of saved start time for weight raising", if a soft |
9 |
real-time weight-raising period happens to be nested in a larger |
10 |
interactive weight-raising period, then BFQ restores the interactive |
11 |
weight raising at the end of the soft real-time weight raising. In |
12 |
particular, BFQ checks whether the latter has ended only on request |
13 |
dispatches. |
14 |
|
15 |
Unfortunately, the above scheme fails to restore interactive weight |
16 |
raising in the following corner case: if a bfq_queue, say Q, |
17 |
1) Is merged with another bfq_queue while it is in a nested soft |
18 |
real-time weight-raising period. The weight-raising state of Q is |
19 |
then saved, and not considered any longer until a split occurs. |
20 |
2) Is split from the other bfq_queue(s) at a time instant when its |
21 |
soft real-time weight raising is already finished. |
22 |
On the split, while resuming the previous, soft real-time |
23 |
weight-raised state of the bfq_queue Q, BFQ checks whether the |
24 |
current soft real-time weight-raising period is actually over. If so, |
25 |
BFQ switches weight raising off for Q, *without* checking whether the |
26 |
soft real-time period was actually nested in a non-yet-finished |
27 |
interactive weight-raising period. |
28 |
|
29 |
This commit addresses this issue by adding the above missing check in |
30 |
bfq_queue splits, and restoring interactive weight raising if needed. |
31 |
|
32 |
Signed-off-by: Paolo Valente <paolo.valente@linaro.org> |
33 |
Tested-by: Angelo Ruocco <angeloruocco90@gmail.com> |
34 |
Tested-by: Mirko Montanari <mirkomontanari91@gmail.com> |
35 |
Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name> |
36 |
Tested-by: Lee Tibbert <lee.tibbert@gmail.com> |
37 |
Signed-off-by: Jens Axboe <axboe@kernel.dk> |
38 |
--- |
39 |
block/bfq-iosched.c | 87 ++++++++++++++++++++++++++++++----------------------- |
40 |
1 file changed, 49 insertions(+), 38 deletions(-) |
41 |
|
42 |
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c |
43 |
index c25955c25e03..33b63bc4a64b 100644 |
44 |
--- a/block/bfq-iosched.c |
45 |
+++ b/block/bfq-iosched.c |
46 |
@@ -724,6 +724,44 @@ static void bfq_updated_next_req(struct bfq_data *bfqd, |
47 |
} |
48 |
} |
49 |
|
50 |
+static unsigned int bfq_wr_duration(struct bfq_data *bfqd) |
51 |
+{ |
52 |
+ u64 dur; |
53 |
+ |
54 |
+ if (bfqd->bfq_wr_max_time > 0) |
55 |
+ return bfqd->bfq_wr_max_time; |
56 |
+ |
57 |
+ dur = bfqd->RT_prod; |
58 |
+ do_div(dur, bfqd->peak_rate); |
59 |
+ |
60 |
+ /* |
61 |
+ * Limit duration between 3 and 13 seconds. Tests show that |
62 |
+ * higher values than 13 seconds often yield the opposite of |
63 |
+ * the desired result, i.e., worsen responsiveness by letting |
64 |
+ * non-interactive and non-soft-real-time applications |
65 |
+ * preserve weight raising for a too long time interval. |
66 |
+ * |
67 |
+ * On the other end, lower values than 3 seconds make it |
68 |
+ * difficult for most interactive tasks to complete their jobs |
69 |
+ * before weight-raising finishes. |
70 |
+ */ |
71 |
+ if (dur > msecs_to_jiffies(13000)) |
72 |
+ dur = msecs_to_jiffies(13000); |
73 |
+ else if (dur < msecs_to_jiffies(3000)) |
74 |
+ dur = msecs_to_jiffies(3000); |
75 |
+ |
76 |
+ return dur; |
77 |
+} |
78 |
+ |
79 |
+/* switch back from soft real-time to interactive weight raising */ |
80 |
+static void switch_back_to_interactive_wr(struct bfq_queue *bfqq, |
81 |
+ struct bfq_data *bfqd) |
82 |
+{ |
83 |
+ bfqq->wr_coeff = bfqd->bfq_wr_coeff; |
84 |
+ bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); |
85 |
+ bfqq->last_wr_start_finish = bfqq->wr_start_at_switch_to_srt; |
86 |
+} |
87 |
+ |
88 |
static void |
89 |
bfq_bfqq_resume_state(struct bfq_queue *bfqq, struct bfq_data *bfqd, |
90 |
struct bfq_io_cq *bic, bool bfq_already_existing) |
91 |
@@ -750,10 +788,16 @@ bfq_bfqq_resume_state(struct bfq_queue *bfqq, struct bfq_data *bfqd, |
92 |
if (bfqq->wr_coeff > 1 && (bfq_bfqq_in_large_burst(bfqq) || |
93 |
time_is_before_jiffies(bfqq->last_wr_start_finish + |
94 |
bfqq->wr_cur_max_time))) { |
95 |
- bfq_log_bfqq(bfqq->bfqd, bfqq, |
96 |
- "resume state: switching off wr"); |
97 |
- |
98 |
- bfqq->wr_coeff = 1; |
99 |
+ if (bfqq->wr_cur_max_time == bfqd->bfq_wr_rt_max_time && |
100 |
+ !bfq_bfqq_in_large_burst(bfqq) && |
101 |
+ time_is_after_eq_jiffies(bfqq->wr_start_at_switch_to_srt + |
102 |
+ bfq_wr_duration(bfqd))) { |
103 |
+ switch_back_to_interactive_wr(bfqq, bfqd); |
104 |
+ } else { |
105 |
+ bfqq->wr_coeff = 1; |
106 |
+ bfq_log_bfqq(bfqq->bfqd, bfqq, |
107 |
+ "resume state: switching off wr"); |
108 |
+ } |
109 |
} |
110 |
|
111 |
/* make sure weight will be updated, however we got here */ |
112 |
@@ -1173,35 +1217,6 @@ static bool bfq_bfqq_update_budg_for_activation(struct bfq_data *bfqd, |
113 |
return wr_or_deserves_wr; |
114 |
} |
115 |
|
116 |
-static unsigned int bfq_wr_duration(struct bfq_data *bfqd) |
117 |
-{ |
118 |
- u64 dur; |
119 |
- |
120 |
- if (bfqd->bfq_wr_max_time > 0) |
121 |
- return bfqd->bfq_wr_max_time; |
122 |
- |
123 |
- dur = bfqd->RT_prod; |
124 |
- do_div(dur, bfqd->peak_rate); |
125 |
- |
126 |
- /* |
127 |
- * Limit duration between 3 and 13 seconds. Tests show that |
128 |
- * higher values than 13 seconds often yield the opposite of |
129 |
- * the desired result, i.e., worsen responsiveness by letting |
130 |
- * non-interactive and non-soft-real-time applications |
131 |
- * preserve weight raising for a too long time interval. |
132 |
- * |
133 |
- * On the other end, lower values than 3 seconds make it |
134 |
- * difficult for most interactive tasks to complete their jobs |
135 |
- * before weight-raising finishes. |
136 |
- */ |
137 |
- if (dur > msecs_to_jiffies(13000)) |
138 |
- dur = msecs_to_jiffies(13000); |
139 |
- else if (dur < msecs_to_jiffies(3000)) |
140 |
- dur = msecs_to_jiffies(3000); |
141 |
- |
142 |
- return dur; |
143 |
-} |
144 |
- |
145 |
/* |
146 |
* Return the farthest future time instant according to jiffies |
147 |
* macros. |
148 |
@@ -3501,11 +3516,7 @@ static void bfq_update_wr_data(struct bfq_data *bfqd, struct bfq_queue *bfqq) |
149 |
bfq_wr_duration(bfqd))) |
150 |
bfq_bfqq_end_wr(bfqq); |
151 |
else { |
152 |
- /* switch back to interactive wr */ |
153 |
- bfqq->wr_coeff = bfqd->bfq_wr_coeff; |
154 |
- bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); |
155 |
- bfqq->last_wr_start_finish = |
156 |
- bfqq->wr_start_at_switch_to_srt; |
157 |
+ switch_back_to_interactive_wr(bfqq, bfqd); |
158 |
bfqq->entity.prio_changed = 1; |
159 |
} |
160 |
} |
161 |
-- |
162 |
2.15.1 |
163 |
|