diff --git a/support-optional-param-filter-arg_prefix.patch b/support-optional-param-filter-arg_prefix.patch new file mode 100644 index 0000000000000000000000000000000000000000..ed39fdd9604e163c72be22ef36e6fe0480a990c5 --- /dev/null +++ b/support-optional-param-filter-arg_prefix.patch @@ -0,0 +1,268 @@ +From 5914d012af959b8a8352cef616db2ad205591ce4 Mon Sep 17 00:00:00 2001 +From: wuchangye +Date: Mon, 15 Sep 2025 09:14:42 +0800 +Subject: [PATCH] support optional param filter: arg_prefix + +Signed-off-by: wuchangye +--- + tuned/ebpf/programmable_sched.h | 8 ++-- + tuned/ebpf/programmable_sched_kern.c | 72 ++++++++++++++++++++++++++-- + tuned/ebpf/programmable_sched_user.c | 54 +++++++++++++-------- + 3 files changed, 105 insertions(+), 29 deletions(-) + +diff --git a/tuned/ebpf/programmable_sched.h b/tuned/ebpf/programmable_sched.h +index 589a94a..b40e823 100644 +--- a/tuned/ebpf/programmable_sched.h ++++ b/tuned/ebpf/programmable_sched.h +@@ -14,13 +14,15 @@ + #ifndef __PROGRAMMABLE_SCHED_H__ + #define __PROGRAMMABLE_SCHED_H__ + +-#define TASK_COMM_LEN 16 ++#define MAX_STR_LEN 32 ++#define MAX_ARGS 100 ++#define MAX_ARG_LEN 256 + + struct sched_numa_info { + __u32 numa_count; + __u32 numa_index; +- __u32 prefix_len; +- char proc_prefix[TASK_COMM_LEN + 1]; ++ char proc_prefix[MAX_STR_LEN + 1]; ++ char arg_prefix[MAX_STR_LEN + 1]; + }; + + #endif /* __PROGRAMMABLE_SCHED_H__ */ +diff --git a/tuned/ebpf/programmable_sched_kern.c b/tuned/ebpf/programmable_sched_kern.c +index a73845d..4e96801 100644 +--- a/tuned/ebpf/programmable_sched_kern.c ++++ b/tuned/ebpf/programmable_sched_kern.c +@@ -99,10 +99,70 @@ static __always_inline int libbpf_sched_set_task_prefer_cpumask(struct task_stru + return bpf_sched_set_task_prefer_cpumask(tsk, mask, len); + } + ++static __always_inline int str_prefix(char *str, char *prefix) ++{ ++ int i = 0; ++ while (*str && *prefix && (i <= MAX_STR_LEN)) { ++ if (*str != *prefix) ++ return -1; ++ str++; ++ prefix++; ++ i++; ++ } ++ ++ if (*prefix) ++ return -1; ++ return 0; ++} ++ ++static __always_inline int args_match(struct task_struct *p, char *arg_prefix) ++{ ++ int i, arg_num, ret = 0; ++ void *arg_start, *arg_end; ++ char arg[MAX_ARG_LEN] = {0}; ++ struct mm_struct *mm = NULL; ++ ++ ret = bpf_probe_read_kernel(&mm, sizeof(mm), &p->mm); ++ if (ret) { ++ bpf_printk("bpf_probe_read_kernel mm failed:%d\n", ret); ++ return ret; ++ } ++ ++ ret |= bpf_probe_read_kernel(&arg_start, sizeof(arg_start), &mm->arg_start); ++ ret |= bpf_probe_read_kernel(&arg_end, sizeof(arg_end), &mm->arg_end); ++ if (ret) { ++ bpf_printk("bpf_probe_read_kernel arg failed:%d\n", ret); ++ return ret; ++ } ++ ++ arg_num = (arg_end - arg_start) / sizeof(void *); ++ if (arg_num > MAX_ARGS) { ++ bpf_printk("arg_num(%d) > MAX_ARGS(%d)\n", arg_num, MAX_ARGS); ++ return -1; ++ } ++ ++ for (i = 0; i < MAX_ARGS; i++) { ++ if (i > arg_num) ++ break; ++ ++ ret = bpf_probe_read_user_str(arg, MAX_ARG_LEN, arg_start); ++ if (ret == 0) { ++ bpf_printk("bpf_probe_read_user_str i:%d failed\n", i); ++ return -1; ++ } ++ ++ arg_start += ret; ++ if (str_prefix(arg, arg_prefix) == 0) ++ return 0; ++ } ++ return -1; ++} ++ + SEC("sched/cfs_exec_init") + void BPF_PROG(programmable_sched, struct task_struct *p) + { +- char comm[TASK_COMM_LEN + 1]; ++ int ret = 0; ++ char comm[MAX_STR_LEN + 1]; + if (bpf_probe_read_kernel(comm, sizeof(comm), &p->comm)) { + bpf_printk("ERROR: read process name failed"); + return; +@@ -115,10 +175,12 @@ void BPF_PROG(programmable_sched, struct task_struct *p) + return; + } + +- for (int i = 0; i < TASK_COMM_LEN; i++) { +- if (i >= numa_info->prefix_len || numa_info->proc_prefix[i] == '\0') +- break; +- if (numa_info->proc_prefix[i] != comm[i]) ++ if (str_prefix(comm, numa_info->proc_prefix) != 0) ++ return; ++ ++ if (numa_info->arg_prefix[0] != '\0') { ++ ret = args_match(p, numa_info->arg_prefix); ++ if (ret) + return; + } + +diff --git a/tuned/ebpf/programmable_sched_user.c b/tuned/ebpf/programmable_sched_user.c +index f193882..acf4dcc 100644 +--- a/tuned/ebpf/programmable_sched_user.c ++++ b/tuned/ebpf/programmable_sched_user.c +@@ -42,7 +42,8 @@ void print_help(const char *prog_name) + printf("Options:\n"); + printf(" -L, --load Load and pin eBPF programs\n"); + printf(" -U, --unload Unload and unpin eBPF programs\n"); +- printf(" -P, --process-prefix Required for load, process name prefix to match (max 16 chars)\n"); ++ printf(" -P, --process-prefix Required for load, process name prefix to match (max 32 chars)\n"); ++ printf(" -A, --arg-prefix Optional for load, arg name prefix to match (max 32 chars)\n"); + printf(" -h, --help Display this help message\n"); + } + +@@ -83,16 +84,17 @@ int set_rlimit(void) + return setrlimit(RLIMIT_MEMLOCK, &r); + } + +-static void parse_arguments(int argc, char **argv, char *process_prefix, int len) ++static void parse_arguments(int argc, char **argv, char *process_prefix, int proc_len, char *arg_prefix, int arg_len) + { + static struct option long_options[] = {{"load", no_argument, 0, 'L'}, + {"unload", no_argument, 0, 'U'}, + {"process-prefix", required_argument, 0, 'P'}, ++ {"arg-prefix", optional_argument, 0, 'A'}, + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0}}; + int opt; + +- while ((opt = getopt_long(argc, argv, "LUP:h", long_options, NULL)) != -1) { ++ while ((opt = getopt_long(argc, argv, "LUP:A:h", long_options, NULL)) != -1) { + switch (opt) { + case 'L': + load_mode = true; +@@ -101,11 +103,17 @@ static void parse_arguments(int argc, char **argv, char *process_prefix, int len + unload_mode = true; + break; + case 'P': +- if (snprintf(process_prefix, len, "%.*s", len - 1, optarg) < 0) { ++ if (snprintf(process_prefix, proc_len, "%.*s", proc_len - 1, optarg) < 0) { + fprintf(stderr, "Failed to run snprintf() in parse_arguments(), errno: %d\n", errno); + exit(EXIT_FAILURE); + } + break; ++ case 'A': ++ if (snprintf(arg_prefix, arg_len, "%.*s", arg_len - 1, optarg) < 0) { ++ fprintf(stderr, "Failed to parse arg_prefix in parse_arguments(), errno: %d\n", errno); ++ exit(EXIT_FAILURE); ++ } ++ break; + case 'h': + print_help(argv[0]); + exit(EXIT_FAILURE); +@@ -120,34 +128,37 @@ static void parse_arguments(int argc, char **argv, char *process_prefix, int len + } + } + +-static int init_numa_info_map(struct programmable_sched_kern *skel, const char *process_prefix) ++static int init_numa_info_map(struct programmable_sched_kern *skel, const char *proc_prefix, const char *arg_prefix) + { +- int numa_map_fd = bpf_map__fd(skel->maps.numa_info_map); ++ int key = 0, len, numa_map_fd, err; ++ struct sched_numa_info val = {0}; ++ ++ numa_map_fd = bpf_map__fd(skel->maps.numa_info_map); + if (numa_map_fd < 0) { + fprintf(stderr, "Failed to get map FD\n"); + return -1; + } + +- int numa_count = get_numa_node_count(); +- int key = 0; +- struct sched_numa_info val = {.numa_count = numa_count, .numa_index = 0}; +- int len = +- snprintf(val.proc_prefix, sizeof(val.proc_prefix), "%.*s", (int)sizeof(val.proc_prefix) - 1, process_prefix); ++ val.numa_count = get_numa_node_count(); ++ len = snprintf(val.proc_prefix, sizeof(val.proc_prefix), "%.*s", (int)sizeof(val.proc_prefix) - 1, proc_prefix); + if (len < 0) { + fprintf(stderr, "Failed to run snprintf() in init_numa_info_map(), errno: %d\n", errno); + return -1; + } +- val.prefix_len = len; + +- int err = bpf_map_update_elem(numa_map_fd, &key, &val, BPF_ANY); +- if (err) { +- fprintf(stderr, "Failed to update mask_map: %d\n", err); ++ len = snprintf(val.arg_prefix, sizeof(val.arg_prefix), "%.*s", (int)sizeof(val.arg_prefix) - 1, arg_prefix); ++ if (len < 0) { ++ fprintf(stderr, "Failed to run arg snprintf() in init_numa_info_map(), errno: %d\n", errno); + return -1; + } +- return 0; ++ ++ err = bpf_map_update_elem(numa_map_fd, &key, &val, BPF_ANY); ++ if (err) ++ fprintf(stderr, "Failed to update mask_map: %d\n", err); ++ return err; + } + +-static int load_and_attach_bpf(struct programmable_sched_kern **skel, const char *process_prefix) ++static int load_and_attach_bpf(struct programmable_sched_kern **skel, const char *proc_prefix, const char *arg_prefix) + { + *skel = programmable_sched_kern__open_and_load(); + if (!*skel) { +@@ -155,7 +166,7 @@ static int load_and_attach_bpf(struct programmable_sched_kern **skel, const char + return -1; + } + +- if (init_numa_info_map(*skel, process_prefix) < 0) { ++ if (init_numa_info_map(*skel, proc_prefix, arg_prefix) < 0) { + return -1; + } + +@@ -222,11 +233,12 @@ static int unload_ebpf_objects(void) + + int main(int argc, char **argv) + { +- char process_prefix[TASK_COMM_LEN + 1] = {0}; ++ char process_prefix[MAX_STR_LEN + 1] = {0}; ++ char arg_prefix[MAX_STR_LEN + 1] = {0}; + struct programmable_sched_kern *skel = NULL; + int err = EXIT_SUCCESS; + +- parse_arguments(argc, argv, process_prefix, sizeof(process_prefix)); ++ parse_arguments(argc, argv, process_prefix, sizeof(process_prefix), arg_prefix, sizeof(arg_prefix)); + + if (load_mode) { + // Validate required process prefix +@@ -243,7 +255,7 @@ int main(int argc, char **argv) + } + + // Load and attach BPF program +- if (load_and_attach_bpf(&skel, process_prefix) < 0) { ++ if (load_and_attach_bpf(&skel, process_prefix, arg_prefix) < 0) { + err = EXIT_FAILURE; + goto cleanup; + } +-- +2.33.0 + diff --git a/tuned.spec b/tuned.spec index bf0d0a928b88f5c94035d2abde6831d96461c7d3..313d0e1440c9fd142a67a83349261add8dd12238 100644 --- a/tuned.spec +++ b/tuned.spec @@ -1,7 +1,7 @@ Summary: A system tuning service for Linux Name: tuned Version: 2.24.1 -Release: 3 +Release: 4 License: GPLv2+ Source0: https://github.com/redhat-performance/%{name}/archive/refs/tags/v%{version}.tar.gz#/%{name}-%{version}.tar.gz URL: http://www.tuned-project.org/ @@ -42,6 +42,7 @@ Patch7: bugfix-expand-variables-in-Plugin.patch Patch8: profiles-add-spark.patch Patch9: profiles-Add-programmable-scheduling-based-on-eBPF.patch Patch10: profiles-Add-vmlinux-to-support-eBPF-program-compila.patch +Patch11: support-optional-param-filter-arg_prefix.patch Provides: tuned-gtk = %{version}-%{release} Provides: tuned-utils = %{version}-%{release} @@ -305,6 +306,9 @@ fi %{_mandir}/man7/tuned-profiles-spectrumscale-ece.7* %changelog +* Sun Sep 14 2025 wuchangye - 2.24.1-4 +- tuned-ebpf: support optional param filter: arg_prefix + * Mon Jun 23 2025 tianmuyang - 2.24.1-3 - profiles: add programmable scheduling based on eBPF - package: change package tuned to architecture-dependent