]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: config: Add auto-increment feature for cpu-map
authorChristopher Faulet <cfaulet@haproxy.com>
Wed, 22 Nov 2017 14:01:51 +0000 (15:01 +0100)
committerWilly Tarreau <w@1wt.eu>
Fri, 24 Nov 2017 14:38:49 +0000 (15:38 +0100)
The prefix "auto:" can be added before the process set to let HAProxy
automatically bind a process to a CPU by incrementing process and CPU sets. To
be valid, both sets must have the same size. No matter the declaration order of
the CPU sets, it will be bound from the lower to the higher bound.

  Examples:
      # all these lines bind the process 1 to the cpu 0, the process 2 to cpu 1
      #  and so on.
      cpu-map auto:1-4   0-3
      cpu-map auto:1-4   0-1 2-3
      cpu-map auto:1-4   3 2 1 0

      # bind each process to exaclty one CPU using all/odd/even keyword
      cpu-map auto:all   0-63
      cpu-map auto:even  0-31
      cpu-map auto:odd   32-63

      # invalid cpu-map because process and CPU sets have different sizes.
      cpu-map auto:1-4   0    # invalid
      cpu-map auto:1     0-3  # invalid

doc/configuration.txt
include/common/cfgparse.h
src/cfgparse.c
src/cli.c
src/listener.c

index 8305515d905fcbf69b6b64b47810ce074bedc539..664c05dfa8b6e83b053b3de6296c6f82c09c7c2b 100644 (file)
@@ -657,7 +657,7 @@ chroot <jail dir>
   with superuser privileges. It is important to ensure that <jail_dir> is both
   empty and unwritable to anyone.
 
-cpu-map <"all"|"odd"|"even"|process_num[-process_num]> <cpu-set>...
+cpu-map [auto:]<"all"|"odd"|"even"|process_num[-process_num]> <cpu-set>...
   On Linux 2.6 and above, it is possible to bind a process to a specific CPU
   set. This means that the process will never run on other CPUs. The "cpu-map"
   directive specifies CPU sets for process sets. The first argument is the
@@ -673,6 +673,28 @@ cpu-map <"all"|"odd"|"even"|process_num[-process_num]> <cpu-set>...
   of them.  Obviously, multiple "cpu-map" directives may be specified. Each
   "cpu-map" directive will replace the previous ones when they overlap.
 
+  The prefix "auto:" can be added before the process set to let HAProxy
+  automatically bind a process to a CPU by incrementing process and CPU
+  sets. To be valid, both sets must have the same size. No matter the
+  declaration order of the CPU sets, it will be bound from the lower to the
+  higher bound.
+
+  Examples:
+      # all these lines bind the process 1 to the cpu 0, the process 2 to cpu 1
+      #  and so on.
+      cpu-map auto:1-4   0-3
+      cpu-map auto:1-4   0-1 2-3
+      cpu-map auto:1-4   3 2 1 0
+
+      # bind each process to exaclty one CPU using all/odd/even keyword
+      cpu-map auto:all   0-63
+      cpu-map auto:even  0-31
+      cpu-map auto:odd   32-63
+
+      # invalid cpu-map because process and CPU sets have different sizes.
+      cpu-map auto:1-4   0    # invalid
+      cpu-map auto:1     0-3  # invalid
+
 crt-base <dir>
   Assigns a default directory to fetch SSL certificates from when a relative
   path is used with "crtfile" directives. Absolute locations specified after
index 7332bd53a9f40a7898eb3742500730b507275099..1ce7251e8be2413960949ee3284a55154dfb8abe 100644 (file)
@@ -86,7 +86,7 @@ int too_many_args_idx(int maxarg, int index, char **args, char **msg, int *err_c
 int too_many_args(int maxarg, char **args, char **msg, int *err_code);
 int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code);
 int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code);
-int parse_process_number(const char *arg, unsigned long *proc, char **err);
+int parse_process_number(const char *arg, unsigned long *proc, int *autoinc, char **err);
 
 /*
  * Sends a warning if proxy <proxy> does not have at least one of the
index d4cfa8641d866925b8565b103ed0550d2813005c..a7d57530598ea133a847c277e04f4fb5582c15e1 100644 (file)
@@ -596,8 +596,16 @@ static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where
  * Note: this function can also be used to parse a thread number or a set of
  * threads.
  */
-int parse_process_number(const char *arg, unsigned long *proc, char **err)
+int parse_process_number(const char *arg, unsigned long *proc, int *autoinc, char **err)
 {
+       if (autoinc) {
+               *autoinc = 0;
+               if (strncmp(arg, "auto:", 5) == 0) {
+                       arg += 5;
+                       *autoinc = 1;
+               }
+       }
+
        if (strcmp(arg, "all") == 0)
                *proc |= ~0UL;
        else if (strcmp(arg, "odd") == 0)
@@ -1698,7 +1706,7 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
                /* map a process list to a CPU set */
 #ifdef USE_CPU_AFFINITY
                unsigned long proc = 0, cpus;
-               int i;
+               int i, n, autoinc;
 
                if (!*args[1] || !*args[2]) {
                        Alert("parsing [%s:%d] : %s expects a process number "
@@ -1709,7 +1717,7 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
                        goto out;
                }
 
-               if (parse_process_number(args[1], &proc, &errmsg)) {
+               if (parse_process_number(args[1], &proc, &autoinc, &errmsg)) {
                        Alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
                        err_code |= ERR_ALERT | ERR_FATAL;
                        goto out;
@@ -1720,9 +1728,23 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
                        err_code |= ERR_ALERT | ERR_FATAL;
                        goto out;
                }
-               for (i = 0; i < LONGBITS; i++)
-                       if (proc & (1UL << i))
-                               global.cpu_map[i] = cpus;
+
+               if (autoinc && my_popcountl(proc) != my_popcountl(cpus)) {
+                       Alert("parsing [%s:%d] : %s : PROC range and CPU sets must have the same size to be auto-assigned\n",
+                             file, linenum, args[0]);
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
+               }
+               for (i = n = 0; i < LONGBITS; i++) {
+                       if (proc & (1UL << i)) {
+                               if (autoinc) {
+                                       n += my_ffsl(cpus >> n);
+                                       global.cpu_map[i] = (1UL << (n-1));
+                               }
+                               else
+                                       global.cpu_map[i] = cpus;
+                       }
+               }
 #else
                Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n",
                      file, linenum, args[0]);
@@ -1747,12 +1769,12 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
                        goto out;
                }
 
-               if (parse_process_number(args[1], &proc, &errmsg)) {
+               if (parse_process_number(args[1], &proc, NULL, &errmsg)) {
                        Alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
                        err_code |= ERR_ALERT | ERR_FATAL;
                        goto out;
                }
-               if (parse_process_number(args[2], &thread, &errmsg)) {
+               if (parse_process_number(args[2], &thread, NULL, &errmsg)) {
                        Alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
                        err_code |= ERR_ALERT | ERR_FATAL;
                        goto out;
@@ -3287,7 +3309,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
                                set = 0;
                                break;
                        }
-                       if (parse_process_number(args[cur_arg], &set, &errmsg)) {
+                       if (parse_process_number(args[cur_arg], &set, NULL, &errmsg)) {
                                Alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
                                err_code |= ERR_ALERT | ERR_FATAL;
                                goto out;
index 05cc15e1d3e624a64d14c2b1fbfe780169966a97..038bdd3838bd40ef9fb281f2dd3dc999c90b7967 100644 (file)
--- a/src/cli.c
+++ b/src/cli.c
@@ -327,7 +327,7 @@ static int stats_parse_global(char **args, int section_type, struct proxy *curpx
                                set = 0;
                                break;
                        }
-                       if (parse_process_number(args[cur_arg], &set, err)) {
+                       if (parse_process_number(args[cur_arg], &set, NULL, err)) {
                                memprintf(err, "'%s %s' : %s", args[0], args[1], *err);
                                return -1;
                        }
index a06a464f0497ba9a300ffb9b8f6e16d656ff68c4..c82ba36e0a0a1c1e73e4d15e9efcc8d9ed997873 100644 (file)
@@ -943,7 +943,7 @@ static int bind_parse_process(char **args, int cur_arg, struct proxy *px, struct
 {
        unsigned long set = 0;
 
-       if (parse_process_number(args[cur_arg + 1], &set, err)) {
+       if (parse_process_number(args[cur_arg + 1], &set, NULL, err)) {
                memprintf(err, "'%s' : %s", args[cur_arg], *err);
                return ERR_ALERT | ERR_FATAL;
        }