1 |
commit: 41cf3e1a269f2ff1d94992251fbc4e65e0c35417 |
2 |
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org> |
3 |
AuthorDate: Sat Nov 29 18:03:46 2014 +0000 |
4 |
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org> |
5 |
CommitDate: Sat Nov 29 18:03:46 2014 +0000 |
6 |
URL: http://sources.gentoo.org/gitweb/?p=proj/linux-patches.git;a=commit;h=41cf3e1a |
7 |
|
8 |
Bump BFQ patchset to v7r6-3.16 |
9 |
|
10 |
--- |
11 |
...-cgroups-kconfig-build-bits-for-v7r6-3.16.patch | 6 +- |
12 |
...ck-introduce-the-v7r6-I-O-sched-for-3.17.patch1 | 421 ++++++++++++++++++--- |
13 |
...add-Early-Queue-Merge-EQM-v7r6-for-3.16.0.patch | 194 ++++++---- |
14 |
3 files changed, 474 insertions(+), 147 deletions(-) |
15 |
|
16 |
diff --git a/5001_BFQ-1-block-cgroups-kconfig-build-bits-for-v7r5-3.16.patch b/5001_BFQ-1-block-cgroups-kconfig-build-bits-for-v7r6-3.16.patch |
17 |
similarity index 97% |
18 |
rename from 5001_BFQ-1-block-cgroups-kconfig-build-bits-for-v7r5-3.16.patch |
19 |
rename to 5001_BFQ-1-block-cgroups-kconfig-build-bits-for-v7r6-3.16.patch |
20 |
index 088bd05..7f6a5f4 100644 |
21 |
--- a/5001_BFQ-1-block-cgroups-kconfig-build-bits-for-v7r5-3.16.patch |
22 |
+++ b/5001_BFQ-1-block-cgroups-kconfig-build-bits-for-v7r6-3.16.patch |
23 |
@@ -1,7 +1,7 @@ |
24 |
-From 6519e5beef1063a86d3fc917cff2592cb599e824 Mon Sep 17 00:00:00 2001 |
25 |
+From 92ef290b97a50b9d60eb928166413140cd7a4802 Mon Sep 17 00:00:00 2001 |
26 |
From: Paolo Valente <paolo.valente@×××××××.it> |
27 |
Date: Thu, 22 May 2014 11:59:35 +0200 |
28 |
-Subject: [PATCH 1/3] block: cgroups, kconfig, build bits for BFQ-v7r5-3.16 |
29 |
+Subject: [PATCH 1/3] block: cgroups, kconfig, build bits for BFQ-v7r6-3.16 |
30 |
|
31 |
Update Kconfig.iosched and do the related Makefile changes to include |
32 |
kernel configuration options for BFQ. Also add the bfqio controller |
33 |
@@ -100,5 +100,5 @@ index 98c4f9b..13b010d 100644 |
34 |
SUBSYS(perf_event) |
35 |
#endif |
36 |
-- |
37 |
-2.0.3 |
38 |
+2.1.2 |
39 |
|
40 |
|
41 |
diff --git a/5002_BFQ-2-block-introduce-the-v7r5-I-O-sched-for-3.16.patch1 b/5002_BFQ-2-block-introduce-the-v7r6-I-O-sched-for-3.17.patch1 |
42 |
similarity index 92% |
43 |
rename from 5002_BFQ-2-block-introduce-the-v7r5-I-O-sched-for-3.16.patch1 |
44 |
rename to 5002_BFQ-2-block-introduce-the-v7r6-I-O-sched-for-3.17.patch1 |
45 |
index 6f630ba..7ae3298 100644 |
46 |
--- a/5002_BFQ-2-block-introduce-the-v7r5-I-O-sched-for-3.16.patch1 |
47 |
+++ b/5002_BFQ-2-block-introduce-the-v7r6-I-O-sched-for-3.17.patch1 |
48 |
@@ -1,9 +1,9 @@ |
49 |
-From c56e6c5db41f7137d3e0b38063ef0c944eec1898 Mon Sep 17 00:00:00 2001 |
50 |
+From e4fcd78909604194d930e38874a9313090b80348 Mon Sep 17 00:00:00 2001 |
51 |
From: Paolo Valente <paolo.valente@×××××××.it> |
52 |
Date: Thu, 9 May 2013 19:10:02 +0200 |
53 |
-Subject: [PATCH 2/3] block: introduce the BFQ-v7r5 I/O sched for 3.16 |
54 |
+Subject: [PATCH 2/3] block: introduce the BFQ-v7r6 I/O sched for 3.16 |
55 |
|
56 |
-Add the BFQ-v7r5 I/O scheduler to 3.16. |
57 |
+Add the BFQ-v7r6 I/O scheduler to 3.16. |
58 |
The general structure is borrowed from CFQ, as much of the code for |
59 |
handling I/O contexts. Over time, several useful features have been |
60 |
ported from CFQ as well (details in the changelog in README.BFQ). A |
61 |
@@ -56,12 +56,12 @@ until it expires. |
62 |
Signed-off-by: Paolo Valente <paolo.valente@×××××××.it> |
63 |
Signed-off-by: Arianna Avanzini <avanzini.arianna@×××××.com> |
64 |
--- |
65 |
- block/bfq-cgroup.c | 930 +++++++++++++ |
66 |
+ block/bfq-cgroup.c | 930 ++++++++++++ |
67 |
block/bfq-ioc.c | 36 + |
68 |
- block/bfq-iosched.c | 3617 +++++++++++++++++++++++++++++++++++++++++++++++++++ |
69 |
- block/bfq-sched.c | 1207 +++++++++++++++++ |
70 |
- block/bfq.h | 742 +++++++++++ |
71 |
- 5 files changed, 6532 insertions(+) |
72 |
+ block/bfq-iosched.c | 3887 +++++++++++++++++++++++++++++++++++++++++++++++++++ |
73 |
+ block/bfq-sched.c | 1207 ++++++++++++++++ |
74 |
+ block/bfq.h | 773 ++++++++++ |
75 |
+ 5 files changed, 6833 insertions(+) |
76 |
create mode 100644 block/bfq-cgroup.c |
77 |
create mode 100644 block/bfq-ioc.c |
78 |
create mode 100644 block/bfq-iosched.c |
79 |
@@ -1048,10 +1048,10 @@ index 0000000..7f6b000 |
80 |
+} |
81 |
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c |
82 |
new file mode 100644 |
83 |
-index 0000000..0a0891b |
84 |
+index 0000000..b919b03 |
85 |
--- /dev/null |
86 |
+++ b/block/bfq-iosched.c |
87 |
-@@ -0,0 +1,3617 @@ |
88 |
+@@ -0,0 +1,3887 @@ |
89 |
+/* |
90 |
+ * Budget Fair Queueing (BFQ) disk scheduler. |
91 |
+ * |
92 |
@@ -1625,6 +1625,220 @@ index 0000000..0a0891b |
93 |
+ return dur; |
94 |
+} |
95 |
+ |
96 |
++/* Empty burst list and add just bfqq (see comments to bfq_handle_burst) */ |
97 |
++static inline void bfq_reset_burst_list(struct bfq_data *bfqd, |
98 |
++ struct bfq_queue *bfqq) |
99 |
++{ |
100 |
++ struct bfq_queue *item; |
101 |
++ struct hlist_node *n; |
102 |
++ |
103 |
++ hlist_for_each_entry_safe(item, n, &bfqd->burst_list, burst_list_node) |
104 |
++ hlist_del_init(&item->burst_list_node); |
105 |
++ hlist_add_head(&bfqq->burst_list_node, &bfqd->burst_list); |
106 |
++ bfqd->burst_size = 1; |
107 |
++} |
108 |
++ |
109 |
++/* Add bfqq to the list of queues in current burst (see bfq_handle_burst) */ |
110 |
++static void bfq_add_to_burst(struct bfq_data *bfqd, struct bfq_queue *bfqq) |
111 |
++{ |
112 |
++ /* Increment burst size to take into account also bfqq */ |
113 |
++ bfqd->burst_size++; |
114 |
++ |
115 |
++ if (bfqd->burst_size == bfqd->bfq_large_burst_thresh) { |
116 |
++ struct bfq_queue *pos, *bfqq_item; |
117 |
++ struct hlist_node *n; |
118 |
++ |
119 |
++ /* |
120 |
++ * Enough queues have been activated shortly after each |
121 |
++ * other to consider this burst as large. |
122 |
++ */ |
123 |
++ bfqd->large_burst = true; |
124 |
++ |
125 |
++ /* |
126 |
++ * We can now mark all queues in the burst list as |
127 |
++ * belonging to a large burst. |
128 |
++ */ |
129 |
++ hlist_for_each_entry(bfqq_item, &bfqd->burst_list, |
130 |
++ burst_list_node) |
131 |
++ bfq_mark_bfqq_in_large_burst(bfqq_item); |
132 |
++ bfq_mark_bfqq_in_large_burst(bfqq); |
133 |
++ |
134 |
++ /* |
135 |
++ * From now on, and until the current burst finishes, any |
136 |
++ * new queue being activated shortly after the last queue |
137 |
++ * was inserted in the burst can be immediately marked as |
138 |
++ * belonging to a large burst. So the burst list is not |
139 |
++ * needed any more. Remove it. |
140 |
++ */ |
141 |
++ hlist_for_each_entry_safe(pos, n, &bfqd->burst_list, |
142 |
++ burst_list_node) |
143 |
++ hlist_del_init(&pos->burst_list_node); |
144 |
++ } else /* burst not yet large: add bfqq to the burst list */ |
145 |
++ hlist_add_head(&bfqq->burst_list_node, &bfqd->burst_list); |
146 |
++} |
147 |
++ |
148 |
++/* |
149 |
++ * If many queues happen to become active shortly after each other, then, |
150 |
++ * to help the processes associated to these queues get their job done as |
151 |
++ * soon as possible, it is usually better to not grant either weight-raising |
152 |
++ * or device idling to these queues. In this comment we describe, firstly, |
153 |
++ * the reasons why this fact holds, and, secondly, the next function, which |
154 |
++ * implements the main steps needed to properly mark these queues so that |
155 |
++ * they can then be treated in a different way. |
156 |
++ * |
157 |
++ * As for the terminology, we say that a queue becomes active, i.e., |
158 |
++ * switches from idle to backlogged, either when it is created (as a |
159 |
++ * consequence of the arrival of an I/O request), or, if already existing, |
160 |
++ * when a new request for the queue arrives while the queue is idle. |
161 |
++ * Bursts of activations, i.e., activations of different queues occurring |
162 |
++ * shortly after each other, are typically caused by services or applications |
163 |
++ * that spawn or reactivate many parallel threads/processes. Examples are |
164 |
++ * systemd during boot or git grep. |
165 |
++ * |
166 |
++ * These services or applications benefit mostly from a high throughput: |
167 |
++ * the quicker the requests of the activated queues are cumulatively served, |
168 |
++ * the sooner the target job of these queues gets completed. As a consequence, |
169 |
++ * weight-raising any of these queues, which also implies idling the device |
170 |
++ * for it, is almost always counterproductive: in most cases it just lowers |
171 |
++ * throughput. |
172 |
++ * |
173 |
++ * On the other hand, a burst of activations may be also caused by the start |
174 |
++ * of an application that does not consist in a lot of parallel I/O-bound |
175 |
++ * threads. In fact, with a complex application, the burst may be just a |
176 |
++ * consequence of the fact that several processes need to be executed to |
177 |
++ * start-up the application. To start an application as quickly as possible, |
178 |
++ * the best thing to do is to privilege the I/O related to the application |
179 |
++ * with respect to all other I/O. Therefore, the best strategy to start as |
180 |
++ * quickly as possible an application that causes a burst of activations is |
181 |
++ * to weight-raise all the queues activated during the burst. This is the |
182 |
++ * exact opposite of the best strategy for the other type of bursts. |
183 |
++ * |
184 |
++ * In the end, to take the best action for each of the two cases, the two |
185 |
++ * types of bursts need to be distinguished. Fortunately, this seems |
186 |
++ * relatively easy to do, by looking at the sizes of the bursts. In |
187 |
++ * particular, we found a threshold such that bursts with a larger size |
188 |
++ * than that threshold are apparently caused only by services or commands |
189 |
++ * such as systemd or git grep. For brevity, hereafter we call just 'large' |
190 |
++ * these bursts. BFQ *does not* weight-raise queues whose activations occur |
191 |
++ * in a large burst. In addition, for each of these queues BFQ performs or |
192 |
++ * does not perform idling depending on which choice boosts the throughput |
193 |
++ * most. The exact choice depends on the device and request pattern at |
194 |
++ * hand. |
195 |
++ * |
196 |
++ * Turning back to the next function, it implements all the steps needed |
197 |
++ * to detect the occurrence of a large burst and to properly mark all the |
198 |
++ * queues belonging to it (so that they can then be treated in a different |
199 |
++ * way). This goal is achieved by maintaining a special "burst list" that |
200 |
++ * holds, temporarily, the queues that belong to the burst in progress. The |
201 |
++ * list is then used to mark these queues as belonging to a large burst if |
202 |
++ * the burst does become large. The main steps are the following. |
203 |
++ * |
204 |
++ * . when the very first queue is activated, the queue is inserted into the |
205 |
++ * list (as it could be the first queue in a possible burst) |
206 |
++ * |
207 |
++ * . if the current burst has not yet become large, and a queue Q that does |
208 |
++ * not yet belong to the burst is activated shortly after the last time |
209 |
++ * at which a new queue entered the burst list, then the function appends |
210 |
++ * Q to the burst list |
211 |
++ * |
212 |
++ * . if, as a consequence of the previous step, the burst size reaches |
213 |
++ * the large-burst threshold, then |
214 |
++ * |
215 |
++ * . all the queues in the burst list are marked as belonging to a |
216 |
++ * large burst |
217 |
++ * |
218 |
++ * . the burst list is deleted; in fact, the burst list already served |
219 |
++ * its purpose (keeping temporarily track of the queues in a burst, |
220 |
++ * so as to be able to mark them as belonging to a large burst in the |
221 |
++ * previous sub-step), and now is not needed any more |
222 |
++ * |
223 |
++ * . the device enters a large-burst mode |
224 |
++ * |
225 |
++ * . if a queue Q that does not belong to the burst is activated while |
226 |
++ * the device is in large-burst mode and shortly after the last time |
227 |
++ * at which a queue either entered the burst list or was marked as |
228 |
++ * belonging to the current large burst, then Q is immediately marked |
229 |
++ * as belonging to a large burst. |
230 |
++ * |
231 |
++ * . if a queue Q that does not belong to the burst is activated a while |
232 |
++ * later, i.e., not shortly after, than the last time at which a queue |
233 |
++ * either entered the burst list or was marked as belonging to the |
234 |
++ * current large burst, then the current burst is deemed as finished and: |
235 |
++ * |
236 |
++ * . the large-burst mode is reset if set |
237 |
++ * |
238 |
++ * . the burst list is emptied |
239 |
++ * |
240 |
++ * . Q is inserted in the burst list, as Q may be the first queue |
241 |
++ * in a possible new burst (then the burst list contains just Q |
242 |
++ * after this step). |
243 |
++ */ |
244 |
++static void bfq_handle_burst(struct bfq_data *bfqd, struct bfq_queue *bfqq, |
245 |
++ bool idle_for_long_time) |
246 |
++{ |
247 |
++ /* |
248 |
++ * If bfqq happened to be activated in a burst, but has been idle |
249 |
++ * for at least as long as an interactive queue, then we assume |
250 |
++ * that, in the overall I/O initiated in the burst, the I/O |
251 |
++ * associated to bfqq is finished. So bfqq does not need to be |
252 |
++ * treated as a queue belonging to a burst anymore. Accordingly, |
253 |
++ * we reset bfqq's in_large_burst flag if set, and remove bfqq |
254 |
++ * from the burst list if it's there. We do not decrement instead |
255 |
++ * burst_size, because the fact that bfqq does not need to belong |
256 |
++ * to the burst list any more does not invalidate the fact that |
257 |
++ * bfqq may have been activated during the current burst. |
258 |
++ */ |
259 |
++ if (idle_for_long_time) { |
260 |
++ hlist_del_init(&bfqq->burst_list_node); |
261 |
++ bfq_clear_bfqq_in_large_burst(bfqq); |
262 |
++ } |
263 |
++ |
264 |
++ /* |
265 |
++ * If bfqq is already in the burst list or is part of a large |
266 |
++ * burst, then there is nothing else to do. |
267 |
++ */ |
268 |
++ if (!hlist_unhashed(&bfqq->burst_list_node) || |
269 |
++ bfq_bfqq_in_large_burst(bfqq)) |
270 |
++ return; |
271 |
++ |
272 |
++ /* |
273 |
++ * If bfqq's activation happens late enough, then the current |
274 |
++ * burst is finished, and related data structures must be reset. |
275 |
++ * |
276 |
++ * In this respect, consider the special case where bfqq is the very |
277 |
++ * first queue being activated. In this case, last_ins_in_burst is |
278 |
++ * not yet significant when we get here. But it is easy to verify |
279 |
++ * that, whether or not the following condition is true, bfqq will |
280 |
++ * end up being inserted into the burst list. In particular the |
281 |
++ * list will happen to contain only bfqq. And this is exactly what |
282 |
++ * has to happen, as bfqq may be the first queue in a possible |
283 |
++ * burst. |
284 |
++ */ |
285 |
++ if (time_is_before_jiffies(bfqd->last_ins_in_burst + |
286 |
++ bfqd->bfq_burst_interval)) { |
287 |
++ bfqd->large_burst = false; |
288 |
++ bfq_reset_burst_list(bfqd, bfqq); |
289 |
++ return; |
290 |
++ } |
291 |
++ |
292 |
++ /* |
293 |
++ * If we get here, then bfqq is being activated shortly after the |
294 |
++ * last queue. So, if the current burst is also large, we can mark |
295 |
++ * bfqq as belonging to this large burst immediately. |
296 |
++ */ |
297 |
++ if (bfqd->large_burst) { |
298 |
++ bfq_mark_bfqq_in_large_burst(bfqq); |
299 |
++ return; |
300 |
++ } |
301 |
++ |
302 |
++ /* |
303 |
++ * If we get here, then a large-burst state has not yet been |
304 |
++ * reached, but bfqq is being activated shortly after the last |
305 |
++ * queue. Then we add bfqq to the burst. |
306 |
++ */ |
307 |
++ bfq_add_to_burst(bfqd, bfqq); |
308 |
++} |
309 |
++ |
310 |
+static void bfq_add_request(struct request *rq) |
311 |
+{ |
312 |
+ struct bfq_queue *bfqq = RQ_BFQQ(rq); |
313 |
@@ -1632,7 +1846,7 @@ index 0000000..0a0891b |
314 |
+ struct bfq_data *bfqd = bfqq->bfqd; |
315 |
+ struct request *next_rq, *prev; |
316 |
+ unsigned long old_wr_coeff = bfqq->wr_coeff; |
317 |
-+ int idle_for_long_time = 0; |
318 |
++ bool interactive = false; |
319 |
+ |
320 |
+ bfq_log_bfqq(bfqd, bfqq, "add_request %d", rq_is_sync(rq)); |
321 |
+ bfqq->queued[rq_is_sync(rq)]++; |
322 |
@@ -1655,11 +1869,35 @@ index 0000000..0a0891b |
323 |
+ bfq_rq_pos_tree_add(bfqd, bfqq); |
324 |
+ |
325 |
+ if (!bfq_bfqq_busy(bfqq)) { |
326 |
-+ int soft_rt = bfqd->bfq_wr_max_softrt_rate > 0 && |
327 |
++ bool soft_rt, |
328 |
++ idle_for_long_time = time_is_before_jiffies( |
329 |
++ bfqq->budget_timeout + |
330 |
++ bfqd->bfq_wr_min_idle_time); |
331 |
++ |
332 |
++ if (bfq_bfqq_sync(bfqq)) { |
333 |
++ bool already_in_burst = |
334 |
++ !hlist_unhashed(&bfqq->burst_list_node) || |
335 |
++ bfq_bfqq_in_large_burst(bfqq); |
336 |
++ bfq_handle_burst(bfqd, bfqq, idle_for_long_time); |
337 |
++ /* |
338 |
++ * If bfqq was not already in the current burst, |
339 |
++ * then, at this point, bfqq either has been |
340 |
++ * added to the current burst or has caused the |
341 |
++ * current burst to terminate. In particular, in |
342 |
++ * the second case, bfqq has become the first |
343 |
++ * queue in a possible new burst. |
344 |
++ * In both cases last_ins_in_burst needs to be |
345 |
++ * moved forward. |
346 |
++ */ |
347 |
++ if (!already_in_burst) |
348 |
++ bfqd->last_ins_in_burst = jiffies; |
349 |
++ } |
350 |
++ |
351 |
++ soft_rt = bfqd->bfq_wr_max_softrt_rate > 0 && |
352 |
++ !bfq_bfqq_in_large_burst(bfqq) && |
353 |
+ time_is_before_jiffies(bfqq->soft_rt_next_start); |
354 |
-+ idle_for_long_time = time_is_before_jiffies( |
355 |
-+ bfqq->budget_timeout + |
356 |
-+ bfqd->bfq_wr_min_idle_time); |
357 |
++ interactive = !bfq_bfqq_in_large_burst(bfqq) && |
358 |
++ idle_for_long_time; |
359 |
+ entity->budget = max_t(unsigned long, bfqq->max_budget, |
360 |
+ bfq_serv_to_charge(next_rq, bfqq)); |
361 |
+ |
362 |
@@ -1682,9 +1920,9 @@ index 0000000..0a0891b |
363 |
+ * If the queue is not being boosted and has been idle |
364 |
+ * for enough time, start a weight-raising period |
365 |
+ */ |
366 |
-+ if (old_wr_coeff == 1 && (idle_for_long_time || soft_rt)) { |
367 |
++ if (old_wr_coeff == 1 && (interactive || soft_rt)) { |
368 |
+ bfqq->wr_coeff = bfqd->bfq_wr_coeff; |
369 |
-+ if (idle_for_long_time) |
370 |
++ if (interactive) |
371 |
+ bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); |
372 |
+ else |
373 |
+ bfqq->wr_cur_max_time = |
374 |
@@ -1694,11 +1932,12 @@ index 0000000..0a0891b |
375 |
+ jiffies, |
376 |
+ jiffies_to_msecs(bfqq->wr_cur_max_time)); |
377 |
+ } else if (old_wr_coeff > 1) { |
378 |
-+ if (idle_for_long_time) |
379 |
++ if (interactive) |
380 |
+ bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); |
381 |
-+ else if (bfqq->wr_cur_max_time == |
382 |
-+ bfqd->bfq_wr_rt_max_time && |
383 |
-+ !soft_rt) { |
384 |
++ else if (bfq_bfqq_in_large_burst(bfqq) || |
385 |
++ (bfqq->wr_cur_max_time == |
386 |
++ bfqd->bfq_wr_rt_max_time && |
387 |
++ !soft_rt)) { |
388 |
+ bfqq->wr_coeff = 1; |
389 |
+ bfq_log_bfqq(bfqd, bfqq, |
390 |
+ "wrais ending at %lu, rais_max_time %u", |
391 |
@@ -1787,8 +2026,7 @@ index 0000000..0a0891b |
392 |
+ } |
393 |
+ |
394 |
+ if (bfqd->low_latency && |
395 |
-+ (old_wr_coeff == 1 || bfqq->wr_coeff == 1 || |
396 |
-+ idle_for_long_time)) |
397 |
++ (old_wr_coeff == 1 || bfqq->wr_coeff == 1 || interactive)) |
398 |
+ bfqq->last_wr_start_finish = jiffies; |
399 |
+} |
400 |
+ |
401 |
@@ -2291,9 +2529,7 @@ index 0000000..0a0891b |
402 |
+ return rq; |
403 |
+} |
404 |
+ |
405 |
-+/* |
406 |
-+ * Must be called with the queue_lock held. |
407 |
-+ */ |
408 |
++/* Must be called with the queue_lock held. */ |
409 |
+static int bfqq_process_refs(struct bfq_queue *bfqq) |
410 |
+{ |
411 |
+ int process_refs, io_refs; |
412 |
@@ -2896,16 +3132,26 @@ index 0000000..0a0891b |
413 |
+ * long comment, we try to briefly describe all the details and motivations |
414 |
+ * behind the components of this logical expression. |
415 |
+ * |
416 |
-+ * First, the expression may be true only for sync queues. Besides, if |
417 |
-+ * bfqq is also being weight-raised, then the expression always evaluates |
418 |
-+ * to true, as device idling is instrumental for preserving low-latency |
419 |
-+ * guarantees (see [1]). Otherwise, the expression evaluates to true only |
420 |
-+ * if bfqq has a non-null idle window and at least one of the following |
421 |
-+ * two conditions holds. The first condition is that the device is not |
422 |
-+ * performing NCQ, because idling the device most certainly boosts the |
423 |
-+ * throughput if this condition holds and bfqq has been granted a non-null |
424 |
-+ * idle window. The second compound condition is made of the logical AND of |
425 |
-+ * two components. |
426 |
++ * First, the expression is false if bfqq is not sync, or if: bfqq happened |
427 |
++ * to become active during a large burst of queue activations, and the |
428 |
++ * pattern of requests bfqq contains boosts the throughput if bfqq is |
429 |
++ * expired. In fact, queues that became active during a large burst benefit |
430 |
++ * only from throughput, as discussed in the comments to bfq_handle_burst. |
431 |
++ * In this respect, expiring bfqq certainly boosts the throughput on NCQ- |
432 |
++ * capable flash-based devices, whereas, on rotational devices, it boosts |
433 |
++ * the throughput only if bfqq contains random requests. |
434 |
++ * |
435 |
++ * On the opposite end, if (a) bfqq is sync, (b) the above burst-related |
436 |
++ * condition does not hold, and (c) bfqq is being weight-raised, then the |
437 |
++ * expression always evaluates to true, as device idling is instrumental |
438 |
++ * for preserving low-latency guarantees (see [1]). If, instead, conditions |
439 |
++ * (a) and (b) do hold, but (c) does not, then the expression evaluates to |
440 |
++ * true only if: (1) bfqq is I/O-bound and has a non-null idle window, and |
441 |
++ * (2) at least one of the following two conditions holds. |
442 |
++ * The first condition is that the device is not performing NCQ, because |
443 |
++ * idling the device most certainly boosts the throughput if this condition |
444 |
++ * holds and bfqq is I/O-bound and has been granted a non-null idle window. |
445 |
++ * The second compound condition is made of the logical AND of two components. |
446 |
+ * |
447 |
+ * The first component is true only if there is no weight-raised busy |
448 |
+ * queue. This guarantees that the device is not idled for a sync non- |
449 |
@@ -3022,6 +3268,12 @@ index 0000000..0a0891b |
450 |
+#define cond_for_seeky_on_ncq_hdd (bfq_bfqq_constantly_seeky(bfqq) && \ |
451 |
+ bfqd->busy_in_flight_queues == \ |
452 |
+ bfqd->const_seeky_busy_in_flight_queues) |
453 |
++ |
454 |
++#define cond_for_expiring_in_burst (bfq_bfqq_in_large_burst(bfqq) && \ |
455 |
++ bfqd->hw_tag && \ |
456 |
++ (blk_queue_nonrot(bfqd->queue) || \ |
457 |
++ bfq_bfqq_constantly_seeky(bfqq))) |
458 |
++ |
459 |
+/* |
460 |
+ * Condition for expiring a non-weight-raised queue (and hence not idling |
461 |
+ * the device). |
462 |
@@ -3033,9 +3285,9 @@ index 0000000..0a0891b |
463 |
+ cond_for_seeky_on_ncq_hdd)))) |
464 |
+ |
465 |
+ return bfq_bfqq_sync(bfqq) && |
466 |
-+ (bfq_bfqq_IO_bound(bfqq) || bfqq->wr_coeff > 1) && |
467 |
++ !cond_for_expiring_in_burst && |
468 |
+ (bfqq->wr_coeff > 1 || |
469 |
-+ (bfq_bfqq_idle_window(bfqq) && |
470 |
++ (bfq_bfqq_IO_bound(bfqq) && bfq_bfqq_idle_window(bfqq) && |
471 |
+ !cond_for_expiring_non_wr) |
472 |
+ ); |
473 |
+} |
474 |
@@ -3179,10 +3431,12 @@ index 0000000..0a0891b |
475 |
+ if (entity->ioprio_changed) |
476 |
+ bfq_log_bfqq(bfqd, bfqq, "WARN: pending prio change"); |
477 |
+ /* |
478 |
-+ * If too much time has elapsed from the beginning |
479 |
-+ * of this weight-raising, stop it. |
480 |
++ * If the queue was activated in a burst, or |
481 |
++ * too much time has elapsed from the beginning |
482 |
++ * of this weight-raising, then end weight raising. |
483 |
+ */ |
484 |
-+ if (time_is_before_jiffies(bfqq->last_wr_start_finish + |
485 |
++ if (bfq_bfqq_in_large_burst(bfqq) || |
486 |
++ time_is_before_jiffies(bfqq->last_wr_start_finish + |
487 |
+ bfqq->wr_cur_max_time)) { |
488 |
+ bfqq->last_wr_start_finish = jiffies; |
489 |
+ bfq_log_bfqq(bfqd, bfqq, |
490 |
@@ -3387,6 +3641,17 @@ index 0000000..0a0891b |
491 |
+ BUG_ON(bfq_bfqq_busy(bfqq)); |
492 |
+ BUG_ON(bfqd->in_service_queue == bfqq); |
493 |
+ |
494 |
++ if (bfq_bfqq_sync(bfqq)) |
495 |
++ /* |
496 |
++ * The fact that this queue is being destroyed does not |
497 |
++ * invalidate the fact that this queue may have been |
498 |
++ * activated during the current burst. As a consequence, |
499 |
++ * although the queue does not exist anymore, and hence |
500 |
++ * needs to be removed from the burst list if there, |
501 |
++ * the burst size has not to be decremented. |
502 |
++ */ |
503 |
++ hlist_del_init(&bfqq->burst_list_node); |
504 |
++ |
505 |
+ bfq_log_bfqq(bfqd, bfqq, "put_queue: %p freed", bfqq); |
506 |
+ |
507 |
+ kmem_cache_free(bfq_pool, bfqq); |
508 |
@@ -3540,6 +3805,7 @@ index 0000000..0a0891b |
509 |
+{ |
510 |
+ RB_CLEAR_NODE(&bfqq->entity.rb_node); |
511 |
+ INIT_LIST_HEAD(&bfqq->fifo); |
512 |
++ INIT_HLIST_NODE(&bfqq->burst_list_node); |
513 |
+ |
514 |
+ atomic_set(&bfqq->ref, 0); |
515 |
+ bfqq->bfqd = bfqd; |
516 |
@@ -4298,6 +4564,7 @@ index 0000000..0a0891b |
517 |
+ |
518 |
+ INIT_LIST_HEAD(&bfqd->active_list); |
519 |
+ INIT_LIST_HEAD(&bfqd->idle_list); |
520 |
++ INIT_HLIST_HEAD(&bfqd->burst_list); |
521 |
+ |
522 |
+ bfqd->hw_tag = -1; |
523 |
+ |
524 |
@@ -4318,6 +4585,9 @@ index 0000000..0a0891b |
525 |
+ bfqd->bfq_failed_cooperations = 7000; |
526 |
+ bfqd->bfq_requests_within_timer = 120; |
527 |
+ |
528 |
++ bfqd->bfq_large_burst_thresh = 11; |
529 |
++ bfqd->bfq_burst_interval = msecs_to_jiffies(500); |
530 |
++ |
531 |
+ bfqd->low_latency = true; |
532 |
+ |
533 |
+ bfqd->bfq_wr_coeff = 20; |
534 |
@@ -4653,7 +4923,7 @@ index 0000000..0a0891b |
535 |
+ device_speed_thresh[1] = (R_fast[1] + R_slow[1]) / 2; |
536 |
+ |
537 |
+ elv_register(&iosched_bfq); |
538 |
-+ pr_info("BFQ I/O-scheduler version: v7r5"); |
539 |
++ pr_info("BFQ I/O-scheduler version: v7r6"); |
540 |
+ |
541 |
+ return 0; |
542 |
+} |
543 |
@@ -5884,12 +6154,12 @@ index 0000000..c4831b7 |
544 |
+} |
545 |
diff --git a/block/bfq.h b/block/bfq.h |
546 |
new file mode 100644 |
547 |
-index 0000000..a83e69d |
548 |
+index 0000000..0378c86 |
549 |
--- /dev/null |
550 |
+++ b/block/bfq.h |
551 |
-@@ -0,0 +1,742 @@ |
552 |
+@@ -0,0 +1,773 @@ |
553 |
+/* |
554 |
-+ * BFQ-v7r5 for 3.16.0: data structures and common functions prototypes. |
555 |
++ * BFQ-v7r6 for 3.16.0: data structures and common functions prototypes. |
556 |
+ * |
557 |
+ * Based on ideas and code from CFQ: |
558 |
+ * Copyright (C) 2003 Jens Axboe <axboe@××××××.dk> |
559 |
@@ -6086,6 +6356,7 @@ index 0000000..a83e69d |
560 |
+ * @dispatched: number of requests on the dispatch list or inside driver. |
561 |
+ * @flags: status flags. |
562 |
+ * @bfqq_list: node for active/idle bfqq list inside our bfqd. |
563 |
++ * @burst_list_node: node for the device's burst list. |
564 |
+ * @seek_samples: number of seeks sampled |
565 |
+ * @seek_total: sum of the distances of the seeks sampled |
566 |
+ * @seek_mean: mean seek distance |
567 |
@@ -6146,6 +6417,8 @@ index 0000000..a83e69d |
568 |
+ |
569 |
+ struct list_head bfqq_list; |
570 |
+ |
571 |
++ struct hlist_node burst_list_node; |
572 |
++ |
573 |
+ unsigned int seek_samples; |
574 |
+ u64 seek_total; |
575 |
+ sector_t seek_mean; |
576 |
@@ -6298,22 +6571,38 @@ index 0000000..a83e69d |
577 |
+ * again idling to a queue which was marked as |
578 |
+ * non-I/O-bound (see the definition of the |
579 |
+ * IO_bound flag for further details). |
580 |
-+ * @bfq_wr_coeff: Maximum factor by which the weight of a weight-raised |
581 |
-+ * queue is multiplied |
582 |
-+ * @bfq_wr_max_time: maximum duration of a weight-raising period (jiffies) |
583 |
-+ * @bfq_wr_rt_max_time: maximum duration for soft real-time processes |
584 |
++ * @last_ins_in_burst: last time at which a queue entered the current |
585 |
++ * burst of queues being activated shortly after |
586 |
++ * each other; for more details about this and the |
587 |
++ * following parameters related to a burst of |
588 |
++ * activations, see the comments to the function |
589 |
++ * @bfq_handle_burst. |
590 |
++ * @bfq_burst_interval: reference time interval used to decide whether a |
591 |
++ * queue has been activated shortly after |
592 |
++ * @last_ins_in_burst. |
593 |
++ * @burst_size: number of queues in the current burst of queue activations. |
594 |
++ * @bfq_large_burst_thresh: maximum burst size above which the current |
595 |
++ * queue-activation burst is deemed as 'large'. |
596 |
++ * @large_burst: true if a large queue-activation burst is in progress. |
597 |
++ * @burst_list: head of the burst list (as for the above fields, more details |
598 |
++ * in the comments to the function bfq_handle_burst). |
599 |
++ * @low_latency: if set to true, low-latency heuristics are enabled. |
600 |
++ * @bfq_wr_coeff: maximum factor by which the weight of a weight-raised |
601 |
++ * queue is multiplied. |
602 |
++ * @bfq_wr_max_time: maximum duration of a weight-raising period (jiffies). |
603 |
++ * @bfq_wr_rt_max_time: maximum duration for soft real-time processes. |
604 |
+ * @bfq_wr_min_idle_time: minimum idle period after which weight-raising |
605 |
-+ * may be reactivated for a queue (in jiffies) |
606 |
++ * may be reactivated for a queue (in jiffies). |
607 |
+ * @bfq_wr_min_inter_arr_async: minimum period between request arrivals |
608 |
+ * after which weight-raising may be |
609 |
+ * reactivated for an already busy queue |
610 |
-+ * (in jiffies) |
611 |
++ * (in jiffies). |
612 |
+ * @bfq_wr_max_softrt_rate: max service-rate for a soft real-time queue, |
613 |
-+ * sectors per seconds |
614 |
++ * sectors per seconds. |
615 |
+ * @RT_prod: cached value of the product R*T used for computing the maximum |
616 |
-+ * duration of the weight raising automatically |
617 |
-+ * @device_speed: device-speed class for the low-latency heuristic |
618 |
-+ * @oom_bfqq: fallback dummy bfqq for extreme OOM conditions |
619 |
++ * duration of the weight raising automatically. |
620 |
++ * @device_speed: device-speed class for the low-latency heuristic. |
621 |
++ * @oom_bfqq: fallback dummy bfqq for extreme OOM conditions. |
622 |
+ * |
623 |
+ * All the fields are protected by the @queue lock. |
624 |
+ */ |
625 |
@@ -6377,6 +6666,13 @@ index 0000000..a83e69d |
626 |
+ unsigned int bfq_failed_cooperations; |
627 |
+ unsigned int bfq_requests_within_timer; |
628 |
+ |
629 |
++ unsigned long last_ins_in_burst; |
630 |
++ unsigned long bfq_burst_interval; |
631 |
++ int burst_size; |
632 |
++ unsigned long bfq_large_burst_thresh; |
633 |
++ bool large_burst; |
634 |
++ struct hlist_head burst_list; |
635 |
++ |
636 |
+ bool low_latency; |
637 |
+ |
638 |
+ /* parameters of the low_latency heuristics */ |
639 |
@@ -6406,6 +6702,10 @@ index 0000000..a83e69d |
640 |
+ * having consumed at most 2/10 of |
641 |
+ * its budget |
642 |
+ */ |
643 |
++ BFQ_BFQQ_FLAG_in_large_burst, /* |
644 |
++ * bfqq activated in a large burst, |
645 |
++ * see comments to bfq_handle_burst. |
646 |
++ */ |
647 |
+ BFQ_BFQQ_FLAG_constantly_seeky, /* |
648 |
+ * bfqq has proved to be slow and |
649 |
+ * seeky until budget timeout |
650 |
@@ -6441,6 +6741,7 @@ index 0000000..a83e69d |
651 |
+BFQ_BFQQ_FNS(sync); |
652 |
+BFQ_BFQQ_FNS(budget_new); |
653 |
+BFQ_BFQQ_FNS(IO_bound); |
654 |
++BFQ_BFQQ_FNS(in_large_burst); |
655 |
+BFQ_BFQQ_FNS(constantly_seeky); |
656 |
+BFQ_BFQQ_FNS(coop); |
657 |
+BFQ_BFQQ_FNS(split_coop); |
658 |
@@ -6561,15 +6862,15 @@ index 0000000..a83e69d |
659 |
+} |
660 |
+ |
661 |
+static inline struct bfq_queue *bic_to_bfqq(struct bfq_io_cq *bic, |
662 |
-+ int is_sync) |
663 |
++ bool is_sync) |
664 |
+{ |
665 |
-+ return bic->bfqq[!!is_sync]; |
666 |
++ return bic->bfqq[is_sync]; |
667 |
+} |
668 |
+ |
669 |
+static inline void bic_set_bfqq(struct bfq_io_cq *bic, |
670 |
-+ struct bfq_queue *bfqq, int is_sync) |
671 |
++ struct bfq_queue *bfqq, bool is_sync) |
672 |
+{ |
673 |
-+ bic->bfqq[!!is_sync] = bfqq; |
674 |
++ bic->bfqq[is_sync] = bfqq; |
675 |
+} |
676 |
+ |
677 |
+static inline struct bfq_data *bic_to_bfqd(struct bfq_io_cq *bic) |
678 |
@@ -6631,5 +6932,5 @@ index 0000000..a83e69d |
679 |
+ |
680 |
+#endif /* _BFQ_H */ |
681 |
-- |
682 |
-2.0.3 |
683 |
+2.1.2 |
684 |
|
685 |
|
686 |
diff --git a/5003_BFQ-3-block-add-Early-Queue-Merge-EQM-v7r5-for-3.16.0.patch b/5003_BFQ-3-block-add-Early-Queue-Merge-EQM-v7r6-for-3.16.0.patch |
687 |
similarity index 87% |
688 |
rename from 5003_BFQ-3-block-add-Early-Queue-Merge-EQM-v7r5-for-3.16.0.patch |
689 |
rename to 5003_BFQ-3-block-add-Early-Queue-Merge-EQM-v7r6-for-3.16.0.patch |
690 |
index e606f5d..53e7c76 100644 |
691 |
--- a/5003_BFQ-3-block-add-Early-Queue-Merge-EQM-v7r5-for-3.16.0.patch |
692 |
+++ b/5003_BFQ-3-block-add-Early-Queue-Merge-EQM-v7r6-for-3.16.0.patch |
693 |
@@ -1,7 +1,7 @@ |
694 |
-From 5b290be286aa74051b4b77a216032b771ceadd23 Mon Sep 17 00:00:00 2001 |
695 |
+From 5428334e0390ccad40fa21dd046eb163025a4f74 Mon Sep 17 00:00:00 2001 |
696 |
From: Mauro Andreolini <mauro.andreolini@×××××××.it> |
697 |
-Date: Wed, 18 Jun 2014 17:38:07 +0200 |
698 |
-Subject: [PATCH 3/3] block, bfq: add Early Queue Merge (EQM) to BFQ-v7r5 for |
699 |
+Date: Sun, 19 Oct 2014 01:15:59 +0200 |
700 |
+Subject: [PATCH 3/3] block, bfq: add Early Queue Merge (EQM) to BFQ-v7r6 for |
701 |
3.16.0 |
702 |
|
703 |
A set of processes may happen to perform interleaved reads, i.e.,requests |
704 |
@@ -34,13 +34,13 @@ Signed-off-by: Mauro Andreolini <mauro.andreolini@×××××××.it> |
705 |
Signed-off-by: Arianna Avanzini <avanzini.arianna@×××××.com> |
706 |
Signed-off-by: Paolo Valente <paolo.valente@×××××××.it> |
707 |
--- |
708 |
- block/bfq-iosched.c | 736 ++++++++++++++++++++++++++++++++++++---------------- |
709 |
+ block/bfq-iosched.c | 743 +++++++++++++++++++++++++++++++++++++--------------- |
710 |
block/bfq-sched.c | 28 -- |
711 |
- block/bfq.h | 46 +++- |
712 |
- 3 files changed, 556 insertions(+), 254 deletions(-) |
713 |
+ block/bfq.h | 54 +++- |
714 |
+ 3 files changed, 573 insertions(+), 252 deletions(-) |
715 |
|
716 |
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c |
717 |
-index 0a0891b..d1d8e67 100644 |
718 |
+index b919b03..bbfb4e1 100644 |
719 |
--- a/block/bfq-iosched.c |
720 |
+++ b/block/bfq-iosched.c |
721 |
@@ -571,6 +571,57 @@ static inline unsigned int bfq_wr_duration(struct bfq_data *bfqd) |
722 |
@@ -64,7 +64,9 @@ index 0a0891b..d1d8e67 100644 |
723 |
+ bfq_mark_bfqq_IO_bound(bfqq); |
724 |
+ else |
725 |
+ bfq_clear_bfqq_IO_bound(bfqq); |
726 |
++ /* Assuming that the flag in_large_burst is already correctly set */ |
727 |
+ if (bic->wr_time_left && bfqq->bfqd->low_latency && |
728 |
++ !bfq_bfqq_in_large_burst(bfqq) && |
729 |
+ bic->cooperations < bfqq->bfqd->bfq_coop_thresh) { |
730 |
+ /* |
731 |
+ * Start a weight raising period with the duration given by |
732 |
@@ -85,9 +87,7 @@ index 0a0891b..d1d8e67 100644 |
733 |
+ bic->wr_time_left = 0; |
734 |
+} |
735 |
+ |
736 |
-+/* |
737 |
-+ * Must be called with the queue_lock held. |
738 |
-+ */ |
739 |
++/* Must be called with the queue_lock held. */ |
740 |
+static int bfqq_process_refs(struct bfq_queue *bfqq) |
741 |
+{ |
742 |
+ int process_refs, io_refs; |
743 |
@@ -98,23 +98,35 @@ index 0a0891b..d1d8e67 100644 |
744 |
+ return process_refs; |
745 |
+} |
746 |
+ |
747 |
- static void bfq_add_request(struct request *rq) |
748 |
- { |
749 |
- struct bfq_queue *bfqq = RQ_BFQQ(rq); |
750 |
-@@ -602,8 +653,11 @@ static void bfq_add_request(struct request *rq) |
751 |
+ /* Empty burst list and add just bfqq (see comments to bfq_handle_burst) */ |
752 |
+ static inline void bfq_reset_burst_list(struct bfq_data *bfqd, |
753 |
+ struct bfq_queue *bfqq) |
754 |
+@@ -815,7 +866,7 @@ static void bfq_add_request(struct request *rq) |
755 |
+ bfq_rq_pos_tree_add(bfqd, bfqq); |
756 |
|
757 |
if (!bfq_bfqq_busy(bfqq)) { |
758 |
- int soft_rt = bfqd->bfq_wr_max_softrt_rate > 0 && |
759 |
-+ bfq_bfqq_cooperations(bfqq) < bfqd->bfq_coop_thresh && |
760 |
+- bool soft_rt, |
761 |
++ bool soft_rt, coop_or_in_burst, |
762 |
+ idle_for_long_time = time_is_before_jiffies( |
763 |
+ bfqq->budget_timeout + |
764 |
+ bfqd->bfq_wr_min_idle_time); |
765 |
+@@ -839,11 +890,12 @@ static void bfq_add_request(struct request *rq) |
766 |
+ bfqd->last_ins_in_burst = jiffies; |
767 |
+ } |
768 |
+ |
769 |
++ coop_or_in_burst = bfq_bfqq_in_large_burst(bfqq) || |
770 |
++ bfq_bfqq_cooperations(bfqq) >= bfqd->bfq_coop_thresh; |
771 |
+ soft_rt = bfqd->bfq_wr_max_softrt_rate > 0 && |
772 |
+- !bfq_bfqq_in_large_burst(bfqq) && |
773 |
++ !coop_or_in_burst && |
774 |
time_is_before_jiffies(bfqq->soft_rt_next_start); |
775 |
-- idle_for_long_time = time_is_before_jiffies( |
776 |
-+ idle_for_long_time = bfq_bfqq_cooperations(bfqq) < |
777 |
-+ bfqd->bfq_coop_thresh && |
778 |
-+ time_is_before_jiffies( |
779 |
- bfqq->budget_timeout + |
780 |
- bfqd->bfq_wr_min_idle_time); |
781 |
+- interactive = !bfq_bfqq_in_large_burst(bfqq) && |
782 |
+- idle_for_long_time; |
783 |
++ interactive = !coop_or_in_burst && idle_for_long_time; |
784 |
entity->budget = max_t(unsigned long, bfqq->max_budget, |
785 |
-@@ -624,11 +678,20 @@ static void bfq_add_request(struct request *rq) |
786 |
+ bfq_serv_to_charge(next_rq, bfqq)); |
787 |
+ |
788 |
+@@ -862,11 +914,20 @@ static void bfq_add_request(struct request *rq) |
789 |
if (!bfqd->low_latency) |
790 |
goto add_bfqq_busy; |
791 |
|
792 |
@@ -132,28 +144,22 @@ index 0a0891b..d1d8e67 100644 |
793 |
+ * requests have not been redirected to a shared queue) |
794 |
+ * start a weight-raising period. |
795 |
*/ |
796 |
-- if (old_wr_coeff == 1 && (idle_for_long_time || soft_rt)) { |
797 |
-+ if (old_wr_coeff == 1 && (idle_for_long_time || soft_rt) && |
798 |
+- if (old_wr_coeff == 1 && (interactive || soft_rt)) { |
799 |
++ if (old_wr_coeff == 1 && (interactive || soft_rt) && |
800 |
+ (!bfq_bfqq_sync(bfqq) || bfqq->bic != NULL)) { |
801 |
bfqq->wr_coeff = bfqd->bfq_wr_coeff; |
802 |
- if (idle_for_long_time) |
803 |
+ if (interactive) |
804 |
bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); |
805 |
-@@ -642,9 +705,11 @@ static void bfq_add_request(struct request *rq) |
806 |
+@@ -880,7 +941,7 @@ static void bfq_add_request(struct request *rq) |
807 |
} else if (old_wr_coeff > 1) { |
808 |
- if (idle_for_long_time) |
809 |
+ if (interactive) |
810 |
bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); |
811 |
-- else if (bfqq->wr_cur_max_time == |
812 |
-- bfqd->bfq_wr_rt_max_time && |
813 |
-- !soft_rt) { |
814 |
-+ else if (bfq_bfqq_cooperations(bfqq) >= |
815 |
-+ bfqd->bfq_coop_thresh || |
816 |
-+ (bfqq->wr_cur_max_time == |
817 |
-+ bfqd->bfq_wr_rt_max_time && |
818 |
-+ !soft_rt)) { |
819 |
- bfqq->wr_coeff = 1; |
820 |
- bfq_log_bfqq(bfqd, bfqq, |
821 |
- "wrais ending at %lu, rais_max_time %u", |
822 |
-@@ -660,18 +725,18 @@ static void bfq_add_request(struct request *rq) |
823 |
+- else if (bfq_bfqq_in_large_burst(bfqq) || |
824 |
++ else if (coop_or_in_burst || |
825 |
+ (bfqq->wr_cur_max_time == |
826 |
+ bfqd->bfq_wr_rt_max_time && |
827 |
+ !soft_rt)) { |
828 |
+@@ -899,18 +960,18 @@ static void bfq_add_request(struct request *rq) |
829 |
/* |
830 |
* |
831 |
* The remaining weight-raising time is lower |
832 |
@@ -184,7 +190,7 @@ index 0a0891b..d1d8e67 100644 |
833 |
* |
834 |
* In addition, the application is now meeting |
835 |
* the requirements for being deemed soft rt. |
836 |
-@@ -706,6 +771,7 @@ static void bfq_add_request(struct request *rq) |
837 |
+@@ -945,6 +1006,7 @@ static void bfq_add_request(struct request *rq) |
838 |
bfqd->bfq_wr_rt_max_time; |
839 |
} |
840 |
} |
841 |
@@ -192,7 +198,7 @@ index 0a0891b..d1d8e67 100644 |
842 |
if (old_wr_coeff != bfqq->wr_coeff) |
843 |
entity->ioprio_changed = 1; |
844 |
add_bfqq_busy: |
845 |
-@@ -918,90 +984,35 @@ static void bfq_end_wr(struct bfq_data *bfqd) |
846 |
+@@ -1156,90 +1218,35 @@ static void bfq_end_wr(struct bfq_data *bfqd) |
847 |
spin_unlock_irq(bfqd->queue->queue_lock); |
848 |
} |
849 |
|
850 |
@@ -297,7 +303,7 @@ index 0a0891b..d1d8e67 100644 |
851 |
|
852 |
if (RB_EMPTY_ROOT(root)) |
853 |
return NULL; |
854 |
-@@ -1020,7 +1031,7 @@ static struct bfq_queue *bfqq_close(struct bfq_data *bfqd) |
855 |
+@@ -1258,7 +1265,7 @@ static struct bfq_queue *bfqq_close(struct bfq_data *bfqd) |
856 |
* next_request position). |
857 |
*/ |
858 |
__bfqq = rb_entry(parent, struct bfq_queue, pos_node); |
859 |
@@ -306,7 +312,7 @@ index 0a0891b..d1d8e67 100644 |
860 |
return __bfqq; |
861 |
|
862 |
if (blk_rq_pos(__bfqq->next_rq) < sector) |
863 |
-@@ -1031,7 +1042,7 @@ static struct bfq_queue *bfqq_close(struct bfq_data *bfqd) |
864 |
+@@ -1269,7 +1276,7 @@ static struct bfq_queue *bfqq_close(struct bfq_data *bfqd) |
865 |
return NULL; |
866 |
|
867 |
__bfqq = rb_entry(node, struct bfq_queue, pos_node); |
868 |
@@ -315,7 +321,7 @@ index 0a0891b..d1d8e67 100644 |
869 |
return __bfqq; |
870 |
|
871 |
return NULL; |
872 |
-@@ -1040,14 +1051,12 @@ static struct bfq_queue *bfqq_close(struct bfq_data *bfqd) |
873 |
+@@ -1278,14 +1285,12 @@ static struct bfq_queue *bfqq_close(struct bfq_data *bfqd) |
874 |
/* |
875 |
* bfqd - obvious |
876 |
* cur_bfqq - passed in so that we don't decide that the current queue |
877 |
@@ -334,7 +340,7 @@ index 0a0891b..d1d8e67 100644 |
878 |
{ |
879 |
struct bfq_queue *bfqq; |
880 |
|
881 |
-@@ -1067,7 +1076,7 @@ static struct bfq_queue *bfq_close_cooperator(struct bfq_data *bfqd, |
882 |
+@@ -1305,7 +1310,7 @@ static struct bfq_queue *bfq_close_cooperator(struct bfq_data *bfqd, |
883 |
* working closely on the same area of the disk. In that case, |
884 |
* we can group them together and don't waste time idling. |
885 |
*/ |
886 |
@@ -343,7 +349,7 @@ index 0a0891b..d1d8e67 100644 |
887 |
if (bfqq == NULL || bfqq == cur_bfqq) |
888 |
return NULL; |
889 |
|
890 |
-@@ -1094,6 +1103,305 @@ static struct bfq_queue *bfq_close_cooperator(struct bfq_data *bfqd, |
891 |
+@@ -1332,6 +1337,307 @@ static struct bfq_queue *bfq_close_cooperator(struct bfq_data *bfqd, |
892 |
return bfqq; |
893 |
} |
894 |
|
895 |
@@ -508,6 +514,8 @@ index 0a0891b..d1d8e67 100644 |
896 |
+ bfqq->bic->wr_time_left = 0; |
897 |
+ bfqq->bic->saved_idle_window = bfq_bfqq_idle_window(bfqq); |
898 |
+ bfqq->bic->saved_IO_bound = bfq_bfqq_IO_bound(bfqq); |
899 |
++ bfqq->bic->saved_in_large_burst = bfq_bfqq_in_large_burst(bfqq); |
900 |
++ bfqq->bic->was_in_burst_list = !hlist_unhashed(&bfqq->burst_list_node); |
901 |
+ bfqq->bic->cooperations++; |
902 |
+ bfqq->bic->failed_cooperations = 0; |
903 |
+} |
904 |
@@ -649,13 +657,11 @@ index 0a0891b..d1d8e67 100644 |
905 |
/* |
906 |
* If enough samples have been computed, return the current max budget |
907 |
* stored in bfqd, which is dynamically updated according to the |
908 |
-@@ -1237,63 +1545,6 @@ static struct request *bfq_check_fifo(struct bfq_queue *bfqq) |
909 |
+@@ -1475,61 +1781,6 @@ static struct request *bfq_check_fifo(struct bfq_queue *bfqq) |
910 |
return rq; |
911 |
} |
912 |
|
913 |
--/* |
914 |
-- * Must be called with the queue_lock held. |
915 |
-- */ |
916 |
+-/* Must be called with the queue_lock held. */ |
917 |
-static int bfqq_process_refs(struct bfq_queue *bfqq) |
918 |
-{ |
919 |
- int process_refs, io_refs; |
920 |
@@ -713,7 +719,7 @@ index 0a0891b..d1d8e67 100644 |
921 |
static inline unsigned long bfq_bfqq_budget_left(struct bfq_queue *bfqq) |
922 |
{ |
923 |
struct bfq_entity *entity = &bfqq->entity; |
924 |
-@@ -2011,7 +2262,7 @@ static inline bool bfq_bfqq_must_idle(struct bfq_queue *bfqq) |
925 |
+@@ -2263,7 +2514,7 @@ static inline bool bfq_bfqq_must_idle(struct bfq_queue *bfqq) |
926 |
*/ |
927 |
static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd) |
928 |
{ |
929 |
@@ -722,7 +728,7 @@ index 0a0891b..d1d8e67 100644 |
930 |
struct request *next_rq; |
931 |
enum bfqq_expiration reason = BFQ_BFQQ_BUDGET_TIMEOUT; |
932 |
|
933 |
-@@ -2021,17 +2272,6 @@ static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd) |
934 |
+@@ -2273,17 +2524,6 @@ static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd) |
935 |
|
936 |
bfq_log_bfqq(bfqd, bfqq, "select_queue: already in-service queue"); |
937 |
|
938 |
@@ -740,7 +746,7 @@ index 0a0891b..d1d8e67 100644 |
939 |
if (bfq_may_expire_for_budg_timeout(bfqq) && |
940 |
!timer_pending(&bfqd->idle_slice_timer) && |
941 |
!bfq_bfqq_must_idle(bfqq)) |
942 |
-@@ -2070,10 +2310,7 @@ static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd) |
943 |
+@@ -2322,10 +2562,7 @@ static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd) |
944 |
bfq_clear_bfqq_wait_request(bfqq); |
945 |
del_timer(&bfqd->idle_slice_timer); |
946 |
} |
947 |
@@ -752,7 +758,7 @@ index 0a0891b..d1d8e67 100644 |
948 |
} |
949 |
} |
950 |
|
951 |
-@@ -2082,40 +2319,30 @@ static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd) |
952 |
+@@ -2334,40 +2571,30 @@ static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd) |
953 |
* in flight (possibly waiting for a completion) or is idling for a |
954 |
* new request, then keep it. |
955 |
*/ |
956 |
@@ -800,25 +806,25 @@ index 0a0891b..d1d8e67 100644 |
957 |
jiffies_to_msecs(bfqq->wr_cur_max_time), |
958 |
bfqq->wr_coeff, |
959 |
bfqq->entity.weight, bfqq->entity.orig_weight); |
960 |
-@@ -2124,11 +2351,15 @@ static void bfq_update_wr_data(struct bfq_data *bfqd, |
961 |
+@@ -2376,12 +2603,16 @@ static void bfq_update_wr_data(struct bfq_data *bfqd, |
962 |
entity->orig_weight * bfqq->wr_coeff); |
963 |
if (entity->ioprio_changed) |
964 |
bfq_log_bfqq(bfqd, bfqq, "WARN: pending prio change"); |
965 |
+ |
966 |
/* |
967 |
- * If too much time has elapsed from the beginning |
968 |
-- * of this weight-raising, stop it. |
969 |
+ * If the queue was activated in a burst, or |
970 |
+ * too much time has elapsed from the beginning |
971 |
+- * of this weight-raising, then end weight raising. |
972 |
+ * of this weight-raising period, or the queue has |
973 |
+ * exceeded the acceptable number of cooperations, |
974 |
-+ * stop it. |
975 |
++ * then end weight raising. |
976 |
*/ |
977 |
-- if (time_is_before_jiffies(bfqq->last_wr_start_finish + |
978 |
-+ if (bfq_bfqq_cooperations(bfqq) >= bfqd->bfq_coop_thresh || |
979 |
-+ time_is_before_jiffies(bfqq->last_wr_start_finish + |
980 |
+ if (bfq_bfqq_in_large_burst(bfqq) || |
981 |
++ bfq_bfqq_cooperations(bfqq) >= bfqd->bfq_coop_thresh || |
982 |
+ time_is_before_jiffies(bfqq->last_wr_start_finish + |
983 |
bfqq->wr_cur_max_time)) { |
984 |
bfqq->last_wr_start_finish = jiffies; |
985 |
- bfq_log_bfqq(bfqd, bfqq, |
986 |
-@@ -2136,11 +2367,13 @@ static void bfq_update_wr_data(struct bfq_data *bfqd, |
987 |
+@@ -2390,11 +2621,13 @@ static void bfq_update_wr_data(struct bfq_data *bfqd, |
988 |
bfqq->last_wr_start_finish, |
989 |
jiffies_to_msecs(bfqq->wr_cur_max_time)); |
990 |
bfq_bfqq_end_wr(bfqq); |
991 |
@@ -835,7 +841,7 @@ index 0a0891b..d1d8e67 100644 |
992 |
} |
993 |
|
994 |
/* |
995 |
-@@ -2377,6 +2610,25 @@ static inline void bfq_init_icq(struct io_cq *icq) |
996 |
+@@ -2642,6 +2875,25 @@ static inline void bfq_init_icq(struct io_cq *icq) |
997 |
struct bfq_io_cq *bic = icq_to_bic(icq); |
998 |
|
999 |
bic->ttime.last_end_request = jiffies; |
1000 |
@@ -861,7 +867,7 @@ index 0a0891b..d1d8e67 100644 |
1001 |
} |
1002 |
|
1003 |
static void bfq_exit_icq(struct io_cq *icq) |
1004 |
-@@ -2390,6 +2642,13 @@ static void bfq_exit_icq(struct io_cq *icq) |
1005 |
+@@ -2655,6 +2907,13 @@ static void bfq_exit_icq(struct io_cq *icq) |
1006 |
} |
1007 |
|
1008 |
if (bic->bfqq[BLK_RW_SYNC]) { |
1009 |
@@ -875,7 +881,7 @@ index 0a0891b..d1d8e67 100644 |
1010 |
bfq_exit_bfqq(bfqd, bic->bfqq[BLK_RW_SYNC]); |
1011 |
bic->bfqq[BLK_RW_SYNC] = NULL; |
1012 |
} |
1013 |
-@@ -2678,6 +2937,10 @@ static void bfq_update_idle_window(struct bfq_data *bfqd, |
1014 |
+@@ -2944,6 +3203,10 @@ static void bfq_update_idle_window(struct bfq_data *bfqd, |
1015 |
if (!bfq_bfqq_sync(bfqq) || bfq_class_idle(bfqq)) |
1016 |
return; |
1017 |
|
1018 |
@@ -886,7 +892,7 @@ index 0a0891b..d1d8e67 100644 |
1019 |
enable_idle = bfq_bfqq_idle_window(bfqq); |
1020 |
|
1021 |
if (atomic_read(&bic->icq.ioc->active_ref) == 0 || |
1022 |
-@@ -2725,6 +2988,7 @@ static void bfq_rq_enqueued(struct bfq_data *bfqd, struct bfq_queue *bfqq, |
1023 |
+@@ -2991,6 +3254,7 @@ static void bfq_rq_enqueued(struct bfq_data *bfqd, struct bfq_queue *bfqq, |
1024 |
if (bfqq->entity.service > bfq_max_budget(bfqd) / 8 || |
1025 |
!BFQQ_SEEKY(bfqq)) |
1026 |
bfq_update_idle_window(bfqd, bfqq, bic); |
1027 |
@@ -894,7 +900,7 @@ index 0a0891b..d1d8e67 100644 |
1028 |
|
1029 |
bfq_log_bfqq(bfqd, bfqq, |
1030 |
"rq_enqueued: idle_window=%d (seeky %d, mean %llu)", |
1031 |
-@@ -2785,13 +3049,49 @@ static void bfq_rq_enqueued(struct bfq_data *bfqd, struct bfq_queue *bfqq, |
1032 |
+@@ -3051,13 +3315,49 @@ static void bfq_rq_enqueued(struct bfq_data *bfqd, struct bfq_queue *bfqq, |
1033 |
static void bfq_insert_request(struct request_queue *q, struct request *rq) |
1034 |
{ |
1035 |
struct bfq_data *bfqd = q->elevator->elevator_data; |
1036 |
@@ -945,7 +951,7 @@ index 0a0891b..d1d8e67 100644 |
1037 |
rq->fifo_time = jiffies + bfqd->bfq_fifo_expire[rq_is_sync(rq)]; |
1038 |
list_add_tail(&rq->queuelist, &bfqq->fifo); |
1039 |
|
1040 |
-@@ -2956,18 +3256,6 @@ static void bfq_put_request(struct request *rq) |
1041 |
+@@ -3222,18 +3522,6 @@ static void bfq_put_request(struct request *rq) |
1042 |
} |
1043 |
} |
1044 |
|
1045 |
@@ -964,7 +970,7 @@ index 0a0891b..d1d8e67 100644 |
1046 |
/* |
1047 |
* Returns NULL if a new bfqq should be allocated, or the old bfqq if this |
1048 |
* was the last process referring to said bfqq. |
1049 |
-@@ -2976,6 +3264,9 @@ static struct bfq_queue * |
1050 |
+@@ -3242,6 +3530,9 @@ static struct bfq_queue * |
1051 |
bfq_split_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq) |
1052 |
{ |
1053 |
bfq_log_bfqq(bfqq->bfqd, bfqq, "splitting queue"); |
1054 |
@@ -974,7 +980,7 @@ index 0a0891b..d1d8e67 100644 |
1055 |
if (bfqq_process_refs(bfqq) == 1) { |
1056 |
bfqq->pid = current->pid; |
1057 |
bfq_clear_bfqq_coop(bfqq); |
1058 |
-@@ -3004,6 +3295,7 @@ static int bfq_set_request(struct request_queue *q, struct request *rq, |
1059 |
+@@ -3270,6 +3561,7 @@ static int bfq_set_request(struct request_queue *q, struct request *rq, |
1060 |
struct bfq_queue *bfqq; |
1061 |
struct bfq_group *bfqg; |
1062 |
unsigned long flags; |
1063 |
@@ -982,9 +988,21 @@ index 0a0891b..d1d8e67 100644 |
1064 |
|
1065 |
might_sleep_if(gfp_mask & __GFP_WAIT); |
1066 |
|
1067 |
-@@ -3022,24 +3314,14 @@ new_queue: |
1068 |
+@@ -3287,25 +3579,26 @@ new_queue: |
1069 |
+ if (bfqq == NULL || bfqq == &bfqd->oom_bfqq) { |
1070 |
bfqq = bfq_get_queue(bfqd, bfqg, is_sync, bic, gfp_mask); |
1071 |
bic_set_bfqq(bic, bfqq, is_sync); |
1072 |
++ if (split && is_sync) { |
1073 |
++ if ((bic->was_in_burst_list && bfqd->large_burst) || |
1074 |
++ bic->saved_in_large_burst) |
1075 |
++ bfq_mark_bfqq_in_large_burst(bfqq); |
1076 |
++ else { |
1077 |
++ bfq_clear_bfqq_in_large_burst(bfqq); |
1078 |
++ if (bic->was_in_burst_list) |
1079 |
++ hlist_add_head(&bfqq->burst_list_node, |
1080 |
++ &bfqd->burst_list); |
1081 |
++ } |
1082 |
++ } |
1083 |
} else { |
1084 |
- /* |
1085 |
- * If the queue was seeky for too long, break it apart. |
1086 |
@@ -1009,7 +1027,7 @@ index 0a0891b..d1d8e67 100644 |
1087 |
} |
1088 |
|
1089 |
bfqq->allocated[rw]++; |
1090 |
-@@ -3050,6 +3332,26 @@ new_queue: |
1091 |
+@@ -3316,6 +3609,26 @@ new_queue: |
1092 |
rq->elv.priv[0] = bic; |
1093 |
rq->elv.priv[1] = bfqq; |
1094 |
|
1095 |
@@ -1076,10 +1094,10 @@ index c4831b7..546a254 100644 |
1096 |
{ |
1097 |
if (bfqd->in_service_bic != NULL) { |
1098 |
diff --git a/block/bfq.h b/block/bfq.h |
1099 |
-index a83e69d..ebbd040 100644 |
1100 |
+index 0378c86..93a2d24 100644 |
1101 |
--- a/block/bfq.h |
1102 |
+++ b/block/bfq.h |
1103 |
-@@ -215,18 +215,21 @@ struct bfq_group; |
1104 |
+@@ -216,18 +216,21 @@ struct bfq_group; |
1105 |
* idle @bfq_queue with no outstanding requests, then |
1106 |
* the task associated with the queue it is deemed as |
1107 |
* soft real-time (see the comments to the function |
1108 |
@@ -1107,7 +1125,7 @@ index a83e69d..ebbd040 100644 |
1109 |
* All the fields are protected by the queue lock of the containing bfqd. |
1110 |
*/ |
1111 |
struct bfq_queue { |
1112 |
-@@ -264,6 +267,7 @@ struct bfq_queue { |
1113 |
+@@ -267,6 +270,7 @@ struct bfq_queue { |
1114 |
unsigned int requests_within_timer; |
1115 |
|
1116 |
pid_t pid; |
1117 |
@@ -1115,7 +1133,7 @@ index a83e69d..ebbd040 100644 |
1118 |
|
1119 |
/* weight-raising fields */ |
1120 |
unsigned long wr_cur_max_time; |
1121 |
-@@ -293,12 +297,34 @@ struct bfq_ttime { |
1122 |
+@@ -296,12 +300,42 @@ struct bfq_ttime { |
1123 |
* @icq: associated io_cq structure |
1124 |
* @bfqq: array of two process queues, the sync and the async |
1125 |
* @ttime: associated @bfq_ttime struct |
1126 |
@@ -1130,6 +1148,11 @@ index a83e69d..ebbd040 100644 |
1127 |
+ * window |
1128 |
+ * @saved_IO_bound: same purpose as the previous two fields for the I/O |
1129 |
+ * bound classification of a queue |
1130 |
++ * @saved_in_large_burst: same purpose as the previous fields for the |
1131 |
++ * value of the field keeping the queue's belonging |
1132 |
++ * to a large burst |
1133 |
++ * @was_in_burst_list: true if the queue belonged to a burst list |
1134 |
++ * before its merge with another cooperating queue |
1135 |
+ * @cooperations: counter of consecutive successful queue merges underwent |
1136 |
+ * by any of the process' @bfq_queues |
1137 |
+ * @failed_cooperations: counter of consecutive failed queue merges of any |
1138 |
@@ -1142,15 +1165,18 @@ index a83e69d..ebbd040 100644 |
1139 |
int ioprio; |
1140 |
+ |
1141 |
+ unsigned int wr_time_left; |
1142 |
-+ unsigned int saved_idle_window; |
1143 |
-+ unsigned int saved_IO_bound; |
1144 |
++ bool saved_idle_window; |
1145 |
++ bool saved_IO_bound; |
1146 |
++ |
1147 |
++ bool saved_in_large_burst; |
1148 |
++ bool was_in_burst_list; |
1149 |
+ |
1150 |
+ unsigned int cooperations; |
1151 |
+ unsigned int failed_cooperations; |
1152 |
}; |
1153 |
|
1154 |
enum bfq_device_speed { |
1155 |
-@@ -511,7 +537,7 @@ enum bfqq_state_flags { |
1156 |
+@@ -537,7 +571,7 @@ enum bfqq_state_flags { |
1157 |
BFQ_BFQQ_FLAG_prio_changed, /* task priority has changed */ |
1158 |
BFQ_BFQQ_FLAG_sync, /* synchronous queue */ |
1159 |
BFQ_BFQQ_FLAG_budget_new, /* no completion with this budget */ |
1160 |
@@ -1159,7 +1185,7 @@ index a83e69d..ebbd040 100644 |
1161 |
* bfqq has timed-out at least once |
1162 |
* having consumed at most 2/10 of |
1163 |
* its budget |
1164 |
-@@ -520,12 +546,13 @@ enum bfqq_state_flags { |
1165 |
+@@ -550,12 +584,13 @@ enum bfqq_state_flags { |
1166 |
* bfqq has proved to be slow and |
1167 |
* seeky until budget timeout |
1168 |
*/ |
1169 |
@@ -1175,7 +1201,7 @@ index a83e69d..ebbd040 100644 |
1170 |
}; |
1171 |
|
1172 |
#define BFQ_BFQQ_FNS(name) \ |
1173 |
-@@ -554,6 +581,7 @@ BFQ_BFQQ_FNS(IO_bound); |
1174 |
+@@ -585,6 +620,7 @@ BFQ_BFQQ_FNS(in_large_burst); |
1175 |
BFQ_BFQQ_FNS(constantly_seeky); |
1176 |
BFQ_BFQQ_FNS(coop); |
1177 |
BFQ_BFQQ_FNS(split_coop); |
1178 |
@@ -1184,5 +1210,5 @@ index a83e69d..ebbd040 100644 |
1179 |
#undef BFQ_BFQQ_FNS |
1180 |
|
1181 |
-- |
1182 |
-2.0.3 |
1183 |
+2.1.2 |