irqbalance/feature-add-new-user-irq-policy-config-rule.patch
2021-04-09 14:58:29 +08:00

388 lines
11 KiB
Diff

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