Package init

This commit is contained in:
overweight 2019-09-30 10:53:30 -04:00
commit aa0afbee66
35 changed files with 4781 additions and 0 deletions

View File

@ -0,0 +1,53 @@
From f2623176c2997e7803d485084fa5150556caddcf Mon Sep 17 00:00:00 2001
From: Kairui Song <kasong@redhat.com>
Date: Mon, 5 Nov 2018 17:18:49 +0800
Subject: [PATCH 102/112] Don't leak socket fd on connection error
Signed-off-by: Kairui Song <kasong@redhat.com>
---
irqbalance.c | 7 ++++---
ui/irqbalance-ui.c | 1 +
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/irqbalance.c b/irqbalance.c
index 0946603..364ca72 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -376,7 +376,7 @@ gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attri
}
if ((recv_size = recvmsg(sock, &msg, 0)) < 0) {
log(TO_ALL, LOG_WARNING, "Error while receiving data.\n");
- goto out;
+ goto out_close;
}
cmsg = CMSG_FIRSTHDR(&msg);
if ((cmsg->cmsg_level == SOL_SOCKET) &&
@@ -388,7 +388,7 @@ gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attri
}
if (!valid_user) {
log(TO_ALL, LOG_INFO, "Permission denied for user to connect to socket.\n");
- goto out;
+ goto out_close;
}
if (!strncmp(buff, "stats", strlen("stats"))) {
@@ -421,7 +421,7 @@ gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attri
need_rescan = 1;
if (!strncmp(irq_string, "NONE", strlen("NONE"))) {
free(irq_string);
- goto out;
+ goto out_close;
}
int irq = strtoul(irq_string, &end, 10);
do {
@@ -457,6 +457,7 @@ gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attri
free(setup);
}
+out_close:
close(sock);
}
--
1.8.3.1

View File

@ -0,0 +1,73 @@
From 721460664afad79e2d96bbcb173eda68eed9743b Mon Sep 17 00:00:00 2001
From: Gerd Rausch <gerd.rausch@oracle.com>
Date: Thu, 18 Oct 2018 11:21:40 -0700
Subject: [PATCH 100/112] Fix ambiguous parsing of *node* entries in /sys.
The code used to use strstr(..., "node") while iterating over
sysfs directories such as /sys/devices/system/cpu/cpu*.
It then made an assumption that the entry would start with "node",
which is not necessarily the case (e.g. the "firmware_node" entry).
The code happened to work for as long as the node[0-9]* entry
would be processed before the "firmware_node" entry shows up.
A change to the linux kernel "end_name_hash" function resulted
in a different hash, and ultimately in a different order
by which entries were returned by readdir(3).
This led to the exposure of this bug.
Signed-off-by: Gerd Rausch <gerd.rausch@oracle.com>
---
cputree.c | 11 ++++++++---
numa.c | 5 ++++-
2 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/cputree.c b/cputree.c
index c88143f..f08ce84 100644
--- a/cputree.c
+++ b/cputree.c
@@ -368,9 +368,14 @@ static void do_one_cpu(char *path)
entry = readdir(dir);
if (!entry)
break;
- if (strstr(entry->d_name, "node")) {
- nodeid = strtoul(&entry->d_name[4], NULL, 10);
- break;
+ if (strncmp(entry->d_name, "node", 4) == 0) {
+ char *end;
+ int num;
+ num = strtol(entry->d_name + 4, &end, 10);
+ if (!*end && num >= 0) {
+ nodeid = num;
+ break;
+ }
}
} while (entry);
closedir(dir);
diff --git a/numa.c b/numa.c
index cd67ec8..f0b1a98 100644
--- a/numa.c
+++ b/numa.c
@@ -29,6 +29,7 @@
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
+#include <ctype.h>
#include <sys/types.h>
#include <dirent.h>
@@ -115,7 +116,9 @@ void build_numa_node_list(void)
entry = readdir(dir);
if (!entry)
break;
- if ((entry->d_type == DT_DIR) && (strstr(entry->d_name, "node"))) {
+ if ((entry->d_type == DT_DIR) &&
+ (strncmp(entry->d_name, "node", 4) == 0) &&
+ isdigit(entry->d_name[4])) {
add_one_node(entry->d_name);
}
} while (entry);
--
1.8.3.1

View File

@ -0,0 +1,34 @@
From 702cab67df2bafd9735a753387eae7febd74263b Mon Sep 17 00:00:00 2001
From: Kairui Song <kasong@redhat.com>
Date: Sun, 2 Sep 2018 23:40:45 +0800
Subject: [PATCH 095/112] Fix an possible overflow error
Got:
"specified bound 2048 exceeds the size 19 of the destination"
when -O2 is used, and a "*** buffer overflow detected ***" error output
with no backtrace.
With -O0, it's gone, guess it's some gcc optimization problem, and the
size there is wrong anyway, this patch could fix it.
---
irqbalance.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/irqbalance.c b/irqbalance.c
index 81bf8d8..0946603 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -444,8 +444,8 @@ gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attri
}
if (!strncmp(buff, "setup", strlen("setup"))) {
char banned[512];
- char *setup = calloc(strlen("SLEEP ") + 11 +1, 1);
- snprintf(setup, 2048, "SLEEP %d ", sleep_interval);
+ char *setup = calloc(strlen("SLEEP ") + 11 + 1, 1);
+ snprintf(setup, strlen("SLEEP ") + 11 + 1, "SLEEP %d ", sleep_interval);
if(g_list_length(cl_banned_irqs) > 0) {
for_each_irq(cl_banned_irqs, get_irq_data, setup);
}
--
1.8.3.1

View File

@ -0,0 +1,253 @@
From 85d37098a551034061d4b77be275d664e109c3fb Mon Sep 17 00:00:00 2001
From: Kairui Song <kasong@redhat.com>
Date: Thu, 30 Aug 2018 17:45:53 +0800
Subject: [PATCH 094/112] Fix several memleak problems found by covscan
Some memleak issues is found by static analysis tools, and can confirm
irqbalance is leaking memory slowly when there are incomming connection
to socket.
This patch could solve the memleak problem.
---
irqbalance.c | 16 ++++++++++++----
ui/irqbalance-ui.c | 31 +++++++++++++++++++++++++++----
ui/ui.c | 2 ++
3 files changed, 41 insertions(+), 8 deletions(-)
diff --git a/irqbalance.c b/irqbalance.c
index bce9d56..81bf8d8 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -372,11 +372,11 @@ gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attri
sock = accept(fd, NULL, NULL);
if (sock < 0) {
log(TO_ALL, LOG_WARNING, "Connection couldn't be accepted.\n");
- return TRUE;
+ goto out;
}
if ((recv_size = recvmsg(sock, &msg, 0)) < 0) {
log(TO_ALL, LOG_WARNING, "Error while receiving data.\n");
- return TRUE;
+ goto out;
}
cmsg = CMSG_FIRSTHDR(&msg);
if ((cmsg->cmsg_level == SOL_SOCKET) &&
@@ -388,7 +388,7 @@ gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attri
}
if (!valid_user) {
log(TO_ALL, LOG_INFO, "Permission denied for user to connect to socket.\n");
- return TRUE;
+ goto out;
}
if (!strncmp(buff, "stats", strlen("stats"))) {
@@ -408,6 +408,7 @@ gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attri
if (new_iterval >= 1) {
sleep_interval = new_iterval;
}
+ free(sleep_string);
} else if (!(strncmp(buff + strlen("settings "), "ban irqs ",
strlen("ban irqs ")))) {
char *end;
@@ -419,12 +420,14 @@ gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attri
cl_banned_irqs = NULL;
need_rescan = 1;
if (!strncmp(irq_string, "NONE", strlen("NONE"))) {
- return TRUE;
+ free(irq_string);
+ goto out;
}
int irq = strtoul(irq_string, &end, 10);
do {
add_cl_banned_irq(irq);
} while((irq = strtoul(end, &end, 10)));
+ free(irq_string);
} else if (!(strncmp(buff + strlen("settings "), "cpus ",
strlen("cpus")))) {
char *cpu_ban_string = malloc(
@@ -436,6 +439,7 @@ gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attri
banned_cpumask_from_ui = NULL;
}
need_rescan = 1;
+ free(cpu_ban_string);
}
}
if (!strncmp(buff, "setup", strlen("setup"))) {
@@ -450,10 +454,14 @@ gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attri
snprintf(setup + strlen(setup), strlen(banned) + 7 + 1,
"BANNED %s", banned);
send(sock, setup, strlen(setup), 0);
+ free(setup);
}
close(sock);
}
+
+out:
+ free(msg.msg_control);
return TRUE;
}
diff --git a/ui/irqbalance-ui.c b/ui/irqbalance-ui.c
index d4deee0..47dd5dc 100644
--- a/ui/irqbalance-ui.c
+++ b/ui/irqbalance-ui.c
@@ -41,6 +41,7 @@ struct msghdr * create_credentials_msg()
cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
memcpy(CMSG_DATA(cmsg), credentials, sizeof(struct ucred));
+ free(credentials);
return msg;
}
@@ -87,6 +88,8 @@ void send_settings(char *data)
sendmsg(socket_fd, msg, 0);
close(socket_fd);
+ free(msg->msg_control);
+ free(msg);
}
char * get_data(char *string)
@@ -115,6 +118,8 @@ char * get_data(char *string)
int len = recv(socket_fd, data, 8192, 0);
close(socket_fd);
data[len] = '\0';
+ free(msg->msg_control);
+ free(msg);
return data;
}
@@ -123,6 +128,7 @@ void parse_setup(char *setup_data)
char *token, *ptr;
int i,j;
char *copy;
+ irq_t *new_irq = NULL;
if((setup_data == NULL) || (strlen(setup_data) == 0)) return;
copy = strdup(setup_data);
if (!copy)
@@ -136,7 +142,7 @@ void parse_setup(char *setup_data)
token = strtok_r(NULL, " ", &ptr);
/* Parse banned IRQ data */
while(!strncmp(token, "IRQ", strlen("IRQ"))) {
- irq_t *new_irq = malloc(sizeof(irq_t));
+ new_irq = malloc(sizeof(irq_t));
new_irq->vector = strtol(strtok_r(NULL, " ", &ptr), NULL, 10);
token = strtok_r(NULL, " ", &ptr);
if(strncmp(token, "LOAD", strlen("LOAD"))) goto out;
@@ -151,6 +157,7 @@ void parse_setup(char *setup_data)
new_irq->assigned_to = NULL;
setup.banned_irqs = g_list_append(setup.banned_irqs, new_irq);
token = strtok_r(NULL, " ", &ptr);
+ new_irq = NULL;
}
if(strncmp(token, "BANNED", strlen("BANNED"))) goto out;
@@ -165,6 +172,7 @@ void parse_setup(char *setup_data)
banned_cpu);
}
}
+ free(map);
}
free(copy);
@@ -173,6 +181,9 @@ void parse_setup(char *setup_data)
out: {
/* Invalid data presented */
printf("Invalid data sent. Unexpected token: %s", token);
+ if (new_irq) {
+ free(new_irq);
+ }
free(copy);
g_list_free(tree);
exit(1);
@@ -240,7 +251,9 @@ void parse_into_tree(char *data)
cpu_node_t *parent = NULL;
char *copy;
tree = NULL;
-
+ irq_t *new_irq = NULL;
+ cpu_node_t *new = NULL;
+
if (!data || strlen(data) == 0)
return;
@@ -255,7 +268,7 @@ void parse_into_tree(char *data)
free(copy);
goto out;
}
- cpu_node_t *new = malloc(sizeof(cpu_node_t));
+ new = malloc(sizeof(cpu_node_t));
new->irqs = NULL;
new->children = NULL;
new->cpu_list = NULL;
@@ -279,7 +292,7 @@ void parse_into_tree(char *data)
/* Parse assigned IRQ data */
while((token != NULL) && (!strncmp(token, "IRQ", strlen("IRQ")))) {
- irq_t *new_irq = malloc(sizeof(irq_t));
+ new_irq = malloc(sizeof(irq_t));
new_irq->vector = strtol(strtok_r(NULL, " ", &ptr), NULL, 10);
token = strtok_r(NULL, " ", &ptr);
if(strncmp(token, "LOAD", strlen("LOAD"))) goto out;
@@ -293,6 +306,7 @@ void parse_into_tree(char *data)
new_irq->is_banned = 0;
new->irqs = g_list_append(new->irqs, new_irq);
token = strtok_r(NULL, " ", &ptr);
+ new_irq = NULL;
}
if((token == NULL) || (strncmp(token, "IRQ", strlen("IRQ")))) {
@@ -306,6 +320,8 @@ void parse_into_tree(char *data)
parent = new;
}
}
+
+ new = NULL;
}
free(copy);
for_each_node(tree, assign_cpu_lists, NULL);
@@ -315,6 +331,12 @@ void parse_into_tree(char *data)
out: {
/* Invalid data presented */
printf("Invalid data sent. Unexpected token: %s\n", token);
+ if (new_irq) {
+ free(new_irq);
+ }
+ if (new) {
+ free(new);
+ }
g_list_free(tree);
exit(1);
}
@@ -330,6 +352,7 @@ gboolean rescan_tree(gpointer data __attribute__((unused)))
display_tree();
}
free(setup_data);
+ free(irqbalance_data);
return TRUE;
}
diff --git a/ui/ui.c b/ui/ui.c
index 4054f0e..06ec472 100644
--- a/ui/ui.c
+++ b/ui/ui.c
@@ -71,6 +71,7 @@ char * check_control_in_sleep_input(int max_len, int column_offest, int line_off
attrset(COLOR_PAIR(6));
break;
case 27:
+ free(input_to);
return NULL;
default:
input_to[iteration] = new;
@@ -115,6 +116,7 @@ int get_valid_sleep_input(int column_offest)
input);
refresh();
}
+ free(input);
}
attrset(COLOR_PAIR(1));
--
1.8.3.1

View File

@ -0,0 +1,58 @@
From d6abbe898baa111207e1e9316dde75c38d555325 Mon Sep 17 00:00:00 2001
From: Neil Horman <nhorman@tuxdriver.com>
Date: Mon, 9 Jul 2018 10:12:41 -0400
Subject: [PATCH 091/112] Fix some string copy limitations
Latest gcc caught some errors in our string copying routines. Fix those
up
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
---
irqbalance.c | 3 +--
procinterrupts.c | 2 +-
ui/irqbalance-ui.c | 2 +-
3 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/irqbalance.c b/irqbalance.c
index 66e56f8..2614719 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -468,8 +468,7 @@ int init_socket(char *socket_name)
}
addr.sun_family = AF_UNIX;
- addr.sun_path[0] = '\0';
- strncpy(addr.sun_path + 1, socket_name, strlen(socket_name));
+ strncpy(addr.sun_path, socket_name, strlen(addr.sun_path));
if (bind(socket_fd, (struct sockaddr *)&addr,
sizeof(sa_family_t) + strlen(socket_name) + 1) < 0) {
log(TO_ALL, LOG_WARNING, "Daemon couldn't be bound to the socket.\n");
diff --git a/procinterrupts.c b/procinterrupts.c
index 4ef8751..7283998 100644
--- a/procinterrupts.c
+++ b/procinterrupts.c
@@ -274,7 +274,7 @@ void parse_proc_interrupts(void)
if (!c)
continue;
- strncpy(savedline, line, sizeof(savedline));
+ strncpy(savedline, line, sizeof(savedline)-1);
*c = 0;
c++;
diff --git a/ui/irqbalance-ui.c b/ui/irqbalance-ui.c
index 3fc46af..d4deee0 100644
--- a/ui/irqbalance-ui.c
+++ b/ui/irqbalance-ui.c
@@ -57,7 +57,7 @@ int init_connection()
addr.sun_family = AF_UNIX;
char socket_name[64];
snprintf(socket_name, 64, "%s%d.sock", SOCKET_PATH, irqbalance_pid);
- strncpy(addr.sun_path + 1, socket_name, strlen(socket_name));
+ strncpy(addr.sun_path, socket_name, strlen(addr.sun_path));
if(connect(socket_fd, (struct sockaddr *)&addr,
sizeof(sa_family_t) + strlen(socket_name) + 1) < 0) {
--
1.8.3.1

View File

@ -0,0 +1,37 @@
From 8adbe9aacb93c5a160f3ecfc00adc10a64d27c14 Mon Sep 17 00:00:00 2001
From: Sekhar Nori <nsekhar@ti.com>
Date: Tue, 19 Feb 2019 08:29:58 +0000
Subject: [PATCH 108/112] Fix string truncation issues detected by GCC 8
This fixes string truncation warning generated by GCC of the form:
irqbalance.c:485:2: warning: 'strncpy' output truncated before terminating nul copying as many bytes from a string as its length [-Wstringop-truncation]
strncpy(addr.sun_path, socket_name, strlen(socket_name));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Using source size in strncpy so fix that by using destination size.
For the instance of this issue in irqbalance-ui.c, fix the issue by
eliminating the unneeded temporary buffer.
Signed-off-by: Sekhar Nori <nsekhar@ti.com>
---
irqbalance.c | 2 +-
ui/irqbalance-ui.c | 5 ++---
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/irqbalance.c b/irqbalance.c
index 60d8a5e..c1a0e15 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -482,7 +482,7 @@ int init_socket()
*/
addr.sun_family = AF_UNIX;
snprintf(socket_name, 64, "%s/%s%d.sock", SOCKET_TMPFS, SOCKET_PATH, getpid());
- strncpy(addr.sun_path, socket_name, strlen(socket_name));
+ strncpy(addr.sun_path, socket_name, sizeof(addr.sun_path));
if (bind(socket_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
log(TO_ALL, LOG_WARNING, "Daemon couldn't be bound to the file-based socket.\n");
--
1.8.3.1

View File

@ -0,0 +1,52 @@
From 0906c9dcf1754bb2f32f9247608cc937650d2a0e Mon Sep 17 00:00:00 2001
From: Neil Horman <nhorman@tuxdriver.com>
Date: Fri, 4 May 2018 06:15:51 -0400
Subject: [PATCH] arm: Add a catchall guessing mechanism
Instead of spamming the logs to indicate we are guessing at an irq type,
and then not finding one, add a catchall regex to match on everything
last to assign the type and class as legacy/other, and report that
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
---
procinterrupts.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/procinterrupts.c b/procinterrupts.c
index eb84a1c..1aa4413 100644
--- a/procinterrupts.c
+++ b/procinterrupts.c
@@ -105,10 +105,12 @@ static void guess_arm_irq_hints(char *name, struct irq_info *info)
{
int i, rc;
static int compiled = 0;
+ /* Note: Last entry is a catchall */
static struct irq_match matches[] = {
{ "eth.*" ,{NULL} ,NULL, IRQ_TYPE_LEGACY, IRQ_GBETH },
{ "[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},
{NULL},
};
@@ -134,8 +136,7 @@ static void guess_arm_irq_hints(char *name, struct irq_info *info)
info->class = matches[i].class;
if (matches[i].refine_match)
matches[i].refine_match(name, info);
-
- log(TO_ALL, LOG_DEBUG, "IRQ %s(%d) is class %d\n", name, info->irq,info->class);
+ log(TO_ALL, LOG_DEBUG, "IRQ %s(%d) guessed as class %d\n", name, info->irq,info->class);
}
}
@@ -214,7 +215,6 @@ GList* collect_full_irq_list()
info->class = IRQ_VIRT_EVENT;
} else {
#ifdef AARCH64
- log(TO_ALL, LOG_DEBUG, "GUESSING AARCH64 CLASS FOR %s\n", irq_name);
guess_arm_irq_hints(irq_name, info);
#else
info->type = IRQ_TYPE_LEGACY;
--
2.21.0.windows.1

View File

@ -0,0 +1,50 @@
From 0c8ecab9e6f5fae5860e7fbc795e988c112edede Mon Sep 17 00:00:00 2001
From: xiashuang <xiashuang1@huawei.com>
Date: Thu, 25 Jul 2019 22:38:32 -0400
Subject: [PATCH] fix fgets will get a redundant new line
this patch fix a bug introduced by bugfix-force-irq-into-rebalance-list-when-irq-removed-and-reinserted.patch.
the previous patch use fgets to get a directory name from buffer. but fgets will get a redundant newline,
so the directory name are always invalid, this patch just remove the '\n'.
---
classify.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/classify.c b/classify.c
index e61c39b..440576f 100644
--- a/classify.c
+++ b/classify.c
@@ -747,6 +747,7 @@ void find_irq_dev_path(int irq, char *dirname, int length)
char path[PATH_MAX];
char buffer[128];
char *brc = NULL;
+ size_t dirlen;
memset(dirname, 0, length);
/* Return defaults if irq is 0 */
@@ -762,8 +763,10 @@ void find_irq_dev_path(int irq, char *dirname, int length)
}
brc = fgets(buffer, 128, output);
- if (brc) {
+ /* fgets will get a redundant \n */
+ if (brc && (dirlen = strcspn(brc, "\n")) > 0) {
log(TO_CONSOLE, LOG_INFO, "msi_irqs IRQ %d dirname is %s\n", irq, brc);
+ brc[dirlen] = '\0';
strncpy(dirname, brc, length);
pclose(output);
return;
@@ -779,8 +782,9 @@ void find_irq_dev_path(int irq, char *dirname, int length)
}
brc = fgets(buffer, 128, output);
- if (brc) {
+ if (brc && (dirlen = strcspn(brc, "\n")) > 0) {
log(TO_CONSOLE, LOG_INFO, "IRQ %d dirname is %s\n", irq, brc);
+ brc[dirlen] = '\0';
strncpy(dirname, brc, length);
pclose(output);
return;
--
1.8.3.1

View File

@ -0,0 +1,30 @@
From 2c040ddc5869635598e4fbf5c63217f60fdef5f1 Mon Sep 17 00:00:00 2001
From: xiashuang <xiashuang1@huawei.com>
Date: Sun, 17 Mar 2019 18:59:09 -0400
Subject: [PATCH 2/4] huawei bugfix fix a hole that flees hotplug event
from 1.0.9, original infoformation is missing
---
irqbalance.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/irqbalance.c b/irqbalance.c
index 6412447..2f699b8 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -284,9 +284,9 @@ gboolean scan(gpointer data)
for_each_irq(NULL, force_rebalance_irq, NULL);
parse_proc_interrupts();
parse_proc_stat();
- sleep_approx(sleep_interval);
- clear_work_stats();
- parse_proc_interrupts();
+
+ /* Still need to check hotplugged or not next round */
+ return TRUE;
}
parse_proc_stat();
--
1.8.3.1

View File

@ -0,0 +1,81 @@
From 384cdfa4ef28415c3df50d1759951a20c6f0661f Mon Sep 17 00:00:00 2001
From: caomeng <caomeng5@huawei.com>
Date: Thu, 4 Jul 2019 03:47:20 +0800
Subject: [PATCH] bugfix-fix-two-same-irq-insert-to-list
When the function force_rebalance_irq is executed,the same irq may be added into
rebalance_irq_list again, resulting in failed irqbalance service. Thus, a function
named irq_in_rebalance_list which is used to check if the irq is in rebalance_irq_list
will be executed before force_rebalance_irq. And this patch fixex the bug introduced
by feature-introduce-verifyhint-to-detect-hint-variation.patch.
---
classify.c | 11 +++++++++++
irqbalance.h | 2 +-
procinterrupts.c | 8 ++++++--
3 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/classify.c b/classify.c
index 0951c72..4d699da 100644
--- a/classify.c
+++ b/classify.c
@@ -288,6 +288,17 @@ static void add_banned_irq(int irq, GList **list)
return;
}
+int irq_in_rebalance_list(int irq)
+{
+ GList *entry = NULL;
+ struct irq_info find = {0};
+
+ find.irq = irq;
+ entry = g_list_find_custom(rebalance_irq_list, &find, compare_ints);
+
+ return entry ? 1 : 0;
+}
+
void add_cl_banned_irq(int irq)
{
add_banned_irq(irq, &cl_banned_irqs);
diff --git a/irqbalance.h b/irqbalance.h
index 80ec017..821de0e 100644
--- a/irqbalance.h
+++ b/irqbalance.h
@@ -107,7 +107,7 @@ extern void free_cl_opts(void);
extern void add_cl_banned_module(char *modname);
#define irq_numa_node(irq) ((irq)->numa_node)
extern void force_rebalance_irq(struct irq_info *info, void *data __attribute__((unused)));
-
+int irq_in_rebalance_list(int irq);
/* huawei */
extern struct irq_info *build_one_dev_entry(const char *dirname, GList *tmp_list);
extern void find_irq_dev_path(int irq, char *dirname, int length);
diff --git a/procinterrupts.c b/procinterrupts.c
index fc4641a..9e38e49 100644
--- a/procinterrupts.c
+++ b/procinterrupts.c
@@ -348,7 +348,9 @@ void parse_proc_interrupts(void)
*/
if (count < info->irq_count) {
log(TO_CONSOLE, LOG_INFO, "Removed and reinserted IRQ %d added into rebalance list\n", number);
- force_rebalance_irq(info, NULL);
+ if (!irq_in_rebalance_list(info->irq)) {
+ force_rebalance_irq(info, NULL);
+ }
}
info->last_irq_count = info->irq_count;
@@ -602,7 +604,9 @@ void update_affinity_hint(struct irq_info *info, void *data __attribute__((unuse
cpumask_parse_user(line, len, 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);
+ if (!irq_in_rebalance_list(info->irq)) {
+ force_rebalance_irq(info, data);
+ }
log(TO_ALL, LOG_INFO, "IRQ(%d): affinity hint modified\n", info->irq);
}
}
--
1.8.3.1

View File

@ -0,0 +1,472 @@
From 1ca314651ddc31cd52ef67893fdd7aac43ea5201 Mon Sep 17 00:00:00 2001
From: zhengshaoyu <zhengshaoyu@huawei.com>
Date: Thu, 22 Jun 2017 04:39:00 +0000
Subject: [PATCH] irqbalance: bugfix popen and pclose
[Changelog]: bugfix popen and pclose
[Author]:zhengshaoyu
Date: Sun, 17 Mar 2019 20:07:28 -0400
---
classify.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++-------
irqbalance.c | 2 +-
irqbalance.h | 5 +++
procinterrupts.c | 112 +++++++++++++++++++++++++++++++------------------
types.h | 1 +
5 files changed, 190 insertions(+), 56 deletions(-)
diff --git a/classify.c b/classify.c
index 9868633..30a8d2a 100644
--- a/classify.c
+++ b/classify.c
@@ -66,6 +66,8 @@ struct pci_info {
#define PCI_SUB_DEVICE_EMC_0568 0x0568
#define PCI_SUB_DEVICE_EMC_dd00 0xdd00
+extern void force_rebalance_irq(struct irq_info *info, void *data __attribute__((unused)));
+
/*
* Apply software workarounds for some special devices
*
@@ -562,11 +564,13 @@ static int check_for_irq_ban(char *path __attribute__((unused)), int irq, GList
/*
* Check to see if we banned module which the irq belongs to.
*/
- entry = g_list_find_custom(proc_interrupts, &find, compare_ints);
- if (entry) {
- res = entry->data;
- if (check_for_module_ban(res->name))
- return 1;
+ if (proc_interrupts) {
+ entry = g_list_find_custom(proc_interrupts, &find, compare_ints);
+ if (entry) {
+ res = entry->data;
+ if (check_for_module_ban(res->name))
+ return 1;
+ }
}
#ifdef INCLUDE_BANSCRIPT
@@ -605,13 +609,14 @@ static int check_for_irq_ban(char *path __attribute__((unused)), int irq, GList
/*
* 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)
+struct irq_info *build_one_dev_entry(const char *dirname, GList *tmp_list)
{
struct dirent *entry;
DIR *msidir;
FILE *fd;
int irqnum;
- struct irq_info *new, hint;
+ struct irq_info *new = NULL;
+ struct irq_info hint;
char path[PATH_MAX];
char devpath[PATH_MAX];
struct user_irq_policy pol;
@@ -635,7 +640,7 @@ static void build_one_dev_entry(const char *dirname, GList *tmp_irqs)
if (new)
continue;
get_irq_user_policy(devpath, irqnum, &pol);
- if ((pol.ban == 1) || (check_for_irq_ban(devpath, irqnum, tmp_irqs))) {
+ if ((pol.ban == 1) || (check_for_irq_ban(devpath, irqnum, tmp_list))) {
add_banned_irq(irqnum, &banned_irqs);
continue;
}
@@ -647,13 +652,13 @@ static void build_one_dev_entry(const char *dirname, GList *tmp_irqs)
}
} while (entry != NULL);
closedir(msidir);
- return;
+ return new;
}
sprintf(path, "%s/%s/irq", SYSPCI_DIR, dirname);
fd = fopen(path, "r");
if (!fd)
- return;
+ return new;
if (fscanf(fd, "%d", &irqnum) < 0)
goto done;
@@ -670,7 +675,7 @@ static void build_one_dev_entry(const char *dirname, GList *tmp_irqs)
if (new)
goto done;
get_irq_user_policy(devpath, irqnum, &pol);
- if ((pol.ban == 1) || (check_for_irq_ban(path, irqnum, tmp_irqs))) {
+ if ((pol.ban == 1) || (check_for_irq_ban(path, irqnum, tmp_list))) {
add_banned_irq(irqnum, &banned_irqs);
goto done;
}
@@ -684,7 +689,56 @@ static void build_one_dev_entry(const char *dirname, GList *tmp_irqs)
done:
fclose(fd);
- return;
+ return new;
+}
+
+void find_irq_dev_path(int irq, char *dirname, int length)
+{
+ char cmd[PATH_MAX + 128];
+ FILE *output = NULL;
+ char path[PATH_MAX];
+ char buffer[128];
+ char *brc = NULL;
+
+ memset(dirname, 0, length);
+ /* Return defaults if irq is 0 */
+ if (!irq)
+ return;
+
+ sprintf(path, "%s/*/msi_irqs", SYSPCI_DIR);
+ sprintf(cmd, "exec find %s -type f -name %d | awk -F '/' '{print $6}' ", path, irq);
+ output = popen(cmd, "r");
+ if (!output) {
+ log(TO_CONSOLE, LOG_WARNING, "Unable to execute IRQ %d path %s\n", irq, path);
+ return;
+ }
+
+ brc = fgets(buffer, 128, output);
+ if (brc) {
+ log(TO_CONSOLE, LOG_INFO, "msi_irqs IRQ %d dirname is %s\n", irq, brc);
+ strncpy(dirname, brc, length);
+ pclose(output);
+ return;
+ }
+ pclose(output);
+
+ sprintf(path, "%s/*/irq", SYSPCI_DIR);
+ sprintf(cmd, "exec grep -w %d %s | awk -F '/' '{print $6}' ", irq, path);
+ output = popen(cmd, "r");
+ if (!output) {
+ log(TO_CONSOLE, LOG_WARNING, "Unable to execute IRQ %d path %s\n", irq, path);
+ return;
+ }
+
+ brc = fgets(buffer, 128, output);
+ if (brc) {
+ log(TO_CONSOLE, LOG_INFO, "IRQ %d dirname is %s\n", irq, brc);
+ strncpy(dirname, brc, length);
+ pclose(output);
+ return;
+ }
+ pclose(output);
+
}
static void free_irq(struct irq_info *info, void *data __attribute__((unused)))
@@ -692,6 +750,42 @@ static void free_irq(struct irq_info *info, void *data __attribute__((unused)))
free(info);
}
+static void remove_no_existing_irq(struct irq_info *info, void *data __attribute__((unused)))
+{
+ GList *entry = NULL;
+
+ if (info->existing) {
+ 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(banned_irqs, info, compare_ints);
+ if (entry)
+ banned_irqs = g_list_delete_link(banned_irqs, 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);
+}
+
void free_irq_db(void)
{
for_each_irq(NULL, free_irq, NULL);
@@ -711,14 +805,14 @@ void free_cl_opts(void)
g_list_free(banned_irqs);
}
-static void add_new_irq(int irq, struct irq_info *hint, GList *proc_interrupts)
+struct irq_info *add_new_irq(int irq, struct irq_info *hint, GList *proc_interrupts)
{
- struct irq_info *new;
+ struct irq_info *new = NULL;
struct user_irq_policy pol;
new = get_irq_info(irq);
if (new)
- return;
+ return new;
/* Set NULL devpath for the irq has no sysfs entries */
get_irq_user_policy(NULL, irq, &pol);
@@ -730,6 +824,8 @@ static void add_new_irq(int irq, struct irq_info *hint, GList *proc_interrupts)
if (!new)
log(TO_CONSOLE, LOG_WARNING, "add_new_irq: Failed to add irq %d\n", irq);
+
+ return new;
}
static void add_missing_irq(struct irq_info *info, void *attr)
diff --git a/irqbalance.c b/irqbalance.c
index 2f699b8..e375a1a 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -238,7 +238,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 8d5b329..73737ed 100644
--- a/irqbalance.h
+++ b/irqbalance.h
@@ -107,6 +107,11 @@ extern void free_cl_opts(void);
extern void add_cl_banned_module(char *modname);
#define irq_numa_node(irq) ((irq)->numa_node)
+/* huawei */
+extern struct irq_info *build_one_dev_entry(const char *dirname, GList *tmp_list);
+extern void find_irq_dev_path(int irq, char *dirname, int length);
+extern struct irq_info *add_new_irq(int irq, struct irq_info *hint, GList *proc_interrupts);
+extern void clear_no_existing_irqs(void);
/*
* Generic object functions
diff --git a/procinterrupts.c b/procinterrupts.c
index eb84a1c..d384860 100644
--- a/procinterrupts.c
+++ b/procinterrupts.c
@@ -142,6 +142,52 @@ static void guess_arm_irq_hints(char *name, struct irq_info *info)
}
#endif
+static 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
+ /* 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;
+ 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->name = strdupa(irq_mod);
+}
+
GList* collect_full_irq_list()
{
@@ -149,10 +187,6 @@ GList* collect_full_irq_list()
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)
@@ -168,7 +206,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;
@@ -186,45 +220,13 @@ GList* collect_full_irq_list()
continue;
savedline = strdup(line);
- 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;
c++;
number = strtoul(line, NULL, 10);
info = calloc(sizeof(struct irq_info), 1);
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 = strdupa(irq_mod);
+ init_irq_class_and_type(savedline, info, number);
tmp_list = g_list_append(tmp_list, info);
}
free(savedline);
@@ -230,6 +235,14 @@ GList* collect_full_irq_list()
return tmp_list;
}
+/* parsing /proc/interrrupts to detect whether removed and reinserted IRQ
+* device happened or not. If yes, then IRQs have to be rescanning again;
+* However, in order to keep no impact on online running IRQs performance stable,
+* removed and reinserted IRQ added back into rebalance_irq_list,
+* for irq load re-calculation instead of trigger rescanning all IRQs.
+* specially, when a new IRQ is detected, it has to be checked what devpath is,
+* then it is added into database accordingly.
+*/
void parse_proc_interrupts(void)
{
FILE *file;
@@ -253,7 +266,9 @@ void parse_proc_interrupts(void)
uint64_t count;
char *c, *c2;
struct irq_info *info;
+ struct irq_info tmp_info;
char savedline[1024];
+ char dirname[PATH_MAX] = {'\0'};
if (getline(&line, &size, file)==0)
break;
@@ -281,9 +296,24 @@ void parse_proc_interrupts(void)
info = get_irq_info(number);
if (!info) {
- need_rescan = 1;
- break;
+ find_irq_dev_path(number, dirname, PATH_MAX);
+ if (strlen(dirname) > 0) {
+ info = build_one_dev_entry(dirname, NULL);
+ log(TO_CONSOLE, LOG_INFO, "new IRQ %d added into database, dirname %s\n", number, dirname);
+ } else {
+ init_irq_class_and_type(savedline, &tmp_info, number);
+ info = add_new_irq(number, &tmp_info, NULL);
+ }
+
+ if (info) {
+ force_rebalance_irq(info, NULL);
+ log(TO_CONSOLE, LOG_INFO, "new IRQ %d added into rebalance list\n", number);
+ } else {
+ need_rescan = 1;
+ break;
+ }
}
+ info->existing = 1;
count = 0;
cpunr = 0;
@@ -307,17 +337,19 @@ void parse_proc_interrupts(void)
* cause an overflow and IRQ won't be rebalanced again
*/
if (count < info->irq_count) {
- need_rescan = 1;
- break;
+ log(TO_CONSOLE, LOG_INFO, "Removed and reinserted IRQ %d added into rebalance list\n", number);
+ force_rebalance_irq(info, NULL);
}
- info->last_irq_count = info->irq_count;
+ info->last_irq_count = info->irq_count;
info->irq_count = count;
/* is interrupt MSI based? */
if ((info->type == IRQ_TYPE_MSI) || (info->type == IRQ_TYPE_MSIX))
msi_found_in_sysfs = 1;
- }
+ }
+ clear_no_existing_irqs();
+
if ((proc_int_has_msi) && (!msi_found_in_sysfs) && (!need_rescan)) {
log(TO_ALL, LOG_WARNING, "WARNING: MSI interrupts found in /proc/interrupts\n");
log(TO_ALL, LOG_WARNING, "But none found in sysfs, you need to update your kernel\n");
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;
};
--
1.8.3.1

View File

@ -0,0 +1,30 @@
From a8ad43cc682e268c9f35633a15636222b6933649 Mon Sep 17 00:00:00 2001
From:Xia Shuang <xiashuang1@huawei.com>
Date: Thu, 29 Aug 2019 14:31:25 +0800
Subject: [PATCH] fix guess_arm_irq_hints
in aarch64, irqbalance will guess
irq's class and type according to irq's name, but it did't work properly now,
a irq's name will be matched twice and class will always be IRQ_OTHER. such
as a nic interrupt, the debug log will be:
IRQ eth3-tx0 (109) guessed as class 5
IRQ eth3-tx0 (109) guessed as class 0
irq's class should be IRQ_GBETH but is IRQ_GBETH.
---
procinterrupts.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/procinterrupts.c b/procinterrupts.c
index 2088c58..3898b10 100644
--- a/procinterrupts.c
+++ b/procinterrupts.c
@@ -137,6 +137,7 @@ static void guess_arm_irq_hints(char *name, struct irq_info *info)
if (matches[i].refine_match)
matches[i].refine_match(name, info);
log(TO_ALL, LOG_DEBUG, "IRQ %s(%d) guessed as class %d\n", name, info->irq,info->class);
+ break;
}
}
--
2.21.0.windows.1

View File

@ -0,0 +1,123 @@
From d57caa98c082fb3bf746b0877aa368544e8e62dc Mon Sep 17 00:00:00 2001
From: Zengruan Ye <yezengruan@huawei.com>
Date: Mon, 15 Jul 2019 21:37:39 +0800
Subject: [PATCH 4/6] bugfix: irqbalance: fix wrong pid value in pid file
If irqbalance is killed by SIGKILL or SIGTERM,
after restarting irqbalance, the pid in pid file is
wrong, that's because the way we forbid starting
multiple irqbalance instances is wrong.
Here we use fcntl to lock pid file to forbid another instance
been launched.
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
---
irqbalance.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 73 insertions(+), 8 deletions(-)
diff --git a/irqbalance.c b/irqbalance.c
index 40ec65c..27cf2eb 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -584,6 +584,77 @@ int init_socket()
return 0;
}
+static int create_lock_pidfile(const char *lockfile)
+{
+ struct flock lock = { 0 };
+ char pid_s[16] = { 0 };
+ int lf = 0;
+ int err = -1;
+
+ lf = open(lockfile, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
+ if (lf == -1) {
+ err = -errno;
+ log(TO_ALL, LOG_WARNING, "irqbalance (%u): Can't create lock file.\n",
+ getpid());
+ return err;
+ }
+
+retry_fcntl:
+ lock.l_type = F_WRLCK;
+ lock.l_start = 0;
+ lock.l_whence = SEEK_SET;
+ lock.l_len = 0;
+ if (fcntl (lf, F_SETLK, &lock) == -1) {
+ err = -errno;
+ switch (errno) {
+ case EINTR:
+ goto retry_fcntl;
+ case EAGAIN:
+ case EACCES:
+ log(TO_ALL, LOG_WARNING, "irqbalance (%u): Another instance is"
+ " already running, errno:%d.\n", getpid(), errno);
+ goto error_close;
+ default:
+ log(TO_ALL, LOG_WARNING, "irqbalance (%u): Can't aquire lock."
+ " errno %d.\n", getpid(), errno);
+ goto error_close;
+ }
+ }
+
+ if (ftruncate(lf, 0) == -1) {
+ err = -errno;
+ log(TO_ALL, LOG_WARNING, "irqbalance (%u): Can't truncate lock file."
+ " errno: %d.\n", getpid(), errno);
+ goto error_close_unlink;
+ }
+ if (snprintf(pid_s, sizeof(pid_s), "%u\n", getpid()) < 0) {
+ log(TO_ALL, LOG_WARNING, "irqbalance (%u): Can't printf pid string.\n", getpid());
+ err = -1;
+ goto error_close_unlink;
+ }
+
+retry_write:
+ if ((size_t)write(lf, pid_s, strlen (pid_s)) != strlen (pid_s)) {
+ err = -errno;
+ if (errno == EINTR) {
+ goto retry_write;
+ } else {
+ log(TO_ALL, LOG_WARNING, "irqbalance (%u): Can't write pid to lock"
+ " file. errno %d\n", getpid(), errno);
+ goto error_close_unlink;
+ }
+ }
+
+ return 0;
+
+error_close_unlink:
+ (void) unlink(lockfile);
+
+error_close:
+ close(lf);
+ return err;
+}
+
int main(int argc, char** argv)
{
struct sigaction action, hupaction;
@@ -676,17 +747,11 @@ int main(int argc, char** argv)
}
if (!foreground_mode) {
- int pidfd = -1;
if (daemon(0,0))
exit(EXIT_FAILURE);
/* Write pidfile */
- if (pidfile && (pidfd = open(pidfile,
- O_WRONLY | O_CREAT | O_EXCL | O_TRUNC,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) >= 0) {
- char str[16];
- snprintf(str, sizeof(str), "%u\n", getpid());
- write(pidfd, str, strlen(str));
- close(pidfd);
+ if (pidfile && create_lock_pidfile(pidfile) < 0) {
+ exit(EXIT_FAILURE);
}
}
--
1.8.3.1

View File

@ -0,0 +1,108 @@
From 3eab5a9cee8a3641988778b676caa4cf9dcb14ab Mon Sep 17 00:00:00 2001
From: xiashuang <xiashuang1@huawei.com>
Date: Sun, 11 Aug 2019 23:48:50 -0400
Subject: [PATCH] Prevent inserting a duplicate entry to avoid list chaos
Introduced by huawei-bugfix-force-irq-into-rebalance-list-when-irq-removed-and-reinserted.patch
and huawei-feature-introduce-verifyhint-to-detect-hint-variation.patch, irq may want be inserted to
rebalance list more then once, and we need to prevent this. we developped a solution in
huawei-bugfix-fix-two-same-irq-insert-to-list.patch, but we are likely to call irq_in_rebalance_list.
this patch remove the code in huawei-bugfix-fix-two-same-irq-insert-to-list.patch and add protection
in force_rebalance_irq instead.
---
classify.c | 13 +------------
irqbalance.c | 4 ++++
irqbalance.h | 3 ++-
procinterrupts.c | 8 ++------
4 files changed, 9 insertions(+), 19 deletions(-)
diff --git a/classify.c b/classify.c
index 34a2e9f..65aeae2 100644
--- a/classify.c
+++ b/classify.c
@@ -260,7 +260,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;
@@ -293,17 +293,6 @@ static void add_banned_irq(int irq, GList **list, int extra_flag)
return;
}
-int irq_in_rebalance_list(int irq)
-{
- GList *entry = NULL;
- struct irq_info find = {0};
-
- find.irq = irq;
- entry = g_list_find_custom(rebalance_irq_list, &find, compare_ints);
-
- return entry ? 1 : 0;
-}
-
#ifdef AARCH64
void add_banned_list_irq(int irq)
{
diff --git a/irqbalance.c b/irqbalance.c
index 6e9de88..fd72d44 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -314,6 +314,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
diff --git a/irqbalance.h b/irqbalance.h
index b6bdebd..120bc9b 100644
--- a/irqbalance.h
+++ b/irqbalance.h
@@ -114,7 +114,8 @@ extern void free_cl_opts(void);
extern void add_cl_banned_module(char *modname);
#define irq_numa_node(irq) ((irq)->numa_node)
extern void force_rebalance_irq(struct irq_info *info, void *data __attribute__((unused)));
-int irq_in_rebalance_list(int irq);
+extern gint compare_ints(gconstpointer a, gconstpointer b);
+
/* huawei */
extern struct irq_info *build_one_dev_entry(const char *dirname, GList *tmp_list);
extern void find_irq_dev_path(int irq, char *dirname, int length);
diff --git a/procinterrupts.c b/procinterrupts.c
index 6b25fef..4bc68d7 100644
--- a/procinterrupts.c
+++ b/procinterrupts.c
@@ -446,9 +446,7 @@ void parse_proc_interrupts(void)
*/
if (count < info->irq_count) {
log(TO_CONSOLE, LOG_INFO, "Removed and reinserted IRQ %d added into rebalance list\n", number);
- if (!irq_in_rebalance_list(info->irq)) {
- force_rebalance_irq(info, NULL);
- }
+ force_rebalance_irq(info, NULL);
}
info->last_irq_count = info->irq_count;
@@ -702,9 +700,7 @@ void update_affinity_hint(struct irq_info *info, void *data __attribute__((unuse
cpumask_parse_user(line, len, current_affinity_hint);
if (!cpus_equal(current_affinity_hint, info->affinity_hint)) {
cpumask_copy(info->affinity_hint, current_affinity_hint);
- if (!irq_in_rebalance_list(info->irq)) {
- force_rebalance_irq(info, data);
- }
+ force_rebalance_irq(info, data);
log(TO_ALL, LOG_INFO, "IRQ(%d): affinity hint modified\n", info->irq);
}
}
--
1.8.3.1

View File

@ -0,0 +1,151 @@
From 21b69dd5d3212026881825901442a51eeecd3dad Mon Sep 17 00:00:00 2001
From: Yun Wu <wuyun.wu@huawei.com>
Date: Tue, 25 Aug 2015 19:47:58 +0800
Subject: [PATCH] use policy prior to the default values
Currently user-defined policies against non-PCI devices' interrupts
are not working properly.
For example, when trying to set "balance_level=core" for a non-PCI
device interrupt which is classified as "other", will result in
the level of "package" because overrided in add_new_irq().
This patch fixes this by restricting irq info initializations in
add_one_irq_to_db(), which requires a change on its parameters.
Signed-off-by: Yun Wu <wuyun.wu@huawei.com>
---
classify.c | 49 +++++++++++++++++++++----------------------------
1 file changed, 21 insertions(+), 28 deletions(-)
diff --git a/classify.c b/classify.c
index df8a89b..9868633 100644
--- a/classify.c
+++ b/classify.c
@@ -342,10 +342,10 @@ void add_cl_banned_module(char *modname)
* related device. NULL devpath means no sysfs entries for
* this irq.
*/
-static struct irq_info *add_one_irq_to_db(const char *devpath, int irq, struct user_irq_policy *pol)
+static struct irq_info *add_one_irq_to_db(const char *devpath, struct irq_info *hint, struct user_irq_policy *pol)
{
- int irq_class = IRQ_OTHER;
- struct irq_info *new, find;
+ int irq = hint->irq;
+ struct irq_info *new;
int numa_node;
char path[PATH_MAX];
FILE *fd;
@@ -357,8 +357,7 @@ static struct irq_info *add_one_irq_to_db(const char *devpath, int irq, struct u
/*
* First check to make sure this isn't a duplicate entry
*/
- find.irq = irq;
- entry = g_list_find_custom(interrupts_db, &find, compare_ints);
+ entry = g_list_find_custom(interrupts_db, hint, compare_ints);
if (entry) {
log(TO_CONSOLE, LOG_INFO, "DROPPING DUPLICATE ENTRY FOR IRQ %d on path %s\n", irq, devpath);
return NULL;
@@ -374,23 +373,24 @@ static struct irq_info *add_one_irq_to_db(const char *devpath, int irq, struct u
return NULL;
new->irq = irq;
- new->class = IRQ_OTHER;
+ new->type = hint->type;
+ new->class = hint->class;
interrupts_db = g_list_append(interrupts_db, new);
/* Some special irqs have NULL devpath */
if (devpath != NULL) {
/* Map PCI class code to irq class */
- irq_class = get_irq_class(devpath);
+ int irq_class = get_irq_class(devpath);
if (irq_class < 0)
goto get_numa_node;
+ new->class = irq_class;
}
- new->class = irq_class;
if (pol->level >= 0)
new->level = pol->level;
else
- new->level = map_class_to_level[irq_class];
+ new->level = map_class_to_level[new->class];
get_numa_node:
numa_node = -1;
@@ -611,13 +611,16 @@ static void build_one_dev_entry(const char *dirname, GList *tmp_irqs)
DIR *msidir;
FILE *fd;
int irqnum;
- struct irq_info *new;
+ struct irq_info *new, hint;
char path[PATH_MAX];
char devpath[PATH_MAX];
struct user_irq_policy pol;
sprintf(path, "%s/%s/msi_irqs", SYSPCI_DIR, dirname);
sprintf(devpath, "%s/%s", SYSPCI_DIR, dirname);
+
+ /* Needs to be further classified */
+ hint.class = IRQ_OTHER;
msidir = opendir(path);
@@ -636,10 +639,11 @@ static void build_one_dev_entry(const char *dirname, GList *tmp_irqs)
add_banned_irq(irqnum, &banned_irqs);
continue;
}
- new = add_one_irq_to_db(devpath, irqnum, &pol);
+ hint.irq = irqnum;
+ hint.type = IRQ_TYPE_MSIX;
+ new = add_one_irq_to_db(devpath, &hint, &pol);
if (!new)
continue;
- new->type = IRQ_TYPE_MSIX;
}
} while (entry != NULL);
closedir(msidir);
@@ -671,10 +675,11 @@ static void build_one_dev_entry(const char *dirname, GList *tmp_irqs)
goto done;
}
- new = add_one_irq_to_db(devpath, irqnum, &pol);
+ hint.irq = irqnum;
+ hint.type = IRQ_TYPE_LEGACY;
+ new = add_one_irq_to_db(devpath, &hint, &pol);
if (!new)
goto done;
- new->type = IRQ_TYPE_LEGACY;
}
done:
@@ -721,22 +726,10 @@ static void add_new_irq(int irq, struct irq_info *hint, GList *proc_interrupts)
add_banned_irq(irq, &banned_irqs);
new = get_irq_info(irq);
} else
- new = add_one_irq_to_db(NULL, irq, &pol);
+ new = add_one_irq_to_db(NULL, hint, &pol);
- if (!new) {
+ if (!new)
log(TO_CONSOLE, LOG_WARNING, "add_new_irq: Failed to add irq %d\n", irq);
- return;
- }
-
- /*
- * Override some of the new irq defaults here
- */
- if (hint) {
- new->type = hint->type;
- new->class = hint->class;
- }
-
- new->level = map_class_to_level[new->class];
}
static void add_missing_irq(struct irq_info *info, void *attr)
--
1.8.3.1

View File

@ -0,0 +1,28 @@
From ff28f445a0808677c983d85a3b8331e4c090d70d Mon Sep 17 00:00:00 2001
From: Neil Horman <nhorman@tuxdriver.com>
Date: Tue, 29 May 2018 10:27:37 -0400
Subject: [PATCH 084/112] classify: remove unused label
A recent refactoring in commit a4fbf90c2395ffa13176e8b002b7ef89a0ffc667
left us with an unused label 'free' in rebuild_irq_db, just remove it
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
---
classify.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/classify.c b/classify.c
index 3394823..3136fc3 100644
--- a/classify.c
+++ b/classify.c
@@ -777,7 +777,6 @@ void rebuild_irq_db(void)
for_each_irq(tmp_irqs, add_missing_irq, interrupts_db);
-free:
g_list_free_full(tmp_irqs, free);
}
--
1.8.3.1

View File

@ -0,0 +1,91 @@
From 0605850acfce6f2ae23759618604f02f946026c2 Mon Sep 17 00:00:00 2001
From: Neil Horman <nhorman@tuxdriver.com>
Date: Tue, 29 May 2018 10:26:00 -0400
Subject: [PATCH 129/152] cputree: adjust snprintf sizes to avoid gcc warnings
Gcc detects potential overruns in our use of PATH_MAX arrays when
parsing cpu topology. This commit corrects those issues by ensuing that
the print size is no longer than the array size in all cases
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
---
cputree.c | 21 ++++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/cputree.c b/cputree.c
index d09af43..c88143f 100644
--- a/cputree.c
+++ b/cputree.c
@@ -241,7 +241,8 @@ static struct topo_obj* add_cpu_to_cache_domain(struct topo_obj *cpu,
return cache;
}
-
+
+#define ADJ_SIZE(r,s) PATH_MAX-strlen(r)-strlen(#s)
static void do_one_cpu(char *path)
{
struct topo_obj *cpu;
@@ -256,7 +257,7 @@ static void do_one_cpu(char *path)
unsigned int max_cache_index, cache_index, cache_stat;
/* skip offline cpus */
- snprintf(new_path, PATH_MAX, "%s/online", path);
+ snprintf(new_path, ADJ_SIZE(path,"/online"), "%s/online", path);
file = fopen(new_path, "r");
if (file) {
char *line = NULL;
@@ -299,7 +300,8 @@ static void do_one_cpu(char *path)
/* try to read the package mask; if it doesn't exist assume solitary */
- snprintf(new_path, PATH_MAX, "%s/topology/core_siblings", path);
+ snprintf(new_path, ADJ_SIZE(path, "/topology/core_siblings"),
+ "%s/topology/core_siblings", path);
file = fopen(new_path, "r");
cpu_set(cpu->number, package_mask);
if (file) {
@@ -311,7 +313,8 @@ static void do_one_cpu(char *path)
free(line);
}
/* try to read the package id */
- snprintf(new_path, PATH_MAX, "%s/topology/physical_package_id", path);
+ snprintf(new_path, ADJ_SIZE(path, "/topology/physical_package_id"),
+ "%s/topology/physical_package_id", path);
file = fopen(new_path, "r");
if (file) {
char *line = NULL;
@@ -329,7 +332,9 @@ static void do_one_cpu(char *path)
cache_index = 1;
do {
struct stat sb;
- snprintf(new_path, PATH_MAX, "%s/cache/index%d/shared_cpu_map", path, cache_index);
+ /* Extra 10 subtraction is for the max character length of %d */
+ snprintf(new_path, ADJ_SIZE(path, "/cache/index%d/shared_cpu_map") - 10,
+ "%s/cache/index%d/shared_cpu_map", path, cache_index);
cache_stat = stat(new_path, &sb);
if (!cache_stat) {
max_cache_index = cache_index;
@@ -340,7 +345,9 @@ static void do_one_cpu(char *path)
} while(!cache_stat);
if (max_cache_index > 0) {
- snprintf(new_path, PATH_MAX, "%s/cache/index%d/shared_cpu_map", path, max_cache_index);
+ /* Extra 10 subtraction is for the max character length of %d */
+ snprintf(new_path, ADJ_SIZE(path, "/cache/index%d/shared_cpu_map") - 10,
+ "%s/cache/index%d/shared_cpu_map", path, max_cache_index);
file = fopen(new_path, "r");
if (file) {
char *line = NULL;
@@ -505,7 +512,7 @@ void parse_cpu_tree(void)
sscanf(entry->d_name, "cpu%d%c", &num, &pad) == 1 &&
!strchr(entry->d_name, ' ')) {
char new_path[PATH_MAX];
- sprintf(new_path, "/sys/devices/system/cpu/%s", entry->d_name);
+ snprintf(new_path, PATH_MAX, "/sys/devices/system/cpu/%s", entry->d_name);
do_one_cpu(new_path);
}
} while (entry);
--
1.8.3.1

View File

@ -0,0 +1,476 @@
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 | 31 +++++----
irqbalance.h | 2 +-
misc/irqbalance.service | 2 +-
placement.c | 3 +-
procinterrupts.c | 3 +-
rules_config.c | 170 ++++++++++++++++++++++++++++++++++++++++++++++++
rules_config.h | 38 +++++++++++
9 files changed, 260 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;
+ }
+
}
diff --git a/irqbalance.c b/irqbalance.c
index 21d578a..d41753c 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -148,6 +148,7 @@ struct option lopts[] = {
{"interval", 1 , NULL, 't'},
{"version", 0, NULL, 'V'},
{"verifyhint", 1, NULL, 'v'},
+ {"rulesconfig", 1, NULL, 'r'},
{0, 0, 0, 0}
};
@@ -155,7 +156,7 @@ static void usage(void)
{
log(TO_CONSOLE, LOG_INFO, "irqbalance [--oneshot | -o] [--debug | -d] [--foreground | -f] [--journal | -j] [--hintpolicy | -h <subset>]\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>] [--verifyhint= | -v n]\n");
+ log(TO_CONSOLE, LOG_INFO, " [--pid= | -s <file>] [--deepestcache= | -c <n>] [--interval= | -t <n>] [--verifyhint= | -v n] [--rulesconfig= | -r <config>]\n");
}
static void version(void)
@@ -170,7 +171,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:h:v:",
+ "odfji:p:s:c:b:l:m:t:V:h:v:r:",
lopts, &longind)) != -1) {
switch(opt) {
@@ -268,6 +269,9 @@ static void parse_command_line(int argc, char **argv)
}
reset_verify_countdown();
break;
+ case 'r':
+ rules_config_file = strdup(optarg);
+ break;
}
}
}
@@ -586,6 +590,19 @@ int main(int argc, char** argv)
HZ = 100;
}
+ if (!foreground_mode) {
+ if (daemon(0,0))
+ exit(EXIT_FAILURE);
+ /* Write pidfile */
+ if (pidfile && create_lock_pidfile(pidfile) < 0) {
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (read_user_policy_config() != 0) {
+ log(TO_ALL, LOG_WARNING, "Read user policy config fail.\n");
+ }
+
build_object_tree();
if (debug_mode)
dump_object_tree();
@@ -600,14 +617,6 @@ int main(int argc, char** argv)
exit(EXIT_SUCCESS);
}
- if (!foreground_mode) {
- if (daemon(0,0))
- exit(EXIT_FAILURE);
- /* Write pidfile */
- if (pidfile && create_lock_pidfile(pidfile) < 0) {
- exit(EXIT_FAILURE);
- }
- }
action.sa_handler = handler;
sigemptyset(&action.sa_mask);
@@ -640,7 +649,7 @@ int main(int argc, char** argv)
log(TO_CONSOLE, LOG_WARNING, "WARNING: Failed to create irqbalance socket thread, return %d.\n", err);
return EXIT_FAILURE;
}
-
+ log(TO_ALL, LOG_INFO, "irqbalance start scan.\n");
while (keep_going) {
cond_sleep();
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,170 @@
+/*
+ * Copyright (C) 2019. Huawei Technologies Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the MuLan PSL v1.
+ *
+ * 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 MuLan PSL v1 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,38 @@
+/*
+ * Copyright (C) 2019. Huawei Technologies Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the MuLan PSL v1.
+ *
+ * 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 MuLan PSL v1 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

View File

@ -0,0 +1,506 @@
From 8541a67cdc3cbaf5c6ed04e9a3b3e2c3f584cb33 Mon Sep 17 00:00:00 2001
From: xiahuang <xiashuang1@huawei.com>
Date: Thu, 21 Mar 2019 19:08:17 -0400
Subject: [PATCH 2/2]
feature-introduce-verifyhint-to-detect-hint-variation
adapt by xiashuang xiashuang1@huawei.com when upgrade to 1.4.0
---
activate.c | 24 +++++-----
classify.c | 18 ++++++--
cpumask.h | 7 +++
irqbalance.c | 135 +++++++++++++++++++++++++++++++++++++++++++------------
irqbalance.h | 5 +++
placement.c | 14 ++++++
procinterrupts.c | 57 +++++++++++++++++++++++
types.h | 1 +
8 files changed, 217 insertions(+), 44 deletions(-)
diff --git a/activate.c b/activate.c
index 8fd3dd0..1c4b867 100644
--- a/activate.c
+++ b/activate.c
@@ -61,26 +61,26 @@ static void activate_mapping(struct irq_info *info, void *data __attribute__((un
char buf[PATH_MAX];
FILE *file;
cpumask_t applied_mask;
- int valid_mask = 0;
- /*
- * only activate mappings for irqs that have moved
- */
- if (!info->moved)
+ if (!info->assigned_obj)
return;
- if (info->assigned_obj) {
- applied_mask = info->assigned_obj->mask;
- valid_mask = 1;
+ applied_mask = 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)) {
+ log(TO_ALL, LOG_WARNING, "irq %d affinity_hint subset empty\n", info->irq);
+ return;
+ }
+ }
}
/*
* Don't activate anything for which we have an invalid mask
*/
- if (!valid_mask || check_affinity(info, applied_mask))
- return;
-
- if (!info->assigned_obj)
+ if (check_affinity(info, applied_mask))
return;
sprintf(buf, "/proc/irq/%i/smp_affinity", info->irq);
diff --git a/classify.c b/classify.c
index 30a8d2a..aa391f4 100644
--- a/classify.c
+++ b/classify.c
@@ -66,8 +66,6 @@ struct pci_info {
#define PCI_SUB_DEVICE_EMC_0568 0x0568
#define PCI_SUB_DEVICE_EMC_dd00 0xdd00
-extern void force_rebalance_irq(struct irq_info *info, void *data __attribute__((unused)));
-
/*
* Apply software workarounds for some special devices
*
@@ -414,7 +412,7 @@ get_numa_node:
fd = fopen(path, "r");
if (!fd) {
cpus_setall(new->cpumask);
- goto out;
+ goto assign_affinity_hint;
}
lcpu_mask = NULL;
ret = getline(&lcpu_mask, &blen, fd);
@@ -426,6 +424,20 @@ get_numa_node:
}
free(lcpu_mask);
+assign_affinity_hint:
+ cpus_clear(new->affinity_hint);
+ sprintf(path, "/proc/irq/%d/affinity_hint", irq);
+ fd = fopen(path, "r");
+ if (!fd)
+ goto out;
+ lcpu_mask = NULL;
+ ret = getline(&lcpu_mask, &blen, fd);
+ fclose(fd);
+ if (ret <= 0)
+ goto out;
+ cpumask_parse_user(lcpu_mask, ret, new->affinity_hint);
+ free(lcpu_mask);
+
out:
log(TO_CONSOLE, LOG_INFO, "Adding IRQ %d to database\n", irq);
return new;
diff --git a/cpumask.h b/cpumask.h
index 0774a88..8dd3703 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?
@@ -150,6 +151,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/irqbalance.c b/irqbalance.c
index e375a1a..bf9a2e4 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -61,10 +61,38 @@ char *banscript = NULL;
char *polscript = NULL;
long HZ;
int sleep_interval = SLEEP_INTERVAL;
-GMainLoop *main_loop;
+int hint_enabled = 0;
+int poll_hint_interval = SLEEP_INTERVAL / 5;
+unsigned int next_verify, next_balance;
char *banned_cpumask_from_ui = NULL;
+static inline void reset_verify_countdown(void)
+{
+ next_verify = poll_hint_interval;
+}
+
+static inline void reset_balance_countdown(void)
+{
+ next_balance = sleep_interval;
+}
+
+static inline int need_verify(void)
+{
+ return !(poll_hint_interval - next_verify);
+}
+
+static inline int need_balance(void)
+{
+ return !(sleep_interval - next_balance);
+}
+
+static inline void reset_countdown(void)
+{
+ reset_verify_countdown();
+ reset_balance_countdown();
+}
+
static void sleep_approx(int seconds)
{
struct timespec ts;
@@ -79,6 +107,26 @@ static void sleep_approx(int seconds)
nanosleep(&ts, NULL);
}
+static void cond_sleep(void)
+{
+ unsigned int timeout;
+
+ if (next_verify < next_balance) {
+ timeout = next_verify;
+ next_balance -= timeout;
+ reset_verify_countdown();
+ } else if (next_verify > next_balance) {
+ timeout = next_balance;
+ next_verify -= timeout;
+ reset_balance_countdown();
+ } else {
+ timeout = next_verify;
+ reset_countdown();
+ }
+
+ sleep_approx(timeout);
+}
+
#ifdef HAVE_GETOPT_LONG
struct option lopts[] = {
{"oneshot", 0, NULL, 'o'},
@@ -95,14 +143,15 @@ struct option lopts[] = {
{"banmod", 1 , NULL, 'm'},
{"interval", 1 , NULL, 't'},
{"version", 0, NULL, 'V'},
+ {"verifyhint", 1, NULL, 'v'},
{0, 0, 0, 0}
};
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, "irqbalance [--oneshot | -o] [--debug | -d] [--foreground | -f] [--journal | -j] [--hintpolicy | -h <subset>]\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>] [--verifyhint= | -v n]\n");
}
static void version(void)
@@ -117,7 +166,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:h:v:",
lopts, &longind)) != -1) {
switch(opt) {
@@ -190,12 +239,30 @@ static void parse_command_line(int argc, char **argv)
journal_logging=1;
foreground_mode=1;
break;
- case 't':
+ case 't':
sleep_interval = strtol(optarg, NULL, 10);
if (sleep_interval < 1) {
usage();
exit(1);
}
+ reset_balance_countdown();
+ 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);
+ }
+ reset_verify_countdown();
break;
}
}
@@ -251,21 +318,18 @@ void force_rebalance_irq(struct irq_info *info, void *data __attribute__((unused
info->assigned_obj = NULL;
}
-gboolean handler(gpointer data __attribute__((unused)))
+void handler(int signum __attribute__((unused)))
{
keep_going = 0;
- g_main_loop_quit(main_loop);
- return TRUE;
}
-gboolean force_rescan(gpointer data __attribute__((unused)))
+void force_rescan(int signum __attribute__((unused)))
{
if (cycle_count)
need_rescan = 1;
- return TRUE;
}
-gboolean scan(gpointer data)
+gboolean scan()
{
log(TO_CONSOLE, LOG_INFO, "\n\n\n-----------------------------------------------------------------------------\n");
clear_work_stats();
@@ -276,7 +340,7 @@ gboolean scan(gpointer data)
if (need_rescan) {
need_rescan = 0;
cycle_count = 0;
- log(TO_CONSOLE, LOG_INFO, "Rescanning cpu topology \n");
+ reset_countdown();
clear_work_stats();
free_object_tree();
@@ -303,16 +367,9 @@ gboolean scan(gpointer data)
keep_going = 0;
cycle_count++;
- if (data != &sleep_interval) {
- data = &sleep_interval;
- g_timeout_add_seconds(sleep_interval, scan, data);
- return FALSE;
- }
-
if (keep_going) {
return TRUE;
} else {
- g_main_loop_quit(main_loop);
return FALSE;
}
}
@@ -501,6 +558,7 @@ int init_socket(char *socket_name)
int main(int argc, char** argv)
{
+ struct sigaction action, hupaction;
sigset_t sigset, old_sigset;
sigemptyset(&sigset);
@@ -600,11 +658,19 @@ int main(int argc, char** argv)
}
}
- g_unix_signal_add(SIGINT, handler, NULL);
- g_unix_signal_add(SIGTERM, handler, NULL);
- g_unix_signal_add(SIGUSR1, handler, NULL);
- g_unix_signal_add(SIGUSR2, handler, NULL);
- g_unix_signal_add(SIGHUP, force_rescan, NULL);
+ action.sa_handler = handler;
+ sigemptyset(&action.sa_mask);
+ action.sa_flags = 0;
+ sigaction(SIGINT, &action, NULL);
+ sigaction(SIGTERM, &action, NULL);
+ sigaction(SIGUSR1, &action, NULL);
+ sigaction(SIGUSR2, &action, NULL);
+
+ hupaction.sa_handler = force_rescan;
+ sigemptyset(&hupaction.sa_mask);
+ hupaction.sa_flags = 0;
+ sigaction(SIGHUP, &hupaction, NULL);
+
sigprocmask(SIG_SETMASK, &old_sigset, NULL);
#ifdef HAVE_LIBCAP_NG
@@ -624,12 +690,23 @@ int main(int argc, char** argv)
if (init_socket()) {
return EXIT_FAILURE;
}
- main_loop = g_main_loop_new(NULL, FALSE);
- int *last_interval = &sleep_interval;
- g_timeout_add_seconds(sleep_interval, scan, last_interval);
- g_main_loop_run(main_loop);
- g_main_loop_quit(main_loop);
+ while (keep_going) {
+ cond_sleep();
+
+ if (need_verify() && hint_changed()) {
+ for_each_irq(NULL, update_affinity_hint, NULL);
+ reset_countdown();
+ }
+
+ if (!need_balance()) {
+ continue;
+ }
+
+ if (!scan()) {
+ break;
+ }
+ }
free_object_tree();
free_cl_opts();
diff --git a/irqbalance.h b/irqbalance.h
index 73737ed..b8141aa 100644
--- a/irqbalance.h
+++ b/irqbalance.h
@@ -106,12 +106,17 @@ extern void migrate_irq(GList **from, GList **to, struct irq_info *info);
extern void free_cl_opts(void);
extern void add_cl_banned_module(char *modname);
#define irq_numa_node(irq) ((irq)->numa_node)
+extern void force_rebalance_irq(struct irq_info *info, void *data __attribute__((unused)));
/* huawei */
extern struct irq_info *build_one_dev_entry(const char *dirname, GList *tmp_list);
extern void find_irq_dev_path(int irq, char *dirname, int length);
extern struct irq_info *add_new_irq(int irq, struct irq_info *hint, GList *proc_interrupts);
extern void clear_no_existing_irqs(void);
+extern void update_affinity_hint(struct irq_info *info, void *data __attribute__((unused)));
+extern int hint_changed(void);
+
+extern int hint_enabled, poll_hint_interval;
/*
* Generic object functions
diff --git a/placement.c b/placement.c
index 5a82111..2085e09 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
@@ -59,6 +60,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/procinterrupts.c b/procinterrupts.c
index d384860..b446c55 100644
--- a/procinterrupts.c
+++ b/procinterrupts.c
@@ -544,3 +544,60 @@ void parse_proc_stat(void)
for_each_object(numa_nodes, compute_irq_branch_load_share, NULL);
}
+
+int hint_changed(void)
+{
+ FILE *file;
+ char *line = NULL;
+ size_t size = 0;
+ int changed = 0;
+
+ file = fopen("/proc/irq/affinity_hint_notify", "r+");
+ if (!file)
+ return changed;
+
+ if (getline(&line, &size, file) > 0 && *line != '0') {
+ fprintf(file, "Done");
+ changed = 1;
+ }
+
+ fclose(file);
+ if (line)
+ free(line);
+ return changed;
+}
+
+void update_affinity_hint(struct irq_info *info, void *data __attribute__((unused)))
+{
+ FILE *file = NULL;
+ cpumask_t current_affinity_hint;
+ char path[PATH_MAX];
+ char *line = NULL;
+ size_t size = 0;
+ ssize_t len;
+
+ if (!hint_enabled)
+ return;
+
+ cpus_clear(info->affinity_hint);
+ sprintf(path, "/proc/irq/%d/affinity_hint", info->irq);
+ file = fopen(path, "r");
+ if (!file)
+ return;
+
+ len = getline(&line, &size, file);
+ fclose(file);
+
+ if (len > 0) {
+ cpumask_parse_user(line, len, 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);
+ log(TO_ALL, LOG_INFO, "IRQ(%d): affinity hint modified\n", info->irq);
+ }
+ }
+
+ if (line)
+ free(line);
+}
+
diff --git a/types.h b/types.h
index 9693cf4..62cc2bb 100644
--- a/types.h
+++ b/types.h
@@ -66,6 +66,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;
--
1.8.3.1

View File

@ -0,0 +1,826 @@
From a7d86761f9c66eb6fb6d13b77e753d6c42b90e12 Mon Sep 17 00:00:00 2001
From: Zengruan Ye <yezengruan@huawei.com>
Date: Tue, 16 Jul 2019 00:07:36 +0800
Subject: [PATCH 6/6] feature: irqbalance: Add ability for socket communication
This will be used with user interface and also can be used as API for users
to create their own scripts on top of. The socket communication can be used
for receiving data about IRQs-to-CPUs assignments and setup, as well as
setting some options during runtime.
Socket address: /var/run/uvp_irqbalance.socket
Data to send to socket:
settings sleep <int>: set new sleep interval value
settings cpus <cpumask> <cpumask> ... : ban listed CPUs from
IRQ handling (old values are forgotten, not added to)
settings ban irqs <irq1> <irq2> ... : ban listed IRQs from balancing (old
values are forgotten, not added to)
Signed-off-by: Xu Yandong <xuyandong2@huawei.com>
---
Makefile.am | 6 +-
classify.c | 20 ++-
cputree.c | 5 +-
irqbalance.c | 164 ++----------------------
irqbalance.h | 2 +
sockapi.c | 400 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
sockapi.h | 18 +++
7 files changed, 452 insertions(+), 163 deletions(-)
create mode 100644 sockapi.c
create mode 100644 sockapi.h
diff --git a/Makefile.am b/Makefile.am
index abf1e8d..62ac482 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -30,7 +30,7 @@ UI_DIR = ui
AM_CFLAGS = $(LIBCAP_NG_CFLAGS) $(GLIB2_CFLAGS)
AM_CPPFLAGS = -I${top_srcdir} -W -Wall -Wshadow -Wformat -Wundef -D_GNU_SOURCE
noinst_HEADERS = bitmap.h constants.h cpumask.h irqbalance.h non-atomic.h \
- types.h $(UI_DIR)/helpers.h $(UI_DIR)/irqbalance-ui.h $(UI_DIR)/ui.h
+ types.h sockapi.h $(UI_DIR)/helpers.h $(UI_DIR)/irqbalance-ui.h $(UI_DIR)/ui.h
sbin_PROGRAMS = irqbalance
if IRQBALANCEUI
@@ -38,8 +38,8 @@ 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
-irqbalance_LDADD = $(LIBCAP_NG_LIBS) $(GLIB2_LIBS)
+ irqlist.c numa.c placement.c procinterrupts.c sockapi.c
+irqbalance_LDADD = $(LIBCAP_NG_LIBS) $(GLIB2_LIBS) -lpthread
if IRQBALANCEUI
irqbalance_ui_SOURCES = $(UI_DIR)/helpers.c $(UI_DIR)/irqbalance-ui.c \
$(UI_DIR)/ui.c
diff --git a/classify.c b/classify.c
index 52fd74a..1e277c4 100644
--- a/classify.c
+++ b/classify.c
@@ -37,7 +37,10 @@ static GList *interrupts_db = NULL;
static GList *banned_irqs = NULL;
GList *cl_banned_irqs = NULL;
static GList *cl_banned_modules = NULL;
-static GList *vm_banned_irqs = NULL;
+GList *vm_banned_irqs = NULL;
+
+pthread_mutex_t cl_banned_list_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t vm_banned_list_mutex = PTHREAD_MUTEX_INITIALIZER;
#define SYSFS_DIR "/sys"
#define SYSPCI_DIR "/sys/bus/pci/devices"
@@ -299,12 +302,16 @@ void add_banned_list_irq(int irq)
void add_cl_banned_irq(int irq)
{
+ irqbalance_mutex_lock(&cl_banned_list_mutex);
add_banned_irq(irq, &cl_banned_irqs, 0);
+ irqbalance_mutex_unlock(&cl_banned_list_mutex);
}
void add_vm_banned_irq(int irq)
{
+ irqbalance_mutex_lock(&vm_banned_list_mutex);
add_banned_irq(irq, &vm_banned_irqs, IRQ_FLAG_VM_BANNED);
+ irqbalance_mutex_unlock(&vm_banned_list_mutex);
}
static int is_banned_irq(int irq)
@@ -314,7 +321,9 @@ static int is_banned_irq(int irq)
find.irq = irq;
+ irqbalance_mutex_lock(&vm_banned_list_mutex);
entry = g_list_find_custom(vm_banned_irqs, &find, compare_ints);
+ irqbalance_mutex_unlock(&vm_banned_list_mutex);
if (!entry)
entry = g_list_find_custom(banned_irqs, &find, compare_ints);
@@ -586,7 +595,9 @@ static int check_for_irq_ban(char *path __attribute__((unused)), int irq, GList
* Check to see if we banned this irq on the command line
*/
find.irq = irq;
+ irqbalance_mutex_lock(&cl_banned_list_mutex);
entry = g_list_find_custom(cl_banned_irqs, &find, compare_ints);
+ irqbalance_mutex_unlock(&cl_banned_list_mutex);
if (entry)
return 1;
@@ -821,9 +832,11 @@ void free_irq_db(void)
banned_irqs = NULL;
g_list_free(rebalance_irq_list);
rebalance_irq_list = NULL;
+ irqbalance_mutex_lock(&vm_banned_list_mutex);
for_each_irq(vm_banned_irqs, free_irq, NULL);
g_list_free(vm_banned_irqs);
vm_banned_irqs = NULL;
+ irqbalance_mutex_unlock(&vm_banned_list_mutex);
}
void free_cl_opts(void)
@@ -918,8 +931,11 @@ struct irq_info *get_irq_info(int irq)
find.irq = irq;
entry = g_list_find_custom(interrupts_db, &find, compare_ints);
- if (!entry)
+ if (!entry) {
+ irqbalance_mutex_lock(&vm_banned_list_mutex);
entry = g_list_find_custom(vm_banned_irqs, &find, compare_ints);
+ irqbalance_mutex_unlock(&vm_banned_list_mutex);
+ }
if (!entry)
entry = g_list_find_custom(banned_irqs, &find, compare_ints);
diff --git a/cputree.c b/cputree.c
index 5551784..0dbb5c8 100644
--- a/cputree.c
+++ b/cputree.c
@@ -39,6 +39,7 @@
#include "irqbalance.h"
extern char *banned_cpumask_from_ui;
+extern int is_set_banned_cpumask_from_ui;
GList *cpus;
GList *cache_domains;
@@ -77,8 +78,8 @@ static void setup_banned_cpus(void)
cpus_clear(nohz_full);
/* A manually specified cpumask overrides auto-detection. */
- if (banned_cpumask_from_ui != NULL) {
- cpulist_parse(banned_cpumask_from_ui,
+ if (is_set_banned_cpumask_from_ui) {
+ cpumask_parse_user(banned_cpumask_from_ui,
strlen(banned_cpumask_from_ui), banned_cpus);
goto out;
}
diff --git a/irqbalance.c b/irqbalance.c
index 27cf2eb..6e9de88 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -34,6 +34,7 @@
#include <sys/socket.h>
#include <sys/un.h>
#include <fcntl.h>
+#include <pthread.h>
#ifdef HAVE_GETOPT_LONG
#include <getopt.h>
#endif
@@ -42,6 +43,7 @@
#include <cap-ng.h>
#endif
#include "irqbalance.h"
+#include "sockapi.h"
volatile int keep_going = 1;
volatile int ban_pci_assigned_irq = 1;
@@ -430,160 +432,6 @@ 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];
- int sock;
- int recv_size = 0;
- int valid_user = 0;
-
- struct iovec iov = { buff, 500 };
- struct msghdr msg = { 0 };
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- msg.msg_control = malloc(CMSG_SPACE(sizeof(struct ucred)));
- msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred));
-
- struct cmsghdr *cmsg;
-
- if (condition == G_IO_IN) {
- sock = accept(fd, NULL, NULL);
- if (sock < 0) {
- log(TO_ALL, LOG_WARNING, "Connection couldn't be accepted.\n");
- goto out;
- }
- if ((recv_size = recvmsg(sock, &msg, 0)) < 0) {
- log(TO_ALL, LOG_WARNING, "Error while receiving data.\n");
- goto out_close;
- }
- cmsg = CMSG_FIRSTHDR(&msg);
- if ((cmsg->cmsg_level == SOL_SOCKET) &&
- (cmsg->cmsg_type == SCM_CREDENTIALS)) {
- struct ucred *credentials = (struct ucred *) CMSG_DATA(cmsg);
- if (!credentials->uid) {
- valid_user = 1;
- }
- }
- if (!valid_user) {
- log(TO_ALL, LOG_INFO, "Permission denied for user to connect to socket.\n");
- goto out_close;
- }
-
- if (!strncmp(buff, "stats", strlen("stats"))) {
- char *stats = NULL;
- for_each_object(numa_nodes, get_object_stat, &stats);
- send(sock, stats, strlen(stats), 0);
- free(stats);
- }
- if (!strncmp(buff, "settings ", strlen("settings "))) {
- if (!(strncmp(buff + strlen("settings "), "sleep ",
- strlen("sleep ")))) {
- char *sleep_string = malloc(
- sizeof(char) * (recv_size - strlen("settings sleep ")));
- strncpy(sleep_string, buff + strlen("settings sleep "),
- recv_size - strlen("settings sleep "));
- int new_iterval = strtoul(sleep_string, NULL, 10);
- if (new_iterval >= 1) {
- sleep_interval = new_iterval;
- }
- free(sleep_string);
- } else if (!(strncmp(buff + strlen("settings "), "ban irqs ",
- strlen("ban irqs ")))) {
- char *end;
- char *irq_string = malloc(
- sizeof(char) * (recv_size - strlen("settings ban irqs ")));
- strncpy(irq_string, buff + strlen("settings ban irqs "),
- recv_size - strlen("settings ban irqs "));
- g_list_free_full(cl_banned_irqs, free);
- cl_banned_irqs = NULL;
- need_rescan = 1;
- if (!strncmp(irq_string, "NONE", strlen("NONE"))) {
- free(irq_string);
- goto out_close;
- }
- int irq = strtoul(irq_string, &end, 10);
- do {
- add_cl_banned_irq(irq);
- } while((irq = strtoul(end, &end, 10)));
- free(irq_string);
- } else if (!(strncmp(buff + strlen("settings "), "cpus ",
- strlen("cpus")))) {
- char *cpu_ban_string = malloc(
- sizeof(char) * (recv_size - strlen("settings cpus ")));
- strncpy(cpu_ban_string, buff + strlen("settings cpus "),
- recv_size - strlen("settings cpus "));
- banned_cpumask_from_ui = strtok(cpu_ban_string, " ");
- if (!strncmp(banned_cpumask_from_ui, "NULL", strlen("NULL"))) {
- banned_cpumask_from_ui = NULL;
- }
- need_rescan = 1;
- free(cpu_ban_string);
- }
- }
- if (!strncmp(buff, "setup", strlen("setup"))) {
- char banned[512];
- char *setup = calloc(strlen("SLEEP ") + 11 + 1, 1);
- snprintf(setup, strlen("SLEEP ") + 11 + 1, "SLEEP %d ", sleep_interval);
- if(g_list_length(cl_banned_irqs) > 0) {
- for_each_irq(cl_banned_irqs, get_irq_data, setup);
- }
- cpumask_scnprintf(banned, 512, banned_cpus);
- setup = realloc(setup, strlen(setup) + strlen(banned) + 7 + 1);
- snprintf(setup + strlen(setup), strlen(banned) + 7 + 1,
- "BANNED %s", banned);
- send(sock, setup, strlen(setup), 0);
- free(setup);
- }
-
-out_close:
- close(sock);
- }
-
-out:
- free(msg.msg_control);
- return TRUE;
-}
-
-int init_socket()
-{
- struct sockaddr_un addr;
- memset(&addr, 0, sizeof(struct sockaddr_un));
-
- socket_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
- if (socket_fd < 0) {
- log(TO_ALL, LOG_WARNING, "Socket couldn't be created.\n");
- return 1;
- }
-
- /*
- * First try to create a file-based socket in tmpfs. If that doesn't
- * succeed, fall back to an abstract socket (non file-based).
- */
- addr.sun_family = AF_UNIX;
- snprintf(socket_name, 64, "%s/%s%d.sock", SOCKET_TMPFS, SOCKET_PATH, getpid());
- strncpy(addr.sun_path, socket_name, sizeof(addr.sun_path));
- if (bind(socket_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
- log(TO_ALL, LOG_WARNING, "Daemon couldn't be bound to the file-based socket.\n");
-
- /* Try binding to abstract */
- memset(&addr, 0, sizeof(struct sockaddr_un));
- addr.sun_family = AF_UNIX;
- if (bind(socket_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
- log(TO_ALL, LOG_WARNING, "Daemon couldn't be bound to the abstract socket, bailing out.\n");
- return 1;
- }
- }
-
- int optval = 1;
- if (setsockopt(socket_fd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) < 0) {
- log(TO_ALL, LOG_WARNING, "Unable to set socket options.\n");
- return 1;
- }
- listen(socket_fd, 1);
- g_unix_fd_add(socket_fd, G_IO_IN, sock_handle, NULL);
- return 0;
-}
-
static int create_lock_pidfile(const char *lockfile)
{
struct flock lock = { 0 };
@@ -657,7 +505,9 @@ error_close:
int main(int argc, char** argv)
{
- struct sigaction action, hupaction;
+ int err;
+ pthread_t socket_tid;
+ struct sigaction action, hupaction;
sigset_t sigset, old_sigset;
sigemptyset(&sigset);
@@ -781,7 +631,9 @@ int main(int argc, char** argv)
parse_proc_interrupts();
parse_proc_stat();
- if (init_socket()) {
+ err = pthread_create(&socket_tid, NULL, &handle_socket_api_event, NULL);
+ if (0 != err) {
+ log(TO_CONSOLE, LOG_WARNING, "WARNING: Failed to create irqbalance socket thread, return %d.\n", err);
return EXIT_FAILURE;
}
diff --git a/irqbalance.h b/irqbalance.h
index 339e2a3..f9b554e 100644
--- a/irqbalance.h
+++ b/irqbalance.h
@@ -44,6 +44,8 @@ extern void set_msi_interrupt_numa(int number);
extern GList *rebalance_irq_list;
+void irqbalance_mutex_lock(pthread_mutex_t *lock);
+void irqbalance_mutex_unlock(pthread_mutex_t *lock);
void update_migration_status(void);
void dump_workloads(void);
void sort_irq_list(GList **list);
diff --git a/sockapi.c b/sockapi.c
new file mode 100644
index 0000000..4a0e683
--- /dev/null
+++ b/sockapi.c
@@ -0,0 +1,410 @@
+/*
+ * Copyright (C) 2019. Huawei Technologies Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the MuLan PSL v1.
+ *
+ * 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 MuLan PSL v1 for more details.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/epoll.h>
+#include <pthread.h>
+
+#include "sockapi.h"
+#include "irqbalance.h"
+
+volatile int is_set_banned_cpumask_from_ui = 0;
+
+extern char *banned_cpumask_from_ui;
+extern int socket_fd;
+extern char socket_name[64];
+extern int sleep_interval;
+extern pthread_mutex_t cl_banned_list_mutex;
+extern GList *cl_banned_irqs;
+extern pthread_mutex_t vm_banned_list_mutex;
+extern GList *vm_banned_irqs;
+extern cpumask_t banned_cpus;
+extern int keep_going;
+
+void irqbalance_mutex_lock(pthread_mutex_t *lock)
+{
+ int err = 0;
+
+ err = pthread_mutex_lock(lock);
+ if (err) {
+ log(TO_ALL, LOG_ERR, "irqbalance: err(%d) irqbalance_mutex_lock failed", err);
+ exit(-1);
+ }
+}
+
+void irqbalance_mutex_unlock(pthread_mutex_t *lock)
+{
+ int err = 0;
+
+ err = pthread_mutex_unlock(lock);
+ if (err) {
+ log(TO_ALL, LOG_ERR, "irqbalance: err(%d) irqbalance_mutex_unlock failed", err);
+ exit(-1);
+ }
+}
+
+static void fill_banned_cpus(char *cpustr, int length)
+{
+ (void)snprintf(cpustr, length, "CPU:");
+ cpumask_scnprintf(cpustr + strlen(cpustr), length - strlen(cpustr), banned_cpus);
+}
+
+static void fill_banned_irqs(char *irqstr, int length)
+{
+ GList *entry = NULL;
+ GList *next = NULL;
+ struct irq_info *info = NULL;
+
+ (void)snprintf(irqstr, length, "IRQ:");
+
+ irqbalance_mutex_lock(&cl_banned_list_mutex);
+ entry = g_list_first(cl_banned_irqs);
+ if (!entry)
+ (void)snprintf(irqstr + strlen(irqstr), length - strlen(irqstr), "None ");
+ while (entry) {
+ next = g_list_next(entry);
+ info = entry->data;
+ (void)snprintf(irqstr + strlen(irqstr), length - strlen(irqstr),
+ "%d,", info->irq);
+ entry = next;
+ }
+ irqbalance_mutex_unlock(&cl_banned_list_mutex);
+
+ (void)snprintf(irqstr + strlen(irqstr) - 1, length - strlen(irqstr), " PCI:");
+
+ irqbalance_mutex_lock(&vm_banned_list_mutex);
+ entry = g_list_first(vm_banned_irqs);
+ if (!entry)
+ (void)snprintf(irqstr + strlen(irqstr), length - strlen(irqstr), "None");
+ while (entry) {
+ next = g_list_next(entry);
+ info = entry->data;
+ (void)snprintf(irqstr + strlen(irqstr), length - strlen(irqstr),
+ "%d,", info->irq);
+ entry = next;
+ }
+ irqbalance_mutex_unlock(&vm_banned_list_mutex);
+}
+
+static int send_msg(int fd, char* buf, int len)
+{
+ int ret = -1;
+
+ do {
+ ret = send(fd, buf, len, 0);
+ } while ((ret <= 0) && (errno == EINTR));
+
+ return ret;
+}
+
+static int setnonblocking(int fd)
+{
+ if (fcntl(fd, F_SETFL, fcntl(socket_fd, F_GETFD, 0)|O_NONBLOCK) < 0) {
+ return -1;
+ }
+ return 0;
+}
+
+static void prase_banned_irq_string(char *irq_string)
+{
+ char *end = NULL;
+ char *last = irq_string;
+ int irq;
+
+ irqbalance_mutex_lock(&cl_banned_list_mutex);
+ g_list_free_full(cl_banned_irqs, free);
+ cl_banned_irqs = NULL;
+ irqbalance_mutex_unlock(&cl_banned_list_mutex);
+
+ log(TO_ALL, LOG_INFO, "Ban irqs(%s) online.\n", irq_string);
+ if (!strncmp(irq_string, "NONE", strlen("NONE"))) {
+ return;
+ }
+
+ irq = strtoul(irq_string, &end, 10);
+ while (last != end) {
+ add_cl_banned_irq(irq);
+ log(TO_ALL, LOG_INFO, "add banned irq %d from api.\n", irq);
+ last = end;
+ irq = strtoul(end, &end, 10);
+ };
+}
+
+static void prase_banned_cpu_string(char *cpu_ban_string)
+{
+ if (strlen(cpu_ban_string) < 1)
+ return;
+ if (!is_set_banned_cpumask_from_ui)
+ is_set_banned_cpumask_from_ui = 1;
+
+ strcpy(banned_cpumask_from_ui, cpu_ban_string);
+ log(TO_ALL, LOG_INFO, "Ban cpus(%s) online.\n", cpu_ban_string);
+ if (!strncmp(banned_cpumask_from_ui, "NONE", strlen("NONE"))) {
+ memset((void*)banned_cpumask_from_ui, 0, NR_CPUS + 1);
+ }
+}
+
+/*
+ * recived cmdline format:
+ * 1: settings sleep <int>
+ * 2: settings ban irqs "<int> <int> <int> <int> ..." or settings ban irqs "NONE"
+ * 3: settings ban cpus <cpumask> <cpumask> or settings ban cpus NONE
+ * */
+int sock_handle(int client_fd)
+{
+ char buff[FILE_LINE_MAX_NUM] = { 0 };
+ int ret = -1;
+ int recv_size = 0;
+ int valid_user = 0;
+ int new_iterval = 0;
+
+ struct cmsghdr *cmsg = NULL;
+ struct ucred *credentials = NULL;
+ struct iovec iov = { buff, FILE_LINE_MAX_NUM - 1 };
+ struct msghdr msg = { NULL, 0, &iov, 1, NULL, 0, 0 };
+
+ msg.msg_control = malloc(CMSG_SPACE(sizeof(struct ucred)));
+ msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred));
+
+ if ((recv_size = recvmsg(client_fd, &msg, 0)) < 0) {
+ log(TO_ALL, LOG_WARNING, "Error while receiving data.\n");
+ goto cleanup;
+ }
+
+ cmsg = CMSG_FIRSTHDR(&msg);
+ if (cmsg == NULL) {
+ log(TO_ALL, LOG_INFO, "There isn't enough space for a cmsghdr in the buffer.\n");
+ goto cleanup;
+ }
+
+ if ((cmsg->cmsg_level == SOL_SOCKET) &&
+ (cmsg->cmsg_type == SCM_CREDENTIALS)) {
+ credentials = (struct ucred *) CMSG_DATA(cmsg);
+ if (!credentials->uid) {
+ valid_user = 1;
+ }
+ }
+ if (!valid_user) {
+ log(TO_ALL, LOG_INFO, "Permission denied for user to connect to socket.\n");
+ goto cleanup;
+ }
+
+ if (!strncmp(buff, "settings ", strlen("settings "))) {
+ if (!(strncmp(buff + strlen("settings "), "sleep ",
+ strlen("sleep ")))) {
+ new_iterval = strtoul(buff + strlen("settings sleep "), NULL, 10);
+ if (new_iterval >= 1) {
+ sleep_interval = new_iterval;
+ }
+ } else if (!(strncmp(buff + strlen("settings "), "ban irqs \"",
+ strlen("ban irqs \"")))
+ && buff[recv_size - 1] == '\"') {
+ buff[recv_size - 1] = '\0';
+ prase_banned_irq_string(buff + strlen("settings ban irqs \""));
+ need_rescan = 1;
+ } else if (!(strncmp(buff + strlen("settings "), "cpus ",
+ strlen("cpus")))) {
+ if (recv_size > (int)(NR_CPUS + strlen("settings cpus "))) {
+ log(TO_ALL, LOG_WARNING, "Recived error setting cpus string %s, ONLY %d cpus support.\n", buff, NR_CPUS);
+ goto cleanup;
+ }
+ buff[recv_size] = '\0';
+ prase_banned_cpu_string(buff + strlen("settings cpus "));
+ need_rescan = 1;
+ }
+ } else if (!strncmp(buff, "stats ", strlen("stats "))) {
+ if (!(strncmp(buff + strlen("stats "), "cpu", strlen("cpu")))) {
+ fill_banned_cpus(buff, FILE_LINE_MAX_NUM - 1);
+ send_msg(client_fd, buff, strlen(buff));
+ } else if (!(strncmp(buff + strlen("stats "), "irq", strlen("irq")))) {
+ fill_banned_irqs(buff, FILE_LINE_MAX_NUM - 1);
+ send_msg(client_fd, buff, strlen(buff));
+ }
+ }
+
+ ret = 0;
+
+cleanup:
+ free(msg.msg_control);
+ return ret;
+}
+
+int init_socket()
+{
+ struct sockaddr_un addr;
+ int optval = 1;
+
+ (void)unlink(socket_name);
+
+ socket_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
+ if (socket_fd < 0) {
+ log(TO_ALL, LOG_WARNING, "Socket couldn't be created.\n");
+ goto cleanup;
+ }
+
+ if (access(SOCKET_TMPFS, F_OK) != 0) {
+ if (mkdir(SOCKET_TMPFS, 0644) == -1) {
+ log(TO_ALL, LOG_WARNING, "Daemon couldn't create directory %s.\n", SOCKET_TMPFS);
+ }
+ }
+
+ /*
+ * First try to create a file-based socket in tmpfs. If that doesn't
+ * succeed, fall back to an abstract socket (non file-based).
+ */
+ memset(&addr, 0, sizeof(struct sockaddr_un));
+ addr.sun_family = AF_UNIX;
+ strncpy(addr.sun_path, socket_name, sizeof(addr.sun_path));
+ if (bind(socket_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ log(TO_ALL, LOG_WARNING, "Daemon couldn't be bound to the file-based socket.\n");
+ /* Try binding to abstract */
+ memset(&addr, 0, sizeof(struct sockaddr_un));
+ addr.sun_family = AF_UNIX;
+ if (bind(socket_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ log(TO_ALL, LOG_WARNING, "Daemon couldn't be bound to the abstract socket, bailing out.\n");
+ goto cleanup;
+ }
+ }
+
+ if (chmod(socket_name, SOCK_RWX_MODE) != 0) {
+ log(TO_ALL, LOG_WARNING, "socket name : %s, chmod failed\n", socket_name);
+ goto cleanup;
+ }
+
+ if (setsockopt(socket_fd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) < 0) {
+ log(TO_ALL, LOG_WARNING, "Unable to set socket options: %s.\n", strerror(errno));
+ goto cleanup;
+ }
+
+ if (listen(socket_fd, MAX_CLIENT) != 0) {
+ log(TO_ALL, LOG_WARNING, "Daemon couldn't be listening to the socket: %s.\n", strerror(errno));
+ goto cleanup;
+ }
+
+ if (setnonblocking(socket_fd) < 0) {
+ log(TO_ALL, LOG_WARNING, "Daemon set connection(listen) nonblocking failed: %s.\n", strerror(errno));
+ goto cleanup;
+ }
+
+ return socket_fd;
+
+cleanup:
+ if (socket_fd >= 0)
+ close(socket_fd);
+
+ return -1;
+}
+
+void *handle_socket_api_event(void *args __attribute__((unused)))
+{
+ int epoll_fd = -1;
+ int conn_fd = -1;
+ int nfds = -1;
+ int i = 0;
+ int cur_fd_count = 1;
+
+ struct epoll_event ev;
+ struct epoll_event *events = NULL;
+
+ snprintf(socket_name, 64, "%s/%s%d.sock", SOCKET_TMPFS, SOCKET_PATH, getpid());
+
+ memset((void*)&ev, 0, sizeof(ev));
+ socket_fd = init_socket();
+ if (socket_fd < 0)
+ exit(-1);
+
+ epoll_fd = epoll_create(MAX_EVENTS);
+ if (epoll_fd < 0) {
+ log(TO_ALL, LOG_WARNING, "Unable to create epoll: %s.\n", strerror(errno));
+ exit(-1);
+ }
+ ev.events = EPOLLIN | EPOLLRDHUP;
+ ev.data.fd = socket_fd;
+ if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, socket_fd, &ev) < 0) {
+ log(TO_ALL, LOG_WARNING, "Daemon epoll set insertion error: %s.\n", strerror(errno));
+ exit(-1);
+ }
+
+ events = (struct epoll_event *)malloc(sizeof(struct epoll_event) * MAX_EVENTS);
+ if (NULL == events) {
+ log(TO_ALL, LOG_WARNING, "Daemon faild to malloc epoll event space.\n");
+ exit(-1);
+ }
+ memset((void*)events, 0, sizeof(struct epoll_event) * MAX_EVENTS);
+
+ banned_cpumask_from_ui = (char*)malloc(NR_CPUS + 1);
+ memset((void*)banned_cpumask_from_ui, 0, NR_CPUS + 1);
+
+ while (keep_going) {
+ nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
+ if ( 0 == nfds) {
+ log(TO_ALL, LOG_WARNING, "Daemon epoll wait failed: %s.\n", strerror(errno));
+ (void)usleep(SLEEP_TIME);
+ continue;
+ }
+ for (i = 0; i < nfds; i++) {
+ if (events[i].data.fd == socket_fd) {
+ conn_fd = accept(socket_fd, NULL, NULL);
+ if (conn_fd < 0) {
+ log(TO_ALL, LOG_WARNING, "Daemon accept failed: %s\n", strerror(errno));
+ continue;
+ }
+ if (cur_fd_count >= MAX_EVENTS) {
+ log(TO_ALL, LOG_WARNING, "Daemon support no more than %d connection\n", MAX_EVENTS);
+ close(conn_fd);
+ continue;
+ }
+ if (setnonblocking(conn_fd) < 0) {
+ log(TO_ALL, LOG_WARNING, "Daemon set connection nonblocking failed: %s.\n", strerror(errno));
+ close(conn_fd);
+ continue;
+ }
+ memset((void*)&ev, 0, sizeof(ev));
+ ev.events = EPOLLIN | EPOLLRDHUP;
+ ev.data.fd = conn_fd;
+ if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, conn_fd, &ev) < 0) {
+ log(TO_ALL, LOG_WARNING, "Daemonadd socket '%d' to poll failed: %s\n", conn_fd, strerror(errno));
+ continue;
+ }
+ cur_fd_count++;
+ continue;
+ } else if (events[i].events&EPOLLERR || events[i].events&EPOLLHUP ) {
+ log(TO_ALL, LOG_WARNING, "epoll is error: %u\n", events[i].events);
+ } else {
+ /* one socket connection only support send&recv data once */
+ sock_handle(events[i].data.fd);
+ }
+ epoll_ctl(epoll_fd, EPOLL_CTL_DEL, events[i].data.fd, &ev);
+ close(events[i].data.fd);
+ events[i].data.fd = -1;
+ cur_fd_count--;
+ }
+ }
+
+ free(events);
+ free(banned_cpumask_from_ui);
+ banned_cpumask_from_ui = NULL;
+ if (socket_fd >= 0)
+ close(socket_fd);
+ if (socket_name[0])
+ unlink(socket_name);
+
+ return 0;
+}
diff --git a/sockapi.h b/sockapi.h
new file mode 100644
index 0000000..254dd3f
--- /dev/null
+++ b/sockapi.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2019. Huawei Technologies Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the MuLan PSL v1.
+ *
+ * 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 MuLan PSL v1 for more details.
+ */
+#ifndef UVP_IRQBALANCE_SOCKAPI_H_
+#define UVP_IRQBALANCE_SOCKAPI_H_
+
+#include <sys/stat.h>
+
+/* set socket file mode to 660 */
+#define SOCK_RWX_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)
+
+#define SLEEP_TIME (100 * 1000) /* 100ms */
+
+#define MAX_CLIENT 512
+#define MAX_EVENTS 1024
+
+#define FILE_LINE_MAX_NUM (4096*6)
+
+void *handle_socket_api_event(void *args);
+
+#endif
--
1.8.3.1

View File

@ -0,0 +1,83 @@
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 1/6] feature: irqbalance: 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 | 23 ++++++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/procinterrupts.c b/procinterrupts.c
index fc4641a..99bcf50 100644
--- a/procinterrupts.c
+++ b/procinterrupts.c
@@ -107,7 +107,9 @@ static void guess_arm_irq_hints(char *name, struct irq_info *info)
static int compiled = 0;
/* Note: Last entry is a catchall */
static struct irq_match matches[] = {
- { "eth.*" ,{NULL} ,NULL, IRQ_TYPE_LEGACY, IRQ_GBETH },
+ { "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},
@@ -152,6 +154,7 @@ static void init_irq_class_and_type(char *savedline, struct irq_info *info, int
int is_xen_dyn = 0;
#ifdef AARCH64
char *tmp = NULL;
+ char irq_fullname[PATH_MAX] = {0};
#endif
irq_name = strtok_r(savedline, " ", &savedptr);
@@ -163,6 +166,16 @@ static void init_irq_class_and_type(char *savedline, struct irq_info *info, int
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
@@ -171,6 +184,13 @@ static void init_irq_class_and_type(char *savedline, struct irq_info *info, int
tmp = strchr(irq_name, '\n');
if (tmp)
*tmp = 0;
+
+ strcat(irq_fullname, irq_name);
+ strcat(irq_fullname, " ");
+ strcat(irq_fullname, savedptr);
+ tmp = strchr(irq_fullname, '\n');
+ if (tmp)
+ *tmp = 0;
#endif
irq_mod = last_token;
info->irq = irq;
@@ -180,6 +200,7 @@ static void init_irq_class_and_type(char *savedline, struct irq_info *info, int
info->class = IRQ_VIRT_EVENT;
} else {
#ifdef AARCH64
+ irq_name = irq_fullname;
guess_arm_irq_hints(irq_name, info);
#else
info->type = IRQ_TYPE_LEGACY;
--
1.8.3.1

View File

@ -0,0 +1,131 @@
From 0ddf835e21b4d33aba9d30755cc5674d1ee5a979 Mon Sep 17 00:00:00 2001
From: Zengruan Ye <yezengruan@huawei.com>
Date: Sat, 13 Jul 2019 19:12:29 +0800
Subject: [PATCH 2/6] feature: irqbalance: arm64: Add irq aff change check
For aarch64, the PPIs format in /proc/interrputs can be parsed
and add to interrupt db, and next, the number of interrupts
is counted and used to calculate the load. Finally these interrupts
maybe scheduled between the NUMA domains.
Acctually, the PPIs cannot change aff, and it should not be added
to interrupt db. This patch fix it.
Add a check before add a interrupt to db, just only reads the irq's
aff, and write it back to avoid any impact on the system,
According to the result of writing to fitler the irq.
Signed-off-by: wanghaibin <wanghaibin.wang@huawei.com>
---
classify.c | 7 +++++++
irqbalance.h | 3 +++
procinterrupts.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 64 insertions(+)
diff --git a/classify.c b/classify.c
index 3a25d62..65cb4e5 100644
--- a/classify.c
+++ b/classify.c
@@ -299,6 +299,13 @@ int irq_in_rebalance_list(int irq)
return entry ? 1 : 0;
}
+#ifdef AARCH64
+void add_banned_list_irq(int irq)
+{
+ add_banned_irq(irq, &banned_irqs);
+}
+#endif
+
void add_cl_banned_irq(int irq)
{
add_banned_irq(irq, &cl_banned_irqs);
diff --git a/irqbalance.h b/irqbalance.h
index 821de0e..c00430f 100644
--- a/irqbalance.h
+++ b/irqbalance.h
@@ -100,6 +100,9 @@ extern int get_cpu_count(void);
extern void rebuild_irq_db(void);
extern void free_irq_db(void);
extern void add_cl_banned_irq(int irq);
+#ifdef AARCH64
+extern void add_banned_list_irq(int irq);
+#endif
extern void for_each_irq(GList *list, void (*cb)(struct irq_info *info, void *data), void *data);
extern struct irq_info *get_irq_info(int irq);
extern void migrate_irq(GList **from, GList **to, struct irq_info *info);
diff --git a/procinterrupts.c b/procinterrupts.c
index 9e38e49..1f04a82 100644
--- a/procinterrupts.c
+++ b/procinterrupts.c
@@ -142,6 +142,42 @@ static void guess_arm_irq_hints(char *name, struct irq_info *info)
}
+
+/*
+ * This check is only invoked at service startup, and avoid any impact on the system,
+ * The scheme just only reads the irq's aff, and write it back. According to the result
+ * of writing to fitler the irq.
+ * Return 0 means the irq can change aff. Other return values, on the contrary.
+ */
+static int is_arm_irq_aff_cannot_change(int irq)
+{
+ char buf[PATH_MAX] = { 0 };
+ FILE *file = NULL;
+ char *line = NULL;
+ size_t size = 0;
+ int ret = 0;
+
+ snprintf(buf, PATH_MAX - 1, "/proc/irq/%i/smp_affinity", irq);
+ file = fopen(buf, "r+");
+ if (!file)
+ return -1;
+
+ if (getline(&line, &size, file) <= 0) {
+ ret = -1;
+ goto out;
+ }
+
+ line[strlen(line) - 1] = '\0';
+
+ fprintf(file, "%s", line);
+ ret = fflush(file);
+
+out:
+ free(line);
+ fclose(file);
+
+ return ret;
+}
#endif
static void init_irq_class_and_type(char *savedline, struct irq_info *info, int irq) {
char *irq_name = NULL;
@@ -233,6 +269,24 @@ GList* collect_full_irq_list()
c++;
number = strtoul(line, NULL, 10);
+#ifdef AARCH64
+ if (is_arm_irq_aff_cannot_change(number)) {
+ /*
+ * This means that the irq affinity cannot be changed, just like:
+ * (1) the irq with IRQF_PERCPU flag, per cpu irq (in arm64, like PPI)
+ * (2) the irq with IRQD_NO_BALANCING flag, some driver request irq can
+ * set the flag according to themselves require. for example in arm64,
+ * for the passthrough doorbell irq (GICV4), in future.
+ * (3) the irq with IRQD_AFFINITY_MANAGED flag, some drivers can set
+ * specially irq affinity, and prohibit user to modify it.
+ *
+ * For these irqs, we can add these to banned irq list.
+ */
+ add_banned_list_irq(number);
+ continue;
+ }
+#endif
+
info = calloc(sizeof(struct irq_info), 1);
if (info) {
init_irq_class_and_type(savedline, info, number);
--
1.8.3.1

View File

@ -0,0 +1,345 @@
From fd447c6f129769fcb685d8a2e22c75a922efe342 Mon Sep 17 00:00:00 2001
From: Zengruan Ye <yezengruan@huawei.com>
Date: Mon, 15 Jul 2019 21:35:29 +0800
Subject: [PATCH 3/6] feature: irqbalance: auto banned pci-assigned irq
checkout VM pci-assigned pci device irq, and banned it
Signed-off-by: Xu Yandong <xuyandong2@huawei.com>
---
activate.c | 38 ++++++++++++++++++++++++++++++++++++-
classify.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++-------
irqbalance.c | 11 +++++++++++
irqbalance.h | 2 ++
procinterrupts.c | 23 ++++++++++++++++++++++
types.h | 1 +
6 files changed, 125 insertions(+), 8 deletions(-)
diff --git a/activate.c b/activate.c
index 1c4b867..ad60fde 100644
--- a/activate.c
+++ b/activate.c
@@ -29,9 +29,12 @@
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
+#include <dirent.h>
#include "irqbalance.h"
+extern int ban_pci_assigned_irq;
+
static int check_affinity(struct irq_info *info, cpumask_t applied_mask)
{
cpumask_t current_mask;
@@ -56,6 +59,30 @@ static int check_affinity(struct irq_info *info, cpumask_t applied_mask)
return cpus_equal(applied_mask, current_mask);
}
+static int is_still_pci_assigned_irq(int irq)
+{
+ DIR *dir = NULL;
+ struct dirent *ptr = NULL;
+ char irq_path[PATH_MAX] = { 0 };
+
+ snprintf(irq_path, PATH_MAX - 1, "/proc/irq/%i/", irq);
+ if ((dir = opendir(irq_path)) == NULL) {
+ return 0;
+ }
+
+ while ((ptr = readdir(dir)) != NULL) {
+ if(strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) {
+ continue;
+ } else if (is_pci_assigned_irq(ptr->d_name)) {
+ closedir(dir);
+ return 1;
+ }
+ }
+
+ closedir(dir);
+ return 0;
+}
+
static void activate_mapping(struct irq_info *info, void *data __attribute__((unused)))
{
char buf[PATH_MAX];
@@ -89,7 +116,16 @@ static void activate_mapping(struct irq_info *info, void *data __attribute__((un
return;
cpumask_scnprintf(buf, PATH_MAX, applied_mask);
- fprintf(file, "%s", buf);
+ if (ban_pci_assigned_irq) {
+ if (!is_still_pci_assigned_irq(info->irq)) {
+ fprintf(file, "%s", buf);
+ } else {
+ log(TO_CONSOLE, LOG_INFO, "IRQ %d is turned into a PCI-assigned irq number.\n", info->irq);
+ need_rescan = 1;
+ }
+ } else {
+ fprintf(file, "%s", buf);
+ }
fclose(file);
info->moved = 0; /*migration is done*/
}
diff --git a/classify.c b/classify.c
index 37bfb29..52fd74a 100644
--- a/classify.c
+++ b/classify.c
@@ -37,6 +37,7 @@ static GList *interrupts_db = NULL;
static GList *banned_irqs = NULL;
GList *cl_banned_irqs = NULL;
static GList *cl_banned_modules = NULL;
+static GList *vm_banned_irqs = NULL;
#define SYSFS_DIR "/sys"
#define SYSPCI_DIR "/sys/bus/pci/devices"
@@ -264,7 +265,7 @@ static gint compare_ints(gconstpointer a, gconstpointer b)
return ai->irq - bi->irq;
}
-static void add_banned_irq(int irq, GList **list)
+static void add_banned_irq(int irq, GList **list, int extra_flag)
{
struct irq_info find, *new;
GList *entry;
@@ -282,6 +283,7 @@ static void add_banned_irq(int irq, GList **list)
new->irq = irq;
new->flags |= IRQ_FLAG_BANNED;
+ new->flags |= extra_flag;
*list = g_list_append(*list, new);
log(TO_CONSOLE, LOG_INFO, "IRQ %d was BANNED.\n", irq);
@@ -291,13 +293,18 @@ static void add_banned_irq(int irq, GList **list)
#ifdef AARCH64
void add_banned_list_irq(int irq)
{
- add_banned_irq(irq, &banned_irqs);
+ add_banned_irq(irq, &banned_irqs, 0);
}
#endif
void add_cl_banned_irq(int irq)
{
- add_banned_irq(irq, &cl_banned_irqs);
+ add_banned_irq(irq, &cl_banned_irqs, 0);
+}
+
+void add_vm_banned_irq(int irq)
+{
+ add_banned_irq(irq, &vm_banned_irqs, IRQ_FLAG_VM_BANNED);
}
static int is_banned_irq(int irq)
@@ -307,7 +314,10 @@ static int is_banned_irq(int irq)
find.irq = irq;
- entry = g_list_find_custom(banned_irqs, &find, compare_ints);
+ entry = g_list_find_custom(vm_banned_irqs, &find, compare_ints);
+ if (!entry)
+ entry = g_list_find_custom(banned_irqs, &find, compare_ints);
+
return entry ? 1:0;
}
@@ -660,7 +670,7 @@ struct irq_info *build_one_dev_entry(const char *dirname, GList *tmp_list)
continue;
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);
+ add_banned_irq(irqnum, &banned_irqs, 0);
continue;
}
hint.irq = irqnum;
@@ -695,7 +705,7 @@ struct irq_info *build_one_dev_entry(const char *dirname, GList *tmp_list)
goto done;
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);
+ add_banned_irq(irqnum, &banned_irqs, 0);
goto done;
}
@@ -811,6 +821,9 @@ void free_irq_db(void)
banned_irqs = NULL;
g_list_free(rebalance_irq_list);
rebalance_irq_list = NULL;
+ for_each_irq(vm_banned_irqs, free_irq, NULL);
+ g_list_free(vm_banned_irqs);
+ vm_banned_irqs = NULL;
}
void free_cl_opts(void)
@@ -832,7 +845,7 @@ struct irq_info *add_new_irq(int irq, struct irq_info *hint, GList *proc_interru
/* Set NULL devpath for the irq has no sysfs entries */
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);
+ add_banned_irq(irq, &banned_irqs, 0);
new = get_irq_info(irq);
} else
new = add_one_irq_to_db(NULL, hint, &pol);
@@ -906,6 +919,9 @@ struct irq_info *get_irq_info(int irq)
entry = g_list_find_custom(interrupts_db, &find, compare_ints);
if (!entry)
+ entry = g_list_find_custom(vm_banned_irqs, &find, compare_ints);
+
+ if (!entry)
entry = g_list_find_custom(banned_irqs, &find, compare_ints);
return entry ? entry->data : NULL;
@@ -954,3 +970,31 @@ void sort_irq_list(GList **list)
{
*list = g_list_sort(*list, sort_irqs);
}
+
+/*
+ * assigned pci device's irq in /proc/interrupts
+ * has keyword "vfio" or "kvm"
+ * and BDF notation "xxxx:xx:xx.x"
+ */
+int is_pci_assigned_irq(const char *line)
+{
+ const char *pos = NULL;
+
+ pos = strstr(line, "vfio");
+ if (!pos) {
+ pos = strstr(line, "kvm");
+ }
+
+ if (!pos)
+ return 0;
+
+ while (*pos) {
+ if (*pos >= '0' && *pos <= '9') {
+ if (*(pos + 4) == ':' && *(pos + 7) == ':' && *(pos + 10) == '.')
+ return 1;
+ }
+ pos++;
+ }
+
+ return 0;
+}
diff --git a/irqbalance.c b/irqbalance.c
index 4787cb2..40ec65c 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -44,6 +44,7 @@
#include "irqbalance.h"
volatile int keep_going = 1;
+volatile int ban_pci_assigned_irq = 1;
int socket_fd;
char socket_name[64];
int one_shot_mode;
@@ -375,6 +376,12 @@ gboolean scan()
}
}
+static void parse_ban_pci_assigned_irq(char *status)
+{
+ if (status && (0 == strcmp(status,"disabled")))
+ ban_pci_assigned_irq = 0;
+}
+
void get_irq_data(struct irq_info *irq, void *data)
{
char **irqdata = (char **)data;
@@ -619,6 +626,10 @@ int main(int argc, char** argv)
foreground_mode=1;
}
+ if (getenv("IRQBALANCE_AUTO_BAN_PCI_ASSIGNED_IRQS")) {
+ parse_ban_pci_assigned_irq(getenv("IRQBALANCE_AUTO_BAN_PCI_ASSIGNED_IRQS"));
+ }
+
/*
* If we are't in debug mode, don't dump anything to the console
* note that everything goes to the console before we check this
diff --git a/irqbalance.h b/irqbalance.h
index 5016cc8..339e2a3 100644
--- a/irqbalance.h
+++ b/irqbalance.h
@@ -103,8 +103,10 @@ extern void add_cl_banned_irq(int irq);
#ifdef AARCH64
extern void add_banned_list_irq(int irq);
#endif
+extern void add_vm_banned_irq(int irq);
extern void for_each_irq(GList *list, void (*cb)(struct irq_info *info, void *data), void *data);
extern struct irq_info *get_irq_info(int irq);
+extern int is_pci_assigned_irq(const char *line);
extern void migrate_irq(GList **from, GList **to, struct irq_info *info);
extern void free_cl_opts(void);
extern void add_cl_banned_module(char *modname);
diff --git a/procinterrupts.c b/procinterrupts.c
index 6cfa661..522b9a1 100644
--- a/procinterrupts.c
+++ b/procinterrupts.c
@@ -42,6 +42,7 @@
static int proc_int_has_msi = 0;
static int msi_found_in_sysfs = 0;
+extern int ban_pci_assigned_irq;
#ifdef AARCH64
struct irq_match {
@@ -290,6 +291,12 @@ GList* collect_full_irq_list()
c++;
number = strtoul(line, NULL, 10);
+ if (ban_pci_assigned_irq && is_pci_assigned_irq(c)) {
+ log(TO_ALL, LOG_INFO, "Banned PCI-assigned irq %d.\n", number);
+ add_vm_banned_irq(number);
+ continue;
+ }
+
#ifdef AARCH64
if (is_arm_irq_aff_cannot_change(number)) {
/*
@@ -333,6 +340,7 @@ void parse_proc_interrupts(void)
FILE *file;
char *line = NULL;
size_t size = 0;
+ int vfio_flag = 0;
file = fopen("/proc/interrupts", "r");
if (!file)
@@ -400,6 +408,21 @@ void parse_proc_interrupts(void)
}
info->existing = 1;
+ if (ban_pci_assigned_irq) {
+ vfio_flag = is_pci_assigned_irq(c);
+ if (vfio_flag && (info->flags & IRQ_FLAG_VM_BANNED) == 0) {
+ log(TO_ALL, LOG_INFO, "IRQ %d has been reused as a pci assigned interrupt number", number);
+ need_rescan = 1;
+ break;
+ }
+
+ if (!vfio_flag && (info->flags & IRQ_FLAG_VM_BANNED) != 0) {
+ log(TO_ALL, LOG_INFO, "IRQ %d has been reused as a general interrupt number", number);
+ need_rescan = 1;
+ break;
+ }
+ }
+
count = 0;
cpunr = 0;
diff --git a/types.h b/types.h
index 62cc2bb..c0950ee 100644
--- a/types.h
+++ b/types.h
@@ -35,6 +35,7 @@
* IRQ Internal tracking flags
*/
#define IRQ_FLAG_BANNED 1
+#define IRQ_FLAG_VM_BANNED 2
enum obj_type_e {
OBJ_TYPE_CPU,
--
1.8.3.1

View File

@ -0,0 +1,36 @@
From aeb65d281ba122ba7539d551984bd37115d48811 Mon Sep 17 00:00:00 2001
From: hejingxian <hejingxian@huawei.com>
Date: Tue, 10 Sep 2019 22:48:24 +0800
Subject: [PATCH] supplement irqbalance service config
Add irqbalance service config: OOMScoreAdjust, Type, PIDFile, StartLimitInterval, StartLimitBurst, and so on.
Modify ExecStart script to improve banirq args config.
---
irqbalance.service | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/misc/irqbalance.service b/misc/irqbalance.service
index 8a5b1f4..ce0022c 100644
--- a/misc/irqbalance.service
+++ b/misc/irqbalance.service
@@ -1,10 +1,16 @@
[Unit]
Description=irqbalance daemon
ConditionVirtualization=!container
+After=syslog.target
[Service]
+OOMScoreAdjust=-500
+Type=simple
+PIDFile=/var/run/irqbalance.pid
EnvironmentFile=/etc/sysconfig/irqbalance
-ExecStart=/usr/sbin/irqbalance --foreground $IRQBALANCE_ARGS
+ExecStart=/usr/sbin/irq_balancer
+StartLimitInterval=10
+StartLimitBurst=10000
[Install]
WantedBy=multi-user.target
--
1.8.3.1

View File

@ -0,0 +1,105 @@
From 9f7b1a93150c6bb1f54a7bf5ce36b344f10cdf4a Mon Sep 17 00:00:00 2001
From: Neil Horman <nhorman@tuxdriver.com>
Date: Wed, 20 Feb 2019 12:03:16 -0500
Subject: [PATCH 110/112] fix balancing when numa information isn't available
Discovered a bug in which, when numa isn't available we failed to assign
the unspecified node to the device tree, leading us to not balance any
interrupts. Make sure it gets added so irq get parsed down through the
tree to the proper topology node
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
---
cputree.c | 22 +++++++++++++++++++---
placement.c | 9 +++++----
2 files changed, 24 insertions(+), 7 deletions(-)
diff --git a/cputree.c b/cputree.c
index f08ce84..5551784 100644
--- a/cputree.c
+++ b/cputree.c
@@ -126,9 +126,10 @@ static void add_numa_node_to_topo_obj(struct topo_obj *obj, int nodeid)
GList *entry;
struct topo_obj *node;
struct topo_obj *cand_node;
+ struct topo_obj *package;
node = get_numa_node(nodeid);
- if (!node || node->number == -1)
+ if (!node || (numa_avail && (node->number == -1)))
return;
entry = g_list_first(obj->numa_nodes);
@@ -141,6 +142,21 @@ static void add_numa_node_to_topo_obj(struct topo_obj *obj, int nodeid)
if (!entry)
obj->numa_nodes = g_list_append(obj->numa_nodes, node);
+
+ if (!numa_avail && obj->obj_type == OBJ_TYPE_PACKAGE) {
+ entry = g_list_first(node->children);
+ while (entry) {
+ package = entry->data;
+ if (package == obj)
+ break;
+ entry = g_list_next(entry);
+ }
+
+ if (!entry) {
+ node->children = g_list_append(node->children, obj);
+ obj->parent = node;
+ }
+ }
}
static struct topo_obj* add_cache_domain_to_package(struct topo_obj *cache,
@@ -189,7 +205,7 @@ static struct topo_obj* add_cache_domain_to_package(struct topo_obj *cache,
cache->parent = package;
}
- if (nodeid > -1)
+ if (!numa_avail || (nodeid > -1))
add_numa_node_to_topo_obj(package, nodeid);
return package;
@@ -236,7 +252,7 @@ static struct topo_obj* add_cpu_to_cache_domain(struct topo_obj *cpu,
cpu->parent = (struct topo_obj *)cache;
}
- if (nodeid > -1)
+ if (!numa_avail || (nodeid > -1))
add_numa_node_to_topo_obj(cache, nodeid);
return cache;
diff --git a/placement.c b/placement.c
index 5a82111..efa8c57 100644
--- a/placement.c
+++ b/placement.c
@@ -130,7 +130,7 @@ static void place_irq_in_node(struct irq_info *info, void *data __attribute__((u
if ((info->level == BALANCE_NONE) && cpus_empty(banned_cpus))
return;
- if (irq_numa_node(info)->number != -1) {
+ if (irq_numa_node(info)->number != -1 || !numa_avail) {
/*
* Need to make sure this node is elligible for migration
* given the banned cpu list
@@ -138,12 +138,13 @@ static void place_irq_in_node(struct irq_info *info, void *data __attribute__((u
if (!cpus_intersects(irq_numa_node(info)->mask, unbanned_cpus))
goto find_placement;
/*
- * This irq belongs to a device with a preferred numa node
- * put it on that node
- */
+ * This irq belongs to a device with a preferred numa node
+ * put it on that node
+ */
migrate_irq(&rebalance_irq_list, &irq_numa_node(info)->interrupts, info);
info->assigned_obj = irq_numa_node(info);
irq_numa_node(info)->load += info->load + 1;
+
return;
}
--
1.8.3.1

43
irq_balancer Normal file
View File

@ -0,0 +1,43 @@
#! /bin/sh
# Copyright (c) 2015 HUAWEI TECHNOLOGIES CO., LTD.
# All rights reserved.
# Check for missing binaries (stale symlinks should not happen)
IRQBALANCE_BIN=/usr/sbin/irqbalance
test -x $IRQBALANCE_BIN || exit 5
IRQBALANCE_PIDFILE="/var/run/irqbalance.pid"
IRQBALANCE_CONFIG_FILE="/etc/sysconfig/irqbalance"
if [ -f $IRQBALANCE_CONFIG_FILE ]; then
. $IRQBALANCE_CONFIG_FILE
fi
# Note: There maybe IRQBALANCE_ARGS env in $IRQBALANCE_CONFIG_FILE
# So, here we should add this.
IRQBALANCE_ARGS=$IRQBALANCE_ARGS" --pid=$IRQBALANCE_PIDFILE"
if [ -n "$IRQBALANCE_BANNED_CPUS" ]; then
export IRQBALANCE_BANNED_CPUS
fi
if [ "$IRQBALANCE_ONESHOT" != "auto" ]; then
export IRQBALANCE_ONESHOT
fi
IRQS_BANNED="$IRQBALANCE_BANNED_INTERRUPTS"
if [ -n "$IRQBALANCE_BANNED_INTERRUPTS" ]; then
export IRQBALANCE_BANNED_INTERRUPTS
fi
for ban_irq in $IRQS_BANNED;
do
if [ -z "${ban_irq//[0-9]/}" ];then
IRQBALANCE_ARGS=$IRQBALANCE_ARGS" --banirq=$ban_irq"
else
echo "Bad irq number $ban_irq, please check config file!"
exit 1
fi
done
$IRQBALANCE_BIN $IRQBALANCE_ARGS

View File

@ -0,0 +1,86 @@
From a4fbf90c2395ffa13176e8b002b7ef89a0ffc667 Mon Sep 17 00:00:00 2001
From: Neil Horman <nhorman@tuxdriver.com>
Date: Mon, 28 May 2018 08:33:08 -0400
Subject: [PATCH 079/112] irq_db: don't fail entirely if we don't have a pci
bus
aarch64 expects to have several interrupts that aren't associated to
devices on a pci bus. However, rebuild_irq_db skips all interrupts if
/sys/bus/pci/devices doesn't exist. Fix this by still calling
add_missing_irq on all collected interrupts regardless of the pci bus
directory.
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
---
classify.c | 29 ++++++++++++++---------------
1 file changed, 14 insertions(+), 15 deletions(-)
diff --git a/classify.c b/classify.c
index d3688fe..a977dc9 100644
--- a/classify.c
+++ b/classify.c
@@ -39,7 +39,7 @@ GList *cl_banned_irqs = NULL;
static GList *cl_banned_modules = NULL;
#define SYSFS_DIR "/sys"
-#define SYSDEV_DIR "/sys/bus/pci/devices"
+#define SYSPCI_DIR "/sys/bus/pci/devices"
#define PCI_MAX_CLASS 0x14
#define PCI_MAX_SERIAL_SUBCLASS 0x81
@@ -616,8 +616,8 @@ static void build_one_dev_entry(const char *dirname, GList *tmp_irqs)
char devpath[PATH_MAX];
struct user_irq_policy pol;
- sprintf(path, "%s/%s/msi_irqs", SYSDEV_DIR, dirname);
- sprintf(devpath, "%s/%s", SYSDEV_DIR, dirname);
+ sprintf(path, "%s/%s/msi_irqs", SYSPCI_DIR, dirname);
+ sprintf(devpath, "%s/%s", SYSPCI_DIR, dirname);
msidir = opendir(path);
@@ -646,7 +646,7 @@ static void build_one_dev_entry(const char *dirname, GList *tmp_irqs)
return;
}
- sprintf(path, "%s/%s/irq", SYSDEV_DIR, dirname);
+ sprintf(path, "%s/%s/irq", SYSPCI_DIR, dirname);
fd = fopen(path, "r");
if (!fd)
return;
@@ -764,22 +764,21 @@ void rebuild_irq_db(void)
tmp_irqs = collect_full_irq_list();
- devdir = opendir(SYSDEV_DIR);
- if (!devdir)
- goto free;
+ devdir = opendir(SYSPCI_DIR);
- do {
- entry = readdir(devdir);
-
- if (!entry)
- break;
+ if (devdir) {
+ do {
+ entry = readdir(devdir);
- build_one_dev_entry(entry->d_name, tmp_irqs);
+ if (!entry)
+ break;
- } while (entry != NULL);
+ build_one_dev_entry(entry->d_name, tmp_irqs);
- closedir(devdir);
+ } while (entry != NULL);
+ closedir(devdir);
+ }
for_each_irq(tmp_irqs, add_missing_irq, interrupts_db);
--
1.8.3.1

View File

@ -0,0 +1,12 @@
diff -up ./misc/irqbalance.service.path ./misc/irqbalance.service
--- ./misc/irqbalance.service.path 2017-11-14 13:09:56.011146473 -0500
+++ ./misc/irqbalance.service 2017-11-14 13:10:13.480075654 -0500
@@ -4,7 +4,7 @@ After=syslog.target
ConditionVirtualization=!container
[Service]
-EnvironmentFile=/path/to/irqbalance.env
+EnvironmentFile=/etc/sysconfig/irqbalance
ExecStart=/usr/sbin/irqbalance --foreground $IRQBALANCE_ARGS
[Install]

BIN
irqbalance-1.4.0.tar.gz Normal file

Binary file not shown.

View File

@ -0,0 +1,105 @@
From 19c25ddc5a13cf0b993cdb0edac0eee80143be34 Mon Sep 17 00:00:00 2001
From: PJ Waskiewicz <peter.waskiewicz.jr@intel.com>
Date: Thu, 9 Aug 2018 10:56:03 -0700
Subject: [PATCH 093/112] irqbalance: Add support for file-based socket for IPC
This patch adds support for a file-based socket in tmpfs. It
also fixes an inadvertent bug that caused the socket in use to
be an abstract socket, which wasn't the intent.
This addresses Issue #72.
Signed-off-by: PJ Waskiewicz <pjwaskiewicz@gmail.com>
---
irqbalance.c | 32 ++++++++++++++++++++++----------
irqbalance.h | 1 +
2 files changed, 23 insertions(+), 10 deletions(-)
diff --git a/irqbalance.c b/irqbalance.c
index 2614719..bce9d56 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -45,6 +45,7 @@
volatile int keep_going = 1;
int socket_fd;
+char socket_name[64];
int one_shot_mode;
int debug_mode;
int foreground_mode;
@@ -456,7 +457,7 @@ gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attri
return TRUE;
}
-int init_socket(char *socket_name)
+int init_socket()
{
struct sockaddr_un addr;
memset(&addr, 0, sizeof(struct sockaddr_un));
@@ -467,13 +468,25 @@ int init_socket(char *socket_name)
return 1;
}
+ /*
+ * First try to create a file-based socket in tmpfs. If that doesn't
+ * succeed, fall back to an abstract socket (non file-based).
+ */
addr.sun_family = AF_UNIX;
- strncpy(addr.sun_path, socket_name, strlen(addr.sun_path));
- if (bind(socket_fd, (struct sockaddr *)&addr,
- sizeof(sa_family_t) + strlen(socket_name) + 1) < 0) {
- log(TO_ALL, LOG_WARNING, "Daemon couldn't be bound to the socket.\n");
- return 1;
+ snprintf(socket_name, 64, "%s/%s%d.sock", SOCKET_TMPFS, SOCKET_PATH, getpid());
+ strncpy(addr.sun_path, socket_name, strlen(socket_name));
+ if (bind(socket_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ log(TO_ALL, LOG_WARNING, "Daemon couldn't be bound to the file-based socket.\n");
+
+ /* Try binding to abstract */
+ memset(&addr, 0, sizeof(struct sockaddr_un));
+ addr.sun_family = AF_UNIX;
+ if (bind(socket_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ log(TO_ALL, LOG_WARNING, "Daemon couldn't be bound to the abstract socket, bailing out.\n");
+ return 1;
+ }
}
+
int optval = 1;
if (setsockopt(socket_fd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) < 0) {
log(TO_ALL, LOG_WARNING, "Unable to set socket options.\n");
@@ -598,10 +611,7 @@ int main(int argc, char** argv)
parse_proc_interrupts();
parse_proc_stat();
- char socket_name[64];
- snprintf(socket_name, 64, "%s%d.sock", SOCKET_PATH, getpid());
-
- if (init_socket(socket_name)) {
+ if (init_socket()) {
return EXIT_FAILURE;
}
main_loop = g_main_loop_new(NULL, FALSE);
@@ -619,6 +629,8 @@ int main(int argc, char** argv)
unlink(pidfile);
/* Remove socket */
close(socket_fd);
+ if (socket_name[0])
+ unlink(socket_name);
return EXIT_SUCCESS;
}
diff --git a/irqbalance.h b/irqbalance.h
index b7a26fc..c4717d3 100644
--- a/irqbalance.h
+++ b/irqbalance.h
@@ -158,6 +158,7 @@ extern unsigned int log_mask;
#endif /* HAVE_LIBSYSTEMD */
#define SOCKET_PATH "irqbalance"
+#define SOCKET_TMPFS "/var/run"
#endif /* __INCLUDE_GUARD_IRQBALANCE_H_ */
--
1.8.3.1

2
irqbalance.rules Normal file
View File

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

141
irqbalance.spec Normal file
View File

@ -0,0 +1,141 @@
Summary: A dynamic adaptive IRQ balancing daemon
Name: irqbalance
Version: 1.4.0
Release: 6
Epoch: 3
License: GPLv2
Source0: https://github.com/Irqbalance/irqbalance/archive/irqbalance-%{version}.tar.gz
Source1: irqbalance.sysconfig
Source2: irqbalance.rules
Source3: irq_balancer
Url: https://github.com/Irqbalance/irqbalance
BuildRequires: autoconf automake libtool libcap-ng systemd
BuildRequires: glib2-devel pkgconf libcap-ng-devel ncurses-devel
Requires: ncurses-libs
%ifnarch %{arm}
BuildRequires: numactl-devel
Requires: numactl-libs
%endif
%define _hardened_build 1
ExcludeArch: s390 s390x
Patch0: add-a-catchall-guessing-mechanis.patch
Patch1: irq_db-don-t-fail-entirely-if-we-don-t-have-a-pci-bu.patch
Patch2: cputree-adjust-snprintf-sizes-to-avoid-gcc-warnings.patch
Patch3: classify-remove-unused-label.patch
Patch4: parse_proc_interrupts-ensure-that-buffer-is-long-eno.patch
Patch5: Fix-some-string-copy-limitations.patch
Patch6: irqbalance-Add-support-for-file-based-socket-for-IPC.patch
Patch7: Fix-several-memleak-problems-found-by-covscan.patch
Patch8: Fix-an-possible-overflow-error.patch
Patch9: procinterrupts-check-xen-dyn-event-more-flexible.patch
Patch10:Fix-ambiguous-parsing-of-node-entries-in-sys.patch
Patch11:Don-t-leak-socket-fd-on-connection-error.patch
Patch12:Fix-string-truncation-issues-detected-by-GCC-8.patch
Patch13:fix-balancing-when-numa-information-isn-t-available.patch
Patch9000: irqbalance-1.0.4-env-file-path.patch
Patch9001: bugfix-fix-a-hole-that-flees-hotplug-event.patch
Patch9002: bugfix-use-policy-prior-to-the-default-values.patch
Patch9003: bugfix-force-irq-into-rebalance-list-when-irq-removed-and-reinserted.patch
Patch9004: feature-introduce-verifyhint-to-detect-hint-variation.patch
Patch9005: bugfix-fix-two-same-irq-insert-to-list.patch
Patch9006: feature-irqbalance-aarch64-add-the-regular-to-get-th.patch
Patch9007: feature-irqbalance-arm64-Add-irq-aff-change-check.patch
Patch9008: feature-irqbalance-auto-banned-pci-assigned-irq.patch
Patch9009: bugfix-irqbalance-fix-wrong-pid-value-in-pid-file.patch
Patch9010: feature-supplement-irqbalance-service-config.patch
Patch9011: feature-irqbalance-Add-ability-for-socket-communicat.patch
Patch9012: bugfix-fgets-will-get-a-redundant-new-line.patch
Patch9013: bugfix-prevent-inserting-a-duplicate-entry-to-avoid-list-ch.patch
Patch9014: bugfix-guess_arm_irq_hints.patch
Patch9015: feature-add-new-user-irq-policy-config-rule.patch
%description
Irqbalance is a daemon to help balance the cpu load generated by
interrupts across all of a systems cpus. Irqbalance identifies the
highest volume interrupt sources, and isolates each of them to a
single unique cpu, so that load is spread as much as possible over
an entire processor set, while minimizing cache miss rates for irq
handlers.
%prep
%autosetup -p1
%build
./autogen.sh
%configure
CFLAGS="%{optflags}" %make_build CFLAGS+='-fstack-protector-strong '
%install
install -D -p -m 0755 %{name} %{buildroot}%{_sbindir}/%{name}
install -D -p -m 0644 ./misc/%{name}.service %{buildroot}/%{_unitdir}/%{name}.service
install -D -p -m 0644 %{SOURCE1} %{buildroot}%{_sysconfdir}/sysconfig/%{name}
install -D -p -m 0755 %{SOURCE2} %{buildroot}%{_sysconfdir}/sysconfig/%{name}.rules
install -D -p -m 0755 %{SOURCE3} %{buildroot}%{_sbindir}/irq_balancer
install -d %{buildroot}%{_mandir}/man1/
install -p -m 0644 ./%{name}.1 %{buildroot}%{_mandir}/man1/
%check
make check
%files
%doc COPYING AUTHORS
%{_sbindir}/%{name}
%{_unitdir}/%{name}.service
%{_mandir}/man1/*
%config(noreplace) %{_sysconfdir}/sysconfig/%{name}
%{_sysconfdir}/sysconfig/%{name}.rules
%{_sbindir}/irq_balancer
%post
%systemd_post %{name}.service
%preun
%systemd_preun %{name}.service
%postun
%systemd_postun_with_restart %{name}.service
%triggerun -- %{name} < 2:0.56-3
if /sbin/chkconfig --level 3 %{name} ; then
/bin/systemctl enable %{name}.service >/dev/null 2>&1 || :
fi
/sbin/chkconfig --del %{name} >/dev/null 2>&1 || :
%changelog
* Mon Sep 23 2019 hejingxian<hejingxian@huawei.com> - 3:1.4.0-6
- Type: enhancement
- ID:NA
- SUG:NA
- DESC: add avoid duplicate-entry insert, guess_arm_irq_hints and new config rule patches
* Thu Sep 12 2019 caomeng<caomeng5@huawei.com> - 3:1.4.0-5
- Type:other
- ID:NA
- SUG:NA
- DESC: fix make in parallel way
* Fri Aug 30 2019 caomeng<caomeng5@huawei.com> - 3:1.4.0-4
- Type:other
- ID:NA
- SUG:NA
- DESC: fix SP comile option
* Thu Aug 29 2019 caomeng<caomeng5@huawei.com> - 3:1.4.0-3
- Type:other
- ID:NA
- SUG:NA
- DESC: openeuler rewrite spec file
* Thu Aug 29 2019 caomeng<caomeng5@huawei.com> - 3:1.4.0-2
- Package init

39
irqbalance.sysconfig Normal file
View File

@ -0,0 +1,39 @@
# irqbalance is a daemon process that distributes interrupts across
# CPUS on SMP systems. The default is to rebalance once every 10
# seconds. This is the environment file that is specified to systemd via the
# EnvironmentFile key in the service unit file (or via whatever method the init
# system you're using has.
#
# ONESHOT=yes
# after starting, wait for a minute, then look at the interrupt
# load and balance it once; after balancing exit and do not change
# it again.
#IRQBALANCE_ONESHOT=
#
# IRQBALANCE_BANNED_CPUS
# 64 bit bitmask which allows you to indicate which cpu's should
# be skipped when reblancing irqs. Cpu numbers which have their
# corresponding bits set to one in this mask will not have any
# irq's assigned to them on rebalance
#
IRQBALANCE_BANNED_CPUS=
## Type: string
## Default: ""
## ServiceRestart: Iirq_balancer
#
# Interrupt that don't get balanced as list (separation character doesn't
# matter). For example broken chipsets don't allow the timer interrupt
# to be set to another CPU than the first, and with this option that
# policy can be applied.
#
IRQBALANCE_BANNED_INTERRUPTS=""
#
# IRQBALANCE_ARGS
# append any args here to the irqbalance daemon as documented in the man page
#
IRQBALANCE_ARGS=

View File

@ -0,0 +1,49 @@
From 8ab70a85bbda79d47c8cc8e1c2767e1cb307f536 Mon Sep 17 00:00:00 2001
From: Neil Horman <nhorman@tuxdriver.com>
Date: Tue, 29 May 2018 11:07:32 -0400
Subject: [PATCH 085/112] parse_proc_interrupts: ensure that buffer is long
enough for a string
Instead of using strcpy to a save each line in /proc/interrupts, use
strdup and free to ensure that the buffer will hold the string
consistently, avoiding the gcc error that using a fixed size stack
variable triggers
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
---
procinterrupts.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/procinterrupts.c b/procinterrupts.c
index 1aa4413..4ef8751 100644
--- a/procinterrupts.c
+++ b/procinterrupts.c
@@ -170,7 +170,7 @@ GList* collect_full_irq_list()
int number;
struct irq_info *info;
char *c;
- char savedline[1024];
+ char *savedline = NULL;
if (getline(&line, &size, file)==0)
break;
@@ -186,7 +186,7 @@ GList* collect_full_irq_list()
if (!c)
continue;
- strncpy(savedline, line, sizeof(savedline));
+ savedline = strdup(line);
irq_name = strtok_r(savedline, " ", &savedptr);
last_token = strtok_r(NULL, " ", &savedptr);
while ((p = strtok_r(NULL, " ", &savedptr))) {
@@ -224,6 +224,7 @@ GList* collect_full_irq_list()
info->name = strdupa(irq_mod);
tmp_list = g_list_append(tmp_list, info);
}
+ free(savedline);
}
fclose(file);
free(line);
--
1.8.3.1

View File

@ -0,0 +1,72 @@
From 0ba1d8a59e209cef20955b8437989e730cd19cb3 Mon Sep 17 00:00:00 2001
From: Xiao Liang <xiliang@redhat.com>
Date: Thu, 18 Oct 2018 21:50:33 +0800
Subject: [PATCH 099/112] procinterrupts: check xen-dyn-event more flexible
In current /proc/interrupts, the 'xen-dyn-event' was split to 'xen-dyn -event'.
It causes interrupts not balanced inside xen guest.
Below result is without this patch:
70: 29 0 0 0 xen-dyn -event vif0-q0-tx
71: 120 0 0 0 xen-dyn -event vif0-q0-rx
72: 586350 0 0 0 xen-dyn -event vif0-q1-tx
73: 44 0 0 0 xen-dyn -event vif0-q1-rx
74: 19 0 0 0 xen-dyn -event vif0-q2-tx
75: 179 0 0 0 xen-dyn -event vif0-q2-rx
76: 67 0 0 0 xen-dyn -event vif0-q3-tx
77: 299637 0 0 0 xen-dyn -event vif0-q3-rx
Below result is with this patch:
[root@dhcp-3-194 ~]# grep vif0 /proc/interrupts
70: 30 0 0 0 xen-dyn -event vif0-q0-tx
71: 305 0 11 0 xen-dyn -event vif0-q0-rx
72: 586354 0 27 0 xen-dyn -event vif0-q1-tx
73: 49 7 5 0 xen-dyn -event vif0-q1-rx
74: 27 0 0 509373 xen-dyn -event vif0-q2-tx
75: 420 0 5 0 xen-dyn -event vif0-q2-rx
76: 179 0 38 0 xen-dyn -event vif0-q3-tx
77: 299803 281433 0 0 xen-dyn -event vif0-q3-rx
Signed-off-by: Xiao Liang <xiliang@redhat.com>
---
procinterrupts.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/procinterrupts.c b/procinterrupts.c
index 7283998..2c8118a 100644
--- a/procinterrupts.c
+++ b/procinterrupts.c
@@ -168,6 +168,7 @@ GList* collect_full_irq_list()
while (!feof(file)) {
int number;
+ int is_xen_dyn = 0;
struct irq_info *info;
char *c;
char *savedline = NULL;
@@ -188,9 +189,13 @@ GList* collect_full_irq_list()
savedline = strdup(line);
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;
}
@@ -210,7 +215,7 @@ GList* collect_full_irq_list()
info = calloc(sizeof(struct irq_info), 1);
if (info) {
info->irq = number;
- if (strstr(irq_name, "xen-dyn-event") != NULL) {
+ if (strstr(irq_name, "-event") != NULL && is_xen_dyn == 1) {
info->type = IRQ_TYPE_VIRT_EVENT;
info->class = IRQ_VIRT_EVENT;
} else {
--
1.8.3.1