static bool arg_crash_reboot;
static char *arg_confirm_spawn;
static ShowStatus arg_show_status;
+static StatusUnitFormat arg_status_unit_format;
static bool arg_switched_root;
static PagerFlags arg_pager_flags;
static bool arg_service_watchdogs;
static EmergencyAction arg_cad_burst_action;
static OOMPolicy arg_default_oom_policy;
static CPUSet arg_cpu_affinity;
+static NUMAPolicy arg_numa_policy;
static int parse_configuration(void);
return 0;
}
-static int parse_crash_chvt(const char *value) {
- int b;
-
- if (safe_atoi(value, &arg_crash_chvt) >= 0)
- return 0;
-
- b = parse_boolean(value);
- if (b < 0)
- return b;
-
- if (b > 0)
- arg_crash_chvt = 0; /* switch to where kmsg goes */
- else
- arg_crash_chvt = -1; /* turn off switching */
-
- return 0;
-}
-
-static int parse_confirm_spawn(const char *value, char **console) {
- char *s;
- int r;
-
- r = value ? parse_boolean(value) : 1;
- if (r == 0) {
- *console = NULL;
- return 0;
- }
-
- if (r > 0) /* on with default tty */
- s = strdup("/dev/console");
- else if (is_path(value)) /* on with fully qualified path */
- s = strdup(value);
- else /* on with only a tty file name, not a fully qualified path */
- s = strjoin("/dev/", value);
- if (!s)
- return -ENOMEM;
-
- *console = s;
- return 0;
-}
-
static int set_machine_id(const char *m) {
sd_id128_t t;
assert(m);
if (!value)
arg_crash_chvt = 0; /* turn on */
else {
- r = parse_crash_chvt(value);
+ r = parse_crash_chvt(value, &arg_crash_chvt);
if (r < 0)
log_warning_errno(r, "Failed to parse crash chvt switch %s, ignoring: %m", value);
}
} else
arg_show_status = SHOW_STATUS_YES;
+ } else if (proc_cmdline_key_streq(key, "systemd.status_unit_format")) {
+
+ if (proc_cmdline_value_missing(key, value))
+ return 0;
+
+ r = status_unit_format_from_string(value);
+ if (r < 0)
+ log_warning_errno(r, "Failed to parse %s=%s, ignoring: %m", key, value);
+ else
+ arg_status_unit_format = r;
+
} else if (proc_cmdline_key_streq(key, "systemd.default_standard_output")) {
if (proc_cmdline_value_missing(key, value))
DEFINE_SETTER(config_parse_target, log_set_target_from_string, "target");
DEFINE_SETTER(config_parse_color, log_show_color_from_string, "color" );
DEFINE_SETTER(config_parse_location, log_show_location_from_string, "location");
-
-static int config_parse_cpu_affinity2(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- CPUSet *affinity = data;
-
- assert(affinity);
-
- (void) parse_cpu_set_extend(rvalue, affinity, true, unit, filename, line, lvalue);
-
- return 0;
-}
-
-static int config_parse_show_status(
- const char* unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- int k;
- ShowStatus *b = data;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- k = parse_show_status(rvalue, b);
- if (k < 0) {
- log_syntax(unit, LOG_ERR, filename, line, k, "Failed to parse show status setting, ignoring: %s", rvalue);
- return 0;
- }
-
- return 0;
-}
-
-static int config_parse_output_restricted(
- const char* unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- ExecOutput t, *eo = data;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- t = exec_output_from_string(rvalue);
- if (t < 0) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse output type, ignoring: %s", rvalue);
- return 0;
- }
-
- if (IN_SET(t, EXEC_OUTPUT_SOCKET, EXEC_OUTPUT_NAMED_FD, EXEC_OUTPUT_FILE, EXEC_OUTPUT_FILE_APPEND)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Standard output types socket, fd:, file:, append: are not supported as defaults, ignoring: %s", rvalue);
- return 0;
- }
-
- *eo = t;
- return 0;
-}
-
-static int config_parse_crash_chvt(
- const char* unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
-
- r = parse_crash_chvt(rvalue);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CrashChangeVT= setting, ignoring: %s", rvalue);
- return 0;
- }
-
- return 0;
-}
-
-static int config_parse_timeout_abort(
- const char* unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
-
- rvalue += strspn(rvalue, WHITESPACE);
- if (isempty(rvalue)) {
- arg_default_timeout_abort_set = false;
- return 0;
- }
-
- r = parse_sec(rvalue, &arg_default_timeout_abort_usec);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse DefaultTimeoutAbortSec= setting, ignoring: %s", rvalue);
- return 0;
- }
-
- arg_default_timeout_abort_set = true;
- return 0;
-}
+DEFINE_SETTER(config_parse_status_unit_format, status_unit_format_from_string, "value");
static int parse_config_file(void) {
const ConfigTableItem items[] = {
- { "Manager", "LogLevel", config_parse_level2, 0, NULL },
- { "Manager", "LogTarget", config_parse_target, 0, NULL },
- { "Manager", "LogColor", config_parse_color, 0, NULL },
- { "Manager", "LogLocation", config_parse_location, 0, NULL },
- { "Manager", "DumpCore", config_parse_bool, 0, &arg_dump_core },
- { "Manager", "CrashChVT", /* legacy */ config_parse_crash_chvt, 0, NULL },
- { "Manager", "CrashChangeVT", config_parse_crash_chvt, 0, NULL },
- { "Manager", "CrashShell", config_parse_bool, 0, &arg_crash_shell },
- { "Manager", "CrashReboot", config_parse_bool, 0, &arg_crash_reboot },
- { "Manager", "ShowStatus", config_parse_show_status, 0, &arg_show_status },
- { "Manager", "CPUAffinity", config_parse_cpu_affinity2, 0, &arg_cpu_affinity },
- { "Manager", "JoinControllers", config_parse_warn_compat, DISABLED_CONFIGURATION, NULL },
- { "Manager", "RuntimeWatchdogSec", config_parse_sec, 0, &arg_runtime_watchdog },
- { "Manager", "ShutdownWatchdogSec", config_parse_sec, 0, &arg_shutdown_watchdog },
- { "Manager", "WatchdogDevice", config_parse_path, 0, &arg_watchdog_device },
- { "Manager", "CapabilityBoundingSet", config_parse_capability_set, 0, &arg_capability_bounding_set },
- { "Manager", "NoNewPrivileges", config_parse_bool, 0, &arg_no_new_privs },
+ { "Manager", "LogLevel", config_parse_level2, 0, NULL },
+ { "Manager", "LogTarget", config_parse_target, 0, NULL },
+ { "Manager", "LogColor", config_parse_color, 0, NULL },
+ { "Manager", "LogLocation", config_parse_location, 0, NULL },
+ { "Manager", "DumpCore", config_parse_bool, 0, &arg_dump_core },
+ { "Manager", "CrashChVT", /* legacy */ config_parse_crash_chvt, 0, &arg_crash_chvt },
+ { "Manager", "CrashChangeVT", config_parse_crash_chvt, 0, &arg_crash_chvt },
+ { "Manager", "CrashShell", config_parse_bool, 0, &arg_crash_shell },
+ { "Manager", "CrashReboot", config_parse_bool, 0, &arg_crash_reboot },
+ { "Manager", "ShowStatus", config_parse_show_status, 0, &arg_show_status },
+ { "Manager", "StatusUnitFormat", config_parse_status_unit_format, 0, &arg_status_unit_format },
+ { "Manager", "CPUAffinity", config_parse_cpu_affinity2, 0, &arg_cpu_affinity },
+ { "Manager", "NUMAPolicy", config_parse_numa_policy, 0, &arg_numa_policy.type },
+ { "Manager", "NUMAMask", config_parse_numa_mask, 0, &arg_numa_policy },
+ { "Manager", "JoinControllers", config_parse_warn_compat, DISABLED_CONFIGURATION, NULL },
+ { "Manager", "RuntimeWatchdogSec", config_parse_sec, 0, &arg_runtime_watchdog },
+ { "Manager", "ShutdownWatchdogSec", config_parse_sec, 0, &arg_shutdown_watchdog },
+ { "Manager", "WatchdogDevice", config_parse_path, 0, &arg_watchdog_device },
+ { "Manager", "CapabilityBoundingSet", config_parse_capability_set, 0, &arg_capability_bounding_set },
+ { "Manager", "NoNewPrivileges", config_parse_bool, 0, &arg_no_new_privs },
#if HAVE_SECCOMP
- { "Manager", "SystemCallArchitectures", config_parse_syscall_archs, 0, &arg_syscall_archs },
+ { "Manager", "SystemCallArchitectures", config_parse_syscall_archs, 0, &arg_syscall_archs },
#endif
- { "Manager", "TimerSlackNSec", config_parse_nsec, 0, &arg_timer_slack_nsec },
- { "Manager", "DefaultTimerAccuracySec", config_parse_sec, 0, &arg_default_timer_accuracy_usec },
- { "Manager", "DefaultStandardOutput", config_parse_output_restricted,0, &arg_default_std_output },
- { "Manager", "DefaultStandardError", config_parse_output_restricted,0, &arg_default_std_error },
- { "Manager", "DefaultTimeoutStartSec", config_parse_sec, 0, &arg_default_timeout_start_usec },
- { "Manager", "DefaultTimeoutStopSec", config_parse_sec, 0, &arg_default_timeout_stop_usec },
- { "Manager", "DefaultTimeoutAbortSec", config_parse_timeout_abort, 0, NULL },
- { "Manager", "DefaultRestartSec", config_parse_sec, 0, &arg_default_restart_usec },
- { "Manager", "DefaultStartLimitInterval", config_parse_sec, 0, &arg_default_start_limit_interval }, /* obsolete alias */
- { "Manager", "DefaultStartLimitIntervalSec",config_parse_sec, 0, &arg_default_start_limit_interval },
- { "Manager", "DefaultStartLimitBurst", config_parse_unsigned, 0, &arg_default_start_limit_burst },
- { "Manager", "DefaultEnvironment", config_parse_environ, 0, &arg_default_environment },
- { "Manager", "DefaultLimitCPU", config_parse_rlimit, RLIMIT_CPU, arg_default_rlimit },
- { "Manager", "DefaultLimitFSIZE", config_parse_rlimit, RLIMIT_FSIZE, arg_default_rlimit },
- { "Manager", "DefaultLimitDATA", config_parse_rlimit, RLIMIT_DATA, arg_default_rlimit },
- { "Manager", "DefaultLimitSTACK", config_parse_rlimit, RLIMIT_STACK, arg_default_rlimit },
- { "Manager", "DefaultLimitCORE", config_parse_rlimit, RLIMIT_CORE, arg_default_rlimit },
- { "Manager", "DefaultLimitRSS", config_parse_rlimit, RLIMIT_RSS, arg_default_rlimit },
- { "Manager", "DefaultLimitNOFILE", config_parse_rlimit, RLIMIT_NOFILE, arg_default_rlimit },
- { "Manager", "DefaultLimitAS", config_parse_rlimit, RLIMIT_AS, arg_default_rlimit },
- { "Manager", "DefaultLimitNPROC", config_parse_rlimit, RLIMIT_NPROC, arg_default_rlimit },
- { "Manager", "DefaultLimitMEMLOCK", config_parse_rlimit, RLIMIT_MEMLOCK, arg_default_rlimit },
- { "Manager", "DefaultLimitLOCKS", config_parse_rlimit, RLIMIT_LOCKS, arg_default_rlimit },
- { "Manager", "DefaultLimitSIGPENDING", config_parse_rlimit, RLIMIT_SIGPENDING, arg_default_rlimit },
- { "Manager", "DefaultLimitMSGQUEUE", config_parse_rlimit, RLIMIT_MSGQUEUE, arg_default_rlimit },
- { "Manager", "DefaultLimitNICE", config_parse_rlimit, RLIMIT_NICE, arg_default_rlimit },
- { "Manager", "DefaultLimitRTPRIO", config_parse_rlimit, RLIMIT_RTPRIO, arg_default_rlimit },
- { "Manager", "DefaultLimitRTTIME", config_parse_rlimit, RLIMIT_RTTIME, arg_default_rlimit },
- { "Manager", "DefaultCPUAccounting", config_parse_tristate, 0, &arg_default_cpu_accounting },
- { "Manager", "DefaultIOAccounting", config_parse_bool, 0, &arg_default_io_accounting },
- { "Manager", "DefaultIPAccounting", config_parse_bool, 0, &arg_default_ip_accounting },
- { "Manager", "DefaultBlockIOAccounting", config_parse_bool, 0, &arg_default_blockio_accounting },
- { "Manager", "DefaultMemoryAccounting", config_parse_bool, 0, &arg_default_memory_accounting },
- { "Manager", "DefaultTasksAccounting", config_parse_bool, 0, &arg_default_tasks_accounting },
- { "Manager", "DefaultTasksMax", config_parse_tasks_max, 0, &arg_default_tasks_max },
- { "Manager", "CtrlAltDelBurstAction", config_parse_emergency_action, 0, &arg_cad_burst_action },
- { "Manager", "DefaultOOMPolicy", config_parse_oom_policy, 0, &arg_default_oom_policy },
+ { "Manager", "TimerSlackNSec", config_parse_nsec, 0, &arg_timer_slack_nsec },
+ { "Manager", "DefaultTimerAccuracySec", config_parse_sec, 0, &arg_default_timer_accuracy_usec },
+ { "Manager", "DefaultStandardOutput", config_parse_output_restricted, 0, &arg_default_std_output },
+ { "Manager", "DefaultStandardError", config_parse_output_restricted, 0, &arg_default_std_error },
+ { "Manager", "DefaultTimeoutStartSec", config_parse_sec, 0, &arg_default_timeout_start_usec },
+ { "Manager", "DefaultTimeoutStopSec", config_parse_sec, 0, &arg_default_timeout_stop_usec },
+ { "Manager", "DefaultTimeoutAbortSec", config_parse_timeout_abort, 0, &arg_default_timeout_abort_set },
+ { "Manager", "DefaultRestartSec", config_parse_sec, 0, &arg_default_restart_usec },
+ { "Manager", "DefaultStartLimitInterval", config_parse_sec, 0, &arg_default_start_limit_interval }, /* obsolete alias */
+ { "Manager", "DefaultStartLimitIntervalSec", config_parse_sec, 0, &arg_default_start_limit_interval },
+ { "Manager", "DefaultStartLimitBurst", config_parse_unsigned, 0, &arg_default_start_limit_burst },
+ { "Manager", "DefaultEnvironment", config_parse_environ, 0, &arg_default_environment },
+ { "Manager", "DefaultLimitCPU", config_parse_rlimit, RLIMIT_CPU, arg_default_rlimit },
+ { "Manager", "DefaultLimitFSIZE", config_parse_rlimit, RLIMIT_FSIZE, arg_default_rlimit },
+ { "Manager", "DefaultLimitDATA", config_parse_rlimit, RLIMIT_DATA, arg_default_rlimit },
+ { "Manager", "DefaultLimitSTACK", config_parse_rlimit, RLIMIT_STACK, arg_default_rlimit },
+ { "Manager", "DefaultLimitCORE", config_parse_rlimit, RLIMIT_CORE, arg_default_rlimit },
+ { "Manager", "DefaultLimitRSS", config_parse_rlimit, RLIMIT_RSS, arg_default_rlimit },
+ { "Manager", "DefaultLimitNOFILE", config_parse_rlimit, RLIMIT_NOFILE, arg_default_rlimit },
+ { "Manager", "DefaultLimitAS", config_parse_rlimit, RLIMIT_AS, arg_default_rlimit },
+ { "Manager", "DefaultLimitNPROC", config_parse_rlimit, RLIMIT_NPROC, arg_default_rlimit },
+ { "Manager", "DefaultLimitMEMLOCK", config_parse_rlimit, RLIMIT_MEMLOCK, arg_default_rlimit },
+ { "Manager", "DefaultLimitLOCKS", config_parse_rlimit, RLIMIT_LOCKS, arg_default_rlimit },
+ { "Manager", "DefaultLimitSIGPENDING", config_parse_rlimit, RLIMIT_SIGPENDING, arg_default_rlimit },
+ { "Manager", "DefaultLimitMSGQUEUE", config_parse_rlimit, RLIMIT_MSGQUEUE, arg_default_rlimit },
+ { "Manager", "DefaultLimitNICE", config_parse_rlimit, RLIMIT_NICE, arg_default_rlimit },
+ { "Manager", "DefaultLimitRTPRIO", config_parse_rlimit, RLIMIT_RTPRIO, arg_default_rlimit },
+ { "Manager", "DefaultLimitRTTIME", config_parse_rlimit, RLIMIT_RTTIME, arg_default_rlimit },
+ { "Manager", "DefaultCPUAccounting", config_parse_tristate, 0, &arg_default_cpu_accounting },
+ { "Manager", "DefaultIOAccounting", config_parse_bool, 0, &arg_default_io_accounting },
+ { "Manager", "DefaultIPAccounting", config_parse_bool, 0, &arg_default_ip_accounting },
+ { "Manager", "DefaultBlockIOAccounting", config_parse_bool, 0, &arg_default_blockio_accounting },
+ { "Manager", "DefaultMemoryAccounting", config_parse_bool, 0, &arg_default_memory_accounting },
+ { "Manager", "DefaultTasksAccounting", config_parse_bool, 0, &arg_default_tasks_accounting },
+ { "Manager", "DefaultTasksMax", config_parse_tasks_max, 0, &arg_default_tasks_max },
+ { "Manager", "CtrlAltDelBurstAction", config_parse_emergency_action, 0, &arg_cad_burst_action },
+ { "Manager", "DefaultOOMPolicy", config_parse_oom_policy, 0, &arg_default_oom_policy },
{}
};
m->cad_burst_action = arg_cad_burst_action;
manager_set_show_status(m, arg_show_status);
+ m->status_unit_format = arg_status_unit_format;
}
static int parse_argv(int argc, char *argv[]) {
break;
case ARG_CRASH_CHVT:
- r = parse_crash_chvt(optarg);
+ r = parse_crash_chvt(optarg, &arg_crash_chvt);
if (r < 0)
return log_error_errno(r, "Failed to parse crash virtual terminal index: \"%s\": %m",
optarg);
"Starts up and maintains the system or user services.\n\n"
" -h --help Show this help\n"
" --version Show version\n"
- " --test Determine startup sequence, dump it and exit\n"
+ " --test Determine initial transaction, dump it and exit\n"
+ " --system In combination with --test: operate as system service manager\n"
+ " --user In combination with --test: operate as per-user service manager\n"
" --no-pager Do not pipe output into a pager\n"
" --dump-configuration-items Dump understood unit configuration items\n"
" --dump-bus-properties Dump exposed bus properties\n"
" --unit=UNIT Set default unit\n"
- " --system Run a system instance, even if PID != 1\n"
- " --user Run a user instance\n"
" --dump-core[=BOOL] Dump core on crash\n"
" --crash-vt=NR Change to specified VT on crash\n"
" --crash-reboot[=BOOL] Reboot on crash\n"
#endif
#if BUMP_PROC_SYS_FS_FILE_MAX
- /* I so wanted to use STRINGIFY(ULONG_MAX) here, but alas we can't as glibc/gcc define that as
- * "(0x7fffffffffffffffL * 2UL + 1UL)". Seriously. 😢 */
- if (asprintf(&t, "%lu\n", ULONG_MAX) < 0) {
+ /* The maximum the kernel allows for this since 5.2 is LONG_MAX, use that. (Previously thing where
+ * different but the operation would fail silently.) */
+ if (asprintf(&t, "%li\n", LONG_MAX) < 0) {
log_oom();
return;
}
log_warning_errno(errno, "Failed to set CPU affinity: %m");
}
+static void update_numa_policy(bool skip_setup) {
+ int r;
+ _cleanup_free_ char *nodes = NULL;
+ const char * policy = NULL;
+
+ if (skip_setup || !mpol_is_valid(numa_policy_get_type(&arg_numa_policy)))
+ return;
+
+ if (DEBUG_LOGGING) {
+ policy = mpol_to_string(numa_policy_get_type(&arg_numa_policy));
+ nodes = cpu_set_to_range_string(&arg_numa_policy.nodes);
+ log_debug("Setting NUMA policy to %s, with nodes %s.", strnull(policy), strnull(nodes));
+ }
+
+ r = apply_numa_policy(&arg_numa_policy);
+ if (r == -EOPNOTSUPP)
+ log_debug_errno(r, "NUMA support not available, ignoring.");
+ else if (r < 0)
+ log_warning_errno(r, "Failed to set NUMA memory policy: %m");
+}
+
static void do_reexecute(
int argc,
char *argv[],
set_manager_defaults(m);
update_cpu_affinity(false);
+ update_numa_policy(false);
if (saved_log_level >= 0)
manager_override_log_level(m, saved_log_level);
return 0;
update_cpu_affinity(skip_setup);
+ update_numa_policy(skip_setup);
if (arg_system) {
/* Make sure we leave a core dump without panicking the kernel. */
log_warning_errno(r, "Failed to set watchdog device to %s, ignoring: %m", arg_watchdog_device);
}
- if (arg_runtime_watchdog > 0 && arg_runtime_watchdog != USEC_INFINITY)
+ if (timestamp_is_set(arg_runtime_watchdog))
watchdog_set_timeout(&arg_runtime_watchdog);
}
arg_crash_reboot = false;
arg_confirm_spawn = mfree(arg_confirm_spawn);
arg_show_status = _SHOW_STATUS_INVALID;
+ arg_status_unit_format = STATUS_UNIT_FORMAT_DEFAULT;
arg_switched_root = false;
arg_pager_flags = 0;
arg_service_watchdogs = true;
arg_default_oom_policy = OOM_STOP;
cpu_set_reset(&arg_cpu_affinity);
+ numa_policy_reset(&arg_numa_policy);
}
static int parse_configuration(void) {