diff --git a/kernel/kernel/files/configs/kernel-x86_64-config b/kernel/kernel/files/configs/kernel-x86_64-config index 803993ff..b0c574aa 100644 --- a/kernel/kernel/files/configs/kernel-x86_64-config +++ b/kernel/kernel/files/configs/kernel-x86_64-config @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86_64 4.9.21 Kernel Configuration +# Linux/x86_64 4.9.27 Kernel Configuration # CONFIG_64BIT=y CONFIG_X86_64=y diff --git a/kernel/kernel/files/patches/linux/patch-4.9.27.xz b/kernel/kernel/files/patches/linux/patch-4.9.27.xz new file mode 100644 index 00000000..77b144dc Binary files /dev/null and b/kernel/kernel/files/patches/linux/patch-4.9.27.xz differ diff --git a/kernel/kernel/files/patches/mageia/block-Turn-into-BFQ-v8r6-for-4.9.0.patch b/kernel/kernel/files/patches/mageia/block-Turn-into-BFQ-v8r7-for-4.9.0.patch similarity index 99% rename from kernel/kernel/files/patches/mageia/block-Turn-into-BFQ-v8r6-for-4.9.0.patch rename to kernel/kernel/files/patches/mageia/block-Turn-into-BFQ-v8r7-for-4.9.0.patch index bd1279b5..5a5307fa 100644 --- a/kernel/kernel/files/patches/mageia/block-Turn-into-BFQ-v8r6-for-4.9.0.patch +++ b/kernel/kernel/files/patches/mageia/block-Turn-into-BFQ-v8r7-for-4.9.0.patch @@ -1,9 +1,13 @@ -From 3e3791c0b4ef3b2067f8454e58001af8e3da3840 Mon Sep 17 00:00:00 2001 +From 0432a5c7bfc4a11531c1e58f574c733a2552f149 Mon Sep 17 00:00:00 2001 From: Paolo Valente Date: Tue, 17 May 2016 08:28:04 +0200 -Subject: [PATCH 4/4] Turn into BFQ-v8r6 for 4.9.0 +Subject: [PATCH 4/4] Turn into BFQ-v8r7 for 4.9.0 -CHANGELOG from v8r4 to v8r6 +CHANGELOG from v8r4 to v8r7 + +BFQ v8r7 + +BUGFIX: make BFQ compile also without hierarchical support BFQ v8r6 @@ -125,9 +129,9 @@ Signed-off-by: Paolo Valente block/Kconfig.iosched | 18 +- block/bfq-cgroup.c | 501 +++--- block/bfq-iosched.c | 3278 ++++++++++++++++++++++------------- - block/bfq-sched.c | 1270 +++++++++++--- + block/bfq-sched.c | 1288 +++++++++++--- block/bfq.h | 800 +++++---- - 7 files changed, 4310 insertions(+), 2089 deletions(-) + 7 files changed, 4320 insertions(+), 2097 deletions(-) create mode 100644 Documentation/block/bfq-iosched.txt diff --git a/Documentation/block/00-INDEX b/Documentation/block/00-INDEX @@ -1601,7 +1605,7 @@ index 0367996..bbaecd0 100644 static struct bfq_group * diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c -index cf3e9b1..0f9cd53 100644 +index cf3e9b1..2a2c130 100644 --- a/block/bfq-iosched.c +++ b/block/bfq-iosched.c @@ -1,5 +1,5 @@ @@ -6201,7 +6205,7 @@ index cf3e9b1..0f9cd53 100644 - - if (bfq_timeout_async == 0) - bfq_timeout_async = 1; -+ char msg[60] = "BFQ I/O-scheduler: v8r6"; ++ char msg[60] = "BFQ I/O-scheduler: v8r7"; #ifdef CONFIG_BFQ_GROUP_IOSCHED ret = blkcg_policy_register(&blkcg_policy_bfq); @@ -6265,10 +6269,10 @@ index cf3e9b1..0f9cd53 100644 return 0; diff --git a/block/bfq-sched.c b/block/bfq-sched.c -index a5ed694..4af77f4 100644 +index a5ed694..797bce7 100644 --- a/block/bfq-sched.c +++ b/block/bfq-sched.c -@@ -7,28 +7,46 @@ +@@ -7,28 +7,166 @@ * Copyright (C) 2008 Fabio Checconi * Paolo Valente * @@ -6276,8 +6280,8 @@ index a5ed694..4af77f4 100644 + * Copyright (C) 2015 Paolo Valente + * + * Copyright (C) 2016 Paolo Valente - */ - ++ */ ++ +static struct bfq_group *bfqq_group(struct bfq_queue *bfqq); + +/** @@ -6292,63 +6296,17 @@ index a5ed694..4af77f4 100644 + return (s64)(a - b) > 0; +} + - #ifdef CONFIG_BFQ_GROUP_IOSCHED --#define for_each_entity(entity) \ -+/* both next loops stop at one of the child entities of the root group */ -+#define for_each_entity(entity) \ - for (; entity ; entity = entity->parent) - - #define for_each_entity_safe(entity, parent) \ - for (; entity && ({ parent = entity->parent; 1; }); entity = parent) - - --static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd, -- int extract, -- struct bfq_data *bfqd); -- --static struct bfq_group *bfqq_group(struct bfq_queue *bfqq); -+static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd); - --static void bfq_update_budget(struct bfq_entity *next_in_service) -+/* -+ * Returns true if this budget changes may let next_in_service->parent -+ * become the next_in_service entity for its parent entity. -+ */ -+static bool bfq_update_parent_budget(struct bfq_entity *next_in_service) - { - struct bfq_entity *bfqg_entity; - struct bfq_group *bfqg; - struct bfq_sched_data *group_sd; -+ bool ret = false; - - BUG_ON(!next_in_service); - -@@ -41,39 +59,134 @@ static void bfq_update_budget(struct bfq_entity *next_in_service) - * as it must never become an in-service entity. - */ - bfqg_entity = bfqg->my_entity; -- if (bfqg_entity) -+ if (bfqg_entity) { -+ if (bfqg_entity->budget > next_in_service->budget) -+ ret = true; - bfqg_entity->budget = next_in_service->budget; -+ } -+ -+ return ret; - } - --static int bfq_update_next_in_service(struct bfq_sched_data *sd) +static struct bfq_entity *bfq_root_active_entity(struct rb_root *tree) - { -- struct bfq_entity *next_in_service; ++{ + struct rb_node *node = tree->rb_node; - -- if (sd->in_service_entity) -- /* will update/requeue at the end of service */ -- return 0; ++ + return rb_entry(node, struct bfq_entity, rb_node); +} + ++static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd); ++ ++static bool bfq_update_parent_budget(struct bfq_entity *next_in_service); ++ +/** + * bfq_update_next_in_service - update sd->next_in_service + * @sd: sched_data for which to perform the update. @@ -6371,20 +6329,15 @@ index a5ed694..4af77f4 100644 + * Returns true if sd->next_in_service changes in such a way that + * entity->parent may become the next_in_service for its parent + * entity. -+ */ + */ +static bool bfq_update_next_in_service(struct bfq_sched_data *sd, + struct bfq_entity *new_entity) +{ + struct bfq_entity *next_in_service = sd->next_in_service; + struct bfq_queue *bfqq; + bool parent_sched_may_change = false; - - /* -- * NOTE: this can be improved in many ways, such as returning -- * 1 (and thus propagating upwards the update) only when the -- * budget changes, or caching the bfqq that will be scheduled -- * next from this subtree. By now we worry more about -- * correctness than about performance... ++ ++ /* + * If this update is triggered by the activation, requeueing + * or repositiong of an entity that does not coincide with + * sd->next_in_service, then a full lookup in the active tree @@ -6395,8 +6348,7 @@ index a5ed694..4af77f4 100644 + * finish time than sd->next_in_service. If this compound + * condition holds, then the new entity becomes the new + * next_in_service. Otherwise no change is needed. - */ -- next_in_service = bfq_lookup_next_entity(sd, 0, NULL); ++ */ + if (new_entity && new_entity != sd->next_in_service) { + /* + * Flag used to decide whether to replace @@ -6445,54 +6397,160 @@ index a5ed694..4af77f4 100644 + bfq_update_parent_budget(next_in_service); + } + - sd->next_in_service = next_in_service; - -- if (next_in_service) -- bfq_update_budget(next_in_service); ++ sd->next_in_service = next_in_service; ++ + if (!next_in_service) + return parent_sched_may_change; -- return 1; --} + bfqq = bfq_entity_to_bfqq(next_in_service); + if (bfqq) + bfq_log_bfqq(bfqq->bfqd, bfqq, + "update_next_in_service: chosen this queue"); -+#ifdef CONFIG_BFQ_GROUP_IOSCHED + #ifdef CONFIG_BFQ_GROUP_IOSCHED +-#define for_each_entity(entity) \ + else { + struct bfq_group *bfqg = + container_of(next_in_service, + struct bfq_group, entity); - --static void bfq_check_next_in_service(struct bfq_sched_data *sd, -- struct bfq_entity *entity) --{ -- BUG_ON(sd->next_in_service != entity); ++ + bfq_log_bfqg((struct bfq_data *)bfqg->bfqd, bfqg, + "update_next_in_service: chosen this entity"); + } +#endif + return parent_sched_may_change; - } ++} + - #else - #define for_each_entity(entity) \ - for (; entity ; entity = NULL) -@@ -86,12 +199,7 @@ static int bfq_update_next_in_service(struct bfq_sched_data *sd) - return 0; ++#ifdef CONFIG_BFQ_GROUP_IOSCHED ++/* both next loops stop at one of the child entities of the root group */ ++#define for_each_entity(entity) \ + for (; entity ; entity = entity->parent) + + #define for_each_entity_safe(entity, parent) \ + for (; entity && ({ parent = entity->parent; 1; }); entity = parent) + +- +-static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd, +- int extract, +- struct bfq_data *bfqd); +- +-static struct bfq_group *bfqq_group(struct bfq_queue *bfqq); +- +-static void bfq_update_budget(struct bfq_entity *next_in_service) ++/* ++ * Returns true if this budget changes may let next_in_service->parent ++ * become the next_in_service entity for its parent entity. ++ */ ++static bool bfq_update_parent_budget(struct bfq_entity *next_in_service) + { + struct bfq_entity *bfqg_entity; + struct bfq_group *bfqg; + struct bfq_sched_data *group_sd; ++ bool ret = false; + + BUG_ON(!next_in_service); + +@@ -41,60 +179,68 @@ static void bfq_update_budget(struct bfq_entity *next_in_service) + * as it must never become an in-service entity. + */ + bfqg_entity = bfqg->my_entity; +- if (bfqg_entity) ++ if (bfqg_entity) { ++ if (bfqg_entity->budget > next_in_service->budget) ++ ret = true; + bfqg_entity->budget = next_in_service->budget; ++ } ++ ++ return ret; + } + +-static int bfq_update_next_in_service(struct bfq_sched_data *sd) ++/* ++ * This function tells whether entity stops being a candidate for next ++ * service, according to the following logic. ++ * ++ * This function is invoked for an entity that is about to be set in ++ * service. If such an entity is a queue, then the entity is no longer ++ * a candidate for next service (i.e, a candidate entity to serve ++ * after the in-service entity is expired). The function then returns ++ * true. ++ * ++ * In contrast, the entity could stil be a candidate for next service ++ * if it is not a queue, and has more than one child. In fact, even if ++ * one of its children is about to be set in service, other children ++ * may still be the next to serve. As a consequence, a non-queue ++ * entity is not a candidate for next-service only if it has only one ++ * child. And only if this condition holds, then the function returns ++ * true for a non-queue entity. ++ */ ++static bool bfq_no_longer_next_in_service(struct bfq_entity *entity) + { +- struct bfq_entity *next_in_service; ++ struct bfq_group *bfqg; + +- if (sd->in_service_entity) +- /* will update/requeue at the end of service */ +- return 0; ++ if (bfq_entity_to_bfqq(entity)) ++ return true; + +- /* +- * NOTE: this can be improved in many ways, such as returning +- * 1 (and thus propagating upwards the update) only when the +- * budget changes, or caching the bfqq that will be scheduled +- * next from this subtree. By now we worry more about +- * correctness than about performance... +- */ +- next_in_service = bfq_lookup_next_entity(sd, 0, NULL); +- sd->next_in_service = next_in_service; ++ bfqg = container_of(entity, struct bfq_group, entity); + +- if (next_in_service) +- bfq_update_budget(next_in_service); ++ BUG_ON(bfqg == ((struct bfq_data *)(bfqg->bfqd))->root_group); ++ BUG_ON(bfqg->active_entities == 0); ++ if (bfqg->active_entities == 1) ++ return true; + +- return 1; ++ return false; } -static void bfq_check_next_in_service(struct bfq_sched_data *sd, - struct bfq_entity *entity) -{ +- BUG_ON(sd->next_in_service != entity); -} -- --static void bfq_update_budget(struct bfq_entity *next_in_service) -+static void bfq_update_parent_budget(struct bfq_entity *next_in_service) +-#else ++#else /* CONFIG_BFQ_GROUP_IOSCHED */ + #define for_each_entity(entity) \ + for (; entity ; entity = NULL) + + #define for_each_entity_safe(entity, parent) \ + for (parent = NULL; entity ; entity = parent) + +-static int bfq_update_next_in_service(struct bfq_sched_data *sd) ++static bool bfq_update_parent_budget(struct bfq_entity *next_in_service) { +- return 0; ++ return false; } - #endif -@@ -105,18 +213,6 @@ static void bfq_update_budget(struct bfq_entity *next_in_service) + +-static void bfq_check_next_in_service(struct bfq_sched_data *sd, +- struct bfq_entity *entity) ++static bool bfq_no_longer_next_in_service(struct bfq_entity *entity) + { ++ return true; + } + +-static void bfq_update_budget(struct bfq_entity *next_in_service) +-{ +-} +-#endif ++#endif /* CONFIG_BFQ_GROUP_IOSCHED */ + + /* + * Shift for timestamp calculations. This actually limits the maximum +@@ -105,18 +251,6 @@ static void bfq_update_budget(struct bfq_entity *next_in_service) */ #define WFQ_SERVICE_SHIFT 22 @@ -6511,7 +6569,7 @@ index a5ed694..4af77f4 100644 static struct bfq_queue *bfq_entity_to_bfqq(struct bfq_entity *entity) { struct bfq_queue *bfqq = NULL; -@@ -151,20 +247,36 @@ static u64 bfq_delta(unsigned long service, unsigned long weight) +@@ -151,20 +285,36 @@ static u64 bfq_delta(unsigned long service, unsigned long weight) static void bfq_calc_finish(struct bfq_entity *entity, unsigned long service) { struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); @@ -6550,7 +6608,7 @@ index a5ed694..4af77f4 100644 } } -@@ -293,10 +405,26 @@ static void bfq_update_min(struct bfq_entity *entity, struct rb_node *node) +@@ -293,10 +443,26 @@ static void bfq_update_min(struct bfq_entity *entity, struct rb_node *node) static void bfq_update_active_node(struct rb_node *node) { struct bfq_entity *entity = rb_entry(node, struct bfq_entity, rb_node); @@ -6577,7 +6635,7 @@ index a5ed694..4af77f4 100644 } /** -@@ -386,8 +514,6 @@ static void bfq_active_insert(struct bfq_service_tree *st, +@@ -386,8 +552,6 @@ static void bfq_active_insert(struct bfq_service_tree *st, BUG_ON(!bfqg); BUG_ON(!bfqd); bfqg->active_entities++; @@ -6586,7 +6644,7 @@ index a5ed694..4af77f4 100644 } #endif } -@@ -399,7 +525,7 @@ static void bfq_active_insert(struct bfq_service_tree *st, +@@ -399,7 +563,7 @@ static void bfq_active_insert(struct bfq_service_tree *st, static unsigned short bfq_ioprio_to_weight(int ioprio) { BUG_ON(ioprio < 0 || ioprio >= IOPRIO_BE_NR); @@ -6595,7 +6653,7 @@ index a5ed694..4af77f4 100644 } /** -@@ -422,9 +548,9 @@ static void bfq_get_entity(struct bfq_entity *entity) +@@ -422,9 +586,9 @@ static void bfq_get_entity(struct bfq_entity *entity) struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); if (bfqq) { @@ -6607,7 +6665,7 @@ index a5ed694..4af77f4 100644 } } -@@ -499,10 +625,6 @@ static void bfq_active_extract(struct bfq_service_tree *st, +@@ -499,10 +663,6 @@ static void bfq_active_extract(struct bfq_service_tree *st, BUG_ON(!bfqd); BUG_ON(!bfqg->active_entities); bfqg->active_entities--; @@ -6618,7 +6676,7 @@ index a5ed694..4af77f4 100644 } #endif } -@@ -547,12 +669,12 @@ static void bfq_forget_entity(struct bfq_service_tree *st, +@@ -547,12 +707,12 @@ static void bfq_forget_entity(struct bfq_service_tree *st, BUG_ON(!entity->on_st); @@ -6633,7 +6691,7 @@ index a5ed694..4af77f4 100644 bfq_put_queue(bfqq); } } -@@ -602,7 +724,7 @@ __bfq_entity_update_weight_prio(struct bfq_service_tree *old_st, +@@ -602,7 +762,7 @@ __bfq_entity_update_weight_prio(struct bfq_service_tree *old_st, if (entity->prio_changed) { struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); @@ -6642,7 +6700,7 @@ index a5ed694..4af77f4 100644 struct bfq_data *bfqd = NULL; struct rb_root *root; #ifdef CONFIG_BFQ_GROUP_IOSCHED -@@ -630,7 +752,10 @@ __bfq_entity_update_weight_prio(struct bfq_service_tree *old_st, +@@ -630,7 +790,10 @@ __bfq_entity_update_weight_prio(struct bfq_service_tree *old_st, entity->new_weight > BFQ_MAX_WEIGHT) { pr_crit("update_weight_prio: new_weight %d\n", entity->new_weight); @@ -6654,7 +6712,7 @@ index a5ed694..4af77f4 100644 } entity->orig_weight = entity->new_weight; if (bfqq) -@@ -661,6 +786,13 @@ __bfq_entity_update_weight_prio(struct bfq_service_tree *old_st, +@@ -661,6 +824,13 @@ __bfq_entity_update_weight_prio(struct bfq_service_tree *old_st, * associated with its new weight. */ if (prev_weight != new_weight) { @@ -6668,7 +6726,7 @@ index a5ed694..4af77f4 100644 root = bfqq ? &bfqd->queue_weights_tree : &bfqd->group_weights_tree; bfq_weights_tree_remove(bfqd, entity, root); -@@ -707,7 +839,7 @@ static void bfq_bfqq_served(struct bfq_queue *bfqq, int served) +@@ -707,7 +877,7 @@ static void bfq_bfqq_served(struct bfq_queue *bfqq, int served) st = bfq_entity_service_tree(entity); entity->service += served; @@ -6677,7 +6735,7 @@ index a5ed694..4af77f4 100644 BUG_ON(st->wsum == 0); st->vtime += bfq_delta(served, st->wsum); -@@ -716,170 +848,419 @@ static void bfq_bfqq_served(struct bfq_queue *bfqq, int served) +@@ -716,170 +886,419 @@ static void bfq_bfqq_served(struct bfq_queue *bfqq, int served) #ifdef CONFIG_BFQ_GROUP_IOSCHED bfqg_stats_set_start_empty_time(bfqq_group(bfqq)); #endif @@ -6731,17 +6789,17 @@ index a5ed694..4af77f4 100644 + if (time_ms > 0 && time_ms < timeout_ms) + tot_serv_to_charge = + (bfqd->bfq_max_budget * time_ms) / timeout_ms; -+ + +- bfq_log_bfqq(bfqq->bfqd, bfqq, "charge_full_budget"); + if (tot_serv_to_charge < entity->service) + tot_serv_to_charge = entity->service; -- bfq_log_bfqq(bfqq->bfqd, bfqq, "charge_full_budget"); +- bfq_bfqq_served(bfqq, entity->budget - entity->service); + bfq_log_bfqq(bfqq->bfqd, bfqq, + "charge_time: %lu/%u ms, %d/%d/%d sectors", + time_ms, timeout_ms, entity->service, + tot_serv_to_charge, entity->budget); - -- bfq_bfqq_served(bfqq, entity->budget - entity->service); ++ + /* Increase budget to avoid inconsistencies */ + if (tot_serv_to_charge > entity->budget) + entity->budget = tot_serv_to_charge; @@ -6948,19 +7006,20 @@ index a5ed694..4af77f4 100644 - * @entity: the entity to activate. + * __bfq_requeue_entity - handle requeueing or repositioning of an entity. + * @entity: the entity being requeued or repositioned. - * -- * Activate @entity and all the entities on the path from it to the root. ++ * + * Requeueing is needed if this entity stops being served, which + * happens if a leaf descendant entity has expired. On the other hand, + * repositioning is needed if the next_inservice_entity for the child + * entity has changed. See the comments inside the function for + * details. -+ * + * +- * Activate @entity and all the entities on the path from it to the root. + * Basically, this function: 1) removes entity from its active tree if + * present there, 2) updates the timestamps of entity and 3) inserts + * entity back into its active tree (in the new, right position for + * the new values of the timestamps). -+ */ + */ +-static void bfq_activate_entity(struct bfq_entity *entity) +static void __bfq_requeue_entity(struct bfq_entity *entity) +{ + struct bfq_sched_data *sd = entity->sched_data; @@ -7065,8 +7124,7 @@ index a5ed694..4af77f4 100644 + * @requeue: true if this is a requeue, which implies that bfqq is + * being expired; thus ALL its ancestors stop being served and must + * therefore be requeued - */ --static void bfq_activate_entity(struct bfq_entity *entity) ++ */ +static void bfq_activate_requeue_entity(struct bfq_entity *entity, + bool non_blocking_wait_rq, + bool requeue) @@ -7186,7 +7244,7 @@ index a5ed694..4af77f4 100644 { struct bfq_sched_data *sd; struct bfq_entity *parent; -@@ -887,63 +1268,153 @@ static void bfq_deactivate_entity(struct bfq_entity *entity, int requeue) +@@ -887,63 +1306,154 @@ static void bfq_deactivate_entity(struct bfq_entity *entity, int requeue) for_each_entity_safe(entity, parent) { sd = entity->sched_data; @@ -7309,7 +7367,8 @@ index a5ed694..4af77f4 100644 + if (!bfq_update_next_in_service(sd, entity) && + !expiration) + /* -+ * next_in_service unchanged, and no ++ * next_in_service unchanged or not causing ++ * any change in entity->parent->sd, and no + * requeueing needed for expiration: stop + * here. + */ @@ -7339,13 +7398,13 @@ index a5ed694..4af77f4 100644 - struct bfq_entity *entry; - struct rb_node *node = st->active.rb_node; + struct bfq_entity *root_entity = bfq_root_active_entity(&st->active); ++ ++ if (bfq_gt(root_entity->min_start, st->vtime)) { ++ struct bfq_queue *bfqq = bfq_entity_to_bfqq(root_entity); - entry = rb_entry(node, struct bfq_entity, rb_node); - if (bfq_gt(entry->min_start, st->vtime)) { - st->vtime = entry->min_start; -+ if (bfq_gt(root_entity->min_start, st->vtime)) { -+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(root_entity); -+ + if (bfqq) + bfq_log_bfqq(bfqq->bfqd, bfqq, + "calc_vtime_jump: new value %llu", @@ -7373,7 +7432,7 @@ index a5ed694..4af77f4 100644 bfq_forget_idle(st); } } -@@ -952,6 +1423,7 @@ static void bfq_update_vtime(struct bfq_service_tree *st) +@@ -952,6 +1462,7 @@ static void bfq_update_vtime(struct bfq_service_tree *st) * bfq_first_active_entity - find the eligible entity with * the smallest finish time * @st: the service tree to select from. @@ -7381,7 +7440,7 @@ index a5ed694..4af77f4 100644 * * This function searches the first schedulable entity, starting from the * root of the tree and going on the left every time on this side there is -@@ -959,7 +1431,8 @@ static void bfq_update_vtime(struct bfq_service_tree *st) +@@ -959,7 +1470,8 @@ static void bfq_update_vtime(struct bfq_service_tree *st) * the right is followed only if a) the left subtree contains no eligible * entities and b) no eligible entity has been found yet. */ @@ -7391,7 +7450,7 @@ index a5ed694..4af77f4 100644 { struct bfq_entity *entry, *first = NULL; struct rb_node *node = st->active.rb_node; -@@ -967,15 +1440,15 @@ static struct bfq_entity *bfq_first_active_entity(struct bfq_service_tree *st) +@@ -967,15 +1479,15 @@ static struct bfq_entity *bfq_first_active_entity(struct bfq_service_tree *st) while (node) { entry = rb_entry(node, struct bfq_entity, rb_node); left: @@ -7410,7 +7469,7 @@ index a5ed694..4af77f4 100644 node = node->rb_left; goto left; } -@@ -993,31 +1466,84 @@ static struct bfq_entity *bfq_first_active_entity(struct bfq_service_tree *st) +@@ -993,31 +1505,84 @@ static struct bfq_entity *bfq_first_active_entity(struct bfq_service_tree *st) * __bfq_lookup_next_entity - return the first eligible entity in @st. * @st: the service tree. * @@ -7510,7 +7569,7 @@ index a5ed694..4af77f4 100644 return entity; } -@@ -1025,50 +1551,118 @@ static struct bfq_entity *__bfq_lookup_next_entity(struct bfq_service_tree *st, +@@ -1025,50 +1590,81 @@ static struct bfq_entity *__bfq_lookup_next_entity(struct bfq_service_tree *st, /** * bfq_lookup_next_entity - return the first eligible entity in @sd. * @sd: the sched_data. @@ -7620,48 +7679,11 @@ index a5ed694..4af77f4 100644 + + return sd->next_in_service != sd->in_service_entity; +} -+ -+/* -+ * This function tells whether entity stops being a candidate for next -+ * service, according to the following logic. -+ * -+ * This function is invoked for an entity that is about to be set in -+ * service. If such an entity is a queue, then the entity is no longer -+ * a candidate for next service (i.e, a candidate entity to serve -+ * after the in-service entity is expired). The function then returns -+ * true. -+ * -+ * In contrast, the entity could stil be a candidate for next service -+ * if it is not a queue, and has more than one child. In fact, even if -+ * one of its children is about to be set in service, other children -+ * may still be the next to serve. As a consequence, a non-queue -+ * entity is not a candidate for next-service only if it has only one -+ * child. And only if this condition holds, then the function returns -+ * true for a non-queue entity. -+ */ -+static bool bfq_no_longer_next_in_service(struct bfq_entity *entity) -+{ -+ struct bfq_group *bfqg; -+ -+ if (bfq_entity_to_bfqq(entity)) -+ return true; -+ -+#ifdef CONFIG_BFQ_GROUP_IOSCHED -+ bfqg = container_of(entity, struct bfq_group, entity); -+ -+ BUG_ON(bfqg == ((struct bfq_data *)(bfqg->bfqd))->root_group); -+ BUG_ON(bfqg->active_entities == 0); -+ if (bfqg->active_entities == 1) -+ return true; -+#endif -+ -+ return false; -+} + /* * Get next queue for service. */ -@@ -1083,58 +1677,208 @@ static struct bfq_queue *bfq_get_next_queue(struct bfq_data *bfqd) +@@ -1083,58 +1679,208 @@ static struct bfq_queue *bfq_get_next_queue(struct bfq_data *bfqd) if (bfqd->busy_queues == 0) return NULL; @@ -7883,7 +7905,7 @@ index a5ed694..4af77f4 100644 { BUG_ON(!bfq_bfqq_busy(bfqq)); BUG_ON(!RB_EMPTY_ROOT(&bfqq->sort_list)); -@@ -1146,27 +1890,20 @@ static void bfq_del_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq, +@@ -1146,27 +1892,20 @@ static void bfq_del_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq, BUG_ON(bfqd->busy_queues == 0); bfqd->busy_queues--; @@ -7918,7 +7940,7 @@ index a5ed694..4af77f4 100644 } /* -@@ -1184,16 +1921,11 @@ static void bfq_add_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq) +@@ -1184,16 +1923,11 @@ static void bfq_add_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq) bfq_mark_bfqq_busy(bfqq); bfqd->busy_queues++; @@ -7938,13 +7960,13 @@ index a5ed694..4af77f4 100644 bfqd->wr_busy_queues++; } diff --git a/block/bfq.h b/block/bfq.h -index fcce855..57ab51d 100644 +index fcce855..bef8244 100644 --- a/block/bfq.h +++ b/block/bfq.h @@ -1,5 +1,5 @@ /* - * BFQ-v7r11 for 4.5.0: data structures and common functions prototypes. -+ * BFQ v8r6 for 4.9.0: data structures and common functions prototypes. ++ * BFQ v8r7 for 4.9.0: data structures and common functions prototypes. * * Based on ideas and code from CFQ: * Copyright (C) 2003 Jens Axboe diff --git a/kernel/kernel/files/patches/mageia/block-update-bfq-from-v8r7-to-v8r10.patch b/kernel/kernel/files/patches/mageia/block-update-bfq-from-v8r7-to-v8r10.patch new file mode 100644 index 00000000..17cea46c --- /dev/null +++ b/kernel/kernel/files/patches/mageia/block-update-bfq-from-v8r7-to-v8r10.patch @@ -0,0 +1,729 @@ + block/bfq-cgroup.c | 12 +-- + block/bfq-iosched.c | 211 +++++++++++++++++++++++++++++++--------------------- + block/bfq-sched.c | 73 ++++++++++++------ + block/bfq.h | 4 +- + 4 files changed, 180 insertions(+), 120 deletions(-) + +diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c +index bbaecd0..a66a723 100644 +--- a/block/bfq-cgroup.c ++++ b/block/bfq-cgroup.c +@@ -771,7 +771,6 @@ static void bfq_pd_offline(struct blkg_policy_data *pd) + + __bfq_deactivate_entity(entity, false); + bfq_put_async_queues(bfqd, bfqg); +- BUG_ON(entity->tree); + + /* + * @blkg is going offline and will be ignored by +@@ -1140,6 +1139,9 @@ static inline void bfqg_stats_update_idle_time(struct bfq_group *bfqg) { } + static inline void bfqg_stats_set_start_idle_time(struct bfq_group *bfqg) { } + static inline void bfqg_stats_update_avg_queue_size(struct bfq_group *bfqg) { } + ++static void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq, ++ struct bfq_group *bfqg) {} ++ + static void bfq_init_entity(struct bfq_entity *entity, + struct bfq_group *bfqg) + { +@@ -1154,13 +1156,7 @@ static void bfq_init_entity(struct bfq_entity *entity, + entity->sched_data = &bfqg->sched_data; + } + +-static struct bfq_group * +-bfq_bic_update_cgroup(struct bfq_io_cq *bic, struct bio *bio) +-{ +- struct bfq_data *bfqd = bic_to_bfqd(bic); +- +- return bfqd->root_group; +-} ++static void bfq_bic_update_cgroup(struct bfq_io_cq *bic, struct bio *bio) {} + + static void bfq_end_wr_async(struct bfq_data *bfqd) + { +diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c +index 78baa07..96b79a0 100644 +--- a/block/bfq-iosched.c ++++ b/block/bfq-iosched.c +@@ -9,7 +9,7 @@ + * + * Copyright (C) 2015 Paolo Valente + * +- * Copyright (C) 2016 Paolo Valente ++ * Copyright (C) 2017 Paolo Valente + * + * Licensed under the GPL-2 as detailed in the accompanying COPYING.BFQ + * file. +@@ -107,7 +107,7 @@ static const int bfq_async_charge_factor = 10; + /* Default timeout values, in jiffies, approximating CFQ defaults. */ + static const int bfq_timeout = (HZ / 8); + +-struct kmem_cache *bfq_pool; ++static struct kmem_cache *bfq_pool; + + /* Below this threshold (in ns), we consider thinktime immediate. */ + #define BFQ_MIN_TT (2 * NSEC_PER_MSEC) +@@ -483,6 +483,22 @@ static void bfq_weights_tree_add(struct bfq_data *bfqd, + + entity->weight_counter = kzalloc(sizeof(struct bfq_weight_counter), + GFP_ATOMIC); ++ ++ /* ++ * In the unlucky event of an allocation failure, we just ++ * exit. This will cause the weight of entity to not be ++ * considered in bfq_differentiated_weights, which, in its ++ * turn, causes the scenario to be deemed wrongly symmetric in ++ * case entity's weight would have been the only weight making ++ * the scenario asymmetric. On the bright side, no unbalance ++ * will however occur when entity becomes inactive again (the ++ * invocation of this function is triggered by an activation ++ * of entity). In fact, bfq_weights_tree_remove does nothing ++ * if !entity->weight_counter. ++ */ ++ if (unlikely(!entity->weight_counter)) ++ return; ++ + entity->weight_counter->weight = entity->weight; + rb_link_node(&entity->weight_counter->weights_node, parent, new); + rb_insert_color(&entity->weight_counter->weights_node, root); +@@ -519,13 +535,45 @@ static void bfq_weights_tree_remove(struct bfq_data *bfqd, + entity->weight_counter = NULL; + } + ++/* ++ * Return expired entry, or NULL to just start from scratch in rbtree. ++ */ ++static struct request *bfq_check_fifo(struct bfq_queue *bfqq, ++ struct request *last) ++{ ++ struct request *rq; ++ ++ if (bfq_bfqq_fifo_expire(bfqq)) ++ return NULL; ++ ++ bfq_mark_bfqq_fifo_expire(bfqq); ++ ++ rq = rq_entry_fifo(bfqq->fifo.next); ++ ++ if (rq == last || ktime_get_ns() < rq->fifo_time) ++ return NULL; ++ ++ bfq_log_bfqq(bfqq->bfqd, bfqq, "check_fifo: returned %p", rq); ++ BUG_ON(RB_EMPTY_NODE(&rq->rb_node)); ++ return rq; ++} ++ + static struct request *bfq_find_next_rq(struct bfq_data *bfqd, + struct bfq_queue *bfqq, + struct request *last) + { + struct rb_node *rbnext = rb_next(&last->rb_node); + struct rb_node *rbprev = rb_prev(&last->rb_node); +- struct request *next = NULL, *prev = NULL; ++ struct request *next, *prev = NULL; ++ ++ BUG_ON(list_empty(&bfqq->fifo)); ++ ++ /* Follow expired path, else get first next available. */ ++ next = bfq_check_fifo(bfqq, last); ++ if (next) { ++ BUG_ON(next == last); ++ return next; ++ } + + BUG_ON(RB_EMPTY_NODE(&last->rb_node)); + +@@ -1359,7 +1407,6 @@ static void bfq_bfqq_handle_idle_busy_switch(struct bfq_data *bfqd, + + bfq_bfqq_expire(bfqd, bfqd->in_service_queue, + false, BFQ_BFQQ_PREEMPTED); +- BUG_ON(in_serv->entity.budget < 0); + } + } + +@@ -1523,12 +1570,15 @@ static void bfq_remove_request(struct request *rq) + elv_rb_del(&bfqq->sort_list, rq); + + if (RB_EMPTY_ROOT(&bfqq->sort_list)) { ++ bfqq->next_rq = NULL; ++ + BUG_ON(bfqq->entity.budget < 0); + + if (bfq_bfqq_busy(bfqq) && bfqq != bfqd->in_service_queue) { ++ BUG_ON(bfqq->ref < 2); /* referred by rq and on tree */ + bfq_del_bfqq_busy(bfqd, bfqq, false); +- +- /* bfqq emptied. In normal operation, when ++ /* ++ * bfqq emptied. In normal operation, when + * bfqq is empty, bfqq->entity.service and + * bfqq->entity.budget must contain, + * respectively, the service received and the +@@ -1537,7 +1587,8 @@ static void bfq_remove_request(struct request *rq) + * this last removal occurred while bfqq is + * not in service. To avoid inconsistencies, + * reset both bfqq->entity.service and +- * bfqq->entity.budget. ++ * bfqq->entity.budget, if bfqq has still a ++ * process that may issue I/O requests to it. + */ + bfqq->entity.budget = bfqq->entity.service = 0; + } +@@ -1868,7 +1919,7 @@ static bool bfq_may_be_close_cooperator(struct bfq_queue *bfqq, + * positives. In case bfqq is weight-raised, such false positives + * would evidently degrade latency guarantees for bfqq. + */ +-bool wr_from_too_long(struct bfq_queue *bfqq) ++static bool wr_from_too_long(struct bfq_queue *bfqq) + { + return bfqq->wr_coeff > 1 && + time_is_before_jiffies(bfqq->last_wr_start_finish + +@@ -2029,7 +2080,8 @@ bfq_merge_bfqqs(struct bfq_data *bfqd, struct bfq_io_cq *bic, + new_bfqq->wr_coeff = bfqq->wr_coeff; + new_bfqq->wr_cur_max_time = bfqq->wr_cur_max_time; + new_bfqq->last_wr_start_finish = bfqq->last_wr_start_finish; +- new_bfqq->wr_start_at_switch_to_srt = bfqq->wr_start_at_switch_to_srt; ++ new_bfqq->wr_start_at_switch_to_srt = ++ bfqq->wr_start_at_switch_to_srt; + if (bfq_bfqq_busy(new_bfqq)) + bfqd->wr_busy_queues++; + new_bfqq->entity.prio_changed = 1; +@@ -2072,6 +2124,7 @@ bfq_merge_bfqqs(struct bfq_data *bfqd, struct bfq_io_cq *bic, + */ + new_bfqq->bic = NULL; + bfqq->bic = NULL; ++ /* release process reference to bfqq */ + bfq_put_queue(bfqq); + } + +@@ -2298,7 +2351,7 @@ static unsigned long bfq_calc_max_budget(struct bfq_data *bfqd) + * function of the estimated peak rate. See comments on + * bfq_calc_max_budget(), and on T_slow and T_fast arrays. + */ +-void update_thr_responsiveness_params(struct bfq_data *bfqd) ++static void update_thr_responsiveness_params(struct bfq_data *bfqd) + { + int dev_type = blk_queue_nonrot(bfqd->queue); + +@@ -2333,7 +2386,7 @@ void update_thr_responsiveness_params(struct bfq_data *bfqd) + BFQ_RATE_SHIFT); + } + +-void bfq_reset_rate_computation(struct bfq_data *bfqd, struct request *rq) ++static void bfq_reset_rate_computation(struct bfq_data *bfqd, struct request *rq) + { + if (rq != NULL) { /* new rq dispatch now, reset accordingly */ + bfqd->last_dispatch = bfqd->first_dispatch = ktime_get_ns() ; +@@ -2350,7 +2403,7 @@ void bfq_reset_rate_computation(struct bfq_data *bfqd, struct request *rq) + bfqd->tot_sectors_dispatched); + } + +-void bfq_update_rate_reset(struct bfq_data *bfqd, struct request *rq) ++static void bfq_update_rate_reset(struct bfq_data *bfqd, struct request *rq) + { + u32 rate, weight, divisor; + +@@ -2400,7 +2453,7 @@ void bfq_update_rate_reset(struct bfq_data *bfqd, struct request *rq) + * total, and rate is below the current estimated peak rate + * - rate is unreasonably high (> 20M sectors/sec) + */ +- if ((bfqd->peak_rate_samples > (3 * bfqd->sequential_samples)>>2 && ++ if ((bfqd->sequential_samples < (3 * bfqd->peak_rate_samples)>>2 && + rate <= bfqd->peak_rate) || + rate > 20<fifo)) +- return NULL; +- +- rq = rq_entry_fifo(bfqq->fifo.next); +- +- if (ktime_get_ns() < rq->fifo_time) +- return NULL; +- +- return rq; +-} +- + static void __bfq_bfqq_expire(struct bfq_data *bfqd, struct bfq_queue *bfqq) + { + BUG_ON(bfqq != bfqd->in_service_queue); +@@ -2904,8 +2934,8 @@ static bool bfq_bfqq_is_slow(struct bfq_data *bfqd, struct bfq_queue *bfqq, + delta_ktime = ktime_sub(delta_ktime, bfqd->last_budget_start); + delta_usecs = ktime_to_us(delta_ktime); + +- /* don't trust short/unrealistic values. */ +- if (delta_usecs < 1000 || delta_usecs >= LONG_MAX) { ++ /* don't use too short time intervals */ ++ if (delta_usecs < 1000) { + if (blk_queue_nonrot(bfqd->queue)) + /* + * give same worst-case guarantees as idling +@@ -2915,7 +2945,7 @@ static bool bfq_bfqq_is_slow(struct bfq_data *bfqd, struct bfq_queue *bfqq, + else /* charge at least one seek */ + *delta_ms = bfq_slice_idle / NSEC_PER_MSEC; + +- bfq_log(bfqd, "bfq_bfqq_is_slow: unrealistic %u", delta_usecs); ++ bfq_log(bfqd, "bfq_bfqq_is_slow: too short %u", delta_usecs); + + return slow; + } +@@ -3067,6 +3097,7 @@ static void bfq_bfqq_expire(struct bfq_data *bfqd, + bool slow; + unsigned long delta = 0; + struct bfq_entity *entity = &bfqq->entity; ++ int ref; + + BUG_ON(bfqq != bfqd->in_service_queue); + +@@ -3174,12 +3205,15 @@ static void bfq_bfqq_expire(struct bfq_data *bfqd, + __bfq_bfqq_recalc_budget(bfqd, bfqq, reason); + BUG_ON(bfqq->next_rq == NULL && + bfqq->entity.budget < bfqq->entity.service); ++ ref = bfqq->ref; + __bfq_bfqq_expire(bfqd, bfqq); + +- BUG_ON(!bfq_bfqq_busy(bfqq) && reason == BFQ_BFQQ_BUDGET_EXHAUSTED && ++ BUG_ON(ref > 1 && ++ !bfq_bfqq_busy(bfqq) && reason == BFQ_BFQQ_BUDGET_EXHAUSTED && + !bfq_class_idle(bfqq)); + +- if (!bfq_bfqq_busy(bfqq) && ++ /* mark bfqq as waiting a request only if a bic still points to it */ ++ if (ref > 1 && !bfq_bfqq_busy(bfqq) && + reason != BFQ_BFQQ_BUDGET_TIMEOUT && + reason != BFQ_BFQQ_BUDGET_EXHAUSTED) + bfq_mark_bfqq_non_blocking_wait_rq(bfqq); +@@ -3504,14 +3538,29 @@ static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd) + !bfq_bfqq_must_idle(bfqq)) + goto expire; + ++check_queue: ++ /* ++ * This loop is rarely executed more than once. Even when it ++ * happens, it is much more convenient to re-execute this loop ++ * than to return NULL and trigger a new dispatch to get a ++ * request served. ++ */ + next_rq = bfqq->next_rq; + /* + * If bfqq has requests queued and it has enough budget left to + * serve them, keep the queue, otherwise expire it. + */ + if (next_rq) { ++ BUG_ON(RB_EMPTY_ROOT(&bfqq->sort_list)); ++ + if (bfq_serv_to_charge(next_rq, bfqq) > + bfq_bfqq_budget_left(bfqq)) { ++ /* ++ * Expire the queue for budget exhaustion, ++ * which makes sure that the next budget is ++ * enough to serve the next request, even if ++ * it comes from the fifo expired path. ++ */ + reason = BFQ_BFQQ_BUDGET_EXHAUSTED; + goto expire; + } else { +@@ -3559,9 +3608,16 @@ static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd) + bfq_bfqq_expire(bfqd, bfqq, false, reason); + new_queue: + bfqq = bfq_set_in_service_queue(bfqd); +- bfq_log(bfqd, "select_queue: new queue %d returned", +- bfqq ? bfqq->pid : 0); ++ if (bfqq) { ++ bfq_log_bfqq(bfqd, bfqq, "select_queue: checking new queue"); ++ goto check_queue; ++ } + keep_queue: ++ if (bfqq) ++ bfq_log_bfqq(bfqd, bfqq, "select_queue: returned this queue"); ++ else ++ bfq_log(bfqd, "select_queue: no queue returned"); ++ + return bfqq; + } + +@@ -3627,45 +3683,17 @@ static int bfq_dispatch_request(struct bfq_data *bfqd, + struct bfq_queue *bfqq) + { + int dispatched = 0; +- struct request *rq; ++ struct request *rq = bfqq->next_rq; + unsigned long service_to_charge; + + BUG_ON(RB_EMPTY_ROOT(&bfqq->sort_list)); +- +- /* Follow expired path, else get first next available. */ +- rq = bfq_check_fifo(bfqq); +- if (!rq) +- rq = bfqq->next_rq; ++ BUG_ON(!rq); + service_to_charge = bfq_serv_to_charge(rq, bfqq); + +- if (service_to_charge > bfq_bfqq_budget_left(bfqq)) { +- /* +- * This may happen if the next rq is chosen in fifo order +- * instead of sector order. The budget is properly +- * dimensioned to be always sufficient to serve the next +- * request only if it is chosen in sector order. The reason +- * is that it would be quite inefficient and little useful +- * to always make sure that the budget is large enough to +- * serve even the possible next rq in fifo order. +- * In fact, requests are seldom served in fifo order. +- * +- * Expire the queue for budget exhaustion, and make sure +- * that the next act_budget is enough to serve the next +- * request, even if it comes from the fifo expired path. +- */ +- bfqq->next_rq = rq; +- /* +- * Since this dispatch is failed, make sure that +- * a new one will be performed +- */ +- if (!bfqd->rq_in_driver) +- bfq_schedule_dispatch(bfqd); +- BUG_ON(bfqq->entity.budget < bfqq->entity.service); +- goto expire; +- } ++ BUG_ON(service_to_charge > bfq_bfqq_budget_left(bfqq)); + + BUG_ON(bfqq->entity.budget < bfqq->entity.service); +- /* Finally, insert request into driver dispatch list. */ ++ + bfq_bfqq_served(bfqq, service_to_charge); + + BUG_ON(bfqq->entity.budget < bfqq->entity.service); +@@ -3805,7 +3833,8 @@ static int bfq_dispatch_requests(struct request_queue *q, int force) + * Task holds one reference to the queue, dropped when task exits. Each rq + * in-flight on this queue also holds a reference, dropped when rq is freed. + * +- * Queue lock must be held here. ++ * Queue lock must be held here. Recall not to use bfqq after calling ++ * this function on it. + */ + static void bfq_put_queue(struct bfq_queue *bfqq) + { +@@ -3874,7 +3903,7 @@ static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq) + + bfq_put_cooperator(bfqq); + +- bfq_put_queue(bfqq); ++ bfq_put_queue(bfqq); /* release process reference */ + } + + static void bfq_init_icq(struct io_cq *icq) +@@ -3973,6 +4002,7 @@ static void bfq_check_ioprio_change(struct bfq_io_cq *bic, struct bio *bio) + + bfqq = bic_to_bfqq(bic, false); + if (bfqq) { ++ /* release process reference on this queue */ + bfq_put_queue(bfqq); + bfqq = bfq_get_queue(bfqd, bio, BLK_RW_ASYNC, bic); + bic_set_bfqq(bic, bfqq, false); +@@ -4093,14 +4123,20 @@ static struct bfq_queue *bfq_get_queue(struct bfq_data *bfqd, + * prune it. + */ + if (async_bfqq) { +- bfqq->ref++; ++ bfqq->ref++; /* ++ * Extra group reference, w.r.t. sync ++ * queue. This extra reference is removed ++ * only if bfqq->bfqg disappears, to ++ * guarantee that this queue is not freed ++ * until its group goes away. ++ */ + bfq_log_bfqq(bfqd, bfqq, "get_queue, bfqq not in async: %p, %d", + bfqq, bfqq->ref); + *async_bfqq = bfqq; + } + + out: +- bfqq->ref++; ++ bfqq->ref++; /* get a process reference to this queue */ + bfq_log_bfqq(bfqd, bfqq, "get_queue, at end: %p, %d", bfqq, bfqq->ref); + rcu_read_unlock(); + return bfqq; +@@ -4274,10 +4310,14 @@ static void bfq_insert_request(struct request_queue *q, struct request *rq) + bfqq->allocated[rq_data_dir(rq)]--; + new_bfqq->ref++; + bfq_clear_bfqq_just_created(bfqq); +- bfq_put_queue(bfqq); + if (bic_to_bfqq(RQ_BIC(rq), 1) == bfqq) + bfq_merge_bfqqs(bfqd, RQ_BIC(rq), + bfqq, new_bfqq); ++ /* ++ * rq is about to be enqueued into new_bfqq, ++ * release rq reference on bfqq ++ */ ++ bfq_put_queue(bfqq); + rq->elv.priv[1] = new_bfqq; + bfqq = new_bfqq; + } +@@ -4697,9 +4737,8 @@ static void bfq_shutdown_timer_wq(struct bfq_data *bfqd) + cancel_work_sync(&bfqd->unplug_work); + } + +-#ifdef CONFIG_BFQ_GROUP_IOSCHED + static void __bfq_put_async_bfqq(struct bfq_data *bfqd, +- struct bfq_queue **bfqq_ptr) ++ struct bfq_queue **bfqq_ptr) + { + struct bfq_group *root_group = bfqd->root_group; + struct bfq_queue *bfqq = *bfqq_ptr; +@@ -4730,7 +4769,6 @@ static void bfq_put_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg) + + __bfq_put_async_bfqq(bfqd, &bfqg->async_idle_bfqq); + } +-#endif + + static void bfq_exit_queue(struct elevator_queue *e) + { +@@ -4755,6 +4793,7 @@ static void bfq_exit_queue(struct elevator_queue *e) + #ifdef CONFIG_BFQ_GROUP_IOSCHED + blkcg_deactivate_policy(q, &blkcg_policy_bfq); + #else ++ bfq_put_async_queues(bfqd, bfqd->root_group); + kfree(bfqd->root_group); + #endif + +@@ -5229,7 +5268,7 @@ static struct blkcg_policy blkcg_policy_bfq = { + static int __init bfq_init(void) + { + int ret; +- char msg[60] = "BFQ I/O-scheduler: v8r7"; ++ char msg[60] = "BFQ I/O-scheduler: v8r10"; + + #ifdef CONFIG_BFQ_GROUP_IOSCHED + ret = blkcg_policy_register(&blkcg_policy_bfq); +@@ -5255,7 +5294,7 @@ static int __init bfq_init(void) + * be run for a long time. + */ + T_slow[0] = msecs_to_jiffies(3500); /* actually 4 sec */ +- T_slow[1] = msecs_to_jiffies(1000); /* actually 1.5 sec */ ++ T_slow[1] = msecs_to_jiffies(6000); /* actually 6.5 sec */ + T_fast[0] = msecs_to_jiffies(7000); /* actually 8 sec */ + T_fast[1] = msecs_to_jiffies(2500); /* actually 3 sec */ + +diff --git a/block/bfq-sched.c b/block/bfq-sched.c +index 797bce7..70aac56 100644 +--- a/block/bfq-sched.c ++++ b/block/bfq-sched.c +@@ -154,7 +154,13 @@ static bool bfq_update_next_in_service(struct bfq_sched_data *sd, + #define for_each_entity(entity) \ + for (; entity ; entity = entity->parent) + +-#define for_each_entity_safe(entity, parent) \ ++/* ++ * For each iteration, compute parent in advance, so as to be safe if ++ * entity is deallocated during the iteration. Such a deallocation may ++ * happen as a consequence of a bfq_put_queue that frees the bfq_queue ++ * containing entity. ++ */ ++#define for_each_entity_safe(entity, parent) \ + for (; entity && ({ parent = entity->parent; 1; }); entity = parent) + + /* +@@ -691,27 +697,31 @@ static void bfq_idle_insert(struct bfq_service_tree *st, + } + + /** +- * bfq_forget_entity - remove an entity from the wfq trees. ++ * bfq_forget_entity - do not consider entity any longer for scheduling + * @st: the service tree. + * @entity: the entity being removed. ++ * @is_in_service: true if entity is currently the in-service entity. + * +- * Update the device status and forget everything about @entity, putting +- * the device reference to it, if it is a queue. Entities belonging to +- * groups are not refcounted. ++ * Forget everything about @entity. In addition, if entity represents ++ * a queue, and the latter is not in service, then release the service ++ * reference to the queue (the one taken through bfq_get_entity). In ++ * fact, in this case, there is really no more service reference to ++ * the queue, as the latter is also outside any service tree. If, ++ * instead, the queue is in service, then __bfq_bfqd_reset_in_service ++ * will take care of putting the reference when the queue finally ++ * stops being served. + */ + static void bfq_forget_entity(struct bfq_service_tree *st, +- struct bfq_entity *entity) ++ struct bfq_entity *entity, ++ bool is_in_service) + { + struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); +- struct bfq_sched_data *sd; +- + BUG_ON(!entity->on_st); + + entity->on_st = false; + st->wsum -= entity->weight; +- if (bfqq) { +- sd = entity->sched_data; +- bfq_log_bfqq(bfqq->bfqd, bfqq, "forget_entity: %p %d", ++ if (bfqq && !is_in_service) { ++ bfq_log_bfqq(bfqq->bfqd, bfqq, "forget_entity (before): %p %d", + bfqq, bfqq->ref); + bfq_put_queue(bfqq); + } +@@ -726,7 +736,8 @@ static void bfq_put_idle_entity(struct bfq_service_tree *st, + struct bfq_entity *entity) + { + bfq_idle_extract(st, entity); +- bfq_forget_entity(st, entity); ++ bfq_forget_entity(st, entity, ++ entity == entity->sched_data->in_service_entity); + } + + /** +@@ -1082,6 +1093,12 @@ static void __bfq_activate_entity(struct bfq_entity *entity, + */ + entity->start = min_vstart; + st->wsum += entity->weight; ++ /* ++ * entity is about to be inserted into a service tree, ++ * and then set in service: get a reference to make ++ * sure entity does not disappear until it is no ++ * longer in service or scheduled for service. ++ */ + bfq_get_entity(entity); + + BUG_ON(entity->on_st && bfqq); +@@ -1264,27 +1281,27 @@ static bool __bfq_deactivate_entity(struct bfq_entity *entity, + { + struct bfq_sched_data *sd = entity->sched_data; + struct bfq_service_tree *st = bfq_entity_service_tree(entity); +- bool was_in_service = entity == sd->in_service_entity; ++ bool is_in_service = entity == sd->in_service_entity; + + if (!entity->on_st) { /* entity never activated, or already inactive */ + BUG_ON(entity == entity->sched_data->in_service_entity); + return false; + } + +- BUG_ON(was_in_service && entity->tree && entity->tree != &st->active); ++ BUG_ON(is_in_service && entity->tree && entity->tree != &st->active); + +- if (was_in_service) ++ if (is_in_service) + bfq_calc_finish(entity, entity->service); + + if (entity->tree == &st->active) + bfq_active_extract(st, entity); +- else if (!was_in_service && entity->tree == &st->idle) ++ else if (!is_in_service && entity->tree == &st->idle) + bfq_idle_extract(st, entity); + else if (entity->tree) + BUG(); + + if (!ins_into_idle_tree || !bfq_gt(entity->finish, st->vtime)) +- bfq_forget_entity(st, entity); ++ bfq_forget_entity(st, entity, is_in_service); + else + bfq_idle_insert(st, entity); + +@@ -1301,7 +1318,7 @@ static void bfq_deactivate_entity(struct bfq_entity *entity, + bool expiration) + { + struct bfq_sched_data *sd; +- struct bfq_entity *parent; ++ struct bfq_entity *parent = NULL; + + for_each_entity_safe(entity, parent) { + sd = entity->sched_data; +@@ -1320,8 +1337,8 @@ static void bfq_deactivate_entity(struct bfq_entity *entity, + + if (!__bfq_deactivate_entity(entity, ins_into_idle_tree)) { + /* +- * Entity is not any tree any more, so, this +- * deactivation is a no-op, and there is ++ * entity is not in any tree any more, so ++ * this deactivation is a no-op, and there is + * nothing to change for upper-level entities + * (in case of expiration, this can never + * happen). +@@ -1821,14 +1838,16 @@ static struct bfq_queue *bfq_get_next_queue(struct bfq_data *bfqd) + + static void __bfq_bfqd_reset_in_service(struct bfq_data *bfqd) + { +- struct bfq_entity *entity = &bfqd->in_service_queue->entity; ++ struct bfq_queue *in_serv_bfqq = bfqd->in_service_queue; ++ struct bfq_entity *in_serv_entity = &in_serv_bfqq->entity; ++ struct bfq_entity *entity = in_serv_entity; + + if (bfqd->in_service_bic) { + put_io_context(bfqd->in_service_bic->icq.ioc); + bfqd->in_service_bic = NULL; + } + +- bfq_clear_bfqq_wait_request(bfqd->in_service_queue); ++ bfq_clear_bfqq_wait_request(in_serv_bfqq); + hrtimer_try_to_cancel(&bfqd->idle_slice_timer); + bfqd->in_service_queue = NULL; + +@@ -1840,6 +1859,14 @@ static void __bfq_bfqd_reset_in_service(struct bfq_data *bfqd) + */ + for_each_entity(entity) + entity->sched_data->in_service_entity = NULL; ++ ++ /* ++ * in_serv_entity is no longer in service, so, if it is in no ++ * service tree either, then release the service reference to ++ * the queue it represents (taken with bfq_get_entity). ++ */ ++ if (!in_serv_entity->on_st) ++ bfq_put_queue(in_serv_bfqq); + } + + static void bfq_deactivate_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq, +@@ -1904,8 +1931,6 @@ static void bfq_del_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq, + BUG_ON(bfqq->entity.budget < 0); + + bfq_deactivate_bfqq(bfqd, bfqq, true, expiration); +- +- BUG_ON(bfqq->entity.budget < 0); + } + + /* +diff --git a/block/bfq.h b/block/bfq.h +index a9da002..e3855af 100644 +--- a/block/bfq.h ++++ b/block/bfq.h +@@ -1,5 +1,5 @@ + /* +- * BFQ v8r7 for 4.9.0: data structures and common functions prototypes. ++ * BFQ v8r10 for 4.9.0: data structures and common functions prototypes. + * + * Based on ideas and code from CFQ: + * Copyright (C) 2003 Jens Axboe +@@ -9,7 +9,7 @@ + * + * Copyright (C) 2015 Paolo Valente + * +- * Copyright (C) 2016 Paolo Valente ++ * Copyright (C) 2017 Paolo Valente + */ + + #ifndef _BFQ_H diff --git a/kernel/kernel/files/patches/mageia/fs-jbd2-Fix-dbench4-performance-regression-for-nobarrier-mounts.patch b/kernel/kernel/files/patches/mageia/fs-jbd2-Fix-dbench4-performance-regression-for-nobarrier-mounts.patch new file mode 100644 index 00000000..6c29cbbf --- /dev/null +++ b/kernel/kernel/files/patches/mageia/fs-jbd2-Fix-dbench4-performance-regression-for-nobarrier-mounts.patch @@ -0,0 +1,39 @@ +From: Jan Kara +Subject: [PATCH] jbd2: Fix dbench4 performance regression for 'nobarrier' mounts +Date: Fri, 28 Apr 2017 11:59:34 +0200 + +Commit b685d3d65ac7 "block: treat REQ_FUA and REQ_PREFLUSH as +synchronous" removed REQ_SYNC flag from WRITE_FUA implementation. Since +JBD2 strips REQ_FUA and REQ_FLUSH flags from submitted IO when the +filesystem is mounted with nobarrier mount option, journal superblock +writes ended up being async writes after this patch and that caused +heavy performance regression for dbench4 benchmark with high number of +processes. In my test setup with HP RAID array with non-volatile write +cache and 32 GB ram, dbench4 runs with 8 processes regressed by ~25%. + +Fix the problem by making sure journal superblock writes are always +treated as synchronous since they generally block progress of the +journalling machinery and thus the whole filesystem. + +Fixes: b685d3d65ac791406e0dfd8779cc9b3707fea5a3 +CC: stable@vger.kernel.org +Signed-off-by: Jan Kara +--- + fs/jbd2/journal.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c +index 5adc2fb62b0f..e768126f6a72 100644 +--- a/fs/jbd2/journal.c ++++ b/fs/jbd2/journal.c +@@ -1348,7 +1348,7 @@ static int jbd2_write_superblock(journal_t *journal, int write_flags) + jbd2_superblock_csum_set(journal, sb); + get_bh(bh); + bh->b_end_io = end_buffer_write_sync; +- ret = submit_bh(REQ_OP_WRITE, write_flags, bh); ++ ret = submit_bh(REQ_OP_WRITE, write_flags | REQ_SYNC, bh); + wait_on_buffer(bh); + if (buffer_write_io_error(bh)) { + clear_buffer_write_io_error(bh); +-- +2.12.0 diff --git a/kernel/kernel/files/patches/mageia/net-libceph-force-gfp_noio-for-socket-allocations.patch b/kernel/kernel/files/patches/mageia/net-libceph-force-gfp_noio-for-socket-allocations.patch deleted file mode 100644 index 75ce33ff..00000000 --- a/kernel/kernel/files/patches/mageia/net-libceph-force-gfp_noio-for-socket-allocations.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 633ee407b9d15a75ac9740ba9d3338815e1fcb95 Mon Sep 17 00:00:00 2001 -From: Ilya Dryomov -Date: Tue, 21 Mar 2017 13:44:28 +0100 -Subject: libceph: force GFP_NOIO for socket allocations - -From: Ilya Dryomov - -commit 633ee407b9d15a75ac9740ba9d3338815e1fcb95 upstream. - -sock_alloc_inode() allocates socket+inode and socket_wq with -GFP_KERNEL, which is not allowed on the writeback path: - - Workqueue: ceph-msgr con_work [libceph] - ffff8810871cb018 0000000000000046 0000000000000000 ffff881085d40000 - 0000000000012b00 ffff881025cad428 ffff8810871cbfd8 0000000000012b00 - ffff880102fc1000 ffff881085d40000 ffff8810871cb038 ffff8810871cb148 - Call Trace: - [] schedule+0x29/0x70 - [] schedule_timeout+0x1bd/0x200 - [] ? ttwu_do_wakeup+0x2c/0x120 - [] ? ttwu_do_activate.constprop.135+0x66/0x70 - [] wait_for_completion+0xbf/0x180 - [] ? try_to_wake_up+0x390/0x390 - [] flush_work+0x165/0x250 - [] ? worker_detach_from_pool+0xd0/0xd0 - [] xlog_cil_force_lsn+0x81/0x200 [xfs] - [] ? __slab_free+0xee/0x234 - [] _xfs_log_force_lsn+0x4d/0x2c0 [xfs] - [] ? lookup_page_cgroup_used+0xe/0x30 - [] ? xfs_reclaim_inode+0xa3/0x330 [xfs] - [] xfs_log_force_lsn+0x3f/0xf0 [xfs] - [] ? xfs_reclaim_inode+0xa3/0x330 [xfs] - [] xfs_iunpin_wait+0xc6/0x1a0 [xfs] - [] ? wake_atomic_t_function+0x40/0x40 - [] xfs_reclaim_inode+0xa3/0x330 [xfs] - [] xfs_reclaim_inodes_ag+0x257/0x3d0 [xfs] - [] xfs_reclaim_inodes_nr+0x33/0x40 [xfs] - [] xfs_fs_free_cached_objects+0x15/0x20 [xfs] - [] super_cache_scan+0x178/0x180 - [] shrink_slab_node+0x14e/0x340 - [] ? mem_cgroup_iter+0x16b/0x450 - [] shrink_slab+0x100/0x140 - [] do_try_to_free_pages+0x335/0x490 - [] try_to_free_pages+0xb9/0x1f0 - [] ? __alloc_pages_direct_compact+0x69/0x1be - [] __alloc_pages_nodemask+0x69a/0xb40 - [] alloc_pages_current+0x9e/0x110 - [] new_slab+0x2c5/0x390 - [] __slab_alloc+0x33b/0x459 - [] ? sock_alloc_inode+0x2d/0xd0 - [] ? inet_sendmsg+0x71/0xc0 - [] ? sock_alloc_inode+0x2d/0xd0 - [] kmem_cache_alloc+0x1a2/0x1b0 - [] sock_alloc_inode+0x2d/0xd0 - [] alloc_inode+0x26/0xa0 - [] new_inode_pseudo+0x1a/0x70 - [] sock_alloc+0x1e/0x80 - [] __sock_create+0x95/0x220 - [] sock_create_kern+0x24/0x30 - [] con_work+0xef9/0x2050 [libceph] - [] ? rbd_img_request_submit+0x4c/0x60 [rbd] - [] process_one_work+0x159/0x4f0 - [] worker_thread+0x11b/0x530 - [] ? create_worker+0x1d0/0x1d0 - [] kthread+0xc9/0xe0 - [] ? flush_kthread_worker+0x90/0x90 - [] ret_from_fork+0x58/0x90 - [] ? flush_kthread_worker+0x90/0x90 - -Use memalloc_noio_{save,restore}() to temporarily force GFP_NOIO here. - -Link: http://tracker.ceph.com/issues/19309 -Reported-by: Sergey Jerusalimov -Signed-off-by: Ilya Dryomov -Reviewed-by: Jeff Layton -Signed-off-by: Greg Kroah-Hartman - ---- - net/ceph/messenger.c | 6 ++++++ - 1 file changed, 6 insertions(+) - ---- a/net/ceph/messenger.c -+++ b/net/ceph/messenger.c -@@ -7,6 +7,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -469,11 +470,16 @@ static int ceph_tcp_connect(struct ceph_ - { - struct sockaddr_storage *paddr = &con->peer_addr.in_addr; - struct socket *sock; -+ unsigned int noio_flag; - int ret; - - BUG_ON(con->sock); -+ -+ /* sock_create_kern() allocates with GFP_KERNEL */ -+ noio_flag = memalloc_noio_save(); - ret = sock_create_kern(read_pnet(&con->msgr->net), paddr->ss_family, - SOCK_STREAM, IPPROTO_TCP, &sock); -+ memalloc_noio_restore(noio_flag); - if (ret) - return ret; - sock->sk->sk_allocation = GFP_NOFS; diff --git a/kernel/kernel/files/patches/mageia/net-macsec-dynamically-allocate-space-for-sglist.patch b/kernel/kernel/files/patches/mageia/net-macsec-dynamically-allocate-space-for-sglist.patch new file mode 100644 index 00000000..abbb40d6 --- /dev/null +++ b/kernel/kernel/files/patches/mageia/net-macsec-dynamically-allocate-space-for-sglist.patch @@ -0,0 +1,117 @@ +From 5294b83086cc1c35b4efeca03644cf9d12282e5b Mon Sep 17 00:00:00 2001 +From: "Jason A. Donenfeld" +Date: Tue, 25 Apr 2017 19:08:18 +0200 +Subject: [PATCH] macsec: dynamically allocate space for sglist + +We call skb_cow_data, which is good anyway to ensure we can actually +modify the skb as such (another error from prior). Now that we have the +number of fragments required, we can safely allocate exactly that amount +of memory. + +Fixes: c09440f7dcb3 ("macsec: introduce IEEE 802.1AE driver") +Signed-off-by: Jason A. Donenfeld +Acked-by: Sabrina Dubroca +Signed-off-by: David S. Miller +--- + drivers/net/macsec.c | 29 ++++++++++++++++++++++------- + 1 file changed, 22 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c +index dbab05a..49ce4e9 100644 +--- a/drivers/net/macsec.c ++++ b/drivers/net/macsec.c +@@ -617,7 +617,8 @@ static void macsec_encrypt_done(struct crypto_async_request *base, int err) + + static struct aead_request *macsec_alloc_req(struct crypto_aead *tfm, + unsigned char **iv, +- struct scatterlist **sg) ++ struct scatterlist **sg, ++ int num_frags) + { + size_t size, iv_offset, sg_offset; + struct aead_request *req; +@@ -629,7 +630,7 @@ static struct aead_request *macsec_alloc_req(struct crypto_aead *tfm, + + size = ALIGN(size, __alignof__(struct scatterlist)); + sg_offset = size; +- size += sizeof(struct scatterlist) * (MAX_SKB_FRAGS + 1); ++ size += sizeof(struct scatterlist) * num_frags; + + tmp = kmalloc(size, GFP_ATOMIC); + if (!tmp) +@@ -649,6 +650,7 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb, + { + int ret; + struct scatterlist *sg; ++ struct sk_buff *trailer; + unsigned char *iv; + struct ethhdr *eth; + struct macsec_eth_header *hh; +@@ -723,7 +725,14 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb, + return ERR_PTR(-EINVAL); + } + +- req = macsec_alloc_req(tx_sa->key.tfm, &iv, &sg); ++ ret = skb_cow_data(skb, 0, &trailer); ++ if (unlikely(ret < 0)) { ++ macsec_txsa_put(tx_sa); ++ kfree_skb(skb); ++ return ERR_PTR(ret); ++ } ++ ++ req = macsec_alloc_req(tx_sa->key.tfm, &iv, &sg, ret); + if (!req) { + macsec_txsa_put(tx_sa); + kfree_skb(skb); +@@ -732,7 +741,7 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb, + + macsec_fill_iv(iv, secy->sci, pn); + +- sg_init_table(sg, MAX_SKB_FRAGS + 1); ++ sg_init_table(sg, ret); + skb_to_sgvec(skb, sg, 0, skb->len); + + if (tx_sc->encrypt) { +@@ -917,6 +926,7 @@ static struct sk_buff *macsec_decrypt(struct sk_buff *skb, + { + int ret; + struct scatterlist *sg; ++ struct sk_buff *trailer; + unsigned char *iv; + struct aead_request *req; + struct macsec_eth_header *hdr; +@@ -927,7 +937,12 @@ static struct sk_buff *macsec_decrypt(struct sk_buff *skb, + if (!skb) + return ERR_PTR(-ENOMEM); + +- req = macsec_alloc_req(rx_sa->key.tfm, &iv, &sg); ++ ret = skb_cow_data(skb, 0, &trailer); ++ if (unlikely(ret < 0)) { ++ kfree_skb(skb); ++ return ERR_PTR(ret); ++ } ++ req = macsec_alloc_req(rx_sa->key.tfm, &iv, &sg, ret); + if (!req) { + kfree_skb(skb); + return ERR_PTR(-ENOMEM); +@@ -936,7 +951,7 @@ static struct sk_buff *macsec_decrypt(struct sk_buff *skb, + hdr = (struct macsec_eth_header *)skb->data; + macsec_fill_iv(iv, sci, ntohl(hdr->packet_number)); + +- sg_init_table(sg, MAX_SKB_FRAGS + 1); ++ sg_init_table(sg, ret); + skb_to_sgvec(skb, sg, 0, skb->len); + + if (hdr->tci_an & MACSEC_TCI_E) { +@@ -2716,7 +2731,7 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb, + } + + #define MACSEC_FEATURES \ +- (NETIF_F_SG | NETIF_F_HIGHDMA) ++ (NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST) + static struct lock_class_key macsec_netdev_addr_lock_key; + + static int macsec_dev_init(struct net_device *dev) +-- +2.10.2 + diff --git a/kernel/kernel/files/patches/mageia/series b/kernel/kernel/files/patches/mageia/series index 1e3c6689..a5ce22a7 100644 --- a/kernel/kernel/files/patches/mageia/series +++ b/kernel/kernel/files/patches/mageia/series @@ -130,7 +130,8 @@ block-Make-CFQ-default-to-IOPS-mode-on-SSDs.patch block-cgroups-kconfig-build-bits-for-BFQ-v7r11-4.5.0.patch block-introduce-the-BFQ-v7r11-I-O-sched-for-4.5.0.patch block-bfq-add-Early-Queue-Merge-EQM-to-BFQ-v7r11-for.patch -block-Turn-into-BFQ-v8r6-for-4.9.0.patch +block-Turn-into-BFQ-v8r7-for-4.9.0.patch +block-update-bfq-from-v8r7-to-v8r10.patch # new macbooks block-nvme-detect-NVMe-controller-in-recent-MacBooks.patch @@ -159,6 +160,9 @@ fs-aufs-4.9-modular.patch # needed for mdadm: imsm: enable bad block support for imsm metadata fs-seq_file-reset-iterator-to-first-record-for-zero-off.patch +# performance regression fix +fs-jbd2-Fix-dbench4-performance-regression-for-nobarrier-mounts.patch + ### ### FireWire ### @@ -266,12 +270,12 @@ net-wireless-rtlwifi-Fix-kernel-oops-introduced-with-commit-e4965.patch # update rtl8xxxu for mga#20508 net-wireless-realtek-rtl8xxxu-linux-4.11-rc.patch -# ceph -net-libceph-force-gfp_noio-for-socket-allocations.patch - # WireGuard support net-wireguard.patch +# CVE-2017-7477 +net-macsec-dynamically-allocate-space-for-sglist.patch + ### ### Platform drivers ### @@ -301,6 +305,12 @@ include-kbuild-export-pci_ids.patch sound-ALSA-hda-realtek-Add-new-codec-ID-ALC299.patch sound-ALSA-hda-realtek-New-codec-support-of-ALC1220.patch +# add support for Gigabyte GA-AX370 Gaming 5 with dual codecs (TTL: 4.12) +sound-ALSA-hda-A-new-flag-to-enforce-prefix-to-each-pin.patch +sound-ALSA-hda-Allow-to-enable-disable-vmaster-build-expli.patch +sound-ALSA-hda-Support-Gigabyte-Gaming-board-with-dual-Rea.patch +sound-ALSA-hda-Use-a-helper-function-for-renaming-kctl-nam.patch + ### ### Staging ### diff --git a/kernel/kernel/files/patches/mageia/sound-ALSA-hda-A-new-flag-to-enforce-prefix-to-each-pin.patch b/kernel/kernel/files/patches/mageia/sound-ALSA-hda-A-new-flag-to-enforce-prefix-to-each-pin.patch new file mode 100644 index 00000000..1899b308 --- /dev/null +++ b/kernel/kernel/files/patches/mageia/sound-ALSA-hda-A-new-flag-to-enforce-prefix-to-each-pin.patch @@ -0,0 +1,68 @@ +From 9f3dadb156692e15933a4a97ef659f65151be4a1 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Mon, 10 Apr 2017 17:12:33 +0200 +Subject: [PATCH 1/4] ALSA: hda - A new flag to enforce prefix to each pin + +This is a preliminary patch for a smooth multi-codec support, and it +introduces a new flag, force_pin_prefix, to struct hda_codec. +This flag is used to force to add the pin location prefix to each +input pin. For example, when there is only one microphone pin, +usually the auto-parser assigns the string "Mic". With this flag on, +it'll be like "Front Mic". Also, the creation of "Master" or "PCM" +playback volume for a single pin is suppressed, too. + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=195305 +Signed-off-by: Takashi Iwai +--- + sound/pci/hda/hda_auto_parser.c | 1 + + sound/pci/hda/hda_codec.h | 1 + + sound/pci/hda/hda_generic.c | 2 ++ + 3 files changed, 4 insertions(+) + +diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c +index a03cf68..d3ea731 100644 +--- a/sound/pci/hda/hda_auto_parser.c ++++ b/sound/pci/hda/hda_auto_parser.c +@@ -580,6 +580,7 @@ const char *hda_get_autocfg_input_label(struct hda_codec *codec, + has_multiple_pins = 1; + if (has_multiple_pins && type == AUTO_PIN_MIC) + has_multiple_pins &= check_mic_location_need(codec, cfg, input); ++ has_multiple_pins |= codec->force_pin_prefix; + return hda_get_input_pin_label(codec, &cfg->inputs[input], + cfg->inputs[input].pin, + has_multiple_pins); +diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h +index f17f252..d6fb2d5 100644 +--- a/sound/pci/hda/hda_codec.h ++++ b/sound/pci/hda/hda_codec.h +@@ -256,6 +256,7 @@ struct hda_codec { + unsigned int dump_coef:1; /* dump processing coefs in codec proc file */ + unsigned int power_save_node:1; /* advanced PM for each widget */ + unsigned int auto_runtime_pm:1; /* enable automatic codec runtime pm */ ++ unsigned int force_pin_prefix:1; /* Add location prefix */ + #ifdef CONFIG_PM + unsigned long power_on_acct; + unsigned long power_off_acct; +diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c +index e7c8f4f..4438328 100644 +--- a/sound/pci/hda/hda_generic.c ++++ b/sound/pci/hda/hda_generic.c +@@ -1125,6 +1125,7 @@ static const char *get_line_out_pfx(struct hda_codec *codec, int ch, + + *index = 0; + if (cfg->line_outs == 1 && !spec->multi_ios && ++ !codec->force_pin_prefix && + !cfg->hp_outs && !cfg->speaker_outs) + return spec->vmaster_mute.hook ? "PCM" : "Master"; + +@@ -1132,6 +1133,7 @@ static const char *get_line_out_pfx(struct hda_codec *codec, int ch, + * use it master (or "PCM" if a vmaster hook is present) + */ + if (spec->multiout.num_dacs == 1 && !spec->mixer_nid && ++ !codec->force_pin_prefix && + !spec->multiout.hp_out_nid[0] && !spec->multiout.extra_out_nid[0]) + return spec->vmaster_mute.hook ? "PCM" : "Master"; + +-- +2.10.2 + diff --git a/kernel/kernel/files/patches/mageia/sound-ALSA-hda-Allow-to-enable-disable-vmaster-build-expli.patch b/kernel/kernel/files/patches/mageia/sound-ALSA-hda-Allow-to-enable-disable-vmaster-build-expli.patch new file mode 100644 index 00000000..57b07e2f --- /dev/null +++ b/kernel/kernel/files/patches/mageia/sound-ALSA-hda-Allow-to-enable-disable-vmaster-build-expli.patch @@ -0,0 +1,78 @@ +From 7480316c265c9fcdbf73b1b8dec061b893b7e987 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Mon, 10 Apr 2017 17:37:34 +0200 +Subject: [PATCH 2/4] ALSA: hda - Allow to enable/disable vmaster build + explicitly + +Another preliminary patch for the dual-codec support: since the +support of vmaster over multiple codecs is difficult, simply disable +it by a new flag to hda_codec struct. A new user hint is added as +well for consistency. + +Signed-off-by: Takashi Iwai +--- + Documentation/sound/hd-audio/notes.rst | 2 ++ + sound/pci/hda/hda_generic.c | 7 +++++-- + sound/pci/hda/hda_generic.h | 1 + + 3 files changed, 8 insertions(+), 2 deletions(-) + +#diff --git a/Documentation/sound/hd-audio/notes.rst b/Documentation/sound/hd-audio/notes.rst +#index 9eeb9b4..f59c3cd 100644 +#--- a/Documentation/sound/hd-audio/notes.rst +#+++ b/Documentation/sound/hd-audio/notes.rst +#@@ -494,6 +494,8 @@ add_hp_mic (bool) +# hp_mic_detect (bool) +# enable/disable the hp/mic shared input for a single built-in mic +# case; default true +#+vmaster (bool) +#+ enable/disable the virtual Master control; default true +# mixer_nid (int) +# specifies the widget NID of the analog-loopback mixer +# +diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c +index 4438328..2842c82 100644 +--- a/sound/pci/hda/hda_generic.c ++++ b/sound/pci/hda/hda_generic.c +@@ -196,6 +196,9 @@ static void parse_user_hints(struct hda_codec *codec) + val = snd_hda_get_bool_hint(codec, "hp_mic_detect"); + if (val >= 0) + spec->suppress_hp_mic_detect = !val; ++ val = snd_hda_get_bool_hint(codec, "vmaster"); ++ if (val >= 0) ++ spec->suppress_vmaster = !val; + + if (!snd_hda_get_int_hint(codec, "mixer_nid", &val)) + spec->mixer_nid = val; +@@ -5033,7 +5036,7 @@ int snd_hda_gen_build_controls(struct hda_codec *codec) + } + + /* if we have no master control, let's create it */ +- if (!spec->no_analog && ++ if (!spec->no_analog && !spec->suppress_vmaster && + !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { + err = snd_hda_add_vmaster(codec, "Master Playback Volume", + spec->vmaster_tlv, slave_pfxs, +@@ -5041,7 +5044,7 @@ int snd_hda_gen_build_controls(struct hda_codec *codec) + if (err < 0) + return err; + } +- if (!spec->no_analog && ++ if (!spec->no_analog && !spec->suppress_vmaster && + !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { + err = __snd_hda_add_vmaster(codec, "Master Playback Switch", + NULL, slave_pfxs, +diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h +index f66fc7e..6177231 100644 +--- a/sound/pci/hda/hda_generic.h ++++ b/sound/pci/hda/hda_generic.h +@@ -229,6 +229,7 @@ struct hda_gen_spec { + unsigned int add_jack_modes:1; /* add i/o jack mode enum ctls */ + unsigned int power_down_unused:1; /* power down unused widgets */ + unsigned int dac_min_mute:1; /* minimal = mute for DACs */ ++ unsigned int suppress_vmaster:1; /* don't create vmaster kctls */ + + /* other internal flags */ + unsigned int no_analog:1; /* digital I/O only */ +-- +2.10.2 + diff --git a/kernel/kernel/files/patches/mageia/sound-ALSA-hda-Support-Gigabyte-Gaming-board-with-dual-Rea.patch b/kernel/kernel/files/patches/mageia/sound-ALSA-hda-Support-Gigabyte-Gaming-board-with-dual-Rea.patch new file mode 100644 index 00000000..0f93df15 --- /dev/null +++ b/kernel/kernel/files/patches/mageia/sound-ALSA-hda-Support-Gigabyte-Gaming-board-with-dual-Rea.patch @@ -0,0 +1,122 @@ +From 7beb3a6e9335d13872f24566b451f8371edd238f Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Mon, 10 Apr 2017 18:05:52 +0200 +Subject: [PATCH 3/4] ALSA: hda - Support Gigabyte Gaming board with dual + Realtek codecs + +This patch adds some workarounds to make Gigabyte GA-AX370 Gaming 5 +board working without the conflicts of kctls, etc. In general, the +dual codec configs result in the conflicts of the following stuff: +- Master controls +- Capture controls +- Analog loopback controls +In addition, the auto-mute and the auto-mic can't work well among +multiple codecs. + +The current "solution" is to disable all these features, and use UCM +for a better PulseAudio management. For a dedicated UCM profile, the +patch overrides the card longname so that the system an get a unique +profile path. + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=195305 +Signed-off-by: Takashi Iwai +--- + sound/pci/hda/patch_realtek.c | 61 +++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 61 insertions(+) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 9371f1a..e81cf83 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -1800,6 +1800,7 @@ enum { + ALC882_FIXUP_NO_PRIMARY_HP, + ALC887_FIXUP_ASUS_BASS, + ALC887_FIXUP_BASS_CHMAP, ++ ALC1220_FIXUP_GB_DUAL_CODECS, + }; + + static void alc889_fixup_coef(struct hda_codec *codec, +@@ -1962,6 +1963,61 @@ static void alc882_fixup_no_primary_hp(struct hda_codec *codec, + static void alc_fixup_bass_chmap(struct hda_codec *codec, + const struct hda_fixup *fix, int action); + ++/* For dual-codec configuration, we need to disable some features to avoid ++ * conflicts of kctls and PCM streams ++ */ ++static void alc_fixup_dual_codecs(struct hda_codec *codec, ++ const struct hda_fixup *fix, int action) ++{ ++ struct alc_spec *spec = codec->spec; ++ ++ if (action != HDA_FIXUP_ACT_PRE_PROBE) ++ return; ++ /* disable vmaster */ ++ spec->gen.suppress_vmaster = 1; ++ /* auto-mute and auto-mic switch don't work with multiple codecs */ ++ spec->gen.suppress_auto_mute = 1; ++ spec->gen.suppress_auto_mic = 1; ++ /* disable aamix as well */ ++ spec->gen.mixer_nid = 0; ++ /* add location prefix to avoid conflicts */ ++ codec->force_pin_prefix = 1; ++} ++ ++static void rename_ctl(struct hda_codec *codec, const char *oldname, ++ const char *newname) ++{ ++ struct snd_kcontrol *kctl; ++ ++ kctl = snd_hda_find_mixer_ctl(codec, oldname); ++ if (kctl) ++ strcpy(kctl->id.name, newname); ++} ++ ++static void alc1220_fixup_gb_dual_codecs(struct hda_codec *codec, ++ const struct hda_fixup *fix, ++ int action) ++{ ++ alc_fixup_dual_codecs(codec, fix, action); ++ switch (action) { ++ case HDA_FIXUP_ACT_PRE_PROBE: ++ /* override card longname to provide a unique UCM profile */ ++ strcpy(codec->card->longname, "HDAudio-Gigabyte-ALC1220DualCodecs"); ++ break; ++ case HDA_FIXUP_ACT_BUILD: ++ /* rename Capture controls depending on the codec */ ++ rename_ctl(codec, "Capture Volume", ++ codec->addr == 0 ? ++ "Rear-Panel Capture Volume" : ++ "Front-Panel Capture Volume"); ++ rename_ctl(codec, "Capture Switch", ++ codec->addr == 0 ? ++ "Rear-Panel Capture Switch" : ++ "Front-Panel Capture Switch"); ++ break; ++ } ++} ++ + static const struct hda_fixup alc882_fixups[] = { + [ALC882_FIXUP_ABIT_AW9D_MAX] = { + .type = HDA_FIXUP_PINS, +@@ -2198,6 +2254,10 @@ static const struct hda_fixup alc882_fixups[] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc_fixup_bass_chmap, + }, ++ [ALC1220_FIXUP_GB_DUAL_CODECS] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = alc1220_fixup_gb_dual_codecs, ++ }, + }; + + static const struct snd_pci_quirk alc882_fixup_tbl[] = { +@@ -2267,6 +2327,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { + SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD), + SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3), + SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE), ++ SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS), + SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX), + SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD), + SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD), +-- +2.10.2 + diff --git a/kernel/kernel/files/patches/mageia/sound-ALSA-hda-Use-a-helper-function-for-renaming-kctl-nam.patch b/kernel/kernel/files/patches/mageia/sound-ALSA-hda-Use-a-helper-function-for-renaming-kctl-nam.patch new file mode 100644 index 00000000..8094a331 --- /dev/null +++ b/kernel/kernel/files/patches/mageia/sound-ALSA-hda-Use-a-helper-function-for-renaming-kctl-nam.patch @@ -0,0 +1,42 @@ +From 56798e6b3a2264b58d50b93cfd66586ede77d661 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Tue, 11 Apr 2017 08:10:52 +0200 +Subject: [PATCH 4/4] ALSA: hda - Use a helper function for renaming kctl names + +Signed-off-by: Takashi Iwai +--- + sound/pci/hda/patch_realtek.c | 11 ++++------- + 1 file changed, 4 insertions(+), 7 deletions(-) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index e81cf83..57eeefd 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -4724,7 +4724,6 @@ static void alc282_fixup_asus_tx300(struct hda_codec *codec, + { 0x1b, 0x21114000 }, /* dock speaker pin */ + {} + }; +- struct snd_kcontrol *kctl; + + switch (action) { + case HDA_FIXUP_ACT_PRE_PROBE: +@@ -4739,12 +4738,10 @@ static void alc282_fixup_asus_tx300(struct hda_codec *codec, + /* this is a bit tricky; give more sane names for the main + * (tablet) speaker and the dock speaker, respectively + */ +- kctl = snd_hda_find_mixer_ctl(codec, "Speaker Playback Switch"); +- if (kctl) +- strcpy(kctl->id.name, "Dock Speaker Playback Switch"); +- kctl = snd_hda_find_mixer_ctl(codec, "Bass Speaker Playback Switch"); +- if (kctl) +- strcpy(kctl->id.name, "Speaker Playback Switch"); ++ rename_ctl(codec, "Speaker Playback Switch", ++ "Dock Speaker Playback Switch"); ++ rename_ctl(codec, "Bass Speaker Playback Switch", ++ "Speaker Playback Switch"); + break; + } + } +-- +2.10.2 + diff --git a/kernel/kernel/pspec.xml b/kernel/kernel/pspec.xml index f732b75a..116f7b1f 100644 --- a/kernel/kernel/pspec.xml +++ b/kernel/kernel/pspec.xml @@ -28,8 +28,8 @@ - patches/linux/patch-4.9.21.xz - + patches/linux/patch-4.9.27.xz + @@ -59,7 +59,8 @@ + patches/mageia/block-Turn-into-BFQ-v8r7-for-4.9.0.patch + patches/mageia/block-update-bfq-from-v8r7-to-v8r10.patch<2--> patches/mageia/block-nvme-detect-NVMe-controller-in-recent-MacBooks.patch patches/mageia/char-tpm-tpm_crb-implement-tpm-crb-idle-state.patch patches/mageia/char-tmp-tpm_crb-fix-Intel-PTT-hw-bug-during-idle-state.patch @@ -69,6 +70,7 @@ patches/fs-aufs-4.9-posix_acl.patch patches/mageia/fs-aufs-4.9-modular.patch patches/mageia/fs-seq_file-reset-iterator-to-first-record-for-zero-off.patch + patches/mageia/fs-jbd2-Fix-dbench4-performance-regression-for-nobarrier-mounts.patch patches/mageia/firewire-ieee1394-module-aliases.patch patches/mageia/char-agp-intel-new-Q57-id.patch @@ -112,14 +114,18 @@ patches/mageia/net-wireless-rtlwifi-Use-dev_kfree_skb_irq-instead-of-kfree_skb.patch patches/mageia/net-wireless-rtlwifi-Fix-kernel-oops-introduced-with-commit-e4965.patch patches/mageia/net-wireless-realtek-rtl8xxxu-linux-4.11-rc.patch - patches/mageia/net-wireguard.patch + patches/mageia/net-macsec-dynamically-allocate-space-for-sglist.patch patches/mageia/platform-x86-add-shuttle-wmi-driver.patch patches/mageia/platform-x86-shuttle-wmi-drop-devinit-exit.patch patches/mageia/platform-x86-shuttle-wmi-4.2-buildfix.patch patches/mageia/include-kbuild-export-pci_ids.patch patches/mageia/sound-ALSA-hda-realtek-Add-new-codec-ID-ALC299.patch patches/mageia/sound-ALSA-hda-realtek-New-codec-support-of-ALC1220.patch + patches/mageia/sound-ALSA-hda-A-new-flag-to-enforce-prefix-to-each-pin.patch + patches/mageia/sound-ALSA-hda-Allow-to-enable-disable-vmaster-build-expli.patch + patches/mageia/sound-ALSA-hda-Support-Gigabyte-Gaming-board-with-dual-Rea.patch + patches/mageia/sound-ALSA-hda-Use-a-helper-function-for-renaming-kctl-nam.patch patches/mageia/hid-usbhid-IBM-BladeCenterHS20-quirk.patch patches/mageia/usb-storage-unusual_devs-add-id.patch patches/mageia/usb-storage-unusual_devs-add-id-2.6.37-buildfix.patch @@ -208,8 +214,8 @@ - 2017-03-30 - 4.9.21 + 2017-05-09 + 4.9.27 Version Bump. security