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