From fd24d8f30012a02f7d107174bb460eb641d8cbce Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Thu, 9 Aug 2012 14:18:23 -0400 Subject: [PATCH] Improve rescan ability for newly allocated interrupts When an interrupt is registered after irqbalance starts we just add it as a misc interrupt, even if its something that we want to balance. Instead, lets add the irq to a temp list, force a rescan, then make sure the newly discovered irqs get added properly on the rescan. Signed-off-by: Neil Horman --- classify.c | 33 ++++++++++++++++++++++++++++++--- irqbalance.h | 2 +- procinterrupts.c | 14 ++++---------- 3 files changed, 35 insertions(+), 14 deletions(-) diff --git a/classify.c b/classify.c index 3c76cea..1ae4ff9 100644 --- a/classify.c +++ b/classify.c @@ -52,6 +52,7 @@ static short class_codes[MAX_CLASS] = { }; static GList *interrupts_db; +static GList *new_irq_list; static GList *banned_irqs; #define SYSDEV_DIR "/sys/bus/pci/devices" @@ -326,6 +327,8 @@ void rebuild_irq_db(void) { DIR *devdir = opendir(SYSDEV_DIR); struct dirent *entry; + GList *gentry; + struct irq_info *ninfo, *iinfo; free_irq_db(); @@ -341,22 +344,46 @@ void rebuild_irq_db(void) build_one_dev_entry(entry->d_name); } while (entry != NULL); + closedir(devdir); + + if (!new_irq_list) + return; + gentry = g_list_first(new_irq_list); + while(gentry) { + ninfo = gentry->data; + iinfo = get_irq_info(ninfo->irq); + new_irq_list = g_list_remove(gentry, ninfo); + if (!iinfo) { + if (debug_mode) + printf("Adding untracked IRQ %d to database\n", ninfo->irq); + interrupts_db = g_list_append(interrupts_db, ninfo); + } else + free(ninfo); + + gentry = g_list_first(new_irq_list); + } + g_list_free(new_irq_list); + new_irq_list = NULL; + } -struct irq_info *add_misc_irq(int irq) +struct irq_info *add_new_irq(int irq) { - struct irq_info *new; + struct irq_info *new, *nnew; new = calloc(sizeof(struct irq_info), 1); - if (!new) + nnew = calloc(sizeof(struct irq_info), 1); + if (!new || !nnew) return NULL; new->irq = irq; new->type = IRQ_TYPE_LEGACY; new->class = IRQ_OTHER; new->numa_node = get_numa_node(-1); + memcpy(nnew, new, sizeof(struct irq_info)); interrupts_db = g_list_append(interrupts_db, new); + new_irq_list = g_list_append(new_irq_list, nnew); return new; } diff --git a/irqbalance.h b/irqbalance.h index 636a69e..e46f31f 100644 --- a/irqbalance.h +++ b/irqbalance.h @@ -108,7 +108,7 @@ 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); -extern struct irq_info *add_misc_irq(int irq); +extern struct irq_info *add_new_irq(int irq); #define irq_numa_node(irq) ((irq)->numa_node) diff --git a/procinterrupts.c b/procinterrupts.c index f1d6745..431fffa 100644 --- a/procinterrupts.c +++ b/procinterrupts.c @@ -84,16 +84,10 @@ void parse_proc_interrupts(void) number = strtoul(line, NULL, 10); info = get_irq_info(number); if (!info) { - /* - * If this is our 0th pass through this routine - * this is an irq that wasn't reported in sysfs - * and we should just add it. If we've been running - * a while then this irq just appeared and its time - * to rescan our irqs - */ - if (cycle_count) - need_rescan = 1; - info = add_misc_irq(number); + if (!cycle_count) + continue; + need_rescan = 1; + info = add_new_irq(number); } count = 0;