introduce banirq option

Fixing bug http://code.google.com/p/irqbalance/issues/detail?id=25

It was pointed out that during the rewrite of irqbalance I inadvertently removed
the support for the IRQBALANCE_BANNED_IRQS environment variable. While going to
return it to the build, it occured to me that, given the availability of msi[x]
irqs, a single system can literally have thousands of interrupt sources, making
the environment variable a non-scalable solution.  Instead I'm adding a new
option, banirqs, which takes its place.  It lets you build a list of irqs that
you want irqbalance to leave alone.

Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
This commit is contained in:
Neil Horman 2012-02-17 14:27:11 -05:00
parent 5ed963e5cb
commit 82047c1a22
4 changed files with 52 additions and 6 deletions

View file

@ -52,6 +52,7 @@ static short class_codes[MAX_CLASS] = {
};
static GList *interrupts_db;
static GList *banned_irqs;
#define SYSDEV_DIR "/sys/bus/pci/devices"
@ -63,6 +64,30 @@ static gint compare_ints(gconstpointer a, gconstpointer b)
return ai->irq - bi->irq;
}
void add_banned_irq(int irq)
{
struct irq_info find, *new;
GList *entry;
find.irq = irq;
entry = g_list_find_custom(banned_irqs, &find, compare_ints);
if (entry)
return;
new = calloc(sizeof(struct irq_info), 1);
if (!new) {
if (debug_mode)
printf("No memory to ban irq %d\n", irq);
return;
}
new->irq = irq;
banned_irqs = g_list_append(banned_irqs, new);
return;
}
/*
* Inserts an irq_info struct into the intterupts_db list
* devpath points to the device directory in sysfs for the
@ -90,6 +115,13 @@ static struct irq_info *add_one_irq_to_db(const char *devpath, int irq)
return NULL;
}
entry = g_list_find_custom(banned_irqs, &find, compare_ints);
if (entry) {
if (debug_mode)
printf("SKIPPING BANNED IRQ %d\n", irq);
return NULL;
}
new = calloc(sizeof(struct irq_info), 1);
if (!new)
return NULL;

View file

@ -66,6 +66,13 @@ average cpu softirq workload, and no cpus are more than 1 standard deviation
above (and have more than 1 irq assigned to them), attempt to place 1 cpu in
powersave mode. In powersave mode, a cpu will not have any irqs balanced to it,
in an effort to prevent that cpu from waking up without need.
.TP
.B --banirq=<irqnum>
Add the specified irq list to the set of banned irqs. irqbalance will not affect
the affinity of any irqs on the banned list, allowing them to be specified
manually. This option is addative and can be specified multiple times
.SH "ENVIRONMENT VARIABLES"
.TP
.B IRQBALANCE_ONESHOT
@ -79,10 +86,6 @@ Same as --debug
.B IRQBALANCE_BANNED_CPUS
Provides a mask of cpus which irqbalance should ignore and never assign interrupts to
.TP
.B IRQBALANCE_BANNED_INTERRUPTS
A list of space delimited IRQ numbers that irqbalance should not touch
.SH "Homepage"
http://code.google.com/p/irqbalance

View file

@ -68,22 +68,24 @@ struct option lopts[] = {
{"foreground", 0, NULL, 'f'},
{"hintpolicy", 1, NULL, 'h'},
{"powerthresh", 1, NULL, 'p'},
{"banirq", 1 , NULL, 'i'},
{0, 0, 0, 0}
};
static void usage(void)
{
printf("irqbalance [--oneshot | -o] [--debug | -d] [--foreground | -f] [--hintpolicy= | -h [exact|subset|ignore]]\n");
printf(" [--powerthresh= | -p <off> | <n>]\n");
printf(" [--powerthresh= | -p <off> | <n>] [--banirq= | -i <n>]\n");
}
static void parse_command_line(int argc, char **argv)
{
int opt;
int longind;
unsigned long val;
while ((opt = getopt_long(argc, argv,
"odfh:p:",
"odfh:i:p:",
lopts, &longind)) != -1) {
switch(opt) {
@ -109,6 +111,14 @@ static void parse_command_line(int argc, char **argv)
exit(1);
}
break;
case 'i':
val = strtoull(optarg, NULL, 10);
if (val == ULONG_MAX) {
usage();
exit(1);
}
add_banned_irq((int)val);
break;
case 'p':
if (!strncmp(optarg, "off", strlen(optarg)))
power_thresh = ULONG_MAX;

View file

@ -103,6 +103,7 @@ extern int get_cpu_count(void);
*/
extern void rebuild_irq_db(void);
extern void free_irq_db(void);
extern void add_banned_irq(int irq);
extern void for_each_irq(GList *list, void (*cb)(struct irq_info *info, void *data), void *data);
extern struct irq_info *get_irq_info(int irq);
extern void migrate_irq(GList **from, GList **to, struct irq_info *info);