From: Lennart Poettering Date: Thu, 25 Jun 2020 13:24:25 +0000 (+0200) Subject: efi-loader: cache LoaderConfigTimeoutOneShot too X-Git-Tag: v246-rc1~79^2~1 X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fsystemd.git;a=commitdiff_plain;h=e8df4eee65643f9b0806763857a9f265e3d764ee efi-loader: cache LoaderConfigTimeoutOneShot too The data from this EFI variable is exposed as dbus property, and gdbus clients are happy to issue GetAllProperties() as if it was free. Hence make sure it's actually free and cache LoaderConfigTimeoutOneShot, since it's easy. --- diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 7fed32c3b41..d8ae0287ec3 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -2751,8 +2751,6 @@ static int property_get_reboot_to_boot_loader_menu( r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU"); if (r == -ENXIO) { - _cleanup_free_ char *v = NULL; - /* EFI case: returns the current value of LoaderConfigTimeoutOneShot. Three cases are distuingished: * * 1. Variable not set, boot into boot loader menu is not enabled (we return UINT64_MAX to the user) @@ -2760,20 +2758,10 @@ static int property_get_reboot_to_boot_loader_menu( * 3. Variable set to numeric value formatted in ASCII, boot into boot loader menu with the specified timeout in seconds */ - r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderConfigTimeoutOneShot", &v); + r = efi_loader_get_config_timeout_one_shot(&x); if (r < 0) { if (r != -ENOENT) - log_warning_errno(r, "Failed to read LoaderConfigTimeoutOneShot variable: %m"); - } else { - uint64_t sec; - - r = safe_atou64(v, &sec); - if (r < 0) - log_warning_errno(r, "Failed to parse LoaderConfigTimeoutOneShot value '%s': %m", v); - else if (sec > (USEC_INFINITY / USEC_PER_SEC)) - log_warning("LoaderConfigTimeoutOneShot too large, ignoring: %m"); - else - x = sec * USEC_PER_SEC; /* return in µs */ + log_warning_errno(r, "Failed to read LoaderConfigTimeoutOneShot variable, ignoring: %m"); } } else if (r < 0) diff --git a/src/shared/efi-loader.c b/src/shared/efi-loader.c index b6ad43b856e..ce9e78b2749 100644 --- a/src/shared/efi-loader.c +++ b/src/shared/efi-loader.c @@ -734,3 +734,41 @@ char *efi_tilt_backslashes(char *s) { return s; } + +int efi_loader_get_config_timeout_one_shot(usec_t *ret) { + _cleanup_free_ char *v = NULL, *fn = NULL; + static struct stat cache_stat = {}; + struct stat new_stat; + static usec_t cache; + uint64_t sec; + int r; + + assert(ret); + + fn = efi_variable_path(EFI_VENDOR_LOADER, "LoaderConfigTimeoutOneShot"); + if (!fn) + return -ENOMEM; + + /* stat() the EFI variable, to see if the mtime changed. If it did we need to cache again. */ + if (stat(fn, &new_stat) < 0) + return -errno; + + if (stat_inode_unmodified(&new_stat, &cache_stat)) { + *ret = cache; + return 0; + } + + r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderConfigTimeoutOneShot", &v); + if (r < 0) + return r; + + r = safe_atou64(v, &sec); + if (r < 0) + return r; + if (sec > USEC_INFINITY / USEC_PER_SEC) + return -ERANGE; + + cache_stat = new_stat; + *ret = cache = sec * USEC_PER_SEC; /* return in µs */ + return 0; +} diff --git a/src/shared/efi-loader.h b/src/shared/efi-loader.h index 96208d25bf5..98bb57ecbd5 100644 --- a/src/shared/efi-loader.h +++ b/src/shared/efi-loader.h @@ -23,6 +23,8 @@ int efi_loader_get_entries(char ***ret); int efi_loader_get_features(uint64_t *ret); +int efi_loader_get_config_timeout_one_shot(usec_t *ret); + #else static inline int efi_reboot_to_firmware_supported(void) { @@ -77,6 +79,10 @@ static inline int efi_loader_get_features(uint64_t *ret) { return -EOPNOTSUPP; } +static inline int efi_loader_get_config_timeout_one_shot(usec_t *ret) { + return -EOPNOTSUPP; +} + #endif bool efi_loader_entry_name_valid(const char *s);