diff --git a/.gitignore b/.gitignore index 9ee7832..f44e3d1 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/irqbalance-1.4.0.tar.gz +SOURCES/irqbalance-1.9.0.tar.gz diff --git a/.irqbalance.metadata b/.irqbalance.metadata index 678d9c9..96f9609 100644 --- a/.irqbalance.metadata +++ b/.irqbalance.metadata @@ -1 +1 @@ -4eb861313d6b93b3be5d5933a7f45ee7b51c7ddb SOURCES/irqbalance-1.4.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.0.4-env-file-path.patch b/SOURCES/irqbalance-1.0.4-env-file-path.patch deleted file mode 100644 index 450d755..0000000 --- a/SOURCES/irqbalance-1.0.4-env-file-path.patch +++ /dev/null @@ -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] diff --git a/SOURCES/irqbalance-1.4.0-Fix-ambiguous-parsing-of-node-entries-in-sys.patch b/SOURCES/irqbalance-1.4.0-Fix-ambiguous-parsing-of-node-entries-in-sys.patch deleted file mode 100644 index 596825f..0000000 --- a/SOURCES/irqbalance-1.4.0-Fix-ambiguous-parsing-of-node-entries-in-sys.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 721460664afad79e2d96bbcb173eda68eed9743b Mon Sep 17 00:00:00 2001 -From: Gerd Rausch -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 ---- - 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 - #include - #include -+#include - #include - #include - -@@ -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 - diff --git a/SOURCES/irqbalance-1.4.0-Fix-an-possible-overflow-error.patch b/SOURCES/irqbalance-1.4.0-Fix-an-possible-overflow-error.patch deleted file mode 100644 index 26816e6..0000000 --- a/SOURCES/irqbalance-1.4.0-Fix-an-possible-overflow-error.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 16cb6df56960f58df61ec35ef3be45286eb3c788 Mon Sep 17 00:00:00 2001 -From: Kairui Song -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 - diff --git a/SOURCES/irqbalance-1.4.0-Fix-several-memleak-problems-found-by-covscan.patch b/SOURCES/irqbalance-1.4.0-Fix-several-memleak-problems-found-by-covscan.patch deleted file mode 100644 index bd0a844..0000000 --- a/SOURCES/irqbalance-1.4.0-Fix-several-memleak-problems-found-by-covscan.patch +++ /dev/null @@ -1,253 +0,0 @@ -From 9ed5c269bd59c95f41829aedf0520930c97b08d3 Mon Sep 17 00:00:00 2001 -From: Kairui Song -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 - diff --git a/SOURCES/irqbalance-1.4.0-procinterrupts-check-xen-dyn-event-more-flexible.patch b/SOURCES/irqbalance-1.4.0-procinterrupts-check-xen-dyn-event-more-flexible.patch deleted file mode 100644 index 23bb4dd..0000000 --- a/SOURCES/irqbalance-1.4.0-procinterrupts-check-xen-dyn-event-more-flexible.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 3eae2edd136540898f8e51546eedfb56729f938d Mon Sep 17 00:00:00 2001 -From: Xiao Liang -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 ---- - 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 - diff --git a/SOURCES/irqbalance-1.5.0-Don-t-leak-socket-fd-on-connection-error.patch b/SOURCES/irqbalance-1.5.0-Don-t-leak-socket-fd-on-connection-error.patch deleted file mode 100644 index 225d47c..0000000 --- a/SOURCES/irqbalance-1.5.0-Don-t-leak-socket-fd-on-connection-error.patch +++ /dev/null @@ -1,65 +0,0 @@ -From ce71f0cc2255aba072eabb2af26f6cb0e31f8189 Mon Sep 17 00:00:00 2001 -From: Kairui Song -Date: Tue, 6 Nov 2018 10:37:15 +0800 -Subject: Don't leak socket fd on connection error - -Signed-off-by: Kairui Song ---- - 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 - diff --git a/SOURCES/irqbalance-1.5.0-Refine-document-about-IRQBALANCE_BANNED_CPUS.patch b/SOURCES/irqbalance-1.5.0-Refine-document-about-IRQBALANCE_BANNED_CPUS.patch deleted file mode 100644 index 6554804..0000000 --- a/SOURCES/irqbalance-1.5.0-Refine-document-about-IRQBALANCE_BANNED_CPUS.patch +++ /dev/null @@ -1,31 +0,0 @@ -From a1abba7b070587cc5fa69597081dcc80f4addef3 Mon Sep 17 00:00:00 2001 -From: Kairui Song -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 ---- - 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 - diff --git a/SOURCES/irqbalance-1.5.0-Update-document-and-remove-dead-options.patch b/SOURCES/irqbalance-1.5.0-Update-document-and-remove-dead-options.patch deleted file mode 100644 index 80b93ea..0000000 --- a/SOURCES/irqbalance-1.5.0-Update-document-and-remove-dead-options.patch +++ /dev/null @@ -1,109 +0,0 @@ -From 5f8ed87f36381569725c67445f12226f41861d1f Mon Sep 17 00:00:00 2001 -From: Kairui Song -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 -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 - -commit 0b95593b19ff13e7e271d5b0b8219e7c70bf773c -Author: Kairui Song -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 - -commit 3ae01f5bd5ef3ed3080c9b06fc63bb02cc03bf1a -Author: Kairui Song -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 - -Signed-off-by: Kairui Song ---- - 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= - 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= -+.B -m, --banmod= -+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= - 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 - Set new value of sleep interval, >= 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 | ] [--banirq= | -i ] [--banmod= | -m ] [--policyscript= | -l