From 7bf5dbae3e35435a1c3573a1f2bc643b084a9ada Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Sep 27 2022 14:45:48 +0000 Subject: import irqbalance-1.9.0-3.el9 --- diff --git a/.gitignore b/.gitignore index c64a80f..f44e3d1 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/irqbalance-1.8.0.tar.gz +SOURCES/irqbalance-1.9.0.tar.gz diff --git a/.irqbalance.metadata b/.irqbalance.metadata index cec434a..96f9609 100644 --- a/.irqbalance.metadata +++ b/.irqbalance.metadata @@ -1 +1 @@ -b4446192904bafcaf32dd8d389d2b7502fa9fd09 SOURCES/irqbalance-1.8.0.tar.gz +828952ed5fa3b502c4b07703395cdf33faa6a60a SOURCES/irqbalance-1.9.0.tar.gz diff --git a/SOURCES/0001-get-irq-module-relationship-from-sys-bus-pci-driver.patch b/SOURCES/0001-get-irq-module-relationship-from-sys-bus-pci-driver.patch new file mode 100644 index 0000000..1961ea8 --- /dev/null +++ b/SOURCES/0001-get-irq-module-relationship-from-sys-bus-pci-driver.patch @@ -0,0 +1,71 @@ +From ff48ac9c84f0b318dfce665605d72e86dfcfe008 Mon Sep 17 00:00:00 2001 +From: Chao Liu +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 +--- + 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 + #include + #include ++#include + + #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 + diff --git a/SOURCES/0001-irqbalance-ui-skip-in-parse_setup-to-avoid-coredump.patch b/SOURCES/0001-irqbalance-ui-skip-in-parse_setup-to-avoid-coredump.patch new file mode 100644 index 0000000..3ed91e4 --- /dev/null +++ b/SOURCES/0001-irqbalance-ui-skip-in-parse_setup-to-avoid-coredump.patch @@ -0,0 +1,64 @@ +From c8d1fff0f16ad906cca153a22faac11516ccc0dd Mon Sep 17 00:00:00 2001 +From: Liu Chao +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 +--- + 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 + diff --git a/SOURCES/0002-check-whether-savedptr-is-NULL-before-invoking-strle.patch b/SOURCES/0002-check-whether-savedptr-is-NULL-before-invoking-strle.patch new file mode 100644 index 0000000..feca09a --- /dev/null +++ b/SOURCES/0002-check-whether-savedptr-is-NULL-before-invoking-strle.patch @@ -0,0 +1,28 @@ +From 522883505d3b02e3294f045f49007b61c00e2c31 Mon Sep 17 00:00:00 2001 +From: Chao Liu +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 +--- + 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 + diff --git a/SOURCES/0003-add-meson.patch b/SOURCES/0003-add-meson.patch new file mode 100644 index 0000000..2faf2fa --- /dev/null +++ b/SOURCES/0003-add-meson.patch @@ -0,0 +1,96 @@ +From 378d4707c26acf05e551219d8b09ddf440bdba2a Mon Sep 17 00:00:00 2001 +From: Rosen Penev +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 +--- + 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 + diff --git a/SOURCES/0004-Prepare-to-handle-thermal-event.patch b/SOURCES/0004-Prepare-to-handle-thermal-event.patch new file mode 100644 index 0000000..2939930 --- /dev/null +++ b/SOURCES/0004-Prepare-to-handle-thermal-event.patch @@ -0,0 +1,259 @@ +From b66647ab757c580b2532c117bd345d1bad3b2bd5 Mon Sep 17 00:00:00 2001 +From: "Chang S. Bae" +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 +--- + 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 + + #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 + #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 ++ ++#include ++#include ++#include ++ ++#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 ++ ++#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 + diff --git a/SOURCES/0005-Implement-Netlink-helper-functions-to-subscribe-ther.patch b/SOURCES/0005-Implement-Netlink-helper-functions-to-subscribe-ther.patch new file mode 100644 index 0000000..60c0de7 --- /dev/null +++ b/SOURCES/0005-Implement-Netlink-helper-functions-to-subscribe-ther.patch @@ -0,0 +1,392 @@ +From c65cda183609116760c54f1c2ad458eef9f44d56 Mon Sep 17 00:00:00 2001 +From: "Chang S. Bae" +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 +--- + 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 + diff --git a/SOURCES/0006-Handle-thermal-events-to-mask-CPUs.patch b/SOURCES/0006-Handle-thermal-events-to-mask-CPUs.patch new file mode 100644 index 0000000..13ec85b --- /dev/null +++ b/SOURCES/0006-Handle-thermal-events-to-mask-CPUs.patch @@ -0,0 +1,242 @@ +From 560291389e33db108d2fb6d954ef059f953c6e33 Mon Sep 17 00:00:00 2001 +From: "Chang S. Bae" +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 +--- + 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 + ++#include + #include + #include + #include +@@ -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 + diff --git a/SOURCES/0007-add-keep_going-check-to-prevent-irqbalance-from-fail.patch b/SOURCES/0007-add-keep_going-check-to-prevent-irqbalance-from-fail.patch new file mode 100644 index 0000000..c6f2995 --- /dev/null +++ b/SOURCES/0007-add-keep_going-check-to-prevent-irqbalance-from-fail.patch @@ -0,0 +1,27 @@ +From 028082a6a1ff650d5cdf796ac55ac26a3874372a Mon Sep 17 00:00:00 2001 +From: Liu Chao +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 +--- + 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 + diff --git a/SOURCES/0008-parse_proc_interrupts-fix-parsing-interrupt-counts.patch b/SOURCES/0008-parse_proc_interrupts-fix-parsing-interrupt-counts.patch new file mode 100644 index 0000000..3ce7467 --- /dev/null +++ b/SOURCES/0008-parse_proc_interrupts-fix-parsing-interrupt-counts.patch @@ -0,0 +1,26 @@ +From 0a82dddbaf5702caded0d0d83a6eafaca743254d Mon Sep 17 00:00:00 2001 +From: Andreas Schwab +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 + diff --git a/SOURCES/0009-irqbalance-ui-move-ASSIGNED-TO-CPUS-to-the-last-colu.patch b/SOURCES/0009-irqbalance-ui-move-ASSIGNED-TO-CPUS-to-the-last-colu.patch new file mode 100644 index 0000000..2c41cda --- /dev/null +++ b/SOURCES/0009-irqbalance-ui-move-ASSIGNED-TO-CPUS-to-the-last-colu.patch @@ -0,0 +1,50 @@ +From 7f1caca47aee32084c319db07d9a236684b818a3 Mon Sep 17 00:00:00 2001 +From: Liu Chao +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 +--- + 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 + diff --git a/SOURCES/0010-irqbalance-ui-can-t-change-window-when-in-editing-st.patch b/SOURCES/0010-irqbalance-ui-can-t-change-window-when-in-editing-st.patch new file mode 100644 index 0000000..d3bb969 --- /dev/null +++ b/SOURCES/0010-irqbalance-ui-can-t-change-window-when-in-editing-st.patch @@ -0,0 +1,347 @@ +From b65faa2b658e3cf4edf6d39e4bb1e103a47ac0de Mon Sep 17 00:00:00 2001 +From: Liu Chao +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=) 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=, argv=) at ui/irqbalance-ui.c:445 + +Signed-off-by: Liu Chao +--- + 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 for changing sleep setup, 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 for changing sleep setup, 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 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 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 for changing sleep setup, 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 for changing sleep setup, 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 for changing sleep setup, 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 + diff --git a/SOURCES/0011-fix-memory-leak-in-ui-ui.c.patch b/SOURCES/0011-fix-memory-leak-in-ui-ui.c.patch new file mode 100644 index 0000000..908aaf5 --- /dev/null +++ b/SOURCES/0011-fix-memory-leak-in-ui-ui.c.patch @@ -0,0 +1,47 @@ +From a61b382805961934c6425f19a762a6ab99884c24 Mon Sep 17 00:00:00 2001 +From: Liu Chao +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 +--- + 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 + diff --git a/SOURCES/0012-irqbalance-ui-support-scroll-under-tui-mode-of-irqba.patch b/SOURCES/0012-irqbalance-ui-support-scroll-under-tui-mode-of-irqba.patch new file mode 100644 index 0000000..65d1578 --- /dev/null +++ b/SOURCES/0012-irqbalance-ui-support-scroll-under-tui-mode-of-irqba.patch @@ -0,0 +1,583 @@ +From db7dc03388a20ba2d873a81c3e14b933e2b09551 Mon Sep 17 00:00:00 2001 +From: Liu Chao +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 +--- + 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 + #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 + diff --git a/SOURCES/0013-irqbalance-ui-print-cpulist-in-SETUP-IRQS.patch b/SOURCES/0013-irqbalance-ui-print-cpulist-in-SETUP-IRQS.patch new file mode 100644 index 0000000..a625222 --- /dev/null +++ b/SOURCES/0013-irqbalance-ui-print-cpulist-in-SETUP-IRQS.patch @@ -0,0 +1,66 @@ +From 577796abe7337c8df446c082688816ec22804876 Mon Sep 17 00:00:00 2001 +From: Liu Chao +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 +--- + 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 + diff --git a/SOURCES/0014-Improve-documentation-and-logging-for-banned-cpus.patch b/SOURCES/0014-Improve-documentation-and-logging-for-banned-cpus.patch new file mode 100644 index 0000000..ac690d9 --- /dev/null +++ b/SOURCES/0014-Improve-documentation-and-logging-for-banned-cpus.patch @@ -0,0 +1,72 @@ +From cfb15f0bb95ebfd4357708eae42febe9f2121fba Mon Sep 17 00:00:00 2001 +From: Tao Liu +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 +--- + 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 + diff --git a/SOURCES/irqbalance-1.8.0-Disable-the-communication-socket-when-UI-is-disabled.patch b/SOURCES/irqbalance-1.8.0-Disable-the-communication-socket-when-UI-is-disabled.patch deleted file mode 100644 index 07d2545..0000000 --- a/SOURCES/irqbalance-1.8.0-Disable-the-communication-socket-when-UI-is-disabled.patch +++ /dev/null @@ -1,159 +0,0 @@ -From 4342acd8d7862e862e0b661135b10671ffeac119 Mon Sep 17 00:00:00 2001 -From: Kairui Song -Date: Thu, 22 Jul 2021 03:05:59 +0800 -Subject: [PATCH] Disable the communication socket when UI is disabled - -The communication socket is added to support the UI, when UI is not -built, also disable the socket. - -Signed-off-by: Kairui Song ---- - configure.ac | 11 +++++++---- - cputree.c | 4 ++++ - irqbalance.c | 23 ++++++++++++++++------- - 3 files changed, 27 insertions(+), 11 deletions(-) - -diff --git a/configure.ac b/configure.ac -index 92a5113..c45b9ce 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -41,10 +41,13 @@ AC_C_INLINE - AM_PROG_CC_C_O - - AC_ARG_WITH([irqbalance-ui], -- [AC_HELP_STRING([--without-irqbalance-ui], -- [Dont build the irqbalance ui component])], -- [with_irqbalanceui=$withval], [with_irqbalanceui=yes]) -- -+ [AS_HELP_STRING([--without-irqbalance-ui], -+ [Dont build the irqbalance ui component])], -+ [with_irqbalanceui=$withval], [with_irqbalanceui=yes]) -+AS_IF( -+ [test "x$with_irqbalanceui" = "xyes"], [ -+ AC_DEFINE([HAVE_IRQBALANCEUI], 1, [Build irqbalance ui component.]) -+]) - AM_CONDITIONAL([IRQBALANCEUI], [test x$with_irqbalanceui = xyes]) - - AC_ARG_WITH([systemd], -diff --git a/cputree.c b/cputree.c -index e4695f2..b716a8f 100644 ---- a/cputree.c -+++ b/cputree.c -@@ -39,7 +39,9 @@ - - #include "irqbalance.h" - -+#ifdef HAVE_IRQBALANCEUI - extern char *banned_cpumask_from_ui; -+#endif - extern char *cpu_ban_string; - - GList *cpus; -@@ -113,12 +115,14 @@ static void setup_banned_cpus(void) - cpumask_t isolated_cpus; - char *env = NULL; - -+#ifdef HAVE_IRQBALANCEUI - /* 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; - } -+#endif - - /* - * Notes: -diff --git a/irqbalance.c b/irqbalance.c -index 3f94847..07a245f 100644 ---- a/irqbalance.c -+++ b/irqbalance.c -@@ -31,22 +31,21 @@ - #include - #include - #include --#include --#include - #include - #include - #ifdef HAVE_GETOPT_LONG - #include - #endif -- - #ifdef HAVE_LIBCAP_NG - #include - #endif -+#ifdef HAVE_IRQBALANCEUI -+#include -+#include -+#endif - #include "irqbalance.h" - - volatile int keep_going = 1; --int socket_fd; --char socket_name[64]; - int one_shot_mode; - int debug_mode; - int foreground_mode; -@@ -67,9 +66,14 @@ int last_interval; - GMainLoop *main_loop; - - char *cpu_ban_string = NULL; --char *banned_cpumask_from_ui = NULL; - unsigned long migrate_ratio = 0; - -+#ifdef HAVE_IRQBALANCEUI -+int socket_fd; -+char socket_name[64]; -+char *banned_cpumask_from_ui = NULL; -+#endif -+ - static void sleep_approx(int seconds) - { - struct timespec ts; -@@ -405,6 +409,7 @@ void get_object_stat(struct topo_obj *object, void *data) - } - } - -+#ifdef HAVE_IRQBALANCEUI - gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attribute__((unused))) - { - char buff[500]; -@@ -585,6 +590,7 @@ int init_socket() - g_unix_fd_add(socket_fd, G_IO_IN, sock_handle, NULL); - return 0; - } -+#endif - - int main(int argc, char** argv) - { -@@ -688,10 +694,12 @@ int main(int argc, char** argv) - parse_proc_interrupts(); - parse_proc_stat(); - -+#ifdef HAVE_IRQBALANCEUI - if (init_socket()) { - ret = EXIT_FAILURE; - goto out; - } -+#endif - main_loop = g_main_loop_new(NULL, FALSE); - last_interval = sleep_interval; - g_timeout_add_seconds(sleep_interval, scan, NULL); -@@ -707,11 +715,12 @@ out: - /* Remove pidfile */ - if (!foreground_mode && pidfile) - unlink(pidfile); -+#ifdef HAVE_IRQBALANCEUI - /* Remove socket */ - if (socket_fd > 0) - close(socket_fd); - if (socket_name[0]) - unlink(socket_name); -- -+#endif - return ret; - } --- -2.31.1 - diff --git a/SOURCES/irqbalance-1.8.0-Drop-CapabilityBoundingSet-from-irqbalance-service.patch b/SOURCES/irqbalance-1.8.0-Drop-CapabilityBoundingSet-from-irqbalance-service.patch deleted file mode 100644 index c855f8a..0000000 --- a/SOURCES/irqbalance-1.8.0-Drop-CapabilityBoundingSet-from-irqbalance-service.patch +++ /dev/null @@ -1,32 +0,0 @@ -From efab2725ea5165732c5e98c0e083a4eec6e355e3 Mon Sep 17 00:00:00 2001 -From: Kairui Song -Date: Fri, 24 Sep 2021 17:43:30 +0800 -Subject: [PATCH] Drop CapabilityBoundingSet from irqbalance service - -libcapng is issuing an error in the system log when irqbalance attempts -to drop capabilities, but systemd service unit has already done dropped -all capabilities. commit 43751df tried to fix this but it didn't fix it -completely. CapabilityBoundingSet also need to be dropped. - -Fixes #182 - -Signed-off-by: Kairui Song ---- - misc/irqbalance.service | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/misc/irqbalance.service b/misc/irqbalance.service -index 014798c..fcc29c2 100644 ---- a/misc/irqbalance.service -+++ b/misc/irqbalance.service -@@ -8,7 +8,6 @@ ConditionVirtualization=!container - EnvironmentFile=-/usr/lib/irqbalance/defaults.env - EnvironmentFile=-/path/to/irqbalance.env - ExecStart=/usr/sbin/irqbalance --foreground $IRQBALANCE_ARGS --CapabilityBoundingSet= - ReadOnlyPaths=/ - ReadWritePaths=/proc/irq - RestrictAddressFamilies=AF_UNIX --- -2.31.1 - diff --git a/SOURCES/irqbalance-1.8.0-drop-NoNewPrivs-from-irqbalance-service.patch b/SOURCES/irqbalance-1.8.0-drop-NoNewPrivs-from-irqbalance-service.patch deleted file mode 100644 index 63cc6f4..0000000 --- a/SOURCES/irqbalance-1.8.0-drop-NoNewPrivs-from-irqbalance-service.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 43751dfc7f29fbf2c46ffcd4fdb6d3f6db291927 Mon Sep 17 00:00:00 2001 -From: Neil Horman -Date: Wed, 12 May 2021 09:26:10 -0400 -Subject: [PATCH] drop NoNewPrivs from irqbalance service - -A recent update to libcapng is issuing an error in the system log, -caused by the fact that irqbalance attempts to drop capabilities when -the systemd service unit has already done so for us. Since irqbalance -drops the caps correctly, theres really no need for us to do so via -systemd as well. So lets drop NoNewCaps in the service unit. - -Signed-off-by: Neil Horman ---- - misc/irqbalance.service | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/misc/irqbalance.service b/misc/irqbalance.service -index e7a3336..014798c 100644 ---- a/misc/irqbalance.service -+++ b/misc/irqbalance.service -@@ -9,7 +9,6 @@ EnvironmentFile=-/usr/lib/irqbalance/defaults.env - EnvironmentFile=-/path/to/irqbalance.env - ExecStart=/usr/sbin/irqbalance --foreground $IRQBALANCE_ARGS - CapabilityBoundingSet= --NoNewPrivileges=yes - ReadOnlyPaths=/ - ReadWritePaths=/proc/irq - RestrictAddressFamilies=AF_UNIX --- -2.31.1 - diff --git a/SOURCES/irqbalance-1.8.0-env-file-path.patch b/SOURCES/irqbalance-1.8.0-env-file-path.patch new file mode 100644 index 0000000..1c9e326 --- /dev/null +++ b/SOURCES/irqbalance-1.8.0-env-file-path.patch @@ -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 diff --git a/SPECS/irqbalance.spec b/SPECS/irqbalance.spec index 1a719e2..3b6a469 100644 --- a/SPECS/irqbalance.spec +++ b/SPECS/irqbalance.spec @@ -1,6 +1,6 @@ Name: irqbalance -Version: 1.8.0 -Release: 4%{?dist} +Version: 1.9.0 +Release: 3%{?dist} Epoch: 2 Summary: IRQ balancing daemon @@ -23,9 +23,22 @@ Requires: numactl-libs ExcludeArch: s390 s390x -Patch1: irqbalance-1.8.0-drop-NoNewPrivs-from-irqbalance-service.patch -Patch2: irqbalance-1.8.0-Disable-the-communication-socket-when-UI-is-disabled.patch -Patch3: irqbalance-1.8.0-Drop-CapabilityBoundingSet-from-irqbalance-service.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 @@ -36,14 +49,28 @@ multiple CPUs for enhanced performance. %patch1 -p1 %patch2 -p1 %patch3 -p1 +%patch4 -p1 +%patch5 -p1 +%patch6 -p1 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 +%patch12 -p1 +%patch13 -p1 +%patch14 -p1 +%patch15 -p1 +%patch16 -p1 %build ./autogen.sh -%configure --without-irqbalance-ui +%configure 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} @@ -56,6 +83,7 @@ make check %files %doc COPYING AUTHORS %{_sbindir}/irqbalance +%{_sbindir}/irqbalance-ui %{_unitdir}/irqbalance.service %{_mandir}/man1/* %config(noreplace) %{_sysconfdir}/sysconfig/irqbalance @@ -76,6 +104,20 @@ fi /sbin/chkconfig --del irqbalance >/dev/null 2>&1 || : %changelog +* Tue Jul 19 2022 Tao Liu - 2:1.9.0-3 +- Rebase to latest upstream commit (c8d1fff0f1) + +* Thu Jul 14 2022 Tao Liu - 2:1.9.0-2 +- Rebase to latest upstream commit (167580790c) + +* Mon Jun 20 2022 Tao Liu - 2:1.9.0-1 +- Rebase to latest upstream release v1.9.0. Resolves:rhbz2097871 + +* Fri Apr 8 2022 Tao Liu - 2:1.8.0-5 +- Document migrateval. Resolves: rhbz2071959 +- Confine irqbalance to systems where it is useful. Resolves: rhbz2063930 +- Wrong EnvironmentFile in irqbalance.service. Resolves: rhbz2058509 + * Mon Sep 27 2021 Kairui Song - 2:1.8.0-4 - Drop CapabilityBoundingSet from irqbalance service. Resolves: rhbz1963152