From 6e2f297d49fd12d61915320564425a71776ec43d Mon Sep 17 00:00:00 2001 From: Tao Liu <ltao@redhat.com> Date: Thu, 7 Nov 2024 10:03:21 +1300 Subject: [PATCH] Rebase to upstream commit (b4b6f194da) Resolves: RHEL-58318 Signed-off-by: Tao Liu <ltao@redhat.com> --- ...eck-if-using-a-negative-index-of-buf.patch | 5 +- 0002-Check-fflush-return-value.patch | 4 +- 0003-fix-32-bit-formats.patch | 69 ++++ 0004-add-void-to-fix-strict-prototypes.patch | 320 ++++++++++++++++++ 0005-cast-void-pointer-to-actual-type.patch | 28 ++ ...-move-build-files-to-repository-root.patch | 113 +++++++ ...-meson-bump-project-version-to-1.9.4.patch | 29 ++ ...n-drop-redundant-install_man-options.patch | 50 +++ ...eson-add-a-minimum-version-decorator.patch | 37 ++ ...h => 0010-Drop-ProtectKernelTunables.patch | 4 +- ...son-replace-generic-array-with-files.patch | 44 +++ 0012-meson-use-find_library-for-numa.patch | 26 ++ 0013-ui-change-void-to-char.patch | 104 ++++++ 0014-clang-tidy-don-t-assign-in-if.patch | 71 ++++ 0015-clang-tidy-properly-use-strncmp.patch | 106 ++++++ 0016-replace-malloc-with-g_malloc0.patch | 32 ++ ...ang-tidy-don-t-use-else-after-return.patch | 151 +++++++++ ...tidy-remove-return-in-void-functions.patch | 36 ++ ...g-tidy-remove-redundant-declarations.patch | 27 ++ ...-clang-tidy-remove-duplicate-include.patch | 27 ++ 0021-CI-add-meson-CI.patch | 92 +++++ ...q-in-a-higher-level-utility-function.patch | 173 ++++++++++ ...s-count-per-CPU-to-avoid-overflowing.patch | 195 +++++++++++ ...to-curses-if-without-irqbalance-ui-i.patch | 43 +++ ...s-space-causing-with-systemd-not-be-.patch | 26 ++ 0026-direct-initialize-msghdr-members.patch | 38 +++ 0027-direct-initialize-iovec.patch | 31 ++ 0028-clang-tidy-add-missing-free.patch | 27 ++ 0029-clang-tidy-don-t-assign-in-if.patch | 43 +++ 0030-clang-tidy-remove-pointless-casts.patch | 37 ++ 0031-use-g_malloc-and-friends.patch | 314 +++++++++++++++++ 0032-remove-malloc-from-ucred.patch | 46 +++ 0033-gcc-analyzer-add-NULL-checks.patch | 42 +++ ...c-analyzer-increase-socket_name-size.patch | 30 ++ 0035-use-g_strdup_printf.patch | 66 ++++ ...d-malloc-with-create_credentials_msg.patch | 111 ++++++ 0037-conver-strncmp-to-g_str_has_prefix.patch | 268 +++++++++++++++ ...E_ARGS-as-empty-string-to-squelch-sy.patch | 23 ++ 0039-Minor-punctuation-fix.patch | 25 ++ ...option-should-return-0-rather-than-1.patch | 41 +++ ...to-CapabilityBoundingSet-in-irqbalan.patch | 46 +++ 0042-Check-info-moved-before-updating.patch | 31 ++ ...balance.1-a-b-a-b-it-s-type-its-type.patch | 38 +++ ...d-of-EIO-when-try-setting-irq-affini.patch | 39 +++ ...nce-1.9.0-environment-file-sysconfig.patch | 6 +- irqbalance.spec | 51 ++- 46 files changed, 3151 insertions(+), 14 deletions(-) create mode 100644 0003-fix-32-bit-formats.patch create mode 100644 0004-add-void-to-fix-strict-prototypes.patch create mode 100644 0005-cast-void-pointer-to-actual-type.patch create mode 100644 0006-meson-move-build-files-to-repository-root.patch create mode 100644 0007-meson-bump-project-version-to-1.9.4.patch create mode 100644 0008-meson-drop-redundant-install_man-options.patch create mode 100644 0009-meson-add-a-minimum-version-decorator.patch rename 0003-Drop-ProtectKernelTunables.patch => 0010-Drop-ProtectKernelTunables.patch (91%) create mode 100644 0011-meson-replace-generic-array-with-files.patch create mode 100644 0012-meson-use-find_library-for-numa.patch create mode 100644 0013-ui-change-void-to-char.patch create mode 100644 0014-clang-tidy-don-t-assign-in-if.patch create mode 100644 0015-clang-tidy-properly-use-strncmp.patch create mode 100644 0016-replace-malloc-with-g_malloc0.patch create mode 100644 0017-clang-tidy-don-t-use-else-after-return.patch create mode 100644 0018-clang-tidy-remove-return-in-void-functions.patch create mode 100644 0019-clang-tidy-remove-redundant-declarations.patch create mode 100644 0020-clang-tidy-remove-duplicate-include.patch create mode 100644 0021-CI-add-meson-CI.patch create mode 100644 0022-Wrap-migrate_irq-in-a-higher-level-utility-function.patch create mode 100644 0023-Track-IRQ-slots-count-per-CPU-to-avoid-overflowing.patch create mode 100644 0024-Disable-linking-to-curses-if-without-irqbalance-ui-i.patch create mode 100644 0025-Remove-extraneous-space-causing-with-systemd-not-be-.patch create mode 100644 0026-direct-initialize-msghdr-members.patch create mode 100644 0027-direct-initialize-iovec.patch create mode 100644 0028-clang-tidy-add-missing-free.patch create mode 100644 0029-clang-tidy-don-t-assign-in-if.patch create mode 100644 0030-clang-tidy-remove-pointless-casts.patch create mode 100644 0031-use-g_malloc-and-friends.patch create mode 100644 0032-remove-malloc-from-ucred.patch create mode 100644 0033-gcc-analyzer-add-NULL-checks.patch create mode 100644 0034-gcc-analyzer-increase-socket_name-size.patch create mode 100644 0035-use-g_strdup_printf.patch create mode 100644 0036-avoid-malloc-with-create_credentials_msg.patch create mode 100644 0037-conver-strncmp-to-g_str_has_prefix.patch create mode 100644 0038-define-IRQBALANCE_ARGS-as-empty-string-to-squelch-sy.patch create mode 100644 0039-Minor-punctuation-fix.patch create mode 100644 0040-Version-option-should-return-0-rather-than-1.patch create mode 100644 0041-Add-CAP_SETPCAP-to-CapabilityBoundingSet-in-irqbalan.patch create mode 100644 0042-Check-info-moved-before-updating.patch create mode 100644 0043-irqbalance.1-a-b-a-b-it-s-type-its-type.patch create mode 100644 0044-Use-EPERM-instead-of-EIO-when-try-setting-irq-affini.patch diff --git a/0001-irqbalance-ui-check-if-using-a-negative-index-of-buf.patch b/0001-irqbalance-ui-check-if-using-a-negative-index-of-buf.patch index f1125bc..d7a7cf2 100644 --- a/0001-irqbalance-ui-check-if-using-a-negative-index-of-buf.patch +++ b/0001-irqbalance-ui-check-if-using-a-negative-index-of-buf.patch @@ -1,7 +1,8 @@ From c0cd6149722ca525cf31a363dbe724689bef4d87 Mon Sep 17 00:00:00 2001 From: Tao Liu <ltao@redhat.com> Date: Wed, 13 Mar 2024 14:30:48 +0800 -Subject: [PATCH 1/3] irqbalance-ui: check if using a negative index of buffer +Subject: [PATCH 01/44] irqbalance-ui: check if using a negative index of + buffer A negative index will be used when recv() fails, which is unexpected for the data buffer. The issue was found by Static Application Security @@ -34,5 +35,5 @@ index b7f9b62..c26eff6 100644 /* msg was truncated, increase bufsz and try again */ default_bufsz += 8192; -- -2.40.1 +2.47.0 diff --git a/0002-Check-fflush-return-value.patch b/0002-Check-fflush-return-value.patch index baebfc8..1bf16b4 100644 --- a/0002-Check-fflush-return-value.patch +++ b/0002-Check-fflush-return-value.patch @@ -1,7 +1,7 @@ From 8301666f3029ff4d9089a273a45ec47671d964c1 Mon Sep 17 00:00:00 2001 From: Andrew Zaborowski <andrew.zaborowski@intel.com> Date: Fri, 29 Mar 2024 18:43:55 -0700 -Subject: [PATCH 2/3] Check fflush() return value +Subject: [PATCH 02/44] Check fflush() return value Since fprintf() may buffer output, as noted in 470a64b19062, fclose()'s error value was also being checked for the write errors. However in @@ -37,5 +37,5 @@ index e30d0f0..0c1e7a1 100644 if (ret < 0) goto error; -- -2.40.1 +2.47.0 diff --git a/0003-fix-32-bit-formats.patch b/0003-fix-32-bit-formats.patch new file mode 100644 index 0000000..b689cf6 --- /dev/null +++ b/0003-fix-32-bit-formats.patch @@ -0,0 +1,69 @@ +From 1277ea524354fa628b4189e699af8d62f8be7021 Mon Sep 17 00:00:00 2001 +From: Rosen Penev <rosenp@gmail.com> +Date: Sun, 31 Mar 2024 14:18:24 -0700 +Subject: [PATCH 03/44] fix 32-bit formats + +exposed with -Wformat when building on 32-bit systems + +Signed-off-by: Rosen Penev <rosenp@gmail.com> +--- + placement.c | 2 +- + ui/ui.c | 8 ++++---- + 2 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/placement.c b/placement.c +index 9fde8cb..dea7c23 100644 +--- a/placement.c ++++ b/placement.c +@@ -172,7 +172,7 @@ static void validate_irq(struct irq_info *info, void *data) + { + if (info->assigned_obj != data) + log(TO_CONSOLE, LOG_INFO, "object validation error: irq %d is wrong, points to %p, should be %p\n", +- info->irq, info->assigned_obj, data); ++ info->irq, (void*)info->assigned_obj, data); + } + + static void validate_object(struct topo_obj *d, void *data __attribute__((unused))) +diff --git a/ui/ui.c b/ui/ui.c +index bee6868..8354fc6 100644 +--- a/ui/ui.c ++++ b/ui/ui.c +@@ -101,7 +101,7 @@ int get_valid_sleep_input(int column_offest) + if(input == NULL) { + curs_set(0); + attrset(COLOR_PAIR(1)); +- mvprintw(2, column_offest, "%lu ", new_sleep); ++ mvprintw(2, column_offest, "%" PRIu64 " ", new_sleep); + move(LINES, COLS); + break; + } +@@ -125,7 +125,7 @@ int get_valid_sleep_input(int column_offest) + } + + attrset(COLOR_PAIR(1)); +- mvprintw(2, column_offest, "%lu ", new_sleep); ++ mvprintw(2, column_offest, "%" PRIu64 " ", new_sleep); + + return new_sleep; + } +@@ -296,7 +296,7 @@ void handle_cpu_banning() + case '\r': { + attrset(COLOR_PAIR(3)); + int banned = toggle_cpu(tmp, position + offset - 6); +- mvprintw(position, 3, "CPU %d ", position + offset - 6); ++ mvprintw(position, 3, "CPU %zu ", position + offset - 6); + if(banned) { + mvprintw(position, 19, "YES"); + } else { +@@ -770,7 +770,7 @@ void display_tree_node_irqs(irq_t *irq, void *data) + 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", ++ printw("%sIRQ %u, IRQs since last rebalance %" PRIu64 "\n", + indent, irq->vector, irq->diff); + } + max_offset++; +-- +2.47.0 + diff --git a/0004-add-void-to-fix-strict-prototypes.patch b/0004-add-void-to-fix-strict-prototypes.patch new file mode 100644 index 0000000..a3a679b --- /dev/null +++ b/0004-add-void-to-fix-strict-prototypes.patch @@ -0,0 +1,320 @@ +From b6a831d692ed7e12db7748db49b3b39516d151d2 Mon Sep 17 00:00:00 2001 +From: Rosen Penev <rosenp@gmail.com> +Date: Sun, 31 Mar 2024 14:31:22 -0700 +Subject: [PATCH 04/44] add void to fix strict-prototypes + +This becomes a hard error with C23 + +Signed-off-by: Rosen Penev <rosenp@gmail.com> +--- + irqbalance.c | 2 +- + irqbalance.h | 2 +- + procinterrupts.c | 2 +- + ui/helpers.c | 2 +- + ui/helpers.h | 2 +- + ui/irqbalance-ui.c | 6 +++--- + ui/irqbalance-ui.h | 5 ++--- + ui/ui.c | 26 +++++++++++++------------- + ui/ui.h | 28 ++++++++++++++-------------- + 9 files changed, 37 insertions(+), 38 deletions(-) + +diff --git a/irqbalance.c b/irqbalance.c +index 12302d7..373161f 100644 +--- a/irqbalance.c ++++ b/irqbalance.c +@@ -544,7 +544,7 @@ out: + return TRUE; + } + +-int init_socket() ++int init_socket(void) + { + struct sockaddr_un addr; + memset(&addr, 0, sizeof(struct sockaddr_un)); +diff --git a/irqbalance.h b/irqbalance.h +index 7b47cd1..09daa3d 100644 +--- a/irqbalance.h ++++ b/irqbalance.h +@@ -36,7 +36,7 @@ extern char *classes[]; + extern void parse_cpu_tree(void); + extern void clear_work_stats(void); + extern void parse_proc_interrupts(void); +-extern GList* collect_full_irq_list(); ++extern GList* collect_full_irq_list(void); + extern void parse_proc_stat(void); + extern void set_interrupt_count(int number, uint64_t count); + extern void set_msi_interrupt_numa(int number); +diff --git a/procinterrupts.c b/procinterrupts.c +index dfa95c6..e7ba653 100644 +--- a/procinterrupts.c ++++ b/procinterrupts.c +@@ -206,7 +206,7 @@ void init_irq_class_and_type(char *savedline, struct irq_info *info, int irq) + info->name = strdup(irq_fullname); + } + +-GList* collect_full_irq_list() ++GList* collect_full_irq_list(void) + { + GList *tmp_list = NULL; + FILE *file; +diff --git a/ui/helpers.c b/ui/helpers.c +index 0e9f76c..247f826 100644 +--- a/ui/helpers.c ++++ b/ui/helpers.c +@@ -165,7 +165,7 @@ void dump_node(cpu_node_t *node, void *data __attribute__((unused))) + } + } + +-void dump_tree() ++void dump_tree(void) + { + for_each_node(tree, dump_node, NULL); + } +diff --git a/ui/helpers.h b/ui/helpers.h +index b8d9fcc..922914b 100644 +--- a/ui/helpers.h ++++ b/ui/helpers.h +@@ -25,7 +25,7 @@ void for_each_node(GList *list, void (*fp)(cpu_node_t *node, void *data), void * + + void dump_irq(irq_t *irq, void *data __attribute__((unused))); + void dump_node(cpu_node_t *node, void *data __attribute__((unused))); +-void dump_tree(); ++void dump_tree(void); + + + #endif /* HELPERS_H */ +diff --git a/ui/irqbalance-ui.c b/ui/irqbalance-ui.c +index c26eff6..f5122ee 100644 +--- a/ui/irqbalance-ui.c ++++ b/ui/irqbalance-ui.c +@@ -28,7 +28,7 @@ setup_t setup; + GMainLoop *main_loop; + static int default_bufsz = 8192; + +-struct msghdr * create_credentials_msg() ++struct msghdr * create_credentials_msg(void) + { + struct ucred *credentials = malloc(sizeof(struct ucred)); + credentials->pid = getpid(); +@@ -51,7 +51,7 @@ struct msghdr * create_credentials_msg() + return msg; + } + +-int init_connection() ++int init_connection(void) + { + struct sockaddr_un addr; + memset(&addr, 0, sizeof(struct sockaddr_un)); +@@ -378,7 +378,7 @@ gboolean rescan_tree(gpointer data __attribute__((unused))) + free(irqbalance_data); + return TRUE; + } +-void scroll_window() { ++void scroll_window(void) { + switch(state) { + case STATE_TREE: + display_tree(); +diff --git a/ui/irqbalance-ui.h b/ui/irqbalance-ui.h +index dc24083..178be4b 100644 +--- a/ui/irqbalance-ui.h ++++ b/ui/irqbalance-ui.h +@@ -72,8 +72,8 @@ typedef struct setup { + + /* Function prototypes */ + +-struct msghdr * create_credentials_msg(); +-int init_connection(); ++struct msghdr * create_credentials_msg(void); ++int init_connection(void); + void send_settings(char *data); + char * get_data(char *string); + void parse_setup(char *setup_data); +@@ -83,7 +83,6 @@ void assign_cpu_lists(cpu_node_t *node, void *data); + void assign_cpu_mask(cpu_node_t *node, void *data); + void parse_into_tree(char *data); + gboolean rescan_tree(gpointer data); +-int main(); + + + #endif /* IRQBALANCE_UI_H */ +diff --git a/ui/ui.c b/ui/ui.c +index 8354fc6..9fa990a 100644 +--- a/ui/ui.c ++++ b/ui/ui.c +@@ -21,7 +21,7 @@ char *IRQ_CLASS_TO_STR[] = { + "10-Gigabit Ethernet", + "Virt Event"}; + +-void show_frame() ++void show_frame(void) + { + int i; + attrset(COLOR_PAIR(4)); +@@ -37,7 +37,7 @@ void show_frame() + } + } + +-void show_footer() ++void show_footer(void) + { + char footer[COLS]; + snprintf(footer, COLS - 1, +@@ -172,7 +172,7 @@ void print_cpu_line(cpu_ban_t *cpu, void *data __attribute__((unused))) + max_offset++; + } + +-void print_all_cpus() ++void print_all_cpus(void) + { + max_offset = 0; + if(all_cpus == NULL) { +@@ -193,7 +193,7 @@ void add_banned_cpu(int *banned_cpu, void *data) + snprintf(data + strlen(data), 1024 - strlen(data), "%d, ", *banned_cpu); + } + +-void display_banned_cpus() ++void display_banned_cpus(void) + { + char banned_cpus[1024] = "Banned CPU numbers: \0"; + if(g_list_length(setup.banned_cpus) > 0) { +@@ -247,7 +247,7 @@ void get_cpu(cpu_node_t *node, void *data __attribute__((unused))) + } + } + +-void handle_cpu_banning() ++void handle_cpu_banning(void) + { + GList *tmp = g_list_copy_deep(all_cpus, copy_cpu_ban, NULL); + attrset(COLOR_PAIR(5)); +@@ -504,7 +504,7 @@ void print_irq_line(irq_t *irq, void *data __attribute__((unused))) + mvprintw(line, 120, "%s", irq_name[line]); + } + +-void print_all_irqs() ++void print_all_irqs(void) + { + max_offset = 0; + attrset(COLOR_PAIR(0)); +@@ -555,13 +555,13 @@ void copy_irqs_from_nodes(cpu_node_t *node, void *data __attribute__((unused))) + } + } + +-void get_all_irqs() ++void get_all_irqs(void) + { + all_irqs = g_list_copy_deep(setup.banned_irqs, copy_irq, NULL); + for_each_node(tree, copy_irqs_from_nodes, NULL); + } + +-void handle_irq_banning() ++void handle_irq_banning(void) + { + GList *tmp = g_list_copy_deep(all_irqs, copy_irq, NULL); + attrset(COLOR_PAIR(5)); +@@ -670,7 +670,7 @@ void handle_irq_banning() + } + } + +-void handle_sleep_setting() ++void handle_sleep_setting(void) + { + char info[128] = "Current sleep interval between rebalancing: \0"; + uint8_t sleep_input_offset = strlen(info) + 3; +@@ -693,7 +693,7 @@ void handle_sleep_setting() + refresh(); + } + +-void init() ++void init(void) + { + signal(SIGINT, close_window); + initscr(); +@@ -732,7 +732,7 @@ void close_window(int sig __attribute__((unused))) + exit(EXIT_SUCCESS); + } + +-void settings() ++void settings(void) + { + clear(); + char *setup_data = get_data(SETUP); +@@ -751,7 +751,7 @@ void settings() + free(setup_data); + } + +-void setup_irqs() ++void setup_irqs(void) + { + clear(); + get_all_irqs(); +@@ -830,7 +830,7 @@ void display_tree_node(cpu_node_t *node, void *data) + } + } + +-void display_tree() ++void display_tree(void) + { + clear(); + char *setup_data = get_data(SETUP); +diff --git a/ui/ui.h b/ui/ui.h +index da5b4b9..f3485d4 100644 +--- a/ui/ui.h ++++ b/ui/ui.h +@@ -17,40 +17,40 @@ extern setup_t setup; + extern int offset; + extern int max_offset; + +-void show_frame(); +-void show_footer(); ++void show_frame(void); ++void show_footer(void); + + char * check_control_in_sleep_input(int max_len, int column_offest, int line_offset); + int get_valid_sleep_input(int column_offest); + + void get_banned_cpu(int *cpu, void *data); + void print_cpu_line(cpu_ban_t *cpu, void *data); +-void print_all_cpus(); ++void print_all_cpus(void); + void add_banned_cpu(int *banned_cpu, void *data); +-void display_banned_cpus(); ++void display_banned_cpus(void); + 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 get_cpu(cpu_node_t *node, void *data); ++void handle_sleep_setting(void); ++void handle_cpu_banning(void); + + void copy_assigned_obj(int *number, void *data); + void print_assigned_objects_string(irq_t *irq, int *line_offset); + void print_irq_line(irq_t *irq, void *data); +-void print_all_irqs(); ++void print_all_irqs(void); + int toggle_irq(GList *irq_list, int position); + void get_new_irq_ban_values(irq_t *irq, void *data); + void copy_irqs_from_nodes(cpu_node_t *node, void *data); +-void get_all_irqs(); +-void handle_irq_banning(); ++void get_all_irqs(void); ++void handle_irq_banning(void); + +-void init(); ++void init(void); + void close_window(int sig); +-void settings(); +-void setup_irqs(); ++void settings(void); ++void setup_irqs(void); + void display_tree_node_irqs(irq_t *irq, void *data); + void display_tree_node(cpu_node_t *node, void *data); +-void display_tree(); ++void display_tree(void); + + + #endif /* UI_H */ +-- +2.47.0 + diff --git a/0005-cast-void-pointer-to-actual-type.patch b/0005-cast-void-pointer-to-actual-type.patch new file mode 100644 index 0000000..6685bd8 --- /dev/null +++ b/0005-cast-void-pointer-to-actual-type.patch @@ -0,0 +1,28 @@ +From f2aebffef0ad990daca4b04eab4900d757b85364 Mon Sep 17 00:00:00 2001 +From: Rosen Penev <rosenp@gmail.com> +Date: Sun, 31 Mar 2024 15:01:38 -0700 +Subject: [PATCH 05/44] cast void pointer to actual type + +pointer arithmetic on void is a GNU extension. + +Signed-off-by: Rosen Penev <rosenp@gmail.com> +--- + ui/ui.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ui/ui.c b/ui/ui.c +index 9fa990a..a107fb9 100644 +--- a/ui/ui.c ++++ b/ui/ui.c +@@ -190,7 +190,7 @@ void print_all_cpus(void) + + void add_banned_cpu(int *banned_cpu, void *data) + { +- snprintf(data + strlen(data), 1024 - strlen(data), "%d, ", *banned_cpu); ++ snprintf((char *)data + strlen(data), 1024 - strlen(data), "%d, ", *banned_cpu); + } + + void display_banned_cpus(void) +-- +2.47.0 + diff --git a/0006-meson-move-build-files-to-repository-root.patch b/0006-meson-move-build-files-to-repository-root.patch new file mode 100644 index 0000000..7ca5e42 --- /dev/null +++ b/0006-meson-move-build-files-to-repository-root.patch @@ -0,0 +1,113 @@ +From 922ee47bbfb44a1ee7346f434092028adf4dffcd Mon Sep 17 00:00:00 2001 +From: Eli Schwartz <eschwartz93@gmail.com> +Date: Mon, 1 Apr 2024 00:15:44 -0400 +Subject: [PATCH 06/44] meson: move build files to repository root + +Per the README and github ticket discussion, the purpose of having it in +contrib/ is to gauge community interest. This interest has now been +expressed by several parties, so that interest is certainly there. + +Let's move it to a more discoverable location. This has two benefits: + +- usability. If various parties intend to use it, then it is easier to + do so from the repository root rather than cd'ing into a subdir. + +- discoverability. At least Gentoo didn't initially realize it existed, + since it wasn't in the repository root, but switched after realizing. + It seems reasonable that other redistributors, too, would be + interested in evaluating its use but hadn't previously noticed the + option. + +Addresses: https://github.com/Irqbalance/irqbalance/pull/211#issuecomment-2028891561 +Signed-off-by: Eli Schwartz <eschwartz93@gmail.com> +--- + contrib/README | 2 -- + contrib/meson.build => meson.build | 30 +++++++++---------- + .../meson_options.txt => meson_options.txt | 0 + 3 files changed, 15 insertions(+), 17 deletions(-) + delete mode 100644 contrib/README + rename contrib/meson.build => meson.build (85%) + rename contrib/meson_options.txt => meson_options.txt (100%) + +diff --git a/contrib/README b/contrib/README +deleted file mode 100644 +index 2158dac..0000000 +--- a/contrib/README ++++ /dev/null +@@ -1,2 +0,0 @@ +-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/meson.build +similarity index 85% +rename from contrib/meson.build +rename to meson.build +index 0c74702..707baed 100644 +--- a/contrib/meson.build ++++ b/meson.build +@@ -25,15 +25,15 @@ if cdata.get('HAVE_IRQBALANCEUI') + + executable( + 'irqbalance-ui', +- '../ui/helpers.c', +- '../ui/irqbalance-ui.c', +- '../ui/ui.c', ++ 'ui/helpers.c', ++ 'ui/irqbalance-ui.c', ++ 'ui/ui.c', + dependencies: [glib_dep, ncurses_dep], + install: true, + ) + + install_man( +- '../irqbalance-ui.1', ++ 'irqbalance-ui.1', + install_dir: get_option('mandir') + '/man1', + install_mode: 'rw-r--r--', + locale: 'en', +@@ -41,20 +41,20 @@ if cdata.get('HAVE_IRQBALANCEUI') + endif + + irqbalance_sources = [ +- '../activate.c', +- '../bitmap.c', +- '../classify.c', +- '../cputree.c', +- '../irqbalance.c', +- '../irqlist.c', +- '../numa.c', +- '../placement.c', +- '../procinterrupts.c', ++ 'activate.c', ++ 'bitmap.c', ++ 'classify.c', ++ 'cputree.c', ++ 'irqbalance.c', ++ 'irqlist.c', ++ 'numa.c', ++ 'placement.c', ++ 'procinterrupts.c', + ] + + if libnl_3_dep.found() and libnl_genl_3_dep.found() + irqbalance_sources += [ +- '../thermal.c', ++ 'thermal.c', + ] + endif + +@@ -66,7 +66,7 @@ executable( + ) + + install_man( +- '../irqbalance.1', ++ 'irqbalance.1', + install_dir: get_option('mandir') + '/man1', + install_mode: 'rw-r--r--', + locale: 'en', +diff --git a/contrib/meson_options.txt b/meson_options.txt +similarity index 100% +rename from contrib/meson_options.txt +rename to meson_options.txt +-- +2.47.0 + diff --git a/0007-meson-bump-project-version-to-1.9.4.patch b/0007-meson-bump-project-version-to-1.9.4.patch new file mode 100644 index 0000000..8b2d889 --- /dev/null +++ b/0007-meson-bump-project-version-to-1.9.4.patch @@ -0,0 +1,29 @@ +From 21e1ae87a832eeeb3971180aade4dfde5c259acf Mon Sep 17 00:00:00 2001 +From: Eli Schwartz <eschwartz93@gmail.com> +Date: Mon, 1 Apr 2024 00:17:52 -0400 +Subject: [PATCH 07/44] meson: bump project version to 1.9.4 + +This was not done in commit f8b8cddfb54516308cd484c883d930f97c9e12ed. + +Signed-off-by: Eli Schwartz <eschwartz93@gmail.com> +--- + meson.build | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/meson.build b/meson.build +index 707baed..9abf2d1 100644 +--- a/meson.build ++++ b/meson.build +@@ -1,4 +1,8 @@ +-project('irqbalance', 'c', version: '1.9.3', default_options: ['warning_level=1']) ++project('irqbalance', 'c', ++ version: '1.9.4', ++ default_options: ['warning_level=1'], ++) ++ + cc = meson.get_compiler('c') + + glib_dep = dependency('glib-2.0') +-- +2.47.0 + diff --git a/0008-meson-drop-redundant-install_man-options.patch b/0008-meson-drop-redundant-install_man-options.patch new file mode 100644 index 0000000..da18f8a --- /dev/null +++ b/0008-meson-drop-redundant-install_man-options.patch @@ -0,0 +1,50 @@ +From ea733f46545116acd3693a76efb6713ba75c7d79 Mon Sep 17 00:00:00 2001 +From: Eli Schwartz <eschwartz93@gmail.com> +Date: Mon, 1 Apr 2024 00:19:59 -0400 +Subject: [PATCH 08/44] meson: drop redundant install_man() options + +It is unnecessary to set the install directory for manpages, since meson +infers this from the file extension and installs *.1 manpages to mandir +in the man1 section for you. + +It is also unnecessary to tag them as "en" because that is the +default... it is likewise unnecessary to tag them with manual file +permissions since the default 644 permission is also the overridden one. + +Signed-off-by: Eli Schwartz <eschwartz93@gmail.com> +--- + meson.build | 14 ++------------ + 1 file changed, 2 insertions(+), 12 deletions(-) + +diff --git a/meson.build b/meson.build +index 9abf2d1..2cd0a9e 100644 +--- a/meson.build ++++ b/meson.build +@@ -36,12 +36,7 @@ if cdata.get('HAVE_IRQBALANCEUI') + install: true, + ) + +- install_man( +- 'irqbalance-ui.1', +- install_dir: get_option('mandir') + '/man1', +- install_mode: 'rw-r--r--', +- locale: 'en', +- ) ++ install_man('irqbalance-ui.1') + endif + + irqbalance_sources = [ +@@ -69,9 +64,4 @@ executable( + install: true, + ) + +-install_man( +- 'irqbalance.1', +- install_dir: get_option('mandir') + '/man1', +- install_mode: 'rw-r--r--', +- locale: 'en', +-) ++install_man('irqbalance.1') +-- +2.47.0 + diff --git a/0009-meson-add-a-minimum-version-decorator.patch b/0009-meson-add-a-minimum-version-decorator.patch new file mode 100644 index 0000000..1dd7cad --- /dev/null +++ b/0009-meson-add-a-minimum-version-decorator.patch @@ -0,0 +1,37 @@ +From 23c6da76e05bdd042e76c3df2b531190797760c4 Mon Sep 17 00:00:00 2001 +From: Eli Schwartz <eschwartz93@gmail.com> +Date: Mon, 1 Apr 2024 00:28:35 -0400 +Subject: [PATCH 09/44] meson: add a minimum version decorator + +Indicate the minimum required version of meson. Version 0.47 (released +March 2020) is needed regardless, since it provides the cross-platform +curses dependency wrapper. This just lets meson know that, so it +can: + +- warn you if you use features from newer versions you didn't intend to + use, which is a sign to either require a higher minimum or avoid the + new feature for maximal compatibility + +- error out if you have an older version of meson too old to build + correctly with + +Signed-off-by: Eli Schwartz <eschwartz93@gmail.com> +--- + meson.build | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/meson.build b/meson.build +index 2cd0a9e..026c4c4 100644 +--- a/meson.build ++++ b/meson.build +@@ -1,6 +1,7 @@ + project('irqbalance', 'c', + version: '1.9.4', + default_options: ['warning_level=1'], ++ meson_version: '>=0.54.0', + ) + + cc = meson.get_compiler('c') +-- +2.47.0 + diff --git a/0003-Drop-ProtectKernelTunables.patch b/0010-Drop-ProtectKernelTunables.patch similarity index 91% rename from 0003-Drop-ProtectKernelTunables.patch rename to 0010-Drop-ProtectKernelTunables.patch index f6fa428..33e608e 100644 --- a/0003-Drop-ProtectKernelTunables.patch +++ b/0010-Drop-ProtectKernelTunables.patch @@ -1,7 +1,7 @@ From f2c8309a4198d8f51069a783905049c5b7eb7600 Mon Sep 17 00:00:00 2001 From: Neil Horman <nhorman@openssl.org> Date: Mon, 1 Apr 2024 08:05:14 -0400 -Subject: [PATCH 3/3] Drop ProtectKernelTunables +Subject: [PATCH 10/44] Drop ProtectKernelTunables It makes /proc/irq read only --- @@ -21,5 +21,5 @@ index 87e19c1..b731cc6 100644 ProtectKernelLogs=yes ProtectControlGroups=yes -- -2.40.1 +2.47.0 diff --git a/0011-meson-replace-generic-array-with-files.patch b/0011-meson-replace-generic-array-with-files.patch new file mode 100644 index 0000000..4f9e117 --- /dev/null +++ b/0011-meson-replace-generic-array-with-files.patch @@ -0,0 +1,44 @@ +From 280b89d44c64d561ce091d3bc1a7145ad3a77167 Mon Sep 17 00:00:00 2001 +From: Rosen Penev <rosenp@gmail.com> +Date: Sun, 31 Mar 2024 13:31:26 -0700 +Subject: [PATCH 11/44] meson: replace generic array with files() + +The latter is more restrictive. + +Signed-off-by: Rosen Penev <rosenp@gmail.com> +--- + meson.build | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/meson.build b/meson.build +index 026c4c4..90d6aac 100644 +--- a/meson.build ++++ b/meson.build +@@ -40,7 +40,7 @@ if cdata.get('HAVE_IRQBALANCEUI') + install_man('irqbalance-ui.1') + endif + +-irqbalance_sources = [ ++irqbalance_sources = files( + 'activate.c', + 'bitmap.c', + 'classify.c', +@@ -50,12 +50,12 @@ irqbalance_sources = [ + 'numa.c', + 'placement.c', + 'procinterrupts.c', +-] ++) + + if libnl_3_dep.found() and libnl_genl_3_dep.found() +- irqbalance_sources += [ ++ irqbalance_sources += files( + 'thermal.c', +- ] ++ ) + endif + + executable( +-- +2.47.0 + diff --git a/0012-meson-use-find_library-for-numa.patch b/0012-meson-use-find_library-for-numa.patch new file mode 100644 index 0000000..b8442ee --- /dev/null +++ b/0012-meson-use-find_library-for-numa.patch @@ -0,0 +1,26 @@ +From 2e1bf9022276fc8753595c2db24d184382ad4a7c Mon Sep 17 00:00:00 2001 +From: Rosen Penev <rosenp@gmail.com> +Date: Sun, 31 Mar 2024 15:00:44 -0700 +Subject: [PATCH 12/44] meson: use find_library for numa + +Older versions of numa do not come with a pkgconfig file. +--- + meson.build | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/meson.build b/meson.build +index 90d6aac..d26ef42 100644 +--- a/meson.build ++++ b/meson.build +@@ -10,7 +10,7 @@ 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')) +-numa_dep = dependency('numa', required: get_option('numa')) ++numa_dep = cc.find_library('numa', required: get_option('numa')) + libnl_3_dep = dependency('libnl-3.0', required: get_option('thermal')) + libnl_genl_3_dep = dependency('libnl-genl-3.0', required: get_option('thermal')) + systemd_dep = dependency('libsystemd', required: get_option('systemd')) +-- +2.47.0 + diff --git a/0013-ui-change-void-to-char.patch b/0013-ui-change-void-to-char.patch new file mode 100644 index 0000000..0a463c9 --- /dev/null +++ b/0013-ui-change-void-to-char.patch @@ -0,0 +1,104 @@ +From 80a8aeb1dbb055bc1daa30e3bf8d80d5b07b33c7 Mon Sep 17 00:00:00 2001 +From: Rosen Penev <rosenp@gmail.com> +Date: Sun, 31 Mar 2024 15:27:43 -0700 +Subject: [PATCH 13/44] ui: change void to char + +It ends up being treated as a char anyway. + +Signed-off-by: Rosen Penev <rosenp@gmail.com> +--- + ui/helpers.c | 2 +- + ui/helpers.h | 2 +- + ui/ui.c | 8 ++++---- + ui/ui.h | 6 +++--- + 4 files changed, 9 insertions(+), 9 deletions(-) + +diff --git a/ui/helpers.c b/ui/helpers.c +index 247f826..3b4c51f 100644 +--- a/ui/helpers.c ++++ b/ui/helpers.c +@@ -117,7 +117,7 @@ void for_each_cpu(GList *list, void (*fp)(cpu_ban_t *cpu, void *data), void *dat + } + } + +-void for_each_int(GList *list, void (*fp)(int *number, void *data), void *data) ++void for_each_int(GList *list, void (*fp)(int *number, char *data), void *data) + { + GList *entry; + entry = g_list_first(list); +diff --git a/ui/helpers.h b/ui/helpers.h +index 922914b..176a8d3 100644 +--- a/ui/helpers.h ++++ b/ui/helpers.h +@@ -16,7 +16,7 @@ char * hex_to_bitmap(char hex_digit); + gpointer copy_cpu_ban(gconstpointer src, gpointer data); + gpointer copy_irq(gconstpointer src, gpointer data); + void for_each_cpu(GList *list, void (*fp)(cpu_ban_t *cpu, void *data), void *data); +-void for_each_int(GList *list, void (*fp)(int *number, void *data), void *data); ++void for_each_int(GList *list, void (*fp)(int *number, char *data), void *data); + void for_each_irq(GList *list, void (*fp)(irq_t *irq, void *data), void *data); + void for_each_node(GList *list, void (*fp)(cpu_node_t *node, void *data), void *data); + +diff --git a/ui/ui.c b/ui/ui.c +index a107fb9..2695ef0 100644 +--- a/ui/ui.c ++++ b/ui/ui.c +@@ -130,7 +130,7 @@ int get_valid_sleep_input(int column_offest) + return new_sleep; + } + +-void get_banned_cpu(int *cpu, void *data __attribute__((unused))) ++void get_banned_cpu(int *cpu, char *data __attribute__((unused))) + { + cpu_ban_t *new = malloc(sizeof(cpu_ban_t)); + new->number = *cpu; +@@ -188,9 +188,9 @@ void print_all_cpus(void) + max_offset = 0; + } + +-void add_banned_cpu(int *banned_cpu, void *data) ++void add_banned_cpu(int *banned_cpu, char *data) + { +- snprintf((char *)data + strlen(data), 1024 - strlen(data), "%d, ", *banned_cpu); ++ snprintf(data + strlen(data), 1024 - strlen(data), "%d, ", *banned_cpu); + } + + void display_banned_cpus(void) +@@ -369,7 +369,7 @@ static inline void bsnl_emit(char *buf, int buflen) + snprintf(buf + len, buflen - len, "%d-%d", rbot, rtop); + } + +-void copy_assigned_obj(int *number, void *data) ++void copy_assigned_obj(int *number, char *data) + { + if (rtop == -1) { + rbot = rtop = *number; +diff --git a/ui/ui.h b/ui/ui.h +index f3485d4..5fbdd7c 100644 +--- a/ui/ui.h ++++ b/ui/ui.h +@@ -23,10 +23,10 @@ void show_footer(void); + char * check_control_in_sleep_input(int max_len, int column_offest, int line_offset); + int get_valid_sleep_input(int column_offest); + +-void get_banned_cpu(int *cpu, void *data); ++void get_banned_cpu(int *cpu, char *data); + void print_cpu_line(cpu_ban_t *cpu, void *data); + void print_all_cpus(void); +-void add_banned_cpu(int *banned_cpu, void *data); ++void add_banned_cpu(int *banned_cpu, char *data); + void display_banned_cpus(void); + int toggle_cpu(GList *cpu_list, int cpu_number); + void get_new_cpu_ban_values(cpu_ban_t *cpu, void *data); +@@ -34,7 +34,7 @@ void get_cpu(cpu_node_t *node, void *data); + void handle_sleep_setting(void); + void handle_cpu_banning(void); + +-void copy_assigned_obj(int *number, void *data); ++void copy_assigned_obj(int *number, char *data); + void print_assigned_objects_string(irq_t *irq, int *line_offset); + void print_irq_line(irq_t *irq, void *data); + void print_all_irqs(void); +-- +2.47.0 + diff --git a/0014-clang-tidy-don-t-assign-in-if.patch b/0014-clang-tidy-don-t-assign-in-if.patch new file mode 100644 index 0000000..cb12203 --- /dev/null +++ b/0014-clang-tidy-don-t-assign-in-if.patch @@ -0,0 +1,71 @@ +From 122ae9e27078585e5c618bee6741f723c03f1aef Mon Sep 17 00:00:00 2001 +From: Rosen Penev <rosenp@gmail.com> +Date: Mon, 1 Apr 2024 13:56:46 -0700 +Subject: [PATCH 14/44] clang-tidy: don't assign in if + +Found with bugprone-assignment-in-if-condition + +Signed-off-by: Rosen Penev <rosenp@gmail.com> +--- + classify.c | 17 +++++++++++------ + irqbalance.c | 3 ++- + 2 files changed, 13 insertions(+), 7 deletions(-) + +diff --git a/classify.c b/classify.c +index 1601a1e..df9c13c 100644 +--- a/classify.c ++++ b/classify.c +@@ -200,25 +200,30 @@ static unsigned int read_pci_data(const char *devpath, const char* file) + /* Get pci information for IRQ classification */ + static int get_pci_info(const char *devpath, struct pci_info *pci) + { +- unsigned int data = PCI_INVAL_DATA; ++ unsigned int data; + +- if ((data = read_pci_data(devpath, "vendor")) == PCI_INVAL_DATA) ++ data = read_pci_data(devpath, "vendor"); ++ if (data == PCI_INVAL_DATA) + return -ENODEV; + pci->vendor = (unsigned short)data; + +- if ((data = read_pci_data(devpath, "device")) == PCI_INVAL_DATA) ++ data = read_pci_data(devpath, "device"); ++ if (data == PCI_INVAL_DATA) + return -ENODEV; + pci->device = (unsigned short)data; + +- if ((data = read_pci_data(devpath, "subsystem_vendor")) == PCI_INVAL_DATA) ++ data = read_pci_data(devpath, "subsystem_vendor"); ++ if (data == PCI_INVAL_DATA) + return -ENODEV; + pci->sub_vendor = (unsigned short)data; + +- if ((data = read_pci_data(devpath, "subsystem_device")) == PCI_INVAL_DATA) ++ data = read_pci_data(devpath, "subsystem_device"); ++ if (data == PCI_INVAL_DATA) + return -ENODEV; + pci->sub_device = (unsigned short)data; + +- if ((data = read_pci_data(devpath, "class")) == PCI_INVAL_DATA) ++ data = read_pci_data(devpath, "class"); ++ if (data == PCI_INVAL_DATA) + return -ENODEV; + pci->class = data; + +diff --git a/irqbalance.c b/irqbalance.c +index 373161f..a8c56c2 100644 +--- a/irqbalance.c ++++ b/irqbalance.c +@@ -422,7 +422,8 @@ gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attri + log(TO_ALL, LOG_WARNING, "Connection couldn't be accepted.\n"); + goto out; + } +- if ((recv_size = recvmsg(sock, &msg, 0)) < 0) { ++ recv_size = recvmsg(sock, &msg, 0); ++ if (recv_size < 0) { + log(TO_ALL, LOG_WARNING, "Error while receiving data.\n"); + goto out_close; + } +-- +2.47.0 + diff --git a/0015-clang-tidy-properly-use-strncmp.patch b/0015-clang-tidy-properly-use-strncmp.patch new file mode 100644 index 0000000..6aa998d --- /dev/null +++ b/0015-clang-tidy-properly-use-strncmp.patch @@ -0,0 +1,106 @@ +From 4c1b0a09bf78365c88e2fdf9713540e59f0375fc Mon Sep 17 00:00:00 2001 +From: Rosen Penev <rosenp@gmail.com> +Date: Mon, 1 Apr 2024 13:58:40 -0700 +Subject: [PATCH 15/44] clang-tidy: properly use strncmp + +Found with bugprone-suspicious-string-compare + +Signed-off-by: Rosen Penev <rosenp@gmail.com> +--- + ui/irqbalance-ui.c | 26 +++++++++++++------------- + 1 file changed, 13 insertions(+), 13 deletions(-) + +diff --git a/ui/irqbalance-ui.c b/ui/irqbalance-ui.c +index f5122ee..581c110 100644 +--- a/ui/irqbalance-ui.c ++++ b/ui/irqbalance-ui.c +@@ -157,7 +157,7 @@ void parse_setup(char *setup_data) + setup.banned_irqs = NULL; + setup.banned_cpus = NULL; + token = strtok_r(copy, " ", &ptr); +- if(strncmp(token, "SLEEP", strlen("SLEEP"))) goto out; ++ if(strncmp(token, "SLEEP", strlen("SLEEP")) != 0) goto out; + setup.sleep = strtol(strtok_r(NULL, " ", &ptr), NULL, 10); + token = strtok_r(NULL, " ", &ptr); + /* Parse banned IRQ data */ +@@ -165,13 +165,13 @@ void parse_setup(char *setup_data) + 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; ++ if(strncmp(token, "LOAD", strlen("LOAD")) != 0) goto out; + new_irq->load = strtol(strtok_r(NULL, " ", &ptr), NULL, 10); + token = strtok_r(NULL, " ", &ptr); +- if(strncmp(token, "DIFF", strlen("DIFF"))) goto out; ++ if(strncmp(token, "DIFF", strlen("DIFF")) != 0) goto out; + new_irq->diff = strtol(strtok_r(NULL, " ", &ptr), NULL, 10); + token = strtok_r(ptr, " ", &ptr); +- if(strncmp(token, "CLASS", strlen("CLASS"))) goto out; ++ if(strncmp(token, "CLASS", strlen("CLASS")) != 0) goto out; + new_irq->class = strtol(strtok_r(NULL, " ", &ptr), NULL, 10); + new_irq->is_banned = 1; + new_irq->assigned_to = NULL; +@@ -180,7 +180,7 @@ void parse_setup(char *setup_data) + new_irq = NULL; + } + +- if(strncmp(token, "BANNED", strlen("BANNED"))) goto out; ++ if(strncmp(token, "BANNED", strlen("BANNED")) != 0) goto out; + token = strtok_r(NULL, " ", &ptr); + for(i = strlen(token) - 1; i >= 0; i--) { + if (token[i] == ',') +@@ -287,7 +287,7 @@ void parse_into_tree(char *data) + token = strtok_r(copy, " ", &ptr); + while(token != NULL) { + /* Parse node data */ +- if(strncmp(token, "TYPE", strlen("TYPE"))) { ++ if(strncmp(token, "TYPE", strlen("TYPE")) != 0) { + free(copy); + goto out; + } +@@ -303,13 +303,13 @@ void parse_into_tree(char *data) + parent = parent->parent; + } + token = strtok_r(NULL, " ", &ptr); +- if(strncmp(token, "NUMBER", strlen("NUMBER"))) goto out; ++ if(strncmp(token, "NUMBER", strlen("NUMBER")) != 0) goto out; + new->number = strtol(strtok_r(NULL, " ", &ptr), NULL, 10); + token = strtok_r(NULL, " ", &ptr); +- if(strncmp(token, "LOAD", strlen("LOAD"))) goto out; ++ if(strncmp(token, "LOAD", strlen("LOAD")) != 0) goto out; + new->load = strtol(strtok_r(NULL, " ", &ptr), NULL, 10); + token = strtok_r(NULL, " ", &ptr); +- if(strncmp(token, "SAVE_MODE", strlen("SAVE_MODE"))) goto out; ++ if(strncmp(token, "SAVE_MODE", strlen("SAVE_MODE")) != 0) goto out; + new->is_powersave = strtol(strtok_r(NULL, " ", &ptr), NULL, 10); + token = strtok_r(NULL, " ", &ptr); + +@@ -318,13 +318,13 @@ void parse_into_tree(char *data) + 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; ++ if(strncmp(token, "LOAD", strlen("LOAD")) != 0) goto out; + new_irq->load = strtol(strtok_r(NULL, " ", &ptr), NULL, 10); + token = strtok_r(NULL, " ", &ptr); +- if(strncmp(token, "DIFF", strlen("DIFF"))) goto out; ++ if(strncmp(token, "DIFF", strlen("DIFF")) != 0) goto out; + new_irq->diff = strtol(strtok_r(NULL, " ", &ptr), NULL, 10); + token = strtok_r(NULL, " ", &ptr); +- if(strncmp(token, "CLASS", strlen("CLASS"))) goto out; ++ if(strncmp(token, "CLASS", strlen("CLASS")) != 0) goto out; + new_irq->class = strtol(strtok_r(NULL, " ", &ptr), NULL, 10); + new_irq->is_banned = 0; + new->irqs = g_list_append(new->irqs, new_irq); +@@ -332,7 +332,7 @@ void parse_into_tree(char *data) + new_irq = NULL; + } + +- if((token == NULL) || (strncmp(token, "IRQ", strlen("IRQ")))) { ++ if((token == NULL) || (strncmp(token, "IRQ", strlen("IRQ")) != 0)) { + new->parent = parent; + if(parent == NULL) { + tree = g_list_append(tree, new); +-- +2.47.0 + diff --git a/0016-replace-malloc-with-g_malloc0.patch b/0016-replace-malloc-with-g_malloc0.patch new file mode 100644 index 0000000..a6d0c24 --- /dev/null +++ b/0016-replace-malloc-with-g_malloc0.patch @@ -0,0 +1,32 @@ +From 8f575ec8bd70bd6895fc876d203ae28b7ab8c495 Mon Sep 17 00:00:00 2001 +From: Rosen Penev <rosenp@gmail.com> +Date: Mon, 1 Apr 2024 14:04:46 -0700 +Subject: [PATCH 16/44] replace malloc with g_malloc0 + +Aborts on failure. There's no null check. + +Signed-off-by: Rosen Penev <rosenp@gmail.com> +--- + ui/irqbalance-ui.c | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +diff --git a/ui/irqbalance-ui.c b/ui/irqbalance-ui.c +index 581c110..06f4602 100644 +--- a/ui/irqbalance-ui.c ++++ b/ui/irqbalance-ui.c +@@ -291,11 +291,7 @@ void parse_into_tree(char *data) + free(copy); + goto out; + } +- new = malloc(sizeof(cpu_node_t)); +- new->irqs = NULL; +- new->children = NULL; +- new->cpu_list = NULL; +- new->cpu_mask = NULL; ++ new = g_malloc0(sizeof(cpu_node_t)); + new->type = strtol(strtok_r(NULL, " ", &ptr), NULL, 10); + if(new->type == OBJ_TYPE_NODE) { + parent = NULL; +-- +2.47.0 + diff --git a/0017-clang-tidy-don-t-use-else-after-return.patch b/0017-clang-tidy-don-t-use-else-after-return.patch new file mode 100644 index 0000000..a7e4682 --- /dev/null +++ b/0017-clang-tidy-don-t-use-else-after-return.patch @@ -0,0 +1,151 @@ +From 2c3cbb5713e86199a10c8624eaf188609635d443 Mon Sep 17 00:00:00 2001 +From: Rosen Penev <rosenp@gmail.com> +Date: Mon, 1 Apr 2024 14:11:56 -0700 +Subject: [PATCH 17/44] clang-tidy: don't use else after return + +Found with readability-else-after-return + +Signed-off-by: Rosen Penev <rosenp@gmail.com> +--- + bitmap.h | 15 +++++---------- + classify.c | 6 ++---- + irqbalance.c | 6 +++--- + numa.c | 2 +- + ui/ui.c | 13 ++++++------- + 5 files changed, 17 insertions(+), 25 deletions(-) + +diff --git a/bitmap.h b/bitmap.h +index 7afce59..9eca1af 100644 +--- a/bitmap.h ++++ b/bitmap.h +@@ -282,8 +282,7 @@ static inline int bitmap_equal(const unsigned long *src1, + { + if (nbits <= BITS_PER_LONG) + return ! ((*src1 ^ *src2) & BITMAP_LAST_WORD_MASK(nbits)); +- else +- return __bitmap_equal(src1, src2, nbits); ++ return __bitmap_equal(src1, src2, nbits); + } + + static inline int bitmap_intersects(const unsigned long *src1, +@@ -291,8 +290,7 @@ static inline int bitmap_intersects(const unsigned long *src1, + { + if (nbits <= BITS_PER_LONG) + return ((*src1 & *src2) & BITMAP_LAST_WORD_MASK(nbits)) != 0; +- else +- return __bitmap_intersects(src1, src2, nbits); ++ return __bitmap_intersects(src1, src2, nbits); + } + + static inline int bitmap_subset(const unsigned long *src1, +@@ -300,24 +298,21 @@ static inline int bitmap_subset(const unsigned long *src1, + { + if (nbits <= BITS_PER_LONG) + return ! ((*src1 & ~(*src2)) & BITMAP_LAST_WORD_MASK(nbits)); +- else +- return __bitmap_subset(src1, src2, nbits); ++ return __bitmap_subset(src1, src2, nbits); + } + + static inline int bitmap_empty(const unsigned long *src, int nbits) + { + if (nbits <= BITS_PER_LONG) + return ! (*src & BITMAP_LAST_WORD_MASK(nbits)); +- else +- return __bitmap_empty(src, nbits); ++ return __bitmap_empty(src, nbits); + } + + static inline int bitmap_full(const unsigned long *src, int nbits) + { + if (nbits <= BITS_PER_LONG) + return ! (~(*src) & BITMAP_LAST_WORD_MASK(nbits)); +- else +- return __bitmap_full(src, nbits); ++ return __bitmap_full(src, nbits); + } + + static inline int bitmap_weight(const unsigned long *src, int nbits) +diff --git a/classify.c b/classify.c +index df9c13c..cc0200d 100644 +--- a/classify.c ++++ b/classify.c +@@ -295,8 +295,7 @@ gint substr_find(gconstpointer a, gconstpointer b) + { + if (strstr(b, a)) + return 0; +- else +- return 1; ++ return 1; + } + + static void add_banned_module(char *modname, GList **modlist) +@@ -558,8 +557,7 @@ static int check_for_module_ban(char *name) + + if (entry) + return 1; +- else +- return 0; ++ return 0; + } + + static int check_for_irq_ban(struct irq_info *irq, char *mod) +diff --git a/irqbalance.c b/irqbalance.c +index a8c56c2..ab4e448 100644 +--- a/irqbalance.c ++++ b/irqbalance.c +@@ -330,10 +330,10 @@ out: + + if (keep_going) { + return TRUE; +- } else { +- g_main_loop_quit(main_loop); +- return FALSE; + } ++ ++ g_main_loop_quit(main_loop); ++ return FALSE; + } + + void get_irq_data(struct irq_info *irq, void *data) +diff --git a/numa.c b/numa.c +index 13d7ebd..5143ea0 100644 +--- a/numa.c ++++ b/numa.c +@@ -116,7 +116,7 @@ void connect_cpu_mem_topo(struct topo_obj *p, void *data __attribute__((unused)) + + if (len == 0) { + return; +- } else if (len > 1) { ++ } if (len > 1) { + for_each_object(p->children, connect_cpu_mem_topo, NULL); + return; + } +diff --git a/ui/ui.c b/ui/ui.c +index 2695ef0..c580f85 100644 +--- a/ui/ui.c ++++ b/ui/ui.c +@@ -113,14 +113,13 @@ int get_valid_sleep_input(int column_offest) + new_sleep = strtol(input, &error, 10); + if((*error == '\0') && (new_sleep >= 1)) { + break; +- } else { +- new_sleep = setup.sleep; +- attrset(COLOR_PAIR(4) | A_BOLD); +- mvprintw(LINES - 2, 1, +- "Invalid input: %s ", +- input); +- refresh(); + } ++ new_sleep = setup.sleep; ++ attrset(COLOR_PAIR(4) | A_BOLD); ++ mvprintw(LINES - 2, 1, ++ "Invalid input: %s ", ++ input); ++ refresh(); + free(input); + } + +-- +2.47.0 + diff --git a/0018-clang-tidy-remove-return-in-void-functions.patch b/0018-clang-tidy-remove-return-in-void-functions.patch new file mode 100644 index 0000000..31e78b9 --- /dev/null +++ b/0018-clang-tidy-remove-return-in-void-functions.patch @@ -0,0 +1,36 @@ +From 9b1ced291f14debdae735723978ed5b44da9deee Mon Sep 17 00:00:00 2001 +From: Rosen Penev <rosenp@gmail.com> +Date: Mon, 1 Apr 2024 14:14:55 -0700 +Subject: [PATCH 18/44] clang-tidy: remove return in void functions + +Found with readability-redundant-control-flow + +Signed-off-by: Rosen Penev <rosenp@gmail.com> +--- + classify.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/classify.c b/classify.c +index cc0200d..08340db 100644 +--- a/classify.c ++++ b/classify.c +@@ -102,8 +102,6 @@ static void apply_pci_quirks(const struct pci_info *pci, int *irq_class) + break; + } + } +- +- return; + } + + /* Determin IRQ class based on PCI class code */ +@@ -283,7 +281,6 @@ static void add_banned_irq(int irq, GList **list) + + *list = g_list_append(*list, new); + log(TO_CONSOLE, LOG_INFO, "IRQ %d was BANNED.\n", irq); +- return; + } + + void add_cl_banned_irq(int irq) +-- +2.47.0 + diff --git a/0019-clang-tidy-remove-redundant-declarations.patch b/0019-clang-tidy-remove-redundant-declarations.patch new file mode 100644 index 0000000..a3a60ae --- /dev/null +++ b/0019-clang-tidy-remove-redundant-declarations.patch @@ -0,0 +1,27 @@ +From 02f7c174f1dfb0699cec4078d90a93901556a0c1 Mon Sep 17 00:00:00 2001 +From: Rosen Penev <rosenp@gmail.com> +Date: Mon, 1 Apr 2024 14:16:26 -0700 +Subject: [PATCH 19/44] clang-tidy: remove redundant declarations + +Found with readability-redundant-declaration + +Signed-off-by: Rosen Penev <rosenp@gmail.com> +--- + ui/ui.h | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/ui/ui.h b/ui/ui.h +index 5fbdd7c..e41ca24 100644 +--- a/ui/ui.h ++++ b/ui/ui.h +@@ -11,7 +11,6 @@ + #include "irqbalance-ui.h" + #include "helpers.h" + +-extern GList *tree; + extern setup_t setup; + + extern int offset; +-- +2.47.0 + diff --git a/0020-clang-tidy-remove-duplicate-include.patch b/0020-clang-tidy-remove-duplicate-include.patch new file mode 100644 index 0000000..dde209f --- /dev/null +++ b/0020-clang-tidy-remove-duplicate-include.patch @@ -0,0 +1,27 @@ +From e78ea2676fdb2754b58ddec3c88b185f1b0b9949 Mon Sep 17 00:00:00 2001 +From: Rosen Penev <rosenp@gmail.com> +Date: Mon, 1 Apr 2024 14:18:35 -0700 +Subject: [PATCH 20/44] clang-tidy: remove duplicate include + +Found with readability-duplicate-include + +Signed-off-by: Rosen Penev <rosenp@gmail.com> +--- + irqbalance.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/irqbalance.c b/irqbalance.c +index ab4e448..870d7c0 100644 +--- a/irqbalance.c ++++ b/irqbalance.c +@@ -26,7 +26,6 @@ + #include <malloc.h> + #include <sys/time.h> + #include <syslog.h> +-#include <unistd.h> + #include <signal.h> + #include <time.h> + #include <sys/types.h> +-- +2.47.0 + diff --git a/0021-CI-add-meson-CI.patch b/0021-CI-add-meson-CI.patch new file mode 100644 index 0000000..9d8b032 --- /dev/null +++ b/0021-CI-add-meson-CI.patch @@ -0,0 +1,92 @@ +From 44795adcf03c951efb92bed69af7d68d230d6d69 Mon Sep 17 00:00:00 2001 +From: Rosen Penev <rosenp@gmail.com> +Date: Sun, 31 Mar 2024 13:59:01 -0700 +Subject: [PATCH 21/44] CI: add meson CI + +tests old and new Clang/GCC on x64 and Alpine Linux on various platforms. + +Signed-off-by: Rosen Penev <rosenp@gmail.com> +--- + .github/workflows/meson.yml | 70 +++++++++++++++++++++++++++++++++++++ + 1 file changed, 70 insertions(+) + create mode 100644 .github/workflows/meson.yml + +diff --git a/.github/workflows/meson.yml b/.github/workflows/meson.yml +new file mode 100644 +index 0000000..df2d826 +--- /dev/null ++++ b/.github/workflows/meson.yml +@@ -0,0 +1,70 @@ ++name: meson ++ ++on: [pull_request, push] ++ ++concurrency: ++ group: ${{github.workflow}}-${{github.head_ref}} ++ cancel-in-progress: true ++ ++jobs: ++ Linux-GCC: ++ runs-on: ubuntu-20.04 ++ strategy: ++ matrix: ++ cc: ['7', '13'] ++ steps: ++ - uses: actions/checkout@v4 ++ - uses: egor-tensin/setup-gcc@v1 ++ with: ++ version: ${{matrix.cc}} ++ - name: Install Packages ++ run: | ++ python3 -m pip install meson ninja ++ sudo apt install -y libcap-ng-dev libnl-3-dev libnl-genl-3-dev libnuma-dev libsystemd-dev ++ - name: Compile and Test ++ run: | ++ meson setup "${{github.workspace}}/build" -Dwarning_level=3 ++ meson compile -C "${{github.workspace}}/build" ++ meson test -C "${{github.workspace}}/build" ++ Linux-Clang: ++ runs-on: ubuntu-20.04 ++ strategy: ++ matrix: ++ cc: ['6.0', '18'] ++ steps: ++ - uses: actions/checkout@v4 ++ - uses: egor-tensin/setup-clang@v1 ++ with: ++ version: ${{matrix.cc}} ++ - name: Install Packages ++ run: | ++ python3 -m pip install meson ninja ++ sudo apt install -y libcap-ng-dev libnl-3-dev libnl-genl-3-dev libnuma-dev libsystemd-dev ++ - name: Compile and Test ++ run: | ++ meson setup "${{github.workspace}}/build" -Dwarning_level=3 ++ meson compile -C "${{github.workspace}}/build" --verbose ++ meson test -C "${{github.workspace}}/build" --verbose ++ Alpine: ++ runs-on: ubuntu-20.04 ++ strategy: ++ matrix: ++ platform: ['aarch64', 'armhf', 'armv7', 'ppc64le', 'riscv64', 's390x'] ++ defaults: ++ run: ++ shell: alpine.sh {0} ++ steps: ++ - name: Get pushed code ++ uses: actions/checkout@v4 ++ ++ - uses: jirutka/setup-alpine@v1 ++ with: ++ branch: edge ++ arch: ${{matrix.platform}} ++ packages: > ++ build-base glib-dev libcap-ng-dev libnl3-dev meson numactl-dev ++ - name: Compile and Test ++ run: | ++ meson setup "${{github.workspace}}/build" -Dwarning_level=3 -Dsystemd=disabled ++ meson compile -C "${{github.workspace}}/build" ++ meson test -C "${{github.workspace}}/build" +-- +2.47.0 + diff --git a/0022-Wrap-migrate_irq-in-a-higher-level-utility-function.patch b/0022-Wrap-migrate_irq-in-a-higher-level-utility-function.patch new file mode 100644 index 0000000..2c6dae7 --- /dev/null +++ b/0022-Wrap-migrate_irq-in-a-higher-level-utility-function.patch @@ -0,0 +1,173 @@ +From d16ad5df4cd14b148513ab9d5cf0ebcf09d023e0 Mon Sep 17 00:00:00 2001 +From: Andrew Zaborowski <andrew.zaborowski@intel.com> +Date: Fri, 10 May 2024 18:38:52 -0700 +Subject: [PATCH 22/44] Wrap migrate_irq in a higher level utility function + +Add migrate_irq_obj and replace existing migrate_irq calls with calls to +the new function. migrate_irq_obj takes source and destination +topo_obj's instead of interrupt lists so as to factor out updating of +the load on the destination cpu and of info->asssigned_obj. + +Pass NULL as destination to move irq to rebalance_irq_list. + +Drop the unneeded force_irq_migration. +--- + irqbalance.c | 4 +--- + irqbalance.h | 1 + + irqlist.c | 31 +++++++++++++++++++++---------- + placement.c | 24 +++++------------------- + 4 files changed, 28 insertions(+), 32 deletions(-) + +diff --git a/irqbalance.c b/irqbalance.c +index 870d7c0..7efbc98 100644 +--- a/irqbalance.c ++++ b/irqbalance.c +@@ -253,9 +253,7 @@ void force_rebalance_irq(struct irq_info *info, void *data __attribute__((unused + if (info->assigned_obj == NULL) + rebalance_irq_list = g_list_append(rebalance_irq_list, info); + else +- migrate_irq(&info->assigned_obj->interrupts, &rebalance_irq_list, info); +- +- info->assigned_obj = NULL; ++ migrate_irq_obj(info->assigned_obj, NULL, info); + } + + gboolean handler(gpointer data __attribute__((unused))) +diff --git a/irqbalance.h b/irqbalance.h +index 09daa3d..76640dd 100644 +--- a/irqbalance.h ++++ b/irqbalance.h +@@ -52,6 +52,7 @@ void dump_workloads(void); + void sort_irq_list(GList **list); + void calculate_placement(void); + void dump_tree(void); ++void migrate_irq_obj(struct topo_obj *from, struct topo_obj *to, struct irq_info *info); + + void activate_mappings(void); + void clear_cpu_tree(void); +diff --git a/irqlist.c b/irqlist.c +index 0ba411e..304b1c6 100644 +--- a/irqlist.c ++++ b/irqlist.c +@@ -108,9 +108,7 @@ static void move_candidate_irqs(struct irq_info *info, void *data) + + log(TO_CONSOLE, LOG_INFO, "Selecting irq %d for rebalancing\n", info->irq); + +- migrate_irq(&info->assigned_obj->interrupts, &rebalance_irq_list, info); +- +- info->assigned_obj = NULL; ++ force_rebalance_irq(info, NULL); + } + + static void migrate_overloaded_irqs(struct topo_obj *obj, void *data) +@@ -146,12 +144,6 @@ static void migrate_overloaded_irqs(struct topo_obj *obj, void *data) + } + } + +-static void force_irq_migration(struct irq_info *info, void *data __attribute__((unused))) +-{ +- migrate_irq(&info->assigned_obj->interrupts, &rebalance_irq_list, info); +- info->assigned_obj = NULL; +-} +- + static void clear_powersave_mode(struct topo_obj *obj, void *data __attribute__((unused))) + { + obj->powersave_mode = 0; +@@ -183,7 +175,7 @@ void update_migration_status(void) + log(TO_ALL, LOG_INFO, "cpu %d entering powersave mode\n", info.powersave->number); + info.powersave->powersave_mode = 1; + if (g_list_length(info.powersave->interrupts) > 0) +- for_each_irq(info.powersave->interrupts, force_irq_migration, NULL); ++ for_each_irq(info.powersave->interrupts, force_rebalance_irq, NULL); + } else if ((info.num_over) && (info.num_powersave)) { + log(TO_ALL, LOG_INFO, "Load average increasing, re-enabling all cpus for irq balancing\n"); + for_each_object(cpus, clear_powersave_mode, NULL); +@@ -205,3 +197,22 @@ void dump_workloads(void) + for_each_irq(NULL, dump_workload, NULL); + } + ++void migrate_irq_obj(struct topo_obj *from, struct topo_obj *to, struct irq_info *info) ++{ ++ ++ GList **from_list; ++ GList **to_list; ++ ++ if (!from) ++ from = info->assigned_obj; ++ ++ from_list = from ? &from->interrupts : &rebalance_irq_list; ++ to_list = to ? &to->interrupts : &rebalance_irq_list; ++ ++ migrate_irq(from_list, to_list, info); ++ ++ if (to) ++ to->load += info->load + 1; ++ ++ info->assigned_obj = to; ++} +diff --git a/placement.c b/placement.c +index dea7c23..f156e0e 100644 +--- a/placement.c ++++ b/placement.c +@@ -74,7 +74,6 @@ static void find_best_object_for_irq(struct irq_info *info, void *data) + { + struct obj_placement place; + struct topo_obj *d = data; +- struct topo_obj *asign; + + if (!info->moved) + return; +@@ -107,13 +106,8 @@ static void find_best_object_for_irq(struct irq_info *info, void *data) + + for_each_object(d->children, find_best_object, &place); + +- asign = place.best; +- +- if (asign) { +- migrate_irq(&d->interrupts, &asign->interrupts, info); +- info->assigned_obj = asign; +- asign->load += info->load; +- } ++ if (place.best) ++ migrate_irq_obj(d, place.best, info); + } + + static void place_irq_in_object(struct topo_obj *d, void *data __attribute__((unused))) +@@ -125,7 +119,6 @@ static void place_irq_in_object(struct topo_obj *d, void *data __attribute__((un + static void place_irq_in_node(struct irq_info *info, void *data __attribute__((unused))) + { + struct obj_placement place; +- struct topo_obj *asign; + + if ((info->level == BALANCE_NONE) && cpus_empty(banned_cpus)) + return; +@@ -145,9 +138,7 @@ static void place_irq_in_node(struct irq_info *info, void *data __attribute__((u + * This irq belongs to a device with a preferred numa node + * put it on that node + */ +- migrate_irq(&rebalance_irq_list, &irq_numa_node(info)->interrupts, info); +- info->assigned_obj = irq_numa_node(info); +- irq_numa_node(info)->load += info->load + 1; ++ migrate_irq_obj(NULL, irq_numa_node(info), info); + + return; + } +@@ -159,13 +150,8 @@ find_placement: + + for_each_object(numa_nodes, find_best_object, &place); + +- asign = place.best; +- +- if (asign) { +- migrate_irq(&rebalance_irq_list, &asign->interrupts, info); +- info->assigned_obj = asign; +- asign->load += info->load; +- } ++ if (place.best) ++ migrate_irq_obj(NULL, place.best, info); + } + + static void validate_irq(struct irq_info *info, void *data) +-- +2.47.0 + diff --git a/0023-Track-IRQ-slots-count-per-CPU-to-avoid-overflowing.patch b/0023-Track-IRQ-slots-count-per-CPU-to-avoid-overflowing.patch new file mode 100644 index 0000000..96e57c6 --- /dev/null +++ b/0023-Track-IRQ-slots-count-per-CPU-to-avoid-overflowing.patch @@ -0,0 +1,195 @@ +From 54051449030cb3c1642f9a6110316d3705eb3a23 Mon Sep 17 00:00:00 2001 +From: Andrew Zaborowski <andrew.zaborowski@intel.com> +Date: Fri, 10 May 2024 18:57:34 -0700 +Subject: [PATCH 23/44] Track IRQ "slots" count per CPU to avoid overflowing + +There are situations where irqbalance may try to migrate large numbers of +IRQs to a topo_obj, there's no upper bound on the number as the +placement logic is based on load mainly. The kernel's irq bitmasks limit +the number of IRQs on each cpu and if more are tried to be migrated, the +write to smp_affinity returns -ENOSPC. This confuses irqbalance's +logic, the topo_obj.interrupts list no longer matches the irqs actually +on that CPU or cache domain, and results in floods of error messages. +See https://github.com/Irqbalance/irqbalance/issues/303 for details. + +For an easy fix, track the number of IRQ slots still free on each CPU. +We start with INT_MAX meaning "unknown" and when we first get a -ENOSPC, +we know we have no slots left. From there update the slots count each +time we migrate IRQs to/from the CPU core topo_obj. We may never see an +-ENOSPC and in that case there's no change in current logic, we never +start tracking. + +This way we don't need to know ahead of time how many slots the kernel +has for each CPU. The number may be arch specific (it is about 200 on +x86-64) and is dependent on the number managed IRQs kernel has +registered, so we don't want to guess. This is also more tolerant to +the topo_obj.interrupts lists not matching exactly the kernel's idea of +each irq's current affinity, e.g. due to -EIO errors in the smp_affinity +writes. + +For now only do the tracking at OBJ_TYPE_CPU level so we don't have to +update slots_left for all parent objs. + +Th commit doesn't try to stop an ongoing activation of all the IRQs +already scheduled for moving to one cpu, when that cpu starts returning +ENOSPC. We'll still see a bunch of those errors in that iteration. +But in subsequent calculate_placement() iterations we avoid assigning +more IRQs to that cpu than we were able to successfully move before. +--- + activate.c | 13 ++++++++++++- + classify.c | 2 ++ + cputree.c | 10 ++++++++++ + irqbalance.c | 3 +++ + irqbalance.h | 1 + + irqlist.c | 11 ++++++++++- + placement.c | 3 +++ + types.h | 1 + + 8 files changed, 42 insertions(+), 2 deletions(-) + +diff --git a/activate.c b/activate.c +index 0c1e7a1..10ad57d 100644 +--- a/activate.c ++++ b/activate.c +@@ -99,7 +99,6 @@ error: + "Cannot change IRQ %i affinity: %s\n", + info->irq, strerror(errsave)); + switch (errsave) { +- case ENOSPC: /* Specified CPU APIC is full. */ + case EAGAIN: /* Interrupted by signal. */ + case EBUSY: /* Affinity change already in progress. */ + case EINVAL: /* IRQ would be bound to no CPU. */ +@@ -107,6 +106,18 @@ error: + case ENOMEM: /* Kernel cannot allocate CPU mask. */ + /* Do not blacklist the IRQ on transient errors. */ + break; ++ case ENOSPC: /* Specified CPU APIC is full. */ ++ if (info->assigned_obj->obj_type != OBJ_TYPE_CPU) ++ break; ++ ++ if (info->assigned_obj->slots_left > 0) ++ info->assigned_obj->slots_left = -1; ++ else ++ /* Negative slots to count how many we need to free */ ++ info->assigned_obj->slots_left--; ++ ++ force_rebalance_irq(info, NULL); ++ break; + default: + /* Any other error is considered permanent. */ + info->level = BALANCE_NONE; +diff --git a/classify.c b/classify.c +index 08340db..69d72ac 100644 +--- a/classify.c ++++ b/classify.c +@@ -883,6 +883,8 @@ static void remove_no_existing_irq(struct irq_info *info, void *data __attribute + entry = g_list_find_custom(info->assigned_obj->interrupts, info, compare_ints); + if (entry) { + info->assigned_obj->interrupts = g_list_delete_link(info->assigned_obj->interrupts, entry); ++ /* Probe number of slots again, don't guess whether the IRQ left a free slot */ ++ info->assigned_obj->slots_left = INT_MAX; + } + } + free_irq(info, NULL); +diff --git a/cputree.c b/cputree.c +index d66be55..6c7b3b4 100644 +--- a/cputree.c ++++ b/cputree.c +@@ -595,3 +595,13 @@ int get_cpu_count(void) + return g_list_length(cpus); + } + ++static void clear_obj_slots(struct topo_obj *d, void *data __attribute__((unused))) ++{ ++ d->slots_left = INT_MAX; ++ for_each_object(d->children, clear_obj_slots, NULL); ++} ++ ++void clear_slots(void) ++{ ++ for_each_object(numa_nodes, clear_obj_slots, NULL); ++} +diff --git a/irqbalance.c b/irqbalance.c +index 7efbc98..1490336 100644 +--- a/irqbalance.c ++++ b/irqbalance.c +@@ -298,6 +298,7 @@ gboolean scan(gpointer data __attribute__((unused))) + } while (need_rebuild); + + for_each_irq(NULL, force_rebalance_irq, NULL); ++ clear_slots(); + parse_proc_interrupts(); + parse_proc_stat(); + return TRUE; +@@ -695,6 +696,8 @@ int main(int argc, char** argv) + parse_proc_interrupts(); + parse_proc_stat(); + ++ clear_slots(); ++ + #ifdef HAVE_IRQBALANCEUI + if (init_socket()) { + ret = EXIT_FAILURE; +diff --git a/irqbalance.h b/irqbalance.h +index 76640dd..47e40cc 100644 +--- a/irqbalance.h ++++ b/irqbalance.h +@@ -98,6 +98,7 @@ extern struct topo_obj *get_numa_node(int nodeid); + #define cpu_numa_node(cpu) ((cpu)->parent->numa_nodes) + extern struct topo_obj *find_cpu_core(int cpunr); + extern int get_cpu_count(void); ++extern void clear_slots(void); + + /* + * irq db functions +diff --git a/irqlist.c b/irqlist.c +index 304b1c6..9483a11 100644 +--- a/irqlist.c ++++ b/irqlist.c +@@ -211,8 +211,17 @@ void migrate_irq_obj(struct topo_obj *from, struct topo_obj *to, struct irq_info + + migrate_irq(from_list, to_list, info); + +- if (to) ++ if (from) { ++ if (from->slots_left != INT_MAX) ++ from->slots_left++; ++ } ++ ++ if (to) { ++ if (to->slots_left != INT_MAX) ++ to->slots_left--; ++ + to->load += info->load + 1; ++ } + + info->assigned_obj = to; + } +diff --git a/placement.c b/placement.c +index f156e0e..3276dea 100644 +--- a/placement.c ++++ b/placement.c +@@ -59,6 +59,9 @@ static void find_best_object(struct topo_obj *d, void *data) + if (d->powersave_mode) + return; + ++ if (d->slots_left <= 0) ++ return; ++ + newload = d->load; + if (newload < best->best_cost) { + best->best = d; +diff --git a/types.h b/types.h +index ea1fae8..5c66bf9 100644 +--- a/types.h ++++ b/types.h +@@ -56,6 +56,7 @@ struct topo_obj { + GList *children; + GList *numa_nodes; + GList **obj_type_list; ++ int slots_left; + }; + + struct irq_info { +-- +2.47.0 + diff --git a/0024-Disable-linking-to-curses-if-without-irqbalance-ui-i.patch b/0024-Disable-linking-to-curses-if-without-irqbalance-ui-i.patch new file mode 100644 index 0000000..3fe3275 --- /dev/null +++ b/0024-Disable-linking-to-curses-if-without-irqbalance-ui-i.patch @@ -0,0 +1,43 @@ +From c90599b15e847d019f8d3058b5c9010d8919a786 Mon Sep 17 00:00:00 2001 +From: Andrew Soknacki <6068404+Sout@users.noreply.github.com> +Date: Thu, 20 Jun 2024 20:38:45 -0400 +Subject: [PATCH 24/44] Disable linking to curses if --without-irqbalance-ui is + specified. + +--- + configure.ac | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 7ec6060..4718444 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -38,12 +38,6 @@ AC_CHECK_LIB(m, floor) + PKG_CHECK_MODULES([GLIB2], [glib-2.0], [], [AC_MSG_ERROR([glib-2.0 is required])]) + + PKG_CHECK_MODULES([NCURSESW], [ncursesw], [has_ncursesw=yes], [AC_CHECK_LIB(curses, mvprintw)]) +-AS_IF([test "x$has_ncursesw" = "xyes"], [ +- AC_SUBST([NCURSESW_CFLAGS]) +- AC_SUBST([NCURSESW_LIBS]) +- LIBS="$LIBS $NCURSESW_LIBS" +- AC_SUBST([LIBS]) +-]) + + AC_CANONICAL_HOST + +@@ -78,6 +72,12 @@ AC_ARG_WITH([irqbalance-ui], + AS_IF( + [test "x$with_irqbalanceui" = "xyes"], [ + AC_DEFINE([HAVE_IRQBALANCEUI], 1, [Build irqbalance ui component.]) ++ AS_IF([test "x$has_ncursesw" = "xyes"], [ ++ AC_SUBST([NCURSESW_CFLAGS]) ++ AC_SUBST([NCURSESW_LIBS]) ++ LIBS="$LIBS $NCURSESW_LIBS" ++ AC_SUBST([LIBS]) ++ ]) + ]) + AM_CONDITIONAL([IRQBALANCEUI], [test x$with_irqbalanceui = xyes]) + +-- +2.47.0 + diff --git a/0025-Remove-extraneous-space-causing-with-systemd-not-be-.patch b/0025-Remove-extraneous-space-causing-with-systemd-not-be-.patch new file mode 100644 index 0000000..e6e1619 --- /dev/null +++ b/0025-Remove-extraneous-space-causing-with-systemd-not-be-.patch @@ -0,0 +1,26 @@ +From 9851c8c9bf8de26295e633475d35e36ccbe93714 Mon Sep 17 00:00:00 2001 +From: Andrew Soknacki <6068404+Sout@users.noreply.github.com> +Date: Thu, 20 Jun 2024 20:38:45 -0400 +Subject: [PATCH 25/44] Remove extraneous space causing --with-systemd not be + aligned + +--- + configure.ac | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index 4718444..678f66e 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -82,7 +82,7 @@ AS_IF( + AM_CONDITIONAL([IRQBALANCEUI], [test x$with_irqbalanceui = xyes]) + + AC_ARG_WITH([systemd], +- [ AS_HELP_STRING([--with-systemd],[Add systemd-lib support])] ++ [AS_HELP_STRING([--with-systemd],[Add systemd-lib support])] + ) + AS_IF( + [test "x$with_systemd" = xyes], [ +-- +2.47.0 + diff --git a/0026-direct-initialize-msghdr-members.patch b/0026-direct-initialize-msghdr-members.patch new file mode 100644 index 0000000..acddbef --- /dev/null +++ b/0026-direct-initialize-msghdr-members.patch @@ -0,0 +1,38 @@ +From 5010a9766aff8a0c8e8644acef40d025ec2e0a48 Mon Sep 17 00:00:00 2001 +From: Rosen Penev <rosenp@gmail.com> +Date: Sun, 30 Jun 2024 16:50:50 -0700 +Subject: [PATCH 26/44] direct initialize msghdr members + +Standard C99. { 0 } is somewhat interesting as some compilers warn about +uninitialized members, which is bogus. + +Signed-off-by: Rosen Penev <rosenp@gmail.com> +--- + irqbalance.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/irqbalance.c b/irqbalance.c +index 1490336..64b41f7 100644 +--- a/irqbalance.c ++++ b/irqbalance.c +@@ -406,11 +406,12 @@ gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attri + int valid_user = 0; + + struct iovec iov = { buff, 500 }; +- struct msghdr msg = { 0 }; +- msg.msg_iov = &iov; +- msg.msg_iovlen = 1; +- msg.msg_control = malloc(CMSG_SPACE(sizeof(struct ucred))); +- msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred)); ++ struct msghdr msg = { ++ .msg_iov = &iov, ++ .msg_iovlen = 1, ++ .msg_control = malloc(CMSG_SPACE(sizeof(struct ucred))), ++ .msg_controllen = CMSG_SPACE(sizeof(struct ucred)), ++ }; + + struct cmsghdr *cmsg; + +-- +2.47.0 + diff --git a/0027-direct-initialize-iovec.patch b/0027-direct-initialize-iovec.patch new file mode 100644 index 0000000..d172e6d --- /dev/null +++ b/0027-direct-initialize-iovec.patch @@ -0,0 +1,31 @@ +From d36ae562c668c25d737b90c4ca1a84d8e9079712 Mon Sep 17 00:00:00 2001 +From: Rosen Penev <rosenp@gmail.com> +Date: Thu, 4 Jul 2024 14:04:14 -0700 +Subject: [PATCH 27/44] direct initialize iovec + +Signed-off-by: Rosen Penev <rosenp@gmail.com> +--- + ui/irqbalance-ui.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/ui/irqbalance-ui.c b/ui/irqbalance-ui.c +index 06f4602..2e6b7d3 100644 +--- a/ui/irqbalance-ui.c ++++ b/ui/irqbalance-ui.c +@@ -118,9 +118,10 @@ try_again: + } + + struct msghdr *msg = create_credentials_msg(); +- struct iovec iov; +- iov.iov_base = (void *) string; +- iov.iov_len = strlen(string); ++ struct iovec iov = { ++ .iov_base = (void *) string, ++ .iov_len = strlen(string), ++ }; + msg->msg_iov = &iov; + sendmsg(socket_fd, msg, 0); + +-- +2.47.0 + diff --git a/0028-clang-tidy-add-missing-free.patch b/0028-clang-tidy-add-missing-free.patch new file mode 100644 index 0000000..db490a8 --- /dev/null +++ b/0028-clang-tidy-add-missing-free.patch @@ -0,0 +1,27 @@ +From 16564e3ced6517ddd15bbcfb84df704f7f614c3b Mon Sep 17 00:00:00 2001 +From: Rosen Penev <rosenp@gmail.com> +Date: Sun, 30 Jun 2024 17:26:11 -0700 +Subject: [PATCH 28/44] clang-tidy: add missing free + +Found with clang-analyzer-unix.Malloc + +Signed-off-by: Rosen Penev <rosenp@gmail.com> +--- + ui/ui.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/ui/ui.c b/ui/ui.c +index c580f85..5401d02 100644 +--- a/ui/ui.c ++++ b/ui/ui.c +@@ -112,6 +112,7 @@ int get_valid_sleep_input(int column_offest) + char *error; + new_sleep = strtol(input, &error, 10); + if((*error == '\0') && (new_sleep >= 1)) { ++ free(input); + break; + } + new_sleep = setup.sleep; +-- +2.47.0 + diff --git a/0029-clang-tidy-don-t-assign-in-if.patch b/0029-clang-tidy-don-t-assign-in-if.patch new file mode 100644 index 0000000..4bd98d3 --- /dev/null +++ b/0029-clang-tidy-don-t-assign-in-if.patch @@ -0,0 +1,43 @@ +From 2ed4dd0233a6e070c7ad128594892510d28f2ea9 Mon Sep 17 00:00:00 2001 +From: Rosen Penev <rosenp@gmail.com> +Date: Sun, 30 Jun 2024 17:14:55 -0700 +Subject: [PATCH 29/44] clang-tidy: don't assign in if + +Found with bugprone-assignment-in-if-condition + +Signed-off-by: Rosen Penev <rosenp@gmail.com> +--- + irqbalance.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +diff --git a/irqbalance.c b/irqbalance.c +index 64b41f7..dfd5d2d 100644 +--- a/irqbalance.c ++++ b/irqbalance.c +@@ -654,13 +654,16 @@ int main(int argc, char** argv) + if (daemon(0,0)) + exit(EXIT_FAILURE); + /* Write pidfile which can be used to avoid starting multiple instances */ +- if (pidfile && (pidfd = open(pidfile, +- O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, +- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) >= 0) { +- char str[16]; +- snprintf(str, sizeof(str), "%u\n", getpid()); +- write(pidfd, str, strlen(str)); +- close(pidfd); ++ if (pidfile) { ++ pidfd = open(pidfile, ++ O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, ++ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); ++ if (pidfd >= 0) { ++ char str[16]; ++ snprintf(str, sizeof(str), "%u\n", getpid()); ++ write(pidfd, str, strlen(str)); ++ close(pidfd); ++ } + } + } + +-- +2.47.0 + diff --git a/0030-clang-tidy-remove-pointless-casts.patch b/0030-clang-tidy-remove-pointless-casts.patch new file mode 100644 index 0000000..6dd2131 --- /dev/null +++ b/0030-clang-tidy-remove-pointless-casts.patch @@ -0,0 +1,37 @@ +From 13916f7e14a2e6270e40519aa2f59319136dad08 Mon Sep 17 00:00:00 2001 +From: Rosen Penev <rosenp@gmail.com> +Date: Sun, 30 Jun 2024 17:16:30 -0700 +Subject: [PATCH 30/44] clang-tidy: remove pointless casts + +Found with readability-redundant-casting + +Signed-off-by: Rosen Penev <rosenp@gmail.com> +--- + cputree.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/cputree.c b/cputree.c +index 6c7b3b4..4820bdf 100644 +--- a/cputree.c ++++ b/cputree.c +@@ -271,7 +271,7 @@ static struct topo_obj* add_cpu_to_cache_domain(struct topo_obj *cpu, + entry = g_list_find(cache->children, cpu); + if (!entry) { + cache->children = g_list_append(cache->children, cpu); +- cpu->parent = (struct topo_obj *)cache; ++ cpu->parent = cache; + } + + if (!numa_avail || (nodeid > NUMA_NO_NODE)) +@@ -441,7 +441,7 @@ static void dump_numa_node_num(struct topo_obj *p, void *data __attribute__((unu + + static void dump_balance_obj(struct topo_obj *d, void *data __attribute__((unused))) + { +- struct topo_obj *c = (struct topo_obj *)d; ++ struct topo_obj *c = d; + log(TO_CONSOLE, LOG_INFO, "%s%s%s%sCPU number %i numa_node is ", + log_indent, log_indent, log_indent, log_indent, c->number); + for_each_object(cpu_numa_node(c), dump_numa_node_num, NULL); +-- +2.47.0 + diff --git a/0031-use-g_malloc-and-friends.patch b/0031-use-g_malloc-and-friends.patch new file mode 100644 index 0000000..0ec328e --- /dev/null +++ b/0031-use-g_malloc-and-friends.patch @@ -0,0 +1,314 @@ +From a7cfbeb0a6609dd56507c129ea2163816c4a4a5f Mon Sep 17 00:00:00 2001 +From: Rosen Penev <rosenp@gmail.com> +Date: Sun, 30 Jun 2024 16:49:20 -0700 +Subject: [PATCH 31/44] use g_malloc and friends + +These should not fail. There are no null checks. + +Signed-off-by: Rosen Penev <rosenp@gmail.com> +--- + irqbalance.c | 4 ++-- + ui/helpers.c | 6 ++--- + ui/irqbalance-ui.c | 57 ++++++++++++++++++++-------------------------- + ui/ui.c | 17 +++++++------- + 4 files changed, 38 insertions(+), 46 deletions(-) + +diff --git a/irqbalance.c b/irqbalance.c +index dfd5d2d..3875d5d 100644 +--- a/irqbalance.c ++++ b/irqbalance.c +@@ -409,7 +409,7 @@ gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attri + struct msghdr msg = { + .msg_iov = &iov, + .msg_iovlen = 1, +- .msg_control = malloc(CMSG_SPACE(sizeof(struct ucred))), ++ .msg_control = g_malloc(CMSG_SPACE(sizeof(struct ucred))), + .msg_controllen = CMSG_SPACE(sizeof(struct ucred)), + }; + +@@ -540,7 +540,7 @@ out_close: + } + + out: +- free(msg.msg_control); ++ g_free(msg.msg_control); + return TRUE; + } + +diff --git a/ui/helpers.c b/ui/helpers.c +index 3b4c51f..529b1b3 100644 +--- a/ui/helpers.c ++++ b/ui/helpers.c +@@ -73,7 +73,7 @@ char * hex_to_bitmap(char hex_digit) { + return "0000\0"; + } + +- char *bitmap = malloc(5 * sizeof(char)); ++ char *bitmap = g_malloc_n(5, sizeof(char)); + bitmap[4] = '\0'; + int i; + for(i = 3; i >= 0; i--) { +@@ -86,7 +86,7 @@ char * hex_to_bitmap(char hex_digit) { + gpointer copy_cpu_ban(gconstpointer src, gpointer data __attribute__((unused))) + { + cpu_ban_t *old = (cpu_ban_t *)src; +- cpu_ban_t *new = malloc(sizeof(cpu_ban_t)); ++ cpu_ban_t *new = g_malloc(sizeof(cpu_ban_t)); + new->number = old->number; + new->is_banned = old->is_banned; + new->is_changed = 0; +@@ -96,7 +96,7 @@ gpointer copy_cpu_ban(gconstpointer src, gpointer data __attribute__((unused))) + gpointer copy_irq(gconstpointer src, gpointer data __attribute__((unused))) + { + irq_t *old = (irq_t *)src; +- irq_t *new = malloc(sizeof(irq_t)); ++ irq_t *new = g_malloc(sizeof(irq_t)); + new->vector = old->vector; + new->load = old->load; + new->diff = old->diff; +diff --git a/ui/irqbalance-ui.c b/ui/irqbalance-ui.c +index 2e6b7d3..9bb76fd 100644 +--- a/ui/irqbalance-ui.c ++++ b/ui/irqbalance-ui.c +@@ -30,15 +30,14 @@ static int default_bufsz = 8192; + + struct msghdr * create_credentials_msg(void) + { +- struct ucred *credentials = malloc(sizeof(struct ucred)); ++ struct ucred *credentials = g_malloc(sizeof(struct ucred)); + credentials->pid = getpid(); + credentials->uid = geteuid(); + credentials->gid = getegid(); + +- struct msghdr *msg = malloc(sizeof(struct msghdr)); +- memset(msg, 0, sizeof(struct msghdr)); ++ struct msghdr *msg = g_malloc0(sizeof(struct msghdr)); + msg->msg_iovlen = 1; +- msg->msg_control = malloc(CMSG_SPACE(sizeof(struct ucred))); ++ msg->msg_control = g_malloc(CMSG_SPACE(sizeof(struct ucred))); + msg->msg_controllen = CMSG_SPACE(sizeof(struct ucred)); + + struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg); +@@ -47,7 +46,7 @@ struct msghdr * create_credentials_msg(void) + cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred)); + memcpy(CMSG_DATA(cmsg), credentials, sizeof(struct ucred)); + +- free(credentials); ++ g_free(credentials); + return msg; + } + +@@ -100,8 +99,8 @@ void send_settings(char *data) + sendmsg(socket_fd, msg, 0); + + close(socket_fd); +- free(msg->msg_control); +- free(msg); ++ g_free(msg->msg_control); ++ g_free(msg); + } + + char * get_data(char *string) +@@ -125,20 +124,20 @@ try_again: + msg->msg_iov = &iov; + sendmsg(socket_fd, msg, 0); + +- char *data = malloc(default_bufsz); ++ char *data = g_malloc(default_bufsz); + int len = recv(socket_fd, data, default_bufsz, MSG_TRUNC); + close(socket_fd); +- free(msg->msg_control); +- free(msg); ++ g_free(msg->msg_control); ++ g_free(msg); + if (len < 0) { +- free(data); ++ g_free(data); + return NULL; + } + data[len] = '\0'; + if (len >= default_bufsz) { + /* msg was truncated, increase bufsz and try again */ + default_bufsz += 8192; +- free(data); ++ g_free(data); + goto try_again; + } + return data; +@@ -163,7 +162,7 @@ void parse_setup(char *setup_data) + token = strtok_r(NULL, " ", &ptr); + /* Parse banned IRQ data */ + while(!strncmp(token, "IRQ", strlen("IRQ"))) { +- new_irq = malloc(sizeof(irq_t)); ++ new_irq = g_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")) != 0) goto out; +@@ -189,26 +188,24 @@ void parse_setup(char *setup_data) + 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)); ++ uint64_t *banned_cpu = g_malloc(sizeof(uint64_t)); + *banned_cpu = cpu; + setup.banned_cpus = g_list_append(setup.banned_cpus, + banned_cpu); + } + cpu++; + } +- free(map); ++ g_free(map); + + } +- free(copy); ++ g_free(copy); + return; + + out: { + /* Invalid data presented */ + printf("Invalid data sent. Unexpected token: %s", token); +- if (new_irq) { +- free(new_irq); +- } +- free(copy); ++ g_free(new_irq); ++ g_free(copy); + g_list_free(tree); + exit(1); + } +@@ -252,7 +249,7 @@ void assign_cpu_lists(cpu_node_t *node, void *data __attribute__((unused))) + + void assign_cpu_mask(cpu_node_t *node, void *data __attribute__((unused))) + { +- char *mask = malloc(16 * sizeof(char)); ++ char *mask = g_malloc_n(16, sizeof(char)); + mask[0] = '\0'; + unsigned int sum = 0; + GList *list_entry = g_list_first(node->cpu_list); +@@ -281,7 +278,7 @@ void parse_into_tree(char *data) + if (!data || strlen(data) == 0) + return; + +- copy = strdup(data); ++ copy = g_strdup(data); + if (!copy) + return; + +@@ -289,8 +286,8 @@ void parse_into_tree(char *data) + while(token != NULL) { + /* Parse node data */ + if(strncmp(token, "TYPE", strlen("TYPE")) != 0) { +- free(copy); +- goto out; ++ g_free(copy); ++ goto out; + } + new = g_malloc0(sizeof(cpu_node_t)); + new->type = strtol(strtok_r(NULL, " ", &ptr), NULL, 10); +@@ -312,7 +309,7 @@ void parse_into_tree(char *data) + + /* Parse assigned IRQ data */ + while((token != NULL) && (!strncmp(token, "IRQ", strlen("IRQ")))) { +- new_irq = malloc(sizeof(irq_t)); ++ new_irq = g_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")) != 0) goto out; +@@ -343,7 +340,7 @@ void parse_into_tree(char *data) + + new = NULL; + } +- free(copy); ++ g_free(copy); + for_each_node(tree, assign_cpu_lists, NULL); + for_each_node(tree, assign_cpu_mask, NULL); + return; +@@ -351,12 +348,8 @@ 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_free(new_irq); ++ g_free(new); + g_list_free(tree); + exit(1); + } +diff --git a/ui/ui.c b/ui/ui.c +index 5401d02..be5df5e 100644 +--- a/ui/ui.c ++++ b/ui/ui.c +@@ -51,7 +51,7 @@ void show_footer(void) + + char * check_control_in_sleep_input(int max_len, int column_offest, int line_offset) + { +- char *input_to = malloc(max_len * sizeof(char)); ++ char *input_to = g_malloc_n(max_len, sizeof(char)); + int iteration = 0; + while(iteration < max_len) { + int new = getch(); +@@ -76,7 +76,7 @@ char * check_control_in_sleep_input(int max_len, int column_offest, int line_off + attrset(COLOR_PAIR(5) | A_REVERSE | A_BOLD); + break; + case 27: +- free(input_to); ++ g_free(input_to); + return NULL; + default: + input_to[iteration] = new; +@@ -112,7 +112,7 @@ int get_valid_sleep_input(int column_offest) + char *error; + new_sleep = strtol(input, &error, 10); + if((*error == '\0') && (new_sleep >= 1)) { +- free(input); ++ g_free(input); + break; + } + new_sleep = setup.sleep; +@@ -121,7 +121,7 @@ int get_valid_sleep_input(int column_offest) + "Invalid input: %s ", + input); + refresh(); +- free(input); ++ g_free(input); + } + + attrset(COLOR_PAIR(1)); +@@ -132,7 +132,7 @@ int get_valid_sleep_input(int column_offest) + + void get_banned_cpu(int *cpu, char *data __attribute__((unused))) + { +- cpu_ban_t *new = malloc(sizeof(cpu_ban_t)); ++ cpu_ban_t *new = g_malloc(sizeof(cpu_ban_t)); + new->number = *cpu; + new->is_banned = 1; + all_cpus = g_list_append(all_cpus, new); +@@ -237,7 +237,7 @@ void get_new_cpu_ban_values(cpu_ban_t *cpu, void *data) + void get_cpu(cpu_node_t *node, void *data __attribute__((unused))) + { + if(node->type == OBJ_TYPE_CPU) { +- cpu_ban_t *new = malloc(sizeof(cpu_ban_t)); ++ cpu_ban_t *new = g_malloc(sizeof(cpu_ban_t)); + new->number = node->number; + new->is_banned = 0; + all_cpus = g_list_append(all_cpus, new); +@@ -402,10 +402,9 @@ void get_irq_name(int end) + char buffer[128]; + + if (irq_name == NULL) { +- irq_name = malloc(sizeof(char *) * LINES); ++ irq_name = g_malloc_n(LINES, sizeof(char *)); + for (i = 4; i < LINES; i++) { +- irq_name[i] = malloc(sizeof(char) * 50); +- memset(irq_name[i], 0, sizeof(char) * 50); ++ irq_name[i] = g_malloc0_n(50, sizeof(char)); + } + } + +-- +2.47.0 + diff --git a/0032-remove-malloc-from-ucred.patch b/0032-remove-malloc-from-ucred.patch new file mode 100644 index 0000000..e84ac44 --- /dev/null +++ b/0032-remove-malloc-from-ucred.patch @@ -0,0 +1,46 @@ +From 7622883bad5b75d28d8e1cb3a2c48b9589aa82b4 Mon Sep 17 00:00:00 2001 +From: Rosen Penev <rosenp@gmail.com> +Date: Thu, 4 Jul 2024 13:54:12 -0700 +Subject: [PATCH 32/44] remove malloc from ucred + +This just gets freed at the end after getting copied. + +Signed-off-by: Rosen Penev <rosenp@gmail.com> +--- + ui/irqbalance-ui.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +diff --git a/ui/irqbalance-ui.c b/ui/irqbalance-ui.c +index 9bb76fd..d281f47 100644 +--- a/ui/irqbalance-ui.c ++++ b/ui/irqbalance-ui.c +@@ -30,10 +30,11 @@ static int default_bufsz = 8192; + + struct msghdr * create_credentials_msg(void) + { +- struct ucred *credentials = g_malloc(sizeof(struct ucred)); +- credentials->pid = getpid(); +- credentials->uid = geteuid(); +- credentials->gid = getegid(); ++ struct ucred credentials = { ++ .pid = getpid(), ++ .uid = geteuid(), ++ .gid = getegid(), ++ }; + + struct msghdr *msg = g_malloc0(sizeof(struct msghdr)); + msg->msg_iovlen = 1; +@@ -44,9 +45,7 @@ struct msghdr * create_credentials_msg(void) + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_CREDENTIALS; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred)); +- memcpy(CMSG_DATA(cmsg), credentials, sizeof(struct ucred)); +- +- g_free(credentials); ++ memcpy(CMSG_DATA(cmsg), &credentials, sizeof(struct ucred)); + return msg; + } + +-- +2.47.0 + diff --git a/0033-gcc-analyzer-add-NULL-checks.patch b/0033-gcc-analyzer-add-NULL-checks.patch new file mode 100644 index 0000000..f2049c6 --- /dev/null +++ b/0033-gcc-analyzer-add-NULL-checks.patch @@ -0,0 +1,42 @@ +From e39848bfe45ea580bc0fd3b966a4199fb2fcd5b8 Mon Sep 17 00:00:00 2001 +From: Rosen Penev <rosenp@gmail.com> +Date: Thu, 4 Jul 2024 14:13:54 -0700 +Subject: [PATCH 33/44] gcc analyzer: add NULL checks + +Found with -Wanalyzer-null-argument + +Signed-off-by: Rosen Penev <rosenp@gmail.com> +--- + irqbalance.c | 2 +- + ui/ui.c | 2 ++ + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/irqbalance.c b/irqbalance.c +index 3875d5d..0b77376 100644 +--- a/irqbalance.c ++++ b/irqbalance.c +@@ -503,7 +503,7 @@ gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attri + recv_size - strlen("settings cpus ")); + cpu_ban_string[recv_size - strlen("settings cpus ")] = '\0'; + banned_cpumask_from_ui = strtok(cpu_ban_string, " "); +- if (!strncmp(banned_cpumask_from_ui, "NULL", strlen("NULL"))) { ++ if (banned_cpumask_from_ui && !strncmp(banned_cpumask_from_ui, "NULL", strlen("NULL"))) { + banned_cpumask_from_ui = NULL; + free(cpu_ban_string); + cpu_ban_string = NULL; +diff --git a/ui/ui.c b/ui/ui.c +index be5df5e..8d7c493 100644 +--- a/ui/ui.c ++++ b/ui/ui.c +@@ -418,6 +418,8 @@ void get_irq_name(int end) + cmd = alloca(sizeof(char) * (len + 1)); + snprintf(cmd, len + 1, "cat /proc/interrupts | awk '{for (i=%d;i<=NF;i++)printf(\"%%s \", $i);print \"\"}' | cut -c-49", cpunr + 2); + output = popen(cmd, "r"); ++ if (!output) ++ return; + for (i = 0; i <= offset; i++) + fgets(buffer, 50, output); + for (i = 4; i < end; i++) +-- +2.47.0 + diff --git a/0034-gcc-analyzer-increase-socket_name-size.patch b/0034-gcc-analyzer-increase-socket_name-size.patch new file mode 100644 index 0000000..48de8ec --- /dev/null +++ b/0034-gcc-analyzer-increase-socket_name-size.patch @@ -0,0 +1,30 @@ +From 4d537284c8d272cf05a64ee8ba226dd54c496a55 Mon Sep 17 00:00:00 2001 +From: Rosen Penev <rosenp@gmail.com> +Date: Thu, 4 Jul 2024 14:24:30 -0700 +Subject: [PATCH 34/44] gcc analyzer: increase socket_name size + +Now matches sun_path size. + +Found with -Wanalyzer-out-of-bounds + +Signed-off-by: Rosen Penev <rosenp@gmail.com> +--- + irqbalance.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/irqbalance.c b/irqbalance.c +index 0b77376..4f3b97d 100644 +--- a/irqbalance.c ++++ b/irqbalance.c +@@ -70,7 +70,7 @@ unsigned long migrate_ratio = 0; + + #ifdef HAVE_IRQBALANCEUI + int socket_fd; +-char socket_name[64]; ++char socket_name[108]; + char *banned_cpumask_from_ui = NULL; + #endif + +-- +2.47.0 + diff --git a/0035-use-g_strdup_printf.patch b/0035-use-g_strdup_printf.patch new file mode 100644 index 0000000..37d6a4d --- /dev/null +++ b/0035-use-g_strdup_printf.patch @@ -0,0 +1,66 @@ +From 434180846db9b1516e1533664b56a253800f88aa Mon Sep 17 00:00:00 2001 +From: Rosen Penev <rosenp@gmail.com> +Date: Thu, 4 Jul 2024 16:11:10 -0700 +Subject: [PATCH 35/44] use g_strdup_printf + +Simplifies the code. + +Signed-off-by: Rosen Penev <rosenp@gmail.com> +--- + ui/ui.c | 15 +++++++-------- + 1 file changed, 7 insertions(+), 8 deletions(-) + +diff --git a/ui/ui.c b/ui/ui.c +index 8d7c493..752744a 100644 +--- a/ui/ui.c ++++ b/ui/ui.c +@@ -396,7 +396,7 @@ void print_assigned_objects_string(irq_t *irq, int *line_offset) + + void get_irq_name(int end) + { +- int i, cpunr, len; ++ int i, cpunr; + FILE *output; + char *cmd; + char buffer[128]; +@@ -414,10 +414,9 @@ void get_irq_name(int end) + fscanf(output, "%d", &cpunr); + pclose(output); + +- len = snprintf(NULL, 0, "cat /proc/interrupts | awk '{for (i=%d;i<=NF;i++)printf(\"%%s \", $i);print \"\"}' | cut -c-49", cpunr + 2); +- cmd = alloca(sizeof(char) * (len + 1)); +- snprintf(cmd, len + 1, "cat /proc/interrupts | awk '{for (i=%d;i<=NF;i++)printf(\"%%s \", $i);print \"\"}' | cut -c-49", cpunr + 2); ++ cmd = g_strdup_printf("cat /proc/interrupts | awk '{for (i=%d;i<=NF;i++)printf(\"%%s \", $i);print \"\"}' | cut -c-49", cpunr + 2); + output = popen(cmd, "r"); ++ g_free(cmd); + if (!output) + return; + for (i = 0; i <= offset; i++) +@@ -683,9 +682,9 @@ void handle_sleep_setting(void) + 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); ++ char *settings_data = g_strdup_printf("%s %" PRIu64, SET_SLEEP, new_sleep); + send_settings(settings_data); ++ g_free(settings_data); + } + attrset(COLOR_PAIR(5)); + mvprintw(LINES - 2, 1, "Press <S> for changing sleep setup, <C> for CPU ban setup. "); +@@ -739,10 +738,10 @@ void settings(void) + char *setup_data = get_data(SETUP); + parse_setup(setup_data); + +- char info[128] = "Current sleep interval between rebalancing: \0"; +- snprintf(info + strlen(info), 128 - strlen(info), "%" PRIu64 "\n", setup.sleep); ++ char *info = g_strdup_printf("Current sleep interval between rebalancing: %" PRIu64 "\n", setup.sleep); + attrset(COLOR_PAIR(1)); + mvprintw(2, 3, "%s", info); ++ g_free(info); + print_all_cpus(); + attrset(COLOR_PAIR(5)); + mvprintw(LINES - 2, 1, "Press <S> for changing sleep setup, <C> for CPU ban setup. "); +-- +2.47.0 + diff --git a/0036-avoid-malloc-with-create_credentials_msg.patch b/0036-avoid-malloc-with-create_credentials_msg.patch new file mode 100644 index 0000000..9ceff7b --- /dev/null +++ b/0036-avoid-malloc-with-create_credentials_msg.patch @@ -0,0 +1,111 @@ +From 6f9f9e9556db8d4ec5dc5f662a5fb13167dfa111 Mon Sep 17 00:00:00 2001 +From: Rosen Penev <rosenp@gmail.com> +Date: Sun, 7 Jul 2024 18:02:12 -0700 +Subject: [PATCH 36/44] avoid malloc with create_credentials_msg + +Not really needed. + +Signed-off-by: Rosen Penev <rosenp@gmail.com> +--- + ui/irqbalance-ui.c | 39 ++++++++++++++++++++------------------- + ui/irqbalance-ui.h | 2 +- + 2 files changed, 21 insertions(+), 20 deletions(-) + +diff --git a/ui/irqbalance-ui.c b/ui/irqbalance-ui.c +index d281f47..f4cc48f 100644 +--- a/ui/irqbalance-ui.c ++++ b/ui/irqbalance-ui.c +@@ -28,7 +28,7 @@ setup_t setup; + GMainLoop *main_loop; + static int default_bufsz = 8192; + +-struct msghdr * create_credentials_msg(void) ++struct msghdr create_credentials_msg(void) + { + struct ucred credentials = { + .pid = getpid(), +@@ -36,12 +36,13 @@ struct msghdr * create_credentials_msg(void) + .gid = getegid(), + }; + +- struct msghdr *msg = g_malloc0(sizeof(struct msghdr)); +- msg->msg_iovlen = 1; +- msg->msg_control = g_malloc(CMSG_SPACE(sizeof(struct ucred))); +- msg->msg_controllen = CMSG_SPACE(sizeof(struct ucred)); ++ struct msghdr msg = { ++ .msg_iovlen = 1, ++ .msg_control = g_malloc(CMSG_SPACE(sizeof(struct ucred))), ++ .msg_controllen = CMSG_SPACE(sizeof(struct ucred)), ++ }; + +- struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg); ++ struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_CREDENTIALS; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred)); +@@ -90,16 +91,17 @@ void send_settings(char *data) + return; + } + +- struct msghdr *msg = create_credentials_msg(); +- struct iovec iov; +- iov.iov_base = (void *) data; +- iov.iov_len = strlen(data); +- msg->msg_iov = &iov; +- sendmsg(socket_fd, msg, 0); ++ struct iovec iov = { ++ .iov_base = (void *) data, ++ .iov_len = strlen(data), ++ }; ++ ++ struct msghdr msg = create_credentials_msg(); ++ msg.msg_iov = &iov; ++ sendmsg(socket_fd, &msg, 0); + + close(socket_fd); +- g_free(msg->msg_control); +- g_free(msg); ++ g_free(msg.msg_control); + } + + char * get_data(char *string) +@@ -115,19 +117,18 @@ try_again: + return NULL; + } + +- struct msghdr *msg = create_credentials_msg(); ++ struct msghdr msg = create_credentials_msg(); + struct iovec iov = { + .iov_base = (void *) string, + .iov_len = strlen(string), + }; +- msg->msg_iov = &iov; +- sendmsg(socket_fd, msg, 0); ++ msg.msg_iov = &iov; ++ sendmsg(socket_fd, &msg, 0); + + char *data = g_malloc(default_bufsz); + int len = recv(socket_fd, data, default_bufsz, MSG_TRUNC); + close(socket_fd); +- g_free(msg->msg_control); +- g_free(msg); ++ g_free(msg.msg_control); + if (len < 0) { + g_free(data); + return NULL; +diff --git a/ui/irqbalance-ui.h b/ui/irqbalance-ui.h +index 178be4b..4a2982d 100644 +--- a/ui/irqbalance-ui.h ++++ b/ui/irqbalance-ui.h +@@ -72,7 +72,7 @@ typedef struct setup { + + /* Function prototypes */ + +-struct msghdr * create_credentials_msg(void); ++struct msghdr create_credentials_msg(void); + int init_connection(void); + void send_settings(char *data); + char * get_data(char *string); +-- +2.47.0 + diff --git a/0037-conver-strncmp-to-g_str_has_prefix.patch b/0037-conver-strncmp-to-g_str_has_prefix.patch new file mode 100644 index 0000000..052158a --- /dev/null +++ b/0037-conver-strncmp-to-g_str_has_prefix.patch @@ -0,0 +1,268 @@ +From da75aae4effd6bc276bb1b882d68617cd02aa8e0 Mon Sep 17 00:00:00 2001 +From: Rosen Penev <rosenp@gmail.com> +Date: Sun, 7 Jul 2024 17:17:33 -0700 +Subject: [PATCH 37/44] conver strncmp to g_str_has_prefix + +Avoids implicit bool conversions. + +Signed-off-by: Rosen Penev <rosenp@gmail.com> +--- + cputree.c | 2 +- + irqbalance.c | 21 +++++++++------------ + numa.c | 2 +- + procinterrupts.c | 6 +++--- + ui/irqbalance-ui.c | 30 +++++++++++++++--------------- + ui/ui.c | 6 +++--- + 6 files changed, 32 insertions(+), 35 deletions(-) + +diff --git a/cputree.c b/cputree.c +index 4820bdf..49b2f37 100644 +--- a/cputree.c ++++ b/cputree.c +@@ -380,7 +380,7 @@ static void do_one_cpu(char *path) + entry = readdir(dir); + if (!entry) + break; +- if (strncmp(entry->d_name, "node", 4) == 0) { ++ if (g_str_has_prefix(entry->d_name, "node")) { + char *end; + int num; + num = strtol(entry->d_name + 4, &end, 10); +diff --git a/irqbalance.c b/irqbalance.c +index 4f3b97d..491a912 100644 +--- a/irqbalance.c ++++ b/irqbalance.c +@@ -154,7 +154,7 @@ static void parse_command_line(int argc, char **argv) + add_cl_banned_module(optarg); + break; + case 'p': +- if (!strncmp(optarg, "off", strlen(optarg))) ++ if (g_str_has_prefix(optarg, "off")) + power_thresh = ULONG_MAX; + else { + power_thresh = strtoull(optarg, &endptr, 10); +@@ -443,15 +443,14 @@ gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attri + goto out_close; + } + +- if (!strncmp(buff, "stats", strlen("stats"))) { ++ if (g_str_has_prefix(buff, "stats")) { + char *stats = NULL; + for_each_object(numa_nodes, get_object_stat, &stats); + send(sock, stats, strlen(stats), 0); + free(stats); + } +- if (!strncmp(buff, "settings ", strlen("settings "))) { +- if (!(strncmp(buff + strlen("settings "), "sleep ", +- strlen("sleep ")))) { ++ if (g_str_has_prefix(buff, "settings ")) { ++ if (g_str_has_prefix(buff + strlen("settings "), "sleep ")) { + char *sleep_string = malloc( + sizeof(char) * (recv_size - strlen("settings sleep ") + 1)); + +@@ -465,8 +464,7 @@ gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attri + sleep_interval = new_iterval; + } + free(sleep_string); +- } else if (!(strncmp(buff + strlen("settings "), "ban irqs ", +- strlen("ban irqs ")))) { ++ } else if (g_str_has_prefix(buff + strlen("settings "), "ban irqs ")) { + char *end; + char *irq_string = malloc( + sizeof(char) * (recv_size - strlen("settings ban irqs ") + 1)); +@@ -479,7 +477,7 @@ gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attri + g_list_free_full(cl_banned_irqs, free); + cl_banned_irqs = NULL; + need_rescan = 1; +- if (!strncmp(irq_string, "NONE", strlen("NONE"))) { ++ if (g_str_has_prefix(irq_string, "NONE")) { + free(irq_string); + goto out_close; + } +@@ -488,8 +486,7 @@ gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attri + add_cl_banned_irq(irq); + } while((irq = strtoul(end, &end, 10))); + free(irq_string); +- } else if (!(strncmp(buff + strlen("settings "), "cpus ", +- strlen("cpus")))) { ++ } else if (g_str_has_prefix(buff + strlen("settings "), "cpus ")) { + banned_cpumask_from_ui = NULL; + free(cpu_ban_string); + cpu_ban_string = NULL; +@@ -503,7 +500,7 @@ gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attri + recv_size - strlen("settings cpus ")); + cpu_ban_string[recv_size - strlen("settings cpus ")] = '\0'; + banned_cpumask_from_ui = strtok(cpu_ban_string, " "); +- if (banned_cpumask_from_ui && !strncmp(banned_cpumask_from_ui, "NULL", strlen("NULL"))) { ++ if (banned_cpumask_from_ui && g_str_has_prefix(banned_cpumask_from_ui, "NULL")) { + banned_cpumask_from_ui = NULL; + free(cpu_ban_string); + cpu_ban_string = NULL; +@@ -511,7 +508,7 @@ gboolean sock_handle(gint fd, GIOCondition condition, gpointer user_data __attri + need_rescan = 1; + } + } +- if (!strncmp(buff, "setup", strlen("setup"))) { ++ if (g_str_has_prefix(buff, "setup")) { + char banned[512]; + char *setup = calloc(strlen("SLEEP ") + 11 + 1, 1); + char *newptr = NULL; +diff --git a/numa.c b/numa.c +index 5143ea0..a79f16e 100644 +--- a/numa.c ++++ b/numa.c +@@ -84,7 +84,7 @@ void build_numa_node_list(void) + if (!entry) + break; + if ((entry->d_type == DT_DIR) && +- (strncmp(entry->d_name, "node", 4) == 0) && ++ g_str_has_prefix(entry->d_name, "node") && + isdigit(entry->d_name[4])) { + add_one_node(strtoul(&entry->d_name[4], NULL, 10)); + } +diff --git a/procinterrupts.c b/procinterrupts.c +index e7ba653..4d04bf2 100644 +--- a/procinterrupts.c ++++ b/procinterrupts.c +@@ -85,7 +85,7 @@ static int check_platform_device(char *name, struct irq_info *info) + + log(TO_ALL, LOG_DEBUG, "Checking entry %s\n", ent->d_name); + for (i = 0; pdev_irq_info[i].d_name != NULL; i++) { +- if (!strncmp(ent->d_name, pdev_irq_info[i].d_name, strlen(pdev_irq_info[i].d_name))) { ++ if (g_str_has_prefix(ent->d_name, pdev_irq_info[i].d_name)) { + info->type = pdev_irq_info[i].type; + info->class = pdev_irq_info[i].class; + rc = 0; +@@ -171,8 +171,8 @@ void init_irq_class_and_type(char *savedline, struct irq_info *info, int irq) + * /proc/interrupts format defined, after of interrupt type + * the reset string is mark the irq desc name. + */ +- if (strncmp(irq_name, "Level", strlen("Level")) == 0 || +- strncmp(irq_name, "Edge", strlen("Edge")) == 0) ++ if (!g_str_has_prefix(irq_name, "Level") || ++ !g_str_has_prefix(irq_name, "Edge")) + break; + #endif + } +diff --git a/ui/irqbalance-ui.c b/ui/irqbalance-ui.c +index f4cc48f..4a6832a 100644 +--- a/ui/irqbalance-ui.c ++++ b/ui/irqbalance-ui.c +@@ -157,21 +157,21 @@ void parse_setup(char *setup_data) + setup.banned_irqs = NULL; + setup.banned_cpus = NULL; + token = strtok_r(copy, " ", &ptr); +- if(strncmp(token, "SLEEP", strlen("SLEEP")) != 0) goto out; ++ if(!g_str_has_prefix(token, "SLEEP")) goto out; + setup.sleep = strtol(strtok_r(NULL, " ", &ptr), NULL, 10); + token = strtok_r(NULL, " ", &ptr); + /* Parse banned IRQ data */ +- while(!strncmp(token, "IRQ", strlen("IRQ"))) { ++ while(g_str_has_prefix(token, "IRQ")) { + new_irq = g_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")) != 0) goto out; ++ if(!g_str_has_prefix(token, "LOAD")) goto out; + new_irq->load = strtol(strtok_r(NULL, " ", &ptr), NULL, 10); + token = strtok_r(NULL, " ", &ptr); +- if(strncmp(token, "DIFF", strlen("DIFF")) != 0) goto out; ++ if(!g_str_has_prefix(token, "DIFF")) goto out; + new_irq->diff = strtol(strtok_r(NULL, " ", &ptr), NULL, 10); + token = strtok_r(ptr, " ", &ptr); +- if(strncmp(token, "CLASS", strlen("CLASS")) != 0) goto out; ++ if(!g_str_has_prefix(token, "CLASS")) goto out; + new_irq->class = strtol(strtok_r(NULL, " ", &ptr), NULL, 10); + new_irq->is_banned = 1; + new_irq->assigned_to = NULL; +@@ -180,7 +180,7 @@ void parse_setup(char *setup_data) + new_irq = NULL; + } + +- if(strncmp(token, "BANNED", strlen("BANNED")) != 0) goto out; ++ if(!g_str_has_prefix(token, "BANNED")) goto out; + token = strtok_r(NULL, " ", &ptr); + for(i = strlen(token) - 1; i >= 0; i--) { + if (token[i] == ',') +@@ -285,7 +285,7 @@ void parse_into_tree(char *data) + token = strtok_r(copy, " ", &ptr); + while(token != NULL) { + /* Parse node data */ +- if(strncmp(token, "TYPE", strlen("TYPE")) != 0) { ++ if(!g_str_has_prefix(token, "TYPE")) { + g_free(copy); + goto out; + } +@@ -297,28 +297,28 @@ void parse_into_tree(char *data) + parent = parent->parent; + } + token = strtok_r(NULL, " ", &ptr); +- if(strncmp(token, "NUMBER", strlen("NUMBER")) != 0) goto out; ++ if(!g_str_has_prefix(token, "NUMBER")) goto out; + new->number = strtol(strtok_r(NULL, " ", &ptr), NULL, 10); + token = strtok_r(NULL, " ", &ptr); +- if(strncmp(token, "LOAD", strlen("LOAD")) != 0) goto out; ++ if(!g_str_has_prefix(token, "LOAD")) goto out; + new->load = strtol(strtok_r(NULL, " ", &ptr), NULL, 10); + token = strtok_r(NULL, " ", &ptr); +- if(strncmp(token, "SAVE_MODE", strlen("SAVE_MODE")) != 0) goto out; ++ if(!g_str_has_prefix(token, "SAVE_MODE")) goto out; + new->is_powersave = strtol(strtok_r(NULL, " ", &ptr), NULL, 10); + token = strtok_r(NULL, " ", &ptr); + + /* Parse assigned IRQ data */ +- while((token != NULL) && (!strncmp(token, "IRQ", strlen("IRQ")))) { ++ while(token && g_str_has_prefix(token, "IRQ")) { + new_irq = g_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")) != 0) goto out; ++ if(!g_str_has_prefix(token, "LOAD")) goto out; + new_irq->load = strtol(strtok_r(NULL, " ", &ptr), NULL, 10); + token = strtok_r(NULL, " ", &ptr); +- if(strncmp(token, "DIFF", strlen("DIFF")) != 0) goto out; ++ if(!g_str_has_prefix(token, "DIFF")) goto out; + new_irq->diff = strtol(strtok_r(NULL, " ", &ptr), NULL, 10); + token = strtok_r(NULL, " ", &ptr); +- if(strncmp(token, "CLASS", strlen("CLASS")) != 0) goto out; ++ if(!g_str_has_prefix(token, "CLASS")) goto out; + new_irq->class = strtol(strtok_r(NULL, " ", &ptr), NULL, 10); + new_irq->is_banned = 0; + new->irqs = g_list_append(new->irqs, new_irq); +@@ -326,7 +326,7 @@ void parse_into_tree(char *data) + new_irq = NULL; + } + +- if((token == NULL) || (strncmp(token, "IRQ", strlen("IRQ")) != 0)) { ++ if(!token || !g_str_has_prefix(token, "IRQ")) { + new->parent = parent; + if(parent == NULL) { + tree = g_list_append(tree, new); +diff --git a/ui/ui.c b/ui/ui.c +index 752744a..8325bcd 100644 +--- a/ui/ui.c ++++ b/ui/ui.c +@@ -336,9 +336,9 @@ void handle_cpu_banning(void) + show_frame(); + show_footer(); + refresh(); +- char settings_string[1024] = "settings cpus \0"; ++ char settings_string[1024] = "settings cpus "; + for_each_cpu(all_cpus, get_new_cpu_ban_values, settings_string); +- if(!strcmp("settings cpus \0", settings_string)) { ++ if(g_str_has_prefix(settings_string, "settings cpus ")) { + strncpy(settings_string + strlen(settings_string), + "NULL", 1024 - strlen(settings_string)); + } +@@ -654,7 +654,7 @@ void handle_irq_banning(void) + refresh(); + char settings_string[1024] = BAN_IRQS; + for_each_irq(all_irqs, get_new_irq_ban_values, settings_string); +- if(!strcmp(BAN_IRQS, settings_string)) { ++ if(g_str_has_prefix(settings_string, BAN_IRQS)) { + strncpy(settings_string + strlen(settings_string), + " NONE", 1024 - strlen(settings_string)); + } +-- +2.47.0 + diff --git a/0038-define-IRQBALANCE_ARGS-as-empty-string-to-squelch-sy.patch b/0038-define-IRQBALANCE_ARGS-as-empty-string-to-squelch-sy.patch new file mode 100644 index 0000000..c44be8d --- /dev/null +++ b/0038-define-IRQBALANCE_ARGS-as-empty-string-to-squelch-sy.patch @@ -0,0 +1,23 @@ +From 42115bda75d9c49156a2799bc178ea105daf5003 Mon Sep 17 00:00:00 2001 +From: Cameron Baird <cameronbaird@microsoft.com> +Date: Wed, 10 Jul 2024 23:09:32 +0000 +Subject: [PATCH 38/44] define IRQBALANCE_ARGS as empty string to squelch + systemd warning + +--- + misc/irqbalance.env | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/misc/irqbalance.env b/misc/irqbalance.env +index 96acb39..84cb843 100644 +--- a/misc/irqbalance.env ++++ b/misc/irqbalance.env +@@ -41,4 +41,4 @@ + # Append any args here to the irqbalance daemon as documented in the man + # page. + # +-#IRQBALANCE_ARGS= ++IRQBALANCE_ARGS="" +-- +2.47.0 + diff --git a/0039-Minor-punctuation-fix.patch b/0039-Minor-punctuation-fix.patch new file mode 100644 index 0000000..238808e --- /dev/null +++ b/0039-Minor-punctuation-fix.patch @@ -0,0 +1,25 @@ +From 2860da404dea0fcfd404f56e546b90f8432176cf Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Torsten=20St=C3=B6ter?= <torsten.stoeter@lin-magdeburg.de> +Date: Fri, 12 Jul 2024 14:24:01 +0200 +Subject: [PATCH 39/44] Minor punctuation fix. + +--- + irqbalance.1 | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/irqbalance.1 b/irqbalance.1 +index 4c75362..a15fb63 100644 +--- a/irqbalance.1 ++++ b/irqbalance.1 +@@ -51,7 +51,7 @@ Enables log output optimized for systemd-journal. + + .TP + .B -p, --powerthresh=<threshold> +-Set the threshold at which we attempt to move a CPU into powersave mode ++Set the threshold at which we attempt to move a CPU into powersave mode. + If more than <threshold> CPUs are more than 1 standard deviation below the + average CPU softirq workload, and no CPUs are more than 1 standard deviation + above (and have more than 1 IRQ assigned to them), attempt to place 1 CPU in +-- +2.47.0 + diff --git a/0040-Version-option-should-return-0-rather-than-1.patch b/0040-Version-option-should-return-0-rather-than-1.patch new file mode 100644 index 0000000..7958a20 --- /dev/null +++ b/0040-Version-option-should-return-0-rather-than-1.patch @@ -0,0 +1,41 @@ +From 5d9eb1987ca8ae895bd2e2cf585954f50d3544ae Mon Sep 17 00:00:00 2001 +From: Tao Liu <ltao@redhat.com> +Date: Tue, 13 Aug 2024 10:30:56 +1200 +Subject: [PATCH 40/44] Version option should return 0 rather than 1 + +Previously invoke irqbalance with --version options, the return value +is 1 instead of 0: + +$ irqbalance --version +irqbalance version 1.9.4 +$ echo $? +1 + +It is unexpected because irqbalance have successfully returned the +version string with no errors, so 0 should be returned instead of 1. +This will confuse some automation tests. + +This patch will make irqbalance return the correct value for version +option. + +Signed-off-by: Tao Liu <ltao@redhat.com> +--- + irqbalance.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/irqbalance.c b/irqbalance.c +index 491a912..6422a7b 100644 +--- a/irqbalance.c ++++ b/irqbalance.c +@@ -122,7 +122,7 @@ static void parse_command_line(int argc, char **argv) + break; + case 'V': + version(); +- exit(1); ++ exit(0); + break; + case 'c': + deepest_cache = strtoul(optarg, &endptr, 10); +-- +2.47.0 + diff --git a/0041-Add-CAP_SETPCAP-to-CapabilityBoundingSet-in-irqbalan.patch b/0041-Add-CAP_SETPCAP-to-CapabilityBoundingSet-in-irqbalan.patch new file mode 100644 index 0000000..0d32619 --- /dev/null +++ b/0041-Add-CAP_SETPCAP-to-CapabilityBoundingSet-in-irqbalan.patch @@ -0,0 +1,46 @@ +From 196385b63d1e4ac1431f39f7b02978c969f4ff21 Mon Sep 17 00:00:00 2001 +From: Tao Liu <ltao@redhat.com> +Date: Tue, 20 Aug 2024 16:46:38 +1200 +Subject: [PATCH 41/44] Add CAP_SETPCAP to CapabilityBoundingSet in + irqbalance.service + +A error message of 'libcap-ng used by "/usr/sbin/irqbalance" failed dropping +bounding set due to not having CAP_SETPCAP in capng_apply' is noticed. + +Previously a similar issue[1] has been fixed by the following commit: + + efab272 Drop CapabilityBoundingSet from irqbalance service + 43751df drop NoNewPrivs from irqbalance service + +in which, CapabilityBoundingSet and NoNewPrivs parameters are dropped +from the irqbalance.service, and get restored by the following commit +later: + + a99b604 Set additional systemd options for service + +So this patch will not do the dropping again, but add CAP_SETPCAP to +CapabilityBoundingSet instead. + +[1]: https://github.com/Irqbalance/irqbalance/issues/182 + +Signed-off-by: Tao Liu <ltao@redhat.com> +--- + misc/irqbalance.service | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/misc/irqbalance.service b/misc/irqbalance.service +index b731cc6..7e0c5d8 100644 +--- a/misc/irqbalance.service ++++ b/misc/irqbalance.service +@@ -9,7 +9,7 @@ ConditionCPUs=>1 + EnvironmentFile=-/usr/lib/irqbalance/defaults.env + EnvironmentFile=-/path/to/irqbalance.env + ExecStart=/usr/sbin/irqbalance $IRQBALANCE_ARGS +-CapabilityBoundingSet= ++CapabilityBoundingSet=CAP_SETPCAP + NoNewPrivileges=yes + ProtectSystem=strict + ReadOnlyPaths=/ +-- +2.47.0 + diff --git a/0042-Check-info-moved-before-updating.patch b/0042-Check-info-moved-before-updating.patch new file mode 100644 index 0000000..7b63d6b --- /dev/null +++ b/0042-Check-info-moved-before-updating.patch @@ -0,0 +1,31 @@ +From 25fa38022bc349cd2d3fdb41fcdad6e7193a73a7 Mon Sep 17 00:00:00 2001 +From: lvgenggeng <lvgenggeng@uniontech.com> +Date: Tue, 3 Sep 2024 23:31:49 +0800 +Subject: [PATCH 42/44] Check info->moved before updating + +In migrate_irq(), the list will not be changed if info not found. + +Signed-off-by: lvgenggeng <lvgenggeng@uniontech.com> +--- + irqlist.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/irqlist.c b/irqlist.c +index 9483a11..5ad2faf 100644 +--- a/irqlist.c ++++ b/irqlist.c +@@ -210,6 +210,11 @@ void migrate_irq_obj(struct topo_obj *from, struct topo_obj *to, struct irq_info + to_list = to ? &to->interrupts : &rebalance_irq_list; + + migrate_irq(from_list, to_list, info); ++ /* ++ * only update list after info found ++ */ ++ if (!info->moved) ++ return; + + if (from) { + if (from->slots_left != INT_MAX) +-- +2.47.0 + diff --git a/0043-irqbalance.1-a-b-a-b-it-s-type-its-type.patch b/0043-irqbalance.1-a-b-a-b-it-s-type-its-type.patch new file mode 100644 index 0000000..a37da64 --- /dev/null +++ b/0043-irqbalance.1-a-b-a-b-it-s-type-its-type.patch @@ -0,0 +1,38 @@ +From 1489ae342e07f2537e60456d2c639f90fd2ec87f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=D0=BD=D0=B0=D0=B1?= <nabijaczleweli@nabijaczleweli.xyz> +Date: Wed, 2 Oct 2024 15:21:08 +0200 +Subject: [PATCH 43/44] irqbalance.1: a , b => a, b; it's type => its type + +--- + irqbalance.1 | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/irqbalance.1 b/irqbalance.1 +index a15fb63..05f7b48 100644 +--- a/irqbalance.1 ++++ b/irqbalance.1 +@@ -193,13 +193,13 @@ Forces a rescan of the available IRQs and system topology. + irqbalance is able to communicate via socket and return it's current assignment + tree and setup, as well as set new settings based on sent values. Socket is abstract, + with a name in form of +-.B irqbalance<PID>.sock +-, where <PID> is the process ID of irqbalance instance to communicate with. ++.BR irqbalance<PID>.sock , ++where <PID> is the process ID of irqbalance instance to communicate with. + Possible values to send: + .TP + .B stats + Retrieve assignment tree of IRQs to CPUs, in recursive manner. For each CPU node +-in tree, it's type, number, load and whether the save mode is active are sent. For ++in tree, its type, number, load and whether the save mode is active are sent. For + 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 +@@ -220,4 +220,3 @@ Based on chosen tools, ancillary message with credentials needs to be sent with + + .SH "HOMEPAGE" + https://github.com/Irqbalance/irqbalance +- +-- +2.47.0 + diff --git a/0044-Use-EPERM-instead-of-EIO-when-try-setting-irq-affini.patch b/0044-Use-EPERM-instead-of-EIO-when-try-setting-irq-affini.patch new file mode 100644 index 0000000..0afbe7f --- /dev/null +++ b/0044-Use-EPERM-instead-of-EIO-when-try-setting-irq-affini.patch @@ -0,0 +1,39 @@ +From 3685d33ea8b3fecb832efc646ac1d4ed3945ed71 Mon Sep 17 00:00:00 2001 +From: Tao Liu <ltao@redhat.com> +Date: Fri, 18 Oct 2024 11:25:44 +1300 +Subject: [PATCH 44/44] Use EPERM instead of EIO when try setting irq affinity + fails + +Kernel commit eb29369fa543e ("genirq/proc: Change the return value for +set affinity permission error") changed the error number from EIO to +EPERM when a specific irq failed to set affinity from userspace. + +In addition, users have complained about EIO is misleading when +setting affinity fails, however it just meaning "user cannot set +affinity", so EPERM is better for that. + +This patch will follow the kernel change, to unify the behaviour of +irqbalance from the kernels which have not integrated the kernel +commit mentioned above. + +Signed-off-by: Tao Liu <ltao@redhat.com> +--- + activate.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/activate.c b/activate.c +index 10ad57d..59a2fce 100644 +--- a/activate.c ++++ b/activate.c +@@ -95,6 +95,8 @@ static void activate_mapping(struct irq_info *info, void *data __attribute__((un + info->moved = 0; /*migration is done*/ + return; + error: ++ /* Use EPERM as the explaination for EIO */ ++ errsave = (errsave == EIO) ? EPERM : errsave; + log(TO_ALL, LOG_WARNING, + "Cannot change IRQ %i affinity: %s\n", + info->irq, strerror(errsave)); +-- +2.47.0 + diff --git a/irqbalance-1.9.0-environment-file-sysconfig.patch b/irqbalance-1.9.0-environment-file-sysconfig.patch index db997bc..0850e77 100644 --- a/irqbalance-1.9.0-environment-file-sysconfig.patch +++ b/irqbalance-1.9.0-environment-file-sysconfig.patch @@ -8,7 +8,7 @@ Subject: [PATCH] misc/irqbalance.service: Use sysconfig for EnvironmentFile 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/misc/irqbalance.service b/misc/irqbalance.service -index 0f79c3e..9bc63b6 100644 +index 7e0c5d8..9ac430f 100644 --- a/misc/irqbalance.service +++ b/misc/irqbalance.service @@ -6,8 +6,7 @@ ConditionVirtualization=!container @@ -19,7 +19,5 @@ index 0f79c3e..9bc63b6 100644 -EnvironmentFile=-/path/to/irqbalance.env +EnvironmentFile=-/etc/sysconfig/irqbalance ExecStart=/usr/sbin/irqbalance $IRQBALANCE_ARGS - CapabilityBoundingSet= + CapabilityBoundingSet=CAP_SETPCAP NoNewPrivileges=yes --- -2.37.1 diff --git a/irqbalance.spec b/irqbalance.spec index 4feb051..c367135 100644 --- a/irqbalance.spec +++ b/irqbalance.spec @@ -6,10 +6,53 @@ Summary: IRQ balancing daemon License: GPL-2.0-only URL: https://github.com/Irqbalance/irqbalance Source0: %{url}/archive/v%{version}/irqbalance-%{version}.tar.gz -Patch1: irqbalance-1.9.0-environment-file-sysconfig.patch -Patch2: 0001-irqbalance-ui-check-if-using-a-negative-index-of-buf.patch -Patch3: 0002-Check-fflush-return-value.patch -Patch4: 0003-Drop-ProtectKernelTunables.patch + +Patch2: 0001-irqbalance-ui-check-if-using-a-negative-index-of-buf.patch +Patch3: 0002-Check-fflush-return-value.patch +Patch4: 0003-fix-32-bit-formats.patch +Patch5: 0004-add-void-to-fix-strict-prototypes.patch +Patch6: 0005-cast-void-pointer-to-actual-type.patch +Patch7: 0006-meson-move-build-files-to-repository-root.patch +Patch8: 0007-meson-bump-project-version-to-1.9.4.patch +Patch9: 0008-meson-drop-redundant-install_man-options.patch +Patch10: 0009-meson-add-a-minimum-version-decorator.patch +Patch11: 0010-Drop-ProtectKernelTunables.patch +Patch12: 0011-meson-replace-generic-array-with-files.patch +Patch13: 0012-meson-use-find_library-for-numa.patch +Patch14: 0013-ui-change-void-to-char.patch +Patch15: 0014-clang-tidy-don-t-assign-in-if.patch +Patch16: 0015-clang-tidy-properly-use-strncmp.patch +Patch17: 0016-replace-malloc-with-g_malloc0.patch +Patch18: 0017-clang-tidy-don-t-use-else-after-return.patch +Patch19: 0018-clang-tidy-remove-return-in-void-functions.patch +Patch20: 0019-clang-tidy-remove-redundant-declarations.patch +Patch21: 0020-clang-tidy-remove-duplicate-include.patch +Patch22: 0021-CI-add-meson-CI.patch +Patch23: 0022-Wrap-migrate_irq-in-a-higher-level-utility-function.patch +Patch24: 0023-Track-IRQ-slots-count-per-CPU-to-avoid-overflowing.patch +Patch25: 0024-Disable-linking-to-curses-if-without-irqbalance-ui-i.patch +Patch26: 0025-Remove-extraneous-space-causing-with-systemd-not-be-.patch +Patch27: 0026-direct-initialize-msghdr-members.patch +Patch28: 0027-direct-initialize-iovec.patch +Patch29: 0028-clang-tidy-add-missing-free.patch +Patch30: 0029-clang-tidy-don-t-assign-in-if.patch +Patch31: 0030-clang-tidy-remove-pointless-casts.patch +Patch32: 0031-use-g_malloc-and-friends.patch +Patch33: 0032-remove-malloc-from-ucred.patch +Patch34: 0033-gcc-analyzer-add-NULL-checks.patch +Patch35: 0034-gcc-analyzer-increase-socket_name-size.patch +Patch36: 0035-use-g_strdup_printf.patch +Patch37: 0036-avoid-malloc-with-create_credentials_msg.patch +Patch38: 0037-conver-strncmp-to-g_str_has_prefix.patch +Patch39: 0038-define-IRQBALANCE_ARGS-as-empty-string-to-squelch-sy.patch +Patch40: 0039-Minor-punctuation-fix.patch +Patch41: 0040-Version-option-should-return-0-rather-than-1.patch +Patch42: 0041-Add-CAP_SETPCAP-to-CapabilityBoundingSet-in-irqbalan.patch +Patch43: 0042-Check-info-moved-before-updating.patch +Patch44: 0043-irqbalance.1-a-b-a-b-it-s-type-its-type.patch +Patch45: 0044-Use-EPERM-instead-of-EIO-when-try-setting-irq-affini.patch + +Patch46: irqbalance-1.9.0-environment-file-sysconfig.patch BuildRequires: autoconf automake libtool libcap-ng BuildRequires: glib2-devel pkgconf libcap-ng-devel