diff --git a/man/sd-daemon.xml b/man/sd-daemon.xml
index 84deda188..64ed5f377 100644
--- a/man/sd-daemon.xml
+++ b/man/sd-daemon.xml
@@ -68,16 +68,14 @@
#define SD_INFO "<6>" /* informational */
#define SD_DEBUG "<7>" /* debug-level messages */
- These prefixes are intended to be used in conjunction with
- stderr-based logging as implemented by systemd. If a systemd
- service definition file is configured with
- StandardError=journal,
- StandardError=syslog or
- StandardError=kmsg, these prefixes can be used
- to encode a log level in lines printed. This is similar to the
- kernel printk()-style logging. See
- klogctl2
- for more information.
+ These prefixes are intended to be used in conjunction with stderr-based logging (or stdout-based
+ logging) as implemented by systemd. If a systemd service definition file is configured with
+ StandardError=journal, StandardError=syslog or
+ StandardError=kmsg (and similar with StandardOutput=), these
+ prefixes can be used to encode a log level in lines printed. This is similar to the kernel
+ printk()-style logging. See
+ klogctl2 for more
+ information.
The log levels are identical to
syslog3's
diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
index 8f1695ad2..79a2c744c 100644
--- a/man/systemd.exec.xml
+++ b/man/systemd.exec.xml
@@ -774,10 +774,11 @@ CapabilityBoundingSet=~CAP_B CAP_C
CPUAffinity=
Controls the CPU affinity of the executed processes. Takes a list of CPU indices or ranges
- separated by either whitespace or commas. CPU ranges are specified by the lower and upper CPU indices separated
- by a dash. This option may be specified more than once, in which case the specified CPU affinity masks are
- merged. If the empty string is assigned, the mask is reset, all assignments prior to this will have no
- effect. See
+ separated by either whitespace or commas. Alternatively, takes a special "numa" value in which case systemd
+ automatically derives allowed CPU range based on the value of NUMAMask= option. CPU ranges
+ are specified by the lower and upper CPU indices separated by a dash. This option may be specified more than
+ once, in which case the specified CPU affinity masks are merged. If the empty string is assigned, the mask
+ is reset, all assignments prior to this will have no effect. See
sched_setaffinity2 for
details.
diff --git a/man/systemd.service.xml b/man/systemd.service.xml
index e178724c5..17e446e20 100644
--- a/man/systemd.service.xml
+++ b/man/systemd.service.xml
@@ -217,8 +217,7 @@
this notification message has been sent. If this option is used, NotifyAccess= (see
below) should be set to open access to the notification socket provided by systemd. If
NotifyAccess= is missing or set to , it will be forcibly set to
- . Note that currently Type= will not work if
- used in combination with PrivateNetwork=.
+ .
Behavior of is very similar to ; however,
actual execution of the service program is delayed until all active jobs are dispatched. This may be used
diff --git a/shell-completion/zsh/_machinectl b/shell-completion/zsh/_machinectl
index 5ffb7e8b9..5955c765a 100644
--- a/shell-completion/zsh/_machinectl
+++ b/shell-completion/zsh/_machinectl
@@ -28,6 +28,7 @@
"start:Start container as a service"
"stop:Stop container (equal to poweroff)"
"login:Get a login prompt on a VM/container"
+ "shell:Invoke a shell (or other command) in a container"
"enable:Enable automatic container start at boot"
"disable:Disable automatic container start at boot"
"poweroff:Power off one or more VMs/containers"
diff --git a/src/basic/capability-util.c b/src/basic/capability-util.c
index 93237646c..caffda62a 100644
--- a/src/basic/capability-util.c
+++ b/src/basic/capability-util.c
@@ -107,6 +107,10 @@ int capability_ambient_set_apply(uint64_t set, bool also_inherit) {
unsigned long i;
int r;
+ /* Check that we can use PR_CAP_AMBIENT or quit early. */
+ if (!ambient_capabilities_supported())
+ return 0;
+
/* Add the capabilities to the ambient set. */
if (also_inherit) {
diff --git a/src/basic/log.h b/src/basic/log.h
index 625be2240..740fdbf61 100644
--- a/src/basic/log.h
+++ b/src/basic/log.h
@@ -74,7 +74,7 @@ int log_get_max_level_realm(LogRealm realm) _pure_;
*/
assert_cc(STRLEN(__FILE__) > STRLEN(RELATIVE_SOURCE_PATH) + 1);
-#define PROJECT_FILE (__FILE__ + STRLEN(RELATIVE_SOURCE_PATH) + 1)
+#define PROJECT_FILE (&__FILE__[STRLEN(RELATIVE_SOURCE_PATH) + 1])
int log_open(void);
void log_close(void);
diff --git a/src/basic/mountpoint-util.c b/src/basic/mountpoint-util.c
index 1d8147b24..0b3587ff5 100644
--- a/src/basic/mountpoint-util.c
+++ b/src/basic/mountpoint-util.c
@@ -310,7 +310,8 @@ bool fstype_is_network(const char *fstype) {
"glusterfs",
"pvfs2", /* OrangeFS */
"ocfs2",
- "lustre");
+ "lustre",
+ "davfs");
}
bool fstype_is_api_vfs(const char *fstype) {
diff --git a/src/basic/user-util.c b/src/basic/user-util.c
index a491f5505..1510fc96e 100644
--- a/src/basic/user-util.c
+++ b/src/basic/user-util.c
@@ -701,16 +701,18 @@ int take_etc_passwd_lock(const char *root) {
bool valid_user_group_name_full(const char *u, bool strict) {
const char *i;
long sz;
+ bool warned = false;
/* Checks if the specified name is a valid user/group name. Also see POSIX IEEE Std 1003.1-2008, 2016 Edition,
* 3.437. We are a bit stricter here however. Specifically we deviate from POSIX rules:
*
* - We require that names fit into the appropriate utmp field
* - We don't allow empty user names
- * - No dots or digits in the first character
+ * - No dots in the first character
*
* If strict==true, additionally:
* - We don't allow any dots (this conflicts with chown syntax which permits dots as user/group name separator)
+ * - We don't allow a digit as the first character
*
* Note that other systems are even more restrictive, and don't permit underscores or uppercase characters.
*/
@@ -720,17 +722,26 @@ bool valid_user_group_name_full(const char *u, bool strict) {
if (!(u[0] >= 'a' && u[0] <= 'z') &&
!(u[0] >= 'A' && u[0] <= 'Z') &&
+ !(u[0] >= '0' && u[0] <= '9' && !strict) &&
u[0] != '_')
return false;
- bool warned = false;
+ bool only_digits_seen = u[0] >= '0' && u[0] <= '9';
+
+ if (only_digits_seen) {
+ log_warning("User or group name \"%s\" starts with a digit, accepting for compatibility.", u);
+ warned = true;
+ }
for (i = u+1; *i; i++) {
if (((*i >= 'a' && *i <= 'z') ||
(*i >= 'A' && *i <= 'Z') ||
(*i >= '0' && *i <= '9') ||
- IN_SET(*i, '_', '-')))
+ IN_SET(*i, '_', '-'))) {
+ if (!(*i >= '0' && *i <= '9'))
+ only_digits_seen = false;
continue;
+ }
if (*i == '.' && !strict) {
if (!warned) {
@@ -744,6 +755,9 @@ bool valid_user_group_name_full(const char *u, bool strict) {
return false;
}
+ if (only_digits_seen)
+ return false;
+
sz = sysconf(_SC_LOGIN_NAME_MAX);
assert_se(sz > 0);
@@ -764,10 +778,10 @@ bool valid_user_group_name_or_id_full(const char *u, bool strict) {
if (isempty(u))
return false;
- if (valid_user_group_name_full(u, strict))
+ if (parse_uid(u, NULL) >= 0)
return true;
- return parse_uid(u, NULL) >= 0;
+ return valid_user_group_name_full(u, strict);
}
bool valid_gecos(const char *d) {
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
index d8ba3e5d9..e8be76e31 100644
--- a/src/core/dbus-execute.c
+++ b/src/core/dbus-execute.c
@@ -56,6 +56,8 @@ static BUS_DEFINE_PROPERTY_GET2(property_get_ioprio_priority, "i", ExecContext,
static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_empty_string, "s", NULL);
static BUS_DEFINE_PROPERTY_GET_REF(property_get_syslog_level, "i", int, LOG_PRI);
static BUS_DEFINE_PROPERTY_GET_REF(property_get_syslog_facility, "i", int, LOG_FAC);
+static BUS_DEFINE_PROPERTY_GET(property_get_cpu_affinity_from_numa, "b", ExecContext, exec_context_get_cpu_affinity_from_numa);
+
static int property_get_environment_files(
sd_bus *bus,
@@ -213,6 +215,7 @@ static int property_get_cpu_affinity(
sd_bus_error *error) {
ExecContext *c = userdata;
+ _cleanup_(cpu_set_reset) CPUSet s = {};
_cleanup_free_ uint8_t *array = NULL;
size_t allocated;
@@ -220,7 +223,16 @@ static int property_get_cpu_affinity(
assert(reply);
assert(c);
- (void) cpu_set_to_dbus(&c->cpu_set, &array, &allocated);
+ if (c->cpu_affinity_from_numa) {
+ int r;
+
+ r = numa_to_cpu_set(&c->numa_policy, &s);
+ if (r < 0)
+ return r;
+ }
+
+ (void) cpu_set_to_dbus(c->cpu_affinity_from_numa ? &s : &c->cpu_set, &array, &allocated);
+
return sd_bus_message_append_array(reply, 'y', array, allocated);
}
@@ -741,6 +753,7 @@ const sd_bus_vtable bus_exec_vtable[] = {
SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("CPUAffinityFromNUMA", "b", property_get_cpu_affinity_from_numa, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("NUMAPolicy", "i", property_get_numa_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("NUMAMask", "ay", property_get_numa_mask, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
@@ -1770,6 +1783,20 @@ int bus_exec_context_set_transient_property(
return 1;
+ } else if (streq(name, "CPUAffinityFromNUMA")) {
+ int q;
+
+ r = sd_bus_message_read_basic(message, 'b', &q);
+ if (r < 0)
+ return r;
+
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+ c->cpu_affinity_from_numa = q;
+ unit_write_settingf(u, flags, name, "%s=%s", "CPUAffinity", "numa");
+ }
+
+ return 1;
+
} else if (streq(name, "NUMAPolicy")) {
int32_t type;
@@ -1784,6 +1811,7 @@ int bus_exec_context_set_transient_property(
c->numa_policy.type = type;
return 1;
+
} else if (streq(name, "Nice")) {
int32_t q;
diff --git a/src/core/execute.c b/src/core/execute.c
index 587b77a3f..3d50a0857 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -3021,6 +3021,33 @@ static int exec_parameters_get_cgroup_path(const ExecParameters *params, char **
return using_subcgroup;
}
+static int exec_context_cpu_affinity_from_numa(const ExecContext *c, CPUSet *ret) {
+ _cleanup_(cpu_set_reset) CPUSet s = {};
+ int r;
+
+ assert(c);
+ assert(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");
+ return 0;
+ }
+
+ 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);
+}
+
+bool exec_context_get_cpu_affinity_from_numa(const ExecContext *c) {
+ assert(c);
+
+ return c->cpu_affinity_from_numa;
+}
+
static int exec_child(
Unit *unit,
const ExecCommand *command,
@@ -3318,11 +3345,26 @@ static int exec_child(
}
}
- if (context->cpu_set.set)
- if (sched_setaffinity(0, context->cpu_set.allocated, context->cpu_set.set) < 0) {
+ if (context->cpu_affinity_from_numa || context->cpu_set.set) {
+ _cleanup_(cpu_set_reset) CPUSet converted_cpu_set = {};
+ const CPUSet *cpu_set;
+
+ if (context->cpu_affinity_from_numa) {
+ r = exec_context_cpu_affinity_from_numa(context, &converted_cpu_set);
+ if (r < 0) {
+ *exit_status = EXIT_CPUAFFINITY;
+ return log_unit_error_errno(unit, r, "Failed to derive CPU affinity mask from NUMA mask: %m");
+ }
+
+ cpu_set = &converted_cpu_set;
+ } else
+ cpu_set = &context->cpu_set;
+
+ if (sched_setaffinity(0, cpu_set->allocated, cpu_set->set) < 0) {
*exit_status = EXIT_CPUAFFINITY;
return log_unit_error_errno(unit, errno, "Failed to set up CPU affinity: %m");
}
+ }
if (mpol_is_valid(numa_policy_get_type(&context->numa_policy))) {
r = apply_numa_policy(&context->numa_policy);
diff --git a/src/core/execute.h b/src/core/execute.h
index 09c1510aa..4baf5b1a4 100644
--- a/src/core/execute.h
+++ b/src/core/execute.h
@@ -21,6 +21,7 @@ typedef struct Manager Manager;
#include "missing_resource.h"
#include "namespace.h"
#include "nsflags.h"
+#include "numa-util.h"
#include "time-util.h"
#define EXEC_STDIN_DATA_MAX (64U*1024U*1024U)
@@ -181,6 +182,7 @@ struct ExecContext {
CPUSet cpu_set;
NUMAPolicy numa_policy;
+ bool cpu_affinity_from_numa;
ExecInput std_input;
ExecOutput std_output;
@@ -405,6 +407,8 @@ void exec_runtime_vacuum(Manager *m);
void exec_params_clear(ExecParameters *p);
+bool exec_context_get_cpu_affinity_from_numa(const ExecContext *c);
+
const char* exec_output_to_string(ExecOutput i) _const_;
ExecOutput exec_output_from_string(const char *s) _pure_;
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index 71a9873da..646364eb8 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -1330,13 +1330,25 @@ int config_parse_exec_cpu_affinity(const char *unit,
void *userdata) {
ExecContext *c = data;
+ int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
- return parse_cpu_set_extend(rvalue, &c->cpu_set, true, unit, filename, line, lvalue);
+ if (streq(rvalue, "numa")) {
+ c->cpu_affinity_from_numa = true;
+ cpu_set_reset(&c->cpu_set);
+
+ return 0;
+ }
+
+ r = parse_cpu_set_extend(rvalue, &c->cpu_set, true, unit, filename, line, lvalue);
+ if (r >= 0)
+ c->cpu_affinity_from_numa = false;
+
+ return r;
}
int config_parse_capability_set(
diff --git a/src/core/swap.c b/src/core/swap.c
index d4da840c0..c5945371d 100644
--- a/src/core/swap.c
+++ b/src/core/swap.c
@@ -207,7 +207,7 @@ static int swap_add_device_dependencies(Swap *s) {
return 0;
p = swap_get_parameters(s);
- if (!p)
+ if (!p || !p->what)
return 0;
mask = s->from_proc_swaps ? UNIT_DEPENDENCY_PROC_SWAP : UNIT_DEPENDENCY_FILE;
diff --git a/src/home/homectl.c b/src/home/homectl.c
index d35034ac0..1ccc053d3 100644
--- a/src/home/homectl.c
+++ b/src/home/homectl.c
@@ -295,7 +295,7 @@ static int handle_generic_user_record_error(
if (sd_bus_error_has_name(error, BUS_ERROR_HOME_ABSENT))
return log_error_errno(SYNTHETIC_ERRNO(EREMOTE),
- "Home of user %s is currently absent, please plug in the necessary stroage device or backing file system.", user_name);
+ "Home of user %s is currently absent, please plug in the necessary storage device or backing file system.", user_name);
else if (sd_bus_error_has_name(error, BUS_ERROR_AUTHENTICATION_LIMIT_HIT))
return log_error_errno(SYNTHETIC_ERRNO(ETOOMANYREFS),
@@ -1207,7 +1207,7 @@ static int add_pkcs11_key_data(JsonVariant **v, const char *uri) {
pkey = X509_get0_pubkey(cert);
if (!pkey)
- return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to exract public key from X.509 certificate.");
+ return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to extract public key from X.509 certificate.");
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA)
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "X.509 certificate does not refer to RSA key.");
@@ -1338,7 +1338,7 @@ static int acquire_new_password(
string_erase(e);
if (unsetenv("NEWPASSWORD") < 0)
- return log_error_errno(errno, "Failed to unse $NEWPASSWORD: %m");
+ return log_error_errno(errno, "Failed to unset $NEWPASSWORD: %m");
return 0;
}
@@ -1376,7 +1376,7 @@ static int acquire_new_password(
return 0;
}
- log_error("Password didn't mach, try again.");
+ log_error("Password didn't match, try again.");
}
}
@@ -3148,7 +3148,7 @@ static int parse_argv(int argc, char *argv[]) {
r = read_line(f, LONG_LINE_MAX, &line);
if (r < 0)
- return log_error_errno(r, "Faile dto read from '%s': %m", optarg+1);
+ return log_error_errno(r, "Failed to read from '%s': %m", optarg+1);
if (r == 0)
break;
diff --git a/src/home/homed-home-bus.c b/src/home/homed-home-bus.c
index 02a87a5ec..6b4fa58a6 100644
--- a/src/home/homed-home-bus.c
+++ b/src/home/homed-home-bus.c
@@ -630,7 +630,7 @@ int bus_home_method_acquire(
/* This operation might not be something we can executed immediately, hence queue it */
fd = home_create_fifo(h, please_suspend);
if (fd < 0)
- return sd_bus_reply_method_errnof(message, fd, "Failed to allocate fifo for %s: %m", h->user_name);
+ return sd_bus_reply_method_errnof(message, fd, "Failed to allocate FIFO for %s: %m", h->user_name);
o = operation_new(OPERATION_ACQUIRE, message);
if (!o)
@@ -681,7 +681,7 @@ int bus_home_method_ref(
fd = home_create_fifo(h, please_suspend);
if (fd < 0)
- return sd_bus_reply_method_errnof(message, fd, "Failed to allocate fifo for %s: %m", h->user_name);
+ return sd_bus_reply_method_errnof(message, fd, "Failed to allocate FIFO for %s: %m", h->user_name);
return sd_bus_reply_method_return(message, "h", fd);
}
diff --git a/src/home/homed-home.c b/src/home/homed-home.c
index f50de2672..3ec47ee5d 100644
--- a/src/home/homed-home.c
+++ b/src/home/homed-home.c
@@ -424,7 +424,7 @@ static int home_verify_user_record(Home *h, UserRecord *hr, bool *ret_signed_loc
case -ENOKEY:
sd_bus_error_setf(ret_error, BUS_ERROR_BAD_SIGNATURE, "User record %s is not signed by any known key, refusing.", hr->user_name);
- return log_error_errno(is_signed, "Home %s contians user record that is not signed by any known key, refusing.", hr->user_name);
+ return log_error_errno(is_signed, "Home %s contains user record that is not signed by any known key, refusing.", hr->user_name);
default:
assert(is_signed < 0);
@@ -438,7 +438,7 @@ static int convert_worker_errno(Home *h, int e, sd_bus_error *error) {
switch (e) {
case -EMSGSIZE:
- return sd_bus_error_setf(error, BUS_ERROR_BAD_HOME_SIZE, "File systems of this type cannot shrinked");
+ return sd_bus_error_setf(error, BUS_ERROR_BAD_HOME_SIZE, "File systems of this type cannot be shrinked");
case -ETXTBSY:
return sd_bus_error_setf(error, BUS_ERROR_BAD_HOME_SIZE, "File systems of this type can only be shrinked offline");
case -ERANGE:
@@ -1472,7 +1472,7 @@ int home_resize(Home *h, uint64_t disk_size, UserRecord *secret, sd_bus_error *e
if (disk_size == UINT64_MAX || disk_size == h->record->disk_size) {
if (h->record->disk_size == UINT64_MAX)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Not disk size to resize to specified.");
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "No disk size to resize to specified.");
c = user_record_ref(h->record); /* Shortcut if size is unspecified or matches the record */
} else {
@@ -1904,7 +1904,7 @@ static int home_get_disk_status_luks(
goto finish;
if (statfs(hd, &sfs) < 0) {
- log_debug_errno(errno, "Failed to statfs() %s, ignoring: %m", hd);
+ log_debug_errno(errno, "Failed to statfs() %s, ignoring: %m", hd);
goto finish;
}
diff --git a/src/home/homed-manager-bus.c b/src/home/homed-manager-bus.c
index a6b30d961..fce854527 100644
--- a/src/home/homed-manager-bus.c
+++ b/src/home/homed-manager-bus.c
@@ -584,7 +584,7 @@ static int method_lock_all_homes(sd_bus_message *message, void *userdata, sd_bus
return -ENOMEM;
}
- log_info("Automatically locking of home of user %s.", h->user_name);
+ log_info("Automatically locking home of user %s.", h->user_name);
r = home_schedule_operation(h, o, error);
if (r < 0)
diff --git a/src/home/homed-manager.c b/src/home/homed-manager.c
index 5d77760f2..c9bfb64e7 100644
--- a/src/home/homed-manager.c
+++ b/src/home/homed-manager.c
@@ -631,7 +631,7 @@ static int manager_add_home_by_image(
}
if (!same) {
- log_debug("Found a multiple images for a user '%s', ignoring image '%s'.", user_name, image_path);
+ log_debug("Found multiple images for user '%s', ignoring image '%s'.", user_name, image_path);
return 0;
}
} else {
@@ -768,7 +768,7 @@ static int manager_assess_image(
r = stat(path, &st);
if (r < 0)
return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno,
- "Failed to stat directory entry '%s', ignoring: %m", dentry_name);
+ "Failed to stat() directory entry '%s', ignoring: %m", dentry_name);
if (S_ISREG(st.st_mode)) {
_cleanup_free_ char *n = NULL, *user_name = NULL, *realm = NULL;
@@ -833,7 +833,7 @@ static int manager_assess_image(
if (errno == ENODATA)
log_debug_errno(errno, "Determined %s is not fscrypt encrypted.", path);
else if (ERRNO_IS_NOT_SUPPORTED(errno))
- log_debug_errno(errno, "Determined %s is not fscrypt encrypted because kernel or file system don't support it.", path);
+ log_debug_errno(errno, "Determined %s is not fscrypt encrypted because kernel or file system doesn't support it.", path);
else
log_debug_errno(errno, "FS_IOC_GET_ENCRYPTION_POLICY failed with unexpected error code on %s, ignoring: %m", path);
@@ -1307,7 +1307,7 @@ static int manager_generate_key_pair(Manager *m) {
/* Write out public key (note that we only do that as a help to the user, we don't make use of this ever */
r = fopen_temporary("/var/lib/systemd/home/local.public", &fpublic, &temp_public);
if (r < 0)
- return log_error_errno(errno, "Failed ot open key file for writing: %m");
+ return log_error_errno(errno, "Failed to open key file for writing: %m");
if (PEM_write_PUBKEY(fpublic, m->private_key) <= 0)
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write public key.");
@@ -1321,7 +1321,7 @@ static int manager_generate_key_pair(Manager *m) {
/* Write out the private key (this actually writes out both private and public, OpenSSL is confusing) */
r = fopen_temporary("/var/lib/systemd/home/local.private", &fprivate, &temp_private);
if (r < 0)
- return log_error_errno(errno, "Failed ot open key file for writing: %m");
+ return log_error_errno(errno, "Failed to open key file for writing: %m");
if (PEM_write_PrivateKey(fprivate, m->private_key, NULL, NULL, 0, NULL, 0) <= 0)
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write private key pair.");
@@ -1660,7 +1660,7 @@ int manager_enqueue_gc(Manager *m, Home *focus) {
r = sd_event_add_defer(m->event, &m->deferred_gc_event_source, on_deferred_gc, m);
if (r < 0)
- return log_error_errno(r, "Failed to allocate gc event source: %m");
+ return log_error_errno(r, "Failed to allocate GC event source: %m");
r = sd_event_source_set_priority(m->deferred_gc_event_source, SD_EVENT_PRIORITY_IDLE);
if (r < 0)
diff --git a/src/home/homed-operation.c b/src/home/homed-operation.c
index 80dc555cd..156a25ec8 100644
--- a/src/home/homed-operation.c
+++ b/src/home/homed-operation.c
@@ -47,7 +47,7 @@ static Operation *operation_free(Operation *o) {
r = sd_bus_reply_method_errnof(o->message, o->ret, "Failed to execute operation: %m");
}
if (r < 0)
- log_warning_errno(r, "Failed ot reply to %s method call, ignoring: %m", sd_bus_message_get_member(o->message));
+ log_warning_errno(r, "Failed to reply to %s method call, ignoring: %m", sd_bus_message_get_member(o->message));
}
sd_bus_message_unref(o->message);
diff --git a/src/home/homework-luks.c b/src/home/homework-luks.c
index 0cd5902bf..d731d0d64 100644
--- a/src/home/homework-luks.c
+++ b/src/home/homework-luks.c
@@ -616,7 +616,7 @@ static int crypt_device_to_evp_cipher(struct crypt_device *cd, const EVP_CIPHER
/* Verify that our key length calculations match what OpenSSL thinks */
r = EVP_CIPHER_key_length(cc);
if (r < 0 || (uint64_t) r != key_size)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Key size of selected cipher doesn't meet out expectations.");
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Key size of selected cipher doesn't meet our expectations.");
*ret = cc;
return 0;
@@ -787,7 +787,7 @@ static int format_luks_token_text(
r = json_variant_format(hr->json, 0, &text);
if (r < 0)
- return log_error_errno(r,"Failed to format user record for LUKS: %m");
+ return log_error_errno(r, "Failed to format user record for LUKS: %m");
text_length = strlen(text);
encrypted_size = text_length + 2*key_size - 1;
@@ -1263,7 +1263,7 @@ int home_activate_luks(
r = dm_deferred_remove(setup.dm_name);
if (r < 0)
- log_warning_errno(r, "Failed to relinquish dm device, ignoring: %m");
+ log_warning_errno(r, "Failed to relinquish DM device, ignoring: %m");
setup.undo_dm = false;
@@ -1328,7 +1328,7 @@ static int run_mkfs(
if (r < 0)
return log_error_errno(r, "Failed to check if mkfs for file system %s exists: %m", fstype);
if (r == 0)
- return log_error_errno(SYNTHETIC_ERRNO(EPROTONOSUPPORT), "Nt mkfs for file system %s installed.", fstype);
+ return log_error_errno(SYNTHETIC_ERRNO(EPROTONOSUPPORT), "No mkfs for file system %s installed.", fstype);
r = safe_fork("(mkfs)", FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_LOG|FORK_WAIT|FORK_STDOUT_TO_STDERR, NULL);
if (r < 0)
@@ -1584,7 +1584,7 @@ static int make_partition_table(
r = fdisk_create_disklabel(c, "gpt");
if (r < 0)
- return log_error_errno(r, "Failed to create gpt disk label: %m");
+ return log_error_errno(r, "Failed to create GPT disk label: %m");
p = fdisk_new_partition();
if (!p)
@@ -2212,7 +2212,7 @@ static int ext4_offline_resize_fs(HomeSetup *setup, uint64_t new_size, bool disc
re_mount = true;
}
- log_info("Temporarary unmounting of file system completed.");
+ log_info("Temporary unmounting of file system completed.");
/* resize2fs requires that the file system is force checked first, do so. */
r = safe_fork("(e2fsck)", FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_LOG|FORK_STDOUT_TO_STDERR, &fsck_pid);
@@ -2426,7 +2426,7 @@ static int apply_resize_partition(int fd, sd_id128_t disk_uuids, struct fdisk_ta
if (n < 0)
return log_error_errno(errno, "Failed to wipe partition table: %m");
if (n != 1024)
- return log_error_errno(SYNTHETIC_ERRNO(EIO), "Short write while whiping partition table.");
+ return log_error_errno(SYNTHETIC_ERRNO(EIO), "Short write while wiping partition table.");
c = fdisk_new_context();
if (!c)
@@ -2536,7 +2536,7 @@ int home_resize_luks(
} else {
r = stat_verify_regular(&st);
if (r < 0)
- return log_error_errno(r, "Image file %s is not a block device nor regular: %m", ip);
+ return log_error_errno(r, "Image %s is not a block device nor regular file: %m", ip);
old_image_size = st.st_size;
diff --git a/src/home/homework-pkcs11.c b/src/home/homework-pkcs11.c
index 941ba23b3..915bc0e57 100644
--- a/src/home/homework-pkcs11.c
+++ b/src/home/homework-pkcs11.c
@@ -53,7 +53,7 @@ int pkcs11_callback(
if (rv != CKR_OK)
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to log into security token '%s': %s", token_label, p11_kit_strerror(rv));
- log_info("Successully logged into security token '%s' via protected authentication path.", token_label);
+ log_info("Successfully logged into security token '%s' via protected authentication path.", token_label);
goto decrypt;
}
diff --git a/src/home/homework.c b/src/home/homework.c
index ecf07ffb4..835f86952 100644
--- a/src/home/homework.c
+++ b/src/home/homework.c
@@ -383,7 +383,7 @@ int home_load_embedded_identity(
return r;
if (!user_record_compatible(h, embedded_home))
- return log_error_errno(SYNTHETIC_ERRNO(EREMCHG), "Hmbedded home record not compatible with host record, refusing.");
+ return log_error_errno(SYNTHETIC_ERRNO(EREMCHG), "Embedded home record not compatible with host record, refusing.");
/* Insist that credentials the user supplies also unlocks any embedded records. */
r = user_record_authenticate(embedded_home, h, pkcs11_decrypted_passwords);
@@ -986,7 +986,7 @@ static int home_remove(UserRecord *h) {
if (stat(ip, &st) < 0) {
if (errno != -ENOENT)
- return log_error_errno(errno, "Failed to stat %s: %m", ip);
+ return log_error_errno(errno, "Failed to stat() %s: %m", ip);
} else {
if (S_ISREG(st.st_mode)) {
diff --git a/src/home/pam_systemd_home.c b/src/home/pam_systemd_home.c
index 67aff9350..440ed85e2 100644
--- a/src/home/pam_systemd_home.c
+++ b/src/home/pam_systemd_home.c
@@ -41,7 +41,7 @@ static int parse_argv(
k = parse_boolean(v);
if (k < 0)
- pam_syslog(handle, LOG_WARNING, "Failed to parse suspend-please= argument, ignoring: %s", v);
+ pam_syslog(handle, LOG_WARNING, "Failed to parse suspend= argument, ignoring: %s", v);
else if (please_suspend)
*please_suspend = k;
@@ -95,7 +95,7 @@ static int acquire_user_record(
r = pam_get_data(handle, "systemd-user-record-is-homed", &b);
if (!IN_SET(r, PAM_SUCCESS, PAM_NO_MODULE_DATA)) {
/* Failure */
- pam_syslog(handle, LOG_ERR, "Failed to get PAM user record is homed flag: %s", pam_strerror(handle, r));
+ pam_syslog(handle, LOG_ERR, "Failed to get PAM user-record-is-homed flag: %s", pam_strerror(handle, r));
return r;
} else if (b == NULL)
/* Nothing cached yet, need to acquire fresh */
@@ -200,7 +200,7 @@ user_unknown:
/* Cache this, so that we don't check again */
r = pam_set_data(handle, "systemd-user-record-is-homed", USER_RECORD_IS_OTHER, NULL);
if (r != PAM_SUCCESS)
- pam_syslog(handle, LOG_ERR, "Failed to set PAM user record is homed flag, ignoring: %s", pam_strerror(handle, r));
+ pam_syslog(handle, LOG_ERR, "Failed to set PAM user-record-is-homed flag, ignoring: %s", pam_strerror(handle, r));
return PAM_USER_UNKNOWN;
}
@@ -214,7 +214,7 @@ static int release_user_record(pam_handle_t *handle) {
k = pam_set_data(handle, "systemd-user-record-is-homed", NULL, NULL);
if (k != PAM_SUCCESS)
- pam_syslog(handle, LOG_ERR, "Failed to release PAM user record is homed flag: %s", pam_strerror(handle, k));
+ pam_syslog(handle, LOG_ERR, "Failed to release PAM user-record-is-homed flag: %s", pam_strerror(handle, k));
return IN_SET(r, PAM_SUCCESS, PAM_NO_MODULE_DATA) ? k : r;
}
diff --git a/src/home/pwquality-util.c b/src/home/pwquality-util.c
index f2342b28f..5863a229b 100644
--- a/src/home/pwquality-util.c
+++ b/src/home/pwquality-util.c
@@ -73,7 +73,7 @@ int quality_check_password(
r = pwquality_read_config(pwq, NULL, &auxerror);
if (r < 0)
- log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to read libpwquality configuation, ignoring: %s",
+ log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to read libpwquality configuration, ignoring: %s",
pwquality_strerror(buf, sizeof(buf), r, auxerror));
pwquality_maybe_disable_dictionary(pwq);
@@ -143,7 +143,7 @@ int suggest_passwords(void) {
r = pwquality_read_config(pwq, NULL, &auxerror);
if (r < 0)
- log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to read libpwquality configuation, ignoring: %s",
+ log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to read libpwquality configuration, ignoring: %s",
pwquality_strerror(buf, sizeof(buf), r, auxerror));
pwquality_maybe_disable_dictionary(pwq);
diff --git a/src/import/pull-raw.c b/src/import/pull-raw.c
index 51c12444e..0183c13f4 100644
--- a/src/import/pull-raw.c
+++ b/src/import/pull-raw.c
@@ -509,14 +509,17 @@ static void raw_pull_job_on_finished(PullJob *j) {
raw_pull_report_progress(i, RAW_FINALIZING);
- r = import_make_read_only_fd(i->raw_job->disk_fd);
- if (r < 0)
- goto finish;
+ if (i->raw_job->etag) {
+ /* Only make a read-only copy if ETag header is set. */
+ r = import_make_read_only_fd(i->raw_job->disk_fd);
+ if (r < 0)
+ goto finish;
- r = rename_noreplace(AT_FDCWD, i->temp_path, AT_FDCWD, i->final_path);
- if (r < 0) {
- log_error_errno(r, "Failed to rename raw file to %s: %m", i->final_path);
- goto finish;
+ r = rename_noreplace(AT_FDCWD, i->temp_path, AT_FDCWD, i->final_path);
+ if (r < 0) {
+ log_error_errno(r, "Failed to rename raw file to %s: %m", i->final_path);
+ goto finish;
+ }
}
i->temp_path = mfree(i->temp_path);
diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
index 56a6a9c43..36f65ad68 100644
--- a/src/journal/sd-journal.c
+++ b/src/journal/sd-journal.c
@@ -2675,13 +2675,12 @@ _public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) {
Get rid of the deleted files now so they don't stay around indefinitely. */
ORDERED_HASHMAP_FOREACH(f, j->files, i) {
r = journal_file_fstat(f);
- if (r < 0) {
+ if (r == -EIDRM)
+ remove_file_real(j, f);
+ else if (r < 0) {
log_debug_errno(r,"Failed to fstat() journal file '%s' : %m", f->path);
continue;
}
-
- if (f->last_stat.st_nlink <= 0)
- remove_file_real(j, f);
}
/* The journal might have changed since the context
diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c
index 48e8aad8f..d072f1c57 100644
--- a/src/libsystemd-network/sd-dhcp-lease.c
+++ b/src/libsystemd-network/sd-dhcp-lease.c
@@ -1175,7 +1175,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
if (r < 0)
log_debug_errno(r, "Failed to deserialize SIP servers %s, ignoring: %m", sip);
else
- lease->ntp_size = r;
+ lease->sip_size = r;
}
if (mtu) {
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 52a7ea3c7..15201f900 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -3424,7 +3424,7 @@ const sd_bus_vtable manager_vtable[] = {
SD_BUS_VTABLE_END
};
-static int session_jobs_reply(Session *s, const char *unit, const char *result) {
+static int session_jobs_reply(Session *s, uint32_t jid, const char *unit, const char *result) {
assert(s);
assert(unit);
@@ -3435,7 +3435,7 @@ static int session_jobs_reply(Session *s, const char *unit, const char *result)
_cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED,
- "Start job for unit '%s' failed with '%s'", unit, result);
+ "Job %u for unit '%s' failed with '%s'", jid, unit, result);
return session_send_create_reply(s, &e);
}
@@ -3475,7 +3475,7 @@ int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *err
if (session) {
if (streq_ptr(path, session->scope_job)) {
session->scope_job = mfree(session->scope_job);
- (void) session_jobs_reply(session, unit, result);
+ (void) session_jobs_reply(session, id, unit, result);
session_save(session);
user_save(session->user);
@@ -3490,7 +3490,7 @@ int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *err
user->service_job = mfree(user->service_job);
LIST_FOREACH(sessions_by_user, session, user->sessions)
- (void) session_jobs_reply(session, unit, NULL /* don't propagate user service failures to the client */);
+ (void) session_jobs_reply(session, id, unit, NULL /* don't propagate user service failures to the client */);
user_save(user);
}
diff --git a/src/login/org.freedesktop.login1.policy b/src/login/org.freedesktop.login1.policy
index b726634cb..1b6d85e5f 100644
--- a/src/login/org.freedesktop.login1.policy
+++ b/src/login/org.freedesktop.login1.policy
@@ -396,7 +396,7 @@
Authentication is required to change the virtual terminal.
auth_admin_keep
- auth_admin_keep
+ yes
yes
diff --git a/src/nss-systemd/nss-systemd.c b/src/nss-systemd/nss-systemd.c
index 9c004616f..08fe100c0 100644
--- a/src/nss-systemd/nss-systemd.c
+++ b/src/nss-systemd/nss-systemd.c
@@ -432,7 +432,7 @@ enum nss_status _nss_systemd_getgrent_r(
if (!getgrent_data.by_membership) {
r = groupdb_iterator_get(getgrent_data.iterator, &gr);
if (r == -ESRCH) {
- /* So we finished iterating native groups now. let's now continue with iterating
+ /* So we finished iterating native groups now. Let's now continue with iterating
* native memberships, and generate additional group entries for any groups
* referenced there that are defined in NSS only. This means for those groups there
* will be two or more entries generated during iteration, but this is apparently how
@@ -511,7 +511,8 @@ enum nss_status _nss_systemd_getgrent_r(
if (!members) {
UNPROTECT_ERRNO;
*errnop = ENOMEM;
- return NSS_STATUS_TRYAGAIN;
+ ret = NSS_STATUS_TRYAGAIN;
+ goto finish;
}
/* Note that we currently generate one group entry per user that is part of a
diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c
index 28d85944a..a30876c1a 100644
--- a/src/shared/bus-unit-util.c
+++ b/src/shared/bus-unit-util.c
@@ -21,6 +21,7 @@
#include "missing_fs.h"
#include "mountpoint-util.h"
#include "nsflags.h"
+#include "numa-util.h"
#include "parse-util.h"
#include "process-util.h"
#include "rlimit-util.h"
@@ -28,6 +29,7 @@
#include "signal-util.h"
#include "socket-util.h"
#include "sort-util.h"
+#include "stdio-util.h"
#include "string-util.h"
#include "syslog-util.h"
#include "terminal-util.h"
@@ -1102,6 +1104,13 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
_cleanup_free_ uint8_t *array = NULL;
size_t allocated;
+ if (eq && streq(eq, "numa")) {
+ r = sd_bus_message_append(m, "(sv)", "CPUAffinityFromNUMA", "b", true);
+ if (r < 0)
+ return bus_log_create_error(r);
+ return r;
+ }
+
r = parse_cpu_set(eq, &cpuset);
if (r < 0)
return log_error_errno(r, "Failed to parse %s value: %s", field, eq);
diff --git a/src/shared/cpu-set-util.c b/src/shared/cpu-set-util.c
index 219314ef5..9b9238362 100644
--- a/src/shared/cpu-set-util.c
+++ b/src/shared/cpu-set-util.c
@@ -14,11 +14,9 @@
#include "log.h"
#include "macro.h"
#include "memory-util.h"
-#include "missing_syscall.h"
#include "parse-util.h"
#include "stat-util.h"
#include "string-util.h"
-#include "string-table.h"
#include "strv.h"
#include "util.h"
@@ -133,7 +131,7 @@ int cpu_set_add_all(CPUSet *a, const CPUSet *b) {
return r;
}
- return 0;
+ return 1;
}
int parse_cpu_set_full(
@@ -218,7 +216,7 @@ int parse_cpu_set_extend(
if (!old->set) {
*old = cpuset;
cpuset = (CPUSet) {};
- return 0;
+ return 1;
}
return cpu_set_add_all(old, &cpuset);
@@ -295,88 +293,3 @@ int cpu_set_from_dbus(const uint8_t *bits, size_t size, CPUSet *set) {
s = (CPUSet) {};
return 0;
}
-
-bool numa_policy_is_valid(const NUMAPolicy *policy) {
- assert(policy);
-
- if (!mpol_is_valid(numa_policy_get_type(policy)))
- return false;
-
- if (!policy->nodes.set &&
- !IN_SET(numa_policy_get_type(policy), MPOL_DEFAULT, MPOL_LOCAL, MPOL_PREFERRED))
- return false;
-
- if (policy->nodes.set &&
- numa_policy_get_type(policy) == MPOL_PREFERRED &&
- CPU_COUNT_S(policy->nodes.allocated, policy->nodes.set) != 1)
- return false;
-
- return true;
-}
-
-static int numa_policy_to_mempolicy(const NUMAPolicy *policy, unsigned long *ret_maxnode, unsigned long **ret_nodes) {
- unsigned node, bits = 0, ulong_bits;
- _cleanup_free_ unsigned long *out = NULL;
-
- assert(policy);
- assert(ret_maxnode);
- assert(ret_nodes);
-
- if (IN_SET(numa_policy_get_type(policy), MPOL_DEFAULT, MPOL_LOCAL) ||
- (numa_policy_get_type(policy) == MPOL_PREFERRED && !policy->nodes.set)) {
- *ret_nodes = NULL;
- *ret_maxnode = 0;
- return 0;
- }
-
- bits = policy->nodes.allocated * 8;
- ulong_bits = sizeof(unsigned long) * 8;
-
- out = new0(unsigned long, DIV_ROUND_UP(policy->nodes.allocated, sizeof(unsigned long)));
- if (!out)
- return -ENOMEM;
-
- /* We don't make any assumptions about internal type libc is using to store NUMA node mask.
- Hence we need to convert the node mask to the representation expected by set_mempolicy() */
- for (node = 0; node < bits; node++)
- if (CPU_ISSET_S(node, policy->nodes.allocated, policy->nodes.set))
- out[node / ulong_bits] |= 1ul << (node % ulong_bits);
-
- *ret_nodes = TAKE_PTR(out);
- *ret_maxnode = bits + 1;
- return 0;
-}
-
-int apply_numa_policy(const NUMAPolicy *policy) {
- int r;
- _cleanup_free_ unsigned long *nodes = NULL;
- unsigned long maxnode;
-
- assert(policy);
-
- if (get_mempolicy(NULL, NULL, 0, 0, 0) < 0 && errno == ENOSYS)
- return -EOPNOTSUPP;
-
- if (!numa_policy_is_valid(policy))
- return -EINVAL;
-
- r = numa_policy_to_mempolicy(policy, &maxnode, &nodes);
- if (r < 0)
- return r;
-
- r = set_mempolicy(numa_policy_get_type(policy), nodes, maxnode);
- if (r < 0)
- return -errno;
-
- return 0;
-}
-
-static const char* const mpol_table[] = {
- [MPOL_DEFAULT] = "default",
- [MPOL_PREFERRED] = "preferred",
- [MPOL_BIND] = "bind",
- [MPOL_INTERLEAVE] = "interleave",
- [MPOL_LOCAL] = "local",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(mpol, int);
diff --git a/src/shared/cpu-set-util.h b/src/shared/cpu-set-util.h
index 27812dfd5..a60d4ec41 100644
--- a/src/shared/cpu-set-util.h
+++ b/src/shared/cpu-set-util.h
@@ -49,30 +49,3 @@ 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 cpus_in_affinity_mask(void);
-
-static inline bool mpol_is_valid(int t) {
- return t >= MPOL_DEFAULT && t <= MPOL_LOCAL;
-}
-
-typedef struct NUMAPolicy {
- /* Always use numa_policy_get_type() to read the value */
- int type;
- CPUSet nodes;
-} NUMAPolicy;
-
-bool numa_policy_is_valid(const NUMAPolicy *p);
-
-static inline int numa_policy_get_type(const NUMAPolicy *p) {
- return p->type < 0 ? (p->nodes.set ? MPOL_PREFERRED : -1) : p->type;
-}
-
-static inline void numa_policy_reset(NUMAPolicy *p) {
- assert(p);
- cpu_set_reset(&p->nodes);
- p->type = -1;
-}
-
-int apply_numa_policy(const NUMAPolicy *policy);
-
-const char* mpol_to_string(int i) _const_;
-int mpol_from_string(const char *s) _pure_;
diff --git a/src/shared/meson.build b/src/shared/meson.build
index fa080f8e6..94174347a 100644
--- a/src/shared/meson.build
+++ b/src/shared/meson.build
@@ -147,6 +147,8 @@ shared_sources = files('''
nscd-flush.h
nsflags.c
nsflags.h
+ numa-util.c
+ numa-util.h
openssl-util.h
os-util.c
os-util.h
diff --git a/src/shared/numa-util.c b/src/shared/numa-util.c
new file mode 100644
index 000000000..187992dc6
--- /dev/null
+++ b/src/shared/numa-util.c
@@ -0,0 +1,135 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include
+#include
+
+#include "alloc-util.h"
+#include "cpu-set-util.h"
+#include "fileio.h"
+#include "macro.h"
+#include "missing_syscall.h"
+#include "numa-util.h"
+#include "stdio-util.h"
+#include "string-table.h"
+
+bool numa_policy_is_valid(const NUMAPolicy *policy) {
+ assert(policy);
+
+ if (!mpol_is_valid(numa_policy_get_type(policy)))
+ return false;
+
+ if (!policy->nodes.set &&
+ !IN_SET(numa_policy_get_type(policy), MPOL_DEFAULT, MPOL_LOCAL, MPOL_PREFERRED))
+ return false;
+
+ if (policy->nodes.set &&
+ numa_policy_get_type(policy) == MPOL_PREFERRED &&
+ CPU_COUNT_S(policy->nodes.allocated, policy->nodes.set) != 1)
+ return false;
+
+ return true;
+}
+
+static int numa_policy_to_mempolicy(const NUMAPolicy *policy, unsigned long *ret_maxnode, unsigned long **ret_nodes) {
+ unsigned node, bits = 0, ulong_bits;
+ _cleanup_free_ unsigned long *out = NULL;
+
+ assert(policy);
+ assert(ret_maxnode);
+ assert(ret_nodes);
+
+ if (IN_SET(numa_policy_get_type(policy), MPOL_DEFAULT, MPOL_LOCAL) ||
+ (numa_policy_get_type(policy) == MPOL_PREFERRED && !policy->nodes.set)) {
+ *ret_nodes = NULL;
+ *ret_maxnode = 0;
+ return 0;
+ }
+
+ bits = policy->nodes.allocated * 8;
+ ulong_bits = sizeof(unsigned long) * 8;
+
+ out = new0(unsigned long, DIV_ROUND_UP(policy->nodes.allocated, sizeof(unsigned long)));
+ if (!out)
+ return -ENOMEM;
+
+ /* We don't make any assumptions about internal type libc is using to store NUMA node mask.
+ Hence we need to convert the node mask to the representation expected by set_mempolicy() */
+ for (node = 0; node < bits; node++)
+ if (CPU_ISSET_S(node, policy->nodes.allocated, policy->nodes.set))
+ out[node / ulong_bits] |= 1ul << (node % ulong_bits);
+
+ *ret_nodes = TAKE_PTR(out);
+ *ret_maxnode = bits + 1;
+ return 0;
+}
+
+int apply_numa_policy(const NUMAPolicy *policy) {
+ int r;
+ _cleanup_free_ unsigned long *nodes = NULL;
+ unsigned long maxnode;
+
+ assert(policy);
+
+ if (get_mempolicy(NULL, NULL, 0, 0, 0) < 0 && errno == ENOSYS)
+ return -EOPNOTSUPP;
+
+ if (!numa_policy_is_valid(policy))
+ return -EINVAL;
+
+ r = numa_policy_to_mempolicy(policy, &maxnode, &nodes);
+ if (r < 0)
+ return r;
+
+ r = set_mempolicy(numa_policy_get_type(policy), nodes, maxnode);
+ if (r < 0)
+ return -errno;
+
+ return 0;
+}
+
+int numa_to_cpu_set(const NUMAPolicy *policy, CPUSet *ret) {
+ int r;
+ size_t i;
+ _cleanup_(cpu_set_reset) CPUSet s = {};
+
+ assert(policy);
+ assert(ret);
+
+ for (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;
+
+ xsprintf(p, "/sys/devices/system/node/node%zu/cpulist", i);
+
+ r = read_one_line_file(p, &l);
+ if (r < 0)
+ return r;
+
+ r = parse_cpu_set(l, &part);
+ if (r < 0)
+ return r;
+
+ r = cpu_set_add_all(&s, &part);
+ if (r < 0)
+ return r;
+ }
+
+ *ret = s;
+ s = (CPUSet) {};
+
+ return 0;
+}
+
+static const char* const mpol_table[] = {
+ [MPOL_DEFAULT] = "default",
+ [MPOL_PREFERRED] = "preferred",
+ [MPOL_BIND] = "bind",
+ [MPOL_INTERLEAVE] = "interleave",
+ [MPOL_LOCAL] = "local",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(mpol, int);
diff --git a/src/shared/numa-util.h b/src/shared/numa-util.h
new file mode 100644
index 000000000..c99178903
--- /dev/null
+++ b/src/shared/numa-util.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "cpu-set-util.h"
+#include "missing_syscall.h"
+
+static inline bool mpol_is_valid(int t) {
+ return t >= MPOL_DEFAULT && t <= MPOL_LOCAL;
+}
+
+typedef struct NUMAPolicy {
+ /* Always use numa_policy_get_type() to read the value */
+ int type;
+ CPUSet nodes;
+} NUMAPolicy;
+
+bool numa_policy_is_valid(const NUMAPolicy *p);
+
+static inline int numa_policy_get_type(const NUMAPolicy *p) {
+ return p->type < 0 ? (p->nodes.set ? MPOL_PREFERRED : -1) : p->type;
+}
+
+static inline void numa_policy_reset(NUMAPolicy *p) {
+ assert(p);
+ cpu_set_reset(&p->nodes);
+ p->type = -1;
+}
+
+int apply_numa_policy(const NUMAPolicy *policy);
+int numa_to_cpu_set(const NUMAPolicy *policy, CPUSet *set);
+
+const char* mpol_to_string(int i) _const_;
+int mpol_from_string(const char *s) _pure_;
diff --git a/src/shared/path-lookup.c b/src/shared/path-lookup.c
index 5b1620974..48e0eec09 100644
--- a/src/shared/path-lookup.c
+++ b/src/shared/path-lookup.c
@@ -125,11 +125,12 @@ int xdg_user_dirs(char ***ret_config_dirs, char ***ret_data_dirs) {
_cleanup_strv_free_ char **config_dirs = NULL, **data_dirs = NULL;
e = getenv("XDG_CONFIG_DIRS");
- if (e) {
+ if (e)
config_dirs = strv_split(e, ":");
- if (!config_dirs)
- return -ENOMEM;
- }
+ else
+ config_dirs = strv_new("/etc/xdg");
+ if (!config_dirs)
+ return -ENOMEM;
e = getenv("XDG_DATA_DIRS");
if (e)
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 07f060e95..7ccdbe5fc 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -58,6 +58,7 @@
#include "main-func.h"
#include "memory-util.h"
#include "mkdir.h"
+#include "numa-util.h"
#include "pager.h"
#include "parse-util.h"
#include "path-lookup.h"
diff --git a/src/test/test-cpu-set-util.c b/src/test/test-cpu-set-util.c
index e1dd2eb32..450e19e06 100644
--- a/src/test/test-cpu-set-util.c
+++ b/src/test/test-cpu-set-util.c
@@ -216,12 +216,12 @@ static void test_parse_cpu_set_extend(void) {
log_info("/* %s */", __func__);
- assert_se(parse_cpu_set_extend("1 3", &c, true, NULL, "fake", 1, "CPUAffinity") == 0);
+ assert_se(parse_cpu_set_extend("1 3", &c, true, NULL, "fake", 1, "CPUAffinity") == 1);
assert_se(CPU_COUNT_S(c.allocated, c.set) == 2);
assert_se(s1 = cpu_set_to_string(&c));
log_info("cpu_set_to_string: %s", s1);
- assert_se(parse_cpu_set_extend("4", &c, true, NULL, "fake", 1, "CPUAffinity") == 0);
+ assert_se(parse_cpu_set_extend("4", &c, true, NULL, "fake", 1, "CPUAffinity") == 1);
assert_se(CPU_COUNT_S(c.allocated, c.set) == 3);
assert_se(s2 = cpu_set_to_string(&c));
log_info("cpu_set_to_string: %s", s2);
@@ -238,7 +238,7 @@ static void test_cpu_set_to_from_dbus(void) {
log_info("/* %s */", __func__);
- assert_se(parse_cpu_set_extend("1 3 8 100-200", &c, true, NULL, "fake", 1, "CPUAffinity") == 0);
+ assert_se(parse_cpu_set_extend("1 3 8 100-200", &c, true, NULL, "fake", 1, "CPUAffinity") == 1);
assert_se(s = cpu_set_to_string(&c));
log_info("cpu_set_to_string: %s", s);
assert_se(CPU_COUNT_S(c.allocated, c.set) == 104);
diff --git a/src/test/test-user-util.c b/src/test/test-user-util.c
index 084a58487..11c01e518 100644
--- a/src/test/test-user-util.c
+++ b/src/test/test-user-util.c
@@ -96,7 +96,7 @@ static void test_valid_user_group_name_compat(void) {
assert_se(valid_user_group_name_compat("eff."));
assert_se(valid_user_group_name_compat("some5"));
- assert_se(!valid_user_group_name_compat("5some"));
+ assert_se(valid_user_group_name_compat("5some"));
assert_se(valid_user_group_name_compat("INNER5NUMBER"));
}
@@ -166,7 +166,7 @@ static void test_valid_user_group_name_or_id_compat(void) {
assert_se(valid_user_group_name_or_id_compat("kk-k"));
assert_se(valid_user_group_name_or_id_compat("some5"));
- assert_se(!valid_user_group_name_or_id_compat("5some"));
+ assert_se(valid_user_group_name_or_id_compat("5some"));
assert_se(valid_user_group_name_or_id_compat("INNER5NUMBER"));
}
diff --git a/src/userdb/userwork.c b/src/userdb/userwork.c
index df11b5b98..3bc5ecc1d 100644
--- a/src/userdb/userwork.c
+++ b/src/userdb/userwork.c
@@ -763,7 +763,7 @@ static int run(int argc, char *argv[]) {
if (parent <= 1)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Parent already died?");
- if (kill(parent, SIGUSR1) < 0)
+ if (kill(parent, SIGUSR2) < 0)
return log_error_errno(errno, "Failed to kill our own parent.");
}
}
diff --git a/test/TEST-36-NUMAPOLICY/testsuite.sh b/test/TEST-36-NUMAPOLICY/testsuite.sh
index 4a2bede43..bd04bb2ef 100755
--- a/test/TEST-36-NUMAPOLICY/testsuite.sh
+++ b/test/TEST-36-NUMAPOLICY/testsuite.sh
@@ -279,6 +279,18 @@ else
# Maks must be ignored
grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog
+ echo "Unit file CPUAffinity=NUMA support"
+ writeTestUnitNUMAPolicy "bind" "0"
+ echo "CPUAffinity=numa" >> $testUnitNUMAConf
+ systemctl daemon-reload
+ systemctl start $testUnit
+ systemctlCheckNUMAProperties $testUnit "bind" "0"
+ pid=$(systemctl show --value -p MainPID $testUnit)
+ cpulist=$(cat /sys/devices/system/node/node0/cpulist)
+ affinity_systemd=$(systemctl show --value -p CPUAffinity $testUnit)
+ [ $cpulist = $affinity_systemd ]
+ pid1StopUnit $testUnit
+
echo "systemd-run NUMAPolicy support"
runUnit='numa-systemd-run-test.service'
@@ -309,6 +321,12 @@ else
systemd-run -p NUMAPolicy=local -p NUMAMask=0 --unit $runUnit sleep 1000
systemctlCheckNUMAProperties $runUnit "local" ""
pid1StopUnit $runUnit
+
+ systemd-run -p NUMAPolicy=local -p NUMAMask=0 -p CPUAffinity=numa --unit $runUnit sleep 1000
+ systemctlCheckNUMAProperties $runUnit "local" ""
+ systemctl cat $runUnit | grep -q 'CPUAffinity=numa'
+ pid1StopUnit $runUnit
+
fi
# Cleanup
diff --git a/units/sys-kernel-tracing.mount b/units/sys-kernel-tracing.mount
index cb42b4701..e29b258a4 100644
--- a/units/sys-kernel-tracing.mount
+++ b/units/sys-kernel-tracing.mount
@@ -12,6 +12,7 @@ Description=Kernel Trace File System
Documentation=https://www.kernel.org/doc/Documentation/trace/ftrace.txt
Documentation=https://www.freedesktop.org/wiki/Software/systemd/APIFileSystems
DefaultDependencies=no
+ConditionVirtualization=!lxc
ConditionPathExists=/sys/kernel/tracing
ConditionCapability=CAP_SYS_RAWIO
Before=sysinit.target
diff --git a/units/systemd-homed.service.in b/units/systemd-homed.service.in
index 7cf98e6fa..6490f48a1 100644
--- a/units/systemd-homed.service.in
+++ b/units/systemd-homed.service.in
@@ -10,7 +10,7 @@
[Unit]
Description=Home Area Manager
Documentation=man:systemd-homed.service(8)
-RequiresMountsFor=/home
+After=home.mount
[Service]
BusName=org.freedesktop.home1