From 3c7fe6d3cca832951b63950e12e29d6428d70bdd Mon Sep 17 00:00:00 2001 From: nhorman Date: Tue, 10 Aug 2010 13:32:58 +0000 Subject: [PATCH] Fix affinity_hint code. Theres a problem with the affintiy_hint code. Specifically it fails to determine when an affinity_hint file is all f's (affinity_hint == all cpus). As such, irqbalance is currently allowing all cpus to handle all irqs, which is the antithesis of its function. It also makes use of cpus_full, which is poorly formed, as it assumes that the affinity_hint mask is always NR_CPUS in length, and each bit is set (even for those cpus not actually present in the system). This patch corrects both of those problems, by only checking all the present cpus in the system in the mask, and detecting when that mask is all f's. Signed-off-by: Neil Horman git-svn-id: https://irqbalance.googlecode.com/svn/trunk@30 46b42954-3823-0410-bd82-eb80b452c9b5 --- bitmap.c | 13 +++++++++++++ cputree.c | 3 +++ irqlist.c | 5 ++++- placement.c | 2 +- 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/bitmap.c b/bitmap.c index 6a1ceae..4842b9d 100644 --- a/bitmap.c +++ b/bitmap.c @@ -74,6 +74,19 @@ int __bitmap_full(const unsigned long *bitmap, int bits) return 1; } +int __bitmap_weight(const unsigned long *bitmap, int bits) +{ + int k, w = 0, lim = bits/BITS_PER_LONG; + + for (k = 0; k < lim; k++) + w += hweight_long(bitmap[k]); + + if (bits % BITS_PER_LONG) + w += hweight_long(bitmap[k] & BITMAP_LAST_WORD_MASK(bits)); + + return w; +} + int __bitmap_equal(const unsigned long *bitmap1, const unsigned long *bitmap2, int bits) { diff --git a/cputree.c b/cputree.c index 280bbbf..3b0c982 100644 --- a/cputree.c +++ b/cputree.c @@ -47,6 +47,7 @@ int core_count; /* Users want to be able to keep interrupts away from some cpus; store these in a cpumask_t */ cpumask_t banned_cpus; +cpumask_t cpu_possible_map; /* it's convenient to have the complement of banned_cpus available so that @@ -158,6 +159,8 @@ static void do_one_cpu(char *path) memset(cpu, 0, sizeof(struct cpu_core)); cpu->number = strtoul(&path[27], NULL, 10); + + cpu_set(cpu->number, cpu_possible_map); cpu_set(cpu->number, cpu->mask); diff --git a/irqlist.c b/irqlist.c index d91563e..6dcdd55 100644 --- a/irqlist.c +++ b/irqlist.c @@ -39,6 +39,7 @@ GList *interrupts; void get_affinity_hint(struct interrupt *irq, int number) { char buf[PATH_MAX]; + cpumask_t tempmask; char *line = NULL; size_t size = 0; FILE *file; @@ -51,7 +52,9 @@ void get_affinity_hint(struct interrupt *irq, int number) fclose(file); return; } - cpumask_parse_user(line, strlen(line), irq->node_mask); + cpumask_parse_user(line, strlen(line), tempmask); + if (!__cpus_full(&tempmask, num_possible_cpus())) + irq->node_mask = tempmask; fclose(file); free(line); } diff --git a/placement.c b/placement.c index aae0576..ff5809d 100644 --- a/placement.c +++ b/placement.c @@ -272,7 +272,7 @@ static void place_affinity_hint(GList *list) } if ((!cpus_empty(irq->node_mask)) && (!cpus_equal(irq->mask, irq->node_mask)) && - (!cpus_full(irq->node_mask))) { + (!__cpus_full(&irq->node_mask, num_possible_cpus()))) { irq->old_mask = irq->mask; irq->mask = irq->node_mask; }