]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: cpu-topo: add "drop-cpu" and "only-cpu" to cpu-set
authorWilly Tarreau <w@1wt.eu>
Wed, 26 Feb 2025 15:06:54 +0000 (16:06 +0100)
committerWilly Tarreau <w@1wt.eu>
Fri, 14 Mar 2025 17:30:30 +0000 (18:30 +0100)
These allow respectively to disable binding to CPUs listed in a set, and
to disable binding to CPUs not in a set.

doc/configuration.txt
src/cpu_topo.c

index cc476d3e073bbe93d2862d3daaad3804516401d4..156fc515686c164bc8b6fdef94eaa33cbe53bece 100644 (file)
@@ -1953,6 +1953,8 @@ cpu-set <directive>...
     - reset              this undoes any previous limitation that could have
                          been inherited by a service manager or a "taskset"
                          command for example.
+    - drop-cpu <set>     do not bind to CPUs in this set
+    - only-cpu <set>     do not bind to CPUs not in this set
 
 crt-base <dir>
   Assigns a default directory to fetch SSL certificates from when a relative
index 082912026e7c9c7aaf43a8e0a60f67a7b1003ee6..2aab0d6b71b36ff2947dcd805566892fa9aa0a86 100644 (file)
@@ -28,6 +28,9 @@ int cpu_mask_forced = 0;
 /* "cpu-set" global configuration */
 struct cpu_set_cfg {
        uint flags; // CPU_SET_FL_XXX above
+       /* CPU numbers to accept / reject */
+       struct hap_cpuset only_cpus;
+       struct hap_cpuset drop_cpus;
 } cpu_set_cfg;
 
 /* Detects CPUs that are online on the system. It may rely on FS access (e.g.
@@ -103,6 +106,13 @@ int cpu_detect_usable(void)
                                ha_cpu_topo[cpu].st |= HA_CPU_F_EXCLUDED;
        }
 
+       /* remove CPUs in the drop-cpu set or not in the only-cpu set */
+       for (cpu = 0; cpu < cpu_topo_maxcpus; cpu++) {
+               if ( ha_cpuset_isset(&cpu_set_cfg.drop_cpus, cpu) ||
+                   !ha_cpuset_isset(&cpu_set_cfg.only_cpus, cpu))
+                       ha_cpu_topo[cpu].st |= HA_CPU_F_DONT_USE;
+       }
+
        /* 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
         * the info so we only update what we know. We take this opportunity
@@ -482,17 +492,32 @@ 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)
 {
+       const char *cpu_set_str[2] = { "", "" };
+       struct hap_cpuset tmp_cpuset = { };
        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 if (strcmp(args[arg], "drop-cpu") == 0 || strcmp(args[arg], "only-cpu") == 0) {
+                       if (!*args[arg + 1]) {
+                               memprintf(err, "missing CPU set");
+                               goto parse_err;
+                       }
+
+                       cpu_set_str[0] = args[arg + 1];
+                       if (parse_cpu_set(cpu_set_str, &tmp_cpuset, err) != 0)
+                               goto parse_err;
+
+                       if (*args[arg] == 'd') // cpus to drop
+                               ha_cpuset_or(&cpu_set_cfg.drop_cpus, &tmp_cpuset);
+                       else // cpus to keep
+                               ha_cpuset_and(&cpu_set_cfg.only_cpus, &tmp_cpuset);
+                       arg++;
+               }
                else {
                        /* fall back with default error message */
                        memprintf(err, "'%s' passed an unknown directive '%s'", args[0], args[arg]);
@@ -508,9 +533,17 @@ static int cfg_parse_cpu_set(char **args, int section_type, struct proxy *curpx,
        /* all done */
        return 0;
 
+ parse_err:
+       /* displays args[0] and args[arg] followed by *err so as to remind the
+        * option name, the sub-directive and the reported error.
+        */
+       memprintf(err, "'%s %s': %s\n.", args[0], args[arg], *err);
+       goto leave;
+
  leave_with_err:
        /* complete with supported directives */
-       memprintf(err, "%s (only 'reset' supported).", *err);
+       memprintf(err, "%s (only 'reset', 'only-cpu', 'drop-cpu' supported).", *err);
+ leave:
        return -1;
 }
 
@@ -542,6 +575,15 @@ static int cpu_topo_alloc(void)
                ha_cpu_topo[cpu].idx = cpu;
        }
 
+       /* pre-inizialize the configured CPU sets */
+       ha_cpuset_zero(&cpu_set_cfg.drop_cpus);
+       ha_cpuset_zero(&cpu_set_cfg.only_cpus);
+
+       /* preset all CPUs in the "only-XXX" sets */
+       for (cpu = 0; cpu < cpu_topo_maxcpus; cpu++) {
+               ha_cpuset_set(&cpu_set_cfg.only_cpus, cpu);
+       }
+
        return 1;
 }