mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2024-12-11 05:54:39 +00:00
MEDIUM: config: limit nbproc to the machine's word size
Some consistency checks cannot be performed between frontends, backends and peers at the moment because there is no way to check for intersection between processes bound to some processes when the number of processes is higher than the number of bits in a word. So first, let's limit the number of processes to the machine's word size. This means nbproc will be limited to 32 on 32-bit machines and 64 on 64-bit machines. This is far more than enough considering that configs rarely go above 16 processes due to scalability and management issues, so 32 or 64 should be fine. This way we'll ensure we can always build a mask of all the processes a section is bound to.
This commit is contained in:
parent
3507d5d096
commit
a9db57ec5c
@ -525,16 +525,16 @@ cpu-map <"all"|"odd"|"even"|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
|
||||
process number to bind. This process must have a number between 1 and 32,
|
||||
and any process IDs above nbproc are ignored. It is possible to specify all
|
||||
processes at once using "all", only odd numbers using "odd" or even numbers
|
||||
using "even", just like with the "bind-process" directive. The second and
|
||||
forthcoming arguments are CPU sets. Each CPU set is either a unique number
|
||||
between 0 and 31 or a range with two such numbers delimited by a dash ('-').
|
||||
Multiple CPU numbers or ranges may be specified, and the processes will be
|
||||
allowed to bind to all of them. Obviously, multiple "cpu-map" directives may
|
||||
be specified. Each "cpu-map" directive will replace the previous ones when
|
||||
they overlap.
|
||||
process number to bind. This process must have a number between 1 and 32 or
|
||||
64, depending on the machine's word size, and any process IDs above nbproc
|
||||
are ignored. It is possible to specify all processes at once using "all",
|
||||
only odd numbers using "odd" or even numbers using "even", just like with the
|
||||
"bind-process" directive. The second and forthcoming arguments are CPU sets.
|
||||
Each CPU set is either a unique number between 0 and 31 or 63 or a range with
|
||||
two such numbers delimited by a dash ('-'). Multiple CPU numbers or ranges
|
||||
may be specified, and the processes will be allowed to bind to all of them.
|
||||
Obviously, multiple "cpu-map" directives may be specified. Each "cpu-map"
|
||||
directive will replace the previous ones when they overlap.
|
||||
|
||||
crt-base <dir>
|
||||
Assigns a default directory to fetch SSL certificates from when a relative
|
||||
@ -624,14 +624,15 @@ pidfile <pidfile>
|
||||
the "-p" command line argument. The file must be accessible to the user
|
||||
starting the process. See also "daemon".
|
||||
|
||||
stats bind-process [ all | odd | even | <number 1-32>[-<number 1-32>] ] ...
|
||||
stats bind-process [ all | odd | even | <number 1-64>[-<number 1-64>] ] ...
|
||||
Limits the stats socket to a certain set of processes numbers. By default the
|
||||
stats socket is bound to all processes, causing a warning to be emitted when
|
||||
nbproc is greater than 1 because there is no way to select the target process
|
||||
when connecting. However, by using this setting, it becomes possible to pin
|
||||
the stats socket to a specific set of processes, typically the first one. The
|
||||
warning will automatically be disabled when this setting is used, whatever
|
||||
the number of processes used.
|
||||
the number of processes used. The maximum process ID depends on the machine's
|
||||
word size (32 or 64).
|
||||
|
||||
ssl-default-bind-ciphers <ciphers>
|
||||
This setting is only available when support for OpenSSL was built in. It sets
|
||||
@ -1830,7 +1831,7 @@ bind /<path> [, ...] [param*]
|
||||
documentation, and section 5 about bind options.
|
||||
|
||||
|
||||
bind-process [ all | odd | even | <number 1-32>[-<number 1-32>] ] ...
|
||||
bind-process [ all | odd | even | <number 1-64>[-<number 1-64>] ] ...
|
||||
Limit visibility of an instance to a certain set of processes numbers.
|
||||
May be used in sections : defaults | frontend | listen | backend
|
||||
yes | yes | yes | yes
|
||||
@ -1838,19 +1839,19 @@ bind-process [ all | odd | even | <number 1-32>[-<number 1-32>] ] ...
|
||||
all All process will see this instance. This is the default. It
|
||||
may be used to override a default value.
|
||||
|
||||
odd This instance will be enabled on processes 1,3,5,...31. This
|
||||
odd This instance will be enabled on processes 1,3,5,...63. This
|
||||
option may be combined with other numbers.
|
||||
|
||||
even This instance will be enabled on processes 2,4,6,...32. This
|
||||
even This instance will be enabled on processes 2,4,6,...64. This
|
||||
option may be combined with other numbers. Do not use it
|
||||
with less than 2 processes otherwise some instances might be
|
||||
missing from all processes.
|
||||
|
||||
number The instance will be enabled on this process number or range,
|
||||
whose values must all be between 1 and 32. You must be
|
||||
careful not to reference a process number greater than the
|
||||
configured global.nbproc, otherwise some instances might be
|
||||
missing from all processes.
|
||||
whose values must all be between 1 and 32 or 64 depending on
|
||||
the machine's word size. You must be careful not to reference
|
||||
a process number greater than the configured global.nbproc,
|
||||
otherwise some instances might be missing from all processes.
|
||||
|
||||
This keyword limits binding of certain instances to certain processes. This
|
||||
is useful in order not to have too many processes listening to the same
|
||||
@ -1858,10 +1859,10 @@ bind-process [ all | odd | even | <number 1-32>[-<number 1-32>] ] ...
|
||||
'nbproc 2' in the global section, then distributes the listeners among 'odd'
|
||||
and 'even' instances.
|
||||
|
||||
At the moment, it is not possible to reference more than 32 processes using
|
||||
this keyword, but this should be more than enough for most setups. Please
|
||||
note that 'all' really means all processes and is not limited to the first
|
||||
32.
|
||||
At the moment, it is not possible to reference more than 32 or 64 processes
|
||||
using this keyword, but this should be more than enough for most setups.
|
||||
Please note that 'all' really means all processes regardless of the machine's
|
||||
word size, and is not limited to the first 32 or 64.
|
||||
|
||||
If some backends are referenced by frontends bound to other processes, the
|
||||
backend automatically inherits the frontend's processes.
|
||||
|
@ -42,6 +42,10 @@
|
||||
# define ULLONG_MAX (LLONG_MAX * 2ULL + 1)
|
||||
#endif
|
||||
|
||||
#ifndef LONGBITS
|
||||
#define LONGBITS ((unsigned int)sizeof(long) * 8)
|
||||
#endif
|
||||
|
||||
/* size used for max length of decimal representation of long long int. */
|
||||
#define NB_LLMAX_STR (sizeof("-9223372036854775807")-1)
|
||||
|
||||
@ -527,7 +531,7 @@ static inline unsigned int div64_32(unsigned long long o1, unsigned int o2)
|
||||
}
|
||||
|
||||
/* Simple popcount implementation. It returns the number of ones in a word */
|
||||
static inline unsigned int popcount(unsigned int a)
|
||||
static inline unsigned int popcount(unsigned long a)
|
||||
{
|
||||
unsigned int cnt;
|
||||
for (cnt = 0; a; a >>= 1) {
|
||||
@ -537,6 +541,15 @@ static inline unsigned int popcount(unsigned int a)
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/* Build a word with the <bits> lower bits set (reverse of popcount) */
|
||||
static inline unsigned long nbits(int bits)
|
||||
{
|
||||
if (--bits < 0)
|
||||
return 0;
|
||||
else
|
||||
return (2UL << bits) - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse binary string written in hexadecimal (source) and store the decoded
|
||||
* result into binstr and set binstrlen to the lengh of binstr. Memory for
|
||||
|
@ -149,7 +149,7 @@ struct global {
|
||||
} ux;
|
||||
} unix_bind;
|
||||
#ifdef USE_CPU_AFFINITY
|
||||
unsigned long cpu_map[32]; /* list of CPU masks for the 32 first processes */
|
||||
unsigned long cpu_map[LONGBITS]; /* list of CPU masks for the 32/64 first processes */
|
||||
#endif
|
||||
struct proxy *stats_fe; /* the frontend holding the stats settings */
|
||||
};
|
||||
|
@ -345,7 +345,7 @@ struct proxy {
|
||||
struct chunk errmsg[HTTP_ERR_SIZE]; /* default or customized error messages for known errors */
|
||||
int uuid; /* universally unique proxy ID, used for SNMP */
|
||||
unsigned int backlog; /* force the frontend's listen backlog */
|
||||
unsigned int bind_proc; /* bitmask of processes using this proxy. 0 = all. */
|
||||
unsigned long bind_proc; /* bitmask of processes using this proxy */
|
||||
|
||||
/* warning: these structs are huge, keep them at the bottom */
|
||||
struct sockaddr_storage dispatch_addr; /* the default address to connect to */
|
||||
|
@ -886,6 +886,12 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
|
||||
goto out;
|
||||
}
|
||||
global.nbproc = atol(args[1]);
|
||||
if (global.nbproc < 1 || global.nbproc > LONGBITS) {
|
||||
Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
|
||||
file, linenum, args[0], LONGBITS, global.nbproc);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(args[0], "maxconn")) {
|
||||
if (global.maxconn != 0) {
|
||||
@ -1369,24 +1375,24 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
|
||||
else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
|
||||
#ifdef USE_CPU_AFFINITY
|
||||
int cur_arg, i;
|
||||
unsigned int proc = 0;
|
||||
unsigned long proc = 0;
|
||||
unsigned long cpus = 0;
|
||||
|
||||
if (strcmp(args[1], "all") == 0)
|
||||
proc = 0xFFFFFFFF;
|
||||
proc = ~0UL;
|
||||
else if (strcmp(args[1], "odd") == 0)
|
||||
proc = 0x55555555;
|
||||
proc = ~0UL/3UL; /* 0x555....555 */
|
||||
else if (strcmp(args[1], "even") == 0)
|
||||
proc = 0xAAAAAAAA;
|
||||
proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
|
||||
else {
|
||||
proc = atoi(args[1]);
|
||||
if (proc >= 1 && proc <= 32)
|
||||
proc = 1 << (proc - 1);
|
||||
proc = atol(args[1]);
|
||||
if (proc >= 1 && proc <= LONGBITS)
|
||||
proc = 1UL << (proc - 1);
|
||||
}
|
||||
|
||||
if (!proc || !*args[2]) {
|
||||
Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to 32, followed by a list of CPU ranges with numbers from 0 to 31.\n",
|
||||
file, linenum, args[0]);
|
||||
Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to %d, followed by a list of CPU ranges with numbers from 0 to %d.\n",
|
||||
file, linenum, args[0], LONGBITS, LONGBITS - 1);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
@ -1408,9 +1414,9 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
|
||||
high = swap;
|
||||
}
|
||||
|
||||
if (high >= sizeof(long) * 8) {
|
||||
if (high >= LONGBITS) {
|
||||
Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
|
||||
file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
|
||||
file, linenum, args[0], LONGBITS - 1);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
@ -1426,8 +1432,8 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
|
||||
}
|
||||
cur_arg++;
|
||||
}
|
||||
for (i = 0; i < 32; i++)
|
||||
if (proc & (1 << i))
|
||||
for (i = 0; i < LONGBITS; i++)
|
||||
if (proc & (1UL << i))
|
||||
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]);
|
||||
@ -2350,7 +2356,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
|
||||
}
|
||||
else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
|
||||
int cur_arg = 1;
|
||||
unsigned int set = 0;
|
||||
unsigned long set = 0;
|
||||
|
||||
while (*args[cur_arg]) {
|
||||
unsigned int low, high;
|
||||
@ -2360,10 +2366,10 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
|
||||
break;
|
||||
}
|
||||
else if (strcmp(args[cur_arg], "odd") == 0) {
|
||||
set |= 0x55555555;
|
||||
set |= ~0UL/3UL; /* 0x555....555 */
|
||||
}
|
||||
else if (strcmp(args[cur_arg], "even") == 0) {
|
||||
set |= 0xAAAAAAAA;
|
||||
set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
|
||||
}
|
||||
else if (isdigit((int)*args[cur_arg])) {
|
||||
char *dash = strchr(args[cur_arg], '-');
|
||||
@ -2378,24 +2384,18 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
|
||||
high = swap;
|
||||
}
|
||||
|
||||
if (low < 1 || high > 32) {
|
||||
Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
|
||||
file, linenum, args[0]);
|
||||
if (low < 1 || high > LONGBITS) {
|
||||
Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
|
||||
file, linenum, args[0], LONGBITS);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (high > global.nbproc) {
|
||||
Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
|
||||
file, linenum, args[0], high, global.nbproc);
|
||||
err_code |= ERR_WARN;
|
||||
}
|
||||
while (low <= high)
|
||||
set |= 1 << (low++ - 1);
|
||||
set |= 1UL << (low++ - 1);
|
||||
}
|
||||
else {
|
||||
Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
|
||||
file, linenum, args[0]);
|
||||
Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
|
||||
file, linenum, args[0], LONGBITS);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
@ -6860,7 +6860,7 @@ out_uri_auth_compat:
|
||||
if (curproxy->bind_proc) {
|
||||
int proc;
|
||||
for (proc = 0; proc < global.nbproc; proc++) {
|
||||
if (curproxy->bind_proc & (1 << proc)) {
|
||||
if (curproxy->bind_proc & (1UL << proc)) {
|
||||
nbproc++;
|
||||
}
|
||||
}
|
||||
|
@ -372,7 +372,7 @@ static int stats_parse_global(char **args, int section_type, struct proxy *curpx
|
||||
}
|
||||
else if (!strcmp(args[1], "bind-process")) { /* enable the socket only on some processes */
|
||||
int cur_arg = 2;
|
||||
unsigned int set = 0;
|
||||
unsigned long set = 0;
|
||||
|
||||
if (!global.stats_fe) {
|
||||
if ((global.stats_fe = alloc_stats_fe("GLOBAL", file, line)) == NULL) {
|
||||
@ -389,10 +389,10 @@ static int stats_parse_global(char **args, int section_type, struct proxy *curpx
|
||||
break;
|
||||
}
|
||||
else if (strcmp(args[cur_arg], "odd") == 0) {
|
||||
set |= 0x55555555;
|
||||
set |= ~0UL/3UL; /* 0x555....555 */
|
||||
}
|
||||
else if (strcmp(args[cur_arg], "even") == 0) {
|
||||
set |= 0xAAAAAAAA;
|
||||
set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
|
||||
}
|
||||
else if (isdigit((int)*args[cur_arg])) {
|
||||
char *dash = strchr(args[cur_arg], '-');
|
||||
@ -407,19 +407,18 @@ static int stats_parse_global(char **args, int section_type, struct proxy *curpx
|
||||
high = swap;
|
||||
}
|
||||
|
||||
if (low < 1 || high > 32) {
|
||||
memprintf(err, "'%s %s' supports process numbers from 1 to 32.\n",
|
||||
args[0], args[1]);
|
||||
if (low < 1 || high > LONGBITS) {
|
||||
memprintf(err, "'%s %s' supports process numbers from 1 to %d.\n",
|
||||
args[0], args[1], LONGBITS);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (low <= high)
|
||||
set |= 1 << (low++ - 1);
|
||||
set |= 1UL << (low++ - 1);
|
||||
}
|
||||
else {
|
||||
memprintf(err,
|
||||
"'%s %s' expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
|
||||
args[0], args[1]);
|
||||
"'%s %s' expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
|
||||
args[0], args[1], LONGBITS);
|
||||
return -1;
|
||||
}
|
||||
cur_arg++;
|
||||
|
@ -1596,7 +1596,7 @@ int main(int argc, char **argv)
|
||||
px = proxy;
|
||||
while (px != NULL) {
|
||||
if (px->bind_proc && px->state != PR_STSTOPPED) {
|
||||
if (!(px->bind_proc & (1 << proc)))
|
||||
if (!(px->bind_proc & (1UL << proc)))
|
||||
stop_proxy(px);
|
||||
}
|
||||
px = px->next;
|
||||
|
Loading…
Reference in New Issue
Block a user