import irqbalance-1.9.0-3.el8

This commit is contained in:
CentOS Sources 2022-11-08 01:58:05 -05:00 committed by Stepan Oksanichenko
parent ea3068a0a0
commit 6e4506a5be
29 changed files with 2420 additions and 724 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
SOURCES/irqbalance-1.4.0.tar.gz
SOURCES/irqbalance-1.9.0.tar.gz

View File

@ -1 +1 @@
4eb861313d6b93b3be5d5933a7f45ee7b51c7ddb SOURCES/irqbalance-1.4.0.tar.gz
828952ed5fa3b502c4b07703395cdf33faa6a60a SOURCES/irqbalance-1.9.0.tar.gz

View File

@ -0,0 +1,71 @@
From ff48ac9c84f0b318dfce665605d72e86dfcfe008 Mon Sep 17 00:00:00 2001
From: Chao Liu <liuchao173@huawei.com>
Date: Tue, 7 Jun 2022 15:15:15 +0800
Subject: [PATCH 01/14] get irq->module relationship from /sys/bus/pci/*/driver
Signed-off-by: Chao Liu <liuchao173@huawei.com>
---
classify.c | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/classify.c b/classify.c
index 9b4640c..526a66b 100644
--- a/classify.c
+++ b/classify.c
@@ -7,6 +7,7 @@
#include <dirent.h>
#include <assert.h>
#include <errno.h>
+#include <libgen.h>
#include "irqbalance.h"
#include "types.h"
@@ -578,7 +579,7 @@ static int check_for_module_ban(char *name)
return 0;
}
-static int check_for_irq_ban(int irq, GList *proc_interrupts)
+static int check_for_irq_ban(int irq, char *mod, GList *proc_interrupts)
{
struct irq_info find, *res;
GList *entry;
@@ -594,6 +595,9 @@ static int check_for_irq_ban(int irq, GList *proc_interrupts)
/*
* Check to see if we banned module which the irq belongs to.
*/
+ if (mod != NULL && strlen(mod) > 0 && check_for_module_ban(mod))
+ return 1;
+
entry = g_list_find_custom(proc_interrupts, &find, compare_ints);
if (entry) {
res = entry->data;
@@ -609,14 +613,25 @@ static void add_new_irq(char *path, struct irq_info *hint, GList *proc_interrupt
struct irq_info *new;
struct user_irq_policy pol;
int irq = hint->irq;
+ char buf[PATH_MAX], drvpath[PATH_MAX];
+ char *mod = NULL;
+ int ret;
new = get_irq_info(irq);
if (new)
return;
+ if (path) {
+ sprintf(buf, "%s/driver", path);
+ ret = readlink(buf, drvpath, PATH_MAX);
+ if (ret > 0 && ret < PATH_MAX) {
+ drvpath[ret] = '\0';
+ mod = basename(drvpath);
+ }
+ }
/* Set NULL devpath for the irq has no sysfs entries */
get_irq_user_policy(path, irq, &pol);
- if ((pol.ban == 1) || check_for_irq_ban(irq, proc_interrupts)) { /*FIXME*/
+ if ((pol.ban == 1) || check_for_irq_ban(irq, mod, proc_interrupts)) { /*FIXME*/
__add_banned_irq(irq, &banned_irqs);
new = get_irq_info(irq);
} else
--
2.33.1

View File

@ -0,0 +1,64 @@
From c8d1fff0f16ad906cca153a22faac11516ccc0dd Mon Sep 17 00:00:00 2001
From: Liu Chao <liuchao173@huawei.com>
Date: Mon, 18 Jul 2022 16:54:53 +0800
Subject: [PATCH] irqbalance-ui: skip ',' in parse_setup to avoid coredump
When processing the ',' in hex_to_bitmap, it returns '0000\ 0' directly.
The return value will be freed in parse_setup, but it is not requested
through malloc.
Fixes: 85d37098a551 ("Fix several memleak problems found by covscan")
And it treat ',' as "0000", which cause irqbalance-ui will display wrong
Banned CPU numbers.
For example:
# IRQBALANCE_BANNED_CPUS="00000002,00000000,00000000" ./irqbalance
or
# IRQBALANCE_BANNED_CPULIST="65" ./irqbalance
# ./irqbalance-ui
Banned CPU numbers: 73
Fixes: 76d1c9d73935 ("Add main user interface files")
Signed-off-by: Liu Chao <liuchao173@huawei.com>
---
ui/irqbalance-ui.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/ui/irqbalance-ui.c b/ui/irqbalance-ui.c
index 47b6c88..b7f9b62 100644
--- a/ui/irqbalance-ui.c
+++ b/ui/irqbalance-ui.c
@@ -142,7 +142,7 @@ try_again:
void parse_setup(char *setup_data)
{
char *token, *ptr;
- int i,j;
+ int i,j, cpu = 0;
char *copy;
irq_t *new_irq = NULL;
if((setup_data == NULL) || (strlen(setup_data) == 0)) return;
@@ -179,14 +179,17 @@ void parse_setup(char *setup_data)
if(strncmp(token, "BANNED", strlen("BANNED"))) goto out;
token = strtok_r(NULL, " ", &ptr);
for(i = strlen(token) - 1; i >= 0; i--) {
+ if (token[i] == ',')
+ continue;
char *map = hex_to_bitmap(token[i]);
for(j = 3; j >= 0; j--) {
if(map[j] == '1') {
uint64_t *banned_cpu = malloc(sizeof(uint64_t));
- *banned_cpu = (4 * (strlen(token) - (i + 1)) + (4 - (j + 1)));
+ *banned_cpu = cpu;
setup.banned_cpus = g_list_append(setup.banned_cpus,
banned_cpu);
}
+ cpu++;
}
free(map);
--
2.33.1

View File

@ -0,0 +1,28 @@
From 522883505d3b02e3294f045f49007b61c00e2c31 Mon Sep 17 00:00:00 2001
From: Chao Liu <liuchao173@huawei.com>
Date: Wed, 8 Jun 2022 10:04:02 +0800
Subject: [PATCH 02/14] check whether savedptr is NULL before invoking strlen
savedptr can be null in musl libc, so the strlen(NULL) will segfault
Signed-off-by: Chao Liu <liuchao173@huawei.com>
---
procinterrupts.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/procinterrupts.c b/procinterrupts.c
index 9015177..57c8801 100644
--- a/procinterrupts.c
+++ b/procinterrupts.c
@@ -178,7 +178,7 @@ void init_irq_class_and_type(char *savedline, struct irq_info *info, int irq)
}
#ifdef AARCH64
- if (strlen(savedptr) > 0) {
+ if (savedptr && strlen(savedptr) > 0) {
snprintf(irq_fullname, PATH_MAX, "%s %s", last_token, savedptr);
tmp = strchr(irq_fullname, '\n');
if (tmp)
--
2.33.1

View File

@ -0,0 +1,96 @@
From 378d4707c26acf05e551219d8b09ddf440bdba2a Mon Sep 17 00:00:00 2001
From: Rosen Penev <rosenp@gmail.com>
Date: Fri, 10 Jun 2022 23:14:27 -0700
Subject: [PATCH 03/14] add meson
Simpler build system. Placing in contrib for now.
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
contrib/README | 2 ++
contrib/meson.build | 45 +++++++++++++++++++++++++++++++++++++++
contrib/meson_options.txt | 11 ++++++++++
3 files changed, 58 insertions(+)
create mode 100644 contrib/README
create mode 100644 contrib/meson.build
create mode 100644 contrib/meson_options.txt
diff --git a/contrib/README b/contrib/README
new file mode 100644
index 0000000..2158dac
--- /dev/null
+++ b/contrib/README
@@ -0,0 +1,2 @@
+This directory contains meson build instructions for irqbalance. This is here to see if there is any interest from
+the general community.
diff --git a/contrib/meson.build b/contrib/meson.build
new file mode 100644
index 0000000..d813233
--- /dev/null
+++ b/contrib/meson.build
@@ -0,0 +1,45 @@
+project('irqbalance', 'c', version: '1.9.0', default_options: ['warning_level=1'])
+cc = meson.get_compiler('c')
+
+glib_dep = dependency('glib-2.0')
+m_dep = cc.find_library('m', required: false)
+capng_dep = dependency('libcap-ng', required: get_option('capng'))
+ncurses_dep = dependency('curses', required: get_option('ui'))
+systemd_dep = dependency('libsystemd', required: get_option('systemd'))
+
+cdata = configuration_data()
+cdata.set('HAVE_GETOPT_LONG', cc.has_function('getopt_long'))
+cdata.set('HAVE_IRQBALANCEUI', ncurses_dep.found())
+cdata.set('HAVE_NUMA_H', cc.has_header('numa.h'))
+cdata.set('HAVE_LIBCAP_NG', capng_dep.found())
+cdata.set('HAVE_LIBSYSTEMD', systemd_dep.found())
+cdata.set_quoted('VERSION', meson.project_version())
+cfile = configure_file(output: 'config.h', configuration: cdata)
+
+if cdata.get('HAVE_IRQBALANCEUI')
+ add_project_arguments('-D_GNU_SOURCE', language: 'c')
+
+ executable(
+ 'irqbalance-ui',
+ '../ui/helpers.c',
+ '../ui/irqbalance-ui.c',
+ '../ui/ui.c',
+ dependencies: [glib_dep, ncurses_dep],
+ install: true,
+ )
+endif
+
+executable(
+ 'irqbalance',
+ '../activate.c',
+ '../bitmap.c',
+ '../classify.c',
+ '../cputree.c',
+ '../irqbalance.c',
+ '../irqlist.c',
+ '../numa.c',
+ '../placement.c',
+ '../procinterrupts.c',
+ dependencies: [glib_dep, m_dep, capng_dep, systemd_dep],
+ install: true,
+)
diff --git a/contrib/meson_options.txt b/contrib/meson_options.txt
new file mode 100644
index 0000000..3515dc3
--- /dev/null
+++ b/contrib/meson_options.txt
@@ -0,0 +1,11 @@
+option('capng', type : 'feature',
+ description : 'Build with libcap-ng support',
+)
+
+option('systemd', type : 'feature',
+ description : 'Build with systemd support',
+)
+
+option('ui', type : 'feature',
+ description : 'Build the UI component',
+)
--
2.33.1

View File

@ -0,0 +1,259 @@
From b66647ab757c580b2532c117bd345d1bad3b2bd5 Mon Sep 17 00:00:00 2001
From: "Chang S. Bae" <chang.seok.bae@intel.com>
Date: Thu, 10 Feb 2022 14:46:01 -0800
Subject: [PATCH 04/14] Prepare to handle thermal event
Intel's new hardware supports Hardware Feedback Interface to provide CPU
performance and energy efficiency information. Every update on this is
delivered via thermal event interrupt. The thermal framework in the Linux
kernel relays these notifications to userspace via a Netlink interface.
When a CPU's performance and efficiency are zero, irqbalance needs to mask
the CPU from interrupts. Introduce a new CPU mask to indicate banned CPUs
for this.
Before supporting this event handling, define functions. Their
implementation will be on the following patches.
This event is available only on x86-64 systems. And it can be subscribed
with help of Netlink libraries. So check them before building it.
Also add a new build option so users may opt out this support. Setting this
option on other systems will result in a build failure.
Signed-off-by: Chang S. Bae <chang.seok.bae@intel.com>
---
Makefile.am | 7 +++--
configure.ac | 22 ++++++++++++++
cputree.c | 6 ++++
irqbalance.c | 4 +++
thermal.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++
thermal.h | 15 ++++++++++
6 files changed, 135 insertions(+), 2 deletions(-)
create mode 100644 thermal.c
create mode 100644 thermal.h
diff --git a/Makefile.am b/Makefile.am
index 84e7d46..9181a34 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -27,7 +27,7 @@ EXTRA_DIST = COPYING autogen.sh misc/irqbalance.service misc/irqbalance.env
SUBDIRS = tests
UI_DIR = ui
-AM_CFLAGS = $(LIBCAP_NG_CFLAGS) $(GLIB2_CFLAGS) $(NUMA_CFLAGS)
+AM_CFLAGS = $(LIBCAP_NG_CFLAGS) $(GLIB2_CFLAGS) $(NUMA_CFLAGS) $(LIBNL3_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
@@ -39,7 +39,10 @@ endif
irqbalance_SOURCES = activate.c bitmap.c classify.c cputree.c irqbalance.c \
irqlist.c numa.c placement.c procinterrupts.c
-irqbalance_LDADD = $(LIBCAP_NG_LIBS) $(GLIB2_LIBS) $(NUMA_LIBS)
+if THERMAL
+irqbalance_SOURCES += thermal.c
+endif
+irqbalance_LDADD = $(LIBCAP_NG_LIBS) $(GLIB2_LIBS) $(NUMA_LIBS) $(LIBNL3_LIBS)
if IRQBALANCEUI
irqbalance_ui_SOURCES = $(UI_DIR)/helpers.c $(UI_DIR)/irqbalance-ui.c \
$(UI_DIR)/ui.c
diff --git a/configure.ac b/configure.ac
index 32082fc..15532c1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -36,6 +36,28 @@ AS_IF([test "x$has_ncursesw" = "xyes"], [
AC_SUBST([LIBS])
])
+AC_CANONICAL_HOST
+
+AC_ARG_ENABLE(thermal,
+ AS_HELP_STRING([--enable-thermal], [enable thermal event support [default=auto]]),,
+ AS_IF([test x"$host_cpu" = x"x86_64"], [enable_thermal=yes], [enable_thermal=no])
+)
+
+AS_IF([test x"$enable_thermal" = x"yes" && test x"$host_cpu" != x"x86_64"],
+ AC_MSG_ERROR([no thermal events support on $host_cpu systems.]),
+)
+
+AS_IF([test x"$enable_thermal" = x"yes"],
+ [PKG_CHECK_MODULES([LIBNL3], [libnl-3.0 libnl-genl-3.0], [have_thermal=yes],
+ AC_MSG_NOTICE([no thermal event support as libnl-3.0 is unavailable.])
+ )]
+)
+
+AS_IF([test "x$have_thermal" = xyes],
+ AC_DEFINE([HAVE_THERMAL], 1, [Build irqbalance to support thermal events])
+)
+AM_CONDITIONAL([THERMAL], [test "x$have_thermal" = xyes])
+
AC_C_CONST
AC_C_INLINE
AM_PROG_CC_C_O
diff --git a/cputree.c b/cputree.c
index b716a8f..c250977 100644
--- a/cputree.c
+++ b/cputree.c
@@ -38,6 +38,7 @@
#include <glib.h>
#include "irqbalance.h"
+#include "thermal.h"
#ifdef HAVE_IRQBALANCEUI
extern char *banned_cpumask_from_ui;
@@ -162,6 +163,11 @@ static void setup_banned_cpus(void)
cpumask_scnprintf(buffer, 4096, nohz_full);
log(TO_CONSOLE, LOG_INFO, "Adaptive-ticks CPUs: %s\n", buffer);
out:
+#ifdef HAVE_THERMAL
+ cpus_or(banned_cpus, banned_cpus, thermal_banned_cpus);
+ cpumask_scnprintf(buffer, 4096, thermal_banned_cpus);
+ log(TO_CONSOLE, LOG_INFO, "Thermal-banned CPUs: %s\n", buffer);
+#endif
cpumask_scnprintf(buffer, 4096, banned_cpus);
log(TO_CONSOLE, LOG_INFO, "Banned CPUs: %s\n", buffer);
}
diff --git a/irqbalance.c b/irqbalance.c
index e8d9ba9..c520c11 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -44,6 +44,7 @@
#include <sys/socket.h>
#endif
#include "irqbalance.h"
+#include "thermal.h"
volatile int keep_going = 1;
int one_shot_mode;
@@ -703,6 +704,8 @@ int main(int argc, char** argv)
goto out;
}
#endif
+ if (init_thermal())
+ log(TO_ALL, LOG_WARNING, "Failed to initialize thermal events.\n");
main_loop = g_main_loop_new(NULL, FALSE);
last_interval = sleep_interval;
g_timeout_add_seconds(sleep_interval, scan, NULL);
@@ -711,6 +714,7 @@ int main(int argc, char** argv)
g_main_loop_quit(main_loop);
out:
+ deinit_thermal();
free_object_tree();
free_cl_opts();
free(polscript);
diff --git a/thermal.c b/thermal.c
new file mode 100644
index 0000000..308bc48
--- /dev/null
+++ b/thermal.c
@@ -0,0 +1,83 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <stdio.h>
+
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+
+#include "irqbalance.h"
+
+cpumask_t thermal_banned_cpus;
+
+static gboolean prepare_netlink(void)
+{
+ gboolean error = TRUE;
+
+ log(TO_ALL, LOG_ERR, "thermal: not yet implement to alloc memory for netlink.\n");
+ return error;
+}
+
+#define NL_FAMILY_NAME "nlctrl"
+
+static gboolean establish_netlink(void)
+{
+ gboolean error = TRUE;
+
+ log(TO_ALL, LOG_ERR, "thermal: not yet implemented to establish netlink.\n");
+ return error;
+}
+
+static gboolean register_netlink_handler(nl_recvmsg_msg_cb_t handler __attribute__((unused)))
+{
+ gboolean error = TRUE;
+
+ log(TO_ALL, LOG_ERR, "thermal: not yet implemented to register thermal handler.\n");
+ return error;
+}
+
+static gboolean set_netlink_nonblocking(void)
+{
+ gboolean error = TRUE;
+
+ log(TO_ALL, LOG_ERR, "thermal: not yet implemented to set nonblocking socket.\n");
+ return error;
+}
+
+void deinit_thermal(void)
+{
+ return;
+}
+
+/*
+ * return value: TRUE with an error; otherwise, FALSE
+ */
+gboolean init_thermal(void)
+{
+ gboolean error;
+
+ error = prepare_netlink();
+ if (error)
+ goto err_out;
+
+ error = establish_netlink();
+ if (error)
+ goto err_out;
+
+ error = register_netlink_handler(NULL);
+ if (error)
+ goto err_out;
+
+ error = set_netlink_nonblocking();
+ if (error)
+ goto err_out;
+
+ return FALSE;
+err_out:
+ deinit_thermal();
+ return TRUE;
+}
diff --git a/thermal.h b/thermal.h
new file mode 100644
index 0000000..657d54e
--- /dev/null
+++ b/thermal.h
@@ -0,0 +1,15 @@
+#ifndef __LINUX_THERMAL_H_
+#define __LINUX_THERMAL_H_
+
+#include <glib.h>
+
+#ifdef HAVE_THERMAL
+gboolean init_thermal(void);
+void deinit_thermal(void);
+extern cpumask_t thermal_banned_cpus;
+#else
+static inline gboolean init_thermal(void) { return FALSE; }
+#define deinit_thermal() do { } while (0)
+#endif
+
+#endif /* __LINUX_THERMAL_H_ */
--
2.33.1

View File

@ -0,0 +1,392 @@
From c65cda183609116760c54f1c2ad458eef9f44d56 Mon Sep 17 00:00:00 2001
From: "Chang S. Bae" <chang.seok.bae@intel.com>
Date: Fri, 11 Feb 2022 12:27:00 -0800
Subject: [PATCH 05/14] Implement Netlink helper functions to subscribe thermal
events
Establish Netlink socket connection in a nonblocking mode and callback
notification.
Tolerate a few times on failures from receiving events. In practice, such
delivery failure is rare. But it may indicate more fundamental issues if
it repeats. So disconnect it unless the failure is transient.
Event-specific handler will be implemented in the next patch.
Signed-off-by: Chang S. Bae <chang.seok.bae@intel.com>
---
thermal.c | 327 +++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 313 insertions(+), 14 deletions(-)
diff --git a/thermal.c b/thermal.c
index 308bc48..16a6f39 100644
--- a/thermal.c
+++ b/thermal.c
@@ -14,43 +14,342 @@
cpumask_t thermal_banned_cpus;
+#define INVALID_NL_FD -1
+#define MAX_RECV_ERRS 2
+
+#define THERMAL_GENL_FAMILY_NAME "thermal"
+#define THERMAL_GENL_EVENT_GROUP_NAME "event"
+#define NL_FAMILY_NAME "nlctrl"
+
+struct family_data {
+ const char *group;
+ int id;
+};
+
+static struct nl_sock *sock;
+static struct nl_cb *callback;
+
+/*
+ * return value: TRUE with an error; otherwise, FALSE
+ */
static gboolean prepare_netlink(void)
{
- gboolean error = TRUE;
+ int rc;
- log(TO_ALL, LOG_ERR, "thermal: not yet implement to alloc memory for netlink.\n");
- return error;
+ sock = nl_socket_alloc();
+ if (!sock) {
+ log(TO_ALL, LOG_ERR, "thermal: socket allocation failed.\n");
+ return TRUE;
+ }
+
+ rc = genl_connect(sock);
+ if (rc) {
+ log(TO_ALL, LOG_ERR, "thermal: socket bind failed.\n");
+ return TRUE;
+ }
+
+ callback = nl_cb_alloc(NL_CB_DEFAULT);
+ if (!callback) {
+ log(TO_ALL, LOG_ERR, "thermal: callback allocation failed.\n");
+ return TRUE;
+ }
+
+ return FALSE;
}
-#define NL_FAMILY_NAME "nlctrl"
+static int handle_groupid(struct nl_msg *msg, void *arg)
+{
+ struct nlattr *attrhdr, *mcgrp, *cur_mcgrp;
+ struct nlattr *attrs[CTRL_ATTR_MAX + 1];
+ struct nla_policy *policy = NULL;
+ struct genlmsghdr *gnlhdr = NULL;
+ struct family_data *data = NULL;
+ struct nlmsghdr *msghdr = NULL;
+ int attrlen, rc, i;
+
+ if (!arg) {
+ log(TO_ALL, LOG_ERR, "thermal: group id - failed to receive argument.\n");
+ return NL_SKIP;
+ }
+ data = arg;
+
+ /* get actual netlink message header */
+ msghdr = nlmsg_hdr(msg);
+
+ /* get the start of the message payload */
+ gnlhdr = nlmsg_data(msghdr);
+
+ /* get the start of the message attribute section */
+ attrhdr = genlmsg_attrdata(gnlhdr, 0);
+
+ /* get the length of the message attribute section */
+ attrlen = genlmsg_attrlen(gnlhdr, 0);
+
+ /* create attribute index based on a stream of attributes */
+ rc = nla_parse(
+ attrs, /* index array to be filled */
+ CTRL_ATTR_MAX, /* the maximum acceptable attribute type */
+ attrhdr, /* head of attribute stream */
+ attrlen, /* length of attribute stream */
+ policy); /* validation policy */
+ if (rc) {
+ log(TO_ALL, LOG_ERR, "thermal: group id - failed to create attributes.\n");
+ return NL_SKIP;
+ }
+
+ /* start of the multi-cast group attribute */
+ mcgrp = attrs[CTRL_ATTR_MCAST_GROUPS];
+ if (!mcgrp) {
+ log(TO_ALL, LOG_ERR, "thermal: group id - no multi-cast group attributes.\n");
+ return NL_SKIP;
+ }
+
+ /* iterate a stream of nested attributes to get the group id */
+ nla_for_each_nested(cur_mcgrp, mcgrp, i) {
+ struct nlattr *nested_attrs[CTRL_ATTR_MCAST_GRP_MAX + 1];
+ struct nlattr *name, *id;
+
+ /* get start and length of payload section */
+ attrhdr = nla_data(cur_mcgrp);
+ attrlen = nla_len(cur_mcgrp);
+
+ rc = nla_parse(nested_attrs, CTRL_ATTR_MCAST_GRP_MAX, attrhdr, attrlen, policy);
+ if (rc)
+ continue;
+
+ name = nested_attrs[CTRL_ATTR_MCAST_GRP_NAME];
+ id = nested_attrs[CTRL_ATTR_MCAST_GRP_ID];
+ if (!name || !id)
+ continue;
+
+ if (strncmp(nla_data(name), data->group, nla_len(name)) != 0)
+ continue;
+
+ data->id = nla_get_u32(id);
+ log(TO_ALL, LOG_DEBUG, "thermal: received group id (%d).\n", data->id);
+ break;
+ }
+ return NL_OK;
+}
+
+static int handle_error(struct sockaddr_nl *sk_addr __attribute__((unused)),
+ struct nlmsgerr *err, void *arg)
+{
+ if (arg) {
+ log(TO_ALL, LOG_INFO, "thermal: received a netlink error (%s).\n",
+ nl_geterror(err->error));
+ *((int *)arg) = err->error;
+ }
+ return NL_SKIP;
+}
+
+static int handle_end(struct nl_msg *msg __attribute__((unused)), void *arg)
+{
+ if (arg)
+ *((int *)arg) = 0;
+ return NL_SKIP;
+}
+
+struct msgheader {
+ unsigned char cmd, version;
+ unsigned int port, seq;
+ int id, hdrlen, flags;
+};
static gboolean establish_netlink(void)
{
+ struct msgheader msghdr = { CTRL_CMD_GETFAMILY, 0, 0, 0, 0, 0, 0 };
+ struct family_data nldata = { THERMAL_GENL_EVENT_GROUP_NAME, -ENOENT };
+ struct nl_cb *cloned_callback = NULL;
+ int rc, group_id, callback_rc = 1;
+ struct nl_msg *msg = NULL;
gboolean error = TRUE;
+ void *hdr;
+
+ msg = nlmsg_alloc();
+ if (!msg) {
+ log(TO_ALL, LOG_ERR, "thermal: message allocation failed.\n");
+ goto err_out;
+ }
+
+ msghdr.id = genl_ctrl_resolve(sock, NL_FAMILY_NAME);
+ if (msghdr.id < 0) {
+ log(TO_ALL, LOG_ERR, "thermal: message id enumeration failed.\n");
+ goto err_out;
+ }
+
+ hdr = genlmsg_put(msg, msghdr.port, msghdr.seq, msghdr.id, msghdr.hdrlen,
+ msghdr.flags, msghdr.cmd, msghdr.version);
+ if (!hdr) {
+ log(TO_ALL, LOG_ERR, "thermal: netlink header setup failed.\n");
+ goto err_out;
+ }
+
+ rc = nla_put_string(msg, CTRL_ATTR_FAMILY_NAME, THERMAL_GENL_FAMILY_NAME);
+ if (rc) {
+ log(TO_ALL, LOG_ERR, "thermal: message setup failed.\n");
+ goto err_out;
+ }
+
+ cloned_callback = nl_cb_clone(callback);
+ if (!cloned_callback) {
+ log(TO_ALL, LOG_ERR, "thermal: callback handle duplication failed.\n");
+ goto err_out;
+ }
+
+ rc = nl_send_auto(sock, msg);
+ if (rc < 0) {
+ log(TO_ALL, LOG_ERR, "thermal: failed to send the first message.\n");
+ goto err_out;
+ }
- log(TO_ALL, LOG_ERR, "thermal: not yet implemented to establish netlink.\n");
+ rc = nl_cb_err(cloned_callback, NL_CB_CUSTOM, handle_error, &callback_rc);
+ if (rc) {
+ log(TO_ALL, LOG_ERR, "thermal: error callback setup failed.\n");
+ goto err_out;
+ }
+
+ rc = nl_cb_set(cloned_callback, NL_CB_ACK, NL_CB_CUSTOM, handle_end, &callback_rc);
+ if (rc) {
+ log(TO_ALL, LOG_ERR, "thermal: ack callback setup failed.\n");
+ goto err_out;
+ }
+
+ rc = nl_cb_set(cloned_callback, NL_CB_FINISH, NL_CB_CUSTOM, handle_end, &callback_rc);
+ if (rc) {
+ log(TO_ALL, LOG_ERR, "thermal: finish callback setup failed.\n");
+ goto err_out;
+ }
+
+ rc = nl_cb_set(cloned_callback, NL_CB_VALID, NL_CB_CUSTOM, handle_groupid, &nldata);
+ if (rc) {
+ log(TO_ALL, LOG_ERR, "thermal: group id callback setup failed.\n");
+ goto err_out;
+ }
+
+ while (callback_rc != 0) {
+ rc = nl_recvmsgs(sock, cloned_callback);
+ if (rc < 0) {
+ log(TO_ALL, LOG_ERR, "thermal: failed to receive messages.\n");
+ goto err_out;
+ }
+ }
+
+ group_id = nldata.id;
+ if (group_id < 0) {
+ log(TO_ALL, LOG_ERR, "thermal: invalid group_id was received.\n");
+ goto err_out;
+ }
+
+ rc = nl_socket_add_membership(sock, group_id);
+ if (rc) {
+ log(TO_ALL, LOG_ERR, "thermal: failed to join the netlink group.\n");
+ goto err_out;
+ }
+
+ error = FALSE;
+err_out:
+ nl_cb_put(cloned_callback);
+ nlmsg_free(msg);
return error;
}
-static gboolean register_netlink_handler(nl_recvmsg_msg_cb_t handler __attribute__((unused)))
+static int handle_thermal_event(struct nl_msg *msg __attribute__((unused)),
+ void *arg __attribute__((unused)))
{
- gboolean error = TRUE;
+ log(TO_ALL, LOG_ERR, "thermal: not yet implemented to process thermal event.\n");
+ return NL_SKIP;
+}
- log(TO_ALL, LOG_ERR, "thermal: not yet implemented to register thermal handler.\n");
- return error;
+static int handler_for_debug(struct nl_msg *msg __attribute__((unused)),
+ void *arg __attribute__((unused)))
+{
+ return NL_SKIP;
+}
+
+/*
+ * return value: TRUE with an error; otherwise, FALSE
+ */
+static gboolean register_netlink_handler(void)
+{
+ int rc;
+
+ rc = nl_cb_set(callback, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, handler_for_debug, NULL);
+ if (rc) {
+ log(TO_ALL, LOG_ERR, "thermal: debug handler registration failed.\n");
+ return TRUE;
+ }
+
+
+ rc = nl_cb_set(callback, NL_CB_VALID, NL_CB_CUSTOM, handle_thermal_event, NULL);
+ if (rc) {
+ log(TO_ALL, LOG_ERR, "thermal: thermal handler registration failed.\n");
+ return TRUE;
+ }
+
+ return FALSE;
}
+/*
+ * return value: TRUE to keep the source; FALSE to disconnect.
+ */
+gboolean receive_thermal_event(gint fd __attribute__((unused)),
+ GIOCondition condition,
+ gpointer user_data __attribute__((unused)))
+{
+ if (condition == G_IO_IN) {
+ static unsigned int retry = 0;
+ int err;
+
+ err = nl_recvmsgs(sock, callback);
+ if (err) {
+ log(TO_ALL, LOG_ERR, "thermal: failed to receive messages (rc=%d).\n", err);
+ retry++;
+
+ /*
+ * Pass a few failures then turn off if it keeps
+ * failing down.
+ */
+ if (retry <= MAX_RECV_ERRS) {
+ log(TO_ALL, LOG_ERR, "thermal: but keep the connection.\n");
+ } else {
+ log(TO_ALL, LOG_ERR, "thermal: disconnect now with %u failures.\n",
+ retry);
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+
+/*
+ * return value: TRUE with an error; otherwise, FALSE
+ */
static gboolean set_netlink_nonblocking(void)
{
- gboolean error = TRUE;
+ int rc, fd;
- log(TO_ALL, LOG_ERR, "thermal: not yet implemented to set nonblocking socket.\n");
- return error;
+ rc = nl_socket_set_nonblocking(sock);
+ if (rc) {
+ log(TO_ALL, LOG_ERR, "thermal: non-blocking mode setup failed.\n");
+ return TRUE;
+ }
+
+ fd = nl_socket_get_fd(sock);
+ if (fd == INVALID_NL_FD) {
+ log(TO_ALL, LOG_ERR, "thermal: file descriptor setup failed.\n");
+ return TRUE;
+ }
+
+ g_unix_fd_add(fd, G_IO_IN, receive_thermal_event, NULL);
+
+ return FALSE;
}
void deinit_thermal(void)
{
- return;
+ nl_cb_put(callback);
+ nl_socket_free(sock);
}
/*
@@ -68,7 +367,7 @@ gboolean init_thermal(void)
if (error)
goto err_out;
- error = register_netlink_handler(NULL);
+ error = register_netlink_handler();
if (error)
goto err_out;
--
2.33.1

View File

@ -0,0 +1,242 @@
From 560291389e33db108d2fb6d954ef059f953c6e33 Mon Sep 17 00:00:00 2001
From: "Chang S. Bae" <chang.seok.bae@intel.com>
Date: Fri, 11 Feb 2022 13:48:01 -0800
Subject: [PATCH 06/14] Handle thermal events to mask CPUs
The Hardware Feedback Interface event is delivered as the Netlink's
THERMAL_GENL_ATTR_CPU_CAPABILITY attribute. Add code to receive and parse
these attributes: logical CPU number, performance, and efficiency
enumeration values (0-1023).
When an event indicates CPU performance and efficiency are zeros, then the
CPU needs to be banned from IRQs. Rebuild object tree to make this banned
list effective.
Creating the banned CPU list here is a bit tricky here because the amount
of data that each Netlink notification can carry out is not enough in some
systems with many cores. This means the handler has to wait for multiple
notifications to determine banned CPUs per thermal event.
Establish a logic to maintain the list based on the kernel behaviors. Also,
always push the current list as of the banned CPUs, because there is no
clear line whether each notification is at the end of a thermal event or
not.
Signed-off-by: Chang S. Bae <chang.seok.bae@intel.com>
---
thermal.c | 172 +++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 165 insertions(+), 7 deletions(-)
diff --git a/thermal.c b/thermal.c
index 16a6f39..64a9cdf 100644
--- a/thermal.c
+++ b/thermal.c
@@ -6,6 +6,7 @@
#include <stdio.h>
+#include <sys/sysinfo.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/family.h>
#include <netlink/genl/ctrl.h>
@@ -14,8 +15,62 @@
cpumask_t thermal_banned_cpus;
-#define INVALID_NL_FD -1
-#define MAX_RECV_ERRS 2
+/* Events of thermal_genl_family */
+enum thermal_genl_event {
+ THERMAL_GENL_EVENT_UNSPEC,
+ THERMAL_GENL_EVENT_TZ_CREATE, /* Thermal zone creation */
+ THERMAL_GENL_EVENT_TZ_DELETE, /* Thermal zone deletion */
+ THERMAL_GENL_EVENT_TZ_DISABLE, /* Thermal zone disabled */
+ THERMAL_GENL_EVENT_TZ_ENABLE, /* Thermal zone enabled */
+ THERMAL_GENL_EVENT_TZ_TRIP_UP, /* Trip point crossed the way up */
+ THERMAL_GENL_EVENT_TZ_TRIP_DOWN, /* Trip point crossed the way down */
+ THERMAL_GENL_EVENT_TZ_TRIP_CHANGE, /* Trip point changed */
+ THERMAL_GENL_EVENT_TZ_TRIP_ADD, /* Trip point added */
+ THERMAL_GENL_EVENT_TZ_TRIP_DELETE, /* Trip point deleted */
+ THERMAL_GENL_EVENT_CDEV_ADD, /* Cdev bound to the thermal zone */
+ THERMAL_GENL_EVENT_CDEV_DELETE, /* Cdev unbound */
+ THERMAL_GENL_EVENT_CDEV_STATE_UPDATE, /* Cdev state updated */
+ THERMAL_GENL_EVENT_TZ_GOV_CHANGE, /* Governor policy changed */
+ THERMAL_GENL_EVENT_CAPACITY_CHANGE, /* CPU capacity changed */
+ __THERMAL_GENL_EVENT_MAX,
+};
+#define THERMAL_GENL_EVENT_MAX (__THERMAL_GENL_EVENT_MAX - 1)
+
+/* Attributes of thermal_genl_family */
+enum thermal_genl_attr {
+ THERMAL_GENL_ATTR_UNSPEC,
+ THERMAL_GENL_ATTR_TZ,
+ THERMAL_GENL_ATTR_TZ_ID,
+ THERMAL_GENL_ATTR_TZ_TEMP,
+ THERMAL_GENL_ATTR_TZ_TRIP,
+ THERMAL_GENL_ATTR_TZ_TRIP_ID,
+ THERMAL_GENL_ATTR_TZ_TRIP_TYPE,
+ THERMAL_GENL_ATTR_TZ_TRIP_TEMP,
+ THERMAL_GENL_ATTR_TZ_TRIP_HYST,
+ THERMAL_GENL_ATTR_TZ_MODE,
+ THERMAL_GENL_ATTR_TZ_NAME,
+ THERMAL_GENL_ATTR_TZ_CDEV_WEIGHT,
+ THERMAL_GENL_ATTR_TZ_GOV,
+ THERMAL_GENL_ATTR_TZ_GOV_NAME,
+ THERMAL_GENL_ATTR_CDEV,
+ THERMAL_GENL_ATTR_CDEV_ID,
+ THERMAL_GENL_ATTR_CDEV_CUR_STATE,
+ THERMAL_GENL_ATTR_CDEV_MAX_STATE,
+ THERMAL_GENL_ATTR_CDEV_NAME,
+ THERMAL_GENL_ATTR_GOV_NAME,
+ THERMAL_GENL_ATTR_CAPACITY,
+ THERMAL_GENL_ATTR_CAPACITY_CPU_COUNT,
+ THERMAL_GENL_ATTR_CAPACITY_CPU_ID,
+ THERMAL_GENL_ATTR_CAPACITY_CPU_PERF,
+ THERMAL_GENL_ATTR_CAPACITY_CPU_EFF,
+ __THERMAL_GENL_ATTR_MAX,
+};
+#define THERMAL_GENL_ATTR_MAX (__THERMAL_GENL_ATTR_MAX - 1)
+
+#define INVALID_NL_FD -1
+#define MAX_RECV_ERRS 2
+#define SYSCONF_ERR -1
+#define INVALID_EVENT_VALUE -1
#define THERMAL_GENL_FAMILY_NAME "thermal"
#define THERMAL_GENL_EVENT_GROUP_NAME "event"
@@ -254,17 +309,115 @@ err_out:
return error;
}
-static int handle_thermal_event(struct nl_msg *msg __attribute__((unused)),
- void *arg __attribute__((unused)))
+enum {
+ INDEX_CPUNUM,
+ INDEX_PERF,
+ INDEX_EFFI,
+ INDEX_MAX
+};
+
+/*
+ * Single netlink notification is not guaranteed to fully deliver all of
+ * the CPU updates per thermal event, due to the implementation choice in
+ * the kernel code. So, this function is intended to manage a CPU list in a
+ * stream of relevant notifications.
+ */
+static void update_banned_cpus(int cur_cpuidx, gboolean need_to_ban)
{
- log(TO_ALL, LOG_ERR, "thermal: not yet implemented to process thermal event.\n");
- return NL_SKIP;
+ static cpumask_t banmask = { 0 }, itrmask = { 0 };
+ long max_cpunum = sysconf(_SC_NPROCESSORS_ONLN);
+
+ if (need_to_ban)
+ cpu_set(cur_cpuidx, banmask);
+
+ cpu_set(cur_cpuidx, itrmask);
+ if (cpus_weight(itrmask) < max_cpunum)
+ return;
+
+ if (cpus_equal(thermal_banned_cpus, banmask))
+ goto out;
+
+ cpus_copy(thermal_banned_cpus, banmask);
+ need_rescan = 1;
+out:
+ cpus_clear(banmask);
+ cpus_clear(itrmask);
+}
+
+static int handle_thermal_event(struct nl_msg *msg, void *arg __attribute__((unused)))
+{
+ int event_data[INDEX_MAX] = { INVALID_EVENT_VALUE };
+ struct nlattr *attrs[THERMAL_GENL_ATTR_MAX + 1];
+ struct genlmsghdr *genlhdr;
+ struct nlmsghdr *msnlh;
+ struct nlattr *cap;
+ int i, remain, rc;
+ void *pos;
+
+ /* get actual netlink message header */
+ msnlh = nlmsg_hdr(msg);
+
+ /* get a pointer to generic netlink header */
+ genlhdr = genlmsg_hdr(msnlh);
+ if (genlhdr->cmd != THERMAL_GENL_EVENT_CAPACITY_CHANGE) {
+ log(TO_ALL, LOG_DEBUG, "thermal: no CPU capacity change.\n");
+ return NL_SKIP;
+ }
+
+ /* parse generic netlink message including attributes */
+ rc = genlmsg_parse(
+ msnlh, /* a pointer to netlink message header */
+ 0, /* length of user header */
+ attrs, /* array to store parsed attributes */
+ THERMAL_GENL_ATTR_MAX, /* maximum attribute id as expected */
+ NULL); /* validation policy */
+ if (rc) {
+ log(TO_ALL, LOG_ERR, "thermal: failed to parse message for thermal event.\n");
+ return NL_SKIP;
+ }
+
+ /* get start and length of payload section */
+ cap = attrs[THERMAL_GENL_ATTR_CAPACITY];
+ pos = nla_data(cap);
+ remain = nla_len(cap);
+
+ for (i = 0; nla_ok(pos, remain); pos = nla_next(pos, &remain), i++) {
+ gboolean valid_event = TRUE, need_to_ban;
+ unsigned int value = nla_get_u32(pos);
+ int idx = i % INDEX_MAX;
+ int cur_cpuidx;
+
+ event_data[idx] = value;
+
+ if (idx != INDEX_EFFI)
+ continue;
+
+ cur_cpuidx = event_data[INDEX_CPUNUM];
+ valid_event = !!(cur_cpuidx <= NR_CPUS);
+ if (!valid_event) {
+ log(TO_ALL, LOG_WARNING, "thermal: invalid event - CPU %d\n",
+ cur_cpuidx);
+ continue;
+ }
+
+ /*
+ * A CPU with no performance and no efficiency cannot
+ * handle IRQs:
+ */
+ need_to_ban = !!(!event_data[INDEX_PERF] && !event_data[INDEX_EFFI]);
+ update_banned_cpus(cur_cpuidx, need_to_ban);
+
+ log(TO_ALL, LOG_DEBUG, "thermal: event - CPU %d, efficiency %d, perf %d.\n",
+ cur_cpuidx, event_data[INDEX_PERF], event_data[INDEX_EFFI]);
+ }
+
+ return NL_OK;
}
static int handler_for_debug(struct nl_msg *msg __attribute__((unused)),
void *arg __attribute__((unused)))
{
- return NL_SKIP;
+ return NL_OK;
}
/*
@@ -274,6 +427,11 @@ static gboolean register_netlink_handler(void)
{
int rc;
+ if (sysconf(_SC_NPROCESSORS_ONLN) == SYSCONF_ERR) {
+ log(TO_ALL, LOG_ERR, "thermal: _SC_NPROCESSORS_ONLN not available.\n");
+ return TRUE;
+ }
+
rc = nl_cb_set(callback, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, handler_for_debug, NULL);
if (rc) {
log(TO_ALL, LOG_ERR, "thermal: debug handler registration failed.\n");
--
2.33.1

View File

@ -0,0 +1,27 @@
From 028082a6a1ff650d5cdf796ac55ac26a3874372a Mon Sep 17 00:00:00 2001
From: Liu Chao <liuchao173@huawei.com>
Date: Sat, 25 Jun 2022 14:13:10 +0800
Subject: [PATCH 07/14] add keep_going check to prevent irqbalance from failing
to exit after SIGTERM
Signed-off-by: Liu Chao <liuchao173@huawei.com>
---
irqbalance.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/irqbalance.c b/irqbalance.c
index c520c11..5eae5b6 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -290,7 +290,7 @@ gboolean scan(gpointer data __attribute__((unused)))
/* cope with cpu hotplug -- detected during /proc/interrupts parsing */
- while (need_rescan || need_rebuild) {
+ while (keep_going && (need_rescan || need_rebuild)) {
int try_times = 0;
need_rescan = 0;
--
2.33.1

View File

@ -0,0 +1,26 @@
From 0a82dddbaf5702caded0d0d83a6eafaca743254d Mon Sep 17 00:00:00 2001
From: Andreas Schwab <schwab@suse.de>
Date: Mon, 27 Jun 2022 13:43:04 +0200
Subject: [PATCH 08/14] parse_proc_interrupts: fix parsing interrupt counts
The name of an interrupt chip can start with a number, stop before it.
---
procinterrupts.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/procinterrupts.c b/procinterrupts.c
index 57c8801..d90bf6d 100644
--- a/procinterrupts.c
+++ b/procinterrupts.c
@@ -331,7 +331,7 @@ void parse_proc_interrupts(void)
while (1) {
uint64_t C;
C = strtoull(c, &c2, 10);
- if (c==c2) /* end of numbers */
+ if (c==c2 || !strchr(" \t", *c2)) /* end of numbers */
break;
count += C;
c=c2;
--
2.33.1

View File

@ -0,0 +1,50 @@
From 7f1caca47aee32084c319db07d9a236684b818a3 Mon Sep 17 00:00:00 2001
From: Liu Chao <liuchao173@huawei.com>
Date: Tue, 28 Jun 2022 16:42:10 +0800
Subject: [PATCH 09/14] irqbalance-ui: move 'ASSIGNED TO CPUS' to the last
column
Signed-off-by: Liu Chao <liuchao173@huawei.com>
---
ui/ui.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/ui/ui.c b/ui/ui.c
index 6ff3305..beafe3a 100644
--- a/ui/ui.c
+++ b/ui/ui.c
@@ -331,7 +331,7 @@ void print_assigned_objects_string(irq_t *irq, int *line_offset)
char assigned_to[128] = "\0";
for_each_int(irq->assigned_to, copy_assigned_obj, assigned_to);
assigned_to[strlen(assigned_to) - 2] = '\0';
- mvprintw(*line_offset, 36, "%s", assigned_to);
+ mvprintw(*line_offset, 68, "%s", assigned_to);
}
void print_irq_line(irq_t *irq, void *data)
@@ -364,9 +364,9 @@ void print_irq_line(irq_t *irq, void *data)
}
mvprintw(*line_offset, 3, "IRQ %d", irq->vector);
mvprintw(*line_offset, 19, "%s", irq->is_banned ? "YES" : "NO ");
- print_assigned_objects_string(irq, line_offset);
- mvprintw(*line_offset, 84, "%s",
+ mvprintw(*line_offset, 36, "%s",
irq->class < 0 ? "Unknown" : IRQ_CLASS_TO_STR[irq->class]);
+ print_assigned_objects_string(irq, line_offset);
(*line_offset)++;
}
@@ -377,8 +377,8 @@ void print_all_irqs()
*line = 4;
attrset(COLOR_PAIR(0));
mvprintw(2, 3,
- "NUMBER IS BANNED ASSIGNED TO CPUS \
- CLASS");
+ "NUMBER IS BANNED CLASS \
+ ASSIGNED TO CPUS");
for_each_irq(all_irqs, print_irq_line, line);
}
--
2.33.1

View File

@ -0,0 +1,347 @@
From b65faa2b658e3cf4edf6d39e4bb1e103a47ac0de Mon Sep 17 00:00:00 2001
From: Liu Chao <liuchao173@huawei.com>
Date: Thu, 30 Jun 2022 10:19:00 +0800
Subject: [PATCH 10/14] irqbalance-ui: can't change window when in editing
state
when invoking setup_irqs in settings or invoking settings in setup_irqs, it
doesn't break but enters another while loop.
For example:
# gdb program `pidof irqbalance-ui`
(gdb) bt
#0 0x0000ffffb0dcc7b0 in poll () from /usr/lib64/libc.so.6
#1 0x0000ffffb0e9097c in _nc_timed_wait () from /usr/lib64/libtinfo.so.6
#2 0x0000ffffb0ecc154 in _nc_wgetch () from /usr/lib64/libncursesw.so.6
#3 0x0000ffffb0eccb18 in wgetch () from /usr/lib64/libncursesw.so.6
#4 0x00000000004045d4 in setup_irqs () at ui/ui.c:637
#5 0x0000000000404084 in settings () at ui/ui.c:614
#6 0x0000000000404084 in settings () at ui/ui.c:614
#7 0x0000000000404084 in settings () at ui/ui.c:614
#8 0x0000000000404084 in settings () at ui/ui.c:614
#9 0x0000000000404084 in settings () at ui/ui.c:614
#10 0x0000000000404084 in settings () at ui/ui.c:614
#11 0x0000000000404084 in settings () at ui/ui.c:614
#12 0x0000000000401fac in key_loop (data=<optimized out>) at ui/irqbalance-ui.c:387
#13 0x0000ffffb105371c in ?? () from /usr/lib64/libglib-2.0.so.0
#14 0x0000ffffb1052a84 in g_main_context_dispatch () from /usr/lib64/libglib-2.0.so.0
#15 0x0000ffffb1052e38 in ?? () from /usr/lib64/libglib-2.0.so.0
#16 0x0000ffffb1053188 in g_main_loop_run () from /usr/lib64/libglib-2.0.so.0
#17 0x000000000040196c in main (argc=<optimized out>, argv=<optimized out>) at ui/irqbalance-ui.c:445
Signed-off-by: Liu Chao <liuchao173@huawei.com>
---
ui/irqbalance-ui.c | 39 ++++++++++---
ui/ui.c | 137 ++++++++++++---------------------------------
ui/ui.h | 2 +-
3 files changed, 69 insertions(+), 109 deletions(-)
diff --git a/ui/irqbalance-ui.c b/ui/irqbalance-ui.c
index 3ad3553..89ed94a 100644
--- a/ui/irqbalance-ui.c
+++ b/ui/irqbalance-ui.c
@@ -16,11 +16,16 @@
#include "helpers.h"
+enum states {
+ STATE_TREE,
+ STATE_SETTINGS,
+ STATE_SETUP_IRQS
+};
+int state;
int irqbalance_pid = -1;
GList *tree = NULL;
setup_t setup;
GMainLoop *main_loop;
-int is_tree = 1;
static int default_bufsz = 8192;
struct msghdr * create_credentials_msg()
@@ -359,7 +364,7 @@ gboolean rescan_tree(gpointer data __attribute__((unused)))
parse_setup(setup_data);
char *irqbalance_data = get_data(STATS);
parse_into_tree(irqbalance_data);
- if(is_tree) {
+ if(state == STATE_TREE) {
display_tree();
}
free(setup_data);
@@ -375,16 +380,35 @@ gboolean key_loop(gpointer data __attribute__((unused)))
close_window(0);
break;
case KEY_F(3):
- is_tree = 1;
- display_tree();
+ if (state == STATE_SETTINGS || state == STATE_SETUP_IRQS) {
+ state = STATE_TREE;
+ display_tree();
+ }
break;
case KEY_F(4):
- is_tree = 0;
+ if (state == STATE_TREE || state == STATE_SETUP_IRQS) {
+ state = STATE_SETTINGS;
+ settings();
+ }
settings();
break;
case KEY_F(5):
- is_tree = 0;
- setup_irqs();
+ if (state == STATE_TREE || state == STATE_SETTINGS) {
+ state = STATE_SETUP_IRQS;
+ setup_irqs();
+ }
+ break;
+ case 'c':
+ if (state == STATE_SETTINGS)
+ handle_cpu_banning();
+ break;
+ case 'i':
+ if (state == STATE_SETUP_IRQS)
+ handle_irq_banning();
+ break;
+ case 's':
+ if (state == STATE_SETTINGS)
+ handle_sleep_setting();
break;
default:
break;
@@ -437,6 +461,7 @@ int main(int argc, char **argv)
}
}
+ state = STATE_TREE;
init();
main_loop = g_main_loop_new(NULL, FALSE);
diff --git a/ui/ui.c b/ui/ui.c
index beafe3a..1e211de 100644
--- a/ui/ui.c
+++ b/ui/ui.c
@@ -273,7 +273,8 @@ void handle_cpu_banning()
attrset(COLOR_PAIR(5));
mvprintw(LINES - 2, 1,
"Press <S> for changing sleep setup, <C> for CPU ban setup. ");
- move(LINES - 1, COLS - 1);
+ show_frame();
+ show_footer();
refresh();
break;
case 's':
@@ -287,8 +288,8 @@ void handle_cpu_banning()
attrset(COLOR_PAIR(5));
mvprintw(LINES - 2, 1,
"Press <S> for changing sleep setup, <C> for CPU ban setup. ");
- attrset(COLOR_PAIR(3));
- move(LINES - 1, COLS - 1);
+ show_frame();
+ show_footer();
refresh();
char settings_string[1024] = "settings cpus \0";
for_each_cpu(all_cpus, get_new_cpu_ban_values, settings_string);
@@ -302,16 +303,6 @@ void handle_cpu_banning()
processing = 0;
close_window(0);
break;
- case KEY_F(3):
- is_tree = 1;
- processing = 0;
- display_tree();
- break;
- case KEY_F(5):
- is_tree = 0;
- processing = 0;
- setup_irqs();
- break;
default:
break;
}
@@ -475,7 +466,8 @@ void handle_irq_banning()
attrset(COLOR_PAIR(5));
mvprintw(LINES - 2, 1, "Press <I> for setting up IRQ banning.\
");
- move(LINES - 1, COLS - 1);
+ show_frame();
+ show_footer();
refresh();
break;
case 's':
@@ -490,7 +482,8 @@ void handle_irq_banning()
mvprintw(LINES - 2, 1, "Press <I> for setting up IRQ banning.\
");
attrset(COLOR_PAIR(3));
- move(LINES - 1, COLS - 1);
+ show_frame();
+ show_footer();
refresh();
char settings_string[1024] = BAN_IRQS;
for_each_irq(all_irqs, get_new_irq_ban_values, settings_string);
@@ -504,22 +497,35 @@ void handle_irq_banning()
processing = 0;
close_window(0);
break;
- case KEY_F(3):
- is_tree = 1;
- processing = 0;
- display_tree();
- break;
- case KEY_F(4):
- is_tree = 0;
- processing = 0;
- settings();
- break;
default:
break;
}
}
}
+void handle_sleep_setting()
+{
+ char info[128] = "Current sleep interval between rebalancing: \0";
+ uint8_t sleep_input_offset = strlen(info) + 3;
+ mvprintw(LINES - 1, 1, "Press ESC for discarding your input.\
+ ");
+ attrset(COLOR_PAIR(0));
+ mvprintw(LINES - 2, 1, " \
+ ");
+ uint64_t new_sleep = get_valid_sleep_input(sleep_input_offset);
+ if(new_sleep != setup.sleep) {
+ setup.sleep = new_sleep;
+ char settings_data[128];
+ snprintf(settings_data, 128, "%s %" PRIu64, SET_SLEEP, new_sleep);
+ send_settings(settings_data);
+ }
+ attrset(COLOR_PAIR(5));
+ mvprintw(LINES - 2, 1, "Press <S> for changing sleep setup, <C> for CPU ban setup. ");
+ show_frame();
+ show_footer();
+ refresh();
+}
+
void init()
{
signal(SIGINT, close_window);
@@ -563,60 +569,15 @@ void settings()
parse_setup(setup_data);
char info[128] = "Current sleep interval between rebalancing: \0";
- uint8_t sleep_input_offset = strlen(info) + 3;
snprintf(info + strlen(info), 128 - strlen(info), "%" PRIu64 "\n", setup.sleep);
attrset(COLOR_PAIR(1));
mvprintw(2, 3, "%s", info);
print_all_cpus();
-
- int user_input = 1;
- while(user_input) {
- attrset(COLOR_PAIR(5));
- mvprintw(LINES - 2, 1,
- "Press <S> for changing sleep setup, <C> for CPU ban setup. ");
- show_frame();
- show_footer();
- refresh();
- int c = getch();
- switch(c) {
- case 's': {
- mvprintw(LINES - 1, 1, "Press ESC for discarding your input.\
- ");
- attrset(COLOR_PAIR(0));
- mvprintw(LINES - 2, 1, " \
- ");
- uint64_t new_sleep = get_valid_sleep_input(sleep_input_offset);
- if(new_sleep != setup.sleep) {
- setup.sleep = new_sleep;
- char settings_data[128];
- snprintf(settings_data, 128, "%s %" PRIu64, SET_SLEEP, new_sleep);
- send_settings(settings_data);
- }
- break;
- }
- case 'c':
- handle_cpu_banning();
- break;
- /* We need to include window changing options as well because the
- * related char was eaten up by getch() already */
- case 'q':
- user_input = 0;
- close_window(0);
- break;
- case KEY_F(3):
- is_tree = 1;
- user_input = 0;
- display_tree();
- break;
- case KEY_F(5):
- is_tree = 0;
- user_input = 0;
- setup_irqs();
- break;
- default:
- break;
- }
- }
+ attrset(COLOR_PAIR(5));
+ mvprintw(LINES - 2, 1, "Press <S> for changing sleep setup, <C> for CPU ban setup. ");
+ show_frame();
+ show_footer();
+ refresh();
free(setup_data);
}
@@ -631,32 +592,6 @@ void setup_irqs()
show_frame();
show_footer();
refresh();
-
- int user_input = 1;
- while(user_input) {
- int c = getch();
- switch(c) {
- case 'i':
- handle_irq_banning();
- break;
- case 'q':
- user_input = 0;
- close_window(0);
- break;
- case KEY_F(3):
- is_tree = 1;
- user_input = 0;
- display_tree();
- break;
- case KEY_F(4):
- is_tree = 0;
- user_input = 0;
- settings();
- break;
- default:
- break;
- }
- }
}
void display_tree_node_irqs(irq_t *irq, void *data)
diff --git a/ui/ui.h b/ui/ui.h
index 0aa8280..ca2a3a6 100644
--- a/ui/ui.h
+++ b/ui/ui.h
@@ -13,7 +13,6 @@
extern GList *tree;
extern setup_t setup;
-extern int is_tree;
void show_frame();
void show_footer();
@@ -29,6 +28,7 @@ void display_banned_cpus();
int toggle_cpu(GList *cpu_list, int cpu_number);
void get_new_cpu_ban_values(cpu_ban_t *cpu, void *data);
void get_cpu();
+void handle_sleep_setting();
void handle_cpu_banning();
void copy_assigned_obj(int *number, void *data);
--
2.33.1

View File

@ -0,0 +1,47 @@
From a61b382805961934c6425f19a762a6ab99884c24 Mon Sep 17 00:00:00 2001
From: Liu Chao <liuchao173@huawei.com>
Date: Thu, 30 Jun 2022 11:30:43 +0800
Subject: [PATCH 11/14] fix memory leak in ui/ui.c
Signed-off-by: Liu Chao <liuchao173@huawei.com>
---
ui/ui.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/ui/ui.c b/ui/ui.c
index 1e211de..6b1c689 100644
--- a/ui/ui.c
+++ b/ui/ui.c
@@ -156,11 +156,10 @@ void print_all_cpus()
for_each_int(setup.banned_cpus, get_banned_cpu, NULL);
all_cpus = g_list_sort(all_cpus, sort_all_cpus);
}
- int *line = malloc(sizeof(int));
- *line = 6;
+ int line = 6;
attrset(COLOR_PAIR(2));
mvprintw(4, 3, "NUMBER IS BANNED");
- for_each_cpu(all_cpus, print_cpu_line, line);
+ for_each_cpu(all_cpus, print_cpu_line, &line);
}
void add_banned_cpu(int *banned_cpu, void *data)
@@ -364,13 +363,12 @@ void print_irq_line(irq_t *irq, void *data)
void print_all_irqs()
{
- int *line = malloc(sizeof(int));
- *line = 4;
+ int line = 4;
attrset(COLOR_PAIR(0));
mvprintw(2, 3,
"NUMBER IS BANNED CLASS \
ASSIGNED TO CPUS");
- for_each_irq(all_irqs, print_irq_line, line);
+ for_each_irq(all_irqs, print_irq_line, &line);
}
int toggle_irq(GList *irq_list, int position)
--
2.33.1

View File

@ -0,0 +1,583 @@
From db7dc03388a20ba2d873a81c3e14b933e2b09551 Mon Sep 17 00:00:00 2001
From: Liu Chao <liuchao173@huawei.com>
Date: Mon, 4 Jul 2022 16:25:14 +0800
Subject: [PATCH 12/14] irqbalance-ui: support scroll under tui mode of
irqbalance-ui
support using Up, Down, PageUp, PageDown to scroll in view mode
support using Up and Down in edit mode
Signed-off-by: Liu Chao <liuchao173@huawei.com>
---
ui/helpers.c | 2 +
ui/irqbalance-ui.c | 138 ++++++++++++++++++++++++---------
ui/irqbalance-ui.h | 2 +
ui/ui.c | 187 ++++++++++++++++++++++++++++++++++++---------
ui/ui.h | 3 +
5 files changed, 262 insertions(+), 70 deletions(-)
diff --git a/ui/helpers.c b/ui/helpers.c
index 5d71275..0e9f76c 100644
--- a/ui/helpers.c
+++ b/ui/helpers.c
@@ -89,6 +89,7 @@ gpointer copy_cpu_ban(gconstpointer src, gpointer data __attribute__((unused)))
cpu_ban_t *new = malloc(sizeof(cpu_ban_t));
new->number = old->number;
new->is_banned = old->is_banned;
+ new->is_changed = 0;
return new;
}
@@ -100,6 +101,7 @@ gpointer copy_irq(gconstpointer src, gpointer data __attribute__((unused)))
new->load = old->load;
new->diff = old->diff;
new->is_banned = old->is_banned;
+ new->is_changed = 0;
new->class = old->class;
new->assigned_to = g_list_copy(old->assigned_to);
return new;
diff --git a/ui/irqbalance-ui.c b/ui/irqbalance-ui.c
index 89ed94a..47b6c88 100644
--- a/ui/irqbalance-ui.c
+++ b/ui/irqbalance-ui.c
@@ -371,48 +371,116 @@ gboolean rescan_tree(gpointer data __attribute__((unused)))
free(irqbalance_data);
return TRUE;
}
-
-gboolean key_loop(gpointer data __attribute__((unused)))
-{
- int c = getch();
- switch(c) {
- case 'q':
- close_window(0);
- break;
- case KEY_F(3):
- if (state == STATE_SETTINGS || state == STATE_SETUP_IRQS) {
- state = STATE_TREE;
- display_tree();
- }
+void scroll_window() {
+ switch(state) {
+ case STATE_TREE:
+ display_tree();
break;
- case KEY_F(4):
- if (state == STATE_TREE || state == STATE_SETUP_IRQS) {
- state = STATE_SETTINGS;
- settings();
- }
+ case STATE_SETTINGS:
settings();
break;
- case KEY_F(5):
- if (state == STATE_TREE || state == STATE_SETTINGS) {
- state = STATE_SETUP_IRQS;
- setup_irqs();
- }
- break;
- case 'c':
- if (state == STATE_SETTINGS)
- handle_cpu_banning();
- break;
- case 'i':
- if (state == STATE_SETUP_IRQS)
- handle_irq_banning();
- break;
- case 's':
- if (state == STATE_SETTINGS)
- handle_sleep_setting();
+ case STATE_SETUP_IRQS:
+ setup_irqs();
break;
default:
break;
}
+}
+
+gboolean key_loop(gpointer data __attribute__((unused)))
+{
+ while(1) {
+ int c = getch();
+ switch(c) {
+ case 'q':
+ close_window(0);
+ break;
+ case KEY_UP:
+ if (offset > 0) {
+ offset--;
+ scroll_window();
+ }
+ break;
+ case KEY_DOWN:
+ if (offset < max_offset) {
+ offset++;
+ scroll_window();
+ }
+ break;
+ case KEY_NPAGE:
+ switch (state) {
+ case STATE_TREE:
+ offset += LINES - 5;
+ break;
+ case STATE_SETTINGS:
+ offset += LINES - 8;
+ break;
+ case STATE_SETUP_IRQS:
+ offset += LINES - 6;
+ break;
+ default:
+ break;
+ }
+ if (offset > max_offset)
+ offset = max_offset;
+ scroll_window();
+ break;
+ case KEY_PPAGE:
+ switch (state) {
+ case STATE_TREE:
+ offset -= LINES - 5;
+ break;
+ case STATE_SETTINGS:
+ offset -= LINES - 8;
+ break;
+ case STATE_SETUP_IRQS:
+ offset -= LINES - 6;
+ break;
+ default:
+ break;
+ }
+ if (offset < 0)
+ offset = 0;
+ scroll_window();
+ break;
+ case KEY_F(3):
+ if (state == STATE_SETTINGS || state == STATE_SETUP_IRQS) {
+ state = STATE_TREE;
+ offset = 0;
+ display_tree();
+ }
+ break;
+ case KEY_F(4):
+ if (state == STATE_TREE || state == STATE_SETUP_IRQS) {
+ state = STATE_SETTINGS;
+ offset = 0;
+ settings();
+ }
+ settings();
+ break;
+ case KEY_F(5):
+ if (state == STATE_TREE || state == STATE_SETTINGS) {
+ state = STATE_SETUP_IRQS;
+ offset = 0;
+ setup_irqs();
+ }
+ break;
+ case 'c':
+ if (state == STATE_SETTINGS)
+ handle_cpu_banning();
+ break;
+ case 'i':
+ if (state == STATE_SETUP_IRQS)
+ handle_irq_banning();
+ break;
+ case 's':
+ if (state == STATE_SETTINGS)
+ handle_sleep_setting();
+ break;
+ default:
+ break;
+ }
+ }
return TRUE;
}
diff --git a/ui/irqbalance-ui.h b/ui/irqbalance-ui.h
index fba7e7c..dc24083 100644
--- a/ui/irqbalance-ui.h
+++ b/ui/irqbalance-ui.h
@@ -41,6 +41,7 @@ typedef struct irq {
uint64_t load;
uint64_t diff;
char is_banned;
+ char is_changed;
GList *assigned_to;
int class;
} irq_t;
@@ -60,6 +61,7 @@ typedef struct cpu_node {
typedef struct cpu_ban {
int number;
char is_banned;
+ char is_changed;
} cpu_ban_t;
typedef struct setup {
diff --git a/ui/ui.c b/ui/ui.c
index 6b1c689..2dad442 100644
--- a/ui/ui.c
+++ b/ui/ui.c
@@ -3,6 +3,8 @@
#include <string.h>
#include "ui.h"
+int offset;
+int max_offset;
GList *all_cpus = NULL;
GList *all_irqs = NULL;
@@ -134,32 +136,54 @@ void get_banned_cpu(int *cpu, void *data __attribute__((unused)))
all_cpus = g_list_append(all_cpus, new);
}
-void print_cpu_line(cpu_ban_t *cpu, void *data)
+void print_tmp_cpu_line(cpu_ban_t *cpu, void *data __attribute__((unused)))
{
- int *line_offset = data;
- if(cpu->is_banned) {
- attrset(COLOR_PAIR(10));
- } else {
- attrset(COLOR_PAIR(9));
+ int line = max_offset - offset + 6;
+ if (max_offset >= offset && line < LINES - 3) {
+ if (cpu->is_changed)
+ attrset(COLOR_PAIR(3));
+ else if(cpu->is_banned)
+ attrset(COLOR_PAIR(10));
+ else
+ attrset(COLOR_PAIR(9));
+ mvprintw(line, 3, "CPU %d ", cpu->number);
+ mvprintw(line, 19, "%s", cpu->is_banned ?
+ "YES " :
+ "NO ");
}
- mvprintw(*line_offset, 3, "CPU %d", cpu->number);
- mvprintw(*line_offset, 19, "%s", cpu->is_banned ?
- "YES " :
- "NO ");
- (*line_offset)++;
+ max_offset++;
+}
+
+void print_cpu_line(cpu_ban_t *cpu, void *data __attribute__((unused)))
+{
+ int line = max_offset - offset + 6;
+ if (max_offset >= offset && line < LINES - 2) {
+ if(cpu->is_banned)
+ attrset(COLOR_PAIR(10));
+ else
+ attrset(COLOR_PAIR(9));
+ mvprintw(line, 3, "CPU %d ", cpu->number);
+ mvprintw(line, 19, "%s", cpu->is_banned ?
+ "YES " :
+ "NO ");
+ }
+ max_offset++;
}
void print_all_cpus()
{
+ max_offset = 0;
if(all_cpus == NULL) {
for_each_node(tree, get_cpu, NULL);
for_each_int(setup.banned_cpus, get_banned_cpu, NULL);
all_cpus = g_list_sort(all_cpus, sort_all_cpus);
}
- int line = 6;
attrset(COLOR_PAIR(2));
mvprintw(4, 3, "NUMBER IS BANNED");
- for_each_cpu(all_cpus, print_cpu_line, &line);
+ for_each_cpu(all_cpus, print_cpu_line, NULL);
+ max_offset -= LINES - 8;
+ if (max_offset < 0)
+ max_offset = 0;
}
void add_banned_cpu(int *banned_cpu, void *data)
@@ -195,6 +219,7 @@ int toggle_cpu(GList *cpu_list, int cpu_number)
} else {
((cpu_ban_t *)(entry->data))->is_banned = 1;
}
+ ((cpu_ban_t *)(entry->data))->is_changed = 1;
return ((cpu_ban_t *)(entry->data))->is_banned;
}
@@ -239,18 +264,37 @@ void handle_cpu_banning()
if(position > 6) {
position--;
move(position, 19);
+ } else if (offset > 0) {
+ offset--;
+ max_offset = 0;
+ for_each_cpu(tmp, print_tmp_cpu_line, NULL);
+ max_offset -= LINES - 9;
+ if (max_offset < 0)
+ max_offset = 0;
+ move(position, 19);
}
break;
case KEY_DOWN:
- if(position <= g_list_length(all_cpus) + 4) {
- position++;
+ if(position < (size_t)(LINES - 4)) {
+ if (position <= g_list_length(all_cpus) + 4 - offset) {
+ position++;
+ move(position, 19);
+ }
+ } else if (offset < max_offset) {
+ offset++;
+ max_offset = 0;
+ for_each_cpu(tmp, print_tmp_cpu_line, NULL);
+ max_offset -= LINES - 9;
+ if (max_offset < 0)
+ max_offset = 0;
move(position, 19);
}
break;
case '\n':
case '\r': {
attrset(COLOR_PAIR(3));
- int banned = toggle_cpu(tmp, position - 6);
+ int banned = toggle_cpu(tmp, position + offset - 6);
+ mvprintw(position, 3, "CPU %d ", position + offset - 6);
if(banned) {
mvprintw(position, 19, "YES");
} else {
@@ -263,8 +307,7 @@ void handle_cpu_banning()
case 27:
processing = 0;
curs_set(0);
- /* Forget the changes */
- tmp = g_list_copy_deep(all_cpus, copy_cpu_ban, NULL);
+ g_list_free(tmp);
print_all_cpus();
attrset(COLOR_PAIR(0));
mvprintw(LINES - 3, 1, " \
@@ -278,6 +321,7 @@ void handle_cpu_banning()
break;
case 's':
processing = 0;
+ g_list_free(all_cpus);
all_cpus = tmp;
curs_set(0);
print_all_cpus();
@@ -324,9 +368,12 @@ void print_assigned_objects_string(irq_t *irq, int *line_offset)
mvprintw(*line_offset, 68, "%s", assigned_to);
}
-void print_irq_line(irq_t *irq, void *data)
+void print_tmp_irq_line(irq_t *irq, void *data __attribute__((unused)))
{
- int *line_offset = data;
+ int line = max_offset - offset + 4;
+ max_offset++;
+ if (line < 4 || line >= LINES - 3)
+ return;
switch(irq->class) {
case(IRQ_OTHER):
attrset(COLOR_PAIR(1));
@@ -352,23 +399,62 @@ void print_irq_line(irq_t *irq, void *data)
attrset(COLOR_PAIR(0));
break;
}
- mvprintw(*line_offset, 3, "IRQ %d", irq->vector);
- mvprintw(*line_offset, 19, "%s", irq->is_banned ? "YES" : "NO ");
- mvprintw(*line_offset, 36, "%s",
+ mvprintw(line, 3, "IRQ %d ", irq->vector);
+ mvprintw(line, 19, "%s", irq->is_banned ? "YES" : "NO ");
+ mvprintw(line, 36, "%s ",
irq->class < 0 ? "Unknown" : IRQ_CLASS_TO_STR[irq->class]);
- print_assigned_objects_string(irq, line_offset);
- (*line_offset)++;
+ print_assigned_objects_string(irq, &line);
+}
+void print_irq_line(irq_t *irq, void *data __attribute__((unused)))
+{
+ int line = max_offset - offset + 4;
+ max_offset++;
+ if (line < 4 || line >= LINES - 2)
+ return;
+ switch(irq->class) {
+ case(IRQ_OTHER):
+ attrset(COLOR_PAIR(1));
+ break;
+ case(IRQ_LEGACY):
+ attrset(COLOR_PAIR(2));
+ break;
+ case(IRQ_SCSI):
+ attrset(COLOR_PAIR(3));
+ break;
+ case(IRQ_VIDEO):
+ attrset(COLOR_PAIR(8));
+ break;
+ case(IRQ_ETH):
+ case(IRQ_GBETH):
+ case(IRQ_10GBETH):
+ attrset(COLOR_PAIR(9));
+ break;
+ case(IRQ_VIRT_EVENT):
+ attrset(COLOR_PAIR(10));
+ break;
+ default:
+ attrset(COLOR_PAIR(0));
+ break;
+ }
+ mvprintw(line, 3, "IRQ %d", irq->vector);
+ mvprintw(line, 19, "%s", irq->is_banned ? "YES" : "NO ");
+ mvprintw(line, 36, "%s ",
+ irq->class < 0 ? "Unknown" : IRQ_CLASS_TO_STR[irq->class]);
+ print_assigned_objects_string(irq, &line);
}
void print_all_irqs()
{
- int line = 4;
+ max_offset = 0;
attrset(COLOR_PAIR(0));
mvprintw(2, 3,
"NUMBER IS BANNED CLASS \
ASSIGNED TO CPUS");
- for_each_irq(all_irqs, print_irq_line, &line);
+ for_each_irq(all_irqs, print_irq_line, NULL);
+ max_offset -= LINES - 6;
+ if (max_offset < 0)
+ max_offset = 0;
}
int toggle_irq(GList *irq_list, int position)
@@ -384,6 +470,7 @@ int toggle_irq(GList *irq_list, int position)
} else {
((irq_t *)(entry->data))->is_banned = 1;
}
+ ((irq_t *)(entry->data))->is_changed = 1;
return ((irq_t *)(entry->data))->is_banned;
}
@@ -431,18 +518,36 @@ void handle_irq_banning()
if(position > 4) {
position--;
move(position, 19);
+ } else if (offset > 0) {
+ offset--;
+ max_offset = 0;
+ for_each_irq(tmp, print_tmp_irq_line, NULL);
+ max_offset -= LINES - 7;
+ if (max_offset < 0)
+ max_offset = 0;
+ move(position, 19);
}
break;
case KEY_DOWN:
- if(position < g_list_length(all_irqs) + 3) {
- position++;
+ if (position < (size_t)(LINES - 4)) {
+ if(position < g_list_length(all_irqs) + 3) {
+ position++;
+ move(position, 19);
+ }
+ } else if (offset < max_offset) {
+ offset++;
+ max_offset = 0;
+ for_each_irq(tmp, print_tmp_irq_line, NULL);
+ max_offset -= LINES - 7;
+ if (max_offset < 0)
+ max_offset = 0;
move(position, 19);
}
break;
case '\n':
case '\r': {
attrset(COLOR_PAIR(3));
- int banned = toggle_irq(tmp, position - 4);
+ int banned = toggle_irq(tmp, position + offset - 4);
if(banned) {
mvprintw(position, 19, "YES");
} else {
@@ -456,7 +561,7 @@ void handle_irq_banning()
processing = 0;
curs_set(0);
/* Forget the changes */
- tmp = g_list_copy_deep(all_irqs, copy_irq, NULL);
+ g_list_free(tmp);
print_all_irqs();
attrset(COLOR_PAIR(0));
mvprintw(LINES - 3, 1, " \
@@ -470,6 +575,7 @@ void handle_irq_banning()
break;
case 's':
processing = 0;
+ g_list_free(all_irqs);
all_irqs = tmp;
curs_set(0);
print_all_irqs();
@@ -548,11 +654,13 @@ void init()
init_pair(10, COLOR_MAGENTA, COLOR_BLACK);
}
+ offset = 0;
display_tree();
}
void close_window(int sig __attribute__((unused)))
{
+ g_list_free(all_cpus);
g_list_free(setup.banned_irqs);
g_list_free(setup.banned_cpus);
g_list_free_full(tree, free);
@@ -595,10 +703,13 @@ void setup_irqs()
void display_tree_node_irqs(irq_t *irq, void *data)
{
char indent[32] = " \0";
- snprintf(indent + strlen(indent), 32 - strlen(indent), "%s", (char *)data);
- attrset(COLOR_PAIR(3));
- printw("%sIRQ %u, IRQs since last rebalance %lu\n",
+ if (max_offset >= offset && max_offset - offset < LINES - 5) {
+ snprintf(indent + strlen(indent), 32 - strlen(indent), "%s", (char *)data);
+ attrset(COLOR_PAIR(3));
+ printw("%sIRQ %u, IRQs since last rebalance %lu\n",
indent, irq->vector, irq->diff);
+ }
+ max_offset++;
}
void display_tree_node(cpu_node_t *node, void *data)
@@ -644,7 +755,9 @@ void display_tree_node(cpu_node_t *node, void *data)
default:
break;
}
- printw("%s", copy_to);
+ if (max_offset >= offset)
+ printw("%s", copy_to);
+ max_offset++;
if(g_list_length(node->irqs) > 0) {
for_each_irq(node->irqs, display_tree_node_irqs, indent);
}
@@ -661,7 +774,11 @@ void display_tree()
char *irqbalance_data = get_data(STATS);
parse_into_tree(irqbalance_data);
display_banned_cpus();
+ max_offset = 0;
for_each_node(tree, display_tree_node, NULL);
+ max_offset -= LINES - 5;
+ if (max_offset < 0)
+ max_offset = 0;
show_frame();
show_footer();
refresh();
diff --git a/ui/ui.h b/ui/ui.h
index ca2a3a6..da5b4b9 100644
--- a/ui/ui.h
+++ b/ui/ui.h
@@ -14,6 +14,9 @@
extern GList *tree;
extern setup_t setup;
+extern int offset;
+extern int max_offset;
+
void show_frame();
void show_footer();
--
2.33.1

View File

@ -0,0 +1,66 @@
From 577796abe7337c8df446c082688816ec22804876 Mon Sep 17 00:00:00 2001
From: Liu Chao <liuchao173@huawei.com>
Date: Mon, 11 Jul 2022 11:12:06 +0800
Subject: [PATCH 13/14] irqbalance-ui: print cpulist in SETUP IRQS
save space for printing interrupt names
Signed-off-by: Liu Chao <liuchao173@huawei.com>
---
ui/ui.c | 30 +++++++++++++++++++++++++++---
1 file changed, 27 insertions(+), 3 deletions(-)
diff --git a/ui/ui.c b/ui/ui.c
index 2dad442..f1490d5 100644
--- a/ui/ui.c
+++ b/ui/ui.c
@@ -352,9 +352,32 @@ void handle_cpu_banning()
}
}
+static int rbot, rtop;
+
+static inline void bsnl_emit(char *buf, int buflen)
+{
+ int len = strlen(buf);
+ if (len > 0) {
+ snprintf(buf + len, buflen - len, ",");
+ len++;
+ }
+ if (rbot == rtop)
+ snprintf(buf + len, buflen - len, "%d", rbot);
+ else
+ snprintf(buf + len, buflen - len, "%d-%d", rbot, rtop);
+}
+
void copy_assigned_obj(int *number, void *data)
{
- snprintf(data + strlen(data), 128 - strlen(data), "%d, ", *number);
+ if (rtop == -1) {
+ rbot = rtop = *number;
+ return;
+ }
+ if (*number > rtop + 1) {
+ bsnl_emit(data, 128);
+ rbot = *number;
+ }
+ rtop = *number;
}
void print_assigned_objects_string(irq_t *irq, int *line_offset)
@@ -363,9 +386,10 @@ void print_assigned_objects_string(irq_t *irq, int *line_offset)
return;
}
char assigned_to[128] = "\0";
+ rtop = -1;
for_each_int(irq->assigned_to, copy_assigned_obj, assigned_to);
- assigned_to[strlen(assigned_to) - 2] = '\0';
- mvprintw(*line_offset, 68, "%s", assigned_to);
+ bsnl_emit(assigned_to, 128);
+ mvprintw(*line_offset, 68, "%s ", assigned_to);
}
void print_tmp_irq_line(irq_t *irq, void *data __attribute__((unused)))
--
2.33.1

View File

@ -0,0 +1,72 @@
From cfb15f0bb95ebfd4357708eae42febe9f2121fba Mon Sep 17 00:00:00 2001
From: Tao Liu <ltao@redhat.com>
Date: Wed, 13 Jul 2022 17:11:40 +0800
Subject: [PATCH 14/14] Improve documentation and logging for banned cpus
This patch have no functional modification. Just improve the doc and log
for isolcpu, nohz_full and numa node banning cpus, for providing more
info for users.
Signed-off-by: Tao Liu <ltao@redhat.com>
---
cputree.c | 6 +++---
irqbalance.1 | 2 +-
placement.c | 6 +++++-
3 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/cputree.c b/cputree.c
index c250977..eb1981e 100644
--- a/cputree.c
+++ b/cputree.c
@@ -159,14 +159,14 @@ static void setup_banned_cpus(void)
cpus_or(banned_cpus, nohz_full, isolated_cpus);
cpumask_scnprintf(buffer, 4096, isolated_cpus);
- log(TO_CONSOLE, LOG_INFO, "Isolated CPUs: %s\n", buffer);
+ log(TO_CONSOLE, LOG_INFO, "Prevent irq assignment to these isolated CPUs: %s\n", buffer);
cpumask_scnprintf(buffer, 4096, nohz_full);
- log(TO_CONSOLE, LOG_INFO, "Adaptive-ticks CPUs: %s\n", buffer);
+ log(TO_CONSOLE, LOG_INFO, "Prevent irq assignment to these adaptive-ticks CPUs: %s\n", buffer);
out:
#ifdef HAVE_THERMAL
cpus_or(banned_cpus, banned_cpus, thermal_banned_cpus);
cpumask_scnprintf(buffer, 4096, thermal_banned_cpus);
- log(TO_CONSOLE, LOG_INFO, "Thermal-banned CPUs: %s\n", buffer);
+ log(TO_CONSOLE, LOG_INFO, "Prevent irq assignment to these thermal-banned CPUs: %s\n", buffer);
#endif
cpumask_scnprintf(buffer, 4096, banned_cpus);
log(TO_CONSOLE, LOG_INFO, "Banned CPUs: %s\n", buffer);
diff --git a/irqbalance.1 b/irqbalance.1
index 361faea..4c75362 100644
--- a/irqbalance.1
+++ b/irqbalance.1
@@ -167,7 +167,7 @@ Same as --debug.
.B IRQBALANCE_BANNED_CPUS
Provides a mask of CPUs which irqbalance should ignore and never assign interrupts to.
If not specified, irqbalance use mask of isolated and adaptive-ticks CPUs on the
-system as the default value.
+system as the default value. The "isolcpus=" boot parameter specifies the isolated CPUs. The "nohz_full=" boot parameter specifies the adaptive-ticks CPUs. By default, no CPU will be an isolated or adaptive-ticks CPU.
This is a hexmask without the leading 0x. On systems with large numbers of
processors, each group of eight hex digits is separated by a comma ,. i.e.
export IRQBALANCE_BANNED_CPUS=fc0 would prevent irqbalance from assigning irqs
diff --git a/placement.c b/placement.c
index 17a9f2e..9fde8cb 100644
--- a/placement.c
+++ b/placement.c
@@ -135,8 +135,12 @@ static void place_irq_in_node(struct irq_info *info, void *data __attribute__((u
* Need to make sure this node is elligible for migration
* given the banned cpu list
*/
- if (!cpus_intersects(irq_numa_node(info)->mask, unbanned_cpus))
+ if (!cpus_intersects(irq_numa_node(info)->mask, unbanned_cpus)) {
+ log(TO_CONSOLE, LOG_WARNING, "There is no suitable CPU in node:%d.\n", irq_numa_node(info)->number);
+ log(TO_CONSOLE, LOG_WARNING, "Irqbalance dispatch irq:%d to other node.\n", info->irq);
goto find_placement;
+ }
+
/*
* This irq belongs to a device with a preferred numa node
* put it on that node
--
2.33.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]

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] 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);
--
2.21.0

View File

@ -1,34 +0,0 @@
From 16cb6df56960f58df61ec35ef3be45286eb3c788 Mon Sep 17 00:00:00 2001
From: Kairui Song <kasong@redhat.com>
Date: Sun, 2 Sep 2018 23:40:45 +0800
Subject: [PATCH 2/4] 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 4b3de54..c89c3c0 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -457,8 +457,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);
}
--
2.17.1

View File

@ -1,253 +0,0 @@
From 9ed5c269bd59c95f41829aedf0520930c97b08d3 Mon Sep 17 00:00:00 2001
From: Kairui Song <kasong@redhat.com>
Date: Thu, 30 Aug 2018 17:45:53 +0800
Subject: 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 6412447..4b3de54 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -385,11 +385,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) &&
@@ -401,7 +401,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"))) {
@@ -421,6 +421,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;
@@ -432,12 +433,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(
@@ -449,6 +452,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"))) {
@@ -463,10 +467,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 3fc46af..99f2ca2 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));
--
2.17.1

View File

@ -1,72 +0,0 @@
From 3eae2edd136540898f8e51546eedfb56729f938d Mon Sep 17 00:00:00 2001
From: Xiao Liang <xiliang@redhat.com>
Date: Thu, 18 Oct 2018 21:50:33 +0800
Subject: 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 eb84a1c..ca9533b 100644
--- a/procinterrupts.c
+++ b/procinterrupts.c
@@ -167,6 +167,7 @@ GList* collect_full_irq_list()
while (!feof(file)) {
int number;
+ int is_xen_dyn = 0;
struct irq_info *info;
char *c;
char savedline[1024];
@@ -187,9 +188,13 @@ GList* collect_full_irq_list()
strncpy(savedline, line, sizeof(savedline));
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;
}
@@ -209,7 +214,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 {
--
2.17.1

View File

@ -1,65 +0,0 @@
From ce71f0cc2255aba072eabb2af26f6cb0e31f8189 Mon Sep 17 00:00:00 2001
From: Kairui Song <kasong@redhat.com>
Date: Tue, 6 Nov 2018 10:37:15 +0800
Subject: 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 c89c3c0..a77f842 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -389,7 +389,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) &&
@@ -401,7 +401,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"))) {
@@ -434,7 +434,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 {
@@ -470,6 +470,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 99f2ca2..6d4c845 100644
--- a/ui/irqbalance-ui.c
+++ b/ui/irqbalance-ui.c
@@ -62,6 +62,7 @@ int init_connection()
if(connect(socket_fd, (struct sockaddr *)&addr,
sizeof(sa_family_t) + strlen(socket_name) + 1) < 0) {
+ close(socket_fd);
return 0;
}
--
2.17.1

View File

@ -1,31 +0,0 @@
From a1abba7b070587cc5fa69597081dcc80f4addef3 Mon Sep 17 00:00:00 2001
From: Kairui Song <kasong@redhat.com>
Date: Tue, 26 Feb 2019 16:26:51 +0800
Subject: [PATCH] Refine document about IRQBALANCE_BANNED_CPUS
There is no declaration about how irqbalance deal with isolated CPUs or
adaptive-ticks CPUs, and how IRQBALANCE_BANNED_CPUS will override the
behavior of auto-banning of such CPUs. Refine the document to avoid
confusion.
Signed-off-by: Kairui Song <kasong@redhat.com>
---
irqbalance.1 | 2 ++
1 file changed, 2 insertions(+)
diff --git a/irqbalance.1 b/irqbalance.1
index 11eb498..d272b6f 100644
--- a/irqbalance.1
+++ b/irqbalance.1
@@ -155,6 +155,8 @@ Same as --debug.
.TP
.B IRQBALANCE_BANNED_CPUS
Provides a mask of CPUs which irqbalance should ignore and never assign interrupts to.
+If not specified, irqbalance use mask of isolated and adaptive-ticks CPUs on the
+system as the default value.
.SH "SIGNALS"
.TP
--
2.28.0

View File

@ -1,109 +0,0 @@
From 5f8ed87f36381569725c67445f12226f41861d1f Mon Sep 17 00:00:00 2001
From: Kairui Song <kasong@redhat.com>
Date: Fri, 9 Nov 2018 11:36:12 +0800
Subject: [PATCH] Update document and remove dead options
This is the stash of following three commits:
commit ea743009f69ad4800c60bf26c776ef4944c6af8b
Author: Kairui Song <kasong@redhat.com>
Date: Mon Mar 25 19:58:58 2019 +0800
Remove a duplicated word in manpage
Just noticed a warning in a manpage scan report, trivial but let's
fix it.
Signed-off-by: Kairui Song <kasong@redhat.com>
commit 0b95593b19ff13e7e271d5b0b8219e7c70bf773c
Author: Kairui Song <kasong@redhat.com>
Date: Fri Nov 9 12:26:29 2018 +0800
Update document for option --banmod and --deepestcache
'--banmod' is not documented, and '--deepestcache's alias '-c' is
missing.
Also fix an typo.
Signed-off-by: Kairui Song <kasong@redhat.com>
commit 3ae01f5bd5ef3ed3080c9b06fc63bb02cc03bf1a
Author: Kairui Song <kasong@redhat.com>
Date: Fri Nov 9 11:36:12 2018 +0800
Remove hintpolicy related options in help message
hintpolicy was dropped sometime ago so related help message should be
dropped as well.
Signed-off-by: Kairui Song <kasong@redhat.com>
Signed-off-by: Kairui Song <kasong@redhat.com>
---
irqbalance.1 | 15 ++++++++++++---
irqbalance.c | 3 +--
2 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/irqbalance.1 b/irqbalance.1
index 68e3cf8..61ae35e 100644
--- a/irqbalance.1
+++ b/irqbalance.1
@@ -62,12 +62,21 @@ in an effort to prevent that CPU from waking up without need.
.B -i, --banirq=<irqnum>
Add the specified IRQ to the set of banned IRQs. irqbalance will not affect
the affinity of any IRQs on the banned list, allowing them to be specified
-manually. This option is addative and can be specified multiple times. For
+manually. This option is additive and can be specified multiple times. For
example to ban IRQs 43 and 44 from balancing, use the following command line:
.B irqbalance --banirq=43 --banirq=44
.TP
-.B --deepestcache=<integer>
+.B -m, --banmod=<module_name>
+Add the specified module to the set of banned modules, similiar to --banirq.
+irqbalance will not affect the affinity of any IRQs of given modules, allowing
+them to be specified manually. This option is additive and can be specified
+multiple times. For example to ban all IRQs of module foo and module bar from
+balancing, use the following command line:
+.B irqbalance --banmod=foo --banmod=bar
+
+.TP
+.B -c, --deepestcache=<integer>
This allows a user to specify the cache level at which irqbalance partitions
cache domains. Specifying a deeper cache may allow a greater degree of
flexibility for irqbalance to assign IRQ affinity to achieve greater performance
@@ -148,7 +157,7 @@ each assigned IRQ type, it's number, load, number of IRQs since last rebalancing
and it's class are sent. Refer to types.h file for explanation of defines.
.TP
.B setup
-Get the current value of sleep interval, mask of banned CPUs and and list of banned IRQs.
+Get the current value of sleep interval, mask of banned CPUs and list of banned IRQs.
.TP
.B settings sleep <s>
Set new value of sleep interval, <s> >= 1.
diff --git a/irqbalance.c b/irqbalance.c
index 6412447..7713cd0 100644
--- a/irqbalance.c
+++ b/irqbalance.c
@@ -84,7 +84,6 @@ struct option lopts[] = {
{"oneshot", 0, NULL, 'o'},
{"debug", 0, NULL, 'd'},
{"foreground", 0, NULL, 'f'},
- {"hintpolicy", 1, NULL, 'h'},
{"powerthresh", 1, NULL, 'p'},
{"banirq", 1 , NULL, 'i'},
{"banscript", 1, NULL, 'b'},
@@ -100,7 +99,7 @@ struct option lopts[] = {
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]\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");
}
--
2.20.1

View File

@ -1,31 +0,0 @@
From acb0c2057952fa8bb502bf6b4222b327efe44c4c Mon Sep 17 00:00:00 2001
From: Kairui Song <kasong@redhat.com>
Date: Mon, 26 Oct 2020 17:26:52 +0800
Subject: [PATCH] Add some examples for IRQBALANCE_BANNED_CPUS
Signed-off-by: Kairui Song <kasong@redhat.com>
---
irqbalance.1 | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/irqbalance.1 b/irqbalance.1
index d272b6f..330c12b 100644
--- a/irqbalance.1
+++ b/irqbalance.1
@@ -157,6 +157,13 @@ Same as --debug.
Provides a mask of CPUs which irqbalance should ignore and never assign interrupts to.
If not specified, irqbalance use mask of isolated and adaptive-ticks CPUs on the
system as the default value.
+This is a hexmask without the leading 0x. On systems with large numbers of
+processors, each group of eight hex digits is separated by a comma ,. i.e.
+export IRQBALANCE_BANNED_CPUS=fc0 would prevent irqbalance from assigning irqs
+to the 7th-12th cpus (cpu6-cpu11) or export IRQBALANCE_BANNED_CPUS=ff000000,00000001
+would prevent irqbalance from assigning irqs to the 1st (cpu0) and 57th-64th cpus
+(cpu56-cpu63).
+
.SH "SIGNALS"
.TP
--
2.28.0

View File

@ -1,30 +0,0 @@
From a1f83a563475bd77843c4b44ee44a7d764bc9bba Mon Sep 17 00:00:00 2001
From: Kairui Song <kasong@redhat.com>
Date: Thu, 28 Jan 2021 15:24:32 +0800
Subject: [PATCH] Also fetch node info for non-PCI devices
non-PCI devices could also be bind to a certain node. So if failed to
fetch the info from sysfs, try to get it from /proc/irq/<irq>/node.
---
classify.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/classify.c b/classify.c
index df8a89b..92f43cc 100644
--- a/classify.c
+++ b/classify.c
@@ -395,7 +395,10 @@ static struct irq_info *add_one_irq_to_db(const char *devpath, int irq, struct u
get_numa_node:
numa_node = -1;
if (numa_avail) {
- sprintf(path, "%s/numa_node", devpath);
+ if (devpath)
+ sprintf(path, "%s/numa_node", devpath);
+ else
+ sprintf(path, "/proc/irq/%i/node", irq);
fd = fopen(path, "r");
if (fd) {
fscanf(fd, "%d", &numa_node);
--
2.29.2

View File

@ -0,0 +1,13 @@
diff --git a/misc/irqbalance.service b/misc/irqbalance.service
index 0f79c3e..18c7e9b 100644
--- a/misc/irqbalance.service
+++ b/misc/irqbalance.service
@@ -7,7 +7,7 @@ ConditionCPUs=>1
[Service]
EnvironmentFile=-/usr/lib/irqbalance/defaults.env
-EnvironmentFile=-/path/to/irqbalance.env
+EnvironmentFile=-/etc/sysconfig/irqbalance
ExecStart=/usr/sbin/irqbalance --foreground $IRQBALANCE_ARGS
ReadOnlyPaths=/
ReadWritePaths=/proc/irq

View File

@ -1,6 +1,6 @@
Name: irqbalance
Version: 1.4.0
Release: 6%{?dist}
Version: 1.9.0
Release: 3%{?dist}
Epoch: 2
Summary: IRQ balancing daemon
@ -23,16 +23,22 @@ Requires: numactl-libs
ExcludeArch: s390 s390x
Patch1: irqbalance-1.0.4-env-file-path.patch
Patch2: irqbalance-1.4.0-Fix-several-memleak-problems-found-by-covscan.patch
Patch3: irqbalance-1.4.0-Fix-an-possible-overflow-error.patch
Patch4: irqbalance-1.5.0-Don-t-leak-socket-fd-on-connection-error.patch
Patch5: irqbalance-1.4.0-procinterrupts-check-xen-dyn-event-more-flexible.patch
Patch6: irqbalance-1.5.0-Update-document-and-remove-dead-options.patch
Patch7: irqbalance-1.4.0-Fix-ambiguous-parsing-of-node-entries-in-sys.patch
Patch8: irqbalance-1.5.0-Refine-document-about-IRQBALANCE_BANNED_CPUS.patch
Patch9: irqbalance-1.7.0-Add-some-examples-for-IRQBALANCE_BANNED_CPUS.patch
Patch10: irqbalance-1.7.0-Also-fetch-node-info-for-non-PCI-devices.patch
Patch1: irqbalance-1.8.0-env-file-path.patch
Patch2: 0001-get-irq-module-relationship-from-sys-bus-pci-driver.patch
Patch3: 0002-check-whether-savedptr-is-NULL-before-invoking-strle.patch
Patch4: 0003-add-meson.patch
Patch5: 0004-Prepare-to-handle-thermal-event.patch
Patch6: 0005-Implement-Netlink-helper-functions-to-subscribe-ther.patch
Patch7: 0006-Handle-thermal-events-to-mask-CPUs.patch
Patch8: 0007-add-keep_going-check-to-prevent-irqbalance-from-fail.patch
Patch9: 0008-parse_proc_interrupts-fix-parsing-interrupt-counts.patch
Patch10: 0009-irqbalance-ui-move-ASSIGNED-TO-CPUS-to-the-last-colu.patch
Patch11: 0010-irqbalance-ui-can-t-change-window-when-in-editing-st.patch
Patch12: 0011-fix-memory-leak-in-ui-ui.c.patch
Patch13: 0012-irqbalance-ui-support-scroll-under-tui-mode-of-irqba.patch
Patch14: 0013-irqbalance-ui-print-cpulist-in-SETUP-IRQS.patch
Patch15: 0014-Improve-documentation-and-logging-for-banned-cpus.patch
Patch16: 0001-irqbalance-ui-skip-in-parse_setup-to-avoid-coredump.patch
%description
irqbalance is a daemon that evenly distributes IRQ load across
@ -50,6 +56,12 @@ multiple CPUs for enhanced performance.
%patch8 -p1
%patch9 -p1
%patch10 -p1
%patch11 -p1
%patch12 -p1
%patch13 -p1
%patch14 -p1
%patch15 -p1
%patch16 -p1
%build
./autogen.sh
@ -58,6 +70,7 @@ CFLAGS="%{optflags}" make %{?_smp_mflags}
%install
install -D -p -m 0755 %{name} %{buildroot}%{_sbindir}/%{name}
install -D -p -m 0755 %{name}-ui %{buildroot}%{_sbindir}/%{name}-ui
install -D -p -m 0644 ./misc/irqbalance.service %{buildroot}/%{_unitdir}/irqbalance.service
install -D -p -m 0644 %{SOURCE1} %{buildroot}%{_sysconfdir}/sysconfig/%{name}
@ -70,6 +83,7 @@ make check
%files
%doc COPYING AUTHORS
%{_sbindir}/irqbalance
%{_sbindir}/irqbalance-ui
%{_unitdir}/irqbalance.service
%{_mandir}/man1/*
%config(noreplace) %{_sysconfdir}/sysconfig/irqbalance
@ -90,6 +104,15 @@ fi
/sbin/chkconfig --del irqbalance >/dev/null 2>&1 || :
%changelog
* Tue Jul 19 2022 Tao Liu <ltao@redhat.com> - 2:1.9.0-3
- Rebase to latest upstream commit (c8d1fff0f1)
* Thu Jul 14 2022 Tao Liu <ltao@redhat.com> - 2:1.9.0-2
- Rebase to latest upstream commit (167580790c)
* Fri Jul 1 2022 Tao Liu <ltao@redhat.com> - 2:1.9.0-1
- Rebase to latest upstream release v1.9.0. Resolves:rhbz2098629
* Fri Jan 29 2021 Kairui Song <kasong@redhat.com> 2:1.4.0-6
- Also fetch node info for non-PCI devices