cpu-set-util: fix null pointer dereference and several cleanups (#37900)
Fixes CID#1611618.
This commit is contained in:
+5
-5
@@ -267,10 +267,10 @@ void cgroup_context_done(CGroupContext *c) {
|
||||
|
||||
c->restrict_network_interfaces = set_free(c->restrict_network_interfaces);
|
||||
|
||||
cpu_set_reset(&c->cpuset_cpus);
|
||||
cpu_set_reset(&c->startup_cpuset_cpus);
|
||||
cpu_set_reset(&c->cpuset_mems);
|
||||
cpu_set_reset(&c->startup_cpuset_mems);
|
||||
cpu_set_done(&c->cpuset_cpus);
|
||||
cpu_set_done(&c->startup_cpuset_cpus);
|
||||
cpu_set_done(&c->cpuset_mems);
|
||||
cpu_set_done(&c->startup_cpuset_mems);
|
||||
|
||||
c->delegate_subgroup = mfree(c->delegate_subgroup);
|
||||
|
||||
@@ -4161,7 +4161,7 @@ int unit_get_cpuset(Unit *u, CPUSet *cpus, const char *name) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return parse_cpu_set_full(v, cpus, false, NULL, NULL, 0, NULL);
|
||||
return parse_cpu_set(v, cpus);
|
||||
}
|
||||
|
||||
CGroupRuntime* cgroup_runtime_new(void) {
|
||||
|
||||
@@ -1241,7 +1241,7 @@ int bus_cgroup_set_property(
|
||||
} else if (STR_IN_SET(name, "AllowedCPUs", "StartupAllowedCPUs", "AllowedMemoryNodes", "StartupAllowedMemoryNodes")) {
|
||||
const void *a;
|
||||
size_t n;
|
||||
_cleanup_(cpu_set_reset) CPUSet new_set = {};
|
||||
_cleanup_(cpu_set_done) CPUSet new_set = {};
|
||||
|
||||
r = sd_bus_message_read_array(message, 'y', &a, &n);
|
||||
if (r < 0)
|
||||
@@ -1267,12 +1267,10 @@ int bus_cgroup_set_property(
|
||||
set = &c->cpuset_mems;
|
||||
else if (streq(name, "StartupAllowedMemoryNodes"))
|
||||
set = &c->startup_cpuset_mems;
|
||||
else
|
||||
assert_not_reached();
|
||||
|
||||
assert(set);
|
||||
|
||||
cpu_set_reset(set);
|
||||
*set = new_set;
|
||||
new_set = (CPUSet) {};
|
||||
cpu_set_done_and_replace(*set, new_set);
|
||||
|
||||
unit_invalidate_cgroup(u, CGROUP_MASK_CPUSET);
|
||||
unit_write_settingf(u, flags, name, "%s=\n%s=%s", name, name, setstr);
|
||||
|
||||
@@ -115,7 +115,7 @@ static int property_get_cpu_affinity(
|
||||
sd_bus_error *error) {
|
||||
|
||||
ExecContext *c = ASSERT_PTR(userdata);
|
||||
_cleanup_(cpu_set_reset) CPUSet s = {};
|
||||
_cleanup_(cpu_set_done) CPUSet s = {};
|
||||
_cleanup_free_ uint8_t *array = NULL;
|
||||
size_t allocated;
|
||||
|
||||
@@ -2876,10 +2876,9 @@ int bus_exec_context_set_transient_property(
|
||||
}
|
||||
#endif
|
||||
if (STR_IN_SET(name, "CPUAffinity", "NUMAMask")) {
|
||||
_cleanup_(cpu_set_done) CPUSet set = {};
|
||||
const void *a;
|
||||
size_t n;
|
||||
bool affinity = streq(name, "CPUAffinity");
|
||||
_cleanup_(cpu_set_reset) CPUSet set = {};
|
||||
|
||||
r = sd_bus_message_read_array(message, 'y', &a, &n);
|
||||
if (r < 0)
|
||||
@@ -2890,8 +2889,10 @@ int bus_exec_context_set_transient_property(
|
||||
return r;
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
CPUSet *cpuset = streq(name, "CPUAffinity") ? &c->cpu_set : &c->numa_policy.nodes;
|
||||
|
||||
if (n == 0) {
|
||||
cpu_set_reset(affinity ? &c->cpu_set : &c->numa_policy.nodes);
|
||||
cpu_set_done(cpuset);
|
||||
unit_write_settingf(u, flags, name, "%s=", name);
|
||||
} else {
|
||||
_cleanup_free_ char *str = NULL;
|
||||
@@ -2901,9 +2902,9 @@ int bus_exec_context_set_transient_property(
|
||||
return -ENOMEM;
|
||||
|
||||
/* We forego any optimizations here, and always create the structure using
|
||||
* cpu_set_add_all(), because we don't want to care if the existing size we
|
||||
* cpu_set_add_set(), because we don't want to care if the existing size we
|
||||
* got over dbus is appropriate. */
|
||||
r = cpu_set_add_all(affinity ? &c->cpu_set : &c->numa_policy.nodes, &set);
|
||||
r = cpu_set_add_set(cpuset, &set);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
@@ -1154,7 +1154,7 @@ static int property_get_cpuset_cpus(
|
||||
sd_bus_error *error) {
|
||||
|
||||
Unit *u = ASSERT_PTR(userdata);
|
||||
_cleanup_(cpu_set_reset) CPUSet cpus = {};
|
||||
_cleanup_(cpu_set_done) CPUSet cpus = {};
|
||||
_cleanup_free_ uint8_t *array = NULL;
|
||||
size_t allocated;
|
||||
|
||||
@@ -1176,7 +1176,7 @@ static int property_get_cpuset_mems(
|
||||
sd_bus_error *error) {
|
||||
|
||||
Unit *u = ASSERT_PTR(userdata);
|
||||
_cleanup_(cpu_set_reset) CPUSet mems = {};
|
||||
_cleanup_(cpu_set_done) CPUSet mems = {};
|
||||
_cleanup_free_ uint8_t *array = NULL;
|
||||
size_t allocated;
|
||||
|
||||
|
||||
@@ -3979,7 +3979,6 @@ static int compile_suggested_paths(const ExecContext *c, const ExecParameters *p
|
||||
}
|
||||
|
||||
static int exec_context_cpu_affinity_from_numa(const ExecContext *c, CPUSet *ret) {
|
||||
_cleanup_(cpu_set_reset) CPUSet s = {};
|
||||
int r;
|
||||
|
||||
assert(c);
|
||||
@@ -3987,16 +3986,17 @@ static int exec_context_cpu_affinity_from_numa(const ExecContext *c, CPUSet *ret
|
||||
|
||||
if (!c->numa_policy.nodes.set) {
|
||||
log_debug("Can't derive CPU affinity mask from NUMA mask because NUMA mask is not set, ignoring");
|
||||
*ret = (CPUSet) {};
|
||||
return 0;
|
||||
}
|
||||
|
||||
_cleanup_(cpu_set_done) CPUSet s = {};
|
||||
r = numa_to_cpu_set(&c->numa_policy, &s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
cpu_set_reset(ret);
|
||||
|
||||
return cpu_set_add_all(ret, &s);
|
||||
*ret = TAKE_STRUCT(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int add_shifted_fd(int *fds, size_t fds_size, size_t *n_fds, int *fd) {
|
||||
@@ -5107,7 +5107,7 @@ int exec_invoke(
|
||||
}
|
||||
|
||||
if (context->cpu_affinity_from_numa || context->cpu_set.set) {
|
||||
_cleanup_(cpu_set_reset) CPUSet converted_cpu_set = {};
|
||||
_cleanup_(cpu_set_done) CPUSet converted_cpu_set = {};
|
||||
const CPUSet *cpu_set;
|
||||
|
||||
if (context->cpu_affinity_from_numa) {
|
||||
|
||||
@@ -494,56 +494,28 @@ static int exec_cgroup_context_deserialize(CGroupContext *c, FILE *f) {
|
||||
if (c->cpuset_cpus.set)
|
||||
return -EINVAL; /* duplicated */
|
||||
|
||||
r = parse_cpu_set_full(
|
||||
val,
|
||||
&c->cpuset_cpus,
|
||||
/* warn= */ false,
|
||||
/* unit= */ NULL,
|
||||
/* filename= */ NULL,
|
||||
/* line= */ 0,
|
||||
/* lvalue= */ NULL);
|
||||
r = parse_cpu_set(val, &c->cpuset_cpus);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if ((val = startswith(l, "exec-cgroup-context-startup-allowed-cpus="))) {
|
||||
if (c->startup_cpuset_cpus.set)
|
||||
return -EINVAL; /* duplicated */
|
||||
|
||||
r = parse_cpu_set_full(
|
||||
val,
|
||||
&c->startup_cpuset_cpus,
|
||||
/* warn= */ false,
|
||||
/* unit= */ NULL,
|
||||
/* filename= */ NULL,
|
||||
/* line= */ 0,
|
||||
/* lvalue= */ NULL);
|
||||
r = parse_cpu_set(val, &c->startup_cpuset_cpus);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if ((val = startswith(l, "exec-cgroup-context-allowed-memory-nodes="))) {
|
||||
if (c->cpuset_mems.set)
|
||||
return -EINVAL; /* duplicated */
|
||||
|
||||
r = parse_cpu_set_full(
|
||||
val,
|
||||
&c->cpuset_mems,
|
||||
/* warn= */ false,
|
||||
/* unit= */ NULL,
|
||||
/* filename= */ NULL,
|
||||
/* line= */ 0,
|
||||
/* lvalue= */ NULL);
|
||||
r = parse_cpu_set(val, &c->cpuset_mems);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if ((val = startswith(l, "exec-cgroup-context-startup-allowed-memory-nodes="))) {
|
||||
if (c->startup_cpuset_mems.set)
|
||||
return -EINVAL; /* duplicated */
|
||||
|
||||
r = parse_cpu_set_full(
|
||||
val,
|
||||
&c->startup_cpuset_mems,
|
||||
/* warn= */ false,
|
||||
/* unit= */ NULL,
|
||||
/* filename= */ NULL,
|
||||
/* line= */ 0,
|
||||
/* lvalue= */ NULL);
|
||||
r = parse_cpu_set(val, &c->startup_cpuset_mems);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if ((val = startswith(l, "exec-cgroup-context-io-weight="))) {
|
||||
|
||||
+1
-1
@@ -720,7 +720,7 @@ void exec_context_done(ExecContext *c) {
|
||||
c->n_temporary_filesystems = 0;
|
||||
c->mount_images = mount_image_free_many(c->mount_images, &c->n_mount_images);
|
||||
|
||||
cpu_set_reset(&c->cpu_set);
|
||||
cpu_set_done(&c->cpu_set);
|
||||
numa_policy_reset(&c->numa_policy);
|
||||
|
||||
c->utmp_id = mfree(c->utmp_id);
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
{{type}}.CPUSchedulingResetOnFork, config_parse_bool, 0, offsetof({{type}}, exec_context.cpu_sched_reset_on_fork)
|
||||
{{type}}.CPUAffinity, config_parse_exec_cpu_affinity, 0, offsetof({{type}}, exec_context)
|
||||
{{type}}.NUMAPolicy, config_parse_numa_policy, 0, offsetof({{type}}, exec_context.numa_policy.type)
|
||||
{{type}}.NUMAMask, config_parse_numa_mask, 0, offsetof({{type}}, exec_context.numa_policy)
|
||||
{{type}}.NUMAMask, config_parse_numa_mask, 0, offsetof({{type}}, exec_context.numa_policy.nodes)
|
||||
{{type}}.UMask, config_parse_mode, 0, offsetof({{type}}, exec_context.umask)
|
||||
{{type}}.Environment, config_parse_environ, 0, offsetof({{type}}, exec_context.environment)
|
||||
{{type}}.EnvironmentFile, config_parse_unit_env_file, 0, offsetof({{type}}, exec_context.environment_files)
|
||||
@@ -197,10 +197,10 @@
|
||||
|
||||
{%- macro CGROUP_CONTEXT_CONFIG_ITEMS(type) -%}
|
||||
{{type}}.Slice, config_parse_unit_slice, 0, 0
|
||||
{{type}}.AllowedCPUs, config_parse_allowed_cpuset, 0, offsetof({{type}}, cgroup_context.cpuset_cpus)
|
||||
{{type}}.StartupAllowedCPUs, config_parse_allowed_cpuset, 0, offsetof({{type}}, cgroup_context.startup_cpuset_cpus)
|
||||
{{type}}.AllowedMemoryNodes, config_parse_allowed_cpuset, 0, offsetof({{type}}, cgroup_context.cpuset_mems)
|
||||
{{type}}.StartupAllowedMemoryNodes, config_parse_allowed_cpuset, 0, offsetof({{type}}, cgroup_context.startup_cpuset_mems)
|
||||
{{type}}.AllowedCPUs, config_parse_unit_cpu_set, 0, offsetof({{type}}, cgroup_context.cpuset_cpus)
|
||||
{{type}}.StartupAllowedCPUs, config_parse_unit_cpu_set, 0, offsetof({{type}}, cgroup_context.startup_cpuset_cpus)
|
||||
{{type}}.AllowedMemoryNodes, config_parse_unit_cpu_set, 0, offsetof({{type}}, cgroup_context.cpuset_mems)
|
||||
{{type}}.StartupAllowedMemoryNodes, config_parse_unit_cpu_set, 0, offsetof({{type}}, cgroup_context.startup_cpuset_mems)
|
||||
{{type}}.CPUAccounting, config_parse_warn_compat, DISABLED_LEGACY, 0
|
||||
{{type}}.CPUWeight, config_parse_cg_cpu_weight, 0, offsetof({{type}}, cgroup_context.cpu_weight)
|
||||
{{type}}.StartupCPUWeight, config_parse_cg_cpu_weight, 0, offsetof({{type}}, cgroup_context.startup_cpu_weight)
|
||||
|
||||
+106
-125
@@ -737,7 +737,7 @@ int config_parse_exec_nice(
|
||||
}
|
||||
|
||||
int config_parse_exec_oom_score_adjust(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
@@ -776,7 +776,7 @@ int config_parse_exec_oom_score_adjust(
|
||||
}
|
||||
|
||||
int config_parse_exec_coredump_filter(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
@@ -814,7 +814,7 @@ int config_parse_exec_coredump_filter(
|
||||
}
|
||||
|
||||
int config_parse_kill_mode(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
@@ -1071,7 +1071,7 @@ int config_parse_exec(
|
||||
}
|
||||
|
||||
int config_parse_socket_bindtodevice(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
@@ -1428,16 +1428,17 @@ int config_parse_exec_output(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_exec_io_class(const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
int config_parse_exec_io_class(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
ExecContext *c = ASSERT_PTR(data);
|
||||
int x;
|
||||
@@ -1464,16 +1465,17 @@ int config_parse_exec_io_class(const char *unit,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_exec_io_priority(const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
int config_parse_exec_io_priority(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
ExecContext *c = ASSERT_PTR(data);
|
||||
int i, r;
|
||||
@@ -1500,16 +1502,17 @@ int config_parse_exec_io_priority(const char *unit,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_exec_cpu_sched_policy(const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
int config_parse_exec_cpu_sched_policy(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
ExecContext *c = ASSERT_PTR(data);
|
||||
int x;
|
||||
@@ -1539,47 +1542,55 @@ int config_parse_exec_cpu_sched_policy(const char *unit,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_numa_mask(const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
int config_parse_numa_mask(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
CPUSet *cpu_set = ASSERT_PTR(data);
|
||||
int r;
|
||||
NUMAPolicy *p = ASSERT_PTR(data);
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
|
||||
if (streq(rvalue, "all")) {
|
||||
r = numa_mask_add_all(&p->nodes);
|
||||
_cleanup_(cpu_set_done) CPUSet c = {};
|
||||
|
||||
r = numa_mask_add_all(&c);
|
||||
if (r < 0)
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to create NUMA mask representing \"all\" NUMA nodes, ignoring: %m");
|
||||
} else {
|
||||
r = parse_cpu_set_extend(rvalue, &p->nodes, true, unit, filename, line, lvalue);
|
||||
if (r < 0)
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse NUMA node mask, ignoring: %s", rvalue);
|
||||
|
||||
cpu_set_done(cpu_set);
|
||||
*cpu_set = TAKE_STRUCT(c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
/* When parsing system.conf or user.conf, rather than unit files, userdata is NULL. */
|
||||
return userdata ?
|
||||
config_parse_unit_cpu_set(unit, filename, line, section, section_line, lvalue, ltype, rvalue, data, userdata) :
|
||||
config_parse_cpu_set(unit, filename, line, section, section_line, lvalue, ltype, rvalue, data, userdata);
|
||||
}
|
||||
|
||||
int config_parse_exec_cpu_sched_prio(const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
int config_parse_exec_cpu_sched_prio(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
ExecContext *c = ASSERT_PTR(data);
|
||||
int i, r;
|
||||
@@ -1824,8 +1835,6 @@ int config_parse_exec_cpu_affinity(
|
||||
void *userdata) {
|
||||
|
||||
ExecContext *c = ASSERT_PTR(data);
|
||||
const Unit *u = userdata;
|
||||
_cleanup_free_ char *k = NULL;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
@@ -1834,21 +1843,12 @@ int config_parse_exec_cpu_affinity(
|
||||
|
||||
if (streq(rvalue, "numa")) {
|
||||
c->cpu_affinity_from_numa = true;
|
||||
cpu_set_reset(&c->cpu_set);
|
||||
|
||||
cpu_set_done(&c->cpu_set);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = unit_full_printf(u, rvalue, &k);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to resolve unit specifiers in '%s', ignoring: %m",
|
||||
rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = parse_cpu_set_extend(k, &c->cpu_set, true, unit, filename, line, lvalue);
|
||||
if (r >= 0)
|
||||
r = config_parse_unit_cpu_set(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &c->cpu_set, userdata);
|
||||
if (r > 0)
|
||||
c->cpu_affinity_from_numa = false;
|
||||
|
||||
return 0;
|
||||
@@ -2166,16 +2166,17 @@ int config_parse_trigger_unit(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_path_spec(const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
int config_parse_path_spec(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
Path *p = ASSERT_PTR(data);
|
||||
PathSpec *s;
|
||||
@@ -2655,16 +2656,17 @@ int config_parse_working_directory(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_unit_env_file(const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
int config_parse_unit_env_file(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
char ***env = ASSERT_PTR(data);
|
||||
const Unit *u = userdata;
|
||||
@@ -3769,7 +3771,7 @@ int config_parse_cpu_quota(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_allowed_cpuset(
|
||||
int config_parse_unit_cpu_set(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
@@ -3781,8 +3783,7 @@ int config_parse_allowed_cpuset(
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
CPUSet *c = data;
|
||||
const Unit *u = userdata;
|
||||
const Unit *u = ASSERT_PTR(userdata);
|
||||
_cleanup_free_ char *k = NULL;
|
||||
int r;
|
||||
|
||||
@@ -3798,8 +3799,7 @@ int config_parse_allowed_cpuset(
|
||||
return 0;
|
||||
}
|
||||
|
||||
(void) parse_cpu_set_extend(k, c, true, unit, filename, line, lvalue);
|
||||
return 0;
|
||||
return config_parse_cpu_set(unit, filename, line, section, section_line, lvalue, ltype, k, data, userdata);
|
||||
}
|
||||
|
||||
int config_parse_memory_limit(
|
||||
@@ -5455,7 +5455,7 @@ int config_parse_extension_images(
|
||||
}
|
||||
|
||||
int config_parse_job_timeout_sec(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
@@ -5493,7 +5493,7 @@ int config_parse_job_timeout_sec(
|
||||
}
|
||||
|
||||
int config_parse_job_running_timeout_sec(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
@@ -5525,7 +5525,7 @@ int config_parse_job_running_timeout_sec(
|
||||
}
|
||||
|
||||
int config_parse_emergency_action(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
@@ -6269,27 +6269,8 @@ void unit_dump_config_items(FILE *f) {
|
||||
}
|
||||
}
|
||||
|
||||
int config_parse_cpu_affinity2(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
CPUSet *affinity = ASSERT_PTR(data);
|
||||
|
||||
(void) parse_cpu_set_extend(rvalue, affinity, true, unit, filename, line, lvalue);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_show_status(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
@@ -6315,7 +6296,7 @@ int config_parse_show_status(
|
||||
}
|
||||
|
||||
int config_parse_output_restricted(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
@@ -6362,7 +6343,7 @@ int config_parse_output_restricted(
|
||||
}
|
||||
|
||||
int config_parse_crash_chvt(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
|
||||
@@ -112,7 +112,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_private_users);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_private_pids);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_protect_control_groups);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_cpu_quota);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_allowed_cpuset);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_unit_cpu_set);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_protect_home);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_protect_hostname);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_protect_system);
|
||||
@@ -140,7 +140,6 @@ CONFIG_PARSER_PROTOTYPE(config_parse_oom_policy);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_numa_policy);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_numa_mask);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_ip_filter_bpf_progs);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_cpu_affinity2);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_show_status);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_status_unit_format);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_output_restricted);
|
||||
|
||||
+3
-3
@@ -741,9 +741,9 @@ static int parse_config_file(void) {
|
||||
{ "Manager", "CrashAction", config_parse_crash_action, 0, &arg_crash_action },
|
||||
{ "Manager", "ShowStatus", config_parse_show_status, 0, &arg_show_status },
|
||||
{ "Manager", "StatusUnitFormat", config_parse_status_unit_format, 0, &arg_status_unit_format },
|
||||
{ "Manager", "CPUAffinity", config_parse_cpu_affinity2, 0, &arg_cpu_affinity },
|
||||
{ "Manager", "CPUAffinity", config_parse_cpu_set, 0, &arg_cpu_affinity },
|
||||
{ "Manager", "NUMAPolicy", config_parse_numa_policy, 0, &arg_numa_policy.type },
|
||||
{ "Manager", "NUMAMask", config_parse_numa_mask, 0, &arg_numa_policy },
|
||||
{ "Manager", "NUMAMask", config_parse_numa_mask, 0, &arg_numa_policy.nodes },
|
||||
{ "Manager", "JoinControllers", config_parse_warn_compat, DISABLED_LEGACY, NULL },
|
||||
{ "Manager", "RuntimeWatchdogSec", config_parse_watchdog_sec, 0, &arg_runtime_watchdog },
|
||||
{ "Manager", "RuntimeWatchdogPreSec", config_parse_watchdog_sec, 0, &arg_pretimeout_watchdog },
|
||||
@@ -2787,7 +2787,7 @@ static void reset_arguments(void) {
|
||||
arg_machine_id = (sd_id128_t) {};
|
||||
arg_cad_burst_action = EMERGENCY_ACTION_REBOOT_FORCE;
|
||||
|
||||
cpu_set_reset(&arg_cpu_affinity);
|
||||
cpu_set_done(&arg_cpu_affinity);
|
||||
numa_policy_reset(&arg_numa_policy);
|
||||
|
||||
arg_random_seed = mfree(arg_random_seed);
|
||||
|
||||
@@ -455,7 +455,7 @@ empty:
|
||||
|
||||
static int effective_cpuset_build_json(sd_json_variant **ret, const char *name, void *userdata, const char *cpuset_name) {
|
||||
Unit *u = ASSERT_PTR(userdata);
|
||||
_cleanup_(cpu_set_reset) CPUSet cpus = {};
|
||||
_cleanup_(cpu_set_done) CPUSet cpus = {};
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
|
||||
@@ -2814,7 +2814,7 @@ DEFINE_STRING_TABLE_LOOKUP(split_mode, SplitMode);
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_split_mode, split_mode, SplitMode);
|
||||
|
||||
int config_parse_line_max(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
@@ -2865,7 +2865,7 @@ int config_parse_line_max(
|
||||
}
|
||||
|
||||
int config_parse_compress(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
@@ -2910,7 +2910,7 @@ int config_parse_compress(
|
||||
}
|
||||
|
||||
int config_parse_forward_to_socket(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
|
||||
@@ -978,7 +978,7 @@ static const char* const user_gc_mode_table[_USER_GC_MODE_MAX] = {
|
||||
DEFINE_STRING_TABLE_LOOKUP(user_gc_mode, UserGCMode);
|
||||
|
||||
int config_parse_tmpfs_size(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
|
||||
@@ -904,7 +904,7 @@ int config_parse_tunnel_key(
|
||||
}
|
||||
|
||||
int config_parse_ipv6_flowlabel(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
@@ -941,7 +941,7 @@ int config_parse_ipv6_flowlabel(
|
||||
}
|
||||
|
||||
int config_parse_encap_limit(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
@@ -976,7 +976,7 @@ int config_parse_encap_limit(
|
||||
}
|
||||
|
||||
int config_parse_6rd_prefix(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
@@ -1013,7 +1013,7 @@ int config_parse_6rd_prefix(
|
||||
}
|
||||
|
||||
int config_parse_erspan_version(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
@@ -1042,7 +1042,7 @@ int config_parse_erspan_version(
|
||||
}
|
||||
|
||||
int config_parse_erspan_index(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
@@ -1071,7 +1071,7 @@ int config_parse_erspan_index(
|
||||
}
|
||||
|
||||
int config_parse_erspan_direction(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
@@ -1100,7 +1100,7 @@ int config_parse_erspan_direction(
|
||||
}
|
||||
|
||||
int config_parse_erspan_hwid(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
|
||||
@@ -132,7 +132,7 @@ int can_set_netlink_message(Link *link, sd_netlink_message *m) {
|
||||
}
|
||||
|
||||
int config_parse_can_bitrate(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
@@ -171,7 +171,7 @@ int config_parse_can_bitrate(
|
||||
}
|
||||
|
||||
int config_parse_can_time_quanta(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
@@ -208,7 +208,7 @@ int config_parse_can_time_quanta(
|
||||
}
|
||||
|
||||
int config_parse_can_restart_usec(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
@@ -245,7 +245,7 @@ int config_parse_can_restart_usec(
|
||||
}
|
||||
|
||||
int config_parse_can_control_mode(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
@@ -284,7 +284,7 @@ int config_parse_can_control_mode(
|
||||
}
|
||||
|
||||
int config_parse_can_termination(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
|
||||
@@ -338,7 +338,7 @@ int link_get_captive_portal(Link *link, const char **ret) {
|
||||
}
|
||||
|
||||
int config_parse_dhcp(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
@@ -383,7 +383,7 @@ int config_parse_dhcp(
|
||||
}
|
||||
|
||||
int config_parse_dhcp_route_metric(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
@@ -492,7 +492,7 @@ int config_parse_ndisc_route_metric(
|
||||
}
|
||||
|
||||
int config_parse_dhcp_send_hostname(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
|
||||
@@ -887,7 +887,7 @@ int link_serialize_dhcp6_client(Link *link, FILE *f) {
|
||||
}
|
||||
|
||||
int config_parse_dhcp6_pd_prefix_hint(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
|
||||
@@ -346,7 +346,7 @@ int ipv4ll_update_mac(Link *link) {
|
||||
}
|
||||
|
||||
int config_parse_ipv4ll(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
@@ -387,7 +387,7 @@ int config_parse_ipv4ll(
|
||||
}
|
||||
|
||||
int config_parse_ipv4ll_address(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
|
||||
@@ -783,7 +783,7 @@ DEFINE_STRING_TABLE_LOOKUP(ip_reverse_path_filter, IPReversePathFilter);
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_ip_reverse_path_filter, ip_reverse_path_filter, IPReversePathFilter);
|
||||
|
||||
int config_parse_ip_forward_deprecated(
|
||||
const char* unit,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
|
||||
@@ -55,7 +55,7 @@ Exec.LimitRTTIME, config_parse_rlimit, RLIMIT_RTTIME,
|
||||
Exec.Hostname, config_parse_hostname, 0, offsetof(Settings, hostname)
|
||||
Exec.NoNewPrivileges, config_parse_tristate, 0, offsetof(Settings, no_new_privileges)
|
||||
Exec.OOMScoreAdjust, config_parse_oom_score_adjust, 0, 0
|
||||
Exec.CPUAffinity, config_parse_cpu_affinity, 0, 0
|
||||
Exec.CPUAffinity, config_parse_cpu_set, 0, offsetof(Settings, cpu_set)
|
||||
Exec.ResolvConf, config_parse_resolv_conf, 0, offsetof(Settings, resolv_conf)
|
||||
Exec.LinkJournal, config_parse_link_journal, 0, 0
|
||||
Exec.Timezone, config_parse_timezone_mode, 0, offsetof(Settings, timezone)
|
||||
|
||||
@@ -1240,10 +1240,7 @@ static int oci_cgroup_cpu_cpus(const char *name, sd_json_variant *v, sd_json_dis
|
||||
if (r < 0)
|
||||
return json_log(v, flags, r, "Failed to parse CPU set specification: %s", n);
|
||||
|
||||
cpu_set_reset(&data->cpu_set);
|
||||
data->cpu_set = set;
|
||||
|
||||
return 0;
|
||||
return cpu_set_done_and_replace(data->cpu_set, set);
|
||||
}
|
||||
|
||||
static int oci_cgroup_cpu(const char *name, sd_json_variant *v, sd_json_dispatch_flags_t flags, void *userdata) {
|
||||
@@ -1270,12 +1267,11 @@ static int oci_cgroup_cpu(const char *name, sd_json_variant *v, sd_json_dispatch
|
||||
|
||||
r = oci_dispatch(v, table, flags, &data);
|
||||
if (r < 0) {
|
||||
cpu_set_reset(&data.cpu_set);
|
||||
cpu_set_done(&data.cpu_set);
|
||||
return r;
|
||||
}
|
||||
|
||||
cpu_set_reset(&s->cpu_set);
|
||||
s->cpu_set = data.cpu_set;
|
||||
cpu_set_done_and_replace(s->cpu_set, data.cpu_set);
|
||||
|
||||
if (data.weight != UINT64_MAX) {
|
||||
r = settings_allocate_properties(s);
|
||||
|
||||
@@ -136,7 +136,7 @@ Settings* settings_free(Settings *s) {
|
||||
strv_free(s->syscall_deny_list);
|
||||
rlimit_free_all(s->rlimit);
|
||||
free(s->hostname);
|
||||
cpu_set_reset(&s->cpu_set);
|
||||
cpu_set_done(&s->cpu_set);
|
||||
strv_free(s->bind_user);
|
||||
|
||||
strv_free(s->network_interfaces);
|
||||
@@ -817,25 +817,6 @@ int config_parse_oom_score_adjust(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_cpu_affinity(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
Settings *settings = ASSERT_PTR(data);
|
||||
|
||||
assert(rvalue);
|
||||
|
||||
return parse_cpu_set_extend(rvalue, &settings->cpu_set, true, unit, filename, line, lvalue);
|
||||
}
|
||||
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_resolv_conf, resolv_conf_mode, ResolvConfMode);
|
||||
|
||||
static const char *const resolv_conf_mode_table[_RESOLV_CONF_MODE_MAX] = {
|
||||
|
||||
@@ -264,7 +264,6 @@ CONFIG_PARSER_PROTOTYPE(config_parse_pid2);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_private_users);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_syscall_filter);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_oom_score_adjust);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_cpu_affinity);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_resolv_conf);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_link_journal);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_timezone_mode);
|
||||
|
||||
+4
-7
@@ -279,7 +279,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_syscall_deny_list, strv_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_seccomp, seccomp_releasep);
|
||||
#endif
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_credentials, machine_credential_context_done);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_cpu_set, cpu_set_reset);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_cpu_set, cpu_set_done);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_sysctl, strv_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_bind_user, strv_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_settings_filename, freep);
|
||||
@@ -1460,8 +1460,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse CPU affinity mask %s: %m", optarg);
|
||||
|
||||
cpu_set_reset(&arg_cpu_set);
|
||||
arg_cpu_set = cpuset;
|
||||
cpu_set_done_and_replace(arg_cpu_set, cpuset);
|
||||
arg_settings_mask |= SETTING_CPU_AFFINITY;
|
||||
break;
|
||||
}
|
||||
@@ -4908,10 +4907,8 @@ static int merge_settings(Settings *settings, const char *path) {
|
||||
|
||||
if (!arg_settings_trusted)
|
||||
log_warning("Ignoring CPUAffinity= setting, file '%s' is not trusted.", path);
|
||||
else {
|
||||
cpu_set_reset(&arg_cpu_set);
|
||||
arg_cpu_set = TAKE_STRUCT(settings->cpu_set);
|
||||
}
|
||||
else
|
||||
cpu_set_done_and_replace(arg_cpu_set, settings->cpu_set);
|
||||
}
|
||||
|
||||
if ((arg_settings_mask & SETTING_RESOLV_CONF) == 0 &&
|
||||
|
||||
@@ -615,7 +615,8 @@ static int bus_append_cgroup_property(sd_bus_message *m, const char *field, cons
|
||||
"StartupAllowedCPUs",
|
||||
"AllowedMemoryNodes",
|
||||
"StartupAllowedMemoryNodes")) {
|
||||
_cleanup_(cpu_set_reset) CPUSet cpuset = {};
|
||||
|
||||
_cleanup_(cpu_set_done) CPUSet cpuset = {};
|
||||
_cleanup_free_ uint8_t *array = NULL;
|
||||
size_t allocated;
|
||||
|
||||
@@ -1564,7 +1565,7 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
|
||||
}
|
||||
|
||||
if (streq(field, "CPUAffinity")) {
|
||||
_cleanup_(cpu_set_reset) CPUSet cpuset = {};
|
||||
_cleanup_(cpu_set_done) CPUSet cpuset = {};
|
||||
_cleanup_free_ uint8_t *array = NULL;
|
||||
size_t allocated;
|
||||
|
||||
@@ -1599,7 +1600,7 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
|
||||
}
|
||||
|
||||
if (streq(field, "NUMAMask")) {
|
||||
_cleanup_(cpu_set_reset) CPUSet nodes = {};
|
||||
_cleanup_(cpu_set_done) CPUSet nodes = {};
|
||||
_cleanup_free_ uint8_t *array = NULL;
|
||||
size_t allocated;
|
||||
|
||||
|
||||
+236
-202
@@ -5,6 +5,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "bitfield.h"
|
||||
#include "cpu-set-util.h"
|
||||
#include "extract-word.h"
|
||||
#include "hexdecoct.h"
|
||||
@@ -12,75 +13,71 @@
|
||||
#include "parse-util.h"
|
||||
#include "string-util.h"
|
||||
|
||||
char* cpu_set_to_string(const CPUSet *a) {
|
||||
_cleanup_free_ char *str = NULL;
|
||||
size_t len = 0;
|
||||
int i, r;
|
||||
/* As of kernel 5.1, CONFIG_NR_CPUS can be set to 8192 on PowerPC */
|
||||
#define CPU_SET_MAX_NCPU 8192
|
||||
|
||||
for (i = 0; (size_t) i < a->allocated * 8; i++) {
|
||||
if (!CPU_ISSET_S(i, a->allocated, a->set))
|
||||
char* cpu_set_to_string(const CPUSet *c) {
|
||||
_cleanup_free_ char *str = NULL;
|
||||
|
||||
assert(c);
|
||||
|
||||
for (size_t i = 0; i < c->allocated * 8; i++) {
|
||||
if (!CPU_ISSET_S(i, c->allocated, c->set))
|
||||
continue;
|
||||
|
||||
if (!GREEDY_REALLOC(str, len + 1 + DECIMAL_STR_MAX(int)))
|
||||
if (strextendf_with_separator(&str, " ", "%zu", i) < 0)
|
||||
return NULL;
|
||||
|
||||
r = sprintf(str + len, len > 0 ? " %d" : "%d", i);
|
||||
assert_se(r > 0);
|
||||
len += r;
|
||||
}
|
||||
|
||||
return TAKE_PTR(str) ?: strdup("");
|
||||
}
|
||||
|
||||
char* cpu_set_to_range_string(const CPUSet *set) {
|
||||
unsigned range_start = 0, range_end;
|
||||
_cleanup_free_ char *str = NULL;
|
||||
bool in_range = false;
|
||||
size_t len = 0;
|
||||
int r;
|
||||
static int add_range(char **str, size_t start, size_t end) {
|
||||
assert(str);
|
||||
assert(start <= end);
|
||||
|
||||
for (unsigned i = 0; i < set->allocated * 8; i++)
|
||||
if (CPU_ISSET_S(i, set->allocated, set->set)) {
|
||||
if (start == end)
|
||||
return strextendf_with_separator(str, " ", "%zu", start);
|
||||
|
||||
return strextendf_with_separator(str, " ", "%zu-%zu", start, end);
|
||||
}
|
||||
|
||||
char* cpu_set_to_range_string(const CPUSet *c) {
|
||||
_cleanup_free_ char *str = NULL;
|
||||
size_t start = 0, end;
|
||||
bool in_range = false;
|
||||
|
||||
assert(c);
|
||||
|
||||
for (size_t i = 0; i < c->allocated * 8; i++) {
|
||||
if (CPU_ISSET_S(i, c->allocated, c->set)) {
|
||||
if (in_range)
|
||||
range_end++;
|
||||
end++;
|
||||
else {
|
||||
range_start = range_end = i;
|
||||
start = end = i;
|
||||
in_range = true;
|
||||
}
|
||||
} else if (in_range) {
|
||||
in_range = false;
|
||||
|
||||
if (!GREEDY_REALLOC(str, len + 2 + 2 * DECIMAL_STR_MAX(unsigned)))
|
||||
return NULL;
|
||||
|
||||
if (range_end > range_start)
|
||||
r = sprintf(str + len, len > 0 ? " %u-%u" : "%u-%u", range_start, range_end);
|
||||
else
|
||||
r = sprintf(str + len, len > 0 ? " %u" : "%u", range_start);
|
||||
assert_se(r > 0);
|
||||
len += r;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (in_range) {
|
||||
if (!GREEDY_REALLOC(str, len + 2 + 2 * DECIMAL_STR_MAX(int)))
|
||||
if (in_range && add_range(&str, start, end) < 0)
|
||||
return NULL;
|
||||
|
||||
if (range_end > range_start)
|
||||
r = sprintf(str + len, len > 0 ? " %u-%u" : "%u-%u", range_start, range_end);
|
||||
else
|
||||
r = sprintf(str + len, len > 0 ? " %u" : "%u", range_start);
|
||||
assert_se(r > 0);
|
||||
in_range = false;
|
||||
}
|
||||
|
||||
if (in_range && add_range(&str, start, end) < 0)
|
||||
return NULL;
|
||||
|
||||
return TAKE_PTR(str) ?: strdup("");
|
||||
}
|
||||
|
||||
char* cpu_set_to_mask_string(const CPUSet *a) {
|
||||
char* cpu_set_to_mask_string(const CPUSet *c) {
|
||||
_cleanup_free_ char *str = NULL;
|
||||
size_t len = 0;
|
||||
bool found_nonzero = false;
|
||||
int r;
|
||||
|
||||
assert(a);
|
||||
assert(c);
|
||||
|
||||
/* Return CPU set in hexadecimal bitmap mask, e.g.
|
||||
* CPU 0 -> "1"
|
||||
@@ -97,177 +94,233 @@ char* cpu_set_to_mask_string(const CPUSet *a) {
|
||||
* CPU 0-63 -> "ffffffff,ffffffff"
|
||||
* CPU 0-71 -> "ff,ffffffff,ffffffff" */
|
||||
|
||||
for (ssize_t i = a->allocated * 8; i >= 0; i -= 4) {
|
||||
uint8_t m = 0;
|
||||
for (size_t i = c->allocated * 8; i > 0; ) {
|
||||
uint32_t m = 0;
|
||||
|
||||
for (size_t j = 0; j < 4; j++)
|
||||
if (CPU_ISSET_S(i + j, a->allocated, a->set))
|
||||
m |= 1U << j;
|
||||
for (int j = (i % 32 ?: 32) - 1; j >= 0; j--)
|
||||
if (CPU_ISSET_S(--i, c->allocated, c->set))
|
||||
SET_BIT(m, j);
|
||||
|
||||
if (!found_nonzero)
|
||||
found_nonzero = m > 0;
|
||||
if (!found_nonzero) {
|
||||
if (m == 0)
|
||||
continue;
|
||||
|
||||
if (!found_nonzero && m == 0)
|
||||
/* Skip leading zeros */
|
||||
continue;
|
||||
|
||||
if (!GREEDY_REALLOC(str, len + 3))
|
||||
r = strextendf_with_separator(&str, ",", "%" PRIx32, m);
|
||||
} else
|
||||
r = strextendf_with_separator(&str, ",", "%08" PRIx32, m);
|
||||
if (r < 0)
|
||||
return NULL;
|
||||
|
||||
str[len++] = hexchar(m);
|
||||
if (i >= 4 && i % 32 == 0)
|
||||
/* Separate by comma for each 32 CPUs. */
|
||||
str[len++] = ',';
|
||||
str[len] = 0;
|
||||
found_nonzero = true;
|
||||
}
|
||||
|
||||
return TAKE_PTR(str) ?: strdup("0");
|
||||
}
|
||||
|
||||
CPUSet* cpu_set_free(CPUSet *c) {
|
||||
if (!c)
|
||||
return c;
|
||||
void cpu_set_done(CPUSet *c) {
|
||||
assert(c);
|
||||
|
||||
cpu_set_reset(c);
|
||||
return mfree(c);
|
||||
if (c->set)
|
||||
CPU_FREE(c->set);
|
||||
|
||||
*c = (CPUSet) {};
|
||||
}
|
||||
|
||||
int cpu_set_realloc(CPUSet *cpu_set, unsigned ncpus) {
|
||||
size_t need;
|
||||
int cpu_set_realloc(CPUSet *c, size_t n) {
|
||||
assert(c);
|
||||
|
||||
assert(cpu_set);
|
||||
if (n > CPU_SET_MAX_NCPU)
|
||||
return -ERANGE;
|
||||
|
||||
need = CPU_ALLOC_SIZE(ncpus);
|
||||
if (need > cpu_set->allocated) {
|
||||
cpu_set_t *t;
|
||||
n = CPU_ALLOC_SIZE(n);
|
||||
if (n <= c->allocated)
|
||||
return 0;
|
||||
|
||||
t = realloc(cpu_set->set, need);
|
||||
if (!t)
|
||||
return -ENOMEM;
|
||||
|
||||
memzero((uint8_t*) t + cpu_set->allocated, need - cpu_set->allocated);
|
||||
|
||||
cpu_set->set = t;
|
||||
cpu_set->allocated = need;
|
||||
}
|
||||
if (!GREEDY_REALLOC0(c->set, DIV_ROUND_UP(n, sizeof(cpu_set_t))))
|
||||
return -ENOMEM;
|
||||
|
||||
c->allocated = n;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cpu_set_add(CPUSet *cpu_set, unsigned cpu) {
|
||||
int cpu_set_add(CPUSet *c, size_t i) {
|
||||
int r;
|
||||
|
||||
if (cpu >= 8192)
|
||||
/* As of kernel 5.1, CONFIG_NR_CPUS can be set to 8192 on PowerPC */
|
||||
assert(c);
|
||||
|
||||
/* cpu_set_realloc() has similar check, but for avoiding overflow. */
|
||||
if (i >= CPU_SET_MAX_NCPU)
|
||||
return -ERANGE;
|
||||
|
||||
r = cpu_set_realloc(cpu_set, cpu + 1);
|
||||
r = cpu_set_realloc(c, i + 1);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
CPU_SET_S(cpu, cpu_set->allocated, cpu_set->set);
|
||||
CPU_SET_S(i, c->allocated, c->set);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cpu_set_add_all(CPUSet *a, const CPUSet *b) {
|
||||
int cpu_set_add_set(CPUSet *c, const CPUSet *src) {
|
||||
int r;
|
||||
|
||||
/* Do this backwards, so if we fail, we fail before changing anything. */
|
||||
for (unsigned cpu_p1 = b->allocated * 8; cpu_p1 > 0; cpu_p1--)
|
||||
if (CPU_ISSET_S(cpu_p1 - 1, b->allocated, b->set)) {
|
||||
r = cpu_set_add(a, cpu_p1 - 1);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
assert(c);
|
||||
assert(src);
|
||||
|
||||
r = cpu_set_realloc(c, src->allocated * 8);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
for (size_t i = 0; i < src->allocated * 8; i++)
|
||||
if (CPU_ISSET_S(i, src->allocated, src->set))
|
||||
CPU_SET_S(i, c->allocated, c->set);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int parse_cpu_set_full(
|
||||
const char *rvalue,
|
||||
CPUSet *cpu_set,
|
||||
bool warn,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *lvalue) {
|
||||
static int cpu_set_add_range(CPUSet *c, size_t start, size_t end) {
|
||||
int r;
|
||||
|
||||
_cleanup_(cpu_set_reset) CPUSet c = {};
|
||||
const char *p = ASSERT_PTR(rvalue);
|
||||
assert(c);
|
||||
assert(start <= end);
|
||||
|
||||
assert(cpu_set);
|
||||
/* cpu_set_realloc() has similar check, but for avoiding overflow. */
|
||||
if (end >= CPU_SET_MAX_NCPU)
|
||||
return -ERANGE;
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *word = NULL;
|
||||
unsigned cpu_lower, cpu_upper;
|
||||
int r;
|
||||
r = cpu_set_realloc(c, end + 1);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = extract_first_word(&p, &word, WHITESPACE ",", EXTRACT_UNQUOTE);
|
||||
if (r == -ENOMEM)
|
||||
return warn ? log_oom() : -ENOMEM;
|
||||
if (r < 0)
|
||||
return warn ? log_syntax(unit, LOG_ERR, filename, line, r, "Invalid value for %s: %s", lvalue, rvalue) : r;
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
r = parse_range(word, &cpu_lower, &cpu_upper);
|
||||
if (r < 0)
|
||||
return warn ? log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CPU affinity '%s'", word) : r;
|
||||
|
||||
if (cpu_lower > cpu_upper) {
|
||||
if (warn)
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0, "Range '%s' is invalid, %u > %u, ignoring.",
|
||||
word, cpu_lower, cpu_upper);
|
||||
|
||||
/* Make sure something is allocated, to distinguish this from the empty case */
|
||||
r = cpu_set_realloc(&c, 1);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
for (unsigned cpu_p1 = MIN(cpu_upper, UINT_MAX-1) + 1; cpu_p1 > cpu_lower; cpu_p1--) {
|
||||
r = cpu_set_add(&c, cpu_p1 - 1);
|
||||
if (r < 0)
|
||||
return warn ? log_syntax(unit, LOG_ERR, filename, line, r,
|
||||
"Cannot add CPU %u to set: %m", cpu_p1 - 1) : r;
|
||||
}
|
||||
}
|
||||
|
||||
*cpu_set = TAKE_STRUCT(c);
|
||||
for (size_t i = start; i <= end; i++)
|
||||
CPU_SET_S(i, c->allocated, c->set);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_cpu_set_extend(
|
||||
const char *rvalue,
|
||||
CPUSet *old,
|
||||
bool warn,
|
||||
int cpu_set_add_all(CPUSet *c) {
|
||||
assert(c);
|
||||
|
||||
long m = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
if (m < 0)
|
||||
return -errno;
|
||||
if (m == 0)
|
||||
return -ENXIO;
|
||||
|
||||
return cpu_set_add_range(c, 0, m - 1);
|
||||
}
|
||||
|
||||
int config_parse_cpu_set(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *lvalue) {
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype, /* 0 when used as conf parser, 1 when used as usual parser */
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
_cleanup_(cpu_set_reset) CPUSet cpuset = {};
|
||||
int r;
|
||||
CPUSet *c = ASSERT_PTR(data);
|
||||
int r, level = ltype ? LOG_DEBUG : LOG_DEBUG;
|
||||
bool critical = ltype;
|
||||
|
||||
assert(old);
|
||||
assert(critical || lvalue);
|
||||
|
||||
r = parse_cpu_set_full(rvalue, &cpuset, true, unit, filename, line, lvalue);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!cpuset.set) {
|
||||
/* An empty assignment resets the CPU list */
|
||||
cpu_set_reset(old);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!old->set) {
|
||||
*old = TAKE_STRUCT(cpuset);
|
||||
if (isempty(rvalue)) {
|
||||
cpu_set_done(c);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return cpu_set_add_all(old, &cpuset);
|
||||
_cleanup_(cpu_set_done) CPUSet cpuset = {};
|
||||
for (const char *p = rvalue;;) {
|
||||
_cleanup_free_ char *word = NULL;
|
||||
|
||||
r = extract_first_word(&p, &word, WHITESPACE ",", EXTRACT_UNQUOTE);
|
||||
if (r == -ENOMEM)
|
||||
return log_oom_full(level);
|
||||
if (r < 0) {
|
||||
if (critical)
|
||||
return log_debug_errno(r, "Failed to parse CPU set: %s", rvalue);
|
||||
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse %s= setting, ignoring assignment: %s",
|
||||
lvalue, rvalue);
|
||||
return 0;
|
||||
}
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
unsigned lower, upper;
|
||||
r = parse_range(word, &lower, &upper);
|
||||
if (r < 0) {
|
||||
if (critical)
|
||||
return log_debug_errno(r, "Failed to parse CPU range: %s", word);
|
||||
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to parse CPU range, ignoring assignment: %s", word);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lower > upper) {
|
||||
if (critical)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Invalid CPU range (%u > %u): %s",
|
||||
lower, upper, word);
|
||||
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Invalid CPU range (%u > %u), ignoring assignment: %s",
|
||||
lower, upper, word);
|
||||
continue;
|
||||
}
|
||||
|
||||
r = cpu_set_add_range(&cpuset, lower, upper);
|
||||
if (r == -ENOMEM)
|
||||
return log_oom_full(level);
|
||||
if (r < 0) {
|
||||
if (critical)
|
||||
return log_debug_errno(r, "Failed to set CPU(s) '%s': %m", word);
|
||||
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to set CPU(s), ignoring assignment: %s", word);
|
||||
}
|
||||
}
|
||||
|
||||
if (!c->set) {
|
||||
*c = TAKE_STRUCT(cpuset);
|
||||
return 1;
|
||||
}
|
||||
|
||||
r = cpu_set_add_set(c, &cpuset);
|
||||
if (r == -ENOMEM)
|
||||
return log_oom_full(level);
|
||||
assert(r >= 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int parse_cpu_set(const char *s, CPUSet *ret) {
|
||||
_cleanup_(cpu_set_done) CPUSet c = {};
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(ret);
|
||||
|
||||
r = config_parse_cpu_set(
|
||||
/* unit = */ NULL,
|
||||
/* filename = */ NULL,
|
||||
/* line = */ 0,
|
||||
/* section = */ NULL,
|
||||
/* section_line = */ 0,
|
||||
/* lvalue = */ NULL,
|
||||
/* ltype = */ 1,
|
||||
/* rvalue = */ s,
|
||||
/* data = */ &c,
|
||||
/* userdata = */ NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = TAKE_STRUCT(c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cpus_in_affinity_mask(void) {
|
||||
@@ -304,58 +357,39 @@ int cpus_in_affinity_mask(void) {
|
||||
}
|
||||
}
|
||||
|
||||
int cpu_set_to_dbus(const CPUSet *set, uint8_t **ret, size_t *allocated) {
|
||||
uint8_t *out;
|
||||
|
||||
assert(set);
|
||||
int cpu_set_to_dbus(const CPUSet *c, uint8_t **ret, size_t *ret_size) {
|
||||
assert(c);
|
||||
assert(ret);
|
||||
assert(ret_size);
|
||||
|
||||
out = new0(uint8_t, set->allocated);
|
||||
if (!out)
|
||||
uint8_t *buf = new0(uint8_t, c->allocated);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
for (unsigned cpu = 0; cpu < set->allocated * 8; cpu++)
|
||||
if (CPU_ISSET_S(cpu, set->allocated, set->set))
|
||||
out[cpu / 8] |= 1u << (cpu % 8);
|
||||
for (size_t i = 0; i < c->allocated * 8; i++)
|
||||
if (CPU_ISSET_S(i, c->allocated, c->set))
|
||||
SET_BIT(buf[i / 8], i % 8);
|
||||
|
||||
*ret = out;
|
||||
*allocated = set->allocated;
|
||||
*ret = buf;
|
||||
*ret_size = c->allocated;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cpu_set_from_dbus(const uint8_t *bits, size_t size, CPUSet *set) {
|
||||
_cleanup_(cpu_set_reset) CPUSet s = {};
|
||||
int cpu_set_from_dbus(const uint8_t *bits, size_t size, CPUSet *ret) {
|
||||
_cleanup_(cpu_set_done) CPUSet c = {};
|
||||
int r;
|
||||
|
||||
assert(bits);
|
||||
assert(set);
|
||||
assert(bits || size == 0);
|
||||
assert(ret);
|
||||
|
||||
for (unsigned cpu = size * 8; cpu > 0; cpu--)
|
||||
if (bits[(cpu - 1) / 8] & (1u << ((cpu - 1) % 8))) {
|
||||
r = cpu_set_add(&s, cpu - 1);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
*set = TAKE_STRUCT(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cpu_mask_add_all(CPUSet *mask) {
|
||||
long m;
|
||||
int r;
|
||||
|
||||
assert(mask);
|
||||
|
||||
m = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
if (m < 0)
|
||||
return -errno;
|
||||
|
||||
for (unsigned i = 0; i < (unsigned) m; i++) {
|
||||
r = cpu_set_add(mask, i);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
r = cpu_set_realloc(&c, size * 8);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
for (size_t i = 0; i < size * 8; i++)
|
||||
if (BIT_SET(bits[i / 8], i % 8))
|
||||
CPU_SET_S(i, c.allocated, c.set);
|
||||
|
||||
*ret = TAKE_STRUCT(c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+20
-37
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <sched.h>
|
||||
|
||||
#include "conf-parser-forward.h"
|
||||
#include "forward.h"
|
||||
|
||||
/* This wraps the libc interface with a variable to keep the allocated size. */
|
||||
@@ -11,46 +12,28 @@ typedef struct CPUSet {
|
||||
size_t allocated; /* in bytes */
|
||||
} CPUSet;
|
||||
|
||||
static inline void cpu_set_reset(CPUSet *a) {
|
||||
assert((a->allocated > 0) == !!a->set);
|
||||
if (a->set)
|
||||
CPU_FREE(a->set);
|
||||
*a = (CPUSet) {};
|
||||
}
|
||||
void cpu_set_done(CPUSet *c);
|
||||
#define cpu_set_done_and_replace(a, b) \
|
||||
({ \
|
||||
CPUSet *_a = &(a), *_b = &(b); \
|
||||
cpu_set_done(_a); \
|
||||
*_a = TAKE_STRUCT(*_b); \
|
||||
0; \
|
||||
})
|
||||
|
||||
CPUSet* cpu_set_free(CPUSet *c);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(CPUSet*, cpu_set_free);
|
||||
int cpu_set_realloc(CPUSet *c, size_t n);
|
||||
int cpu_set_add(CPUSet *c, size_t i);
|
||||
int cpu_set_add_set(CPUSet *c, const CPUSet *src);
|
||||
int cpu_set_add_all(CPUSet *c);
|
||||
|
||||
int cpu_set_add_all(CPUSet *a, const CPUSet *b);
|
||||
int cpu_set_add(CPUSet *a, unsigned cpu);
|
||||
char* cpu_set_to_string(const CPUSet *c);
|
||||
char* cpu_set_to_range_string(const CPUSet *c);
|
||||
char* cpu_set_to_mask_string(const CPUSet *c);
|
||||
|
||||
char* cpu_set_to_string(const CPUSet *a);
|
||||
char* cpu_set_to_range_string(const CPUSet *a);
|
||||
char* cpu_set_to_mask_string(const CPUSet *a);
|
||||
int cpu_set_realloc(CPUSet *cpu_set, unsigned ncpus);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_cpu_set);
|
||||
int parse_cpu_set(const char *s, CPUSet *ret);
|
||||
|
||||
int parse_cpu_set_full(
|
||||
const char *rvalue,
|
||||
CPUSet *cpu_set,
|
||||
bool warn,
|
||||
const char *unit,
|
||||
const char *filename, unsigned line,
|
||||
const char *lvalue);
|
||||
int parse_cpu_set_extend(
|
||||
const char *rvalue,
|
||||
CPUSet *old,
|
||||
bool warn,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *lvalue);
|
||||
|
||||
static inline int parse_cpu_set(const char *rvalue, CPUSet *cpu_set){
|
||||
return parse_cpu_set_full(rvalue, cpu_set, false, NULL, NULL, 0, NULL);
|
||||
}
|
||||
|
||||
int cpu_set_to_dbus(const CPUSet *set, uint8_t **ret, size_t *allocated);
|
||||
int cpu_set_from_dbus(const uint8_t *bits, size_t size, CPUSet *set);
|
||||
int cpu_set_to_dbus(const CPUSet *c, uint8_t **ret, size_t *ret_size);
|
||||
int cpu_set_from_dbus(const uint8_t *bits, size_t size, CPUSet *ret);
|
||||
|
||||
int cpus_in_affinity_mask(void);
|
||||
int cpu_mask_add_all(CPUSet *mask);
|
||||
|
||||
@@ -91,17 +91,15 @@ int apply_numa_policy(const NUMAPolicy *policy) {
|
||||
}
|
||||
|
||||
int numa_to_cpu_set(const NUMAPolicy *policy, CPUSet *ret) {
|
||||
_cleanup_(cpu_set_done) CPUSet s = {};
|
||||
int r;
|
||||
size_t i;
|
||||
_cleanup_(cpu_set_reset) CPUSet s = {};
|
||||
|
||||
assert(policy);
|
||||
assert(ret);
|
||||
|
||||
for (i = 0; i < policy->nodes.allocated * 8; i++) {
|
||||
for (size_t i = 0; i < policy->nodes.allocated * 8; i++) {
|
||||
_cleanup_free_ char *l = NULL;
|
||||
char p[STRLEN("/sys/devices/system/node/node//cpulist") + DECIMAL_STR_MAX(size_t) + 1];
|
||||
_cleanup_(cpu_set_reset) CPUSet part = {};
|
||||
|
||||
if (!CPU_ISSET_S(i, policy->nodes.allocated, policy->nodes.set))
|
||||
continue;
|
||||
@@ -112,11 +110,12 @@ int numa_to_cpu_set(const NUMAPolicy *policy, CPUSet *ret) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_(cpu_set_done) CPUSet part = {};
|
||||
r = parse_cpu_set(l, &part);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = cpu_set_add_all(&s, &part);
|
||||
r = cpu_set_add_set(&s, &part);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ static inline int numa_policy_get_type(const NUMAPolicy *p) {
|
||||
|
||||
static inline void numa_policy_reset(NUMAPolicy *p) {
|
||||
assert(p);
|
||||
cpu_set_reset(&p->nodes);
|
||||
cpu_set_done(&p->nodes);
|
||||
p->type = -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1775,7 +1775,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
|
||||
"EffectiveCPUs", "EffectiveMemoryNodes")) {
|
||||
|
||||
_cleanup_free_ char *affinity = NULL;
|
||||
_cleanup_(cpu_set_reset) CPUSet set = {};
|
||||
_cleanup_(cpu_set_done) CPUSet set = {};
|
||||
const void *a;
|
||||
size_t n;
|
||||
|
||||
|
||||
@@ -38,139 +38,137 @@ TEST(parse_cpu_set) {
|
||||
/* empty */
|
||||
ASSERT_CPUSET_EMPTY(c);
|
||||
ASSERT_CPUSET_STRING(c, "", "", "0");
|
||||
cpu_set_reset(&c);
|
||||
cpu_set_done(&c);
|
||||
|
||||
/* Single value */
|
||||
ASSERT_OK(parse_cpu_set_full("0", &c, true, NULL, "fake", 1, "CPUAffinity"));
|
||||
ASSERT_OK(parse_cpu_set("0", &c));
|
||||
ASSERT_CPUSET_COUNT(c, 1);
|
||||
ASSERT_CPUSET_ISSET(c, 0);
|
||||
ASSERT_CPUSET_STRING(c, "0", "0", "1");
|
||||
cpu_set_reset(&c);
|
||||
cpu_set_done(&c);
|
||||
|
||||
/* Simple range (from CPUAffinity example) */
|
||||
ASSERT_OK(parse_cpu_set_full("1 2 4", &c, true, NULL, "fake", 1, "CPUAffinity"));
|
||||
ASSERT_OK(parse_cpu_set("1 2 4", &c));
|
||||
ASSERT_CPUSET_COUNT(c, 3);
|
||||
ASSERT_CPUSET_ISSET(c, 1);
|
||||
ASSERT_CPUSET_ISSET(c, 2);
|
||||
ASSERT_CPUSET_ISSET(c, 4);
|
||||
ASSERT_CPUSET_STRING(c, "1 2 4", "1-2 4", "16");
|
||||
cpu_set_reset(&c);
|
||||
cpu_set_done(&c);
|
||||
|
||||
/* A more interesting range */
|
||||
ASSERT_OK(parse_cpu_set_full("0 1 2 3 8 9 10 11", &c, true, NULL, "fake", 1, "CPUAffinity"));
|
||||
ASSERT_OK(parse_cpu_set("0 1 2 3 8 9 10 11", &c));
|
||||
ASSERT_CPUSET_COUNT(c, 8);
|
||||
for (unsigned i = 0; i < 4; i++)
|
||||
ASSERT_CPUSET_ISSET(c, i);
|
||||
for (unsigned i = 8; i < 12; i++)
|
||||
ASSERT_CPUSET_ISSET(c, i);
|
||||
ASSERT_CPUSET_STRING(c, "0 1 2 3 8 9 10 11", "0-3 8-11", "f0f");
|
||||
cpu_set_reset(&c);
|
||||
cpu_set_done(&c);
|
||||
|
||||
/* Quoted strings */
|
||||
ASSERT_OK(parse_cpu_set_full("8 '9' 10 \"11\"", &c, true, NULL, "fake", 1, "CPUAffinity"));
|
||||
ASSERT_OK(parse_cpu_set("8 '9' 10 \"11\"", &c));
|
||||
ASSERT_CPUSET_COUNT(c, 4);
|
||||
for (unsigned i = 8; i < 12; i++)
|
||||
ASSERT_CPUSET_ISSET(c, i);
|
||||
ASSERT_CPUSET_STRING(c, "8 9 10 11", "8-11", "f00");
|
||||
cpu_set_reset(&c);
|
||||
cpu_set_done(&c);
|
||||
|
||||
/* Use commas as separators */
|
||||
ASSERT_OK(parse_cpu_set_full("0,1,2,3 8,9,10,11", &c, true, NULL, "fake", 1, "CPUAffinity"));
|
||||
ASSERT_OK(parse_cpu_set("0,1,2,3 8,9,10,11", &c));
|
||||
ASSERT_CPUSET_COUNT(c, 8);
|
||||
for (unsigned i = 0; i < 4; i++)
|
||||
ASSERT_CPUSET_ISSET(c, i);
|
||||
for (unsigned i = 8; i < 12; i++)
|
||||
ASSERT_CPUSET_ISSET(c, i);
|
||||
ASSERT_CPUSET_STRING(c, "0 1 2 3 8 9 10 11", "0-3 8-11", "f0f");
|
||||
cpu_set_reset(&c);
|
||||
cpu_set_done(&c);
|
||||
|
||||
/* Commas with spaces (and trailing comma, space) */
|
||||
ASSERT_OK(parse_cpu_set_full("0, 1, 2, 3, 4, 5, 6, 7, 63, ", &c, true, NULL, "fake", 1, "CPUAffinity"));
|
||||
ASSERT_OK(parse_cpu_set("0, 1, 2, 3, 4, 5, 6, 7, 63, ", &c));
|
||||
ASSERT_CPUSET_COUNT(c, 9);
|
||||
for (unsigned i = 0; i < 8; i++)
|
||||
ASSERT_CPUSET_ISSET(c, i);
|
||||
ASSERT_CPUSET_ISSET(c, 63);
|
||||
ASSERT_CPUSET_STRING(c, "0 1 2 3 4 5 6 7 63", "0-7 63", "80000000,000000ff");
|
||||
cpu_set_reset(&c);
|
||||
cpu_set_done(&c);
|
||||
|
||||
/* Ranges */
|
||||
ASSERT_OK(parse_cpu_set_full("0-3,8-11", &c, true, NULL, "fake", 1, "CPUAffinity"));
|
||||
ASSERT_OK(parse_cpu_set("0-3,8-11", &c));
|
||||
ASSERT_CPUSET_COUNT(c, 8);
|
||||
for (unsigned i = 0; i < 4; i++)
|
||||
ASSERT_CPUSET_ISSET(c, i);
|
||||
for (unsigned i = 8; i < 12; i++)
|
||||
ASSERT_CPUSET_ISSET(c, i);
|
||||
ASSERT_CPUSET_STRING(c, "0 1 2 3 8 9 10 11", "0-3 8-11", "f0f");
|
||||
cpu_set_reset(&c);
|
||||
cpu_set_done(&c);
|
||||
|
||||
ASSERT_OK(parse_cpu_set_full("36-39,44-47", &c, true, NULL, "fake", 1, "CPUAffinity"));
|
||||
ASSERT_OK(parse_cpu_set("36-39,44-47", &c));
|
||||
ASSERT_CPUSET_COUNT(c, 8);
|
||||
for (unsigned i = 36; i < 40; i++)
|
||||
ASSERT_CPUSET_ISSET(c, i);
|
||||
for (unsigned i = 44; i < 48; i++)
|
||||
ASSERT_CPUSET_ISSET(c, i);
|
||||
ASSERT_CPUSET_STRING(c, "36 37 38 39 44 45 46 47", "36-39 44-47", "f0f0,00000000");
|
||||
cpu_set_reset(&c);
|
||||
cpu_set_done(&c);
|
||||
|
||||
ASSERT_OK(parse_cpu_set_full("64-71", &c, true, NULL, "fake", 1, "CPUAffinity"));
|
||||
ASSERT_OK(parse_cpu_set("64-71", &c));
|
||||
ASSERT_CPUSET_COUNT(c, 8);
|
||||
for (unsigned i = 64; i < 72; i++)
|
||||
ASSERT_CPUSET_ISSET(c, i);
|
||||
ASSERT_CPUSET_STRING(c, "64 65 66 67 68 69 70 71", "64-71", "ff,00000000,00000000");
|
||||
cpu_set_reset(&c);
|
||||
cpu_set_done(&c);
|
||||
|
||||
/* Ranges with trailing comma, space */
|
||||
ASSERT_OK(parse_cpu_set_full("0-3 8-11, ", &c, true, NULL, "fake", 1, "CPUAffinity"));
|
||||
ASSERT_OK(parse_cpu_set("0-3 8-11, ", &c));
|
||||
ASSERT_CPUSET_COUNT(c, 8);
|
||||
for (unsigned i = 0; i < 4; i++)
|
||||
ASSERT_CPUSET_ISSET(c, i);
|
||||
for (unsigned i = 8; i < 12; i++)
|
||||
ASSERT_CPUSET_ISSET(c, i);
|
||||
ASSERT_CPUSET_STRING(c, "0 1 2 3 8 9 10 11", "0-3 8-11", "f0f");
|
||||
cpu_set_reset(&c);
|
||||
|
||||
/* Negative range (returns empty cpu_set) */
|
||||
ASSERT_OK(parse_cpu_set_full("3-0", &c, true, NULL, "fake", 1, "CPUAffinity"));
|
||||
ASSERT_CPUSET_COUNT(c, 0);
|
||||
ASSERT_CPUSET_STRING(c, "", "", "0");
|
||||
cpu_set_reset(&c);
|
||||
cpu_set_done(&c);
|
||||
|
||||
/* Overlapping ranges */
|
||||
ASSERT_OK(parse_cpu_set_full("0-7 4-11", &c, true, NULL, "fake", 1, "CPUAffinity"));
|
||||
ASSERT_OK(parse_cpu_set("0-7 4-11", &c));
|
||||
ASSERT_CPUSET_COUNT(c, 12);
|
||||
for (unsigned i = 0; i < 12; i++)
|
||||
ASSERT_CPUSET_ISSET(c, i);
|
||||
ASSERT_CPUSET_STRING(c, "0 1 2 3 4 5 6 7 8 9 10 11", "0-11", "fff");
|
||||
cpu_set_reset(&c);
|
||||
cpu_set_done(&c);
|
||||
|
||||
/* Mix ranges and individual CPUs */
|
||||
ASSERT_OK(parse_cpu_set_full("0,2 4-11", &c, true, NULL, "fake", 1, "CPUAffinity"));
|
||||
ASSERT_OK(parse_cpu_set("0,2 4-11", &c));
|
||||
ASSERT_CPUSET_COUNT(c, 10);
|
||||
ASSERT_CPUSET_ISSET(c, 0);
|
||||
ASSERT_CPUSET_ISSET(c, 2);
|
||||
for (unsigned i = 4; i < 12; i++)
|
||||
ASSERT_CPUSET_ISSET(c, i);
|
||||
ASSERT_CPUSET_STRING(c, "0 2 4 5 6 7 8 9 10 11", "0 2 4-11", "ff5");
|
||||
cpu_set_reset(&c);
|
||||
cpu_set_done(&c);
|
||||
|
||||
/* Negative range */
|
||||
ASSERT_ERROR(parse_cpu_set("3-0", &c), EINVAL);
|
||||
ASSERT_CPUSET_EMPTY(c);
|
||||
|
||||
/* Garbage */
|
||||
ASSERT_ERROR(parse_cpu_set_full("0 1 2 3 garbage", &c, true, NULL, "fake", 1, "CPUAffinity"), EINVAL);
|
||||
ASSERT_ERROR(parse_cpu_set("0 1 2 3 garbage", &c), EINVAL);
|
||||
ASSERT_CPUSET_EMPTY(c);
|
||||
|
||||
/* Range with garbage */
|
||||
ASSERT_ERROR(parse_cpu_set_full("0-3 8-garbage", &c, true, NULL, "fake", 1, "CPUAffinity"), EINVAL);
|
||||
ASSERT_ERROR(parse_cpu_set("0-3 8-garbage", &c), EINVAL);
|
||||
ASSERT_CPUSET_EMPTY(c);
|
||||
|
||||
/* Empty string */
|
||||
ASSERT_OK(parse_cpu_set_full("", &c, true, NULL, "fake", 1, "CPUAffinity"));
|
||||
ASSERT_OK(parse_cpu_set("", &c));
|
||||
ASSERT_CPUSET_EMPTY(c); /* empty string returns NULL */
|
||||
|
||||
/* Runaway quoted string */
|
||||
ASSERT_ERROR(parse_cpu_set_full("0 1 2 3 \"4 5 6 7 ", &c, true, NULL, "fake", 1, "CPUAffinity"), EINVAL);
|
||||
ASSERT_ERROR(parse_cpu_set("0 1 2 3 \"4 5 6 7 ", &c), EINVAL);
|
||||
ASSERT_CPUSET_EMPTY(c);
|
||||
|
||||
/* Maximum allocation */
|
||||
ASSERT_OK(parse_cpu_set_full("8000-8191", &c, true, NULL, "fake", 1, "CPUAffinity"));
|
||||
ASSERT_OK(parse_cpu_set("8000-8191", &c));
|
||||
ASSERT_CPUSET_COUNT(c, 192);
|
||||
|
||||
_cleanup_free_ char *expected_str = NULL;
|
||||
@@ -182,28 +180,41 @@ TEST(parse_cpu_set) {
|
||||
ASSERT_NOT_NULL(strextend_with_separator(&expected_mask, ",", i < 6 ? "ffffffff" : "00000000"));
|
||||
|
||||
ASSERT_CPUSET_STRING(c, expected_str, "8000-8191", expected_mask);
|
||||
cpu_set_reset(&c);
|
||||
cpu_set_done(&c);
|
||||
}
|
||||
|
||||
TEST(parse_cpu_set_extend) {
|
||||
#define parse(str, c) \
|
||||
config_parse_cpu_set( \
|
||||
"unit", \
|
||||
"filename", \
|
||||
/* line = */ 0, \
|
||||
"[Section]", \
|
||||
/* section_line = */ 0, \
|
||||
"CPUAffinity", \
|
||||
/* ltype = */ 0, \
|
||||
str, \
|
||||
c, \
|
||||
/* userdata = */ NULL)
|
||||
|
||||
TEST(config_parse_cpu_set) {
|
||||
CPUSet c = {};
|
||||
|
||||
ASSERT_OK_POSITIVE(parse_cpu_set_extend("1 3", &c, true, NULL, "fake", 1, "CPUAffinity"));
|
||||
ASSERT_OK_POSITIVE(parse("1 3", &c));
|
||||
ASSERT_CPUSET_COUNT(c, 2);
|
||||
ASSERT_CPUSET_STRING(c, "1 3", "1 3", "a");
|
||||
|
||||
ASSERT_OK_POSITIVE(parse_cpu_set_extend("4", &c, true, NULL, "fake", 1, "CPUAffinity"));
|
||||
ASSERT_OK_POSITIVE(parse("4", &c));
|
||||
ASSERT_CPUSET_COUNT(c, 3);
|
||||
ASSERT_CPUSET_STRING(c, "1 3 4", "1 3-4", "1a");
|
||||
|
||||
ASSERT_OK_ZERO(parse_cpu_set_extend("", &c, true, NULL, "fake", 1, "CPUAffinity"));
|
||||
ASSERT_OK_POSITIVE(parse("", &c));
|
||||
ASSERT_CPUSET_EMPTY(c);
|
||||
}
|
||||
|
||||
TEST(cpu_set_to_from_dbus) {
|
||||
_cleanup_(cpu_set_reset) CPUSet c = {}, c2 = {};
|
||||
_cleanup_(cpu_set_done) CPUSet c = {}, c2 = {};
|
||||
|
||||
ASSERT_OK_POSITIVE(parse_cpu_set_extend("1 3 8 100-200", &c, true, NULL, "fake", 1, "CPUAffinity"));
|
||||
ASSERT_OK(parse_cpu_set("1 3 8 100-200", &c));
|
||||
ASSERT_CPUSET_COUNT(c, 104);
|
||||
|
||||
_cleanup_free_ char *expected_str = strdup("1 3 8");
|
||||
@@ -251,4 +262,4 @@ TEST(print_cpu_alloc_size) {
|
||||
log_info("CPU_ALLOC_SIZE(8191) = %zu", CPU_ALLOC_SIZE(8191));
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN(LOG_INFO);
|
||||
DEFINE_TEST_MAIN(LOG_DEBUG);
|
||||
|
||||
@@ -331,7 +331,7 @@ static void test_exec_bindpaths(Manager *m) {
|
||||
}
|
||||
|
||||
static void test_exec_cpuaffinity(Manager *m) {
|
||||
_cleanup_(cpu_set_reset) CPUSet c = {};
|
||||
_cleanup_(cpu_set_done) CPUSet c = {};
|
||||
|
||||
ASSERT_OK(cpu_set_realloc(&c, 8192)); /* just allocate the maximum possible size */
|
||||
ASSERT_OK_ERRNO(sched_getaffinity(0, c.allocated, c.set));
|
||||
|
||||
+15
-30
@@ -12,7 +12,6 @@
|
||||
#include "condition.h"
|
||||
#include "conf-files.h"
|
||||
#include "conf-parser.h"
|
||||
#include "cpu-set-util.h"
|
||||
#include "creds-util.h"
|
||||
#include "device-private.h"
|
||||
#include "device-util.h"
|
||||
@@ -78,7 +77,7 @@ static LinkConfig* link_config_free(LinkConfig *config) {
|
||||
free(config->alias);
|
||||
free(config->wol_password_file);
|
||||
erase_and_free(config->wol_password);
|
||||
cpu_set_free(config->rps_cpu_mask);
|
||||
cpu_set_done(&config->rps_cpu_mask);
|
||||
|
||||
ordered_hashmap_free(config->sr_iov_by_section);
|
||||
|
||||
@@ -954,10 +953,10 @@ static int link_apply_rps_cpu_mask(Link *link) {
|
||||
}
|
||||
|
||||
/* Skip if the config is not specified. */
|
||||
if (!config->rps_cpu_mask)
|
||||
if (!config->rps_cpu_mask.set)
|
||||
return 0;
|
||||
|
||||
mask_str = cpu_set_to_mask_string(config->rps_cpu_mask);
|
||||
mask_str = cpu_set_to_mask_string(&config->rps_cpu_mask);
|
||||
if (!mask_str)
|
||||
return log_oom();
|
||||
|
||||
@@ -1369,49 +1368,35 @@ int config_parse_rps_cpu_mask(
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
_cleanup_(cpu_set_freep) CPUSet *allocated = NULL;
|
||||
CPUSet *mask, **rps_cpu_mask = ASSERT_PTR(data);
|
||||
CPUSet *mask = ASSERT_PTR(data);
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
*rps_cpu_mask = cpu_set_free(*rps_cpu_mask);
|
||||
return 0;
|
||||
}
|
||||
if (streq(rvalue, "disable")) {
|
||||
_cleanup_(cpu_set_done) CPUSet c = {};
|
||||
|
||||
if (*rps_cpu_mask)
|
||||
mask = *rps_cpu_mask;
|
||||
else {
|
||||
allocated = new0(CPUSet, 1);
|
||||
if (!allocated)
|
||||
r = cpu_set_realloc(&c, 1);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
mask = allocated;
|
||||
return cpu_set_done_and_replace(*mask, c);
|
||||
}
|
||||
|
||||
if (streq(rvalue, "disable"))
|
||||
cpu_set_reset(mask);
|
||||
if (streq(rvalue, "all")) {
|
||||
_cleanup_(cpu_set_done) CPUSet c = {};
|
||||
|
||||
else if (streq(rvalue, "all")) {
|
||||
r = cpu_mask_add_all(mask);
|
||||
r = cpu_set_add_all(&c);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to create CPU affinity mask representing \"all\" cpus, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
r = parse_cpu_set_extend(rvalue, mask, /* warn= */ true, unit, filename, line, lvalue);
|
||||
if (r < 0)
|
||||
return 0;
|
||||
|
||||
return cpu_set_done_and_replace(*mask, c);
|
||||
}
|
||||
|
||||
if (allocated)
|
||||
*rps_cpu_mask = TAKE_PTR(allocated);
|
||||
|
||||
return 0;
|
||||
return config_parse_cpu_set(unit, filename, line, section, section_line, lvalue, ltype, rvalue, data, userdata);
|
||||
}
|
||||
|
||||
static const char* const mac_address_policy_table[_MAC_ADDRESS_POLICY_MAX] = {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "sd-device.h"
|
||||
|
||||
#include "cpu-set-util.h"
|
||||
#include "ether-addr-util.h"
|
||||
#include "ethtool-util.h"
|
||||
#include "forward.h"
|
||||
@@ -110,7 +111,7 @@ struct LinkConfig {
|
||||
uint32_t eee_advertise[N_ADVERTISE];
|
||||
|
||||
/* Rx RPS CPU mask */
|
||||
CPUSet *rps_cpu_mask;
|
||||
CPUSet rps_cpu_mask;
|
||||
|
||||
/* SR-IOV */
|
||||
uint32_t sr_iov_num_vfs;
|
||||
|
||||
Reference in New Issue
Block a user