irqbalance/backport-add-irq-hotplug-feature-for-irqbalance.patch
2021-04-09 14:58:29 +08:00

353 lines
9.0 KiB
Diff

From 0ba4a60a2a732150e5016389e32b2e81906a72c2 Mon Sep 17 00:00:00 2001
From: hejingxian 00273181 <hejingxian@huawei.com>
Date: Fri, 4 Dec 2020 10:52:57 +0800
Subject: [PATCH] add irq hotplug feature for irqbalance
Conflict:NA
Reference:https://github.com/Irqbalance/irqbalance/commit/0ba4a60a2a732150e5016389e32b2e81906a72c2
---
classify.c | 70 +++++++++++++++++++++++--------
irqbalance.c | 2 +-
irqbalance.h | 4 +-
procinterrupts.c | 104 ++++++++++++++++++++++++++++-------------------
4 files changed, 120 insertions(+), 60 deletions(-)
diff --git a/classify.c b/classify.c
index 9f588bc..0d556e9 100644
--- a/classify.c
+++ b/classify.c
@@ -619,7 +619,7 @@ static void add_new_irq(char *path, struct irq_info *hint, GList *proc_interrupt
/*
* Figures out which interrupt(s) relate to the device we"re looking at in dirname
*/
-static void build_one_dev_entry(const char *dirname, GList *tmp_irqs)
+static void build_one_dev_entry(const char *dirname, GList *tmp_irqs, int build_irq)
{
struct dirent *entry;
DIR *msidir;
@@ -642,10 +642,14 @@ static void build_one_dev_entry(const char *dirname, GList *tmp_irqs)
if (!entry)
break;
irqnum = strtol(entry->d_name, NULL, 10);
- if (irqnum) {
+ /* If build_irq is valid, only add irq when it's number equals to build_irq */
+ if (irqnum && ((build_irq < 0) || (irqnum == build_irq))) {
+ printf("add irq:%d %d for %s\n", irqnum, build_irq, path);
hint.irq = irqnum;
hint.type = IRQ_TYPE_MSIX;
add_new_irq(devpath, &hint, tmp_irqs);
+ if (build_irq >= 0)
+ break;
}
} while (entry != NULL);
closedir(msidir);
@@ -665,9 +669,12 @@ static void build_one_dev_entry(const char *dirname, GList *tmp_irqs)
#else
if (irqnum) {
#endif
- hint.irq = irqnum;
- hint.type = IRQ_TYPE_LEGACY;
- add_new_irq(devpath, &hint, tmp_irqs);
+ /* If build_irq is valid, only add irq when it's number equals to build_irq */
+ if ((build_irq < 0) || (irqnum == build_irq)) {
+ hint.irq = irqnum;
+ hint.type = IRQ_TYPE_LEGACY;
+ add_new_irq(devpath, &hint, tmp_irqs);
+ }
}
done:
@@ -712,31 +719,60 @@ static void free_tmp_irqs(gpointer data)
free(info);
}
-void rebuild_irq_db(void)
+static struct irq_info * build_dev_irqs(GList *tmp_irqs, int build_irq)
{
DIR *devdir;
struct dirent *entry;
- GList *tmp_irqs = NULL;
-
- free_irq_db();
-
- tmp_irqs = collect_full_irq_list();
+ struct irq_info *new_irq = NULL;
devdir = opendir(SYSPCI_DIR);
-
if (devdir) {
do {
entry = readdir(devdir);
-
if (!entry)
break;
-
- build_one_dev_entry(entry->d_name, tmp_irqs);
-
+ /* when hotplug irqs, we add one irq at one time */
+ build_one_dev_entry(entry->d_name, tmp_irqs, build_irq);
+ if (build_irq >= 0) {
+ new_irq = get_irq_info(build_irq);
+ if (new_irq)
+ break;
+ }
} while (entry != NULL);
-
closedir(devdir);
}
+ return new_irq;
+}
+
+int proc_irq_hotplug(char *savedline, int irq, struct irq_info **pinfo)
+{
+ struct irq_info tmp_info = {0};
+
+ /* firstly, init irq info by read device info */
+ *pinfo = build_dev_irqs(interrupts_db, irq);
+ if (*pinfo == NULL) {
+ /* secondly, init irq info by parse savedline */
+ init_irq_class_and_type(savedline, &tmp_info, irq);
+ add_new_irq(NULL, &tmp_info, interrupts_db);
+ *pinfo = get_irq_info(irq);
+ }
+ if (*pinfo == NULL) {
+ return -1;
+ }
+
+ force_rebalance_irq(*pinfo, NULL);
+ return 0;
+}
+
+void rebuild_irq_db(void)
+{
+ GList *tmp_irqs = NULL;
+
+ free_irq_db();
+
+ tmp_irqs = collect_full_irq_list();
+
+ build_dev_irqs(tmp_irqs, -1);
for_each_irq(tmp_irqs, add_missing_irq, interrupts_db);
diff --git a/irqbalance.c b/irqbalance.c
index eaa0ce1..9baa955 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -249,7 +249,7 @@ static void dump_object_tree(void)
for_each_object(numa_nodes, dump_numa_node_info, NULL);
}
-static void force_rebalance_irq(struct irq_info *info, void *data __attribute__((unused)))
+void force_rebalance_irq(struct irq_info *info, void *data __attribute__((unused)))
{
if (info->level == BALANCE_NONE)
return;
diff --git a/irqbalance.h b/irqbalance.h
index acf0ed5..d8e80a9 100644
--- a/irqbalance.h
+++ b/irqbalance.h
@@ -40,8 +40,11 @@ extern GList* collect_full_irq_list();
extern void parse_proc_stat(void);
extern void set_interrupt_count(int number, uint64_t count);
extern void set_msi_interrupt_numa(int number);
+extern void init_irq_class_and_type(char *savedline, struct irq_info *info, int irq);
+extern int proc_irq_hotplug(char *line, int irq, struct irq_info **pinfo);
extern GList *rebalance_irq_list;
+extern void force_rebalance_irq(struct irq_info *info, void *data __attribute__((unused)));
void update_migration_status(void);
void dump_workloads(void);
@@ -52,7 +55,6 @@ void dump_tree(void);
void activate_mappings(void);
void clear_cpu_tree(void);
void free_cpu_topo(gpointer data);
-
/*===================NEW BALANCER FUNCTIONS============================*/
/*
diff --git a/procinterrupts.c b/procinterrupts.c
index 858b66b..0671be0 100644
--- a/procinterrupts.c
+++ b/procinterrupts.c
@@ -145,16 +145,59 @@ static void guess_arm_irq_hints(char *name, struct irq_info *info)
}
#endif
+void init_irq_class_and_type(char *savedline, struct irq_info *info, int irq)
+{
+ char *irq_name = NULL;
+ char *irq_mod = NULL;
+ char *savedptr = NULL;
+ char *last_token = NULL;
+ char *p = NULL;
+ int is_xen_dyn = 0;
+#ifdef AARCH64
+ char *tmp = NULL;
+#endif
+
+ irq_name = strtok_r(savedline, " ", &savedptr);
+ if (strstr(irq_name, "xen-dyn") != NULL)
+ is_xen_dyn = 1;
+ last_token = strtok_r(NULL, " ", &savedptr);
+ while ((p = strtok_r(NULL, " ", &savedptr))) {
+ irq_name = last_token;
+ if (strstr(irq_name, "xen-dyn") != NULL)
+ is_xen_dyn = 1;
+ last_token = p;
+ }
+
+#ifdef AARCH64
+ irq_name = last_token;
+ tmp = strchr(irq_name, '\n');
+ if (tmp)
+ *tmp = 0;
+#endif
+ irq_mod = last_token;
+ info->irq = irq;
+
+ if (strstr(irq_name, "-event") != NULL && is_xen_dyn == 1) {
+ info->type = IRQ_TYPE_VIRT_EVENT;
+ info->class = IRQ_VIRT_EVENT;
+ } else {
+#ifdef AARCH64
+ guess_arm_irq_hints(irq_name, info);
+#else
+ info->type = IRQ_TYPE_LEGACY;
+ info->class = IRQ_OTHER;
+#endif
+ }
+ info->numa_node = get_numa_node(0);
+ info->name = strdup(irq_mod);
+}
+
GList* collect_full_irq_list()
{
GList *tmp_list = NULL;
FILE *file;
char *line = NULL;
size_t size = 0;
- char *irq_name, *irq_mod, *savedptr, *last_token, *p;
-#ifdef AARCH64
- char *tmp;
-#endif
file = fopen("/proc/interrupts", "r");
if (!file)
@@ -169,7 +212,6 @@ GList* collect_full_irq_list()
while (!feof(file)) {
int number;
- int is_xen_dyn = 0;
struct irq_info *info;
char *c;
char *savedline = NULL;
@@ -191,44 +233,12 @@ GList* collect_full_irq_list()
savedline = strdup(line);
if (!savedline)
break;
- irq_name = strtok_r(savedline, " ", &savedptr);
- if (strstr(irq_name, "xen-dyn") != NULL)
- is_xen_dyn = 1;
- last_token = strtok_r(NULL, " ", &savedptr);
- while ((p = strtok_r(NULL, " ", &savedptr))) {
- irq_name = last_token;
- if (strstr(irq_name, "xen-dyn") != NULL)
- is_xen_dyn = 1;
- last_token = p;
- }
-
-#ifdef AARCH64
- /* Of course the formatting for /proc/interrupts is different on different arches */
- irq_name = last_token;
- tmp = strchr(irq_name, '\n');
- if (tmp)
- *tmp = 0;
-#endif
- irq_mod = last_token;
-
*c = 0;
number = strtoul(line, NULL, 10);
info = calloc(1, sizeof(struct irq_info));
if (info) {
- info->irq = number;
- if (strstr(irq_name, "-event") != NULL && is_xen_dyn == 1) {
- info->type = IRQ_TYPE_VIRT_EVENT;
- info->class = IRQ_VIRT_EVENT;
- } else {
-#ifdef AARCH64
- guess_arm_irq_hints(irq_name, info);
-#else
- info->type = IRQ_TYPE_LEGACY;
- info->class = IRQ_OTHER;
-#endif
- }
- info->name = strdup(irq_mod);
+ init_irq_class_and_type(savedline, info, number);
tmp_list = g_list_append(tmp_list, info);
}
free(savedline);
@@ -238,11 +248,13 @@ GList* collect_full_irq_list()
return tmp_list;
}
+
void parse_proc_interrupts(void)
{
FILE *file;
char *line = NULL;
size_t size = 0;
+ int ret;
file = fopen("/proc/interrupts", "r");
if (!file)
@@ -261,6 +273,7 @@ void parse_proc_interrupts(void)
uint64_t count;
char *c, *c2;
struct irq_info *info;
+ char *savedline = NULL;
if (getline(&line, &size, file)<=0)
break;
@@ -280,15 +293,24 @@ void parse_proc_interrupts(void)
if (!c)
continue;
+ savedline = strdup(line);
+ if (!savedline)
+ break;
*c = 0;
c++;
number = strtoul(line, NULL, 10);
info = get_irq_info(number);
if (!info) {
- need_rescan = 1;
- break;
+ ret = proc_irq_hotplug(savedline, number, &info);
+ if (ret < 0) {
+ /* hotplug fail, need to rescan */
+ need_rescan = 1;
+ free(savedline);
+ break;
+ }
}
+ free(savedline);
count = 0;
cpunr = 0;
@@ -316,7 +338,7 @@ void parse_proc_interrupts(void)
break;
}
- info->last_irq_count = info->irq_count;
+ info->last_irq_count = info->irq_count;
info->irq_count = count;
/* is interrupt MSI based? */
--
2.23.0