From: Christopher Faulet Date: Wed, 22 Nov 2017 14:01:51 +0000 (+0100) Subject: MINOR: config: Add auto-increment feature for cpu-map X-Git-Tag: v1.8.0~34 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=26028f620941a514417b3186841580739052ae56;p=thirdparty%2Fhaproxy.git MINOR: config: Add auto-increment feature for cpu-map 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 --- diff --git a/doc/configuration.txt b/doc/configuration.txt index 8305515d90..664c05dfa8 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -657,7 +657,7 @@ chroot with superuser privileges. It is important to ensure that is both empty and unwritable to anyone. -cpu-map <"all"|"odd"|"even"|process_num[-process_num]> ... +cpu-map [auto:]<"all"|"odd"|"even"|process_num[-process_num]> ... 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]> ... 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 Assigns a default directory to fetch SSL certificates from when a relative path is used with "crtfile" directives. Absolute locations specified after diff --git a/include/common/cfgparse.h b/include/common/cfgparse.h index 7332bd53a9..1ce7251e8b 100644 --- a/include/common/cfgparse.h +++ b/include/common/cfgparse.h @@ -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 does not have at least one of the diff --git a/src/cfgparse.c b/src/cfgparse.c index d4cfa8641d..a7d5753059 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -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; diff --git a/src/cli.c b/src/cli.c index 05cc15e1d3..038bdd3838 100644 --- 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; } diff --git a/src/listener.c b/src/listener.c index a06a464f04..c82ba36e0a 100644 --- a/src/listener.c +++ b/src/listener.c @@ -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; }