backport patches

This commit is contained in:
SuperSix173 2021-04-09 14:45:12 +08:00
parent 9852dc1539
commit c65a85a98c
22 changed files with 2765 additions and 49 deletions

View File

@ -1,39 +0,0 @@
From 31c7d128fd6f083c7395b327f824a0c11d5e380f Mon Sep 17 00:00:00 2001
From: Yunfeng Ye <yeyunfeng@huawei.com>
Date: Sat, 21 Nov 2020 14:27:28 +0800
Subject: [PATCH] Add IRQBALANCE_BANNED_CPULIST to env file
Signed-off-by: Yunfeng Ye <yeyunfeng@huawei.com>
---
misc/irqbalance.env | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/misc/irqbalance.env b/misc/irqbalance.env
index 23570b2..237e4af 100644
--- a/misc/irqbalance.env
+++ b/misc/irqbalance.env
@@ -22,6 +22,21 @@
#IRQBALANCE_BANNED_CPUS=
#
+# IRQBALANCE_BANNED_CPULIST
+# The CPUs list which allows you to indicate which CPUs should
+# be skipped when reblancing IRQs. CPU numbers in CPUs list will
+# not have any IRQs assigned to them on rebalance.
+#
+# The format of CPUs list is:
+# <cpu number>,...,<cpu number>
+# or a range:
+# <cpu number>-<cpu number>
+# or a mixture:
+# <cpu number>,...,<cpu number>-<cpu number>
+#
+#IRQBALANCE_BANNED_CPULIST=
+
+#
# IRQBALANCE_ARGS
# Append any args here to the irqbalance daemon as documented in the man
# page.
--
1.8.3.1

View File

@ -0,0 +1,115 @@
From ef9bf64affbca0b030f9128d93f302296d166dac Mon Sep 17 00:00:00 2001
From: hejingxian 00273181 <hejingxian@huawei.com>
Date: Mon, 4 Jan 2021 12:34:02 +0800
Subject: [PATCH] Add hot pull method for irqbalance
Conflict:NA
Reference:https://github.com/Irqbalance/irqbalance/commit/ef9bf64affbca0b030f9128d93f302296d166dac
---
classify.c | 37 +++++++++++++++++++++++++++++++++++++
irqbalance.h | 1 +
procinterrupts.c | 4 +++-
types.h | 1 +
4 files changed, 42 insertions(+), 1 deletion(-)
diff --git a/classify.c b/classify.c
index 4b6ffa8..beb2919 100644
--- a/classify.c
+++ b/classify.c
@@ -852,3 +852,39 @@ void sort_irq_list(GList **list)
{
*list = g_list_sort(*list, sort_irqs);
}
+
+static void remove_no_existing_irq(struct irq_info *info, void *data __attribute__((unused)))
+{
+ GList *entry = NULL;
+
+ if (info->existing) {
+ /* clear existing flag for next detection */
+ info->existing = 0;
+ return;
+ }
+
+ entry = g_list_find_custom(interrupts_db, info, compare_ints);
+ if (entry)
+ interrupts_db = g_list_delete_link(interrupts_db, entry);
+
+ entry = g_list_find_custom(rebalance_irq_list, info, compare_ints);
+ if (entry)
+ rebalance_irq_list = g_list_delete_link(rebalance_irq_list, entry);
+
+ if(info->assigned_obj) {
+ entry = g_list_find_custom(info->assigned_obj->interrupts, info, compare_ints);
+ if (entry) {
+ info->assigned_obj->interrupts = g_list_delete_link(info->assigned_obj->interrupts, entry);
+ }
+ }
+ log(TO_CONSOLE, LOG_INFO, "IRQ %d is removed from interrupts_db.\n", info->irq);
+ free_irq(info, NULL);
+}
+
+void clear_no_existing_irqs(void)
+{
+ for_each_irq(NULL, remove_no_existing_irq, NULL);
+ if (banned_irqs) {
+ for_each_irq(banned_irqs, remove_no_existing_irq, NULL);
+ }
+}
+
diff --git a/irqbalance.h b/irqbalance.h
index d8e80a9..e7f6b94 100644
--- a/irqbalance.h
+++ b/irqbalance.h
@@ -42,6 +42,7 @@ 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 void clear_no_existing_irqs(void);
extern GList *rebalance_irq_list;
extern void force_rebalance_irq(struct irq_info *info, void *data __attribute__((unused)));
diff --git a/procinterrupts.c b/procinterrupts.c
index 0671be0..854282f 100644
--- a/procinterrupts.c
+++ b/procinterrupts.c
@@ -248,7 +248,6 @@ GList* collect_full_irq_list()
return tmp_list;
}
-
void parse_proc_interrupts(void)
{
FILE *file;
@@ -310,6 +309,7 @@ void parse_proc_interrupts(void)
break;
}
}
+ info->existing = 1;
free(savedline);
count = 0;
@@ -354,6 +354,8 @@ void parse_proc_interrupts(void)
*/
msi_found_in_sysfs = 1;
}
+ if (!need_rescan)
+ clear_no_existing_irqs();
fclose(file);
free(line);
}
diff --git a/types.h b/types.h
index a01d649..9693cf4 100644
--- a/types.h
+++ b/types.h
@@ -70,6 +70,7 @@ struct irq_info {
uint64_t last_irq_count;
uint64_t load;
int moved;
+ int existing;
struct topo_obj *assigned_obj;
char *name;
};
--
2.23.0

View File

@ -0,0 +1,43 @@
From 6ae114f8719a6a49cef73a32d820a77e900ddf08 Mon Sep 17 00:00:00 2001
From: hejingxian 00273181 <hejingxian@huawei.com>
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

View File

@ -0,0 +1,39 @@
From 31dea01f3a47aa6374560638486879e5129f9c94 Mon Sep 17 00:00:00 2001
From: Kairui Song <kasong@redhat.com>
Date: Thu, 28 Jan 2021 15:24:32 +0800
Subject: [PATCH] Also fetch node info for non-PCI devices
non-PCI devices could also be bind to a certain node. So if failed to
fetch the info from sysfs, try to get it from /proc/irq/<irq>/node.
Conflict:NA
Reference:https://github.com/Irqbalance/irqbalance/commit/31dea01f3a47aa6374560638486879e5129f9c94
---
classify.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/classify.c b/classify.c
index beb2919..105ecd6 100644
--- a/classify.c
+++ b/classify.c
@@ -361,9 +361,14 @@ static struct irq_info *add_one_irq_to_db(const char *devpath, struct irq_info *
get_numa_node:
numa_node = NUMA_NO_NODE;
- if (devpath != NULL && numa_avail) {
- sprintf(path, "%s/numa_node", devpath);
- process_one_line(path, get_int, &numa_node);
+ if (numa_avail) {
+ if (devpath != NULL) {
+ sprintf(path, "%s/numa_node", devpath);
+ process_one_line(path, get_int, &numa_node);
+ } else {
+ sprintf(path, "/proc/irq/%i/node", irq);
+ process_one_line(path, get_int, &numa_node);
+ }
}
if (pol->numa_node_set == 1)
--
2.23.0

View File

@ -0,0 +1,28 @@
From 518d81cdd8c54c820d16afb73658753b46032676 Mon Sep 17 00:00:00 2001
From: SuperSix173 <liuchao173@huawei.com>
Date: Tue, 6 Apr 2021 10:26:17 +0800
Subject: [PATCH] Hotplug may occur again during sleep, so wait until there is
no hotplug
Conflict:NA
Reference:https://github.com/Irqbalance/irqbalance/commit/518d81cdd8c54c820d16afb73658753b46032676
---
irqbalance.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/irqbalance.c b/irqbalance.c
index 458bb07..3f94847 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -285,7 +285,7 @@ gboolean scan(gpointer data __attribute__((unused)))
/* cope with cpu hotplug -- detected during /proc/interrupts parsing */
- if (need_rescan || need_rebuild) {
+ while (need_rescan || need_rebuild) {
int try_times = 0;
need_rescan = 0;
--
2.23.0

View File

@ -0,0 +1,56 @@
From c8757c6d870c4788da4980abaf21cb7369702ee9 Mon Sep 17 00:00:00 2001
From: Paride Legovini <paride@debian.org>
Date: Tue, 25 Aug 2020 23:18:27 +0200
Subject: [PATCH] activate_mapping: activate only online CPUs
When echoing a mask to /proc/irq/N/smp_affinity make sure to activate
only CPUs which are online. Activating a CPU which is not online results
in a EOVERFLOW.
Originally fixed in Debian by Helge Deller <deller@gmx.de>.
Conflict:NA
Reference:https://github.com/Irqbalance/irqbalance/commit/c8757c6d870c4788da4980abaf21cb7369702ee9
---
activate.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/activate.c b/activate.c
index 065f880..62cfd08 100644
--- a/activate.c
+++ b/activate.c
@@ -49,6 +49,7 @@ static void activate_mapping(struct irq_info *info, void *data __attribute__((un
char buf[PATH_MAX];
FILE *file;
int ret = 0;
+ cpumask_t applied_mask;
/*
* only activate mappings for irqs that have moved
@@ -59,10 +60,13 @@ static void activate_mapping(struct irq_info *info, void *data __attribute__((un
if (!info->assigned_obj)
return;
+ /* activate only online cpus, otherwise writing to procfs returns EOVERFLOW */
+ cpus_and(applied_mask, cpu_online_map, info->assigned_obj->mask);
+
/*
* Don't activate anything for which we have an invalid mask
*/
- if (check_affinity(info, info->assigned_obj->mask))
+ if (check_affinity(info, applied_mask))
return;
sprintf(buf, "/proc/irq/%i/smp_affinity", info->irq);
@@ -70,7 +74,7 @@ static void activate_mapping(struct irq_info *info, void *data __attribute__((un
if (!file)
return;
- cpumask_scnprintf(buf, PATH_MAX, info->assigned_obj->mask);
+ cpumask_scnprintf(buf, PATH_MAX, applied_mask);
ret = fprintf(file, "%s", buf);
if (ret < 0) {
log(TO_ALL, LOG_WARNING, "cannot change irq %i's affinity, add it to banned list", info->irq);
--
2.23.0

View File

@ -7,7 +7,8 @@ allows banning of cpus using the taskset cpulist syntax in addition to the
bitmap syntax supported via the existing environment variable bitmap syntax supported via the existing environment variable
IRQBALANCE_BANNED_CPUS IRQBALANCE_BANNED_CPUS
Signed-off-by: Yunfeng Ye <yeyunfeng@huawei.com> Conflict:NA
Reference:https://github.com/Irqbalance/irqbalance/commit/677b686e223c74e64f5b230bdb4079555a5a62a9
--- ---
cputree.c | 6 ++++++ cputree.c | 6 ++++++
irqbalance.1 | 6 ++++++ irqbalance.1 | 6 ++++++
@ -48,5 +49,5 @@ index 3005f6b..33ffd26 100644
.TP .TP
.B SIGHUP .B SIGHUP
-- --
1.8.3.1 2.23.0

View File

@ -0,0 +1,352 @@
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

View File

@ -0,0 +1,57 @@
From 6fe032945b69d8f382fa3e8de8e4fdce84063199 Mon Sep 17 00:00:00 2001
From: Yunfeng Ye <yeyunfeng@huawei.com>
Date: Fri, 20 Nov 2020 00:15:58 +0800
Subject: [PATCH] log correctly for isolated and nohz_full cpus
When the banded CPU is configured, and the "isolcpus" or "nohz_full"
is configured, the log for isolated and nohz CPUs are not correct.
So only log relevant infomation when isolcpus and nohz_full has been
handled, also put the cpus_clear() closer.
Conflict:NA
Reference:https://github.com/Irqbalance/irqbalance/commit/6fe032945b69d8f382fa3e8de8e4fdce84063199
---
cputree.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/cputree.c b/cputree.c
index 80a6d9d..eed20db 100644
--- a/cputree.c
+++ b/cputree.c
@@ -112,9 +112,6 @@ static void setup_banned_cpus(void)
cpumask_t isolated_cpus;
char *env = NULL;
- cpus_clear(isolated_cpus);
- cpus_clear(nohz_full);
-
/* A manually specified cpumask overrides auto-detection. */
if (cpu_ban_string != NULL && banned_cpumask_from_ui != NULL) {
cpulist_parse(banned_cpumask_from_ui,
@@ -133,6 +130,9 @@ static void setup_banned_cpus(void)
goto out;
}
+ cpus_clear(isolated_cpus);
+ cpus_clear(nohz_full);
+
path = "/sys/devices/system/cpu/isolated";
process_one_line(path, get_mask_from_cpulist, &isolated_cpus);
@@ -141,11 +141,11 @@ static void setup_banned_cpus(void)
cpus_or(banned_cpus, nohz_full, isolated_cpus);
-out:
cpumask_scnprintf(buffer, 4096, isolated_cpus);
log(TO_CONSOLE, LOG_INFO, "Isolated CPUs: %s\n", buffer);
cpumask_scnprintf(buffer, 4096, nohz_full);
log(TO_CONSOLE, LOG_INFO, "Adaptive-ticks CPUs: %s\n", buffer);
+out:
cpumask_scnprintf(buffer, 4096, banned_cpus);
log(TO_CONSOLE, LOG_INFO, "Banned CPUs: %s\n", buffer);
}
--
2.23.0

View File

@ -0,0 +1,93 @@
From c924f1df705a301a0ffc01fce4c7712756c8b1d2 Mon Sep 17 00:00:00 2001
From: Zengruan Ye <yezengruan@huawei.com>
Date: Sat, 13 Jul 2019 19:09:09 +0800
Subject: [PATCH] feature: aarch64: add the regular to get the correct irq
class on hisi board
First, get the full irq desc name, include that the name split by blank, just like
(hisi_sas_v2_hw sata). We use the irq type to mark the begin of the name.
Second, for hisi bord, we consider to match the IRQ_SCSI class (which the
irqbalance service concerned, and the eth device match follow the
open community rule) by keywords group hisi & sas or hisi & sata.
Signed-off-by: wanghaibin <wanghaibin.wang@huawei.com>
---
procinterrupts.c | 33 ++++++++++++++++++++++++++++++++-
1 file changed, 32 insertions(+), 1 deletion(-)
diff --git a/procinterrupts.c b/procinterrupts.c
index 854282f..32c5e53 100644
--- a/procinterrupts.c
+++ b/procinterrupts.c
@@ -108,6 +108,8 @@ static void guess_arm_irq_hints(char *name, struct irq_info *info)
/* Note: Last entry is a catchall */
static struct irq_match matches[] = {
{ "eth.*" ,{NULL} ,NULL, IRQ_TYPE_LEGACY, IRQ_GBETH },
+ { "hisi\\w*? *sas" ,{NULL} ,NULL, IRQ_TYPE_LEGACY, IRQ_SCSI},
+ { "hisi\\w*? *sata" ,{NULL} ,NULL, IRQ_TYPE_LEGACY, IRQ_SCSI},
{ "[A-Z0-9]{4}[0-9a-f]{4}", {NULL} ,check_platform_device, IRQ_TYPE_LEGACY, IRQ_OTHER},
{ "PNP[0-9a-f]{4}", {NULL} ,check_platform_device, IRQ_TYPE_LEGACY, IRQ_OTHER},
{ ".*", {NULL}, NULL, IRQ_TYPE_LEGACY, IRQ_OTHER},
@@ -155,6 +157,8 @@ void init_irq_class_and_type(char *savedline, struct irq_info *info, int irq)
int is_xen_dyn = 0;
#ifdef AARCH64
char *tmp = NULL;
+ int irq_fullname_valid = 1;
+ char irq_fullname[PATH_MAX] = {0};
#endif
irq_name = strtok_r(savedline, " ", &savedptr);
@@ -166,6 +170,16 @@ void init_irq_class_and_type(char *savedline, struct irq_info *info, int irq)
if (strstr(irq_name, "xen-dyn") != NULL)
is_xen_dyn = 1;
last_token = p;
+
+#ifdef AARCH64
+ /*
+ * /proc/interrupts format defined, after of interrupt type
+ * the reset string is mark the irq desc name.
+ */
+ if (strncmp(irq_name, "Level", strlen("Level")) == 0 ||
+ strncmp(irq_name, "Edge", strlen("Edge")) == 0)
+ break;
+#endif
}
#ifdef AARCH64
@@ -173,6 +187,17 @@ void init_irq_class_and_type(char *savedline, struct irq_info *info, int irq)
tmp = strchr(irq_name, '\n');
if (tmp)
*tmp = 0;
+
+ if (strlen(irq_name) + strlen(savedptr) + 1 < PATH_MAX) {
+ strcat(irq_fullname, irq_name);
+ strcat(irq_fullname, " ");
+ strcat(irq_fullname, savedptr);
+ tmp = strchr(irq_fullname, '\n');
+ if (tmp)
+ *tmp = 0;
+ } else {
+ irq_fullname_valid = 0;
+ }
#endif
irq_mod = last_token;
info->irq = irq;
@@ -182,7 +207,13 @@ void init_irq_class_and_type(char *savedline, struct irq_info *info, int irq)
info->class = IRQ_VIRT_EVENT;
} else {
#ifdef AARCH64
- guess_arm_irq_hints(irq_name, info);
+ if (irq_fullname_valid) {
+ irq_name = irq_fullname;
+ guess_arm_irq_hints(irq_name, info);
+ } else {
+ info->type = IRQ_TYPE_LEGACY;
+ info->class = IRQ_OTHER;
+ }
#else
info->type = IRQ_TYPE_LEGACY;
info->class = IRQ_OTHER;
--
2.23.0

View File

@ -0,0 +1,34 @@
From 7db6af3a25c9742febce616081a723e1c92889d1 Mon Sep 17 00:00:00 2001
From: BiaoXiang Ye <yebiaoxiang@huawei.com>
Date: Wed, 1 Jul 2020 12:05:33 +0800
Subject: [PATCH] feature: add ability to set hintpolicy during runtime
irqbalance adds default config --hintpolicy=subset, so we need provide the ability to set
hintpolicy back to ignore during runtime.
---
irqbalance.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/irqbalance.c b/irqbalance.c
index 859fd6a..ffbb191 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -538,6 +538,15 @@ gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attri
cpu_ban_string = NULL;
}
need_rescan = 1;
+ } else if (!(strncmp(buff + strlen("settings "), "hintpolicy ",
+ strlen("hintpolicy ")))) {
+ if (!(strncmp(buff + strlen("settings hintpolicy "), "ignore",
+ strlen("ignore")))) {
+ hint_enabled = 0;
+ } else if (!(strncmp(buff + strlen("settings hintpolicy "),
+ "subset", strlen("subset")))) {
+ hint_enabled = 1;
+ }
}
}
if (!strncmp(buff, "setup", strlen("setup"))) {
--
2.23.0

View File

@ -0,0 +1,89 @@
From 84a2df1c9962a87f55e1c0d3bd2118fd754a4b48 Mon Sep 17 00:00:00 2001
From: hejingxian <hejingxian@huawei.com>
Date: Fri, 3 Jan 2020 16:43:28 +0800
Subject: [PATCH] feature: add new irq migrate rule to avoid high cpu irq load
By the old irq migrate rule, the irqs cannot be moved if the adjustment_load will become smaller then
the min_load after moving irq. However, we can accept that the delta load become smaller after moving irq.
---
irqbalance.c | 8 +++++++-
irqbalance.h | 1 +
irqlist.c | 3 ++-
3 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/irqbalance.c b/irqbalance.c
index 9449e40..82ac3ea 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -72,6 +72,7 @@ GMainLoop *main_loop;
char *cpu_ban_string = NULL;
char *banned_cpumask_from_ui = NULL;
unsigned long migrate_ratio = 0;
+unsigned long load_limit = 0;
static void sleep_approx(int seconds)
{
@@ -106,6 +107,7 @@ struct option lopts[] = {
{"hintpolicy", 1, NULL, 'h'},
{"verifyhint", 1, NULL, 'v'},
{"notclearhint", 0, NULL, 'n'},
+ {"loadlimit", 1, NULL, 'g'},
{0, 0, 0, 0}
};
@@ -115,6 +117,7 @@ static void usage(void)
log(TO_CONSOLE, LOG_INFO, " [--powerthresh= | -p <off> | <n>] [--banirq= | -i <n>] [--banmod= | -m <module>] [--policyscript= | -l <script>]\n");
log(TO_CONSOLE, LOG_INFO, " [--pid= | -s <file>] [--deepestcache= | -c <n>] [--interval= | -t <n>] [--migrateval= | -e <n>]\n");
log(TO_CONSOLE, LOG_INFO, " [--rulesconfig= | -r <config>] [--hintpolicy | -h <subset>] [--verifyhint= | -v n] [--notclearhint | -n]\n");
+ log(TO_CONSOLE, LOG_INFO, " [--loadlimit= | -g <n>]\n");
}
static void version(void)
@@ -129,7 +132,7 @@ static void parse_command_line(int argc, char **argv)
unsigned long val;
while ((opt = getopt_long(argc, argv,
- "odfjVni:p:s:c:l:m:t:e:r:h:v:",
+ "odfjVni:p:s:c:l:m:t:e:r:h:v:g:",
lopts, &longind)) != -1) {
switch(opt) {
@@ -223,6 +226,9 @@ static void parse_command_line(int argc, char **argv)
case 'n':
clear_affinity_hint = 0;
break;
+ case 'g':
+ load_limit = strtoul(optarg, NULL, 10);
+ break;
}
}
}
diff --git a/irqbalance.h b/irqbalance.h
index 4a73b83..9ff8f37 100644
--- a/irqbalance.h
+++ b/irqbalance.h
@@ -83,6 +83,7 @@ extern cpumask_t banned_cpus;
extern cpumask_t unbanned_cpus;
extern long HZ;
extern unsigned long migrate_ratio;
+extern unsigned long load_limit;
/*
* Numa node access routines
diff --git a/irqlist.c b/irqlist.c
index 9ab321a..98a4224 100644
--- a/irqlist.c
+++ b/irqlist.c
@@ -97,7 +97,8 @@ static void move_candidate_irqs(struct irq_info *info, void *data)
}
/* If we can migrate an irq without swapping the imbalance do it. */
- if ((lb_info->min_load + info->load) - (lb_info->adjustment_load - info->load) < delta_load) {
+ if ((lb_info->min_load + info->load) - (lb_info->adjustment_load - info->load) < delta_load &&
+ lb_info->adjustment_load > load_limit) {
lb_info->adjustment_load -= info->load;
lb_info->min_load += info->load;
if (lb_info->min_load > lb_info->adjustment_load) {
--
2.23.0

View File

@ -0,0 +1,387 @@
From 0406d202af914881af1a6caf5247e7ac40564366 Mon Sep 17 00:00:00 2001
From: hejingxian <hejingxian@huawei.com>
Date: Tue, 17 Sep 2019 23:32:54 +0800
Subject: [PATCH] add new user irq policy config rule
When there is many irqs, the old user irq policy script will cost too much time.
Therefore, we introduce a new user irq policy config rule which avoid policy script running
for every irq.
---
Makefile.am | 2 +-
classify.c | 19 ++++--
irqbalance.c | 15 ++++-
irqbalance.h | 1 +
placement.c | 3 +-
rules_config.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++++
rules_config.h | 40 ++++++++++++
7 files changed, 244 insertions(+), 10 deletions(-)
create mode 100644 rules_config.c
create mode 100644 rules_config.h
diff --git a/Makefile.am b/Makefile.am
index 73988b3..3086d67 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -38,7 +38,7 @@ sbin_PROGRAMS += irqbalance-ui
endif
irqbalance_SOURCES = activate.c bitmap.c classify.c cputree.c irqbalance.c \
- irqlist.c numa.c placement.c procinterrupts.c
+ irqlist.c numa.c placement.c procinterrupts.c rules_config.c
irqbalance_LDADD = $(LIBCAP_NG_LIBS) $(GLIB2_LIBS)
if IRQBALANCEUI
irqbalance_ui_SOURCES = $(UI_DIR)/helpers.c $(UI_DIR)/irqbalance-ui.c \
diff --git a/classify.c b/classify.c
index 74103bf..254197e 100644
--- a/classify.c
+++ b/classify.c
@@ -625,12 +625,18 @@ static void add_new_irq(char *path, struct irq_info *hint, GList *proc_interrupt
return;
/* Set NULL devpath for the irq has no sysfs entries */
- get_irq_user_policy(path, irq, &pol);
+ if (user_policy_list == NULL) {
+ get_irq_user_policy(path, irq, &pol);
+ }
if ((pol.ban == 1) || check_for_irq_ban(irq, proc_interrupts)) { /*FIXME*/
__add_banned_irq(irq, &banned_irqs);
new = get_irq_info(irq);
- } else
+ } else {
new = add_one_irq_to_db(path, hint, &pol);
+ if ((new != NULL) && (user_policy_list != NULL)) {
+ set_usr_irq_policy(hint->name, new);
+ }
+ }
if (!new)
log(TO_CONSOLE, LOG_WARNING, "add_new_irq: Failed to add irq %d\n", irq);
@@ -781,14 +787,15 @@ 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 */
+ /* firstly, init irq info by parse savedline */
+ init_irq_class_and_type(savedline, &tmp_info, irq);
+ /* secondly, 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);
- }
+ } else
+ set_usr_irq_policy(tmp_info.name, *pinfo);
if (*pinfo == NULL) {
return -1;
}
diff --git a/irqbalance.c b/irqbalance.c
index 10e2b13..ecc3eca 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -99,6 +99,7 @@ struct option lopts[] = {
{"interval", 1 , NULL, 't'},
{"version", 0, NULL, 'V'},
{"migrateval", 1, NULL, 'e'},
+ {"rulesconfig", 1, NULL, 'r'},
{0, 0, 0, 0}
};
@@ -107,6 +108,7 @@ static void usage(void)
log(TO_CONSOLE, LOG_INFO, "irqbalance [--oneshot | -o] [--debug | -d] [--foreground | -f] [--journal | -j]\n");
log(TO_CONSOLE, LOG_INFO, " [--powerthresh= | -p <off> | <n>] [--banirq= | -i <n>] [--banmod= | -m <module>] [--policyscript= | -l <script>]\n");
log(TO_CONSOLE, LOG_INFO, " [--pid= | -s <file>] [--deepestcache= | -c <n>] [--interval= | -t <n>] [--migrateval= | -e <n>]\n");
+ log(TO_CONSOLE, LOG_INFO, " [--rulesconfig= | -r <config>]\n");
}
static void version(void)
@@ -121,7 +123,7 @@ static void parse_command_line(int argc, char **argv)
unsigned long val;
while ((opt = getopt_long(argc, argv,
- "odfjVi:p:s:c:l:m:t:e:",
+ "odfjVi:p:s:c:l:m:t:e:r:",
lopts, &longind)) != -1) {
switch(opt) {
@@ -193,6 +195,9 @@ static void parse_command_line(int argc, char **argv)
case 'e':
migrate_ratio = strtoul(optarg, NULL, 10);
break;
+ case 'r':
+ rules_config_file = strdup(optarg);
+ break;
}
}
}
@@ -661,6 +666,14 @@ int main(int argc, char** argv)
}
}
+ if (read_user_policy_config() != 0) {
+ log(TO_ALL, LOG_WARNING, "Read user policy config fail.\n");
+ }
+ if (rules_config_file) {
+ free(rules_config_file);
+ rules_config_file = NULL;
+ }
+
build_object_tree();
if (debug_mode)
dump_object_tree();
diff --git a/irqbalance.h b/irqbalance.h
index 618f254..78d0adc 100644
--- a/irqbalance.h
+++ b/irqbalance.h
@@ -14,6 +14,7 @@
#include "types.h"
#include "config.h"
+#include "rules_config.h"
#ifdef __aarch64__
#define AARCH64
diff --git a/placement.c b/placement.c
index 17a9f2e..bf27297 100644
--- a/placement.c
+++ b/placement.c
@@ -52,8 +52,7 @@ static void find_best_object(struct topo_obj *d, void *data)
* also don't consider any node that doesn't have at least one cpu in
* the unbanned list
*/
- if ((d->obj_type == OBJ_TYPE_NODE) &&
- (!cpus_intersects(d->mask, unbanned_cpus)))
+ if (!cpus_intersects(d->mask, unbanned_cpus))
return;
if (d->powersave_mode)
diff --git a/rules_config.c b/rules_config.c
new file mode 100644
index 0000000..e32a31e
--- /dev/null
+++ b/rules_config.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2019. Huawei Technologies Co., Ltd. All rights reserved.
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include "irqbalance.h"
+
+char *rules_config_file = NULL;
+USER_IRQ_POLICY *user_policy_list = NULL;
+
+void add_usr_irq_policy(USER_IRQ_POLICY *policy)
+{
+ if (policy == NULL) {
+ return;
+ }
+ policy->next = user_policy_list;
+ user_policy_list = policy;
+}
+
+USER_IRQ_POLICY *get_usr_irq_policy(char *name)
+{
+ USER_IRQ_POLICY *p = user_policy_list;
+ if (name == NULL) {
+ return NULL;
+ }
+ while (p != NULL) {
+ if (strstr(name, p->irq_type) != NULL) {
+ return p;
+ }
+ p = p->next;
+ }
+ return NULL;
+}
+
+void set_usr_irq_policy(char *name, struct irq_info *info)
+{
+ USER_IRQ_POLICY *user_policy;
+
+ if (user_policy_list == NULL) {
+ return;
+ }
+
+ user_policy = get_usr_irq_policy(name);
+ if (user_policy != NULL) {
+ if (user_policy->numa_node_set) {
+ info->numa_node = get_numa_node(user_policy->numa_node);
+ log(TO_ALL, LOG_WARNING, "override irq (%d) numa_node to %d\n",
+ info->irq, user_policy->numa_node);
+ }
+ if (user_policy->balance_level_set) {
+ info->level = user_policy->balance_level;
+ log(TO_ALL, LOG_WARNING, "override irq (%d) balance_level to %d\n",
+ info->irq, info->level);
+ }
+ }
+
+}
+
+int read_user_policy_config()
+{
+ FILE *file;
+ char *line = NULL;
+ size_t size = 0;
+ size_t len;
+ char *key;
+ char *value;
+ char *c;
+ int level;
+ int node = -1;
+ char savedline[CONFIG_LINE_MAX_LEN] = {0};
+ USER_IRQ_POLICY *cur_policy = NULL;
+ char *levelvals[] = { "none", "package", "cache", "core" };
+
+ if (rules_config_file == NULL) {
+ return 0;
+ }
+ log(TO_ALL, LOG_INFO, "rules_config_file is: %s\n", rules_config_file);
+ file = fopen(rules_config_file, "r");
+ if (!file)
+ return -1;
+
+ while (!feof(file)) {
+ if (getline(&line, &size, file) <= 0)
+ break;
+ c = line;
+ if (*c == '#') {
+ continue;
+ }
+ len = strlen(line);
+ if (len > sizeof(savedline)-1) {
+ continue;
+ }
+ strncpy(savedline, line, len);
+ savedline[len] = '\0';
+ c = savedline;
+ while (*c == ' ') {
+ c++;
+ }
+ key = c;
+ /* make sure there is no space near '=' */
+ c = strchr(savedline, '=');
+ if (c != NULL) {
+ value = c + 1;
+ *c = '\0';
+ } else {
+ continue;
+ }
+ c = strchr(value, '\n');
+ if (c != NULL) {
+ *c = '\0';
+ }
+ if ((strlen(key) == 0) || (strlen(value) == 0)) {
+ continue;
+ }
+ log(TO_ALL, LOG_INFO, "User irq policy config read: key is %s, value is %s\n", key, value);
+ if (strcmp(key, "type") == 0) {
+ cur_policy = malloc(sizeof(USER_IRQ_POLICY));
+ if (cur_policy == NULL) {
+ goto out;
+ }
+ cur_policy->next = NULL;
+ cur_policy->numa_node_set = 0;
+ cur_policy->balance_level_set = 0;
+ if (strlen(value) > CONFIG_TYPE_MAX_LEN - 1) {
+ continue;
+ }
+ strncpy(cur_policy->irq_type, value, strlen(value) + 1);
+ add_usr_irq_policy(cur_policy);
+ } else if (strcmp(key, "balance_level") == 0) {
+ if (cur_policy == NULL) {
+ goto out;
+ }
+ for (level = 0; level < MAX_LEVEL_NUM; level++) {
+ if (strcasecmp(value, levelvals[level]) == 0) {
+ break;
+ }
+ }
+ if (level >= MAX_LEVEL_NUM) {
+ log(TO_ALL, LOG_WARNING, "Bad value for balance_level policy: %s\n", value);
+ } else {
+ cur_policy->balance_level = level;
+ cur_policy->balance_level_set = 1;
+ }
+ } else if (strcmp(key, "numa_node") == 0) {
+ if (cur_policy == NULL) {
+ goto out;
+ }
+ node = strtoul(value, NULL, 10);
+ /* check node */
+ if (node != -1 && !get_numa_node(node)) {
+ log(TO_ALL, LOG_WARNING, "NUMA node %d doesn't exist\n",
+ node);
+ continue;
+ }
+ cur_policy->numa_node = node;
+ cur_policy->numa_node_set = 1;
+ }
+ }
+out:
+ fclose(file);
+ if (line) {
+ free(line);
+ }
+ return 0;
+}
diff --git a/rules_config.h b/rules_config.h
new file mode 100644
index 0000000..edcac8a
--- /dev/null
+++ b/rules_config.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019. Huawei Technologies Co., Ltd. All rights reserved.
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#ifndef _INCLUDE_RULES_CONFIG_H
+#define _INCLUDE_RULES_CONFIG_H
+
+#define CONFIG_TYPE_MAX_LEN 32
+#define CONFIG_LINE_MAX_LEN 512
+#define MAX_LEVEL_NUM 4
+
+typedef struct user_irq_policy_config {
+ char irq_type[CONFIG_TYPE_MAX_LEN];
+ int numa_node;
+ int balance_level;
+ int numa_node_set;
+ int balance_level_set;
+ struct user_irq_policy_config *next;
+}USER_IRQ_POLICY;
+extern USER_IRQ_POLICY *user_policy_list;
+extern char *rules_config_file;
+
+void add_usr_irq_policy(USER_IRQ_POLICY *policy);
+
+USER_IRQ_POLICY *get_usr_irq_policy(char *name);
+
+int read_user_policy_config();
+
+void set_usr_irq_policy(char *name, struct irq_info *info);
+
+#endif
--
2.23.0

View File

@ -0,0 +1,105 @@
From e44eed4faef6ee1bd1ae41dd27a8513d37681f7f Mon Sep 17 00:00:00 2001
From: liuchao <liuchao173@huawei.com>
Date: Tue, 17 Dec 2019 02:54:57 +0000
Subject: [PATCH] feature: add switch to clear affinity hint
All irqs' affinity hints are cleared in update_affinity_hint and forced
to rebalance. In some scenarios, it will affect performance.
---
hint_verify.c | 10 +++++++++-
irqbalance.c | 9 +++++++--
2 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/hint_verify.c b/hint_verify.c
index 3492902..2f895be 100644
--- a/hint_verify.c
+++ b/hint_verify.c
@@ -18,6 +18,7 @@ extern int keep_going;
extern GMainLoop *main_loop;
extern gboolean scan();
extern int last_interval;
+extern int clear_affinity_hint;
int real_sleep_interval;
int sleep_interval_count;
@@ -55,7 +56,8 @@ void update_affinity_hint(struct irq_info *info, void *data __attribute__((unuse
if (!hint_enabled)
return;
- cpus_clear(info->affinity_hint);
+ if (clear_affinity_hint)
+ cpus_clear(info->affinity_hint);
sprintf(path, "/proc/irq/%d/affinity_hint", info->irq);
process_one_line(path, get_mask_from_bitmap, &current_affinity_hint);
@@ -68,6 +70,11 @@ void update_affinity_hint(struct irq_info *info, void *data __attribute__((unuse
}
}
+static void check_clear()
+{
+ process_one_line("/etc/sysconfig/irqbalance_clear", get_int, &clear_affinity_hint);
+}
+
/*
* This function is the main loop of irqbalance, which include:
* 1. scan opration for irq balancing;
@@ -92,6 +99,7 @@ gboolean poll_hint_affinity_and_scan(gpointer data __attribute__((unused)))
sleep_count++;
if (need_verify_flag && hint_changed()) {
+ check_clear();
for_each_irq(NULL, update_affinity_hint, NULL);
if (hint_has_changed) {
hint_has_changed = FALSE;
diff --git a/irqbalance.c b/irqbalance.c
index 5985d8d..9449e40 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -54,6 +54,7 @@ int numa_avail;
int journal_logging = 0;
int need_rescan;
int need_rebuild;
+int clear_affinity_hint = 1;
unsigned int log_mask = TO_ALL;
const char *log_indent;
unsigned long power_thresh = ULONG_MAX;
@@ -104,6 +105,7 @@ struct option lopts[] = {
{"rulesconfig", 1, NULL, 'r'},
{"hintpolicy", 1, NULL, 'h'},
{"verifyhint", 1, NULL, 'v'},
+ {"notclearhint", 0, NULL, 'n'},
{0, 0, 0, 0}
};
@@ -112,7 +114,7 @@ static void usage(void)
log(TO_CONSOLE, LOG_INFO, "irqbalance [--oneshot | -o] [--debug | -d] [--foreground | -f] [--journal | -j]\n");
log(TO_CONSOLE, LOG_INFO, " [--powerthresh= | -p <off> | <n>] [--banirq= | -i <n>] [--banmod= | -m <module>] [--policyscript= | -l <script>]\n");
log(TO_CONSOLE, LOG_INFO, " [--pid= | -s <file>] [--deepestcache= | -c <n>] [--interval= | -t <n>] [--migrateval= | -e <n>]\n");
- log(TO_CONSOLE, LOG_INFO, " [--rulesconfig= | -r <config>] [--hintpolicy | -h <subset>] [--verifyhint= | -v n]\n");
+ log(TO_CONSOLE, LOG_INFO, " [--rulesconfig= | -r <config>] [--hintpolicy | -h <subset>] [--verifyhint= | -v n] [--notclearhint | -n]\n");
}
static void version(void)
@@ -127,7 +129,7 @@ static void parse_command_line(int argc, char **argv)
unsigned long val;
while ((opt = getopt_long(argc, argv,
- "odfjVi:p:s:c:l:m:t:e:r:h:v:",
+ "odfjVni:p:s:c:l:m:t:e:r:h:v:",
lopts, &longind)) != -1) {
switch(opt) {
@@ -218,6 +220,9 @@ static void parse_command_line(int argc, char **argv)
exit(1);
}
break;
+ case 'n':
+ clear_affinity_hint = 0;
+ break;
}
}
}
--
2.23.0

View File

@ -0,0 +1,100 @@
From b697a97436dafa13f0ae3febde299bfc20498f9d Mon Sep 17 00:00:00 2001
From: liuchao <liuchao173@huawei.com>
Date: Wed, 23 Oct 2019 11:42:26 +0000
Subject: [PATCH] feature: add the switch of printing log
add the switch of printing log
---
cputree.c | 16 ++++++++--------
irqbalance.c | 11 ++++++++++-
2 files changed, 18 insertions(+), 9 deletions(-)
diff --git a/cputree.c b/cputree.c
index 010e672..48d3d0d 100644
--- a/cputree.c
+++ b/cputree.c
@@ -399,23 +399,23 @@ static void dump_irq(struct irq_info *info, void *data)
indent[i] = log_indent[0];
indent[i] = '\0';
- log(TO_CONSOLE, LOG_INFO, "%sInterrupt %i node_num is %d (%s/%lu:%lu) \n", indent,
+ log(TO_ALL, LOG_INFO, "%sInterrupt %i node_num is %d (%s/%lu:%lu) \n", indent,
info->irq, irq_numa_node(info)->number, classes[info->class], info->load, (info->irq_count - info->last_irq_count));
free(indent);
}
static void dump_numa_node_num(struct topo_obj *p, void *data __attribute__((unused)))
{
- log(TO_CONSOLE, LOG_INFO, "%d ", p->number);
+ log(TO_ALL, LOG_INFO, "%d ", p->number);
}
static void dump_balance_obj(struct topo_obj *d, void *data __attribute__((unused)))
{
struct topo_obj *c = (struct topo_obj *)d;
- log(TO_CONSOLE, LOG_INFO, "%s%s%s%sCPU number %i numa_node is ",
+ log(TO_ALL, LOG_INFO, "%s%s%s%sCPU number %i numa_node is ",
log_indent, log_indent, log_indent, log_indent, c->number);
for_each_object(cpu_numa_node(c), dump_numa_node_num, NULL);
- log(TO_CONSOLE, LOG_INFO, "(load %lu)\n", (unsigned long)c->load);
+ log(TO_ALL, LOG_INFO, "(load %lu)\n", (unsigned long)c->load);
if (c->interrupts)
for_each_irq(c->interrupts, dump_irq, (void *)18);
}
@@ -424,10 +424,10 @@ static void dump_cache_domain(struct topo_obj *d, void *data)
{
char *buffer = data;
cpumask_scnprintf(buffer, 4095, d->mask);
- log(TO_CONSOLE, LOG_INFO, "%s%sCache domain %i: numa_node is ",
+ log(TO_ALL, LOG_INFO, "%s%sCache domain %i: numa_node is ",
log_indent, log_indent, d->number);
for_each_object(d->numa_nodes, dump_numa_node_num, NULL);
- log(TO_CONSOLE, LOG_INFO, "cpu mask is %s (load %lu) \n", buffer,
+ log(TO_ALL, LOG_INFO, "cpu mask is %s (load %lu) \n", buffer,
(unsigned long)d->load);
if (d->children)
for_each_object(d->children, dump_balance_obj, NULL);
@@ -439,9 +439,9 @@ static void dump_package(struct topo_obj *d, void *data)
{
char *buffer = data;
cpumask_scnprintf(buffer, 4096, d->mask);
- log(TO_CONSOLE, LOG_INFO, "Package %i: numa_node ", d->number);
+ log(TO_ALL, LOG_INFO, "Package %i: numa_node ", d->number);
for_each_object(d->numa_nodes, dump_numa_node_num, NULL);
- log(TO_CONSOLE, LOG_INFO, "cpu mask is %s (load %lu)\n",
+ log(TO_ALL, LOG_INFO, "cpu mask is %s (load %lu)\n",
buffer, (unsigned long)d->load);
if (d->children)
for_each_object(d->children, dump_cache_domain, buffer);
diff --git a/irqbalance.c b/irqbalance.c
index ecc3eca..450a1ff 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -266,6 +266,15 @@ gboolean force_rescan(gpointer data __attribute__((unused)))
return TRUE;
}
+static int check_debug()
+{
+ int ret = 0;
+
+ process_one_line("/etc/sysconfig/irqbalance_debug", get_int, &ret);
+
+ return ret;
+}
+
gboolean scan(gpointer data __attribute__((unused)))
{
log(TO_CONSOLE, LOG_INFO, "\n\n\n-----------------------------------------------------------------------------\n");
@@ -310,7 +319,7 @@ gboolean scan(gpointer data __attribute__((unused)))
activate_mappings();
out:
- if (debug_mode)
+ if (debug_mode || check_debug())
dump_tree();
if (one_shot_mode)
keep_going = 0;
--
2.23.0

View File

@ -0,0 +1,39 @@
From 2fdfbc218be09a6335df8dde15498f75fa12bc0a Mon Sep 17 00:00:00 2001
From: liuchao <liuchao173@huawei.com>
Date: Thu, 6 Feb 2020 06:44:51 +0000
Subject: [PATCH] feature: enable irqbalance to link with multiple clients at
the same time
---
irqbalance.c | 2 +-
irqbalance.h | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/irqbalance.c b/irqbalance.c
index 368233f..f0a4164 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -608,7 +608,7 @@ int init_socket()
log(TO_ALL, LOG_WARNING, "Unable to set socket options.\n");
return 1;
}
- listen(socket_fd, 1);
+ listen(socket_fd, MAX_CLIENT_NUM);
g_unix_fd_add(socket_fd, G_IO_IN, sock_handle, NULL);
return 0;
}
diff --git a/irqbalance.h b/irqbalance.h
index fba8a1b..8662741 100644
--- a/irqbalance.h
+++ b/irqbalance.h
@@ -174,6 +174,7 @@ extern unsigned int log_mask;
#define SOCKET_PATH "irqbalance"
#define SOCKET_TMPFS "/run/irqbalance"
+#define MAX_CLIENT_NUM 32
extern int process_one_line(char *path, void (*cb)(char *line, void *data), void *data);
extern void get_mask_from_bitmap(char *line, void *mask);
--
2.23.0

View File

@ -0,0 +1,678 @@
From 5390ed72086f1d9ffce2b4ca367daf2cbda4d358 Mon Sep 17 00:00:00 2001
From: hejingxian <hejingxian@huawei.com>
Date: Tue, 18 Feb 2020 14:49:31 +0800
Subject: [PATCH] feature: encapsulate and compile the functions in irqbalance-ui
into a shared library
users can send settings msg to irqbalance or get information from irqbalance
by calling external functions in the shared library.
Signed-off-by: Liu Chao <liuchao173@huawei.com>
Signed-off-by: He Jingxian <hejingxian@huawei.com>
---
irqbalance.c | 4 +-
irqbalance.h | 1 +
ui/Makefile | 29 ++++
ui/client.c | 435 +++++++++++++++++++++++++++++++++++++++++++++++++
ui/irqbalance-ui.c | 4 +-
ui/irqbalance-ui.h | 1 +
ui/irqbalance_client.h | 111 +++++++++++++
7 files changed, 581 insertions(+), 4 deletions(-)
create mode 100644 ui/Makefile
create mode 100644 ui/client.c
create mode 100644 ui/irqbalance_client.h
diff --git a/irqbalance.c b/irqbalance.c
index 1af23c6..7c79087 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -452,12 +452,12 @@ void get_object_stat(struct topo_obj *object, void *data)
gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attribute__((unused)))
{
- char buff[500];
+ char buff[SOCKET_RECV_BUF_LEN];
int sock;
int recv_size = 0;
int valid_user = 0;
- struct iovec iov = { buff, 500 };
+ struct iovec iov = { buff, SOCKET_RECV_BUF_LEN };
struct msghdr msg = { 0 };
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
diff --git a/irqbalance.h b/irqbalance.h
index b2e5409..842cead 100644
--- a/irqbalance.h
+++ b/irqbalance.h
@@ -175,6 +175,7 @@ extern unsigned int log_mask;
#define SOCKET_PATH "irqbalance"
#define SOCKET_TMPFS "/run/irqbalance"
#define MAX_CLIENT_NUM 32
+#define SOCKET_RECV_BUF_LEN 4096
extern int process_one_line(char *path, void (*cb)(char *line, void *data), void *data);
extern void get_mask_from_bitmap(char *line, void *mask);
diff --git a/ui/Makefile b/ui/Makefile
new file mode 100644
index 0000000..27e0fbf
--- /dev/null
+++ b/ui/Makefile
@@ -0,0 +1,29 @@
+#!/bin/make
+export SHELL = /bin/bash
+DIR = $(shell pwd)
+TARGET = libirqbalance_client.so
+
+RM = rm
+CC = gcc
+
+SRC = $(wildcard $(DIR)/*.c)
+OBJ = $(patsubst $(DIR)/%.c,$(DIR)/%.o,$(SRC))
+
+INC = -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include
+CFLAG = -g3 -Wall -fPIC -D_GNU_SOURCE -fstack-protector-strong -D_FORTIFY_SOURCE=2 -O2 -ftrapv
+SHARED = -shared
+LFLAG = -lglib-2.0 -lncursesw -z now -s
+
+CFLAG += $(INC)
+
+all: $(TARGET)
+
+$(TARGET): $(OBJ)
+ $(CC) $(SHARED) $(LFLAG) -o $@ $(OBJ)
+
+$(DIR)/%.o: $(DIR)/%.c
+ $(CC) $(CFLAG) -c $< -o $@
+
+clean:
+ -$(RM) $(DIR)/*.o
+ -$(RM) $(TARGET)
diff --git a/ui/client.c b/ui/client.c
new file mode 100644
index 0000000..027404b
--- /dev/null
+++ b/ui/client.c
@@ -0,0 +1,435 @@
+/*
+ * Copyright (C) 2020. Huawei Technologies Co., Ltd. All rights reserved.
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#include <sys/socket.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "irqbalance-ui.h"
+#include "irqbalance_client.h"
+
+extern int irqbalance_pid;
+extern GList *tree;
+
+void irqbalance_set_pid(int pid)
+{
+ irqbalance_pid = pid;
+}
+
+/*
+ * string format:
+ * <int> <int> <int> <int> ... or NONE
+ */
+int irqbalance_set_ban_irqs(const char *irqs)
+{
+ char *data = NULL;
+ const char *tmp;
+ int ret = IRQBALANCE_SUCCESS;
+ int socket_fd = 0;
+ int i;
+ struct msghdr *msg = NULL;
+ struct iovec iov;
+
+ if (irqs == NULL || strlen(irqs) == 0) {
+ ret = IRQBALANCE_INPUT_ILLEGAL;
+ goto out;
+ }
+ if (strncmp(irqs, "NONE", strlen("NONE"))) {
+ tmp = irqs;
+ for (i = 0; i < strlen(irqs); i++) {
+ if (*tmp != ' ' && (*tmp < '0' || *tmp > '9')) {
+ ret = IRQBALANCE_INPUT_ILLEGAL;
+ goto out;
+ }
+ tmp++;
+ }
+ }
+
+ socket_fd = init_connection();
+ if (!socket_fd) {
+ ret = IRQBALANCE_CONNECT_FAIL;
+ goto out;
+ }
+
+ data = (char *)malloc(strlen(irqs) + strlen(BAN_IRQS) + 1);
+ if (!data) {
+ ret = IRQBALANCE_MALLOC_FAIL;
+ goto out;
+ }
+ msg = create_credentials_msg();
+ if (!msg) {
+ ret = IRQBALANCE_MALLOC_FAIL;
+ goto out;
+ }
+ snprintf(data, strlen(irqs) + strlen(BAN_IRQS) + 1,
+ "%s%s", BAN_IRQS, irqs);
+ iov.iov_base = (void *) data;
+ iov.iov_len = strlen(data) + 1;
+ msg->msg_iov = &iov;
+ if (sendmsg(socket_fd, msg, 0) == -1)
+ ret = IRQBALANCE_SEND_FAIL;
+
+out:
+ if (socket_fd > 0)
+ close(socket_fd);
+ if (msg)
+ free(msg->msg_control);
+ free(msg);
+ free(data);
+ return ret;
+}
+
+unsigned int char_to_hex(char c)
+{
+ unsigned int hex;
+
+ if (c >= '0' && c <= '9') {
+ hex = c - '0';
+ } else {
+ hex = c - 'a' + 10;
+ }
+ return hex;
+}
+
+char *parse_cpus_to_cpulist(const char *cpus)
+{
+ int i, ret;
+ const char *tmp;
+ char *cpulist;
+ int cpus_len;
+ unsigned int hex;
+ int index;
+
+ if (cpus == NULL
+ || strlen(cpus) == 0
+ || strlen(cpus) > CPU_MASK_MAX_LEN)
+ return NULL;
+
+ if (strncmp(cpus, "NULL", strlen("NULL"))) {
+ tmp = cpus;
+ cpus_len = strlen(cpus);
+ for (i = 0; i < cpus_len; i++) {
+ if ((*tmp < '0' || *tmp > '9')
+ && (*tmp < 'a' || *tmp > 'f'))
+ return NULL;
+ tmp++;
+ }
+ cpulist = (char *)malloc(CPU_LIST_MAX_LEN);
+ if (!cpulist)
+ return NULL;
+ cpulist[0] = 0;
+ for (i = 0; i < cpus_len; i++) {
+ hex = char_to_hex(cpus[cpus_len - 1 - i]);
+ index = 0;
+ while (hex) {
+ if (hex & 1) {
+ ret = snprintf(cpulist + strlen(cpulist),
+ CPU_LIST_MAX_LEN - strlen(cpulist), "%d,", (i << 2) + index);
+ if (ret < 0)
+ break;
+ }
+ index++;
+ hex = (hex >> 1);
+ }
+ }
+ } else {
+ cpulist = strdup(cpus);
+ }
+ return cpulist;
+}
+
+/*
+ * string format:
+ * 00000001 or NULL
+ */
+int irqbalance_set_ban_cpus(const char *cpus)
+{
+ int socket_fd = 0;
+ int ret = IRQBALANCE_SUCCESS;
+ char *data = NULL;
+ char *cpulist = NULL;
+ struct msghdr *msg = NULL;
+ struct iovec iov;
+
+ cpulist = parse_cpus_to_cpulist(cpus);
+ if(!cpulist) {
+ ret = IRQBALANCE_INPUT_ILLEGAL;
+ goto out;
+ }
+
+ socket_fd = init_connection();
+ if(!socket_fd) {
+ ret = IRQBALANCE_CONNECT_FAIL;
+ goto out;
+ }
+
+ data = (char *)malloc(strlen(cpulist) + strlen(BAN_CPUS) + 1);
+ if (!data) {
+ ret = IRQBALANCE_MALLOC_FAIL;
+ goto out;
+ }
+ msg = create_credentials_msg();
+ if (!msg) {
+ ret = IRQBALANCE_MALLOC_FAIL;
+ goto out;
+ }
+ snprintf(data, strlen(cpulist) + strlen(BAN_CPUS) + 1,
+ "%s%s", BAN_CPUS, cpulist);
+ iov.iov_base = (void *) data;
+ iov.iov_len = strlen(data) + 1;
+ msg->msg_iov = &iov;
+ if (sendmsg(socket_fd, msg, 0) == -1)
+ ret = IRQBALANCE_SEND_FAIL;
+
+out:
+ if (socket_fd)
+ close(socket_fd);
+ if (msg)
+ free(msg->msg_control);
+ free(msg);
+ free(data);
+ free(cpulist);
+ return ret;
+}
+
+int irqbalance_set_sleep_interval(int sleep)
+{
+ char data[DATA_BUF_MAX_LEN];
+ int ret = IRQBALANCE_SUCCESS;
+ int socket_fd = 0;
+ struct msghdr *msg = NULL;
+ struct iovec iov;
+
+ if (sleep < 1) {
+ ret = IRQBALANCE_INPUT_ILLEGAL;
+ goto out;
+ }
+
+ socket_fd = init_connection();
+ if(!socket_fd) {
+ ret = IRQBALANCE_CONNECT_FAIL;
+ goto out;
+ }
+
+ msg = create_credentials_msg();
+ if (!msg) {
+ ret = IRQBALANCE_MALLOC_FAIL;
+ goto out;
+ }
+ snprintf(data, DATA_BUF_MAX_LEN, "%s %d", SET_SLEEP, sleep);
+ iov.iov_base = (void *) data;
+ iov.iov_len = strlen(data) + 1;
+ msg->msg_iov = &iov;
+ if (sendmsg(socket_fd, msg, 0) == -1)
+ ret = IRQBALANCE_SEND_FAIL;
+
+out:
+ if (socket_fd)
+ close(socket_fd);
+ if (msg)
+ free(msg->msg_control);
+ free(msg);
+ return ret;
+}
+
+void free_banned_irq_list(irqbalance_banned_irq_list_t *list_head)
+{
+ irqbalance_banned_irq_list_t *banned_irq = list_head;
+ irqbalance_banned_irq_list_t *next_banned_irq;
+
+ while (banned_irq) {
+ next_banned_irq = banned_irq->next;
+ free(banned_irq);
+ banned_irq = next_banned_irq;
+ }
+}
+
+/* get user setup info, including sleep setting, banned irqs and banned cpus info */
+irqbalance_setup_t *irqbalance_get_setup_info()
+{
+ char *token, *ptr, *setup_info;
+ char *copy = NULL;
+ char *scan;
+ int i, sleep, setup_size;
+ int ban_irq_num = 0;
+ int ban_irq_size = sizeof(irqbalance_banned_irq_t);
+ irqbalance_setup_t *setup_data = NULL;
+ irqbalance_banned_irq_list_t *banned_irq = NULL;
+ irqbalance_banned_irq_list_t *list_head = NULL;
+
+ setup_info = get_data(SETUP);
+ if (setup_info == NULL || strlen(setup_info) == 0)
+ return NULL;
+ copy = strdup(setup_info);
+ if (!copy)
+ goto out;
+
+ token = strtok_r(copy, " ", &ptr);
+ if (!token)
+ goto out;
+ if(strncmp(token, "SLEEP", strlen("SLEEP")))
+ goto out;
+ scan = strtok_r(NULL, " ", &ptr);
+ if (!scan)
+ goto out;
+ sleep = strtol(scan, NULL, 10);
+ token = strtok_r(NULL, " ", &ptr);
+ while(token && !strncmp(token, "IRQ", strlen("IRQ"))) {
+ banned_irq = (irqbalance_banned_irq_list_t *)malloc(sizeof(irqbalance_banned_irq_list_t));
+ if (!banned_irq)
+ goto out;
+ scan = strtok_r(NULL, " ", &ptr);
+ if (!scan)
+ goto out;
+ banned_irq->irq = strtol(scan, NULL, 10);
+ token = strtok_r(NULL, " ", &ptr);
+ if (!token || strncmp(token, "LOAD", strlen("LOAD")))
+ goto out;
+ scan = strtok_r(NULL, " ", &ptr);
+ if (!scan)
+ goto out;
+ banned_irq->load = strtol(scan, NULL, 10);
+ token = strtok_r(NULL, " ", &ptr);
+ if (!token || strncmp(token, "DIFF", strlen("DIFF")))
+ goto out;
+ scan = strtok_r(NULL, " ", &ptr);
+ if (!scan)
+ goto out;
+ banned_irq->diff = strtol(scan, NULL, 10);
+ token = strtok_r(ptr, " ", &ptr);
+ if (!token || strncmp(token, "CLASS", strlen("CLASS")))
+ goto out;
+ scan = strtok_r(NULL, " ", &ptr);
+ if (!scan)
+ goto out;
+ banned_irq->class = strtol(scan, NULL, 10);
+ banned_irq->next = list_head;
+ list_head = banned_irq;
+ ban_irq_num++;
+ token = strtok_r(NULL, " ", &ptr);
+ banned_irq = NULL;
+ }
+ if (ban_irq_num > 1)
+ setup_size = sizeof(irqbalance_setup_t) + (ban_irq_num - 1) * ban_irq_size;
+ else
+ setup_size = sizeof(irqbalance_setup_t);
+ setup_data = (irqbalance_setup_t *)malloc(setup_size);
+ if (!setup_data)
+ goto out;
+ memset(setup_data->banned_cpus, 0, NR_CPUS + 1);
+ setup_data->sleep = sleep;
+ setup_data->ban_irq_num = ban_irq_num;
+ banned_irq = list_head;
+ for (i = ban_irq_num; i > 0; i--) {
+ memcpy(&(setup_data->banned_irqs[i - 1]), banned_irq, ban_irq_size);
+ banned_irq = banned_irq->next;
+ }
+ if(strncmp(token, "BANNED", strlen("BANNED")))
+ goto out;
+ token = strtok_r(NULL, " ", &ptr);
+ if (strlen(token) > NR_CPUS)
+ goto out;
+ strcpy(setup_data->banned_cpus, token);
+out:
+ free(setup_info);
+ free(copy);
+ free_banned_irq_list(list_head);
+ return setup_data;
+}
+
+/* the type of the GList pointer data is irqbalance_cpu_node_t*/
+GList *irqbalance_get_stats_info()
+{
+ char *stats_data;
+
+ stats_data = get_data(STATS);
+ if (stats_data == NULL)
+ return NULL;
+ parse_into_tree(stats_data);
+ free(stats_data);
+ return tree;
+}
+
+/* get banned cpus mask */
+char *irqbalance_get_banned_cpus()
+{
+ char *setup_info;
+ char *copy;
+ char *bancpu_str;
+
+ setup_info = get_data(SETUP);
+ if (setup_info == NULL)
+ return NULL;
+ bancpu_str = strstr(setup_info, "BANNED");
+ if (bancpu_str == NULL) {
+ free(setup_info);
+ return NULL;
+ }
+ copy = strdup(bancpu_str + strlen("BANNED") + 1);
+ free(setup_info);
+ return copy;
+}
+
+/* get banned irqs string */
+char *irqbalance_get_banned_irqs()
+{
+ char *setup_info;
+ char *copy;
+ char *start_ptr, *end_ptr;
+ char *ret_str, *temp, *last_temp;;
+
+ setup_info = get_data(SETUP);
+ if (setup_info == NULL)
+ return NULL;
+ start_ptr = strstr(setup_info, "IRQ");
+ if (start_ptr == NULL) {
+ free(setup_info);
+ return NULL;
+ }
+ copy = strdup(start_ptr);
+ free(setup_info);
+ if (copy == NULL)
+ return NULL;
+ end_ptr = strstr(copy, "BANNED");
+ if (end_ptr)
+ *end_ptr = '\0';
+
+ ret_str = (char*)malloc(strlen(copy) + 1);
+ if (ret_str == NULL) {
+ free(copy);
+ return NULL;
+ }
+ memset(ret_str, 0, strlen(copy) + 1);
+ temp = copy + strlen("IRQ") + 1;
+ last_temp = temp;
+ while (*temp) {
+ temp = strstr(last_temp, " ");
+ if (temp)
+ *temp = '\0';
+ else
+ break;
+ strcat(ret_str, last_temp);
+ strcat(ret_str, " ");
+ last_temp = strstr(temp + 1, "IRQ");
+ if (last_temp == NULL)
+ break;
+ last_temp = last_temp + strlen("IRQ") + 1;
+ temp = last_temp;
+ }
+ free(copy);
+ if (strlen(ret_str) == 0) {
+ free(ret_str);
+ return NULL;
+ }
+ return ret_str;
+}
+
diff --git a/ui/irqbalance-ui.c b/ui/irqbalance-ui.c
index 943f008..f0deaf8 100644
--- a/ui/irqbalance-ui.c
+++ b/ui/irqbalance-ui.c
@@ -120,8 +120,8 @@ char * get_data(char *string)
* With a select, ioctl to determine size, and malloc based
* on that
*/
- char *data = malloc(8192);
- int len = recv(socket_fd, data, 8192, 0);
+ char *data = malloc(RECV_BUF_SIZE);
+ int len = recv(socket_fd, data, RECV_BUF_SIZE, 0);
close(socket_fd);
data[len] = '\0';
free(msg->msg_control);
diff --git a/ui/irqbalance-ui.h b/ui/irqbalance-ui.h
index b32d58a..503c0c5 100644
--- a/ui/irqbalance-ui.h
+++ b/ui/irqbalance-ui.h
@@ -26,6 +26,7 @@
#define IRQ_10GBETH 6
#define IRQ_VIRT_EVENT 7
+#define RECV_BUF_SIZE (4096 * 8)
/* Typedefs */
diff --git a/ui/irqbalance_client.h b/ui/irqbalance_client.h
new file mode 100644
index 0000000..8f18b79
--- /dev/null
+++ b/ui/irqbalance_client.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2020. Huawei Technologies Co., Ltd. All rights reserved.
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#include <glib.h>
+#include <glib-unix.h>
+
+#ifndef IRQBALANCE_CLIENT_H
+#define IRQBALANCE_CLIENT_H
+
+/* ERRORNO */
+#define IRQBALANCE_SUCCESS 0
+#define IRQBALANCE_INPUT_ILLEGAL 1
+#define IRQBALANCE_CONNECT_FAIL 2
+#define IRQBALANCE_SEND_FAIL 3
+#define IRQBALANCE_MALLOC_FAIL 4
+
+#define BAN_CPUS "settings cpus "
+#define DATA_BUF_MAX_LEN 128
+#define NR_CPUS 1024
+#define CPU_LIST_MAX_LEN 4096
+#define CPU_MASK_MAX_LEN 256
+
+typedef enum irqbalance_node_type {
+ IRQ_OBJ_TYPE_CPU,
+ IRQ_OBJ_TYPE_CACHE,
+ IRQ_OBJ_TYPE_PACKAGE,
+ IRQ_OBJ_TYPE_NODE
+} irqbalance_node_type_e;
+
+typedef struct irqbalance_irq {
+ int vector;
+ unsigned long load;
+ unsigned long diff;
+ char is_banned;
+ GList *assigned_to;
+ int class;
+} irqbalance_irq_t;
+
+typedef struct irqbalance_cpu_node {
+ irqbalance_node_type_e type;
+ int number;
+ unsigned long load;
+ int is_powersave;
+ struct irqbalance_cpu_node *parent;
+ GList *children;
+ GList *irqs;
+ GList *cpu_list;
+ char *cpu_mask;
+} irqbalance_cpu_node_t;
+
+typedef struct irqbalance_banned_irq_list {
+ int irq;
+ int class;
+ unsigned long load;
+ unsigned long diff;
+ struct irqbalance_banned_irq_list *next;
+} irqbalance_banned_irq_list_t;
+
+typedef struct irqbalance_banned_irq_info {
+ int irq;
+ int class;
+ unsigned long load;
+ unsigned long diff;
+} irqbalance_banned_irq_t;
+
+typedef struct irqbalance_setup_data {
+ int sleep;
+ char banned_cpus[NR_CPUS + 1];
+ int ban_irq_num;
+ irqbalance_banned_irq_t banned_irqs[1];
+} irqbalance_setup_t;
+
+/*
+ * set_ban_irqs string format:
+ * <int> <int> <int> <int> ... or NONE
+ * */
+int irqbalance_set_ban_irqs(const char *irqs);
+
+/*
+ * set_ban_cpus string format:
+ * 00000001 or NULL
+ * */
+int irqbalance_set_ban_cpus(const char *cpus);
+
+/* set sleep interval of irqbalance main loop */
+int irqbalance_set_sleep_interval(int sleep);
+
+/* get user setup info, including sleep setting, banned irqs and banned cpus info */
+irqbalance_setup_t *irqbalance_get_setup_info();
+
+/* get irqbalance stats tree */
+GList *irqbalance_get_stats_info();
+
+/* get banned cpus mask */
+char *irqbalance_get_banned_cpus();
+
+/* get banned irqs string */
+char *irqbalance_get_banned_irqs();
+
+/* set the pid of irqbalance server */
+void irqbalance_set_pid(int pid);
+#endif
--
1.8.3.1

View File

@ -0,0 +1,468 @@
From e5b83ac140634830b8f8d9ca8d40a1d9d16d2d5b Mon Sep 17 00:00:00 2001
From: hejingxian <hejingxian@huawei.com>
Date: Tue, 12 Nov 2019 15:29:16 +0800
Subject: [PATCH] feature: introduce affinity hint verify to detect user hint variation
In order to make the user affinity hint becomes effective quickly,
introduce the periodically affinity hint verify.
---
Makefile.am | 2 +-
activate.c | 14 ++++--
classify.c | 5 ++-
cpumask.h | 7 +++
hint_verify.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++
hint_verify.h | 21 ++++++++
irqbalance.c | 43 ++++++++++-----
irqbalance.h | 5 ++
placement.c | 14 ++++++
types.h | 1 +
10 files changed, 228 insertions(+), 20 deletions(-)
create mode 100644 hint_verify.c
create mode 100644 hint_verify.h
diff --git a/Makefile.am b/Makefile.am
index 3086d67..aacb399 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -38,7 +38,7 @@ sbin_PROGRAMS += irqbalance-ui
endif
irqbalance_SOURCES = activate.c bitmap.c classify.c cputree.c irqbalance.c \
- irqlist.c numa.c placement.c procinterrupts.c rules_config.c
+ irqlist.c numa.c placement.c procinterrupts.c rules_config.c hint_verify.c
irqbalance_LDADD = $(LIBCAP_NG_LIBS) $(GLIB2_LIBS)
if IRQBALANCEUI
irqbalance_ui_SOURCES = $(UI_DIR)/helpers.c $(UI_DIR)/irqbalance-ui.c \
diff --git a/activate.c b/activate.c
index 93fde58..c5859bf 100644
--- a/activate.c
+++ b/activate.c
@@ -78,11 +78,6 @@ static void activate_mapping(struct irq_info *info, void *data __attribute__((un
int ret = 0;
cpumask_t applied_mask;
- /*
- * only activate mappings for irqs that have moved
- */
- if (!info->moved)
- return;
if (!info->assigned_obj)
return;
@@ -90,6 +85,15 @@ static void activate_mapping(struct irq_info *info, void *data __attribute__((un
/* activate only online cpus, otherwise writing to procfs returns EOVERFLOW */
cpus_and(applied_mask, cpu_online_map, info->assigned_obj->mask);
+ if (hint_enabled) {
+ if (!cpus_empty(info->affinity_hint)) {
+ cpus_and(applied_mask, applied_mask, info->affinity_hint);
+ if (!cpus_intersects(applied_mask, unbanned_cpus)) {
+ return;
+ }
+ }
+ }
+
/*
* Don't activate anything for which we have an invalid mask
*/
diff --git a/classify.c b/classify.c
index 254197e..e9987ee 100644
--- a/classify.c
+++ b/classify.c
@@ -263,7 +263,7 @@ static int get_irq_class(const char *devpath)
return irq_class;
}
-static gint compare_ints(gconstpointer a, gconstpointer b)
+gint compare_ints(gconstpointer a, gconstpointer b)
{
const struct irq_info *ai = a;
const struct irq_info *bi = b;
@@ -397,6 +397,9 @@ get_numa_node:
process_one_line(path, get_mask_from_bitmap, &new->cpumask);
}
+ sprintf(path, "/proc/irq/%d/affinity_hint", irq);
+ process_one_line(path, get_mask_from_bitmap, &new->affinity_hint);
+
log(TO_CONSOLE, LOG_INFO, "Adding IRQ %d to database\n", irq);
return new;
}
diff --git a/cpumask.h b/cpumask.h
index 5bebbeb..bc5f006 100644
--- a/cpumask.h
+++ b/cpumask.h
@@ -30,6 +30,7 @@
* void cpus_xor(dst, src1, src2) dst = src1 ^ src2
* void cpus_andnot(dst, src1, src2) dst = src1 & ~src2
* void cpus_complement(dst, src) dst = ~src
+ * void cpumask_copy(dst, src) dst = src
*
* int cpus_equal(mask1, mask2) Does mask1 == mask2?
* int cpus_intersects(mask1, mask2) Do mask1 and mask2 intersect?
@@ -142,6 +143,12 @@ static inline void __cpus_complement(cpumask_t *dstp,
bitmap_complement(dstp->bits, srcp->bits, nbits);
}
+#define cpumask_copy(dst, src) __cpumask_copy(&(dst), &(src), NR_CPUS)
+static inline void __cpumask_copy(cpumask_t *dstp, const cpumask_t *srcp, int nbits)
+{
+ bitmap_copy(dstp->bits, srcp->bits, nbits);
+}
+
#define cpus_equal(src1, src2) __cpus_equal(&(src1), &(src2), NR_CPUS)
static inline int __cpus_equal(const cpumask_t *src1p,
const cpumask_t *src2p, int nbits)
diff --git a/hint_verify.c b/hint_verify.c
new file mode 100644
index 0000000..3492902
--- /dev/null
+++ b/hint_verify.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2019. Huawei Technologies Co., Ltd. All rights reserved.
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include "irqbalance.h"
+
+extern int keep_going;
+extern GMainLoop *main_loop;
+extern gboolean scan();
+extern int last_interval;
+
+int real_sleep_interval;
+int sleep_interval_count;
+int poll_hint_interval_count;
+int sleep_count = 0;
+gboolean hint_has_changed = FALSE;
+
+int hint_changed(void)
+{
+ FILE *file;
+ char *line = NULL;
+ size_t size = 0;
+ gboolean changed = FALSE;
+
+ file = fopen("/proc/irq/affinity_hint_notify", "r+");
+ if (!file)
+ return changed;
+
+ if (getline(&line, &size, file) > 0 && *line != '0') {
+ fprintf(file, "Done");
+ changed = TRUE;
+ }
+
+ fclose(file);
+ if (line)
+ free(line);
+ return changed;
+}
+
+void update_affinity_hint(struct irq_info *info, void *data __attribute__((unused)))
+{
+ cpumask_t current_affinity_hint;
+ char path[PATH_MAX];
+
+ if (!hint_enabled)
+ return;
+
+ cpus_clear(info->affinity_hint);
+ sprintf(path, "/proc/irq/%d/affinity_hint", info->irq);
+ process_one_line(path, get_mask_from_bitmap, &current_affinity_hint);
+
+ if (!cpus_equal(current_affinity_hint, info->affinity_hint)) {
+ cpumask_copy(info->affinity_hint, current_affinity_hint);
+ force_rebalance_irq(info, data);
+ hint_has_changed = TRUE;
+ cpumask_scnprintf(path, PATH_MAX, current_affinity_hint);
+ log(TO_ALL, LOG_INFO, "IRQ(%d): affinity hint modified %s\n", info->irq, path);
+ }
+}
+
+/*
+ * This function is the main loop of irqbalance, which include:
+ * 1. scan opration for irq balancing;
+ * 2. poll irq affinity hint changes for quickly applying them.
+ */
+gboolean poll_hint_affinity_and_scan(gpointer data __attribute__((unused)))
+{
+ gboolean need_verify_flag = FALSE;
+ gboolean need_scan_flag = FALSE;
+
+ if (!sleep_interval_count)
+ sleep_interval_count = 1;
+ if (!poll_hint_interval_count)
+ poll_hint_interval_count = 1;
+
+ if (sleep_count % sleep_interval_count == 0) {
+ need_scan_flag = TRUE;
+ }
+ if (sleep_count % poll_hint_interval_count == 0) {
+ need_verify_flag = TRUE;
+ }
+ sleep_count++;
+
+ if (need_verify_flag && hint_changed()) {
+ for_each_irq(NULL, update_affinity_hint, NULL);
+ if (hint_has_changed) {
+ hint_has_changed = FALSE;
+ sleep_count = 1;
+ need_scan_flag = TRUE;
+ }
+ }
+
+ if (need_scan_flag) {
+ if (!scan()) {
+ g_main_loop_quit(main_loop);
+ return FALSE;
+ }
+ }
+
+ update_interval_and_count();
+ if (last_interval != real_sleep_interval) {
+ last_interval = real_sleep_interval;
+ g_timeout_add_seconds(real_sleep_interval, poll_hint_affinity_and_scan, NULL);
+ return FALSE;
+ }
+
+ if (keep_going) {
+ return TRUE;
+ } else {
+ g_main_loop_quit(main_loop);
+ return FALSE;
+ }
+}
+
+void update_interval_and_count()
+{
+ real_sleep_interval =
+ sleep_interval > poll_hint_interval ? poll_hint_interval : sleep_interval;
+ if (!real_sleep_interval) {
+ sleep_interval_count = 1;
+ poll_hint_interval_count = 1;
+ return;
+ }
+ sleep_interval_count = sleep_interval / real_sleep_interval;
+ poll_hint_interval_count = poll_hint_interval / real_sleep_interval;
+}
diff --git a/hint_verify.h b/hint_verify.h
new file mode 100644
index 0000000..7391b32
--- /dev/null
+++ b/hint_verify.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2019. Huawei Technologies Co., Ltd. All rights reserved.
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#ifndef _INCLUDE_HINT_VERIFY_H
+#define _INCLUDE_HINT_VERIFY_H
+
+extern int real_sleep_interval;
+extern gboolean poll_hint_affinity_and_scan();
+extern void update_interval_and_count();
+
+#endif
diff --git a/irqbalance.c b/irqbalance.c
index 450a1ff..5985d8d 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -64,6 +64,8 @@ char *polscript = NULL;
long HZ;
int sleep_interval = SLEEP_INTERVAL;
int last_interval;
+int hint_enabled = 0;
+int poll_hint_interval = SLEEP_INTERVAL / 5;
GMainLoop *main_loop;
char *cpu_ban_string = NULL;
@@ -100,6 +102,8 @@ struct option lopts[] = {
{"version", 0, NULL, 'V'},
{"migrateval", 1, NULL, 'e'},
{"rulesconfig", 1, NULL, 'r'},
+ {"hintpolicy", 1, NULL, 'h'},
+ {"verifyhint", 1, NULL, 'v'},
{0, 0, 0, 0}
};
@@ -108,7 +112,7 @@ static void usage(void)
log(TO_CONSOLE, LOG_INFO, "irqbalance [--oneshot | -o] [--debug | -d] [--foreground | -f] [--journal | -j]\n");
log(TO_CONSOLE, LOG_INFO, " [--powerthresh= | -p <off> | <n>] [--banirq= | -i <n>] [--banmod= | -m <module>] [--policyscript= | -l <script>]\n");
log(TO_CONSOLE, LOG_INFO, " [--pid= | -s <file>] [--deepestcache= | -c <n>] [--interval= | -t <n>] [--migrateval= | -e <n>]\n");
- log(TO_CONSOLE, LOG_INFO, " [--rulesconfig= | -r <config>]\n");
+ log(TO_CONSOLE, LOG_INFO, " [--rulesconfig= | -r <config>] [--hintpolicy | -h <subset>] [--verifyhint= | -v n]\n");
}
static void version(void)
@@ -123,7 +127,7 @@ static void parse_command_line(int argc, char **argv)
unsigned long val;
while ((opt = getopt_long(argc, argv,
- "odfjVi:p:s:c:l:m:t:e:r:",
+ "odfjVi:p:s:c:l:m:t:e:r:h:v:",
lopts, &longind)) != -1) {
switch(opt) {
@@ -198,6 +202,22 @@ static void parse_command_line(int argc, char **argv)
case 'r':
rules_config_file = strdup(optarg);
break;
+ case 'h':
+ if (!strncmp(optarg, "subset", strlen(optarg)))
+ hint_enabled = 1;
+ else {
+ usage();
+ exit(1);
+ }
+
+ break;
+ case 'v':
+ poll_hint_interval = strtol(optarg, NULL, 10);
+ if (poll_hint_interval < 1) {
+ usage();
+ exit(1);
+ }
+ break;
}
}
}
@@ -261,6 +283,10 @@ void force_rebalance_irq(struct irq_info *info, void *data __attribute__((unused)))
if (info->level == BALANCE_NONE)
return;
+ /* Prevent inserting a duplicate entry to avoid list chaos */
+ if (g_list_find_custom(rebalance_irq_list, info, compare_ints))
+ return;
+
if (info->assigned_obj == NULL)
rebalance_irq_list = g_list_append(rebalance_irq_list, info);
else
@@ -275,7 +299,7 @@ static int check_debug()
return ret;
}
-gboolean scan(gpointer data __attribute__((unused)))
+gboolean scan()
{
log(TO_CONSOLE, LOG_INFO, "\n\n\n-----------------------------------------------------------------------------\n");
clear_work_stats();
@@ -325,17 +349,9 @@ out:
keep_going = 0;
cycle_count++;
- /* sleep_interval may be changed by socket */
- if (last_interval != sleep_interval) {
- last_interval = sleep_interval;
- g_timeout_add_seconds(sleep_interval, scan, NULL);
- return FALSE;
- }
-
if (keep_going) {
return TRUE;
} else {
- g_main_loop_quit(main_loop);
return FALSE;
}
}
@@ -720,9 +736,10 @@ int main(int argc, char** argv)
ret = EXIT_FAILURE;
goto out;
}
+ update_interval_and_count();
main_loop = g_main_loop_new(NULL, FALSE);
- last_interval = sleep_interval;
- g_timeout_add_seconds(sleep_interval, scan, NULL);
+ last_interval = real_sleep_interval;
+ g_timeout_add_seconds(real_sleep_interval, poll_hint_affinity_and_scan, NULL);
g_main_loop_run(main_loop);
g_main_loop_quit(main_loop);
diff --git a/irqbalance.h b/irqbalance.h
index 78d0adc..4a73b83 100644
--- a/irqbalance.h
+++ b/irqbalance.h
@@ -15,6 +15,7 @@
#include "types.h"
#include "config.h"
#include "rules_config.h"
+#include "hint_verify.h"
#ifdef __aarch64__
#define AARCH64
@@ -114,6 +115,10 @@ extern void add_banned_irq(int irq);
extern void add_cl_banned_module(char *modname);
extern void add_banned_irq(int irq);
extern void remove_one_irq_from_db(int irq);
+extern void force_rebalance_irq(struct irq_info *info, void *data __attribute__((unused)));
+extern gint compare_ints(gconstpointer a, gconstpointer b);
+extern int hint_enabled, poll_hint_interval;
+extern int sleep_interval;
#define irq_numa_node(irq) ((irq)->numa_node)
diff --git a/placement.c b/placement.c
index bf27297..db79b8b 100644
--- a/placement.c
+++ b/placement.c
@@ -41,6 +41,7 @@ static void find_best_object(struct topo_obj *d, void *data)
{
struct obj_placement *best = (struct obj_placement *)data;
uint64_t newload;
+ cpumask_t subset;
/*
* Don't consider the unspecified numa node here
@@ -58,6 +59,19 @@ static void find_best_object(struct topo_obj *d, void *data)
if (d->powersave_mode)
return;
+ /*
+ * If the hint feature is enabled, then we only want
+ * to consider objects that are within the irqs hint, but
+ * only if that irq in fact has published a hint
+ */
+ if (hint_enabled) {
+ if (!cpus_empty(best->info->affinity_hint)) {
+ cpus_and(subset, best->info->affinity_hint, d->mask);
+ if (cpus_empty(subset))
+ return;
+ }
+ }
+
newload = d->load;
if (newload < best->best_cost) {
best->best = d;
diff --git a/types.h b/types.h
index fa91561..3a04318 100644
--- a/types.h
+++ b/types.h
@@ -67,6 +67,7 @@ struct irq_info {
int flags;
struct topo_obj *numa_node;
cpumask_t cpumask;
+ cpumask_t affinity_hint;
uint64_t irq_count;
uint64_t last_irq_count;
uint64_t load;
--
2.23.0

View File

@ -21,6 +21,10 @@ if [ -n "$IRQBALANCE_BANNED_CPUS" ]; then
export IRQBALANCE_BANNED_CPUS export IRQBALANCE_BANNED_CPUS
fi fi
if [ -n "$IRQBALANCE_BANNED_CPULIST" ]; then
export IRQBALANCE_BANNED_CPULIST
fi
if [ "$IRQBALANCE_ONESHOT" != "auto" ]; then if [ "$IRQBALANCE_ONESHOT" != "auto" ]; then
export IRQBALANCE_ONESHOT export IRQBALANCE_ONESHOT
fi fi

2
irqbalance.rules Normal file
View File

@ -0,0 +1,2 @@
#!/bin/bash
echo > /dev/null

View File

@ -1,16 +1,17 @@
Summary: A dynamic adaptive IRQ balancing daemon Summary: A dynamic adaptive IRQ balancing daemon
Name: irqbalance Name: irqbalance
Version: 1.7.0 Version: 1.7.0
Release: 4 Release: 5
Epoch: 3 Epoch: 3
License: GPLv2 License: GPLv2
Source0: https://github.com/Irqbalance/irqbalance/archive/v%{version}.tar.gz#/irqbalance-%{version}.tar.gz Source0: https://github.com/Irqbalance/irqbalance/archive/v%{version}.tar.gz#/irqbalance-%{version}.tar.gz
Source1: irqbalance.service Source1: irqbalance.service
Source2: irqbalance.sysconfig Source2: irqbalance.sysconfig
Source3: irq_balancer Source3: irqbalance.rules
Source4: irq_balancer
Url: https://github.com/irqbalance/irqbalance Url: https://github.com/irqbalance/irqbalance
BuildRequires: gdb autoconf automake libtool libcap-ng systemd BuildRequires: autoconf automake libtool libcap-ng systemd
BuildRequires: glib2-devel pkgconf libcap-ng-devel ncurses-devel BuildRequires: glib2-devel pkgconf libcap-ng-devel ncurses-devel
Requires: ncurses-libs Requires: ncurses-libs
@ -22,8 +23,25 @@ Requires: numactl-libs
%define _hardened_build 1 %define _hardened_build 1
Patch6000: add-env-variable-to-ban-cpus-using-cpulist-syntax.patch
Patch6001: Add-IRQBALANCE_BANNED_CPULIST-to-env-file.patch Patch6000: backport-add-env-variable-to-ban-cpus-using-cpulist-syntax.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
Patch6005: backport-Add-hot-pull-method-for-irqbalance.patch
Patch6006: backport-Also-fetch-node-info-for-non-PCI-devices.patch
Patch6007: backport-Hotplug-may-occur-again-during-sleep-so-wait-until-t.patch
Patch9000: feature-aarch64-add-the-regular-to-get-the-correct-i.patch
Patch9001: feature-add-new-user-irq-policy-config-rule.patch
Patch9002: feature-add-the-switch-of-printing-log.patch
Patch9003: feature-introduce-verifyhint-to-detect-hint-variatio.patch
Patch9004: feature-add-switch-to-clear-affinity-hint.patch
Patch9005: feature-add-new-irq-migrate-rule-to-avoid-high-cpu-i.patch
Patch9006: feature-enable-irqbalance-to-link-with-multiple-clie.patch
Patch9007: feature-add-ability-to-set-hintpolicy-during-runtime.patch
Patch9008: feature-encapsulate-and-compile-the-functions-in-irqbalance-ui.patch
%description %description
Irqbalance is a daemon to help balance the cpu load generated by Irqbalance is a daemon to help balance the cpu load generated by
@ -33,6 +51,20 @@ single unique cpu, so that load is spread as much as possible over
an entire processor set, while minimizing cache miss rates for irq an entire processor set, while minimizing cache miss rates for irq
handlers. handlers.
%package devel
Summary: The development files of irqbalance client
Requires: glib2-devel ncurses-devel irqbalance-libs
%description devel
Development files for irqbalance client.
%package libs
Summary: The shared librariy of irqbalance client
Requires: glib2 ncurses-libs
%description libs
Shared librariy for irqbalance client.
%package_help %package_help
%prep %prep
@ -42,6 +74,10 @@ handlers.
./autogen.sh ./autogen.sh
%configure %configure
CFLAGS="%{optflags}" %make_build CFLAGS+='-fstack-protector-strong ' CFLAGS="%{optflags}" %make_build CFLAGS+='-fstack-protector-strong '
cd ui
rm -rf *.o
make
cd -
%install %install
install -D -p -m 0755 %{name} %{buildroot}%{_sbindir}/%{name} install -D -p -m 0755 %{name} %{buildroot}%{_sbindir}/%{name}
@ -49,6 +85,9 @@ install -D -p -m 0644 %{SOURCE1} %{buildroot}/%{_unitdir}/%{name}.service
install -D -p -m 0644 %{SOURCE2} %{buildroot}%{_sysconfdir}/sysconfig/%{name} install -D -p -m 0644 %{SOURCE2} %{buildroot}%{_sysconfdir}/sysconfig/%{name}
install -D -p -m 0755 %{SOURCE3} %{buildroot}%{_sbindir}/irq_balancer install -D -p -m 0755 %{SOURCE3} %{buildroot}%{_sbindir}/irq_balancer
install -D -p -m 0755 ui/irqbalance_client.h %{buildroot}/%{_includedir}/irqbalance_client.h
install -D -p -m 0755 ui/libirqbalance_client.so %{buildroot}/%{_libdir}/libirqbalance_client.so
install -d %{buildroot}%{_mandir}/man1/ install -d %{buildroot}%{_mandir}/man1/
install -p -m 0644 ./%{name}.1 %{buildroot}%{_mandir}/man1/ install -p -m 0644 ./%{name}.1 %{buildroot}%{_mandir}/man1/
@ -62,6 +101,12 @@ make check
%config(noreplace) %{_sysconfdir}/sysconfig/%{name} %config(noreplace) %{_sysconfdir}/sysconfig/%{name}
%{_sbindir}/irq_balancer %{_sbindir}/irq_balancer
%files devel
%{_includedir}/irqbalance_client.h
%files libs
%{_libdir}/libirqbalance_client.so
%files help %files help
%{_mandir}/man1/* %{_mandir}/man1/*
@ -81,6 +126,12 @@ fi
/sbin/chkconfig --del %{name} >/dev/null 2>&1 || : /sbin/chkconfig --del %{name} >/dev/null 2>&1 || :
%changelog %changelog
* Fri Apr 9 2021 Liu Chao <liuchao173@huawei.com> - 3:1.7.0-5
- Type:enhanced
- ID:NA
- SUG:restart
- DESC:backport patches
* Tue May 2 2021 Liu Chao <liuchao173@huawei.com> - 3:1.7.0-4 * Tue May 2 2021 Liu Chao <liuchao173@huawei.com> - 3:1.7.0-4
- Type:enhanced - Type:enhanced
- ID:NA - ID:NA

View File

@ -21,6 +21,20 @@
# #
#IRQBALANCE_BANNED_CPUS= #IRQBALANCE_BANNED_CPUS=
# IRQBALANCE_BANNED_CPULIST
# The CPUs list which allows you to indicate which CPUs should
# be skipped when reblancing IRQs. CPU numbers in CPUs list will
# not have any IRQs assigned to them on rebalance.
#
# The format of CPUs list is:
# <cpu number>,...,<cpu number>
# or a range:
# <cpu number>-<cpu number>
# or a mixture:
# <cpu number>,...,<cpu number>-<cpu number>
#
#IRQBALANCE_BANNED_CPULIST=
# #
# IRQBALANCE_BANNED_INTERRUPTS # IRQBALANCE_BANNED_INTERRUPTS
# Interrupts that don't get banlanced as list (separation character # Interrupts that don't get banlanced as list (separation character
@ -35,4 +49,4 @@
# Append any args here to the irqbalance daemon as documented in the man # Append any args here to the irqbalance daemon as documented in the man
# page. # page.
# #
#IRQBALANCE_ARGS= IRQBALANCE_ARGS="--hintpolicy=subset"