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
This commit is contained in:
Christopher Faulet 2017-11-22 15:01:51 +01:00 committed by Willy Tarreau
parent ff8131861f
commit 26028f6209
5 changed files with 57 additions and 13 deletions

View 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

View 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

View 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;

View File

@ -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;
}

View 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;
}