summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorsirlucjan2017-08-03 18:16:15 +0200
committersirlucjan2017-08-03 18:16:15 +0200
commit9c67733b4846365636cb2f94c1c97595dfa8378f (patch)
treeef93286fe46da95ddd56193a211b155a9de50a2e
parentece576f82876545fc2904e4e606d40abe42dd6e4 (diff)
downloadaur-9c67733b4846365636cb2f94c1c97595dfa8378f.tar.gz
Update 0006-BFQ-bugfix-for-v8r12.patch
-rw-r--r--.SRCINFO4
-rw-r--r--0006-BFQ-bugfix-for-v8r12.patch345
-rw-r--r--PKGBUILD4
3 files changed, 345 insertions, 8 deletions
diff --git a/.SRCINFO b/.SRCINFO
index bbdb27dbac45..47722e87101e 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,6 +1,6 @@
pkgbase = linux-bfq
pkgver = 4.11.12
- pkgrel = 2
+ pkgrel = 3
url = http://algo.ing.unimo.it
arch = i686
arch = x86_64
@@ -40,7 +40,7 @@ pkgbase = linux-bfq
sha512sums = d6faa67f3ef40052152254ae43fee031365d0b1524aa0718b659eb75afc21a3f79ea8d62d66ea311a800109bed545bc8f79e8752319cd378eef2cbd3a09aba22
sha512sums = 2dc6b0ba8f7dbf19d2446c5c5f1823587de89f4e28e9595937dd51a87755099656f2acec50e3e2546ea633ad1bfd1c722e0c2b91eef1d609103d8abdc0a7cbaf
sha512sums = b1f6306a27d7e25eb4ff3eb51cb1fe38b0ca035cff229537d1b9f68bdc25861f2fecdeeeb1582e34cd166ee4275e49e4c679247a4c36109b2dcd6d4fa9456d60
- sha512sums = c03c5a8dd81c40e01639d04bbb4d5347e844c76248965c020a76addc83b1e897f4b9a26c6b6125739175577c8d8829054ce7ce8400f8d71d6cd2c2f89fc6ac3b
+ sha512sums = 9a80a4824e6a8f34a9bcc687b1e1fa91300a5a5fb515db6022e7e43cbacbf2ad93dda1250f968e070be4f6e2429a21e9cf97838120915de9a1144745c34a7188
pkgname = linux-bfq
pkgdesc = Linux Kernel and modules with the BFQ scheduler.
diff --git a/0006-BFQ-bugfix-for-v8r12.patch b/0006-BFQ-bugfix-for-v8r12.patch
index 68e7c41bddf6..09317c62fb45 100644
--- a/0006-BFQ-bugfix-for-v8r12.patch
+++ b/0006-BFQ-bugfix-for-v8r12.patch
@@ -1,7 +1,7 @@
From 518e5275d6057ee8b3b4eeebaaa779c5aca7a15c Mon Sep 17 00:00:00 2001
From: Paolo Valente <paolo.valente@linaro.org>
Date: Thu, 20 Jul 2017 10:46:39 +0200
-Subject: [PATCH 1/3] Add extra checks related to entity scheduling
+Subject: [PATCH 1/4] Add extra checks related to entity scheduling
- extra checks related to ioprioi-class changes
- specific check on st->idle in __bfq_requeue_entity
@@ -67,7 +67,7 @@ index 90d2856358a1..b6eb25887262 100644
From 6af8852b69527087d11c81a4dcb49d24f297dbce Mon Sep 17 00:00:00 2001
From: Paolo Valente <paolo.valente@linaro.org>
Date: Fri, 21 Jul 2017 12:08:57 +0200
-Subject: [PATCH 2/3] block, bfq: reset in_service_entity if it becomes idle
+Subject: [PATCH 2/4] block, bfq: reset in_service_entity if it becomes idle
BFQ implements hierarchical scheduling by representing each group of
queues with a generic parent entity. For each parent entity, BFQ
@@ -125,7 +125,7 @@ index b6eb25887262..fdf1c713d050 100644
From 52ce0ffe68b5e3fefaed21cfb32f104202eddc25 Mon Sep 17 00:00:00 2001
From: Paolo Valente <paolo.valente@linaro.org>
Date: Fri, 28 Jul 2017 21:09:51 +0200
-Subject: [PATCH 3/3] block, bfq: consider also in_service_entity to state
+Subject: [PATCH 3/4] block, bfq: consider also in_service_entity to state
whether an entity is active
Groups of BFQ queues are represented by generic entities in BFQ. When
@@ -440,4 +440,341 @@ index 77dc72c35fbf..ffa833863d88 100644
+ * bfqd.
*/
struct bfq_sched_data {
- struct bfq_entity *in_service_entity; /* entity in service */
+ struct bfq_entity *in_service_entity; /* entity in service */
+
+From ef8d4eb597ec77088b5d8cd08ff5a9145c47a57c Mon Sep 17 00:00:00 2001
+From: Paolo Valente <paolo.valente@linaro.org>
+Date: Thu, 4 May 2017 10:53:43 +0200
+Subject: [PATCH 4/4] block, bfq: improve and refactor throughput-boosting
+ logic
+
+When a queue associated with a process remains empty, there are cases
+where throughput gets boosted if the device is idled to await the
+arrival of a new I/O request for that queue. Currently, BFQ assumes
+that one of these cases is when the device has no internal queueing
+(regardless of the properties of the I/O being served). Unfortunately,
+this condition has proved to be too general. So, this commit refines it
+as "the device has no internal queueing and is rotational".
+
+This refinement provides a significant throughput boost with random
+I/O, on flash-based storage without internal queueing. For example, on
+a HiKey board, throughput increases by up to 125%, growing, e.g., from
+6.9MB/s to 15.6MB/s with two or three random readers in parallel.
+
+This commit also refactors the code related to device idling, for the
+following reason. Finding the change that provides the above large
+improvement has been slightly more difficult than it had to be,
+because the logic that decides whether to idle the device is still
+scattered across three functions. Almost all of the logic is in the
+function bfq_bfqq_may_idle, but (1) part of the decision is made in
+bfq_update_idle_window, and (2) the function bfq_bfqq_must_idle may
+switch off idling regardless of the output of bfq_bfqq_may_idle. In
+addition, both bfq_update_idle_window and bfq_bfqq_must_idle make
+their decisions as a function of parameters that are used, for similar
+purposes, also in bfq_bfqq_may_idle. This commit addresses this issue
+by moving all the logic into bfq_bfqq_may_idle.
+
+Signed-off-by: Paolo Valente <paolo.valente@linaro.org>
+Signed-off-by: Luca Miccio <lucmiccio@gmail.com>
+---
+ block/bfq-iosched.c | 141 ++++++++++++++++++++++++++++------------------------
+ block/bfq.h | 12 ++---
+ 2 files changed, 83 insertions(+), 70 deletions(-)
+
+diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
+index ea92c7461b89..e75df37a1cd3 100644
+--- a/block/bfq-iosched.c
++++ b/block/bfq-iosched.c
+@@ -684,10 +684,10 @@ bfq_bfqq_resume_state(struct bfq_queue *bfqq, struct bfq_data *bfqd,
+ unsigned int old_wr_coeff;
+ bool busy = bfq_already_existing && bfq_bfqq_busy(bfqq);
+
+- if (bic->saved_idle_window)
+- bfq_mark_bfqq_idle_window(bfqq);
++ if (bic->saved_has_short_ttime)
++ bfq_mark_bfqq_has_short_ttime(bfqq);
+ else
+- bfq_clear_bfqq_idle_window(bfqq);
++ bfq_clear_bfqq_has_short_ttime(bfqq);
+
+ if (bic->saved_IO_bound)
+ bfq_mark_bfqq_IO_bound(bfqq);
+@@ -2047,7 +2047,7 @@ static void bfq_bfqq_save_state(struct bfq_queue *bfqq)
+ if (!bic)
+ return;
+
+- bic->saved_idle_window = bfq_bfqq_idle_window(bfqq);
++ bic->saved_has_short_ttime = bfq_bfqq_has_short_ttime(bfqq);
+ bic->saved_IO_bound = bfq_bfqq_IO_bound(bfqq);
+ bic->saved_in_large_burst = bfq_bfqq_in_large_burst(bfqq);
+ bic->was_in_burst_list = !hlist_unhashed(&bfqq->burst_list_node);
+@@ -3214,9 +3214,9 @@ static void bfq_bfqq_expire(struct bfq_data *bfqd,
+ }
+
+ bfq_log_bfqq(bfqd, bfqq,
+- "expire (%d, slow %d, num_disp %d, idle_win %d, weight %d)",
++ "expire (%d, slow %d, num_disp %d, short_ttime %d, weight %d)",
+ reason, slow, bfqq->dispatched,
+- bfq_bfqq_idle_window(bfqq), entity->weight);
++ bfq_bfqq_has_short_ttime(bfqq), entity->weight);
+
+ /*
+ * Increase, decrease or leave budget unchanged according to
+@@ -3298,7 +3298,10 @@ static bool bfq_may_expire_for_budg_timeout(struct bfq_queue *bfqq)
+ static bool bfq_bfqq_may_idle(struct bfq_queue *bfqq)
+ {
+ struct bfq_data *bfqd = bfqq->bfqd;
+- bool idling_boosts_thr, idling_boosts_thr_without_issues,
++ bool rot_without_queueing =
++ !blk_queue_nonrot(bfqd->queue) && !bfqd->hw_tag,
++ bfqq_sequential_and_IO_bound,
++ idling_boosts_thr, idling_boosts_thr_without_issues,
+ idling_needed_for_service_guarantees,
+ asymmetric_scenario;
+
+@@ -3306,27 +3309,44 @@ static bool bfq_bfqq_may_idle(struct bfq_queue *bfqq)
+ return true;
+
+ /*
++ * Idling is performed only if slice_idle > 0. In addition, we
++ * do not idle if
++ * (a) bfqq is async
++ * (b) bfqq is in the idle io prio class: in this case we do
++ * not idle because we want to minimize the bandwidth that
++ * queues in this class can steal to higher-priority queues
++ */
++ if (bfqd->bfq_slice_idle == 0 || !bfq_bfqq_sync(bfqq) ||
++ bfq_class_idle(bfqq))
++ return false;
++
++ bfqq_sequential_and_IO_bound = !BFQQ_SEEKY(bfqq) &&
++ bfq_bfqq_IO_bound(bfqq) && bfq_bfqq_has_short_ttime(bfqq);
++ /*
+ * The next variable takes into account the cases where idling
+ * boosts the throughput.
+ *
+ * The value of the variable is computed considering, first, that
+ * idling is virtually always beneficial for the throughput if:
+- * (a) the device is not NCQ-capable, or
+- * (b) regardless of the presence of NCQ, the device is rotational
+- * and the request pattern for bfqq is I/O-bound and sequential.
++ * (a) the device is not NCQ-capable and rotational, or
++ * (b) regardless of the presence of NCQ, the device is rotational and
++ * the request pattern for bfqq is I/O-bound and sequential, or
++ * (c) regardless of whether it is rotational, the device is
++ * not NCQ-capable and the request pattern for bfqq is
++ * I/O-bound and sequential.
+ *
+ * Secondly, and in contrast to the above item (b), idling an
+ * NCQ-capable flash-based device would not boost the
+ * throughput even with sequential I/O; rather it would lower
+ * the throughput in proportion to how fast the device
+ * is. Accordingly, the next variable is true if any of the
+- * above conditions (a) and (b) is true, and, in particular,
+- * happens to be false if bfqd is an NCQ-capable flash-based
+- * device.
++ * above conditions (a), (b) or (c) is true, and, in
++ * particular, happens to be false if bfqd is an NCQ-capable
++ * flash-based device.
+ */
+- idling_boosts_thr = !bfqd->hw_tag ||
+- (!blk_queue_nonrot(bfqd->queue) && bfq_bfqq_IO_bound(bfqq) &&
+- bfq_bfqq_idle_window(bfqq));
++ idling_boosts_thr = rot_without_queueing ||
++ ((!blk_queue_nonrot(bfqd->queue) || !bfqd->hw_tag) &&
++ bfqq_sequential_and_IO_bound);
+
+ /*
+ * The value of the next variable,
+@@ -3497,12 +3517,10 @@ static bool bfq_bfqq_may_idle(struct bfq_queue *bfqq)
+ asymmetric_scenario && !bfq_bfqq_in_large_burst(bfqq);
+
+ /*
+- * We have now all the components we need to compute the return
+- * value of the function, which is true only if both the following
+- * conditions hold:
+- * 1) bfqq is sync, because idling make sense only for sync queues;
+- * 2) idling either boosts the throughput (without issues), or
+- * is necessary to preserve service guarantees.
++ * We have now all the components we need to compute the
++ * return value of the function, which is true only if idling
++ * either boosts the throughput (without issues), or is
++ * necessary to preserve service guarantees.
+ */
+ bfq_log_bfqq(bfqd, bfqq, "may_idle: sync %d idling_boosts_thr %d",
+ bfq_bfqq_sync(bfqq), idling_boosts_thr);
+@@ -3514,9 +3532,8 @@ static bool bfq_bfqq_may_idle(struct bfq_queue *bfqq)
+ bfq_bfqq_IO_bound(bfqq),
+ idling_needed_for_service_guarantees);
+
+- return bfq_bfqq_sync(bfqq) &&
+- (idling_boosts_thr_without_issues ||
+- idling_needed_for_service_guarantees);
++ return idling_boosts_thr_without_issues ||
++ idling_needed_for_service_guarantees;
+ }
+
+ /*
+@@ -3532,10 +3549,7 @@ static bool bfq_bfqq_may_idle(struct bfq_queue *bfqq)
+ */
+ static bool bfq_bfqq_must_idle(struct bfq_queue *bfqq)
+ {
+- struct bfq_data *bfqd = bfqq->bfqd;
+-
+- return RB_EMPTY_ROOT(&bfqq->sort_list) && bfqd->bfq_slice_idle != 0 &&
+- bfq_bfqq_may_idle(bfqq);
++ return RB_EMPTY_ROOT(&bfqq->sort_list) && bfq_bfqq_may_idle(bfqq);
+ }
+
+ /*
+@@ -3994,7 +4008,6 @@ static void bfq_set_next_ioprio_data(struct bfq_queue *bfqq,
+ case IOPRIO_CLASS_IDLE:
+ bfqq->new_ioprio_class = IOPRIO_CLASS_IDLE;
+ bfqq->new_ioprio = 7;
+- bfq_clear_bfqq_idle_window(bfqq);
+ break;
+ }
+
+@@ -4058,8 +4071,14 @@ static void bfq_init_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq,
+ bfq_set_next_ioprio_data(bfqq, bic);
+
+ if (is_sync) {
++ /*
++ * No need to mark as has_short_ttime if in
++ * idle_class, because no device idling is performed
++ * for queues in idle class
++ */
+ if (!bfq_class_idle(bfqq))
+- bfq_mark_bfqq_idle_window(bfqq);
++ /* tentatively mark as has_short_ttime */
++ bfq_mark_bfqq_has_short_ttime(bfqq);
+ bfq_mark_bfqq_sync(bfqq);
+ bfq_mark_bfqq_just_created(bfqq);
+ } else
+@@ -4195,18 +4214,19 @@ bfq_update_io_seektime(struct bfq_data *bfqd, struct bfq_queue *bfqq,
+ blk_rq_sectors(rq) < BFQQ_SECT_THR_NONROT);
+ }
+
+-/*
+- * Disable idle window if the process thinks too long or seeks so much that
+- * it doesn't matter.
+- */
+-static void bfq_update_idle_window(struct bfq_data *bfqd,
+- struct bfq_queue *bfqq,
+- struct bfq_io_cq *bic)
++static void bfq_update_has_short_ttime(struct bfq_data *bfqd,
++ struct bfq_queue *bfqq,
++ struct bfq_io_cq *bic)
+ {
+- int enable_idle;
++ bool has_short_ttime = true;
+
+- /* Don't idle for async or idle io prio class. */
+- if (!bfq_bfqq_sync(bfqq) || bfq_class_idle(bfqq))
++ /*
++ * No need to update has_short_ttime if bfqq is async or in
++ * idle io prio class, or if bfq_slice_idle is zero, because
++ * no device idling is performed for bfqq in this case.
++ */
++ if (!bfq_bfqq_sync(bfqq) || bfq_class_idle(bfqq) ||
++ bfqd->bfq_slice_idle == 0)
+ return;
+
+ /* Idle window just restored, statistics are meaningless. */
+@@ -4214,27 +4234,22 @@ static void bfq_update_idle_window(struct bfq_data *bfqd,
+ bfqd->bfq_wr_min_idle_time))
+ return;
+
+- enable_idle = bfq_bfqq_idle_window(bfqq);
+-
++ /* Think time is infinite if no process is linked to
++ * bfqq. Otherwise check average think time to
++ * decide whether to mark as has_short_ttime
++ */
+ if (atomic_read(&bic->icq.ioc->active_ref) == 0 ||
+- bfqd->bfq_slice_idle == 0 ||
+- (bfqd->hw_tag && BFQQ_SEEKY(bfqq) &&
+- bfqq->wr_coeff == 1))
+- enable_idle = 0;
+- else if (bfq_sample_valid(bic->ttime.ttime_samples)) {
+- if (bic->ttime.ttime_mean > bfqd->bfq_slice_idle &&
+- bfqq->wr_coeff == 1)
+- enable_idle = 0;
+- else
+- enable_idle = 1;
+- }
+- bfq_log_bfqq(bfqd, bfqq, "update_idle_window: enable_idle %d",
+- enable_idle);
++ (bfq_sample_valid(bic->ttime.ttime_samples) &&
++ bic->ttime.ttime_mean > bfqd->bfq_slice_idle))
++ has_short_ttime = false;
++
++ bfq_log_bfqq(bfqd, bfqq, "update_has_short_ttime: has_short_ttime %d",
++ has_short_ttime);
+
+- if (enable_idle)
+- bfq_mark_bfqq_idle_window(bfqq);
++ if (has_short_ttime)
++ bfq_mark_bfqq_has_short_ttime(bfqq);
+ else
+- bfq_clear_bfqq_idle_window(bfqq);
++ bfq_clear_bfqq_has_short_ttime(bfqq);
+ }
+
+ /*
+@@ -4250,14 +4265,12 @@ static void bfq_rq_enqueued(struct bfq_data *bfqd, struct bfq_queue *bfqq,
+ bfqq->meta_pending++;
+
+ bfq_update_io_thinktime(bfqd, bic);
++ bfq_update_has_short_ttime(bfqd, bfqq, bic);
+ bfq_update_io_seektime(bfqd, bfqq, rq);
+- if (bfqq->entity.service > bfq_max_budget(bfqd) / 8 ||
+- !BFQQ_SEEKY(bfqq))
+- bfq_update_idle_window(bfqd, bfqq, bic);
+
+ bfq_log_bfqq(bfqd, bfqq,
+- "rq_enqueued: idle_window=%d (seeky %d)",
+- bfq_bfqq_idle_window(bfqq), BFQQ_SEEKY(bfqq));
++ "rq_enqueued: has_short_ttime=%d (seeky %d)",
++ bfq_bfqq_has_short_ttime(bfqq), BFQQ_SEEKY(bfqq));
+
+ bfqq->last_request_pos = blk_rq_pos(rq) + blk_rq_sectors(rq);
+
+diff --git a/block/bfq.h b/block/bfq.h
+index ffa833863d88..1f2c7518d507 100644
+--- a/block/bfq.h
++++ b/block/bfq.h
+@@ -349,11 +349,11 @@ struct bfq_io_cq {
+ #endif
+
+ /*
+- * Snapshot of the idle window before merging; taken to
+- * remember this value while the queue is merged, so as to be
+- * able to restore it in case of split.
++ * Snapshot of the has_short_time flag before merging; taken
++ * to remember its value while the queue is merged, so as to
++ * be able to restore it in case of split.
+ */
+- bool saved_idle_window;
++ bool saved_has_short_ttime;
+ /*
+ * Same purpose as the previous two fields for the I/O bound
+ * classification of a queue.
+@@ -610,7 +610,7 @@ enum bfqq_state_flags {
+ */
+ BFQ_BFQQ_FLAG_must_alloc, /* must be allowed rq alloc */
+ BFQ_BFQQ_FLAG_fifo_expire, /* FIFO checked in this slice */
+- BFQ_BFQQ_FLAG_idle_window, /* slice idling enabled */
++ BFQ_BFQQ_FLAG_has_short_ttime, /* queue has a short think time */
+ BFQ_BFQQ_FLAG_sync, /* synchronous queue */
+ BFQ_BFQQ_FLAG_IO_bound, /*
+ * bfqq has timed-out at least once
+@@ -649,7 +649,7 @@ BFQ_BFQQ_FNS(wait_request);
+ BFQ_BFQQ_FNS(non_blocking_wait_rq);
+ BFQ_BFQQ_FNS(must_alloc);
+ BFQ_BFQQ_FNS(fifo_expire);
+-BFQ_BFQQ_FNS(idle_window);
++BFQ_BFQQ_FNS(has_short_ttime);
+ BFQ_BFQQ_FNS(sync);
+ BFQ_BFQQ_FNS(IO_bound);
+ BFQ_BFQQ_FNS(in_large_burst);
diff --git a/PKGBUILD b/PKGBUILD
index 381695a4c40a..962e8c1d1f1f 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -52,7 +52,7 @@ pkgbase=linux-bfq
# pkgname=('linux-bfq' 'linux-bfq-headers' 'linux-bfq-docs')
_srcname=linux-4.11
pkgver=4.11.12
-pkgrel=2
+pkgrel=3
arch=('i686' 'x86_64')
url="http://algo.ing.unimo.it"
license=('GPL2')
@@ -438,7 +438,7 @@ sha512sums=('6610eed97ffb7207c71771198c36179b8244ace7222bebb109507720e26c5f17d91
'd6faa67f3ef40052152254ae43fee031365d0b1524aa0718b659eb75afc21a3f79ea8d62d66ea311a800109bed545bc8f79e8752319cd378eef2cbd3a09aba22'
'2dc6b0ba8f7dbf19d2446c5c5f1823587de89f4e28e9595937dd51a87755099656f2acec50e3e2546ea633ad1bfd1c722e0c2b91eef1d609103d8abdc0a7cbaf'
'b1f6306a27d7e25eb4ff3eb51cb1fe38b0ca035cff229537d1b9f68bdc25861f2fecdeeeb1582e34cd166ee4275e49e4c679247a4c36109b2dcd6d4fa9456d60'
- 'c03c5a8dd81c40e01639d04bbb4d5347e844c76248965c020a76addc83b1e897f4b9a26c6b6125739175577c8d8829054ce7ce8400f8d71d6cd2c2f89fc6ac3b')
+ '9a80a4824e6a8f34a9bcc687b1e1fa91300a5a5fb515db6022e7e43cbacbf2ad93dda1250f968e070be4f6e2429a21e9cf97838120915de9a1144745c34a7188')
validpgpkeys=(
'ABAF11C65A2970B130ABE3C479BE3E4300411886' # Linus Torvalds