From 8ff57497b3ad0b60b99930ff7271d2e42869fc8f Mon Sep 17 00:00:00 2001 From: qinyu Date: Thu, 5 Jan 2023 17:52:39 +0800 Subject: [PATCH] irqbalance: add irq hotplug feature for irqbalance add irq hotplug feature for irqbalance Signed-off-by: qinyu --- ...rt-Add-log-for-hotplug-appropriately.patch | 43 +++ ...d-irq-hotplug-feature-for-irqbalance.patch | 352 ++++++++++++++++++ irqbalance.spec | 10 +- 3 files changed, 404 insertions(+), 1 deletion(-) create mode 100644 backport-Add-log-for-hotplug-appropriately.patch create mode 100644 backport-add-irq-hotplug-feature-for-irqbalance.patch diff --git a/backport-Add-log-for-hotplug-appropriately.patch b/backport-Add-log-for-hotplug-appropriately.patch new file mode 100644 index 0000000..d11c4eb --- /dev/null +++ b/backport-Add-log-for-hotplug-appropriately.patch @@ -0,0 +1,43 @@ +From 6ae114f8719a6a49cef73a32d820a77e900ddf08 Mon Sep 17 00:00:00 2001 +From: hejingxian 00273181 +Date: Thu, 17 Dec 2020 17:47:45 +0800 +Subject: [PATCH] Add log for hotplug appropriately + +Conflict:NA +Reference:https://github.com/Irqbalance/irqbalance/commit/6ae114f8719a6a49cef73a32d820a77e900ddf08 +--- + classify.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/classify.c b/classify.c +index 0d556e9..4b6ffa8 100644 +--- a/classify.c ++++ b/classify.c +@@ -644,12 +644,13 @@ static void build_one_dev_entry(const char *dirname, GList *tmp_irqs, int build_ + irqnum = strtol(entry->d_name, NULL, 10); + /* 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) ++ if (build_irq >= 0) { ++ log(TO_CONSOLE, LOG_INFO, "Hotplug dev irq: %d finished.\n", irqnum); + break; ++ } + } + } while (entry != NULL); + closedir(msidir); +@@ -674,6 +675,8 @@ static void build_one_dev_entry(const char *dirname, GList *tmp_irqs, int build_ + hint.irq = irqnum; + hint.type = IRQ_TYPE_LEGACY; + add_new_irq(devpath, &hint, tmp_irqs); ++ if (build_irq >= 0) ++ log(TO_CONSOLE, LOG_INFO, "Hotplug dev irq: %d finished.\n", irqnum); + } + } + +-- +2.23.0 + diff --git a/backport-add-irq-hotplug-feature-for-irqbalance.patch b/backport-add-irq-hotplug-feature-for-irqbalance.patch new file mode 100644 index 0000000..d96b536 --- /dev/null +++ b/backport-add-irq-hotplug-feature-for-irqbalance.patch @@ -0,0 +1,352 @@ +From 0ba4a60a2a732150e5016389e32b2e81906a72c2 Mon Sep 17 00:00:00 2001 +From: hejingxian 00273181 +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 + diff --git a/irqbalance.spec b/irqbalance.spec index 6a59971..940d2c0 100644 --- a/irqbalance.spec +++ b/irqbalance.spec @@ -1,7 +1,7 @@ Summary: A dynamic adaptive IRQ balancing daemon Name: irqbalance Version: 1.7.0 -Release: 6 +Release: 7 Epoch: 3 License: GPLv2 Source0: https://github.com/Irqbalance/irqbalance/archive/irqbalance-%{version}.tar.gz @@ -24,6 +24,8 @@ Requires: numactl-libs Patch6000: fix-unsigned-integer-subtraction-sign-overflow.patch Patch6001: backport-activate_mapping-activate-only-online-CPUs.patch Patch6002: backport-log-correctly-for-isolated-and-nohz_full-cpus.patch +Patch6003: backport-add-irq-hotplug-feature-for-irqbalance.patch +Patch6004: backport-Add-log-for-hotplug-appropriately.patch %description Irqbalance is a daemon to help balance the cpu load generated by @@ -81,6 +83,12 @@ fi /sbin/chkconfig --del %{name} >/dev/null 2>&1 || : %changelog +* Thu Jan 5 2023 qinyu - 3:1.7.0-7 +- Type:bugfix +- ID:NA +- SUG:restart +- DESC: add irq hotplug feature for irqbalance + * Thu Jan 5 2023 qinyu - 3:1.7.0-6 - Type:bugfix - ID:NA