mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-10 01:17:44 +03:00
Merge pull request #1382 from filbranden/cpuaffinity2
Use parse_cpu_set in CPUAffinity support (for units)
This commit is contained in:
commit
2c995032e8
@ -2578,6 +2578,62 @@ cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
|
||||
}
|
||||
}
|
||||
|
||||
int parse_cpu_set(
|
||||
const char *rvalue,
|
||||
cpu_set_t **cpu_set,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *lvalue) {
|
||||
|
||||
const char *whole_rvalue = rvalue;
|
||||
_cleanup_cpu_free_ cpu_set_t *c = NULL;
|
||||
unsigned ncpus = 0;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *word = NULL;
|
||||
unsigned cpu;
|
||||
int r;
|
||||
|
||||
r = extract_first_word(&rvalue, &word, WHITESPACE, EXTRACT_QUOTES);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
||||
"Invalid value for %s: %s", lvalue, whole_rvalue);
|
||||
return r;
|
||||
}
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
r = safe_atou(word, &cpu);
|
||||
|
||||
if (!c)
|
||||
if (!(c = cpu_set_malloc(&ncpus)))
|
||||
return log_oom();
|
||||
|
||||
if (r < 0 || cpu >= ncpus) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, -r,
|
||||
"Failed to parse CPU affinity '%s'", rvalue);
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
CPU_SET_S(cpu, CPU_ALLOC_SIZE(ncpus), c);
|
||||
}
|
||||
if (!isempty(rvalue))
|
||||
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
|
||||
"Trailing garbage, ignoring.");
|
||||
|
||||
/* On success, sets *cpu_set and returns ncpus for the system. */
|
||||
if (c) {
|
||||
*cpu_set = c;
|
||||
c = NULL;
|
||||
}
|
||||
return (int) ncpus;
|
||||
}
|
||||
|
||||
int files_same(const char *filea, const char *fileb) {
|
||||
struct stat a, b;
|
||||
|
||||
|
@ -375,6 +375,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(cpu_set_t*, CPU_FREE);
|
||||
#define _cleanup_cpu_free_ _cleanup_(CPU_FREEp)
|
||||
|
||||
cpu_set_t* cpu_set_malloc(unsigned *ncpus);
|
||||
int parse_cpu_set(const char *rvalue, cpu_set_t **cpu_set, const char *unit, const char *filename, unsigned line, const char *lvalue);
|
||||
|
||||
#define xsprintf(buf, fmt, ...) \
|
||||
assert_message_se((size_t) snprintf(buf, ELEMENTSOF(buf), fmt, __VA_ARGS__) < ELEMENTSOF(buf), \
|
||||
|
@ -875,50 +875,30 @@ int config_parse_exec_cpu_affinity(const char *unit,
|
||||
void *userdata) {
|
||||
|
||||
ExecContext *c = data;
|
||||
const char *word, *state;
|
||||
size_t l;
|
||||
_cleanup_cpu_free_ cpu_set_t *cpuset = NULL;
|
||||
int ncpus;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
ncpus = parse_cpu_set(rvalue, &cpuset, unit, filename, line, lvalue);
|
||||
|
||||
if (ncpus < 0)
|
||||
return ncpus;
|
||||
|
||||
if (c->cpuset)
|
||||
CPU_FREE(c->cpuset);
|
||||
|
||||
if (ncpus == 0)
|
||||
/* An empty assignment resets the CPU list */
|
||||
if (c->cpuset)
|
||||
CPU_FREE(c->cpuset);
|
||||
c->cpuset = NULL;
|
||||
return 0;
|
||||
else {
|
||||
c->cpuset = cpuset;
|
||||
cpuset = NULL;
|
||||
}
|
||||
|
||||
FOREACH_WORD_QUOTED(word, l, rvalue, state) {
|
||||
_cleanup_free_ char *t = NULL;
|
||||
int r;
|
||||
unsigned cpu;
|
||||
|
||||
t = strndup(word, l);
|
||||
if (!t)
|
||||
return log_oom();
|
||||
|
||||
r = safe_atou(t, &cpu);
|
||||
|
||||
if (!c->cpuset) {
|
||||
c->cpuset = cpu_set_malloc(&c->cpuset_ncpus);
|
||||
if (!c->cpuset)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
if (r < 0 || cpu >= c->cpuset_ncpus) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, ERANGE,
|
||||
"Failed to parse CPU affinity '%s', ignoring: %s", t, rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CPU_SET_S(cpu, CPU_ALLOC_SIZE(c->cpuset_ncpus), c->cpuset);
|
||||
}
|
||||
if (!isempty(state))
|
||||
log_syntax(unit, LOG_WARNING, filename, line, EINVAL,
|
||||
"Trailing garbage, ignoring.");
|
||||
c->cpuset_ncpus = ncpus;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -434,48 +434,16 @@ static int config_parse_cpu_affinity2(
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
const char *whole_rvalue = rvalue;
|
||||
_cleanup_cpu_free_ cpu_set_t *c = NULL;
|
||||
unsigned ncpus = 0;
|
||||
int ncpus;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
ncpus = parse_cpu_set(rvalue, &c, unit, filename, line, lvalue);
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *word = NULL;
|
||||
unsigned cpu;
|
||||
int r;
|
||||
if (ncpus < 0)
|
||||
return ncpus;
|
||||
|
||||
r = extract_first_word(&rvalue, &word, WHITESPACE, EXTRACT_QUOTES);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Invalid value for %s: %s", lvalue, whole_rvalue);
|
||||
return r;
|
||||
}
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
r = safe_atou(word, &cpu);
|
||||
|
||||
if (!c)
|
||||
if (!(c = cpu_set_malloc(&ncpus)))
|
||||
return log_oom();
|
||||
|
||||
if (r < 0 || cpu >= ncpus) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, -r,
|
||||
"Failed to parse CPU affinity '%s'", rvalue);
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
CPU_SET_S(cpu, CPU_ALLOC_SIZE(ncpus), c);
|
||||
}
|
||||
if (!isempty(rvalue))
|
||||
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
|
||||
"Trailing garbage, ignoring.");
|
||||
|
||||
if (c)
|
||||
if (sched_setaffinity(0, CPU_ALLOC_SIZE(ncpus), c) < 0)
|
||||
log_warning("Failed to set CPU affinity: %m");
|
||||
if (sched_setaffinity(0, CPU_ALLOC_SIZE(ncpus), c) < 0)
|
||||
log_warning("Failed to set CPU affinity: %m");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -960,6 +960,64 @@ static void test_parse_size(void) {
|
||||
assert_se(parse_size("-10B 20K", 1024, &bytes) == -ERANGE);
|
||||
}
|
||||
|
||||
static void test_parse_cpu_set(void) {
|
||||
cpu_set_t *c = NULL;
|
||||
int ncpus;
|
||||
int cpu;
|
||||
|
||||
/* Simple range (from CPUAffinity example) */
|
||||
ncpus = parse_cpu_set("1 2", &c, NULL, "fake", 1, "CPUAffinity");
|
||||
assert_se(ncpus >= 1024);
|
||||
assert_se(CPU_ISSET_S(1, CPU_ALLOC_SIZE(ncpus), c));
|
||||
assert_se(CPU_ISSET_S(2, CPU_ALLOC_SIZE(ncpus), c));
|
||||
assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 2);
|
||||
c = mfree(c);
|
||||
|
||||
/* A more interesting range */
|
||||
ncpus = parse_cpu_set("0 1 2 3 8 9 10 11", &c, NULL, "fake", 1, "CPUAffinity");
|
||||
assert_se(ncpus >= 1024);
|
||||
assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 8);
|
||||
for (cpu = 0; cpu < 4; cpu++)
|
||||
assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
|
||||
for (cpu = 8; cpu < 12; cpu++)
|
||||
assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
|
||||
c = mfree(c);
|
||||
|
||||
/* Quoted strings */
|
||||
ncpus = parse_cpu_set("8 '9' 10 \"11\"", &c, NULL, "fake", 1, "CPUAffinity");
|
||||
assert_se(ncpus >= 1024);
|
||||
assert_se(CPU_COUNT_S(CPU_ALLOC_SIZE(ncpus), c) == 4);
|
||||
for (cpu = 8; cpu < 12; cpu++)
|
||||
assert_se(CPU_ISSET_S(cpu, CPU_ALLOC_SIZE(ncpus), c));
|
||||
c = mfree(c);
|
||||
|
||||
/* Use commas as separators */
|
||||
ncpus = parse_cpu_set("0,1,2,3 8,9,10,11", &c, NULL, "fake", 1, "CPUAffinity");
|
||||
assert_se(ncpus < 0);
|
||||
assert_se(!c);
|
||||
|
||||
/* Ranges */
|
||||
ncpus = parse_cpu_set("0-3,8-11", &c, NULL, "fake", 1, "CPUAffinity");
|
||||
assert_se(ncpus < 0);
|
||||
assert_se(!c);
|
||||
|
||||
/* Garbage */
|
||||
ncpus = parse_cpu_set("0 1 2 3 garbage", &c, NULL, "fake", 1, "CPUAffinity");
|
||||
assert_se(ncpus < 0);
|
||||
assert_se(!c);
|
||||
|
||||
/* Empty string */
|
||||
c = NULL;
|
||||
ncpus = parse_cpu_set("", &c, NULL, "fake", 1, "CPUAffinity");
|
||||
assert_se(ncpus == 0); /* empty string returns 0 */
|
||||
assert_se(!c);
|
||||
|
||||
/* Runnaway quoted string */
|
||||
ncpus = parse_cpu_set("0 1 2 3 \"4 5 6 7 ", &c, NULL, "fake", 1, "CPUAffinity");
|
||||
assert_se(ncpus < 0);
|
||||
assert_se(!c);
|
||||
}
|
||||
|
||||
static void test_config_parse_iec_uint64(void) {
|
||||
uint64_t offset = 0;
|
||||
assert_se(config_parse_iec_uint64(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4M", &offset, NULL) == 0);
|
||||
@ -2250,6 +2308,7 @@ int main(int argc, char *argv[]) {
|
||||
test_u64log2();
|
||||
test_protect_errno();
|
||||
test_parse_size();
|
||||
test_parse_cpu_set();
|
||||
test_config_parse_iec_uint64();
|
||||
test_strextend();
|
||||
test_strrep();
|
||||
|
Loading…
Reference in New Issue
Block a user