From: Willy Tarreau Date: Wed, 26 Feb 2025 14:17:41 +0000 (+0100) Subject: MINOR: cpu-topo: add a new "cpu-set" global directive to choose cpus X-Git-Tag: v3.2-dev8~74 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cda4956d9c1fc6e8a0f87ca8f6264cc389d40bc0;p=thirdparty%2Fhaproxy.git MINOR: cpu-topo: add a new "cpu-set" global directive to choose cpus For now it's limited, it only supports "reset" to ask that any previous "taskset" be ignored. The goal will be to later add more actions that allow to symbolically define sets of cpus to bind to or to drop. This also clears the cpu_mask_forced variable that is used to detect that a taskset had been used. --- diff --git a/doc/configuration.txt b/doc/configuration.txt index 2404544c3..cc476d3e0 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -1522,6 +1522,7 @@ The following keywords are supported in the "global" section : - chroot - cluster-secret - cpu-map + - cpu-set - crt-base - daemon - default-path @@ -1946,6 +1947,13 @@ cpu-map [auto:][/] [,...] [...] cpu-map 4/1-40 40-79,120-159 +cpu-set ... + Allows to symbolically describe what sets of CPUs to run on. The directive + supports the following keyword: + - reset this undoes any previous limitation that could have + been inherited by a service manager or a "taskset" + command for example. + crt-base Assigns a default directory to fetch SSL certificates from when a relative path is used with "crtfile" or "crt" directives. Absolute locations specified diff --git a/src/cpu_topo.c b/src/cpu_topo.c index 15dd5b5a9..082912026 100644 --- a/src/cpu_topo.c +++ b/src/cpu_topo.c @@ -6,11 +6,16 @@ #include #include +#include #include #include #include #include +/* for cpu_set.flags below */ +#define CPU_SET_FL_NONE 0x0000 +#define CPU_SET_FL_DO_RESET 0x0001 + /* CPU topology information, ha_cpuset_size() entries, allocated at boot */ int cpu_topo_maxcpus = -1; // max number of CPUs supported by OS/haproxy int cpu_topo_lastcpu = -1; // last supposed online CPU (no need to look beyond) @@ -20,6 +25,11 @@ struct cpu_map *cpu_map; /* non-zero if we're certain that taskset or similar was used to force CPUs */ int cpu_mask_forced = 0; +/* "cpu-set" global configuration */ +struct cpu_set_cfg { + uint flags; // CPU_SET_FL_XXX above +} cpu_set_cfg; + /* Detects CPUs that are online on the system. It may rely on FS access (e.g. * /sys on Linux). Returns the number of CPUs detected or 0 if the detection * failed. @@ -83,13 +93,15 @@ int cpu_detect_usable(void) struct hap_cpuset boot_set = { }; int cpu; - /* update the list with the CPUs currently bound to the current process */ - ha_cpuset_detect_bound(&boot_set); + if (!(cpu_set_cfg.flags & CPU_SET_FL_DO_RESET)) { + /* update the list with the CPUs currently bound to the current process */ + ha_cpuset_detect_bound(&boot_set); - /* remove the known-excluded CPUs */ - for (cpu = 0; cpu < cpu_topo_maxcpus; cpu++) - if (!ha_cpuset_isset(&boot_set, cpu)) - ha_cpu_topo[cpu].st |= HA_CPU_F_EXCLUDED; + /* remove the known-excluded CPUs */ + for (cpu = 0; cpu < cpu_topo_maxcpus; cpu++) + if (!ha_cpuset_isset(&boot_set, cpu)) + ha_cpu_topo[cpu].st |= HA_CPU_F_EXCLUDED; + } /* Update the list of currently offline CPUs. Normally it's a subset * of the unbound ones, but we cannot infer anything if we don't have @@ -463,6 +475,45 @@ int cpu_detect_topology(void) #endif // OS-specific cpu_detect_topology() +/* Parse the "cpu-set" global directive, which takes action names and + * optional values, and fills the cpu_set structure above. + */ +static int cfg_parse_cpu_set(char **args, int section_type, struct proxy *curpx, + const struct proxy *defpx, const char *file, int line, + char **err) +{ + int arg; + + for (arg = 1; *args[arg]; arg++) { + if (strcmp(args[arg], "reset") == 0) { + if (too_many_args(0 + arg, args, err, NULL)) + return -1; + + /* reset the excluded CPUs first (undo "taskset") */ + cpu_set_cfg.flags |= CPU_SET_FL_DO_RESET; + cpu_mask_forced = 0; + } + else { + /* fall back with default error message */ + memprintf(err, "'%s' passed an unknown directive '%s'", args[0], args[arg]); + goto leave_with_err; + } + } + + if (arg == 1) { + memprintf(err, "'%s' requires a directive and an optional value", args[0]); + goto leave_with_err; + } + + /* all done */ + return 0; + + leave_with_err: + /* complete with supported directives */ + memprintf(err, "%s (only 'reset' supported).", *err); + return -1; +} + /* Allocates everything needed to store CPU topology at boot. * Returns non-zero on success, zero on failure. */ @@ -502,3 +553,11 @@ static void cpu_topo_deinit(void) INITCALL0(STG_ALLOC, cpu_topo_alloc); REGISTER_POST_DEINIT(cpu_topo_deinit); + +/* config keyword parsers */ +static struct cfg_kw_list cfg_kws = {ILH, { + { CFG_GLOBAL, "cpu-set", cfg_parse_cpu_set, 0 }, + { 0, NULL, NULL } +}}; + +INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);