File irqbalance-fix-find_best_object-for-the-same-d-load.patch of Package irqbalance.3491

From: Seiichi Ikarashi <s.ikarashi@jp.fujitsu.com>
Date: Fri, 3 Jul 2015 21:42:30 +0900
Subject: irqbalance: fix find_best_object() for the same d->load value
References: bsc#979303
Patch-Mainline: v1.1.0
Git-commit: 2c08906e4157c4bb44eb9c89c36fda8b303fced0
Git-repo: github.com/Irqbalance/irqbalance.git

Signed-off-by: Sebastian Parschauer <sparschauer@suse.de>

find_best_object() has a problem that three or more topo_obj, which have
the same ->load value, are involved. The comparison of the ->interrupts
length are always held with the one, which is registered in best->best.
Think about the following case:

  topo_obj A, the length of ->interrupts is 3.
           B,                               1.
           C,                               2.

  and find_best_object() eats them in the order of A, B, and C.

Here, find_best_object() wrongly chooses C, instead of B, because
the length of -> interrupts of B is not compared with that of C.

To fix this, remember only the best one and compare it with the next one.

Signed-off-by: Seiichi Ikarashi <s.ikarashi@jp.fujitsu.com>
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
---
 placement.c | 17 ++++++-----------
 1 file changed, 6 insertions(+), 11 deletions(-)

Index: irqbalance-1.0.7/placement.c
===================================================================
--- irqbalance-1.0.7.orig/placement.c
+++ irqbalance-1.0.7/placement.c
@@ -33,7 +33,6 @@ GList *rebalance_irq_list;
 
 struct obj_placement {
 		struct topo_obj *best;
-		struct topo_obj *least_irqs;
 		uint64_t best_cost;
 		struct irq_info *info;
 };
@@ -70,12 +69,10 @@ static void find_best_object(struct topo
 	if (newload < best->best_cost) {
 		best->best = d;
 		best->best_cost = newload;
-		best->least_irqs = NULL;
-	}
-
-	if (newload == best->best_cost) {
-		if (g_list_length(d->interrupts) < g_list_length(best->best->interrupts))
-			best->least_irqs = d;
+	} else if (newload == best->best_cost) {
+		if (g_list_length(d->interrupts) < g_list_length(best->best->interrupts)) {
+			best->best = d;
+		}
 	}
 }
 
@@ -112,12 +109,11 @@ static void find_best_object_for_irq(str
 
 	place.info = info;
 	place.best = NULL;
-	place.least_irqs = NULL;
 	place.best_cost = ULLONG_MAX;
 
 	for_each_object(d->children, find_best_object, &place);
 
-	asign = place.least_irqs ? place.least_irqs : place.best;
+	asign = place.best;
 
 	if (asign) {
 		migrate_irq(&d->interrupts, &asign->interrupts, info);
@@ -153,12 +149,11 @@ static void place_irq_in_node(struct irq
 
 	place.best_cost = ULLONG_MAX;
 	place.best = NULL;
-	place.least_irqs = NULL;
 	place.info = info;
 
 	for_each_object(numa_nodes, find_best_object, &place);
 
-	asign = place.least_irqs ? place.least_irqs : place.best;
+	asign = place.best;
 
 	if (asign) {
 		migrate_irq(&rebalance_irq_list, &asign->interrupts, info);
openSUSE Build Service is sponsored by