!15 Rebase to v1.7.0

Merge pull request !15 from SuperSix173/openEuler-20.03-LTS
This commit is contained in:
openeuler-ci-bot 2020-08-17 09:14:28 +08:00 committed by Gitee
commit e2b4a3d61e
62 changed files with 49 additions and 6811 deletions

View File

@ -1,29 +0,0 @@
From 7dafc4d5c8d8229f107c90d97f33a4094eb89c6e Mon Sep 17 00:00:00 2001
From: liuchao173 <liuchao173@huawei.com>
Date: Thu, 7 Nov 2019 09:12:42 +0000
Subject: [PATCH 1/8] backport: Checking return value of strdup() in
collect_full_irq_list()
strdup() may return NULL if memory allocation fail, checking the return
value before reference.
Signed-off-by: Yunfeng Ye <yeyunfeng@huawei.com>
---
procinterrupts.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/procinterrupts.c b/procinterrupts.c
index 2c8118a..87fae2f 100644
--- a/procinterrupts.c
+++ b/procinterrupts.c
@@ -188,6 +188,8 @@ GList* collect_full_irq_list()
continue;
savedline = strdup(line);
+ if (!savedline)
+ break;
irq_name = strtok_r(savedline, " ", &savedptr);
if (strstr(irq_name, "xen-dyn") != NULL)
is_xen_dyn = 1;
--
2.19.1

View File

@ -1,65 +0,0 @@
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);
}
diff --git a/ui/irqbalance-ui.c b/ui/irqbalance-ui.c
index 5a76ddf..005eea4 100644
--- a/ui/irqbalance-ui.c
+++ b/ui/irqbalance-ui.c
@@ -66,6 +66,7 @@ int init_connection()
memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
if (connect(socket_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ close(socket_fd);
return 0;
}
--
1.8.3.1

View File

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

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

@ -1,57 +0,0 @@
From ce806df0081cf09344197285e32bd2113d86f554 Mon Sep 17 00:00:00 2001
From: Kairui Song <kasong@redhat.com>
Date: Mon, 3 Sep 2018 00:30:14 +0800
Subject: [PATCH 23/58] Fix irqbalance ui failing to connect to irqbalance
daemon
irqbalance ui is faling due to the changes in commit 19c25dd.
This patch align irqbalance-ui's socket connecting routine with
irqbalance.c
---
ui/irqbalance-ui.c | 16 +++++++++++-----
ui/irqbalance-ui.h | 1 +
2 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/ui/irqbalance-ui.c b/ui/irqbalance-ui.c
index 47dd5dc..5a76ddf 100644
--- a/ui/irqbalance-ui.c
+++ b/ui/irqbalance-ui.c
@@ -57,12 +57,18 @@ 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, socket_name, strlen(addr.sun_path));
- if(connect(socket_fd, (struct sockaddr *)&addr,
- sizeof(sa_family_t) + strlen(socket_name) + 1) < 0) {
- return 0;
+ snprintf(socket_name, 64, "%s/%s%d.sock", SOCKET_TMPFS, SOCKET_PATH, irqbalance_pid);
+ strncpy(addr.sun_path, socket_name, strlen(socket_name));
+
+ if(connect(socket_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ /* Try connect to abstract */
+ memset(&addr, 0, sizeof(struct sockaddr_un));
+ addr.sun_family = AF_UNIX;
+ if (connect(socket_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ return 0;
+ }
+
}
return socket_fd;
diff --git a/ui/irqbalance-ui.h b/ui/irqbalance-ui.h
index f97fcb1..b32d58a 100644
--- a/ui/irqbalance-ui.h
+++ b/ui/irqbalance-ui.h
@@ -8,6 +8,7 @@
#include <glib-unix.h>
#define SOCKET_PATH "irqbalance"
+#define SOCKET_TMPFS "/var/run"
#define STATS "stats"
#define SET_SLEEP "settings sleep "
--
1.8.3.1

View File

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

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

@ -1,54 +0,0 @@
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");
diff --git a/ui/irqbalance-ui.c b/ui/irqbalance-ui.c
index 005eea4..1119665 100644
--- a/ui/irqbalance-ui.c
+++ b/ui/irqbalance-ui.c
@@ -56,10 +56,9 @@ int init_connection()
return 0;
}
addr.sun_family = AF_UNIX;
- char socket_name[64];
- snprintf(socket_name, 64, "%s/%s%d.sock", SOCKET_TMPFS, SOCKET_PATH, irqbalance_pid);
- strncpy(addr.sun_path, socket_name, strlen(socket_name));
+ snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s%d.sock", SOCKET_TMPFS,
+ SOCKET_PATH, irqbalance_pid);
if(connect(socket_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
/* Try connect to abstract */
--
1.8.3.1

View File

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

@ -1,61 +0,0 @@
From 07032f71ea956ca195c9b2386d09d24b07b7133f Mon Sep 17 00:00:00 2001
From: hejingxian <hejingxian@huawei.com>
Date: Tue, 12 Nov 2019 10:59:20 +0800
Subject: [PATCH] Prevent inserting a duplicate entry to avoid list chaos
Introduced by bugfix-force-irq-into-rebalance-list-when-irq-removed-and-reinserted.patch
and 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
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 bugfix-fix-two-same-irq-insert-to-list.patch and add protection
in force_rebalance_irq instead.
---
classify.c | 2 +-
irqbalance.c | 4 ++++
irqbalance.h | 1 +
3 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/classify.c b/classify.c
index f041054..5aed9e5 100644
--- a/classify.c
+++ b/classify.c
@@ -263,7 +263,7 @@ static int get_irq_class(const char *devpath)
return irq_class;
}
-static gint compare_ints(gconstpointer a, gconstpointer b)
+gint compare_ints(gconstpointer a, gconstpointer b)
{
const struct irq_info *ai = a;
const struct irq_info *bi = b;
diff --git a/irqbalance.c b/irqbalance.c
index 395669c..faa8e6a 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -251,6 +251,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 c07a4fc..1befb46 100644
--- a/irqbalance.h
+++ b/irqbalance.h
@@ -113,6 +113,7 @@ 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 gint compare_ints(gconstpointer a, gconstpointer b);
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);
--
1.8.3.1

View File

@ -1,29 +0,0 @@
From 73c26ac2d6e856c5a9ffd1c48ed7c1abc85de3df Mon Sep 17 00:00:00 2001
From: liuchao <liuchao173@huawei.com>
Date: Sat, 12 Oct 2019 03:34:44 +0000
Subject: [PATCH] irqbalance: change irq ban check path to devpath
keep the parameters 'path' of check_for_irq_ban function consistent with line 699.
In check_for_irq_ban,
sprintf(cmd, "%s %s %d > /dev/null",banscript, path, irq);
the banscript is unique, so the path should keep consistent.
---
classify.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/classify.c b/classify.c
index 7c97d47..3681c48 100644
--- a/classify.c
+++ b/classify.c
@@ -719,7 +719,7 @@ struct irq_info *build_one_dev_entry(const char *dirname, GList *tmp_list)
if (user_policy_list == NULL) {
get_irq_user_policy(devpath, irqnum, &pol);
}
- if ((pol.ban == 1) || (check_for_irq_ban(path, irqnum, tmp_list))) {
+ if ((pol.ban == 1) || (check_for_irq_ban(devpath, irqnum, tmp_list))) {
add_banned_irq(irqnum, &banned_irqs, 0);
goto done;
}
--
2.19.1

View File

@ -1,29 +0,0 @@
From 0d6ed42e5d195f6a00d2f000ce8da11e89cb3010 Mon Sep 17 00:00:00 2001
From: caihongda <caihongda@huawei.com>
Date: Fri, 1 Nov 2019 10:06:03 +0800
Subject: [PATCH] irqbalance: bufix in banned irq delete
reason: The banned irq will not be added int interrupts_db, so
we need to additionaly delete it if it is no_existing.
To test this in llt, we add a stub for function
is_banned_irq.
Signed-off-by: caihongda <caihongda@huawei.com>
diff --git a/classify.c b/classify.c
index 9f72ae8..585f2dc 100644
--- a/classify.c
+++ b/classify.c
@@ -853,6 +860,9 @@ static void remove_no_existing_irq(struct irq_info *info, void *data __attribute
void clear_no_existing_irqs(void)
{
for_each_irq(NULL, remove_no_existing_irq, NULL);
+ if (banned_irqs){
+ for_each_irq(banned_irqs, remove_no_existing_irq, NULL);
+ }
}
void free_irq_db(void)
--
2.19.1

View File

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

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

@ -1,34 +0,0 @@
From f3c1502c83f5ae09202a707669c924fc2bd0cca4 Mon Sep 17 00:00:00 2001
From: liuchao173 <liuchao173@huawei.com>
Date: Mon, 18 Nov 2019 13:57:11 +0000
Subject: [PATCH] irqblance: fix memory leak of strdup
fix memory leak of strdup in collect_full_irq_list(), when continue
in if branch, the savedline isn't freed
---
procinterrupts.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/procinterrupts.c b/procinterrupts.c
index e36fcac..bde31f4 100644
--- a/procinterrupts.c
+++ b/procinterrupts.c
@@ -321,6 +321,7 @@ GList* collect_full_irq_list()
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);
+ free(savedline);
continue;
}
@@ -338,6 +339,7 @@ GList* collect_full_irq_list()
* For these irqs, we can add these to banned irq list.
*/
add_banned_list_irq(number);
+ free(savedline);
continue;
}
#endif
--
2.19.1

View File

@ -1,161 +0,0 @@
From feeb95206e1f178e2bbf0393483861f364bd7d5b Mon Sep 17 00:00:00 2001
From: liuchao173 <liuchao173@huawei.com>
Date: Wed, 23 Oct 2019 11:38:17 +0000
Subject: [PATCH] irqbalance: fix new irqs in hotplug keep stay on one numa node
when the number of cpus is huge, hotplug occurs and new irqs will stay on one numa node
---
classify.c | 25 +++++++++++++++++++++++++
procinterrupts.c | 24 +++++++++++++++++++++---
rules_config.c | 4 ++++
3 files changed, 50 insertions(+), 3 deletions(-)
diff --git a/classify.c b/classify.c
index 3681c48..54f27f0 100644
--- a/classify.c
+++ b/classify.c
@@ -38,6 +38,7 @@ static GList *banned_irqs = NULL;
GList *cl_banned_irqs = NULL;
static GList *cl_banned_modules = NULL;
static GList *vm_banned_irqs = NULL;
+extern int need_add_single;
#define SYSFS_DIR "/sys"
#define SYSPCI_DIR "/sys/bus/pci/devices"
@@ -646,6 +647,21 @@ static int check_for_irq_ban(char *path __attribute__((unused)), int irq, GList
return 0;
}
+int is_proc_irq_info_exist(int irq, GList *tmp_list)
+{
+ GList *entry;
+ struct irq_info find;
+
+ if (!tmp_list) {
+ return 1;
+ }
+
+ find.irq = irq;
+ entry = g_list_find_custom(tmp_list, &find, compare_ints);
+
+ return entry ? 1 : 0;
+}
+
/*
* Figures out which interrupt(s) relate to the device we"re looking at in dirname
*/
@@ -686,6 +702,12 @@ struct irq_info *build_one_dev_entry(const char *dirname, GList *tmp_list)
add_banned_irq(irqnum, &banned_irqs, 0);
continue;
}
+ if (!is_proc_irq_info_exist(irqnum, tmp_list)) {
+ continue;
+ }
+ if (need_add_single && need_add_single != irqnum) {
+ continue;
+ }
hint.irq = irqnum;
hint.type = IRQ_TYPE_MSIX;
new = add_one_irq_to_db(devpath, &hint, &pol);
@@ -723,6 +745,9 @@ struct irq_info *build_one_dev_entry(const char *dirname, GList *tmp_list)
add_banned_irq(irqnum, &banned_irqs, 0);
goto done;
}
+ if (!is_proc_irq_info_exist(irqnum, tmp_list)) {
+ goto done;
+ }
hint.irq = irqnum;
hint.type = IRQ_TYPE_LEGACY;
diff --git a/procinterrupts.c b/procinterrupts.c
index c32c1b2..f0dd608 100644
--- a/procinterrupts.c
+++ b/procinterrupts.c
@@ -43,6 +43,7 @@
static int proc_int_has_msi = 0;
static int msi_found_in_sysfs = 0;
extern int ban_pci_assigned_irq;
+int need_add_single = 0;
#ifdef AARCH64
struct irq_match {
@@ -361,9 +362,10 @@ void parse_proc_interrupts(void)
uint64_t count;
char *c, *c2;
struct irq_info *info;
- struct irq_info tmp_info;
- char savedline[1024];
+ struct irq_info tmp_info = {0};
+ char *savedline = NULL;
char dirname[PATH_MAX] = {'\0'};
+ struct irq_info *lookup;
if (getline(&line, &size, file)<=0)
break;
@@ -383,7 +385,9 @@ void parse_proc_interrupts(void)
if (!c)
continue;
- strncpy(savedline, line, sizeof(savedline)-1);
+ savedline = strdup(line);
+ if (!savedline)
+ continue;
*c = 0;
c++;
@@ -391,23 +395,36 @@ void parse_proc_interrupts(void)
info = get_irq_info(number);
if (!info) {
+ init_irq_class_and_type(savedline, &tmp_info, number);
find_irq_dev_path(number, dirname, PATH_MAX);
if (strlen(dirname) > 0) {
+ need_add_single = number;
info = build_one_dev_entry(dirname, NULL);
+ need_add_single = 0;
+ lookup = get_irq_info(number);
+ if (lookup != NULL) {
+ lookup->existing = 1;
+ set_usr_irq_policy(tmp_info.name, lookup);
+ }
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 (tmp_info.name) {
+ free(tmp_info.name);
+ tmp_info.name = 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;
+ free(savedline);
break;
}
}
+ free(savedline);
info->existing = 1;
if (ban_pci_assigned_irq) {
diff --git a/rules_config.c b/rules_config.c
index 767e9e1..9313fc6 100644
--- a/rules_config.c
+++ b/rules_config.c
@@ -43,6 +43,10 @@ void set_usr_irq_policy(char *name, struct irq_info *info)
{
USER_IRQ_POLICY *user_policy;
+ if (user_policy_list == NULL) {
+ return;
+ }
+
user_policy = get_usr_irq_policy(name);
if (user_policy != NULL) {
if (user_policy->numa_node_set) {
--
2.19.1

View File

@ -1,25 +0,0 @@
From d4fc2426a38728b912ec1acf3a3a990636e48b1d Mon Sep 17 00:00:00 2001
From: liuchao173 <liuchao173@huawei.com>
Date: Fri, 1 Nov 2019 02:42:19 +0000
Subject: [PATCH] irqbalance: fix new msi irq hasnot been added to rebalance list
fix new msi irq hasnot been added to rebalance_irq_list
---
procinterrupts.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/procinterrupts.c b/procinterrupts.c
index 64b462a..33e72ea 100644
--- a/procinterrupts.c
+++ b/procinterrupts.c
@@ -405,6 +405,7 @@ void parse_proc_interrupts(void)
if (lookup != NULL) {
lookup->existing = 1;
set_usr_irq_policy(tmp_info.name, lookup);
+ info = lookup;
}
log(TO_CONSOLE, LOG_INFO, "new IRQ %d added into database, dirname %s\n", number, dirname);
} else {
--
2.19.1

View File

@ -1,79 +0,0 @@
From f04d6488c12e215e2302b44c77bf66fce4950aef Mon Sep 17 00:00:00 2001
From: liuchao <liuchao173@huawei.com>
Date: Thu, 5 Dec 2019 15:28:14 +0800
Subject: [PATCH] fix sleep interval when sleep_interval is changed by
socket
currently, in scan, irqbalance compare sleep_interval's address to decide if sleep_interval is changed, accutually this judgement is always false now.
Signed-off-by: liuchao <liuchao173@huawei.com>
---
hint_verify.c | 10 ++++++----
irqbalance.c | 5 +++--
2 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/hint_verify.c b/hint_verify.c
index b3175ae..0718078 100644
--- a/hint_verify.c
+++ b/hint_verify.c
@@ -15,6 +15,7 @@
extern int keep_going;
extern GMainLoop *main_loop;
extern gboolean scan();
+extern int last_interval;
int real_sleep_interval;
int sleep_interval_count;
diff --git a/hint_verify.c b/hint_verify.c
index b3175ae..4258557 100644
--- a/hint_verify.c
+++ b/hint_verify.c
@@ -84,7 +84,7 @@ void update_affinity_hint(struct irq_info *info, void *data __attribute__((unuse
* 1. scan opration for irq balancing;
* 2. poll irq affinity hint changes for quickly applying them.
*/
-gboolean poll_hint_affinity_and_scan(gpointer data)
+gboolean poll_hint_affinity_and_scan(gpointer data __attribute__((unused)))
{
gboolean need_verify_flag = FALSE;
gboolean need_scan_flag = FALSE;
@@ -118,9 +118,10 @@ gboolean poll_hint_affinity_and_scan(gpointer data)
}
}
- if (data != &real_sleep_interval) {
- data = &real_sleep_interval;
- g_timeout_add_seconds(real_sleep_interval, poll_hint_affinity_and_scan, data);
+ update_interval_and_count();
+ if (last_interval != real_sleep_interval) {
+ last_interval = real_sleep_interval;
+ g_timeout_add_seconds(real_sleep_interval, poll_hint_affinity_and_scan, NULL);
return FALSE;
}
diff --git a/irqbalance.c b/irqbalance.c
index 3fc00db..05eaa29 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -67,6 +67,7 @@ long HZ;
int sleep_interval = SLEEP_INTERVAL;
int hint_enabled = 0;
int poll_hint_interval = SLEEP_INTERVAL / 5;
+int last_interval;
GMainLoop *main_loop;
char *banned_cpumask_from_ui = NULL;
@@ -641,8 +642,8 @@ int main(int argc, char** argv)
log(TO_ALL, LOG_INFO, "irqbalance start scan.\n");
update_interval_and_count();
main_loop = g_main_loop_new(NULL, FALSE);
- int *last_interval = &real_sleep_interval;
- g_timeout_add_seconds(real_sleep_interval, poll_hint_affinity_and_scan, last_interval);
+ last_interval = real_sleep_interval;
+ g_timeout_add_seconds(real_sleep_interval, poll_hint_affinity_and_scan, NULL);
g_main_loop_run(main_loop);
g_main_loop_quit(main_loop);
--
2.19.1

View File

@ -1,64 +0,0 @@
From f4d052d7b210612a7ffbdd7c3cfbce213c9a0e21 Mon Sep 17 00:00:00 2001
From: liuchao173 <liuchao173@huawei.com>
Date: Fri, 8 Nov 2019 08:47:43 +0000
Subject: [PATCH] irqbalance: fix strcat may cause buffer overrun
when the sum length of irq_name and saveptr is more than PATH_MAX, strcat will cause buffer overrun
---
procinterrupts.c | 26 ++++++++++++++++++--------
1 file changed, 18 insertions(+), 8 deletions(-)
diff --git a/procinterrupts.c b/procinterrupts.c
index 373d8b5..0b24b56 100644
--- a/procinterrupts.c
+++ b/procinterrupts.c
@@ -205,6 +205,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_valid = 1;
char irq_fullname[PATH_MAX] = {0};
#endif
@@ -236,12 +237,16 @@ static void init_irq_class_and_type(char *savedline, struct irq_info *info, int
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;
+ if (strlen(irq_name) + strlen(savedptr) + 1 < PATH_MAX) {
+ strcat(irq_fullname, irq_name);
+ strcat(irq_fullname, " ");
+ strcat(irq_fullname, savedptr);
+ tmp = strchr(irq_fullname, '\n');
+ if (tmp)
+ *tmp = 0;
+ } else {
+ irq_fullname_valid = 0;
+ }
#endif
irq_mod = last_token;
info->irq = irq;
@@ -251,8 +256,13 @@ 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);
+ if (irq_fullname_valid) {
+ irq_name = irq_fullname;
+ guess_arm_irq_hints(irq_name, info);
+ } else {
+ info->type = IRQ_TYPE_LEGACY;
+ info->class = IRQ_OTHER;
+ }
#else
info->type = IRQ_TYPE_LEGACY;
info->class = IRQ_OTHER;
--
2.19.1

View File

@ -1,471 +0,0 @@
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,10 @@ extern void free_cl_opts(void);
extern void add_cl_banned_module(char *modname);
#define irq_numa_node(irq) ((irq)->numa_node)
+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;
@@ -188,45 +222,13 @@ GList* collect_full_irq_list()
savedline = strdup(line);
if (!savedline)
break;
- irq_name = strtok_r(savedline, " ", &savedptr);
- if (strstr(irq_name, "xen-dyn") != NULL)
- is_xen_dyn = 1;
- last_token = strtok_r(NULL, " ", &savedptr);
- while ((p = strtok_r(NULL, " ", &savedptr))) {
- irq_name = last_token;
- if (strstr(irq_name, "xen-dyn") != NULL)
- is_xen_dyn = 1;
- last_token = p;
- }
-
-#ifdef AARCH64
- /* Of course the formatting for /proc/interrupts is different on different arches */
- irq_name = last_token;
- tmp = strchr(irq_name, '\n');
- if (tmp)
- *tmp = 0;
-#endif
- irq_mod = last_token;
-
*c = 0;
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 = strdup(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

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

@ -1,125 +0,0 @@
From 948425c293615a9f4a30e9049d6ca4380c7b6c83 Mon Sep 17 00:00:00 2001
From: hejingxian <hejingxian@huawei.com>
Date: Wed, 13 Nov 2019 13:13:28 +0800
Subject: [PATCH] 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 | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 75 insertions(+), 8 deletions(-)
diff --git a/irqbalance.c b/irqbalance.c
index 18cd7de..467e968 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -560,6 +560,78 @@ 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;
+ }
+ }
+ close(lf);
+ return 0;
+
+error_close_unlink:
+ (void) unlink(lockfile);
+
+error_close:
+ close(lf);
+ return err;
+}
+
+
int main(int argc, char** argv)
{
sigset_t sigset, old_sigset;
@@ -652,17 +724,12 @@ 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) {
+ ret = EXIT_FAILURE;
+ goto out;
}
}
--
1.8.3.1

View File

@ -1,118 +0,0 @@
From 74970054568728d11dbbb160e0c5cacdfeb07ff3 Mon Sep 17 00:00:00 2001
From: liuchao <liuchao173@huawei.com>
Date: Fri, 11 Oct 2019 07:49:55 +0000
Subject: [PATCH] irqbalance: make the return value of getline() handled correct
getline() will return -1 when fail, so make the return value handle correct.
---
activate.c | 2 +-
cputree.c | 6 +++---
procinterrupts.c | 12 ++++++------
3 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/activate.c b/activate.c
index ad60fde..87336f4 100644
--- a/activate.c
+++ b/activate.c
@@ -47,7 +47,7 @@ static int check_affinity(struct irq_info *info, cpumask_t applied_mask)
file = fopen(buf, "r");
if (!file)
return 1;
- if (getline(&line, &size, file)==0) {
+ if (getline(&line, &size, file)<=0) {
free(line);
fclose(file);
return 1;
diff --git a/cputree.c b/cputree.c
index 0dbb5c8..51ef357 100644
--- a/cputree.c
+++ b/cputree.c
@@ -324,7 +324,7 @@ static void do_one_cpu(char *path)
if (file) {
char *line = NULL;
size_t size = 0;
- if (getline(&line, &size, file))
+ if (getline(&line, &size, file) > 0)
cpumask_parse_user(line, strlen(line), package_mask);
fclose(file);
free(line);
@@ -336,7 +336,7 @@ static void do_one_cpu(char *path)
if (file) {
char *line = NULL;
size_t size = 0;
- if (getline(&line, &size, file))
+ if (getline(&line, &size, file) > 0)
packageid = strtoul(line, NULL, 10);
fclose(file);
free(line);
@@ -369,7 +369,7 @@ static void do_one_cpu(char *path)
if (file) {
char *line = NULL;
size_t size = 0;
- if (getline(&line, &size, file))
+ if (getline(&line, &size, file) > 0)
cpumask_parse_user(line, strlen(line), cache_mask);
fclose(file);
free(line);
diff --git a/procinterrupts.c b/procinterrupts.c
index 18b3ceb..c32c1b2 100644
--- a/procinterrupts.c
+++ b/procinterrupts.c
@@ -262,7 +262,7 @@ GList* collect_full_irq_list()
return NULL;
/* first line is the header we don't need; nuke it */
- if (getline(&line, &size, file)==0) {
+ if (getline(&line, &size, file)<=0) {
free(line);
fclose(file);
return NULL;
@@ -274,7 +274,7 @@ GList* collect_full_irq_list()
char *c;
char *savedline = NULL;
- if (getline(&line, &size, file)==0)
+ if (getline(&line, &size, file)<=0)
break;
/* lines with letters in front are special, like NMI count. Ignore */
@@ -349,7 +349,7 @@ void parse_proc_interrupts(void)
return;
/* first line is the header we don't need; nuke it */
- if (getline(&line, &size, file)==0) {
+ if (getline(&line, &size, file)<=0) {
free(line);
fclose(file);
return;
@@ -365,7 +365,7 @@ void parse_proc_interrupts(void)
char savedline[1024];
char dirname[PATH_MAX] = {'\0'};
- if (getline(&line, &size, file)==0)
+ if (getline(&line, &size, file)<=0)
break;
if (!proc_int_has_msi)
@@ -579,7 +579,7 @@ void parse_proc_stat(void)
}
/* first line is the header we don't need; nuke it */
- if (getline(&line, &size, file)==0) {
+ if (getline(&line, &size, file)<=0) {
free(line);
log(TO_ALL, LOG_WARNING, "WARNING read /proc/stat. balancing is broken\n");
fclose(file);
@@ -588,7 +588,7 @@ void parse_proc_stat(void)
cpucount = 0;
while (!feof(file)) {
- if (getline(&line, &size, file)==0)
+ if (getline(&line, &size, file)<=0)
break;
if (!strstr(line, "cpu"))
--
2.19.1

View File

@ -1,27 +0,0 @@
From cea147fc56b018266ac3235b82cdaf7d0ba74628 Mon Sep 17 00:00:00 2001
From: hejingxian <hejingxian@huawei.com>
Date: Fri, 10 Jan 2020 15:36:57 +0800
Subject: [PATCH] prevent version cmd need an argument
In order to prevent the version cmd need an argument,
the option 'V' can't be followed by ':'.
---
irqbalance.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/irqbalance.c b/irqbalance.c
index 15fb0fe..f182b3c 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -133,7 +133,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:r:ne:g:",
+ "odfjVni:p:s:c:b:l:m:t:h:v:r:e:g:",
lopts, &longind)) != -1) {
switch(opt) {
--
1.8.3.1

View File

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

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

@ -1,106 +0,0 @@
From 22a40e9d0dd59ee58ff06d2b6360007e046d608f Mon Sep 17 00:00:00 2001
From: liuchao173 <liuchao173@huawei.com>
Date: Thu, 7 Nov 2019 09:33:47 +0000
Subject: [PATCH 6/8] irqbalance: correct to use realloc() function
The man doc about realloc() say:
"
If realloc() fails the original block is left untouched; it is not
freed or move
"
So make the handling of realloc() function correctly.
In addition, there is another problem about parameter using in
sock_handle(), it should be use the address of @setup instead of @setup.
Signed-off-by: Yunfeng Ye <yeyunfeng@huawei.com>
---
irqbalance.c | 33 +++++++++++++++++++++++----------
1 file changed, 23 insertions(+), 10 deletions(-)
diff --git a/irqbalance.c b/irqbalance.c
index c9378d0..cace4d8 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -321,14 +321,18 @@ gboolean scan(gpointer data)
void get_irq_data(struct irq_info *irq, void *data)
{
char **irqdata = (char **)data;
+ char *newptr = NULL;
+
if (!*irqdata)
- *irqdata = calloc(24 + 1 + 11 + 20 + 20 + 11, 1);
+ newptr = calloc(24 + 1 + 11 + 20 + 20 + 11, 1);
else
- *irqdata = realloc(*irqdata, strlen(*irqdata) + 24 + 1 + 11 + 20 + 20 + 11);
+ newptr = realloc(*irqdata, strlen(*irqdata) + 24 + 1 + 11 + 20 + 20 + 11);
- if (!*irqdata)
+ if (!newptr)
return;
+ *irqdata = newptr;
+
sprintf(*irqdata + strlen(*irqdata),
"IRQ %d LOAD %lu DIFF %lu CLASS %d ", irq->irq, irq->load,
(irq->irq_count - irq->last_irq_count), irq->class);
@@ -338,6 +342,7 @@ void get_object_stat(struct topo_obj *object, void *data)
{
char **stats = (char **)data;
char *irq_data = NULL;
+ char *newptr = NULL;
size_t irqdlen;
if (g_list_length(object->interrupts) > 0) {
@@ -355,13 +360,17 @@ void get_object_stat(struct topo_obj *object, void *data)
* This should be adjusted if the string in the sprintf is changed
*/
if (!*stats) {
- *stats = calloc(irqdlen + 31 + 11 + 20 + 11 + 1, 1);
+ newptr = calloc(irqdlen + 31 + 11 + 20 + 11 + 1, 1);
} else {
- *stats = realloc(*stats, strlen(*stats) + irqdlen + 31 + 11 + 20 + 11 + 1);
+ newptr = realloc(*stats, strlen(*stats) + irqdlen + 31 + 11 + 20 + 11 + 1);
}
- if (!*stats)
+ if (!newptr) {
+ free(irq_data);
return;
+ }
+
+ *stats = newptr;
sprintf(*stats + strlen(*stats), "TYPE %d NUMBER %d LOAD %lu SAVE_MODE %d %s",
object->obj_type, object->number, object->load,
@@ -475,19 +484,23 @@ 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);
+ char *newptr = NULL;
if (!setup)
goto out_close;
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);
+ 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);
- if (!setup)
- goto out_close;
+ newptr = realloc(setup, strlen(setup) + strlen(banned) + 7 + 1);
+ if (!newptr)
+ goto out_free_setup;
+
+ setup = newptr;
snprintf(setup + strlen(setup), strlen(banned) + 7 + 1,
"BANNED %s", banned);
send(sock, setup, strlen(setup), 0);
+out_free_setup:
free(setup);
}
--
2.19.1

View File

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

@ -1,121 +0,0 @@
From 84a2df1c9962a87f55e1c0d3bd2118fd754a4b48 Mon Sep 17 00:00:00 2001
From: hejingxian <hejingxian@huawei.com>
Date: Fri, 3 Jan 2020 16:43:28 +0800
Subject: [PATCH] add new irq migrate rule to avoid high cpu irq load
By the old irq migrate rule, the irqs cannot be moved if the adjustment_load will become smaller then
the min_load after moving irq. However, we can accept that the delta load become smaller after moving irq.
---
irqbalance.c | 14 ++++++++++++--
irqbalance.h | 3 ++-
irqlist.c | 15 ++++++++++++++-
3 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/irqbalance.c b/irqbalance.c
index 1ca401e..15fb0fe 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -69,6 +69,8 @@ int sleep_interval = SLEEP_INTERVAL;
int last_interval;
int hint_enabled = 0;
int poll_hint_interval = SLEEP_INTERVAL / 5;
+unsigned long migrate_val = 0;
+unsigned long load_limit = 0;
GMainLoop *main_loop;
char *cpu_ban_string = NULL;
@@ -106,6 +108,8 @@ struct option lopts[] = {
{"verifyhint", 1, NULL, 'v'},
{"rulesconfig", 1, NULL, 'r'},
{"notclearhint", 0, NULL, 'n'},
+ {"migrateval", 1, NULL, 'e'},
+ {"loadlimit", 1, NULL, 'g'},
{0, 0, 0, 0}
};
@@ -114,7 +118,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, " [--rulesconfig= | -r <config>] [--notclearhint | -n]\n");
+ log(TO_CONSOLE, LOG_INFO, " [--rulesconfig= | -r <config>] [--notclearhint | -n] [--migrateval= | -e <n>] [--loadlimit= | -g <n>]\n");
}
static void version(void)
@@ -129,7 +133,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:r:n",
+ "odfji:p:s:c:b:l:m:t:V:h:v:r:ne:g:",
lopts, &longind)) != -1) {
switch(opt) {
@@ -231,6 +235,12 @@ static void parse_command_line(int argc, char **argv)
case 'n':
clear_affinity_hint = 0;
break;
+ case 'e':
+ migrate_val = strtoul(optarg, NULL, 10);
+ break;
+ case 'g':
+ load_limit = strtoul(optarg, NULL, 10);
+ break;
}
}
diff --git a/irqbalance.h b/irqbalance.h
index 72e141b..d4f6e7a 100644
--- a/irqbalance.h
+++ b/irqbalance.h
@@ -124,7 +124,8 @@ extern struct irq_info *add_new_irq(int irq, struct irq_info *hint, GList *proc_
extern void clear_no_existing_irqs(void);
extern int hint_enabled, poll_hint_interval;
extern int sleep_interval;
-
+extern unsigned long migrate_val;
+extern unsigned long load_limit;
/*
* Generic object functions
*/
diff --git a/irqlist.c b/irqlist.c
index 95ccc7a..3c38b18 100644
--- a/irqlist.c
+++ b/irqlist.c
@@ -76,6 +76,7 @@ static void compute_deviations(struct topo_obj *obj, void *data)
static void move_candidate_irqs(struct irq_info *info, void *data)
{
struct load_balance_info *lb_info = data;
+ unsigned long delta_load = 0;
/* Don't rebalance irqs that don't want it */
if (info->level == BALANCE_NONE)
@@ -91,12 +92,24 @@ static void move_candidate_irqs(struct irq_info *info, void *data)
if (info->load <= 1)
return;
+ if (migrate_val > 0) {
+ delta_load = (lb_info->adjustment_load - lb_info->min_load) / migrate_val;
+ }
+
/* If we can migrate an irq without swapping the imbalance do it. */
if ((lb_info->adjustment_load - info->load) > (lb_info->min_load + info->load)) {
lb_info->adjustment_load -= info->load;
lb_info->min_load += info->load;
- } else
+ } else if (delta_load && load_limit && (lb_info->adjustment_load > load_limit) &&
+ (lb_info->min_load + info->load) - (lb_info->adjustment_load - info->load) < delta_load) {
+ lb_info->adjustment_load -= info->load;
+ lb_info->min_load += info->load;
+ if (lb_info->min_load > lb_info->adjustment_load) {
+ lb_info->min_load = lb_info->adjustment_load;
+ }
+ } else {
return;
+ }
log(TO_CONSOLE, LOG_INFO, "Selecting irq %d for rebalancing\n", info->irq);
--
1.8.3.1

View File

@ -1,488 +0,0 @@
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 | 38 +++++----
irqbalance.h | 2 +-
misc/irqbalance.service | 2 +-
placement.c | 3 +-
procinterrupts.c | 3 +-
rules_config.c | 172 ++++++++++++++++++++++++++++++++++++++++++++++++
rules_config.h | 40 +++++++++++
9 files changed, 271 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
+ irqlist.c numa.c placement.c procinterrupts.c rules_config.c
irqbalance_LDADD = $(LIBCAP_NG_LIBS) $(GLIB2_LIBS)
if IRQBALANCEUI
irqbalance_ui_SOURCES = $(UI_DIR)/helpers.c $(UI_DIR)/irqbalance-ui.c \
diff --git a/classify.c b/classify.c
index 65aeae2..7c97d47 100644
--- a/classify.c
+++ b/classify.c
@@ -663,7 +663,7 @@ struct irq_info *build_one_dev_entry(const char *dirname, GList *tmp_list)
sprintf(path, "%s/%s/msi_irqs", SYSPCI_DIR, dirname);
sprintf(devpath, "%s/%s", SYSPCI_DIR, dirname);
-
+ memset(&pol, -1, sizeof(struct user_irq_policy));
/* Needs to be further classified */
hint.class = IRQ_OTHER;
@@ -679,7 +679,9 @@ struct irq_info *build_one_dev_entry(const char *dirname, GList *tmp_list)
new = get_irq_info(irqnum);
if (new)
continue;
- get_irq_user_policy(devpath, irqnum, &pol);
+ if (user_policy_list == NULL) {
+ get_irq_user_policy(devpath, irqnum, &pol);
+ }
if ((pol.ban == 1) || (check_for_irq_ban(devpath, irqnum, tmp_list))) {
add_banned_irq(irqnum, &banned_irqs, 0);
continue;
@@ -714,7 +716,9 @@ struct irq_info *build_one_dev_entry(const char *dirname, GList *tmp_list)
new = get_irq_info(irqnum);
if (new)
goto done;
- get_irq_user_policy(devpath, irqnum, &pol);
+ if (user_policy_list == NULL) {
+ get_irq_user_policy(devpath, irqnum, &pol);
+ }
if ((pol.ban == 1) || (check_for_irq_ban(path, irqnum, tmp_list))) {
add_banned_irq(irqnum, &banned_irqs, 0);
goto done;
@@ -855,18 +859,24 @@ struct irq_info *add_new_irq(int irq, struct irq_info *hint, GList *proc_interru
struct irq_info *new = NULL;
struct user_irq_policy pol;
+ memset(&pol, -1, sizeof(struct user_irq_policy));
new = get_irq_info(irq);
if (new)
return new;
/* Set NULL devpath for the irq has no sysfs entries */
- get_irq_user_policy(NULL, irq, &pol);
+ if (user_policy_list == NULL) {
+ get_irq_user_policy(NULL, irq, &pol);
+ }
if ((pol.ban == 1) || check_for_irq_ban(NULL, irq, proc_interrupts)) { /*FIXME*/
add_banned_irq(irq, &banned_irqs, 0);
new = get_irq_info(irq);
- } else
+ } else {
new = add_one_irq_to_db(NULL, hint, &pol);
-
+ if ((new != NULL) && (user_policy_list != NULL)) {
+ set_usr_irq_policy(hint->name, new);
+ }
+ }
if (!new)
log(TO_CONSOLE, LOG_WARNING, "add_new_irq: Failed to add irq %d\n", irq);
@@ -880,6 +890,16 @@ static void add_missing_irq(struct irq_info *info, void *attr)
if (!lookup)
add_new_irq(info->irq, info, proc_interrupts);
+ else {
+ if (user_policy_list != NULL) {
+ set_usr_irq_policy(info->name, lookup);
+ }
+ }
+ if (info->name) {
+ free(info->name);
+ info->name = NULL;
+ }
+
}
static void free_tmp_irqs(gpointer data)
diff --git a/irqbalance.c b/irqbalance.c
index 21d578a..d41753c 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -99,6 +99,7 @@ struct option lopts[] = {
{"banmod", 1 , NULL, 'm'},
{"interval", 1 , NULL, 't'},
{"version", 0, NULL, 'V'},
+ {"rulesconfig", 1, NULL, 'r'},
{0, 0, 0, 0}
};
@@ -106,7 +107,7 @@ static void usage(void)
{
log(TO_CONSOLE, LOG_INFO, "irqbalance [--oneshot | -o] [--debug | -d] [--foreground | -f] [--journal | -j] [--hintpolicy= | -h [exact|subset|ignore]]\n");
log(TO_CONSOLE, LOG_INFO, " [--powerthresh= | -p <off> | <n>] [--banirq= | -i <n>] [--banmod= | -m <module>] [--policyscript= | -l <script>]\n");
- log(TO_CONSOLE, LOG_INFO, " [--pid= | -s <file>] [--deepestcache= | -c <n>] [--interval= | -t <n>]\n");
+ log(TO_CONSOLE, LOG_INFO, " [--pid= | -s <file>] [--deepestcache= | -c <n>] [--interval= | -t <n>] [--rulesconfig= | -r <config>]\n");
}
static void version(void)
@@ -121,7 +122,7 @@ static void parse_command_line(int argc, char **argv)
unsigned long val;
while ((opt = getopt_long(argc, argv,
- "odfji:p:s:c:b:l:m:t:V",
+ "odfji:p:s:c:b:l:m:t:V:r",
lopts, &longind)) != -1) {
switch(opt) {
@@ -201,6 +202,9 @@ static void parse_command_line(int argc, char **argv)
exit(1);
}
break;
+ case 'r':
+ rules_config_file = strdup(optarg);
+ break;
}
}
}
@@ -539,6 +543,25 @@ int main(int argc, char** argv)
log(TO_ALL, LOG_WARNING, "Unable to determin HZ defaulting to 100\n");
HZ = 100;
}
+ if (!foreground_mode) {
+ if (daemon(0,0)) {
+ ret = EXIT_FAILURE;
+ goto out;
+ }
+ /* Write pidfile */
+ if (pidfile && create_lock_pidfile(pidfile) < 0) {
+ ret = EXIT_FAILURE;
+ goto out;
+ }
+ }
+
+ if (read_user_policy_config() != 0) {
+ log(TO_ALL, LOG_WARNING, "Read user policy config fail.\n");
+ }
+ if (rules_config_file) {
+ free(rules_config_file);
+ rules_config_file = NULL;
+ }
build_object_tree();
if (debug_mode)
@@ -554,16 +573,6 @@ int main(int argc, char** argv)
goto out;
}
- if (!foreground_mode) {
- if (daemon(0,0))
- exit(EXIT_FAILURE);
- /* Write pidfile */
- if (pidfile && create_lock_pidfile(pidfile) < 0) {
- ret = EXIT_FAILURE;
- goto out;
- }
- }
-
g_unix_signal_add(SIGINT, handler, NULL);
g_unix_signal_add(SIGTERM, handler, NULL);
g_unix_signal_add(SIGUSR1, handler, NULL);
@@ -589,6 +598,7 @@ int main(int argc, char** argv)
ret = EXIT_FAILURE;
goto out;
}
+ log(TO_ALL, LOG_INFO, "irqbalance start scan.\n");
main_loop = g_main_loop_new(NULL, FALSE);
last_interval = sleep_interval;
g_timeout_add_seconds(sleep_interval, scan, NULL);
diff --git a/irqbalance.h b/irqbalance.h
index 120bc9b..42f95cb 100644
--- a/irqbalance.h
+++ b/irqbalance.h
@@ -14,7 +14,7 @@
#include "types.h"
#include "config.h"
-
+#include "rules_config.h"
#ifdef __aarch64__
#define AARCH64
#endif
diff --git a/misc/irqbalance.service b/misc/irqbalance.service
index ce0022c..2c002b2 100644
--- a/misc/irqbalance.service
+++ b/misc/irqbalance.service
@@ -5,7 +5,7 @@ After=syslog.target
[Service]
OOMScoreAdjust=-500
-Type=simple
+Type=forking
PIDFile=/var/run/irqbalance.pid
EnvironmentFile=/etc/sysconfig/irqbalance
ExecStart=/usr/sbin/irq_balancer
diff --git a/placement.c b/placement.c
index 19462bb..d887c60 100644
--- a/placement.c
+++ b/placement.c
@@ -53,8 +53,7 @@ static void find_best_object(struct topo_obj *d, void *data)
* also don't consider any node that doesn't have at least one cpu in
* the unbanned list
*/
- if ((d->obj_type == OBJ_TYPE_NODE) &&
- (!cpus_intersects(d->mask, unbanned_cpus)))
+ if (!cpus_intersects(d->mask, unbanned_cpus))
return;
if (d->powersave_mode)
diff --git a/procinterrupts.c b/procinterrupts.c
index 60b2545..18b3ceb 100644
--- a/procinterrupts.c
+++ b/procinterrupts.c
@@ -245,7 +245,8 @@ static void init_irq_class_and_type(char *savedline, struct irq_info *info, int
info->class = IRQ_OTHER;
#endif
}
- info->name = strdupa(irq_mod);
+
+ info->name = strdup(irq_mod);
}
diff --git a/rules_config.c b/rules_config.c
new file mode 100644
index 0000000..1270ac7
--- /dev/null
+++ b/rules_config.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2019. Huawei Technologies Co., Ltd. All rights reserved.
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include "irqbalance.h"
+
+char *rules_config_file = NULL;
+USER_IRQ_POLICY *user_policy_list = NULL;
+
+void add_usr_irq_policy(USER_IRQ_POLICY *policy)
+{
+ if (policy == NULL) {
+ return;
+ }
+ policy->next = user_policy_list;
+ user_policy_list = policy;
+}
+
+USER_IRQ_POLICY *get_usr_irq_policy(char *name)
+{
+ USER_IRQ_POLICY *p = user_policy_list;
+ if (name == NULL) {
+ return NULL;
+ }
+ while (p != NULL) {
+ if (strstr(name, p->irq_type) != NULL) {
+ return p;
+ }
+ p = p->next;
+ }
+ return NULL;
+}
+
+void set_usr_irq_policy(char *name, struct irq_info *info)
+{
+ USER_IRQ_POLICY *user_policy;
+
+ user_policy = get_usr_irq_policy(name);
+ if (user_policy != NULL) {
+ if (user_policy->numa_node_set) {
+ info->numa_node = get_numa_node(user_policy->numa_node);
+ log(TO_ALL, LOG_WARNING, "override irq (%d) numa_node to %d\n",
+ info->irq, user_policy->numa_node);
+ }
+ if (user_policy->balance_level_set) {
+ info->level = user_policy->balance_level;
+ log(TO_ALL, LOG_WARNING, "override irq (%d) balance_level to %d\n",
+ info->irq, info->level);
+ }
+ }
+
+}
+
+int read_user_policy_config()
+{
+ FILE *file;
+ char *line = NULL;
+ size_t size = 0;
+ size_t len;
+ char *key;
+ char *value;
+ char *c;
+ int level;
+ int node = -1;
+ char savedline[CONFIG_LINE_MAX_LEN] = {0};
+ USER_IRQ_POLICY *cur_policy = NULL;
+ char *levelvals[] = { "none", "package", "cache", "core" };
+
+ if (rules_config_file == NULL) {
+ return 0;
+ }
+ log(TO_ALL, LOG_INFO, "rules_config_file is: %s\n", rules_config_file);
+ file = fopen(rules_config_file, "r");
+ if (!file)
+ return -1;
+
+ while (!feof(file)) {
+ if (getline(&line, &size, file) <= 0)
+ break;
+ c = line;
+ if (*c == '#') {
+ continue;
+ }
+ len = strlen(line);
+ if (len > sizeof(savedline)-1) {
+ continue;
+ }
+ strncpy(savedline, line, len);
+ savedline[len] = '\0';
+ c = savedline;
+ while (*c == ' ') {
+ c++;
+ }
+ key = c;
+ /* make sure there is no space near '=' */
+ c = strchr(savedline, '=');
+ if (c != NULL) {
+ value = c + 1;
+ *c = '\0';
+ } else {
+ continue;
+ }
+ c = strchr(value, '\n');
+ if (c != NULL) {
+ *c = '\0';
+ }
+ if ((strlen(key) == 0) || (strlen(value) == 0)) {
+ continue;
+ }
+ log(TO_ALL, LOG_INFO, "User irq policy config read: key is %s, value is %s\n", key, value);
+ if (strcmp(key, "type") == 0) {
+ cur_policy = malloc(sizeof(USER_IRQ_POLICY));
+ if (cur_policy == NULL) {
+ goto out;
+ }
+ cur_policy->next = NULL;
+ cur_policy->numa_node_set = 0;
+ cur_policy->balance_level_set = 0;
+ if (strlen(value) > CONFIG_TYPE_MAX_LEN - 1) {
+ continue;
+ }
+ strncpy(cur_policy->irq_type, value, strlen(value) + 1);
+ add_usr_irq_policy(cur_policy);
+ } else if (strcmp(key, "balance_level") == 0) {
+ if (cur_policy == NULL) {
+ goto out;
+ }
+ for (level = 0; level < MAX_LEVEL_NUM; level++) {
+ if (strcasecmp(value, levelvals[level]) == 0) {
+ break;
+ }
+ }
+ if (level >= MAX_LEVEL_NUM) {
+ log(TO_ALL, LOG_WARNING, "Bad value for balance_level policy: %s\n", value);
+ } else {
+ cur_policy->balance_level = level;
+ cur_policy->balance_level_set = 1;
+ }
+ } else if (strcmp(key, "numa_node") == 0) {
+ if (cur_policy == NULL) {
+ goto out;
+ }
+ node = strtoul(value, NULL, 10);
+ /* check node */
+ if (!get_numa_node(node)) {
+ log(TO_ALL, LOG_WARNING, "NUMA node %d doesn't exist\n",
+ node);
+ continue;
+ }
+ cur_policy->numa_node = node;
+ cur_policy->numa_node_set = 1;
+ }
+ }
+out:
+ fclose(file);
+ if (line) {
+ free(line);
+ }
+ return 0;
+
+}
+
diff --git a/rules_config.h b/rules_config.h
new file mode 100644
index 0000000..b8f9dc5
--- /dev/null
+++ b/rules_config.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019. Huawei Technologies Co., Ltd. All rights reserved.
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#ifndef _INCLUDE_RULES_CONFIG_H
+#define _INCLUDE_RULES_CONFIG_H
+
+#define CONFIG_TYPE_MAX_LEN 32
+#define CONFIG_LINE_MAX_LEN 512
+#define MAX_LEVEL_NUM 4
+
+typedef struct user_irq_policy_config {
+ char irq_type[CONFIG_TYPE_MAX_LEN];
+ int numa_node;
+ int balance_level;
+ int numa_node_set;
+ int balance_level_set;
+ struct user_irq_policy_config *next;
+}USER_IRQ_POLICY;
+extern USER_IRQ_POLICY *user_policy_list;
+extern char *rules_config_file;
+
+void add_usr_irq_policy(USER_IRQ_POLICY *policy);
+
+USER_IRQ_POLICY *get_usr_irq_policy(char *name);
+
+int read_user_policy_config();
+
+void set_usr_irq_policy(char *name, struct irq_info *info);
+
+#endif
--
1.8.3.1

View File

@ -1,123 +0,0 @@
From e44eed4faef6ee1bd1ae41dd27a8513d37681f7f Mon Sep 17 00:00:00 2001
From: liuchao <liuchao173@huawei.com>
Date: Tue, 17 Dec 2019 02:54:57 +0000
Subject: [PATCH] add switch to clear affinity hint
All irqs' affinity hints are cleared in update_affinity_hint and forced
to rebalance. In some scenarios, it will affect performance.
---
hint_verify.c | 26 +++++++++++++++++++++++++-
irqbalance.c | 10 ++++++++--
2 files changed, 33 insertions(+), 3 deletions(-)
diff --git a/hint_verify.c b/hint_verify.c
index 0718078..11ef868 100644
--- a/hint_verify.c
+++ b/hint_verify.c
@@ -16,6 +16,7 @@ extern int keep_going;
extern GMainLoop *main_loop;
extern gboolean scan();
extern int last_interval;
+extern int clear_affinity_hint;
int real_sleep_interval;
int sleep_interval_count;
@@ -57,7 +58,8 @@ void update_affinity_hint(struct irq_info *info, void *data __attribute__((unuse
if (!hint_enabled)
return;
- cpus_clear(info->affinity_hint);
+ if (clear_affinity_hint)
+ cpus_clear(info->affinity_hint);
sprintf(path, "/proc/irq/%d/affinity_hint", info->irq);
file = fopen(path, "r");
if (!file)
@@ -80,6 +82,27 @@ void update_affinity_hint(struct irq_info *info, void *data __attribute__((unuse
free(line);
}
+static void check_clear()
+{
+ char *line = NULL;
+ size_t size = 0;
+ FILE *file;
+
+ file = fopen("/etc/sysconfig/irqbalance_clear", "r");
+ if (!file)
+ return;
+ if (getline(&line, &size, file) <= 0)
+ goto out;
+ if (line != NULL && strstr(line, "0") != NULL)
+ clear_affinity_hint = 0;
+ else
+ clear_affinity_hint = 1;
+
+out:
+ fclose(file);
+ free(line);
+}
+
/*
* This function is the main loop of irqbalance, which include:
* 1. scan opration for irq balancing;
@@ -104,6 +127,7 @@ gboolean poll_hint_affinity_and_scan(gpointer data __attribute__((unused)))
sleep_count++;
if (need_verify_flag && hint_changed()) {
+ check_clear();
for_each_irq(NULL, update_affinity_hint, NULL);
if (hint_has_changed) {
hint_has_changed = FALSE;
diff --git a/irqbalance.c b/irqbalance.c
index 05eaa29..77076fa 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -55,6 +55,7 @@ int foreground_mode;
int numa_avail;
int journal_logging = 0;
int need_rescan;
+int clear_affinity_hint = 1;
unsigned int log_mask = TO_ALL;
const char *log_indent;
unsigned long power_thresh = ULONG_MAX;
@@ -104,14 +105,16 @@ struct option lopts[] = {
{"version", 0, NULL, 'V'},
{"verifyhint", 1, NULL, 'v'},
{"rulesconfig", 1, NULL, 'r'},
+ {"notclearhint", 0, NULL, 'n'},
{0, 0, 0, 0}
};
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] [--rulesconfig= | -r <config>]\n");
+ log(TO_CONSOLE, LOG_INFO, " [--pid= | -s <file>] [--deepestcache= | -c <n>] [--interval= | -t <n>] [--verifyhint= | -v n]\n");
+ log(TO_CONSOLE, LOG_INFO, " [--rulesconfig= | -r <config>] [--notclearhint | -n]\n");
}
static void version(void)
@@ -126,7 +128,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:r:",
+ "odfji:p:s:c:b:l:m:t:V:h:v:r:n",
lopts, &longind)) != -1) {
switch(opt) {
@@ -225,6 +227,10 @@ static void parse_command_line(int argc, char **argv)
case 'r':
rules_config_file = strdup(optarg);
break;
+ case 'n':
+ clear_affinity_hint = 0;
+ break;
+
}
}
}
--
2.19.1

View File

@ -1,114 +0,0 @@
From b697a97436dafa13f0ae3febde299bfc20498f9d Mon Sep 17 00:00:00 2001
From: liuchao173 <liuchao173@huawei.com>
Date: Wed, 23 Oct 2019 11:42:26 +0000
Subject: [PATCH] irqbalance: add the switch of printing log
add the switch of printing log
---
cputree.c | 16 ++++++++--------
irqbalance.c | 25 +++++++++++++++++++++++++-
2 files changed, 32 insertions(+), 9 deletions(-)
diff --git a/cputree.c b/cputree.c
index 99f14d2..1465103 100644
--- a/cputree.c
+++ b/cputree.c
@@ -432,23 +432,23 @@ static void dump_irq(struct irq_info *info, void *data)
indent[i] = log_indent[0];
indent[i] = '\0';
- log(TO_CONSOLE, LOG_INFO, "%sInterrupt %i node_num is %d (%s/%lu:%lu) \n", indent,
+ log(TO_ALL, LOG_INFO, "%sInterrupt %i node_num is %d (%s/%lu:%lu) \n", indent,
info->irq, irq_numa_node(info)->number, classes[info->class], info->load, (info->irq_count - info->last_irq_count));
free(indent);
}
static void dump_numa_node_num(struct topo_obj *p, void *data __attribute__((unused)))
{
- log(TO_CONSOLE, LOG_INFO, "%d ", p->number);
+ log(TO_ALL, LOG_INFO, "%d ", p->number);
}
static void dump_balance_obj(struct topo_obj *d, void *data __attribute__((unused)))
{
struct topo_obj *c = (struct topo_obj *)d;
- log(TO_CONSOLE, LOG_INFO, "%s%s%s%sCPU number %i numa_node is ",
+ log(TO_ALL, LOG_INFO, "%s%s%s%sCPU number %i numa_node is ",
log_indent, log_indent, log_indent, log_indent, c->number);
for_each_object(cpu_numa_node(c), dump_numa_node_num, NULL);
- log(TO_CONSOLE, LOG_INFO, "(load %lu)\n", (unsigned long)c->load);
+ log(TO_ALL, LOG_INFO, "(load %lu)\n", (unsigned long)c->load);
if (c->interrupts)
for_each_irq(c->interrupts, dump_irq, (void *)18);
}
@@ -457,10 +457,10 @@ static void dump_cache_domain(struct topo_obj *d, void *data)
{
char *buffer = data;
cpumask_scnprintf(buffer, 4095, d->mask);
- log(TO_CONSOLE, LOG_INFO, "%s%sCache domain %i: numa_node is ",
+ log(TO_ALL, LOG_INFO, "%s%sCache domain %i: numa_node is ",
log_indent, log_indent, d->number);
for_each_object(d->numa_nodes, dump_numa_node_num, NULL);
- log(TO_CONSOLE, LOG_INFO, "cpu mask is %s (load %lu) \n", buffer,
+ log(TO_ALL, LOG_INFO, "cpu mask is %s (load %lu) \n", buffer,
(unsigned long)d->load);
if (d->children)
for_each_object(d->children, dump_balance_obj, NULL);
@@ -472,9 +472,9 @@ static void dump_package(struct topo_obj *d, void *data)
{
char *buffer = data;
cpumask_scnprintf(buffer, 4096, d->mask);
- log(TO_CONSOLE, LOG_INFO, "Package %i: numa_node ", d->number);
+ log(TO_ALL, LOG_INFO, "Package %i: numa_node ", d->number);
for_each_object(d->numa_nodes, dump_numa_node_num, NULL);
- log(TO_CONSOLE, LOG_INFO, "cpu mask is %s (load %lu)\n",
+ log(TO_ALL, LOG_INFO, "cpu mask is %s (load %lu)\n",
buffer, (unsigned long)d->load);
if (d->children)
for_each_object(d->children, dump_cache_domain, buffer);
diff --git a/irqbalance.c b/irqbalance.c
index d41753c..7d8d15c 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -273,6 +273,29 @@ gboolean force_rescan(gpointer data __attribute__((unused)))
return TRUE;
}
+static int check_debug()
+{
+ char *line = NULL;
+ size_t size = 0;
+ FILE *file;
+
+ file = fopen("/etc/sysconfig/irqbalance_debug", "r");
+ if (!file)
+ return 0;
+ if (getline(&line, &size, file) <= 0) {
+ goto out;
+ }
+ if (line != NULL && strstr(line, "1") != NULL) {
+ fclose(file);
+ free(line);
+ return 1;
+ }
+out:
+ fclose(file);
+ free(line);
+ return 0;
+}
+
gboolean scan(gpointer data __attribute__((unused)))
{
log(TO_CONSOLE, LOG_INFO, "\n\n\n-----------------------------------------------------------------------------\n");
@@ -305,7 +328,7 @@ gboolean scan(gpointer data)
calculate_placement();
activate_mappings();
- if (debug_mode)
+ if (debug_mode || check_debug())
dump_tree();
if (one_shot_mode)
keep_going = 0;
--
2.19.1

View File

@ -1,43 +0,0 @@
From 2fdfbc218be09a6335df8dde15498f75fa12bc0a Mon Sep 17 00:00:00 2001
From: liuchao <liuchao173@huawei.com>
Date: Thu, 6 Feb 2020 06:44:51 +0000
Subject: [PATCH] feature: enable irqbalance to link with multiple clients at
the same time
Type:bugfix/CVE/requirement/cleancode/testcode
CVE:
DTS/AR:
reason:
---
irqbalance.c | 2 +-
irqbalance.h | 2 ++
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/irqbalance.c b/irqbalance.c
index 1af23c6..dc8307d 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -622,7 +622,7 @@ int init_socket()
log(TO_ALL, LOG_WARNING, "Unable to set socket options.\n");
return 1;
}
- listen(socket_fd, 1);
+ listen(socket_fd, MAX_CLIENT_NUM);
g_unix_fd_add(socket_fd, G_IO_IN, sock_handle, NULL);
return 0;
}
diff --git a/irqbalance.h b/irqbalance.h
index 61b39dd..2d59d31 100644
--- a/irqbalance.h
+++ b/irqbalance.h
@@ -177,5 +177,7 @@ extern unsigned int log_mask;
#define SOCKET_PATH "irqbalance"
#define SOCKET_TMPFS "/var/run"
#define SOCKET_RECV_BUF_LEN 4096
+#define MAX_CLIENT_NUM 32
+
#endif /* __INCLUDE_GUARD_IRQBALANCE_H_ */
--
2.19.1

View File

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

View File

@ -1,511 +0,0 @@
From e5b83ac140634830b8f8d9ca8d40a1d9d16d2d5b Mon Sep 17 00:00:00 2001
From: hejingxian <hejingxian@huawei.com>
Date: Tue, 12 Nov 2019 15:29:16 +0800
Subject: [PATCH] feature: introduce affinity hint verify to detect user hint variation
In order to make the user affinity hint becomes effective quickly,
introduce the periodically affinity hint verify.
---
Makefile.am | 2 +-
activate.c | 24 +++++------
classify.c | 18 ++++++--
cpumask.h | 7 +++
hint_verify.c | 151 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
hint_verify.h | 21 +++++++++
irqbalance.c | 40 +++++++++++------
irqbalance.h | 4 ++
placement.c | 14 ++++++
types.h | 1 +
10 files changed, 252 insertions(+), 30 deletions(-)
create mode 100644 hint_verify.c
create mode 100644 hint_verify.h
diff --git a/Makefile.am b/Makefile.am
index 9276bfb..5fac265 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -38,7 +38,7 @@ sbin_PROGRAMS += irqbalance-ui
endif
irqbalance_SOURCES = activate.c bitmap.c classify.c cputree.c irqbalance.c \
- irqlist.c numa.c placement.c procinterrupts.c rules_config.c
+ irqlist.c numa.c placement.c procinterrupts.c rules_config.c hint_verify.c
irqbalance_LDADD = $(LIBCAP_NG_LIBS) $(GLIB2_LIBS)
if IRQBALANCEUI
irqbalance_ui_SOURCES = $(UI_DIR)/helpers.c $(UI_DIR)/irqbalance-ui.c \
diff --git a/activate.c b/activate.c
index d9e1fc3..87336f4 100644
--- a/activate.c
+++ b/activate.c
@@ -88,26 +88,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 5aed9e5..75677f4 100644
--- a/classify.c
+++ b/classify.c
@@ -71,8 +71,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
*
@@ -448,7 +446,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);
@@ -460,6 +458,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/hint_verify.c b/hint_verify.c
new file mode 100644
index 0000000..7a904b0
--- /dev/null
+++ b/hint_verify.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2019. Huawei Technologies Co., Ltd. All rights reserved.
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include "irqbalance.h"
+
+extern int keep_going;
+extern GMainLoop *main_loop;
+extern gboolean scan();
+extern int last_interval;
+
+int real_sleep_interval;
+int sleep_interval_count;
+int poll_hint_interval_count;
+int sleep_count = 0;
+gboolean hint_has_changed = FALSE;
+
+int hint_changed(void)
+{
+ FILE *file;
+ char *line = NULL;
+ size_t size = 0;
+ gboolean changed = FALSE;
+
+ file = fopen("/proc/irq/affinity_hint_notify", "r+");
+ if (!file)
+ return changed;
+
+ if (getline(&line, &size, file) > 0 && *line != '0') {
+ fprintf(file, "Done");
+ changed = TRUE;
+ }
+
+ fclose(file);
+ if (line)
+ free(line);
+ return changed;
+}
+
+void update_affinity_hint(struct irq_info *info, void *data __attribute__((unused)))
+{
+ 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);
+ hint_has_changed = TRUE;
+ log(TO_ALL, LOG_INFO, "IRQ(%d): affinity hint modified %s\n", info->irq, line);
+ }
+ }
+
+ if (line)
+ free(line);
+}
+
+/*
+ * This function is the main loop of irqbalance, which include:
+ * 1. scan opration for irq balancing;
+ * 2. poll irq affinity hint changes for quickly applying them.
+ */
+gboolean poll_hint_affinity_and_scan(gpointer data __attribute__((unused)))
+{
+ gboolean need_verify_flag = FALSE;
+ gboolean need_scan_flag = FALSE;
+
+ if (!sleep_interval_count)
+ sleep_interval_count = 1;
+ if (!poll_hint_interval_count)
+ poll_hint_interval_count = 1;
+
+ if (sleep_count % sleep_interval_count == 0) {
+ need_scan_flag = TRUE;
+ }
+ if (sleep_count % poll_hint_interval_count == 0) {
+ need_verify_flag = TRUE;
+ }
+ sleep_count++;
+
+ if (need_verify_flag && hint_changed()) {
+ for_each_irq(NULL, update_affinity_hint, NULL);
+ if (hint_has_changed) {
+ hint_has_changed = FALSE;
+ sleep_count = 1;
+ need_scan_flag = TRUE;
+ }
+ }
+
+ if (need_scan_flag) {
+ if (!scan()) {
+ g_main_loop_quit(main_loop);
+ return FALSE;
+ }
+ }
+
+ update_interval_and_count();
+ if (last_interval != real_sleep_interval) {
+ last_interval = real_sleep_interval;
+ g_timeout_add_seconds(real_sleep_interval, poll_hint_affinity_and_scan, NULL);
+ return FALSE;
+ }
+
+ if (keep_going) {
+ return TRUE;
+ } else {
+ g_main_loop_quit(main_loop);
+ return FALSE;
+ }
+}
+
+void update_interval_and_count()
+{
+ real_sleep_interval =
+ sleep_interval > poll_hint_interval ? poll_hint_interval : sleep_interval;
+ if (!real_sleep_interval) {
+ sleep_interval_count = 1;
+ poll_hint_interval_count = 1;
+ return;
+ }
+ sleep_interval_count = sleep_interval / real_sleep_interval;
+ poll_hint_interval_count = poll_hint_interval / real_sleep_interval;
+}
+
diff --git a/hint_verify.h b/hint_verify.h
new file mode 100644
index 0000000..a309461
--- /dev/null
+++ b/hint_verify.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2019. Huawei Technologies Co., Ltd. All rights reserved.
+ *
+ * This program file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#ifndef _INCLUDE_HINT_VERIFY_H
+#define _INCLUDE_HINT_VERIFY_H
+
+extern int real_sleep_interval;
+extern gboolean poll_hint_affinity_and_scan();
+extern void update_interval_and_count();
+
+#endif
diff --git a/irqbalance.c b/irqbalance.c
index faa8e6a..4a7eb39 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -65,6 +65,8 @@ char *banscript = NULL;
long HZ;
int sleep_interval = SLEEP_INTERVAL;
int last_interval;
+int hint_enabled = 0;
+int poll_hint_interval = SLEEP_INTERVAL / 5;
GMainLoop *main_loop;
char *cpu_ban_string = NULL;
@@ -99,15 +101,16 @@ struct option lopts[] = {
{"banmod", 1 , NULL, 'm'},
{"interval", 1 , NULL, 't'},
{"version", 0, NULL, 'V'},
+ {"verifyhint", 1, NULL, 'v'},
{"rulesconfig", 1, NULL, 'r'},
{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>] [--rulesconfig= | -r <config>]\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)
@@ -122,7 +125,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:r",
+ "odfji:p:s:c:b:l:m:t:V:h:v:r:",
lopts, &longind)) != -1) {
switch(opt) {
@@ -202,6 +205,22 @@ static void parse_command_line(int argc, char **argv)
exit(1);
}
break;
+ case 'h':
+ if (!strncmp(optarg, "subset", strlen(optarg)))
+ hint_enabled = 1;
+ else {
+ usage();
+ exit(1);
+ }
+
+ break;
+ case 'v':
+ poll_hint_interval = strtol(optarg, NULL, 10);
+ if (poll_hint_interval < 1) {
+ usage();
+ exit(1);
+ }
+ break;
case 'r':
rules_config_file = strdup(optarg);
break;
@@ -300,7 +319,7 @@ out:
return 0;
}
-gboolean scan(gpointer data __attribute__((unused)))
+gboolean scan()
{
log(TO_CONSOLE, LOG_INFO, "\n\n\n-----------------------------------------------------------------------------\n");
clear_work_stats();
@@ -338,17 +357,9 @@ gboolean scan(gpointer data)
keep_going = 0;
cycle_count++;
- /* sleep_interval may be changed by socket */
- if (last_interval != sleep_interval) {
- last_interval = sleep_interval;
- g_timeout_add_seconds(sleep_interval, scan, NULL);
- return FALSE;
- }
-
if (keep_going) {
return TRUE;
} else {
- g_main_loop_quit(main_loop);
return FALSE;
}
}
@@ -626,9 +638,10 @@ int main(int argc, char** argv)
goto out;
}
log(TO_ALL, LOG_INFO, "irqbalance start scan.\n");
+ update_interval_and_count();
main_loop = g_main_loop_new(NULL, FALSE);
- last_interval = sleep_interval;
- g_timeout_add_seconds(sleep_interval, scan, NULL);
+ last_interval = real_sleep_interval;
+ g_timeout_add_seconds(real_sleep_interval, poll_hint_affinity_and_scan, NULL);
g_main_loop_run(main_loop);
g_main_loop_quit(main_loop);
diff --git a/irqbalance.h b/irqbalance.h
index 1befb46..72e141b 100644
--- a/irqbalance.h
+++ b/irqbalance.h
@@ -15,6 +15,7 @@
#include "types.h"
#include "config.h"
#include "rules_config.h"
+#include "hint_verify.h"
#ifdef __aarch64__
#define AARCH64
#endif
@@ -113,6 +114,7 @@ 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)));
extern gint compare_ints(gconstpointer a, gconstpointer b);
extern struct irq_info *build_one_dev_entry(const char *dirname, GList *tmp_list);
@@ -120,6 +122,8 @@ 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 int hint_enabled, poll_hint_interval;
+extern int sleep_interval;
/*
* Generic object functions
diff --git a/placement.c b/placement.c
index 48ac68b..d887c60 100644
--- a/placement.c
+++ b/placement.c
@@ -41,6 +41,7 @@ static void find_best_object(struct topo_obj *d, void *data)
{
struct obj_placement *best = (struct obj_placement *)data;
uint64_t newload;
+ cpumask_t subset;
/*
* Don't consider the unspecified numa node here
@@ -58,6 +59,19 @@ static void find_best_object(struct topo_obj *d, void *data)
if (d->powersave_mode)
return;
+ /*
+ * If the hint feature is enabled, then we only want
+ * to consider objects that are within the irqs hint, but
+ * only if that irq in fact has published a hint
+ */
+ if (hint_enabled) {
+ if (!cpus_empty(best->info->affinity_hint)) {
+ cpus_and(subset, best->info->affinity_hint, d->mask);
+ if (cpus_empty(subset))
+ return;
+ }
+ }
+
newload = d->load;
if (newload < best->best_cost) {
best->best = d;
diff --git a/types.h b/types.h
index e1f3dc6..c0950ee 100644
--- a/types.h
+++ b/types.h
@@ -67,6 +67,7 @@ struct irq_info {
int flags;
struct topo_obj *numa_node;
cpumask_t cpumask;
+ cpumask_t affinity_hint;
uint64_t irq_count;
uint64_t last_irq_count;
uint64_t load;
--
1.8.3.1

View File

@ -1,552 +0,0 @@
From 8e84d5ba4aad02509165cb1926091baa3630e418 Mon Sep 17 00:00:00 2001
From: hejingxian <hejingxian@huawei.com>
Date: Fri, 14 Feb 2020 16:42:01 +0800
Subject: [PATCH] feature: add ability for unblock 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>
Signed-off-by: He Jingxian <hejingxian@huawei.com>
---
Makefile.am | 4 +-
classify.c | 2 +-
cputree.c | 20 ++--
irqbalance.c | 33 +++++--
irqbalance.h | 1 +
sockapi.c | 297 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
sockapi.h | 19 ++++
7 files changed, 359 insertions(+), 17 deletions(-)
create mode 100644 sockapi.c
create mode 100644 sockapi.h
diff --git a/Makefile.am b/Makefile.am
index 46e7173..c7be22d 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,7 +38,7 @@ sbin_PROGRAMS += irqbalance-ui
endif
irqbalance_SOURCES = activate.c bitmap.c classify.c cputree.c irqbalance.c \
- irqlist.c numa.c placement.c procinterrupts.c rules_config.c hint_verify.c
+ irqlist.c numa.c placement.c procinterrupts.c rules_config.c hint_verify.c sockapi.c
irqbalance_LDADD = $(LIBCAP_NG_LIBS) $(GLIB2_LIBS)
if IRQBALANCEUI
irqbalance_ui_SOURCES = $(UI_DIR)/helpers.c $(UI_DIR)/irqbalance-ui.c \
diff --git a/classify.c b/classify.c
index 91ff022..b0bb3b4 100644
--- a/classify.c
+++ b/classify.c
@@ -37,7 +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;
+GList *vm_banned_irqs = NULL;
extern int need_add_single;
#define SYSFS_DIR "/sys"
diff --git a/cputree.c b/cputree.c
index 741c7c8..5a96e30 100644
--- a/cputree.c
+++ b/cputree.c
@@ -40,6 +40,8 @@
extern char *banned_cpumask_from_ui;
extern char *cpu_ban_string;
+extern int use_unblock_socket;
+extern int is_set_banned_cpumask_from_ui;
GList *cpus;
GList *cache_domains;
@@ -78,12 +80,18 @@ static void setup_banned_cpus(void)
cpus_clear(nohz_full);
/* A manually specified cpumask overrides auto-detection. */
- if (cpu_ban_string != NULL && banned_cpumask_from_ui != NULL) {
- cpulist_parse(banned_cpumask_from_ui,
- strlen(banned_cpumask_from_ui), banned_cpus);
- goto out;
- }
- if (getenv("IRQBALANCE_BANNED_CPUS")) {
+ if (!use_unblock_socket && cpu_ban_string != NULL && banned_cpumask_from_ui != NULL) {
+ cpulist_parse(banned_cpumask_from_ui,
+ strlen(banned_cpumask_from_ui), banned_cpus);
+ goto out;
+ }
+ if (use_unblock_socket && is_set_banned_cpumask_from_ui) {
+ cpumask_parse_user(banned_cpumask_from_ui,
+ strlen(banned_cpumask_from_ui), banned_cpus);
+ goto out;
+ }
+
+ if (getenv("IRQBALANCE_BANNED_CPUS")) {
cpumask_parse_user(getenv("IRQBALANCE_BANNED_CPUS"), strlen(getenv("IRQBALANCE_BANNED_CPUS")), banned_cpus);
goto out;
}
diff --git a/irqbalance.c b/irqbalance.c
index dc8307d..1774eda 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -42,6 +42,7 @@
#include <cap-ng.h>
#endif
#include "irqbalance.h"
+#include "sockapi.h"
volatile int keep_going = 1;
volatile int ban_pci_assigned_irq = 1;
@@ -73,6 +74,7 @@ GMainLoop *main_loop;
char *cpu_ban_string = NULL;
char *banned_cpumask_from_ui = NULL;
+int use_unblock_socket = 1;
static void sleep_approx(int seconds)
{
@@ -109,6 +111,7 @@ struct option lopts[] = {
{"notclearhint", 0, NULL, 'n'},
{"migrateval", 1, NULL, 'e'},
{"loadlimit", 1, NULL, 'g'},
+ {"blocksocket", 0, NULL, 'k'},
{0, 0, 0, 0}
};
@@ -116,8 +119,8 @@ 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, " [--rulesconfig= | -r <config>] [--notclearhint | -n] [--migrateval= | -e <n>] [--loadlimit= | -g <n>]\n");
+ log(TO_CONSOLE, LOG_INFO, " [--pid= | -s <file>] [--deepestcache= | -c <n>] [--interval= | -t <n>] [--verifyhint= | -v n] [--blocksocket | -k]\n");
+ log(TO_CONSOLE, LOG_INFO, " [--rulesconfig= | -r <config>] [--notclearhint | -n] [--migrateval= | -e <n>] [--loadlimit= | -g <n>]\n");
}
static void version(void)
@@ -132,7 +135,7 @@ static void parse_command_line(int argc, char **argv)
unsigned long val;
while ((opt = getopt_long(argc, argv,
- "odfjVni:p:s:c:b:l:m:t:h:v:r:e:g:",
+ "odfjVni:p:s:c:b:l:m:t:h:v:r:e:g:k",
lopts, &longind)) != -1) {
switch(opt) {
@@ -240,7 +243,9 @@ static void parse_command_line(int argc, char **argv)
case 'g':
load_limit = strtoul(optarg, NULL, 10);
break;
-
+ case 'k':
+ use_unblock_socket = 0;
+ break;
}
}
}
@@ -562,9 +567,12 @@ gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attri
if (!setup)
goto out_close;
snprintf(setup, strlen("SLEEP ") + 11 + 1, "SLEEP %d ", sleep_interval);
- if(g_list_length(cl_banned_irqs) > 0) {
+ if (g_list_length(cl_banned_irqs) > 0) {
for_each_irq(cl_banned_irqs, get_irq_data, &setup);
}
+ if (g_list_length(vm_banned_irqs) > 0) {
+ for_each_irq(vm_banned_irqs, get_irq_data, &setup);
+ }
cpumask_scnprintf(banned, 512, banned_cpus);
newptr = realloc(setup, strlen(setup) + strlen(banned) + 7 + 1);
if (!newptr)
@@ -827,10 +835,18 @@ int main(int argc, char** argv)
parse_proc_interrupts();
parse_proc_stat();
- if (init_socket()) {
- ret = EXIT_FAILURE;
- goto out;
+ if (use_unblock_socket) {
+ if (init_unblock_socket()) {
+ ret = EXIT_FAILURE;
+ goto out;
+ }
+ } else {
+ if (init_socket()) {
+ ret = EXIT_FAILURE;
+ goto out;
+ }
}
+
log(TO_ALL, LOG_INFO, "irqbalance start scan.\n");
update_interval_and_count();
main_loop = g_main_loop_new(NULL, FALSE);
@@ -852,6 +868,7 @@ out:
close(socket_fd);
if (socket_name[0])
unlink(socket_name);
+ free(banned_cpumask_from_ui);
return ret;
}
diff --git a/irqbalance.h b/irqbalance.h
index fc42a9b..7473ee7 100644
--- a/irqbalance.h
+++ b/irqbalance.h
@@ -65,6 +65,7 @@ extern GList *cache_domains;
extern GList *cpus;
extern int numa_avail;
extern GList *cl_banned_irqs;
+extern GList *vm_banned_irqs;
extern int debug_mode;
extern int journal_logging;
diff --git a/sockapi.c b/sockapi.c
new file mode 100644
index 0000000..9891978
--- /dev/null
+++ b/sockapi.c
@@ -0,0 +1,297 @@
+#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 GList *cl_banned_irqs;
+extern GList *vm_banned_irqs;
+extern cpumask_t banned_cpus;
+extern int keep_going;
+int cur_fd_count = 0;
+
+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:");
+ 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;
+ }
+
+ (void)snprintf(irqstr + strlen(irqstr) - 1, length - strlen(irqstr), " PCI:");
+
+ 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;
+ }
+}
+
+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,
+ (int)((unsigned int)fcntl(socket_fd, F_GETFL, 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;
+
+ g_list_free_full(cl_banned_irqs, free);
+ cl_banned_irqs = NULL;
+
+ 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);
+ }
+}
+
+gboolean recv_msg_handle(gint client_fd,
+ GIOCondition condition,
+ gpointer user_data __attribute__((unused)))
+{
+ char buff[FILE_LINE_MAX_NUM];
+ struct cmsghdr *cmsg;
+ int recv_size = 0;
+ int valid_user = 0;
+ struct iovec iov = { buff, FILE_LINE_MAX_NUM - 1 };
+ struct msghdr msg = { 0 };
+ int new_iterval = 0;
+
+ if (condition == G_IO_IN) {
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = malloc(CMSG_SPACE(sizeof(struct ucred)));
+ if (!msg.msg_control) {
+ goto out_close;
+ }
+ 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:%d %s\n", recv_size, strerror(errno));
+ 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, "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, "Setting cpus more than limit: %d.\n",
+ NR_CPUS);
+ goto out_close;
+ }
+ 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));
+ }
+ }
+out_close:
+ close(client_fd);
+ free(msg.msg_control);
+ cur_fd_count--;
+ }
+ return FALSE;
+}
+
+gboolean accept_handle(gint fd,
+ GIOCondition condition,
+ gpointer user_data __attribute__((unused)))
+{
+ int client_fd;
+
+ if (condition != G_IO_IN) {
+ return TRUE;
+ }
+ client_fd = accept(fd, NULL, NULL);
+ if (client_fd < 0) {
+ log(TO_ALL, LOG_WARNING, "Connection couldn't be accepted.\n");
+ return TRUE;
+ }
+ if (cur_fd_count >= MAX_EVENTS) {
+ log(TO_ALL, LOG_WARNING, "Daemon support no more than %d connection\n",
+ MAX_EVENTS);
+ close(client_fd);
+ return TRUE;
+ }
+ if (setnonblocking(client_fd) < 0) {
+ log(TO_ALL, LOG_WARNING, "Daemon set connection nonblocking failed: %s.\n",
+ strerror(errno));
+ close(client_fd);
+ return TRUE;
+ }
+ cur_fd_count++;
+ g_unix_fd_add(client_fd, G_IO_IN, recv_msg_handle, NULL);
+ return TRUE;
+}
+
+
+int init_unblock_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");
+ 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).
+ */
+ memset(&addr, 0, sizeof(struct sockaddr_un));
+ 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.\n");
+ return 1;
+ }
+ }
+
+ if (chmod(socket_name, SOCK_RWX_MODE) != 0) {
+ /* when use abstract socket, chmod may fail. No need return here. */
+ log(TO_ALL, LOG_WARNING, "socket name : %s, chmod failed\n", socket_name);
+ }
+
+ 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));
+ return 1;
+ }
+
+ if (listen(socket_fd, MAX_CLIENT) != 0) {
+ log(TO_ALL, LOG_WARNING, "Daemon couldn't be listening to the socket: %s.\n",
+ strerror(errno));
+ return 1;
+ }
+
+ if (setnonblocking(socket_fd) < 0) {
+ log(TO_ALL, LOG_WARNING, "Daemon set connection(listen) nonblocking failed: %s.\n",
+ strerror(errno));
+ return 1;
+ }
+ banned_cpumask_from_ui = (char*)malloc(NR_CPUS + 1);
+ if (!banned_cpumask_from_ui) {
+ log(TO_ALL, LOG_WARNING, "Daemon faild to malloc banned_cpumask_from_ui space.\n");
+ return 1;
+ }
+ memset((void*)banned_cpumask_from_ui, 0, NR_CPUS + 1);
+
+ g_unix_fd_add(socket_fd, G_IO_IN, accept_handle, NULL);
+
+ return 0;
+}
diff --git a/sockapi.h b/sockapi.h
new file mode 100644
index 0000000..3875234
--- /dev/null
+++ b/sockapi.h
@@ -0,0 +1,19 @@
+#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)
+
+int init_unblock_socket();
+
+#endif
--
1.8.3.1

View File

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

@ -1,131 +0,0 @@
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 @@ static void add_banned_irq(int irq, GList **list, int extra_flag)
return;
}
+#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

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

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

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

View File

@ -1,96 +0,0 @@
From 6c350eb9af2e36c40f4c1f2122e4b5b270c011b2 Mon Sep 17 00:00:00 2001
From: Weiping Zhang <zhangweiping@didiglobal.com>
Date: Fri, 8 Nov 2019 23:43:55 +0800
Subject: [PATCH 5/5] fix invalid pointer dereference banned_cpumask_from_ui
The memory of cpu_ban_string was release in sock_handle function,
so the banned_cpumask_from_ui will dereference an invalid memory.
Fix this issue by delay release memory.
Reproduce:
echo "settings cpus 0-3" | nc -U `find /var/run/irqbalance/ -name *sock`
Signed-off-by: Weiping Zhang <zhangweiping@didiglobal.com>
---
cputree.c | 7 ++++++-
irqbalance.c | 21 ++++++++++++++++++---
2 files changed, 24 insertions(+), 4 deletions(-)
diff --git a/cputree.c b/cputree.c
index 305f617..4c5fdf5 100644
--- a/cputree.c
+++ b/cputree.c
@@ -39,6 +39,7 @@
#include "irqbalance.h"
extern char *banned_cpumask_from_ui;
+extern char *cpu_ban_string;
GList *cpus;
GList *cache_domains;
@@ -104,9 +105,13 @@ static void setup_banned_cpus(void)
cpus_clear(nohz_full);
/* A manually specified cpumask overrides auto-detection. */
- if (banned_cpumask_from_ui != NULL) {
+ if (cpu_ban_string != NULL && banned_cpumask_from_ui != NULL) {
cpulist_parse(banned_cpumask_from_ui,
strlen(banned_cpumask_from_ui), banned_cpus);
+ /* release it safety, it was allocated in sock_handle */
+ free(cpu_ban_string);
+ cpu_ban_string = NULL;
+ banned_cpumask_from_ui = NULL;
goto out;
}
if (getenv("IRQBALANCE_BANNED_CPUS")) {
diff --git a/irqbalance.c b/irqbalance.c
index c9379ad..7630e38 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -65,6 +65,7 @@ int sleep_interval = SLEEP_INTERVAL;
int last_interval;
GMainLoop *main_loop;
+char *cpu_ban_string = NULL;
char *banned_cpumask_from_ui = NULL;
static void sleep_approx(int seconds)
@@ -469,7 +470,14 @@ gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attri
free(irq_string);
} else if (!(strncmp(buff + strlen("settings "), "cpus ",
strlen("cpus")))) {
- char *cpu_ban_string = malloc(
+ /*
+ * if cpu_ban_string has not been consumed,
+ * just ignore this request.
+ */
+ if (cpu_ban_string != NULL)
+ goto out_close;
+
+ cpu_ban_string = malloc(
sizeof(char) * (recv_size - strlen("settings cpus ")));
if (!cpu_ban_string)
goto out_close;
@@ -479,9 +487,16 @@ gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attri
banned_cpumask_from_ui = strtok(cpu_ban_string, " ");
if (!strncmp(banned_cpumask_from_ui, "NULL", strlen("NULL"))) {
banned_cpumask_from_ui = NULL;
+ free(cpu_ban_string);
+ cpu_ban_string = NULL;;
+ } else {
+ /*
+ * don't free cpu_ban_string at here, it will be
+ * released after we have store it to @banned_cpus
+ * in setup_banned_cpus function.
+ */
+ need_rescan = 1;
}
- need_rescan = 1;
- free(cpu_ban_string);
}
}
if (!strncmp(buff, "setup", strlen("setup"))) {
--
1.8.3.1

View File

@ -1,27 +0,0 @@
From d85897487c5f523ebc9ba8a56de911592703fed3 Mon Sep 17 00:00:00 2001
From: liuchao173 <liuchao173@huawei.com>
Date: Thu, 7 Nov 2019 09:27:55 +0000
Subject: [PATCH 5/8] backport: fix resource leak for not invoking closedir()
after opendir()
fix resource leak for not invoking closedir() after opendir()
Signed-off-by: Yunfeng Ye <yeyunfeng@huawei.com>
---
ui/irqbalance-ui.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/ui/irqbalance-ui.c b/ui/irqbalance-ui.c
index 47dd5dc..4dfbd46 100644
--- a/ui/irqbalance-ui.c
+++ b/ui/irqbalance-ui.c
@@ -418,6 +418,7 @@ int main(int argc, char **argv)
fclose(f);
}
} while((entry) && (irqbalance_pid == -1));
+ closedir(dir);
}
if(irqbalance_pid == -1) {
printf("Unable to determine irqbalance PID\n");
--
2.19.1

View File

@ -1,70 +0,0 @@
From 4bddf961e18f59b27301b73895c0ae3a6cde9b7b Mon Sep 17 00:00:00 2001
From: liuchao173 <liuchao173@huawei.com>
Date: Thu, 7 Nov 2019 09:38:21 +0000
Subject: [PATCH 8/8] backport: fix resource leak on the error paths in main()
Currently, both checking for core count < 2 and init_socket() fail, just
return directly, so lead to resource leak.
Make it correct to free resource when on these situation.
Signed-off-by: Yunfeng Ye <yeyunfeng@huawei.com>
---
irqbalance.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/irqbalance.c b/irqbalance.c
index cace4d8..5e5ef9b 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -556,6 +556,7 @@ int init_socket()
int main(int argc, char** argv)
{
sigset_t sigset, old_sigset;
+ int ret = EXIT_SUCCESS;
sigemptyset(&sigset);
sigaddset(&sigset,SIGINT);
@@ -636,7 +637,7 @@ int main(int argc, char** argv)
"single cpu. Shutting down\n";
log(TO_ALL, LOG_WARNING, "%s", msg);
- exit(EXIT_SUCCESS);
+ goto out;
}
if (!foreground_mode) {
@@ -673,7 +674,8 @@ int main(int argc, char** argv)
parse_proc_stat();
if (init_socket()) {
- return EXIT_FAILURE;
+ ret = EXIT_FAILURE;
+ goto out;
}
main_loop = g_main_loop_new(NULL, FALSE);
last_interval = sleep_interval;
@@ -682,6 +684,7 @@ int main(int argc, char** argv)
g_main_loop_quit(main_loop);
+out:
free_object_tree();
free_cl_opts();
@@ -689,9 +692,10 @@ int main(int argc, char** argv)
if (!foreground_mode && pidfile)
unlink(pidfile);
/* Remove socket */
- close(socket_fd);
+ if (socket_fd > 0)
+ close(socket_fd);
if (socket_name[0])
unlink(socket_name);
- return EXIT_SUCCESS;
+ return ret;
}
--
2.19.1

View File

@ -1,62 +0,0 @@
From 97730f051e042e67da5728a3b59528c9d0fb72d2 Mon Sep 17 00:00:00 2001
From: Pyxisha <xiashuang1@huawei.com>
Date: Mon, 15 Jul 2019 20:47:07 +0800
Subject: [PATCH 45/50] fix sleep interval when sleep_interval is changed by
socket
currently, in scan, irqbalance compare sleep_interval's address to decide if sleep_interval is changed, accutually this judgement is always false now.
sign_off_by: Shuang Xia <xiashuang1@huawei.com>
---
irqbalance.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/irqbalance.c b/irqbalance.c
index c1a0e15..d424326 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -61,6 +61,7 @@ char *pidfile = NULL;
char *polscript = NULL;
long HZ;
int sleep_interval = SLEEP_INTERVAL;
+int last_interval;
GMainLoop *main_loop;
char *banned_cpumask_from_ui = NULL;
@@ -251,7 +252,7 @@ gboolean force_rescan(gpointer data __attribute__((unused)))
return TRUE;
}
-gboolean scan(gpointer data)
+gboolean scan(gpointer data __attribute__((unused)))
{
log(TO_CONSOLE, LOG_INFO, "\n\n\n-----------------------------------------------------------------------------\n");
clear_work_stats();
@@ -289,9 +290,10 @@ gboolean scan(gpointer data)
keep_going = 0;
cycle_count++;
- if (data != &sleep_interval) {
- data = &sleep_interval;
- g_timeout_add_seconds(sleep_interval, scan, data);
+ /* sleep_interval may be changed by socket */
+ if (last_interval != sleep_interval) {
+ last_interval = sleep_interval;
+ g_timeout_add_seconds(sleep_interval, scan, NULL);
return FALSE;
}
@@ -623,8 +625,8 @@ int main(int argc, char** argv)
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);
+ last_interval = sleep_interval;
+ g_timeout_add_seconds(sleep_interval, scan, NULL);
g_main_loop_run(main_loop);
g_main_loop_quit(main_loop);
--
2.19.1

View File

@ -1,66 +0,0 @@
From 559980c2e1dea1082949c17d52794c43c35f40ce Mon Sep 17 00:00:00 2001
From: liuchao173 <liuchao173@huawei.com>
Date: Thu, 7 Nov 2019 09:35:42 +0000
Subject: [PATCH 7/8] backport: fix the problem of banmod that memory is freed
before using
Currently strdupa() is used to allocate memory for irq_info's name in
collect_full_irq_list(), we know that it allocate memory from stack,
when the invoking function return, the memory will be freed. so if the
irq_info's name is invalid, it will lead to check_for_module_ban() no
correct.
check_for_irq_ban
check_for_module_ban(res->name) // res->name is not valid
Use strdup() instead of strdupa(), and free the memory of irq_info's
name before freeing the irq_info.
Signed-off-by: Yunfeng Ye <yeyunfeng@huawei.com>
---
classify.c | 9 ++++++++-
procinterrupts.c | 2 +-
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/classify.c b/classify.c
index 3136fc3..ed3f3ba 100644
--- a/classify.c
+++ b/classify.c
@@ -748,6 +748,13 @@ static void add_missing_irq(struct irq_info *info, void *attr)
add_new_irq(info->irq, info, proc_interrupts);
}
+static void free_tmp_irqs(gpointer data)
+{
+ struct irq_info *info = data;
+
+ free(info->name);
+ free(info);
+}
void rebuild_irq_db(void)
{
@@ -777,7 +784,7 @@ void rebuild_irq_db(void)
for_each_irq(tmp_irqs, add_missing_irq, interrupts_db);
- g_list_free_full(tmp_irqs, free);
+ g_list_free_full(tmp_irqs, free_tmp_irqs);
}
diff --git a/procinterrupts.c b/procinterrupts.c
index 87fae2f..11fe1bc 100644
--- a/procinterrupts.c
+++ b/procinterrupts.c
@@ -228,7 +228,7 @@ GList* collect_full_irq_list()
info->class = IRQ_OTHER;
#endif
}
- info->name = strdupa(irq_mod);
+ info->name = strdup(irq_mod);
tmp_list = g_list_append(tmp_list, info);
}
free(savedline);
--
2.19.1

View File

@ -1,66 +0,0 @@
From 0fab11043aef5b835ed5564dc15476cdbfb54d5b Mon Sep 17 00:00:00 2001
From: SuperSix173 <liuchao173@huawei.com>
Date: Thu, 6 Feb 2020 11:43:48 +0800
Subject: [PATCH] free cpu_ban_string when the next request come
---
cputree.c | 4 ----
irqbalance.c | 19 +++++--------------
2 files changed, 5 insertions(+), 18 deletions(-)
diff --git a/cputree.c b/cputree.c
index 9aa4794..bef1f40 100644
--- a/cputree.c
+++ b/cputree.c
@@ -118,10 +118,6 @@ static void setup_banned_cpus(void)
if (cpu_ban_string != NULL && banned_cpumask_from_ui != NULL) {
cpulist_parse(banned_cpumask_from_ui,
strlen(banned_cpumask_from_ui), banned_cpus);
- /* release it safety, it was allocated in sock_handle */
- free(cpu_ban_string);
- cpu_ban_string = NULL;
- banned_cpumask_from_ui = NULL;
goto out;
}
if (getenv("IRQBALANCE_BANNED_CPUS")) {
diff --git a/irqbalance.c b/irqbalance.c
index e76d27b..9f65c88 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -471,12 +471,9 @@ gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attri
free(irq_string);
} else if (!(strncmp(buff + strlen("settings "), "cpus ",
strlen("cpus")))) {
- /*
- * if cpu_ban_string has not been consumed,
- * just ignore this request.
- */
- if (cpu_ban_string != NULL)
- goto out_close;
+ banned_cpumask_from_ui = NULL;
+ free(cpu_ban_string);
+ cpu_ban_string = NULL;
cpu_ban_string = malloc(
sizeof(char) * (recv_size - strlen("settings cpus ")));
@@ -489,15 +486,9 @@ gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attri
if (!strncmp(banned_cpumask_from_ui, "NULL", strlen("NULL"))) {
banned_cpumask_from_ui = NULL;
free(cpu_ban_string);
- cpu_ban_string = NULL;;
- } else {
- /*
- * don't free cpu_ban_string at here, it will be
- * released after we have store it to @banned_cpus
- * in setup_banned_cpus function.
- */
- need_rescan = 1;
+ cpu_ban_string = NULL;
}
+ need_rescan = 1;
}
}
if (!strncmp(buff, "setup", strlen("setup"))) {
--
2.21.0.windows.1

View File

@ -1,35 +0,0 @@
From 0f7965c9cc3963c4dbfa7b61820ff973ef5da539 Mon Sep 17 00:00:00 2001
From: liuchao173 <liuchao173@huawei.com>
Date: Thu, 7 Nov 2019 09:22:15 +0000
Subject: [PATCH 3/8] backport: free the memory when getline() fail in
add_one_node()
when getline() fail, the memory still need to be freed.
Signed-off-by: Yunfeng Ye <yeyunfeng@huawei.com>
---
numa.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/numa.c b/numa.c
index f0b1a98..542e1f4 100644
--- a/numa.c
+++ b/numa.c
@@ -74,12 +74,11 @@ static void add_one_node(const char *nodename)
cpus_clear(new->mask);
} else {
ret = getline(&cpustr, &blen, f);
- if (ret <= 0) {
+ if (ret <= 0)
cpus_clear(new->mask);
- } else {
+ else
cpumask_parse_user(cpustr, ret, new->mask);
- free(cpustr);
- }
+ free(cpustr);
}
fclose(f);
new->obj_type = OBJ_TYPE_NODE;
--
2.19.1

View File

@ -1,106 +0,0 @@
From 9fd716f6627c0bb3b63cef94780e20101d9616c3 Mon Sep 17 00:00:00 2001
From: liuchao173 <liuchao173@huawei.com>
Date: Thu, 7 Nov 2019 09:19:33 +0000
Subject: [PATCH 2/8] backport:
getline-clean-up-freeing-of-lines-from-getline.patch
It was noted that several calls to getline failed to free the resultant line,
which the man page for getline says to do even if the call fails. Clean that up
here
And while we're at it, merge some of the free calls so they're common to a
function where they can be, and not strewn all over the place
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
---
cputree.c | 29 +++++++++++++++++------------
1 file changed, 17 insertions(+), 12 deletions(-)
diff --git a/cputree.c b/cputree.c
index 5551784..91919ec 100644
--- a/cputree.c
+++ b/cputree.c
@@ -91,10 +91,10 @@ static void setup_banned_cpus(void)
if (getline(&line, &size, file) > 0) {
if (strlen(line) && line[0] != '\n')
cpulist_parse(line, strlen(line), isolated_cpus);
- free(line);
- line = NULL;
- size = 0;
}
+ free(line);
+ line = NULL;
+ size = 0;
fclose(file);
}
@@ -103,10 +103,10 @@ static void setup_banned_cpus(void)
if (getline(&line, &size, file) > 0) {
if (strlen(line) && line[0] != '\n')
cpulist_parse(line, strlen(line), nohz_full);
- free(line);
- line = NULL;
- size = 0;
}
+ free(line);
+ line = NULL;
+ size = 0;
fclose(file);
}
@@ -271,6 +271,7 @@ static void do_one_cpu(char *path)
int nodeid;
int packageid = 0;
unsigned int max_cache_index, cache_index, cache_stat;
+ int ret = 1;
/* skip offline cpus */
snprintf(new_path, ADJ_SIZE(path,"/online"), "%s/online", path);
@@ -278,14 +279,12 @@ static void do_one_cpu(char *path)
if (file) {
char *line = NULL;
size_t size = 0;
- if (getline(&line, &size, file)==0)
- return;
+ if (getline(&line, &size, file)>0)
+ ret = (line && line[0]=='0') ? 1 : 0;
fclose(file);
- if (line && line[0]=='0') {
- free(line);
- return;
- }
free(line);
+ if (ret)
+ return;
}
cpu = calloc(sizeof(struct topo_obj), 1);
@@ -327,6 +326,8 @@ static void do_one_cpu(char *path)
cpumask_parse_user(line, strlen(line), package_mask);
fclose(file);
free(line);
+ line = NULL;
+ size = 0;
}
/* try to read the package id */
snprintf(new_path, ADJ_SIZE(path, "/topology/physical_package_id"),
@@ -339,6 +340,8 @@ static void do_one_cpu(char *path)
packageid = strtoul(line, NULL, 10);
fclose(file);
free(line);
+ line = NULL;
+ size = 0;
}
/* try to read the cache mask; if it doesn't exist assume solitary */
@@ -372,6 +375,8 @@ static void do_one_cpu(char *path)
cpumask_parse_user(line, strlen(line), cache_mask);
fclose(file);
free(line);
+ line = NULL;
+ size = 0;
}
}
--
2.19.1

View File

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

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

Binary file not shown.

BIN
irqbalance-1.7.0.tar.gz Normal file

Binary file not shown.

View File

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

View File

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

19
irqbalance.service Normal file
View File

@ -0,0 +1,19 @@
[Unit]
Description=irqbalance daemon
Documentation=man:irqbalance(1)
Documentation=https://github.com/Irqbalance/irqbalance
ConditionVirtualization=!container
After=syslog.target
[Service]
OOMScoreAdjust=-500
Type=forking
PIDFile=/var/run/irqbalance.pid
EnvironmentFile=/etc/sysconfig/irqbalance
ExecStart=/usr/sbin/irq_balancer
StartLimitInterval=10
StartLimitBurst=10000
RuntimeDirectory=irqbalance/
[Install]
WantedBy=multi-user.target

View File

@ -1,14 +1,12 @@
Summary: A dynamic adaptive IRQ balancing daemon
Name: irqbalance
Version: 1.4.0
Release: 18
Version: 1.7.0
Release: 1
Epoch: 3
License: GPLv2
Source0: https://github.com/Irqbalance/irqbalance/archive/irqbalance-%{version}.tar.gz
Source1: irqbalance.sysconfig
Source2: irqbalance.rules
Source3: irq_balancer
Source1: irqbalance.service
Source2: irq_balancer
Url: https://github.com/irqbalance/irqbalance
BuildRequires: gdb autoconf automake libtool libcap-ng systemd
@ -23,63 +21,6 @@ Requires: numactl-libs
%define _hardened_build 1
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: Fix-irqbalance-ui-failing-to-connect-to-irqbalance-d.patch
Patch10:procinterrupts-check-xen-dyn-event-more-flexible.patch
Patch11:Fix-ambiguous-parsing-of-node-entries-in-sys.patch
Patch12:Don-t-leak-socket-fd-on-connection-error.patch
Patch13:Fix-string-truncation-issues-detected-by-GCC-8.patch
Patch14:fix-balancing-when-numa-information-isn-t-available.patch
Patch6000: Checking-return-value-of-strdup-in-collect_full_irq_.patch
Patch6001: getline-clean-up-freeing-of-lines-from-getline.patch
Patch6002: free-the-memory-when-getline-fail-in-add_one_node.patch
Patch6003: prevent-NULL-pointer-dereference-when-memory-allocat.patch
Patch6004: fix-resource-leak-for-not-invoking-closedir-after-op.patch
Patch6005: correct-to-use-realloc-function.patch
Patch6006: fix-the-problem-of-banmod-that-memory-is-freed-befor.patch
Patch6007: fix-sleep-interval-when-sleep_interval-is-changed-by.patch
Patch6008: fix-resource-leak-on-the-error-paths-in-main.patch
Patch6009: fix-invalid-pointer-dereference-banned_cpumask_from_.patch
Patch6010: free-cpu_ban_string-when-the-next-request-come.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-irqbalance-aarch64-add-the-regular-to-get-th.patch
Patch9005: feature-irqbalance-arm64-Add-irq-aff-change-check.patch
Patch9006: feature-irqbalance-auto-banned-pci-assigned-irq.patch
Patch9007: bugfix-irqbalance-fix-wrong-pid-value-in-pid-file.patch
Patch9008: feature-supplement-irqbalance-service-config.patch
Patch9009: bugfix-fgets-will-get-a-redundant-new-line.patch
Patch9010: bugfix-Prevent-inserting-a-duplicate-entry-to-avoid-list-ch.patch
Patch9011: bugfix-guess_arm_irq_hints.patch
Patch9012: feature-add-new-user-irq-policy-config-rule.patch
Patch9013: bugfix-make-the-return-value-of-getline-handled-correct.patch
Patch9014: bugfix-change-irq-ban-check-path-to-devpath.patch
Patch9015: bugfix-fix-new-irqs-in-hotplug-keep-stay-on-one-numa.patch
Patch9016: feature-add-the-switch-of-printing-log.patch
Patch9017: bugfix-fix-new-msi-irq-hasnot-been-added-to-rebalance-list.patch
Patch9018: bugfix-delete-no-existing-banned-irq.patch
Patch9019: bugfix-fix-strcat-may-cause-buffer-overrun.patch
Patch9020: feature-introduce-verifyhint-to-detect-hint-variation.patch
Patch9021: bugfix-fix-memory-leak-of-strdup-in-collect_full_irq_list.patch
Patch9022: feature-add-switch-to-clear-affinity-hint.patch
Patch9023: feature-add-new-irq-migrate-rule-to-avoid-high-cpu-irq-load.patch
Patch9024: bugfix-prevent-version-cmd-need-an-argument.patch
Patch9025: feature-encapsulate-and-compile-the-functions-in-irqbalance-ui.patch
Patch9026: feature-enable-irqbalance-to-link-with-multiple-clie.patch
Patch9027: feature-irqbalance-Add-ability-for-socket-communicat.patch
%description
Irqbalance is a daemon to help balance the cpu load generated by
interrupts across all of a systems cpus. Irqbalance identifies the
@ -88,20 +29,6 @@ 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.
%package devel
Summary: The development files of irqbalance client
Requires: glib2-devel ncurses-devel irqbalance-libs
%description devel
Development files for irqbalance client.
%package libs
Summary: The shared librariy of irqbalance client
Requires: glib2 ncurses-libs
%description libs
Shared librariy for irqbalanace client
%package_help
%prep
@ -110,20 +37,13 @@ Shared librariy for irqbalanace client
%build
./autogen.sh
%configure
CFLAGS="%{optflags}" %make_build CFLAGS+='-fstack-protector-strong -fPIC'
cd ui
make
cd -
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 -p -m 0640 ui/irqbalance_client.h %{buildroot}%{_includedir}/irqbalance_client.h
install -D -p -m 0640 ui/libirqbalance_client.so %{buildroot}%{_libdir}/libirqbalance_client.so
install -D -p -m 0644 %{SOURCE1} %{buildroot}/%{_unitdir}/%{name}.service
install -D -p -m 0644 ./misc/irqbalance.env %{buildroot}%{_sysconfdir}/sysconfig/%{name}
install -D -p -m 0755 %{SOURCE2} %{buildroot}%{_sbindir}/irq_balancer
install -d %{buildroot}%{_mandir}/man1/
install -p -m 0644 ./%{name}.1 %{buildroot}%{_mandir}/man1/
@ -136,15 +56,8 @@ make check
%{_sbindir}/%{name}
%{_unitdir}/%{name}.service
%config(noreplace) %{_sysconfdir}/sysconfig/%{name}
%{_sysconfdir}/sysconfig/%{name}.rules
%{_sbindir}/irq_balancer
%files devel
%{_includedir}/irqbalance_client.h
%files libs
%{_libdir}/libirqbalance_client.so
%files help
%{_mandir}/man1/*
@ -164,6 +77,24 @@ fi
/sbin/chkconfig --del %{name} >/dev/null 2>&1 || :
%changelog
* Fri Aug 14 2020 Liu Chao <liuchao173@huawei.com> - 3:1.7.0-1
- Type:enhanced
- ID:NA
- SUG:restart
- DESC:rebase to v1.7.0
* Fri Jul 3 2020 Liu Chao <liuchao173@huawei.com> - 3:1.6.0-1
- Type:enhanced
- ID:NA
- SUG:restart
- DESC:rebase to v1.6.0
* Tue Mar 24 2020 Liu chao <liuchao173@huawei.com> - 3:1.4.0-19
- Type:bugfix
- ID:NA
- SUG:restart
- DESC:refactor patches
* Tue Mar 24 2020 Shuaishuai Song <songshuaishuai2@huawei.com> - 3:1.4.0-18
- Type:bugfix
- ID:NA

View File

@ -1,39 +0,0 @@
# 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=

4
irqbalance.yaml Normal file
View File

@ -0,0 +1,4 @@
version_control: github
src_repo: Irqbalance/irqbalance
tag_prefix: "^v"
seperator: "."

View File

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

@ -1,109 +0,0 @@
From f37fe357b21ffd7ab210b088c36300d9562406cb Mon Sep 17 00:00:00 2001
From: liuchao173 <liuchao173@huawei.com>
Date: Thu, 7 Nov 2019 09:26:30 +0000
Subject: [PATCH 4/8] backport: prevent NULL pointer dereference when memory
allocation failure
There are several places where memory allocation does not check return
values, adding null pointer checks.
Signed-off-by: Yunfeng Ye <yeyunfeng@huawei.com>
---
cputree.c | 2 ++
irqbalance.c | 20 ++++++++++++++++++++
2 files changed, 22 insertions(+)
diff --git a/cputree.c b/cputree.c
index 91919ec..9cd2db8 100644
--- a/cputree.c
+++ b/cputree.c
@@ -432,6 +432,8 @@ static void dump_irq(struct irq_info *info, void *data)
int i;
char * indent = malloc (sizeof(char) * (spaces + 1));
+ if (!indent)
+ return;
for ( i = 0; i < spaces; i++ )
indent[i] = log_indent[0];
diff --git a/irqbalance.c b/irqbalance.c
index 93e4909..c9378d0 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -326,6 +326,9 @@ void get_irq_data(struct irq_info *irq, void *data)
else
*irqdata = realloc(*irqdata, strlen(*irqdata) + 24 + 1 + 11 + 20 + 20 + 11);
+ if (!*irqdata)
+ return;
+
sprintf(*irqdata + strlen(*irqdata),
"IRQ %d LOAD %lu DIFF %lu CLASS %d ", irq->irq, irq->load,
(irq->irq_count - irq->last_irq_count), irq->class);
@@ -357,6 +360,9 @@ void get_object_stat(struct topo_obj *object, void *data)
*stats = realloc(*stats, strlen(*stats) + irqdlen + 31 + 11 + 20 + 11 + 1);
}
+ if (!*stats)
+ return;
+
sprintf(*stats + strlen(*stats), "TYPE %d NUMBER %d LOAD %lu SAVE_MODE %d %s",
object->obj_type, object->number, object->load,
object->powersave_mode, irq_data ? irq_data : "");
@@ -393,6 +399,10 @@ gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attri
goto out_close;
}
cmsg = CMSG_FIRSTHDR(&msg);
+ if (!cmsg) {
+ log(TO_ALL, LOG_WARNING, "Connection no memory.\n");
+ goto out_close;
+ }
if ((cmsg->cmsg_level == SOL_SOCKET) &&
(cmsg->cmsg_type == SCM_CREDENTIALS)) {
struct ucred *credentials = (struct ucred *) CMSG_DATA(cmsg);
@@ -416,6 +426,8 @@ gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attri
strlen("sleep ")))) {
char *sleep_string = malloc(
sizeof(char) * (recv_size - strlen("settings sleep ")));
+ if (!sleep_string)
+ goto out_close;
strncpy(sleep_string, buff + strlen("settings sleep "),
recv_size - strlen("settings sleep "));
int new_iterval = strtoul(sleep_string, NULL, 10);
@@ -428,6 +440,8 @@ gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attri
char *end;
char *irq_string = malloc(
sizeof(char) * (recv_size - strlen("settings ban irqs ")));
+ if (!irq_string)
+ goto out_close;
strncpy(irq_string, buff + strlen("settings ban irqs "),
recv_size - strlen("settings ban irqs "));
g_list_free_full(cl_banned_irqs, free);
@@ -446,6 +460,8 @@ gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attri
strlen("cpus")))) {
char *cpu_ban_string = malloc(
sizeof(char) * (recv_size - strlen("settings cpus ")));
+ if (!cpu_ban_string)
+ goto out_close;
strncpy(cpu_ban_string, buff + strlen("settings cpus "),
recv_size - strlen("settings cpus "));
banned_cpumask_from_ui = strtok(cpu_ban_string, " ");
@@ -459,12 +475,16 @@ 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);
+ if (!setup)
+ goto out_close;
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);
+ if (!setup)
+ goto out_close;
snprintf(setup + strlen(setup), strlen(banned) + 7 + 1,
"BANNED %s", banned);
send(sock, setup, strlen(setup), 0);
--
2.19.1

View File

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