mirror of
https://github.com/systemd/systemd
synced 2026-04-03 13:44:55 +02:00
Compare commits
No commits in common. "3663f754f1dab56c5860d91e42983d30243d0617" and "aedec452b9e5dd197881f2164fb205dfe8bfdcec" have entirely different histories.
3663f754f1
...
aedec452b9
@ -99,8 +99,8 @@
|
||||
<term><option>set-default</option> <replaceable>ID</replaceable></term>
|
||||
<term><option>set-oneshot</option> <replaceable>ID</replaceable></term>
|
||||
|
||||
<listitem><para>Sets the default boot loader entry. Takes a single boot loader entry ID string or a glob
|
||||
pattern as argument. The <option>set-oneshot</option> command will set the default entry only for the next boot,
|
||||
<listitem><para>Sets the default boot loader entry. Takes a single boot loader entry ID string as
|
||||
argument. The <option>set-oneshot</option> command will set the default entry only for the next boot,
|
||||
the <option>set-default</option> will set it persistently for all future boots.</para></listitem>
|
||||
|
||||
<listitem><para>Optionally, the boot loader entry ID may be specified as one of: <option>@default</option>,
|
||||
@ -111,12 +111,8 @@
|
||||
see <ulink url="https://systemd.io/BOOT_LOADER_SPECIFICATION">Boot Loader Specification</ulink> for details.
|
||||
These special IDs are primarily useful as a quick way to persistently make the currently booted boot loader
|
||||
entry the default choice, or to upgrade the default boot loader entry for the next boot to the default boot
|
||||
loader entry for all future boots, but may be used for other operations too.</para>
|
||||
|
||||
<para>If set to <option>@saved</option> the chosen entry will be saved as an EFI variable
|
||||
on every boot and automatically selected the next time the boot loader starts.</para>
|
||||
|
||||
<para>When an empty string ("") is specified as an ID, then the corresponding EFI variable will be unset.
|
||||
loader entry for all future boots, but may be used for other operations too.
|
||||
When an empty string ("") is specified as an ID, then the corresponding EFI variable will be unset.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
@ -60,9 +60,6 @@
|
||||
selected entry will be stored as an EFI variable, overriding this option.
|
||||
</para>
|
||||
|
||||
<para>If set to <literal>@saved</literal> the chosen entry will be saved as an EFI variable
|
||||
on every boot and automatically selected the next time the boot loader starts.</para>
|
||||
|
||||
<table>
|
||||
<title>Automatically detected entries will use the following names:</title>
|
||||
|
||||
|
||||
@ -72,4 +72,3 @@ Packages=
|
||||
strace
|
||||
tpm2-tss
|
||||
less
|
||||
netcat
|
||||
|
||||
@ -1834,7 +1834,7 @@ static int parse_loader_entry_target_arg(const char *arg1, char16_t **ret_target
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to get EFI variable 'LoaderEntryDefault': %m");
|
||||
|
||||
} else if (arg1[0] == '@' && !streq(arg1, "@saved"))
|
||||
} else if (arg1[0] == '@')
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unsupported special entry identifier: %s", arg1);
|
||||
else {
|
||||
encoded = utf8_to_utf16(arg1, strlen(arg1));
|
||||
|
||||
@ -67,17 +67,13 @@ typedef struct {
|
||||
UINT32 timeout_sec; /* Actual timeout used (efi_main() override > efivar > config). */
|
||||
UINT32 timeout_sec_config;
|
||||
UINT32 timeout_sec_efivar;
|
||||
CHAR16 *entry_default_config;
|
||||
CHAR16 *entry_default_efivar;
|
||||
CHAR16 *entry_default_pattern;
|
||||
CHAR16 *entry_oneshot;
|
||||
CHAR16 *entry_saved;
|
||||
CHAR16 *options_edit;
|
||||
BOOLEAN editor;
|
||||
BOOLEAN auto_entries;
|
||||
BOOLEAN auto_firmware;
|
||||
BOOLEAN force_menu;
|
||||
BOOLEAN use_saved_entry;
|
||||
BOOLEAN use_saved_entry_efivar;
|
||||
INT64 console_mode;
|
||||
INT64 console_mode_efivar;
|
||||
RandomSeedMode random_seed_mode;
|
||||
@ -439,7 +435,7 @@ static void print_status(Config *config, CHAR16 *loaded_image_path) {
|
||||
UINT64 key;
|
||||
UINTN x_max, y_max;
|
||||
SecureBootMode secure;
|
||||
_cleanup_freepool_ CHAR16 *device_part_uuid = NULL;
|
||||
_cleanup_freepool_ CHAR16 *device_part_uuid = NULL, *default_efivar = NULL;
|
||||
|
||||
assert(config);
|
||||
assert(loaded_image_path);
|
||||
@ -449,6 +445,7 @@ static void print_status(Config *config, CHAR16 *loaded_image_path) {
|
||||
|
||||
secure = secure_boot_mode();
|
||||
(void) efivar_get(LOADER_GUID, L"LoaderDevicePartUUID", &device_part_uuid);
|
||||
(void) efivar_get(LOADER_GUID, L"LoaderEntryDefault", &default_efivar);
|
||||
|
||||
/* We employ some unusual indentation here for readability. */
|
||||
|
||||
@ -489,10 +486,9 @@ static void print_status(Config *config, CHAR16 *loaded_image_path) {
|
||||
Print(L" timeout (EFI var): %lu s\n", config->timeout_sec_efivar);
|
||||
}
|
||||
|
||||
ps_string(L" default: %s\n", config->entry_default_config);
|
||||
ps_string(L" default (EFI var): %s\n", config->entry_default_efivar);
|
||||
ps_string(L" default: %s\n", config->entry_default_pattern);
|
||||
ps_string(L" default (one-shot): %s\n", config->entry_oneshot);
|
||||
ps_string(L" saved entry: %s\n", config->entry_saved);
|
||||
ps_string(L" default (EFI var): %s\n", default_efivar);
|
||||
ps_bool(L" editor: %s\n", config->editor);
|
||||
ps_bool(L" auto-entries: %s\n", config->auto_entries);
|
||||
ps_bool(L" auto-firmware: %s\n", config->auto_firmware);
|
||||
@ -590,7 +586,6 @@ static BOOLEAN menu_run(
|
||||
INT16 idx;
|
||||
BOOLEAN exit = FALSE, run = TRUE, firmware_setup = FALSE;
|
||||
INT64 console_mode_initial = ST->ConOut->Mode->Mode, console_mode_efivar_saved = config->console_mode_efivar;
|
||||
INTN default_efivar_saved = config->idx_default_efivar;
|
||||
|
||||
graphics_mode(FALSE);
|
||||
ST->ConIn->Reset(ST->ConIn, FALSE);
|
||||
@ -836,20 +831,20 @@ static BOOLEAN menu_run(
|
||||
case KEYPRESS(0, 0, 'd'):
|
||||
case KEYPRESS(0, 0, 'D'):
|
||||
if (config->idx_default_efivar != (INTN)idx_highlight) {
|
||||
FreePool(config->entry_default_efivar);
|
||||
config->entry_default_efivar = StrDuplicate(config->entries[idx_highlight]->id);
|
||||
if (!config->entry_default_efivar) {
|
||||
log_oom();
|
||||
return FALSE;
|
||||
}
|
||||
/* store the selected entry in a persistent EFI variable */
|
||||
efivar_set(
|
||||
LOADER_GUID,
|
||||
L"LoaderEntryDefault",
|
||||
config->entries[idx_highlight]->id,
|
||||
EFI_VARIABLE_NON_VOLATILE);
|
||||
config->idx_default_efivar = idx_highlight;
|
||||
status = StrDuplicate(L"Default boot entry selected.");
|
||||
} else {
|
||||
config->entry_default_efivar = mfree(config->entry_default_efivar);
|
||||
/* clear the default entry EFI variable */
|
||||
efivar_set(LOADER_GUID, L"LoaderEntryDefault", NULL, EFI_VARIABLE_NON_VOLATILE);
|
||||
config->idx_default_efivar = -1;
|
||||
status = StrDuplicate(L"Default boot entry cleared.");
|
||||
}
|
||||
config->use_saved_entry_efivar = FALSE;
|
||||
refresh = TRUE;
|
||||
break;
|
||||
|
||||
@ -959,9 +954,6 @@ static BOOLEAN menu_run(
|
||||
|
||||
/* Update EFI vars after we left the menu to reduce NVRAM writes. */
|
||||
|
||||
if (default_efivar_saved != config->idx_default_efivar)
|
||||
efivar_set(LOADER_GUID, L"LoaderEntryDefault", config->entry_default_efivar, EFI_VARIABLE_NON_VOLATILE);
|
||||
|
||||
if (console_mode_efivar_saved != config->console_mode_efivar) {
|
||||
if (config->console_mode_efivar == CONSOLE_MODE_KEEP)
|
||||
efivar_set(LOADER_GUID, L"LoaderConfigConsoleMode", NULL, EFI_VARIABLE_NON_VOLATILE);
|
||||
@ -1117,12 +1109,9 @@ static void config_defaults_load_from_file(Config *config, CHAR8 *content) {
|
||||
}
|
||||
|
||||
if (strcmpa((CHAR8 *)"default", key) == 0) {
|
||||
if (value[0] == '@' && strcmpa((CHAR8 *)"@saved", value) != 0) {
|
||||
log_error_stall(L"Unsupported special entry identifier: %a", value);
|
||||
continue;
|
||||
}
|
||||
FreePool(config->entry_default_config);
|
||||
config->entry_default_config = stra_to_str(value);
|
||||
FreePool(config->entry_default_pattern);
|
||||
config->entry_default_pattern = stra_to_str(value);
|
||||
StrLwr(config->entry_default_pattern);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1548,18 +1537,6 @@ static void config_load_defaults(Config *config, EFI_FILE *root_dir) {
|
||||
err = efivar_get_uint_string(LOADER_GUID, L"LoaderConfigConsoleMode", &value);
|
||||
if (!EFI_ERROR(err))
|
||||
config->console_mode_efivar = value;
|
||||
|
||||
err = efivar_get(LOADER_GUID, L"LoaderEntryOneShot", &config->entry_oneshot);
|
||||
if (!EFI_ERROR(err))
|
||||
/* Unset variable now, after all it's "one shot". */
|
||||
(void) efivar_set(LOADER_GUID, L"LoaderEntryOneShot", NULL, EFI_VARIABLE_NON_VOLATILE);
|
||||
|
||||
(void) efivar_get(LOADER_GUID, L"LoaderEntryDefault", &config->entry_default_efivar);
|
||||
|
||||
config->use_saved_entry = streq_ptr(config->entry_default_config, L"@saved");
|
||||
config->use_saved_entry_efivar = streq_ptr(config->entry_default_efivar, L"@saved");
|
||||
if (config->use_saved_entry || config->use_saved_entry_efivar)
|
||||
(void) efivar_get(LOADER_GUID, L"LoaderEntryLastBooted", &config->entry_saved);
|
||||
}
|
||||
|
||||
static void config_load_entries(
|
||||
@ -1645,45 +1622,69 @@ static void config_sort_entries(Config *config) {
|
||||
sort_pointer_array((void**) config->entries, config->entry_count, (compare_pointer_func_t) config_entry_compare);
|
||||
}
|
||||
|
||||
static INTN config_entry_find(Config *config, CHAR16 *needle) {
|
||||
static INTN config_entry_find(Config *config, CHAR16 *id) {
|
||||
assert(config);
|
||||
|
||||
if (!needle)
|
||||
return -1;
|
||||
assert(id);
|
||||
|
||||
for (UINTN i = 0; i < config->entry_count; i++)
|
||||
if (MetaiMatch(config->entries[i]->id, needle))
|
||||
if (StrCmp(config->entries[i]->id, id) == 0)
|
||||
return (INTN) i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void config_default_entry_select(Config *config) {
|
||||
_cleanup_freepool_ CHAR16 *entry_default = NULL;
|
||||
EFI_STATUS err;
|
||||
INTN i;
|
||||
|
||||
assert(config);
|
||||
|
||||
i = config_entry_find(config, config->entry_oneshot);
|
||||
if (i >= 0) {
|
||||
config->idx_default = i;
|
||||
return;
|
||||
/*
|
||||
* The EFI variable to specify a boot entry for the next, and only the
|
||||
* next reboot. The variable is always cleared directly after it is read.
|
||||
*/
|
||||
err = efivar_get(LOADER_GUID, L"LoaderEntryOneShot", &config->entry_oneshot);
|
||||
if (!EFI_ERROR(err)) {
|
||||
efivar_set(LOADER_GUID, L"LoaderEntryOneShot", NULL, EFI_VARIABLE_NON_VOLATILE);
|
||||
|
||||
i = config_entry_find(config, config->entry_oneshot);
|
||||
if (i >= 0) {
|
||||
config->idx_default = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
i = config_entry_find(config, config->use_saved_entry_efivar ? config->entry_saved : config->entry_default_efivar);
|
||||
if (i >= 0) {
|
||||
config->idx_default = i;
|
||||
config->idx_default_efivar = i;
|
||||
return;
|
||||
/*
|
||||
* The EFI variable to select the default boot entry overrides the
|
||||
* configured pattern. The variable can be set and cleared by pressing
|
||||
* the 'd' key in the loader selection menu.
|
||||
*/
|
||||
err = efivar_get(LOADER_GUID, L"LoaderEntryDefault", &entry_default);
|
||||
if (!EFI_ERROR(err)) {
|
||||
i = config_entry_find(config, entry_default);
|
||||
if (i >= 0) {
|
||||
config->idx_default = i;
|
||||
config->idx_default_efivar = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (config->use_saved_entry)
|
||||
/* No need to do the same thing twice. */
|
||||
i = config->use_saved_entry_efivar ? -1 : config_entry_find(config, config->entry_saved);
|
||||
else
|
||||
i = config_entry_find(config, config->entry_default_config);
|
||||
if (i >= 0) {
|
||||
config->idx_default = i;
|
||||
if (config->entry_count == 0)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Match the pattern from the end of the list to the start, find last
|
||||
* entry (largest number) matching the given pattern.
|
||||
*/
|
||||
if (config->entry_default_pattern) {
|
||||
i = config->entry_count;
|
||||
while (i--) {
|
||||
if (MetaiMatch(config->entries[i]->id, config->entry_default_pattern)) {
|
||||
config->idx_default = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* select the last suitable entry */
|
||||
@ -2223,7 +2224,7 @@ static void config_free(Config *config) {
|
||||
for (UINTN i = 0; i < config->entry_count; i++)
|
||||
config_entry_free(config->entries[i]);
|
||||
FreePool(config->entries);
|
||||
FreePool(config->entry_default_config);
|
||||
FreePool(config->entry_default_pattern);
|
||||
FreePool(config->options_edit);
|
||||
FreePool(config->entry_oneshot);
|
||||
}
|
||||
@ -2255,29 +2256,6 @@ static void config_write_entries_to_variable(Config *config) {
|
||||
(void) efivar_set_raw(LOADER_GUID, L"LoaderEntries", buffer, sz, 0);
|
||||
}
|
||||
|
||||
static void save_selected_entry(const Config *config, const ConfigEntry *entry) {
|
||||
assert(config);
|
||||
assert(entry);
|
||||
assert(!entry->call);
|
||||
|
||||
/* Always export the selected boot entry to the system in a volatile var. */
|
||||
(void) efivar_set(LOADER_GUID, L"LoaderEntrySelected", entry->id, 0);
|
||||
|
||||
/* Do not save or delete if this was a oneshot boot. */
|
||||
if (streq_ptr(config->entry_oneshot, entry->id))
|
||||
return;
|
||||
|
||||
if (config->use_saved_entry_efivar || (!config->entry_default_efivar && config->use_saved_entry)) {
|
||||
/* Avoid unnecessary NVRAM writes. */
|
||||
if (streq_ptr(config->entry_saved, entry->id))
|
||||
return;
|
||||
|
||||
(void) efivar_set(LOADER_GUID, L"LoaderEntryLastBooted", entry->id, EFI_VARIABLE_NON_VOLATILE);
|
||||
} else
|
||||
/* Delete the non-volatile var if not needed. */
|
||||
(void) efivar_set(LOADER_GUID, L"LoaderEntryLastBooted", NULL, EFI_VARIABLE_NON_VOLATILE);
|
||||
}
|
||||
|
||||
static void export_variables(
|
||||
EFI_LOADED_IMAGE *loaded_image,
|
||||
const CHAR16 *loaded_image_path,
|
||||
@ -2456,7 +2434,9 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
||||
}
|
||||
|
||||
config_entry_bump_counters(entry, root_dir);
|
||||
save_selected_entry(&config, entry);
|
||||
|
||||
/* Export the selected boot entry to the system */
|
||||
(void) efivar_set(LOADER_GUID, L"LoaderEntrySelected", entry->id, 0);
|
||||
|
||||
/* Optionally, read a random seed off the ESP and pass it to the OS */
|
||||
(void) process_random_seed(root_dir, config.random_seed_mode);
|
||||
|
||||
@ -786,11 +786,6 @@ static void automount_enter_running(Automount *a) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (unit_has_failed_condition_or_assert(trigger)) {
|
||||
automount_enter_dead(a, AUTOMOUNT_FAILURE_MOUNT_CONDITION_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
r = manager_add_job(UNIT(a)->manager, JOB_START, trigger, JOB_REPLACE, NULL, &error, NULL);
|
||||
if (r < 0) {
|
||||
log_unit_warning(UNIT(a), "Failed to queue mount startup job: %s", bus_error_message(&error, r));
|
||||
@ -1079,12 +1074,11 @@ static int automount_test_start_limit(Unit *u) {
|
||||
}
|
||||
|
||||
static const char* const automount_result_table[_AUTOMOUNT_RESULT_MAX] = {
|
||||
[AUTOMOUNT_SUCCESS] = "success",
|
||||
[AUTOMOUNT_FAILURE_RESOURCES] = "resources",
|
||||
[AUTOMOUNT_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
|
||||
[AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT] = "mount-start-limit-hit",
|
||||
[AUTOMOUNT_FAILURE_UNMOUNTED] = "unmounted",
|
||||
[AUTOMOUNT_FAILURE_MOUNT_CONDITION_FAILED] = "mount-condition-failed",
|
||||
[AUTOMOUNT_SUCCESS] = "success",
|
||||
[AUTOMOUNT_FAILURE_RESOURCES] = "resources",
|
||||
[AUTOMOUNT_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
|
||||
[AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT] = "mount-start-limit-hit",
|
||||
[AUTOMOUNT_FAILURE_UNMOUNTED] = "unmounted",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(automount_result, AutomountResult);
|
||||
|
||||
@ -11,7 +11,6 @@ typedef enum AutomountResult {
|
||||
AUTOMOUNT_FAILURE_UNMOUNTED,
|
||||
AUTOMOUNT_FAILURE_START_LIMIT_HIT,
|
||||
AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT,
|
||||
AUTOMOUNT_FAILURE_MOUNT_CONDITION_FAILED,
|
||||
_AUTOMOUNT_RESULT_MAX,
|
||||
_AUTOMOUNT_RESULT_INVALID = -EINVAL,
|
||||
} AutomountResult;
|
||||
|
||||
@ -480,7 +480,7 @@ static void path_enter_dead(Path *p, PathResult f) {
|
||||
p->result = f;
|
||||
|
||||
unit_log_result(UNIT(p), p->result == PATH_SUCCESS, path_result_to_string(p->result));
|
||||
path_set_state(p, p->result == PATH_SUCCESS ? PATH_DEAD : PATH_FAILED);
|
||||
path_set_state(p, p->result != PATH_SUCCESS ? PATH_FAILED : PATH_DEAD);
|
||||
}
|
||||
|
||||
static void path_enter_running(Path *p) {
|
||||
@ -780,11 +780,6 @@ static void path_trigger_notify(Unit *u, Unit *other) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (unit_has_failed_condition_or_assert(other)) {
|
||||
path_enter_dead(p, PATH_FAILURE_UNIT_CONDITION_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Don't propagate anything if there's still a job queued */
|
||||
if (other->job)
|
||||
return;
|
||||
@ -837,11 +832,10 @@ static const char* const path_type_table[_PATH_TYPE_MAX] = {
|
||||
DEFINE_STRING_TABLE_LOOKUP(path_type, PathType);
|
||||
|
||||
static const char* const path_result_table[_PATH_RESULT_MAX] = {
|
||||
[PATH_SUCCESS] = "success",
|
||||
[PATH_FAILURE_RESOURCES] = "resources",
|
||||
[PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
|
||||
[PATH_FAILURE_UNIT_START_LIMIT_HIT] = "unit-start-limit-hit",
|
||||
[PATH_FAILURE_UNIT_CONDITION_FAILED] = "unit-condition-failed",
|
||||
[PATH_SUCCESS] = "success",
|
||||
[PATH_FAILURE_RESOURCES] = "resources",
|
||||
[PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
|
||||
[PATH_FAILURE_UNIT_START_LIMIT_HIT] = "unit-start-limit-hit",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(path_result, PathResult);
|
||||
|
||||
@ -46,7 +46,6 @@ typedef enum PathResult {
|
||||
PATH_FAILURE_RESOURCES,
|
||||
PATH_FAILURE_START_LIMIT_HIT,
|
||||
PATH_FAILURE_UNIT_START_LIMIT_HIT,
|
||||
PATH_FAILURE_UNIT_CONDITION_FAILED,
|
||||
_PATH_RESULT_MAX,
|
||||
_PATH_RESULT_INVALID = -EINVAL,
|
||||
} PathResult;
|
||||
|
||||
@ -2335,15 +2335,6 @@ static void socket_enter_running(Socket *s, int cfd_in) {
|
||||
goto refuse;
|
||||
}
|
||||
|
||||
if (UNIT_ISSET(s->service) && cfd < 0) {
|
||||
Unit *service = UNIT_DEREF(s->service);
|
||||
|
||||
if (unit_has_failed_condition_or_assert(service)) {
|
||||
socket_enter_dead(s, SOCKET_FAILURE_SERVICE_CONDITION_FAILED);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (cfd < 0) {
|
||||
bool pending = false;
|
||||
Unit *other;
|
||||
@ -3453,16 +3444,15 @@ static const char* const socket_exec_command_table[_SOCKET_EXEC_COMMAND_MAX] = {
|
||||
DEFINE_STRING_TABLE_LOOKUP(socket_exec_command, SocketExecCommand);
|
||||
|
||||
static const char* const socket_result_table[_SOCKET_RESULT_MAX] = {
|
||||
[SOCKET_SUCCESS] = "success",
|
||||
[SOCKET_FAILURE_RESOURCES] = "resources",
|
||||
[SOCKET_FAILURE_TIMEOUT] = "timeout",
|
||||
[SOCKET_FAILURE_EXIT_CODE] = "exit-code",
|
||||
[SOCKET_FAILURE_SIGNAL] = "signal",
|
||||
[SOCKET_FAILURE_CORE_DUMP] = "core-dump",
|
||||
[SOCKET_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
|
||||
[SOCKET_FAILURE_TRIGGER_LIMIT_HIT] = "trigger-limit-hit",
|
||||
[SOCKET_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit",
|
||||
[SOCKET_FAILURE_SERVICE_CONDITION_FAILED] = "service-condition-failed",
|
||||
[SOCKET_SUCCESS] = "success",
|
||||
[SOCKET_FAILURE_RESOURCES] = "resources",
|
||||
[SOCKET_FAILURE_TIMEOUT] = "timeout",
|
||||
[SOCKET_FAILURE_EXIT_CODE] = "exit-code",
|
||||
[SOCKET_FAILURE_SIGNAL] = "signal",
|
||||
[SOCKET_FAILURE_CORE_DUMP] = "core-dump",
|
||||
[SOCKET_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
|
||||
[SOCKET_FAILURE_TRIGGER_LIMIT_HIT] = "trigger-limit-hit",
|
||||
[SOCKET_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit"
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(socket_result, SocketResult);
|
||||
|
||||
@ -38,7 +38,6 @@ typedef enum SocketResult {
|
||||
SOCKET_FAILURE_START_LIMIT_HIT,
|
||||
SOCKET_FAILURE_TRIGGER_LIMIT_HIT,
|
||||
SOCKET_FAILURE_SERVICE_START_LIMIT_HIT,
|
||||
SOCKET_FAILURE_SERVICE_CONDITION_FAILED,
|
||||
_SOCKET_RESULT_MAX,
|
||||
_SOCKET_RESULT_INVALID = -EINVAL,
|
||||
} SocketResult;
|
||||
|
||||
@ -598,11 +598,6 @@ static void timer_enter_running(Timer *t) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (unit_has_failed_condition_or_assert(trigger)) {
|
||||
timer_enter_dead(t, TIMER_FAILURE_UNIT_CONDITION_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
r = manager_add_job(UNIT(t)->manager, JOB_START, trigger, JOB_REPLACE, NULL, &error, NULL);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
@ -916,10 +911,9 @@ static const char* const timer_base_table[_TIMER_BASE_MAX] = {
|
||||
DEFINE_STRING_TABLE_LOOKUP(timer_base, TimerBase);
|
||||
|
||||
static const char* const timer_result_table[_TIMER_RESULT_MAX] = {
|
||||
[TIMER_SUCCESS] = "success",
|
||||
[TIMER_FAILURE_RESOURCES] = "resources",
|
||||
[TIMER_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
|
||||
[TIMER_FAILURE_UNIT_CONDITION_FAILED] = "unit-condition-failed",
|
||||
[TIMER_SUCCESS] = "success",
|
||||
[TIMER_FAILURE_RESOURCES] = "resources",
|
||||
[TIMER_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(timer_result, TimerResult);
|
||||
|
||||
@ -32,7 +32,6 @@ typedef enum TimerResult {
|
||||
TIMER_SUCCESS,
|
||||
TIMER_FAILURE_RESOURCES,
|
||||
TIMER_FAILURE_START_LIMIT_HIT,
|
||||
TIMER_FAILURE_UNIT_CONDITION_FAILED,
|
||||
_TIMER_RESULT_MAX,
|
||||
_TIMER_RESULT_INVALID = -EINVAL,
|
||||
} TimerResult;
|
||||
|
||||
@ -1851,10 +1851,16 @@ static bool unit_verify_deps(Unit *u) {
|
||||
int unit_start(Unit *u) {
|
||||
UnitActiveState state;
|
||||
Unit *following;
|
||||
int r;
|
||||
|
||||
assert(u);
|
||||
|
||||
/* Check start rate limiting early so that failure conditions don't cause us to enter a busy loop. */
|
||||
if (UNIT_VTABLE(u)->test_start_limit) {
|
||||
int r = UNIT_VTABLE(u)->test_start_limit(u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* If this is already started, then this will succeed. Note that this will even succeed if this unit
|
||||
* is not startable by the user. This is relied on to detect when we need to wait for units and when
|
||||
* waiting is finished. */
|
||||
@ -1904,13 +1910,6 @@ int unit_start(Unit *u) {
|
||||
return unit_start(following);
|
||||
}
|
||||
|
||||
/* Check start rate limiting early so that failure conditions don't cause us to enter a busy loop. */
|
||||
if (UNIT_VTABLE(u)->test_start_limit) {
|
||||
r = UNIT_VTABLE(u)->test_start_limit(u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* If it is stopped, but we cannot start it, then fail */
|
||||
if (!UNIT_VTABLE(u)->start)
|
||||
return -EBADR;
|
||||
@ -5865,16 +5864,6 @@ Condition *unit_find_failed_condition(Unit *u) {
|
||||
return failed_trigger && !has_succeeded_trigger ? failed_trigger : NULL;
|
||||
}
|
||||
|
||||
bool unit_has_failed_condition_or_assert(Unit *u) {
|
||||
if (dual_timestamp_is_set(&u->condition_timestamp) && !u->condition_result)
|
||||
return true;
|
||||
|
||||
if (dual_timestamp_is_set(&u->assert_timestamp) && !u->assert_result)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static const char* const collect_mode_table[_COLLECT_MODE_MAX] = {
|
||||
[COLLECT_INACTIVE] = "inactive",
|
||||
[COLLECT_INACTIVE_OR_FAILED] = "inactive-or-failed",
|
||||
|
||||
@ -988,8 +988,6 @@ int unit_thaw_vtable_common(Unit *u);
|
||||
|
||||
Condition *unit_find_failed_condition(Unit *u);
|
||||
|
||||
bool unit_has_failed_condition_or_assert(Unit *u);
|
||||
|
||||
/* Macros which append UNIT= or USER_UNIT= to the message */
|
||||
|
||||
#define log_unit_full_errno_zerook(unit, level, error, ...) \
|
||||
|
||||
@ -52,10 +52,8 @@ case "$command" in
|
||||
|
||||
users=$(systemctl list-units 'user@*' --legend=no | sed -n -r 's/.*user@([0-9]+).service.*/\1/p')
|
||||
for user in $users; do
|
||||
for unit in "$@"; do
|
||||
SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT}} \
|
||||
systemctl --user -M "$user@" set-property "$unit" Markers=+needs-restart &
|
||||
done
|
||||
SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT}} \
|
||||
systemctl --user -M "$user@" set-property "$unit" Markers=+needs-restart &
|
||||
done
|
||||
wait
|
||||
;;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
[Unit]
|
||||
ConditionPathExists=/tmp/nonexistent
|
||||
ConditionPathExists=!/tmp/nonexistent
|
||||
|
||||
[Service]
|
||||
ExecStart=true
|
||||
|
||||
@ -13,5 +13,5 @@ ExecStart=-socat -T20 OPEN:test.file UNIX-CONNECT:/run/test.ctl
|
||||
# systemd enough time even on slower machines, to reach the trigger limit.
|
||||
ExecStart=sleep 10
|
||||
ExecStart=sh -x -c 'test "$(systemctl show test10.socket -P ActiveState)" = failed'
|
||||
ExecStart=sh -x -c 'test "$(systemctl show test10.socket -P Result)" = service-condition-failed'
|
||||
ExecStart=sh -x -c 'test "$(systemctl show test10.socket -P Result)" = trigger-limit-hit'
|
||||
ExecStart=sh -x -c 'echo OK >/testok'
|
||||
|
||||
@ -8,10 +8,10 @@ Type=oneshot
|
||||
ExecStart=rm -f /tmp/nonexistent
|
||||
ExecStart=systemctl start test63.path
|
||||
ExecStart=touch /tmp/test63
|
||||
# Make sure systemd has sufficient time to hit the start limit for test63.service.
|
||||
ExecStart=sleep 2
|
||||
# Ensure both the service and the corresponding path unit go inactive due to the failed condition check.
|
||||
ExecStart=sh -x -c 'test "$(systemctl show test63.service -P ActiveState)" = inactive'
|
||||
ExecStart=sh -x -c 'test "$(systemctl show test63.service -P Result)" = success'
|
||||
ExecStart=sh -x -c 'test "$(systemctl show test63.service -P ActiveState)" = failed'
|
||||
ExecStart=sh -x -c 'test "$(systemctl show test63.service -P Result)" = start-limit-hit'
|
||||
ExecStart=sh -x -c 'test "$(systemctl show test63.path -P ActiveState)" = failed'
|
||||
ExecStart=sh -x -c 'test "$(systemctl show test63.path -P Result)" = unit-condition-failed'
|
||||
ExecStart=sh -x -c 'test "$(systemctl show test63.path -P Result)" = unit-start-limit-hit'
|
||||
ExecStart=sh -x -c 'echo OK >/testok'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user