485 lines
13 KiB
Diff
485 lines
13 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 | 32 +++++++--
|
|
irqbalance.c | 34 +++++----
|
|
irqbalance.h | 2 +-
|
|
misc/irqbalance.service | 2 +-
|
|
placement.c | 3 +-
|
|
procinterrupts.c | 3 +-
|
|
rules_config.c | 172 ++++++++++++++++++++++++++++++++++++++++++++++++
|
|
rules_config.h | 40 +++++++++++
|
|
9 files changed, 267 insertions(+), 23 deletions(-)
|
|
create mode 100644 rules_config.c
|
|
create mode 100644 rules_config.h
|
|
|
|
diff --git a/Makefile.am b/Makefile.am
|
|
index 62ac482..9276bfb 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 sockapi.c
|
|
+ irqlist.c numa.c placement.c procinterrupts.c sockapi.c rules_config.c
|
|
irqbalance_LDADD = $(LIBCAP_NG_LIBS) $(GLIB2_LIBS) -lpthread
|
|
if IRQBALANCEUI
|
|
irqbalance_ui_SOURCES = $(UI_DIR)/helpers.c $(UI_DIR)/irqbalance-ui.c \
|
|
diff --git a/classify.c b/classify.c
|
|
index 65aeae2..7c97d47 100644
|
|
--- a/classify.c
|
|
+++ b/classify.c
|
|
@@ -663,7 +663,7 @@ struct irq_info *build_one_dev_entry(const char *dirname, GList *tmp_list)
|
|
|
|
sprintf(path, "%s/%s/msi_irqs", SYSPCI_DIR, dirname);
|
|
sprintf(devpath, "%s/%s", SYSPCI_DIR, dirname);
|
|
-
|
|
+ memset(&pol, -1, sizeof(struct user_irq_policy));
|
|
/* Needs to be further classified */
|
|
hint.class = IRQ_OTHER;
|
|
|
|
@@ -679,7 +679,9 @@ struct irq_info *build_one_dev_entry(const char *dirname, GList *tmp_list)
|
|
new = get_irq_info(irqnum);
|
|
if (new)
|
|
continue;
|
|
- get_irq_user_policy(devpath, irqnum, &pol);
|
|
+ if (user_policy_list == NULL) {
|
|
+ get_irq_user_policy(devpath, irqnum, &pol);
|
|
+ }
|
|
if ((pol.ban == 1) || (check_for_irq_ban(devpath, irqnum, tmp_list))) {
|
|
add_banned_irq(irqnum, &banned_irqs, 0);
|
|
continue;
|
|
@@ -714,7 +716,9 @@ struct irq_info *build_one_dev_entry(const char *dirname, GList *tmp_list)
|
|
new = get_irq_info(irqnum);
|
|
if (new)
|
|
goto done;
|
|
- get_irq_user_policy(devpath, irqnum, &pol);
|
|
+ if (user_policy_list == NULL) {
|
|
+ get_irq_user_policy(devpath, irqnum, &pol);
|
|
+ }
|
|
if ((pol.ban == 1) || (check_for_irq_ban(path, irqnum, tmp_list))) {
|
|
add_banned_irq(irqnum, &banned_irqs, 0);
|
|
goto done;
|
|
@@ -855,18 +859,24 @@ struct irq_info *add_new_irq(int irq, struct irq_info *hint, GList *proc_interru
|
|
struct irq_info *new = NULL;
|
|
struct user_irq_policy pol;
|
|
|
|
+ memset(&pol, -1, sizeof(struct user_irq_policy));
|
|
new = get_irq_info(irq);
|
|
if (new)
|
|
return new;
|
|
|
|
/* Set NULL devpath for the irq has no sysfs entries */
|
|
- get_irq_user_policy(NULL, irq, &pol);
|
|
+ if (user_policy_list == NULL) {
|
|
+ get_irq_user_policy(NULL, irq, &pol);
|
|
+ }
|
|
if ((pol.ban == 1) || check_for_irq_ban(NULL, irq, proc_interrupts)) { /*FIXME*/
|
|
add_banned_irq(irq, &banned_irqs, 0);
|
|
new = get_irq_info(irq);
|
|
- } else
|
|
+ } else {
|
|
new = add_one_irq_to_db(NULL, 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);
|
|
|
|
@@ -880,6 +890,16 @@ static void add_missing_irq(struct irq_info *info, void *attr)
|
|
|
|
if (!lookup)
|
|
add_new_irq(info->irq, info, proc_interrupts);
|
|
+ else {
|
|
+ if (user_policy_list != NULL) {
|
|
+ set_usr_irq_policy(info->name, lookup);
|
|
+ }
|
|
+ }
|
|
+ if (info->name) {
|
|
+ free(info->name);
|
|
+ info->name = NULL;
|
|
+ }
|
|
+
|
|
}
|
|
|
|
static void free_tmp_irqs(gpointer data)
|
|
diff --git a/irqbalance.c b/irqbalance.c
|
|
index 21d578a..d41753c 100644
|
|
--- a/irqbalance.c
|
|
+++ b/irqbalance.c
|
|
@@ -99,6 +99,7 @@ struct option lopts[] = {
|
|
{"banmod", 1 , NULL, 'm'},
|
|
{"interval", 1 , NULL, 't'},
|
|
{"version", 0, NULL, 'V'},
|
|
+ {"rulesconfig", 1, NULL, 'r'},
|
|
{0, 0, 0, 0}
|
|
};
|
|
|
|
@@ -106,7 +107,7 @@ static void usage(void)
|
|
{
|
|
log(TO_CONSOLE, LOG_INFO, "irqbalance [--oneshot | -o] [--debug | -d] [--foreground | -f] [--journal | -j] [--hintpolicy= | -h [exact|subset|ignore]]\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>]\n");
|
|
+ log(TO_CONSOLE, LOG_INFO, " [--pid= | -s <file>] [--deepestcache= | -c <n>] [--interval= | -t <n>] [--rulesconfig= | -r <config>]\n");
|
|
}
|
|
|
|
static void version(void)
|
|
@@ -121,7 +122,7 @@ static void parse_command_line(int argc, char **argv)
|
|
unsigned long val;
|
|
|
|
while ((opt = getopt_long(argc, argv,
|
|
- "odfji:p:s:c:b:l:m:t:V",
|
|
+ "odfji:p:s:c:b:l:m:t:V:r",
|
|
lopts, &longind)) != -1) {
|
|
|
|
switch(opt) {
|
|
@@ -201,6 +202,9 @@ static void parse_command_line(int argc, char **argv)
|
|
exit(1);
|
|
}
|
|
break;
|
|
+ case 'r':
|
|
+ rules_config_file = strdup(optarg);
|
|
+ break;
|
|
}
|
|
}
|
|
}
|
|
@@ -539,6 +543,21 @@ int main(int argc, char** argv)
|
|
log(TO_ALL, LOG_WARNING, "Unable to determin HZ defaulting to 100\n");
|
|
HZ = 100;
|
|
}
|
|
+ if (!foreground_mode) {
|
|
+ if (daemon(0,0)) {
|
|
+ ret = EXIT_FAILURE;
|
|
+ goto out;
|
|
+ }
|
|
+ /* Write pidfile */
|
|
+ if (pidfile && create_lock_pidfile(pidfile) < 0) {
|
|
+ ret = EXIT_FAILURE;
|
|
+ goto out;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (read_user_policy_config() != 0) {
|
|
+ log(TO_ALL, LOG_WARNING, "Read user policy config fail.\n");
|
|
+ }
|
|
|
|
build_object_tree();
|
|
if (debug_mode)
|
|
@@ -554,16 +573,6 @@ int main(int argc, char** argv)
|
|
goto out;
|
|
}
|
|
|
|
- if (!foreground_mode) {
|
|
- if (daemon(0,0))
|
|
- exit(EXIT_FAILURE);
|
|
- /* Write pidfile */
|
|
- if (pidfile && create_lock_pidfile(pidfile) < 0) {
|
|
- ret = EXIT_FAILURE;
|
|
- goto out;
|
|
- }
|
|
- }
|
|
-
|
|
g_unix_signal_add(SIGINT, handler, NULL);
|
|
g_unix_signal_add(SIGTERM, handler, NULL);
|
|
g_unix_signal_add(SIGUSR1, handler, NULL);
|
|
@@ -589,6 +598,7 @@ int main(int argc, char** argv)
|
|
goto out;
|
|
}
|
|
|
|
+ log(TO_ALL, LOG_INFO, "irqbalance start scan.\n");
|
|
main_loop = g_main_loop_new(NULL, FALSE);
|
|
int *last_interval = &sleep_interval;
|
|
g_timeout_add_seconds(sleep_interval, scan, last_interval);
|
|
diff --git a/irqbalance.h b/irqbalance.h
|
|
index 120bc9b..42f95cb 100644
|
|
--- a/irqbalance.h
|
|
+++ b/irqbalance.h
|
|
@@ -14,7 +14,7 @@
|
|
|
|
#include "types.h"
|
|
#include "config.h"
|
|
-
|
|
+#include "rules_config.h"
|
|
#ifdef __aarch64__
|
|
#define AARCH64
|
|
#endif
|
|
diff --git a/misc/irqbalance.service b/misc/irqbalance.service
|
|
index ce0022c..2c002b2 100644
|
|
--- a/misc/irqbalance.service
|
|
+++ b/misc/irqbalance.service
|
|
@@ -5,7 +5,7 @@ After=syslog.target
|
|
|
|
[Service]
|
|
OOMScoreAdjust=-500
|
|
-Type=simple
|
|
+Type=forking
|
|
PIDFile=/var/run/irqbalance.pid
|
|
EnvironmentFile=/etc/sysconfig/irqbalance
|
|
ExecStart=/usr/sbin/irq_balancer
|
|
diff --git a/placement.c b/placement.c
|
|
index 19462bb..d887c60 100644
|
|
--- a/placement.c
|
|
+++ b/placement.c
|
|
@@ -53,8 +53,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/procinterrupts.c b/procinterrupts.c
|
|
index 60b2545..18b3ceb 100644
|
|
--- a/procinterrupts.c
|
|
+++ b/procinterrupts.c
|
|
@@ -245,7 +245,8 @@ static void init_irq_class_and_type(char *savedline, struct irq_info *info, int
|
|
info->class = IRQ_OTHER;
|
|
#endif
|
|
}
|
|
- info->name = strdupa(irq_mod);
|
|
+
|
|
+ info->name = strdup(irq_mod);
|
|
}
|
|
|
|
|
|
diff --git a/rules_config.c b/rules_config.c
|
|
new file mode 100644
|
|
index 0000000..1270ac7
|
|
--- /dev/null
|
|
+++ b/rules_config.c
|
|
@@ -0,0 +1,172 @@
|
|
+/*
|
|
+ * 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;
|
|
+
|
|
+ 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 (!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..b8f9dc5
|
|
--- /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
|
|
--
|
|
1.8.3.1
|
|
|
|
|