]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
efi-loader: cache LoaderConfigTimeoutOneShot too
authorLennart Poettering <lennart@poettering.net>
Thu, 25 Jun 2020 13:24:25 +0000 (15:24 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 26 Jun 2020 08:43:42 +0000 (10:43 +0200)
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.

src/login/logind-dbus.c
src/shared/efi-loader.c
src/shared/efi-loader.h

index 7fed32c3b416bf6f60ce13c12c7ab4c4378a704c..d8ae0287ec326769a67f83ac3da85f489374620b 100644 (file)
@@ -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)
index b6ad43b856ec2b1f3b61b48991728241ec922dc6..ce9e78b2749d5ecca0d018b6e73510298c31e7bd 100644 (file)
@@ -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;
+}
index 96208d25bf5ea053687d156e579063cf72164d64..98bb57ecbd5038dd174f15e5aa34a91c940eeb30 100644 (file)
@@ -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);